feat(extension): app shelf + engine proxy on the amicode service (fork-cutover static and proxy slice, #822) - #824
Open
aarontrowbridge wants to merge 7 commits into
Open
Conversation
…the amicode service (#822) The #822 static slice: an AppShelf module (vscode-free, the service's founding discipline) serves the built app-bundle dist from the service origin — origin document, asset content types, SPA fallback for GETs that accept HTML (API-style GETs fall through honestly), path-traversal refusal, and the honest needs-setup placeholder when no dist is present. Precedence: exact route table → /amicode/* namespace 404 (fork parity, unmatched /amicode/* never proxies or SPA-falls) → shelf → honest 503 until the engine-proxy slice lands next.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…engine-token auth + wiring + packaging remain) The dead cast's tdd-RED state, preserved verbatim: engine_proxy.ts (transparent passthrough, late-bound upstream getter, RFC hop-by-hop handling), the proxy contract tests (3 RED: passthrough, POST body, SSE unbuffered — they 401 at authorized() because accept-engine-token is not implemented yet), and the attachEngineProxy precedence wiring in server/index. Remaining for #822: accept-both auth (service mint AND engine token, incl. /amicode/* routes), the wiring layer teaching the service the engine upstream, packaging the dist, the env-gated boot proof, honest comment updates.
…int on every route (#822) The framed app bootstraps with the ENGINE credential, so the service's auth now accepts BOTH its own per-boot mint and the engine's: on /amicode/* routes AND proxied paths. The proxy forwards Authorization unchanged (transparent by design). Also covers the precedence contract: an exact /amicode/* route never reaches the proxy; a static shelf hit never reaches the proxy.
) startAmicodeService() now takes the #822 boot options: the engine context (per-boot mint + LATE-BOUND URL getter — the engine restarts on solver-mode switches while the service deliberately does not, so the proxy resolves the current upstream per request; a restart gap answers the honest 503) and the app dist root (override setting > packaged dist/app). The superseded total-separation comment is updated honestly: the engine token is accepted ALONGSIDE the service's own mint, not shared. extension.ts passes serverManager's URL late + the amicode.appBundleDir override; the service modules stay vscode-free.
build:app runs the app-bundle README's proven recipe — materialize → bun install → vite build — and stages the dist into packages/extension/ dist/app (the fetch:opencode precedent for a build product riding the VSIX; resolveAppDistRoot's default already expects it). Verified for real end-to-end: 4,713-package bun install, 13.8s vite build, 18 top-level entries staged. The boot proof (amicode_service_boot_probe.mjs, the telaio_app_probe convention) esbuild-bundles the REAL service from source — no transcribed logic — boots it against a real spawned vendored engine + the real built dist, and asserts all four surfaces with the ENGINE credential: app document from the origin, engine API through the proxy, SSE through the proxy, one /amicode/* route. Env-gated: absent dist → honest SKIP, CI never false-greens. Ran it for real: PASS. The ci.yml lane is the honest stub: the full bun dist build is NOT wired into CI in this slice (packaging chore follow-up); the lane runs the probe, which self-skips with the reason printed.
aarontrowbridge
marked this pull request as ready for review
September 5, 2026 18:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #822 — the fork-cutover static + proxy slice: the extension-host amicode service gains an app shelf (static serving of the built app-bundle dist) and a reverse proxy to the spawned engine, with precedence exact /amicode/ routes → static hit → engine proxy*, and auth accepting both the service's per-boot mint and the engine token.
Acceptance Criteria
test/amicode_service_app_shelf.test.ts(6 tests, incl. raw-socket traversal carriers refused 403, API-style GETs never handed the SPA doc)test/amicode_service_engine_proxy.test.ts(mock engine records method/headers/body verbatim; SSE chunks arrive ≥180ms apart — progressive, not buffered) + the live probe's real-engine/session+/eventtest/amicode_service_engine_proxy.test.ts"precedence: …" (the mock engine must never see an/amicode/*or/assetshit)/amicode/*unaffected) and the live probe asserts a live dist never serves the markerscripts/amicode_service_boot_probe.mjsesbuild-bundles the REAL service source (no transcribed logic), spawns the vendored engine (password-armed), serves the REAL built dist. Ran it for real: PASS on all four (realbuild:appoutput: 4,713-pkg bun install, 13.8s vite build; vendored 1.18.10 engine). CI lane added; it self-skips with the reason printed until the dist-build chore (chore(ci): wire the app-bundle dist build into CI + the release pipeline (the #822 packaging stub's follow-up) #825) lands.Slices
app_shelf.ts— static serving: origin doc, content types, SPA fallback (GET + accepts HTML only), traversal refusal, needs-setup placeholderengine_proxy.ts— transparent reverse proxy (method/headers/body passthrough, RFC 7230 hop-by-hop strip, SSE unbuffered), honest 503 when the upstream is not bound; never-throwingserver.tsauthorized() checks both mints, constant-time per mint; Basic is the only carrier the service itself validates —?auth_token=is the ENGINE's carrier, which the proxy passes through unchanged)startAmicodeServicelearns the engine upstream (LATE-BOUND URL getter + engine password — the engine restarts on solver-mode switches while the service deliberately does not) + the app dist root; extension.ts boot call-site; the dev-override settingamicode.appBundleDirbuild:appscript (materialize → bun install → vite build → stage todist/app— verified for real end-to-end); rides the VSIX via the existing dist/ packaging (the fetch:opencode precedent). The CI-time bun build is NOT wired in this slice — the ci.yml boot-proof lane is the honest self-skipping stub, follow-up chore chore(ci): wire the app-bundle dist build into CI + the release pipeline (the #822 packaging stub's follow-up) #825scripts/amicode_service_boot_probe.mjs, the telaio_app_probe precedent) + its real-service entrysrc/amicode_service_boot_probe.tsHonest notes
/amicode/*route table (asserted).