Skip to content

Drop JS obfuscation — Phase 1 (behavioral); resolves #188, #191 Phase 1#95

Merged
kennethphough merged 1 commit into
masterfrom
feature/drop-js-obfuscation
May 30, 2026
Merged

Drop JS obfuscation — Phase 1 (behavioral); resolves #188, #191 Phase 1#95
kennethphough merged 1 commit into
masterfrom
feature/drop-js-obfuscation

Conversation

@kennethphough

Copy link
Copy Markdown
Member

Drop JS obfuscation — Phase 1 (behavioral, no schema change)

Resolves #188 (version-bloat) and is Phase 1 of #191 (drop JS obfuscation). Pairs with kyte-shipyard 2.1.0.

Why

JS obfuscation has been forced on every install since v1: no real security (client JS is readable in the browser), storage bloat (the obfuscated copy duplicates the source), and operational breakage (WAFs/firewalls have blocked legitimate obfuscated JS). It also drives #188: non-deterministic re-obfuscation made detectChanges see a change on every publish → a content-identical KytePageVersion each time.

What (behavioral only — no migration)

  • Publish always serves plain source. KytePageController::buildJavaScript() (page JS, the kyte_connect block, header/footer) and KyteScriptController::handleScriptPublication() ignore the obfuscate_js / obfuscate_kyte_connect flags. Lossless — the plain source was always stored alongside the obfuscated copy.
  • #188 fix: obfuscate_js removed from the metadata-field sets and javascript_obfuscated/content_js_obfuscated from the content-field sets in detectChanges/addChangedFieldsToVersion (KytePage) and detectScriptChanges/addChangedFieldsToScriptVersion (KyteScript). (generateContentHash already excluded them.)
  • Application.obfuscate_kyte_connect now defaults to 0 for new apps.

The obfuscated columns are left in place (inert). They get dropped in a follow-up (Phase 2, expand/contract) once this is confirmed stable — so a code rollback never strands a dropped column on a live DB.

Compatibility

Forward/backward compatible during rollout: the storage hooks still accept the *_obfuscated columns, so an older Shipyard that sends an obfuscated blob keeps working (kyte-php ignores it at publish), and a newer Shipyard that sends empty *_obfuscated + obfuscate_js=0 also works.

Verification

  • PHPStan clean; php -l clean.
  • Deployed to dev (19) and exercised the real patched buildJavaScript via a reflection harness with both obfuscate flags set to 1 → output contains the plain JS + plain kyte_connect and excludes the obfuscated variants. MCP read path (list_applicationsread_page) confirmed healthy on the patched code.
  • Full phpunit runs in CI (MariaDB).

🤖 Generated with Claude Code

…e 1)

Stop producing/serving obfuscated JS without any schema change. Obfuscated
columns are left inert and dropped later (Phase 2, expand/contract).

- Publish always serves plain source: KytePageController::buildJavaScript()
  (page JS, kyte_connect block, header/footer) and
  KyteScriptController::handleScriptPublication() ignore the obfuscate_js /
  obfuscate_kyte_connect flags. Lossless — plain source was always stored.
- Fix #188 version-bloat: remove javascript_obfuscated / content_js_obfuscated
  from the content-field sets and obfuscate_js from the metadata sets in
  detectChanges/addChangedFieldsToVersion (KytePage) and
  detectScriptChanges/addChangedFieldsToScriptVersion (KyteScript). A publish
  of unchanged source no longer spawns a content-identical version.
- Application.obfuscate_kyte_connect now defaults to 0 for new apps.

No migration. Storage hooks still accept the *_obfuscated columns, so the
change is forward/backward compatible with any Shipyard version during rollout.
PHPStan clean; full phpunit runs in CI (MariaDB).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kennethphough
kennethphough merged commit 7c96eb0 into master May 30, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant