Skip to content

feat(GAT-9016): land the server shell, landing page and API docs - #134

Merged
calmacx merged 2 commits into
feat/GAT-9592-testsfrom
feat/GAT-9016-server-shell
Sep 23, 2026
Merged

calmacx merged 2 commits into
feat/GAT-9592-testsfrom
feat/GAT-9016-server-shell

Conversation

@calmacx

@calmacx calmacx commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

What

Replaces the minimal app/root.tsx stub from #132 with the real server shell, and lands RouteError.tsx, routes/home.tsx, routes/docs.tsx and their two routes.ts entries. The shell turns on the root middleware — five security headers plus a MAX_BODY_MB request-body limit, both requiring future.v8_middleware — and a loader that starts the schema reloader as an idempotent lazy singleton. Also corrects the MAX_BODY_MB default from 512 to 10.

Why

This is the last unported piece of src/app.js: Express ran helmet() and express.json({limit:'10mb'}) on every request (src/app.js:38-41) and served Swagger UI at /docs (src/app.js:95). With those ported, WS1's three deliverables — migrate off Express, prove parity, ship the docs — are complete. The PR 2 stub existed only so react-router build could succeed while the lib and API layers stacked.

Testing

Verified against a production build (npm run build && npm start), not dev. Full suite green: 62 passed across 10 files, up from 58 — two from the restored app.test.ts, two from the new security-header cases. npm run typecheck, npm run lint and npm run build all exit 0, and build/openapi.json carries 10 paths.

All five security headers confirmed present on /list/schemas with the expected values. MAX_BODY_MB boundary confirmed: an 11 MB body returns 413, a 9 MB body does not. [schema] loadSchemas() starting appears exactly once across repeated requests, so the loader's singleton holds. No [retention] output, confirming the sweeper is genuinely absent rather than silently starting. grep -rl "jwt-decode\|@google-cloud/pubsub\|GATEWAY_API_URL" build/client/ is empty, so nothing server-only leaked into the client bundle. GET / 200, GET /docs 200 rendering Swagger UI, GET /no-such-route 404.

Notes

  • root.tsx is not a byte-identical port and should not be reviewed as one. Vite statically resolves literal-string await import(), so keeping the auth.server and retention.server imports would force this workstream to carry the whole admin lib layer just to satisfy the build. The auth decode, the retention start, the Avatar/role gating and the nav entries for /playground, /schema-graph, /schema-view, /results and /benchmark are all trimmed out and land in WS4 PR01 with the features that need them. git diff poc/GAT-XXXX -- app/root.tsx reads the delta directly: removals plus the nav-array edit, no added logic.
  • MAX_BODY_MB 512 to 10 is a deliberate behaviour change, in the safe direction. src/app.js:40 is express.json({limit:'10mb'}); the documented 512 never matched the running service and would have accepted bodies 51x larger than production has ever seen.
  • The security-headers block is appended to tests/regressions.test.ts rather than restored from the POC copy — test(GAT-9592): port Vitest suites and add the production regression replay harness #130 made four real parity fixes to that file and taking the POC version wholesale would have reverted them. It now asserts all five headers rather than the POC's two, and covers the HTML route as well as the API one.
  • docs.tsx exports no meta(), so /docs has no <title>. That is POC behaviour, left as-is rather than widened here; worth a follow-up.
  • The build emits INEFFECTIVE_DYNAMIC_IMPORT for schema.server.ts — root.tsx imports it dynamically but six API routes import it statically, so it cannot be split into its own chunk. Benign, but it means the await import() defers only the call, not the module load.
  • No auth anywhere in this PR. Express had none, and no WS1 route calls requireAuth or requireAdmin. JWT_SECRET provisioning is a WS4 PR01 precondition, not a cutover blocker.

🤖 Generated with Claude Code

@gh-actions-pipelines-app

Copy link
Copy Markdown

🎉 Great job! Your PR title follows the correct format. 🚀

@calmacx
calmacx added this pull request to stack #133 September 21, 2026 10:32
@calmacx
calmacx force-pushed the feat/GAT-9016-server-shell branch from 0e3027d to 1875f78 Compare September 21, 2026 14:12
@calmacx
calmacx removed this pull request from stack #133 September 22, 2026 08:33
@calmacx
calmacx added this pull request to stack #139 September 22, 2026 09:17
@calmacx
calmacx force-pushed the feat/GAT-9016-server-shell branch from 1875f78 to 8a1eb25 Compare September 22, 2026 09:24
Replaces the minimal root.tsx stub from GAT-9528 with the real shell and
completes the port of src/app.js: helmet()'s security headers and the
express.json body limit become the root middleware, and the Swagger UI
that Express served at /docs returns as a route.

root.tsx is deliberately NOT a byte-identical port of the POC file.
Vite statically resolves literal-string await import(), so keeping the
auth.server and retention.server imports would have forced WS1 to carry
the whole admin lib layer to satisfy the build. Dropped here and restored
in WS4 PR01 alongside the features that need them:

  - loader: getUser() and the user in the SSR payload
  - loader: ensureRetentionSweeperStarted() — nothing writes data/ in WS1,
    so the sweeper would have nothing to sweep
  - the Avatar, role gating and the local TRASERUser interface
  - nav entries for /playground, /schema-graph, /schema-view, /results
    and /benchmark

Kept: the middleware, the schema reloader, the MUI theme and its toggle,
and the inline ErrorBoundary. Run `git diff poc/GAT-XXXX -- app/root.tsx`
to read the delta directly; it is removals plus the nav-array edit.

MAX_BODY_MB now defaults to 10 rather than 512. src/app.js:40 is
express.json({limit:'10mb'}), so the documented 512 never matched the
service being replaced and would have accepted bodies 51x larger than
production has ever seen. Verified: 11mb -> 413, 9mb -> not 413.

Refs: upgrade-plans/ws1-pr06-server-shell-docs.md
app.test.ts and the security-headers block both needed a root.tsx that
exports middleware and a routes.ts with an index() entry, neither of
which existed until this PR, so GAT-9592 deferred them here.

The security block is appended rather than taken from the POC file:
GAT-9592 made four real parity fixes to regressions.test.ts, and
restoring the POC copy wholesale would have reverted them. It also now
asserts all five headers instead of the POC's two, and checks the HTML
route as well as the API one, since the middleware covers both.

Case count 58 to 62 across 10 files.

Refs: upgrade-plans/ws1-pr06-server-shell-docs.md
@calmacx
calmacx merged commit b1be4c0 into dev Sep 23, 2026
3 checks passed
@calmacx
calmacx deleted the feat/GAT-9016-server-shell branch September 23, 2026 08:55

This branch was successfully deployed

1 active deployment
dev — 06492669 Deployed Sep 22, 2026 by calmacx via testing #727
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.

2 participants