spec(phase-8): deployment requirements + design#6
Merged
Conversation
Translates ADR 003 into 14 EARS-format requirements that Phase 8 tasks can execute against. No architecture decisions are reopened here — the spec references ADR 003, ADR 001, and ADR 002 as the decision record. Coverage - R1 split Railway services (web static + API Node 20) - R2 Neon Postgres production branch, forward-only migrations, two-phase destructive column changes, single-deploy non-breaking additions - R3 Better Auth + GitHub OAuth with SameSite=None; Secure; Domain=.stackfast.app cookies - R4 Upstash Redis rate limiter (30/min generation, 100/min reads, fail-open on any Upstash error, Retry-After only on 429) - R5 production health check - R6 post-deploy rate-limit smoke test - R7 Sentry behind SENTRY_DSN feature flag (no-op when absent, idempotent init, scrub idea/constraints, Git SHA release) - R8 admin API key enforcement on /admin/* and /internal/*, 401 immediately when no auth headers present, Authorization: Bearer fallback supported - R9 DNS + custom domains with HTTP→HTTPS redirect - R10 CORS locked to https://stackfast.app, never wildcard in prod - R11 auth fails closed in production regardless of ALLOW_AUTH_BYPASS; non-prod honors bypass only when not false - R12 Railway CLI rollback per service; block automatic rollback when schema would be incompatible; multi-generation rollbacks allowed with manual reconciliation - R13 staging environment isolation (separate Neon branch, OAuth app, secrets, ALLOW_AUTH_BYPASS=false) - R14 README deployment documentation Non-goals section explicitly rules out preview envs, blue/green, multi-region, custom CDN, APM, and status-page tooling. Correctness properties surfaced for PBT in the design phase - Fail-open rate limiter (R4.5) - Idempotent Sentry init + no-op on falsy DSN (R7.3, R7.4) - CORS never wildcard in prod (R10.3, R10.4) - Admin paths 401 without valid key (R8.1, R8.3, R8.5) - Fail-closed auth in prod (R11.2, R11.3, R11.4) Ran analyze_requirements and folded in 13 clarifications across requirements 2, 4, 8, 11, and 12. Design and tasks phases follow as separate PRs.
Maps the 14 approved Phase 8 requirements onto concrete implementation modules, file edits, Railway manifests, and a testing strategy spanning unit, contract, property-based, and post-deploy smoke layers. Shape - Additive and reversible: new rate-limit module, new Sentry modules, new Railway manifests, two small auth/app.ts edits. - RATE_LIMIT_BACKEND=memory|upstash feature flag lets the rate-limiter migration ship, flip, and roll back independently of Upstash provisioning. - Sentry is idempotent and a no-op when SENTRY_DSN is falsy; the same DSN-gated branch is used on both API and web. - Auth fails closed in production regardless of ALLOW_AUTH_BYPASS, implemented as a two-line guard in apps/api/src/middleware/auth.ts. - No shared package (registry, rules-engine, exporter, ai, schemas, shared) is modified. PBT properties - Upstash failures never produce a 429 (fail-open invariant). - Sentry init is idempotent and a no-op without a DSN. - CORS never echoes Access-Control-Allow-Origin: * with credentials in production. - Admin key gating precedes every other middleware and returns 401 on any missing/mismatched key variant. - Production auth fails closed whenever the auth subsystem is not ready, regardless of ALLOW_AUTH_BYPASS. Open questions resolved before committing - Staging DNS: staging.stackfast.app + api.staging.stackfast.app (shared cookie domain, no second branch in Better Auth config). - Migration command: drizzle-kit push for MVP; promote to migrate once a real migrations folder appears. - Retry-After on exempt routes: /health and /openapi.json never reach the rate-limit middleware, so the constraint is trivially satisfied. Tasks phase follows in a separate PR.
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
Phase 8 deployment spec: the requirements and design phases of a requirements-first Kiro spec, grounded in ADR 003. No code changes — this PR is spec + design only. Tasks phase follows in a separate PR.
Spec files:
.kiro/specs/phase-8-deployment/requirements.md.kiro/specs/phase-8-deployment/design.md.kiro/specs/phase-8-deployment/.config.kiroRequirements (14 total)
Each requirement is EARS-formatted with numbered acceptance criteria. Highlights:
SameSite=None; Secure; Domain=.stackfast.appcookies, production OAuth app, GitHub callbackRetry-Afteronly on 429SENTRY_DSNis falsy, idempotent, scrubidea/constraints, Git SHA releaseAuthorization: Bearerfallback, 401 ifADMIN_API_KEYunsethttps://stackfast.app, never wildcard in prodALLOW_AUTH_BYPASSALLOW_AUTH_BYPASS=falseNon-goals are explicit: preview envs, blue/green, multi-region, custom CDN, APM, status-page tooling.
Design highlights
apps/api/src/rate-limit/module, new Sentry modules, new Railway manifests. Only two surgical edits to existing code (app.ts rate-limit swap + auth.ts two-line guard for R11).RATE_LIMIT_BACKEND=memory|upstashfeature flag so the migration ships, flips, and rolls back independently of Upstash provisioning.scripts/deploy/migrate.ts,scripts/deploy/smoke.ts,scripts/deploy/rollback.mdcodify the operator steps.Open questions
All resolved before merge (see Design § 11):
staging.stackfast.app+api.staging.stackfast.app(shared cookie domain)drizzle-kit pushfor MVP; promote tomigratewhen the first real migrations folder appearsRetry-Afteron exempt routes:/healthand/openapi.jsonnever reach the rate-limit middleware, so R4.8 is trivially satisfiedReview focus
The design doc is 263 lines; worth reviewing are:
rate-limitmodule's public API. Any concerns with the drop-in signature?Next
If this lands, the Tasks phase will translate Design § 2's file layout and § 9's migration plan into a numbered checklist for implementation.
Summary by cubic
Adds Phase 8 deployment requirements and design, translating ADR 003 into a Kiro spec for production rollout of
stackfast.appandapi.stackfast.app.No code changes; defines R1–R14 covering split Railway services, Neon migrations, Upstash-backed rate limiting (fail-open), cross-origin Better Auth cookies, CORS lock-down, Sentry behind
SENTRY_DSN, health/smoke checks, admin key enforcement, rollback, and staging isolation.Written for commit 88fce53. Summary will update on new commits.