Milestone 8: polish — client-smoke, Dockerfile, compose, architecture doc#13
Merged
Conversation
… doc Brief §12 milestone 8: shipping artifacts that turn the working app into something a team could actually adopt. client-smoke/ is a typed tRPC client workspace (own tsconfig, no workspaces). It imports the generated AppRouter, boots the app in-process, and exercises one query (ping), one mutation (auth.login), and one auth-protected query (users.me) against a live local server. npm run client-smoke:typecheck is now part of npm run ci so a router change that breaks the AppRouter contract fails CI. Dockerfile is a multi-stage production build. Stage 1 installs full deps (including a C++ toolchain so better-sqlite3's prebuild fallback succeeds on slim images), generates the tRPC schema, runs tsc. Stage 2 ships dist/ + production deps + migrations + scripts on a slim Node base with a /data volume for SQLite persistence. The same image runs either the API (default) or the worker (override the CMD). docker-compose.yml stands up the two-process stack (api + worker) on a shared SQLite volume with an HTTP healthcheck and a 15s stop_grace_period on the worker. A Postgres service section is committed as a commented recipe for the production swap path documented in docs/architecture.md. docs/architecture.md is a one-sitting tour: module graph, request lifecycle (auth middleware + tRPC + request-scoped DI), the central @transactional workflow, why the custom SyncDrizzleTransactionalAdapter exists, outbox flow, worker process, layout map, test map, production deployment recipe. README finalized to reflect the v0.1 state across all eight milestones. Local npm run ci passes: 45/45 tests, 91.43% statements, 95.55% functions, client-smoke:typecheck included.
rodrigobnogueira
added a commit
that referenced
this pull request
May 25, 2026
Milestone 8: polish — client-smoke, Dockerfile, compose, architecture doc
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.
Summary
npm run ciexits 0 locally (and now includesclient-smoke:typecheck).Changes
client-smoke/— typed tRPC client workspace per brief §5. Owntsconfig.json(no npm workspaces).client-smoke/client.tsimportsAppRouterfromsrc/@generated/server.ts, boots the app in-process, seeds the DB, and runs three procedures against127.0.0.1via@trpc/client'screateTRPCClient+httpBatchLink:ping(unauth query)auth.login(mutation)users.mewithAuthorization: Bearer <token>(auth-protected query)Output:
npm run client-smokeruns it.npm run client-smoke:typecheckis added tonpm run ci.Dockerfile— multi-stage production build. Stage 1 installs full deps (with python + g++ sobetter-sqlite3's prebuild fallback succeeds on slim images), generates the tRPC schema, runstsc. Stage 2 shipsdist/+ production deps + migrations + scripts on a slim Node base, with a/datavolume for SQLite persistence. The same image runs either the API (defaultCMD) or the worker (node dist/scripts/start-worker.jsoverride).docker-compose.yml— two-process stack (api + worker) on a shared SQLite volume, with an HTTP healthcheck on api and a 15sstop_grace_periodon the worker. A Postgres service section is committed commented as the production swap recipe; uncomment + flipDATABASE_URLto switch.docs/architecture.md— one-sitting tour: module graph, request lifecycle (Express auth middleware + tRPC + request-scoped DI), authentication (scrypt + JWT), the central@Transactionalworkflow, why the customSyncDrizzleTransactionalAdapterexists (better-sqlite3's sync tx model), outbox flow, worker process, layout map, test map, production deployment recipe.bootstraptov0.1.Modules Touched
organizations/users/membershipsprojectsaudit-logoutboxauth/contexttrpcdatabasePublic Surface (libraries)
client-smoke/consumes only the generatedAppRoutertype — the supported public surface ofnest-trpc-native. NoTrpcRouterreach-through, no Nest internals.Security Review
client-smoke/client.tsuses literal inputs against the seeded admin; no untrusted data path.${AUTH_SECRET:?…}to refuse to start ifAUTH_SECRETis unset; theclient-smokescript uses a clearly-marked test secret only.apihealthcheck uses127.0.0.1from inside the container, not the published port; no extra surface exposed.@trpc/clientis a devDep on the same line of the tRPC ecosystem as@trpc/server(already in dependencies); same release cadence.Dependency Review
@trpc/client@11.17.0— devDep, consumed only byclient-smoke/. Not pulled into the app's runtime bundle. Required to demonstrate that the generatedAppRouteris consumable by a typed client. Justification documented inCHANGELOG.md. Nopreinstall/install/postinstall/preparescripts.@trpc/clientaddition and its transitive package-lock entries).Migrations
Validation
npm run typechecknpm run client-smoke:typecheck(new in CI)npm run lintnpm run complexity:checknpm run test:cov— 45/45 tests; 91.43% statements / 95.55% functionsnpm run security:audit— exits 0 (4 moderate dev-only findings unchanged)npm run buildnpm run smokenpm run client-smoke— printed expected output end-to-endValidation Notes
Release Notes
CHANGELOG.mdupdated under[Unreleased]with milestone-8 entry + the@trpc/clientjustification.This is the last brief-defined milestone. After merge, suggest tagging
v0.1.0per brief §14's "definition of done."