Application Zero
Purpose and execution contract
Application Zero is Foodtruck Order's second epic: an extended vertical slice establishing the application capabilities needed before meaningful ordering-domain work. The first vertical slice proves PostgreSQL → repository → application → Fastify → browser. Preserve that working path. A repository that can later be copied for another conventional application is a consequence of development order, not a framework goal.
These files are executable implementation prompts, not claims that features already exist. Read this
README, the selected task, AGENTS.md, and the linked source-of-truth guides; inspect actual code
and completed prerequisites before editing. Implement only the selected increment. Update normal
guides and state/handover records during implementation; specs must not become the only
documentation of the finished system. Apply the Definition of Done.
Statuses are Idea, Draft, Ready, In progress, and Done. Ready means the prompt is implementable once its listed dependencies have landed. Done additionally requires acceptance, local validation, required hosted CI, and artifact evidence for the delivered revision. Change task and table status together; do not mark future work Done because these specifications were written.
Inspected baseline (2026-09-14)
The inspected working tree was clean. Sources include all of the original vertical-slice spec, architecture, stack, development, testing, CI, Docker, documentation, current state, and handover, checked against code. Reinspect these sources when implementing; package manifests/lockfile remain version authorities.
- Root tooling is Node 24.x/pnpm 10.34.5. Workspaces are
frontend/(@foodtruck-order/frontend),backend/(@foodtruck-order/backend),packages/db/(@foodtruck-order/db), andtests/e2e/(@foodtruck-order/e2e). Noapps/, Nx, Turborepo, shared DTO package, or generic service layer exists. - Frontend is React 19/Vite 8/React Router 7.
frontend/src/app/router.tsxexports reusableappRouteswith/and*;app/layout/AppLayout.tsxrenders header/main/footer. Styling uses Tailwind 4. Zustand 5 is installed but unused; MUI, Redux, and i18n are absent. app/providers.tsxsupplies TanStack Query 5.app/query-client.tscreates clients with one query retry.app/api/api-client.tsowns fetch, URL resolution, JSON parsing,ApiError, andApiNetworkError;message-api.tssuppliesgetMessage(). Pages must use this boundary.src/test/test-utils.tsxcurrently reproduces only the query provider instead of invokingAppProviders; AZ-001 consolidates that discrepancy while maintaining isolated clients.- Backend uses Fastify 5, optional
@fastify/cors, Zod 4 environment validation, and dotenv.server.tsis the composition root;app.tsreceives aMessageService; application/domain do not import HTTP or database clients. Repository implementations use Drizzle/postgres.js. - The only domain data is
messageswith seeded id 1, not orders/products/restaurants/users.GET /api/messagereturns{ "message": "..." }, with documented 400/404/500 errors; anonymousGET /healthreturns liveness independently of PostgreSQL. API errors currently use{ "error": "<safe description>" }. Unknown-route 404s use Fastify's different default shape.request.log.erroris present butFastify()has logging disabled. Do not claim observability is already implemented. packages/db/src/schema/,drizzle/,drizzle.config.ts, client, seed, and readiness tooling own persistence.pnpm db:generategenerates committed SQL/journal;pnpm db:migrateapplies journaled migrations;pnpm db:seedupserts the message. The backend integration helper currently splits sorted SQL on semicolons and bypasses migration journaling; AZ-005 must fix that before extending authentication migrations.- Frontend/backend use Vitest 3; frontend uses RTL/jest-dom/jsdom. Backend has fast injection tests
and real HTTP/PostgreSQL integration profiles with dedicated databases. Chromium Playwright
currently has one desktop project, dev and Docker configurations, and a real database-backed
message journey.
tests/ci/artifacts.test.mjsuses Node's test runner. Existing v8 coverage requires 100% statements/branches/functions/lines globally and per-file for configured frontend/backend sources. Preserve this policy and its narrow exclusions. pnpm qualitybuilds db then checks Prettier, strict type-aware ESLint (hooks/a11y/import hygiene), workspace types, OpenAPI, and TypeDoc. It does not enforce layer boundaries, scan secrets, validate translation parity, spellcheck, or comprehensively crawl Markdown links.- CI has
quality,test,build,docs,coverage, andvalidate-docker. Every job uses a frozen install; the latter two wait for all four initial jobs. Six successful artifacts aredb-dist,frontend-dist,backend-dist,docs-site,frontend-coverage, andbackend-coverage; Playwright diagnostics are failure-only. Preserve identifiers, upload semantics, thresholds, and operational merge requirements when adding gates. - Trusted main additionally runs
staging-migratewith secretSTAGING_DATABASE_URL, after all validation. Render/Neon staging settings are external and not proven by local checks. Separatecloudflare-pages.ymlrebuilds/publishes docs through Direct Upload; no application image registry or production deployment is implemented. Added blocking jobs must join the staging dependency gate. Do not supply hosted secrets to PR tests. - Six-service Compose is canonical: PostgreSQL → migrate → seed → backend, static frontend, nginx
gateway. Only gateway 8080 and PostgreSQL 5432 publish host ports.
/api/*shares the browser origin; gateway/healthis SPA HTML, not backend health. Vite proxies/apito host backend. RuntimeAPI_BASE_URL→ build-timeVITE_API_BASE_URL→ same-origin precedence must survive. All browser configuration is public;.envand server credentials stay out of images. - OpenAPI 3.1 in
docs/api/openapi.yamlis authoritative. Backend tests compare route surfaces, not every response schema. Redocly/Swagger UI/TypeDoc/marked build ignoreddocs-site/; configured Markdown pages are rendered, other specs are copied as raw Markdown.
Scope
Establish mobile-first UI, MUI/theming and centralized branding, conventional shell and icon side menu, declarative page registration, version/build information, localized shared preferences, session authentication/users, account settings, consistent errors/feedback, baseline observability, one outbound email integration, incremental Mocking Bird, password recovery, and substantial responsive/accessibility/security/documentation CI improvements. Feature tasks add their own tests immediately; final quality tasks consolidate checks rather than defer testing until epic end.
Non-goals
Do not turn Foodtruck Order into a starter-kit product, generic SaaS framework, white-label platform, plugin system, or generic page/integration/repository/service/controller architecture. Do not refactor the message to make it reusable. No orders/payments/POS/QR/kitchen functionality, multi-device synchronization, production infrastructure, microservices, event bus, Kubernetes, Redis, speculative caching, coverage-policy replacement, elaborate feature flags, or tracing vendor.
No tenancy IDs, organization hierarchy, invitations, self-registration, RBAC engine, or runtime business branding. User administration remains a deliberate provisioning CLI; no admin screen is needed without an authorization model. No external identity provider, social login, MFA, or email change/verification workflow in this epic. An eventual internet production launch may require separately scoped additional authentication controls; this epic delivers a production-shaped foundation, not a deployment claim.
Cross-task architectural decisions
- Mobile first: design and verify 360×800 first; include 320px reflow, 768×1024 tablet, and
1280×800 desktop. MUI default styles represent small screens;
md(900px default) enhances navigation to a permanent drawer. Narrow devices reserve no sidebar width. Prefer vertical forms/cards over desktop tables; touch controls target at least 44×44 CSS pixels, with visible focus, semantic labels, logical reading order, sensible document scrolling, and reduced-motion respect. At 200% zoom content/actions remain accessible. Verify virtual-keyboard usability manually on a phone; jsdom does not prove layout, touch, focus trapping, or contrast. - MUI and brand: use Material UI with Emotion and
@mui/icons-material, one theme factory and one static Foodtruck Order identity configuration. Include light/dark/system as a small preference, not runtime white labeling. Migrate existing affected surfaces; remove Tailwind only once no usages remain in AZ-002. Avoid parallel styling constants and global reset clashes. MUI installation documents the default Emotion engine and React compatibility. Select compatible versions at implementation, record them in the lockfile, and update techstack instead of assuming latest versions work. - Registration: one typed declaration drives route creation and menu rendering, with path,
localized label key, MUI icon, element, optional navigation visibility, access (
publicorauthenticated), and optional developer-only visibility. Public auth/detail/fallback routes need no menu entry. Create page + declaration + locale keys + tests; do not maintain a second menu list or implement a plugin registry. React Router remains the router. - State/i18n: keep TanStack Query as the sole server-data/current-user cache. Adopt Redux
Toolkit/react-redux for shared language and appearance preferences, remove unused Zustand, and
keep drawer/form/snackbar state local or in narrow React context. No RTK Query, Redux tokens,
mirrored query data, cart, or generalized persistence middleware. Use
i18next/react-i18next with bundled
en,sv, andhuresources; default/fallback English preserves the existing English UI. Device preferences persist locally; AZ-007 adds account synchronization with explicit precedence. Database message text is domain data and is not translated. - Authentication: internal email/password authentication using maintained Fastify cookie, session, CSRF, and rate-limit plugins; PostgreSQL session store behind a concrete contract; Argon2id through a maintained library. No custom crypto/JWT refresh-token scheme. This fits the existing backend and learning objective while allowing revocation without a new provider. External OIDC is an alternative for future MFA/SSO needs, not today's dependency. Follow OWASP password storage, sessions, and password recovery. Public Home/message and health stay public; Settings/account are protected. Future ordering channels require explicit authorization decisions; never infer access from menu visibility.
- Deployment boundary: introduce validated
DEPLOYMENT_ENV=local|test|staging|productionseparately fromNODE_ENV. Compose runs production builds with local deployment classification; staging/production forbid insecure session cookies, developer endpoints, mock outbound behavior, and example credentials. An explicit local classification on a production build is necessary for local HTTP Compose; it is not a safe hosted configuration. Test this combination. No permissive hosted defaults; unknown/missing hosted configuration must fail clearly. Same-origin is the supported authenticated deployment baseline. Exact-origin credentialed CORS may support separately hosted same-site frontend/API; unrelated cross-site cookie deployment is not supported here. Document required custom-domain/same-origin hosting assumptions before claiming staging auth works; no new gateway deployment is included. - Integrations: email for recovery is the concrete proof. Application code depends on a narrow
email capability; provider JSON/auth/timeouts live in backend-specific adapter code, wired by
server.ts. Select Resend's HTTPS REST endpoint for this epic, without an SDK, subscription, provider signup, or live send in CI. Native Node fetch is sufficient. This is a small replaceable adapter, not a vendor-neutral framework. See Resend API. SMTP/Nodemailer is a realistic alternative, but Render free services block common SMTP ports; current hosting plan is not established, so HTTPS avoids that known restriction. Provider credentials, sender domain verification, and operational account selection are deployment prerequisites, not blockers for implementing deterministic local behavior. A future owner choice to use another vendor changes only the adapter spec, not the application capability. - Mocking Bird: intercept only this explicitly injected outbound HTTP transport, never global fetch or arbitrary URLs. Start with capture + success/failure/timeout/latency fixtures; add a guarded developer UI next. No response scripting, proxy server, arbitrary header/body editor, live runtime toggle, persisted history, or production backdoor. In mocked mode, unmatched requests fail closed rather than falling through to a real provider. Dedicated local email previews may expose synthetic reset links for tests; logs/history must redact tokens.
- Errors/logging: retain the mandatory safe
errordescription, add optional stable code, field validation issues, and correlation ID without changing existing message descriptions. UI translates known codes and never displays arbitrary backend internals. Fastify's built-in Pino supplies structured logging; no new log platform. Log allowlisted event metadata, not passwords/cookies/session IDs/reset URLs/mail bodies/provider auth headers.
Task sequence
| ID | Task | Depends on | Status |
|---|---|---|---|
| AZ-001 | Localized shared preferences | Vertical slice | Done |
| AZ-002 | Mobile application shell and navigation | AZ-001 | Done |
| AZ-003 | API errors and mobile feedback | AZ-002 | Done |
| AZ-004 | Structured diagnostics | AZ-003 | Done |
| AZ-005 | Users and session authentication API | AZ-004 | Done |
| AZ-006 | Login and protected navigation | AZ-005 | Done |
| AZ-007 | Account settings and password change | AZ-006 | Done |
| AZ-008 | Email integration and Mocking Bird capture | AZ-005 | Ready |
| AZ-009 | Mocking Bird developer console | AZ-006, AZ-008 | Done |
| AZ-010 | Password recovery | AZ-007, AZ-009 | In progress |
| AZ-011 | Responsive accessibility gate | AZ-010 | In progress |
| AZ-012 | Supply-chain and container quality | AZ-005 | Ready |
| AZ-013 | Documentation, translations and boundary gates | AZ-011, AZ-012 | Ready |
Execute in numeric order for a straightforward progression. After AZ-005, AZ-008 and AZ-012 can proceed independently alongside AZ-006/AZ-007; coordinate lockfile, config, CI, and docs edits. AZ-009 joins authentication/navigation and outbound capture. AZ-010 joins account and recovery delivery; AZ-011 then checks the complete UI. AZ-013 consolidates quality after both branches. These are dependency opportunities, not an instruction to run multiple agents. Do not run database/Compose jobs concurrently against shared ports/databases.
No task is Draft: required architectural choices above are made, while ordinary implementation choices remain with the agent. No owner answer is required before AZ-001. Hosted authentication origin/TLS settings and email credentials/sender identity must be configured and verified when an actual staging/production release is authorized; local tests do not establish those facts.
Verification and quality responsibilities
Each task lists existing commands or explicitly names introduced commands. All run pnpm quality
and appropriate tests/builds; affected production code retains strict coverage. Feature work must
extend normal test, coverage, and validate-docker execution immediately, not wait for a final
CI task. pnpm validate:docker already contains integration and Docker E2E. It deletes only its own
isolated Compose volume: the development database is preserved automatically, as described in Docker
§6.8. Never run reset, seed, test provisioning, or Mocking Bird against hosted business data.
- Unit: isolated preference precedence, application policies, safe error mapping.
- RTL/component: navigation semantics, localized controls, form/loading/error interactions.
- Frontend integration: real providers/router/query/API boundary with external HTTP controlled.
- API: Fastify injection contracts plus real HTTP where cookies/session/database collaborate.
- PostgreSQL: uniqueness, expiry, migration upgrade/rerun, atomic reset consumption/revocation.
- Integration client: real adapter serialization through a controlled HTTP server/transport; no real provider credentials or recipients in automated tests.
- Mocking Bird: development scenarios at the outbound boundary; not a substitute for provider adapter tests or real authentication/database tests.
- E2E: browser → gateway → real backend → real PostgreSQL; only external email is mocked. Use per-test users and isolation across mobile/desktop projects. Feature tasks test mobile journeys before AZ-011 consolidates reusable axe coverage.
Blocking PR additions: responsive/axe checks in existing Docker validation, translation parity,
source/generated-site links, scoped spelling, architecture imports/generated-output enforcement,
high/critical dependency scanning, secret scanning, Dockerfile and migration validation. Scheduled
informational additions: all-severity dependency inventory and built-container vulnerabilities,
external URL checks, dependency license inventory. Do not expand pnpm quality to require network,
Docker, or hosted secrets. No standalone JSX-as-HTML validation: it is not rendered HTML. JSX a11y,
browser DOM assertions, and axe cover useful defects; broader HTML conformance remains targeted
manual review. Automated accessibility results do not establish full WCAG compliance.
Future business considerations
Another foodtruck owner may eventually need separately owned business data, users, authorization, and branding. Keep user identity independent from the message, business singleton, and static brand configuration. Do not attach every user/data record to an implicit global business in service APIs. Do not claim Application Zero's global identity table enforces future business isolation. That future epic must design memberships, scoped uniqueness where needed, ownership/migration rules, and backend authorization before exposing data to a second business. No tenant fields now.
Static identity/theming and narrow auth/integration boundaries make evolution easier without runtime branding, a permission engine, or reusable platform abstractions today. Future payments will need their own idempotency and authorization rules; do not derive them from email fixtures.
Planning delivery and continuation notes
This planning change only relocates the original spec, repairs affected references, and adds specs.
Application functionality, dependencies, migrations, Docker, and CI remain unchanged. The original
vertical-slice bytes are preserved. Its relative DoD link now needs an extra directory traversal;
docs/specs/definition-of-done.md is a forwarding pointer to the single authoritative DoD, keeping
the unchanged historical specification readable without duplicating the completion contract.
The task's explicit scope restriction takes precedence over the usual handover-update convention:
state/handover content outside docs/specs is only touched to repair moved paths. This section is
the planning continuation record. Reference repairs affect root README.md,
docs/current-state.md, docs/ai-handover.md, and scripts/build-docs-site.mjs; no other existing
source files change.
Planning validation: pnpm quality, pnpm docs:build, and git diff --check passed. A one-off
review checked all 13 prompts' required sections/statuses, table/dependencies (no cycles or missing
prerequisites), authored Markdown link targets, and original-spec byte identity. Generated-site
review checked 467 local HTML links/anchors across 29 pages with no failures, and confirmed rendered
vertical-slice and raw Application Zero sources. No application tests/builds, Docker reset/E2E, live
email, hosted CI or artifact uploads were executed for this prose/reference-only change;
documentation generation and the db prerequisite build are the applicable local builds. Redocly's
existing /health 4xx advisory remains non-blocking.
Next action: review this epic, obtain normal CI for the planning revision, then implement AZ-001. Hosted CI and artifact evidence remain required for that revision; local validation does not mark the epic's future feature tasks Done or establish the final project DoD.