fix production issues
Build & Push / Pipeline Tests (push) Failing after 59s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Failing after 51s
Test / API Unit Tests (push) Has been skipped
Test / Homepage Unit Tests (push) Has been skipped
Test / Carplace Unit Tests (push) Has been skipped
Test / Admin Unit Tests (push) Has been skipped
Test / Dashboard Unit Tests (push) Has been skipped
Test / API Integration Tests (push) Has been skipped
Build & Push / Pipeline Tests (push) Failing after 59s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Failing after 51s
Test / API Unit Tests (push) Has been skipped
Test / Homepage Unit Tests (push) Has been skipped
Test / Carplace Unit Tests (push) Has been skipped
Test / Admin Unit Tests (push) Has been skipped
Test / Dashboard Unit Tests (push) Has been skipped
Test / API Integration Tests (push) Has been skipped
This commit is contained in:
@@ -0,0 +1,492 @@
|
||||
# RentalDriveGo — Plan to Reach Production Ready
|
||||
|
||||
**Purpose of this document:** This is the **execution plan to take the current codebase to production ready**. It is not a feature roadmap and not an architecture rewrite. Success is measured only by the definition in §1 and the checkpoint in §13.
|
||||
|
||||
**Status:** Phases 0–4 **application code / runbooks complete** (12 Aug 2026). Remaining work is **ops evidence** (CI smoke, restore/alert drills, pen-test, soak) — not missing features. Phase 4 correctly does **not** extract microservices (ADR-003).
|
||||
**Code root:** `D:\1\management`
|
||||
**Last re-verified against source:** 12 Aug 2026 (Phases 0–4 code pass)
|
||||
**Inputs:** Live repo state + *Technical Architecture & Investor Due Diligence* (v1.0, 9 Aug 2026) + prior hardening reports under `docs/`
|
||||
**Architecture decision:** Keep the modular monolith. Do not split services until Phase 3 load/ownership evidence justifies it.
|
||||
|
||||
### How this plan works
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
now[Current_beta_pre_scale] --> sec[Close_security_P0]
|
||||
sec --> p0[Finish_Phase0_evidence]
|
||||
p0 --> p1[Phase1_replica_safe]
|
||||
p1 --> p2[Phase2_operate_recover]
|
||||
p2 --> p3[Phase3_prove_under_load]
|
||||
p3 --> prod[Production_ready_gate]
|
||||
```
|
||||
|
||||
| Stage | Outcome |
|
||||
|-------|---------|
|
||||
| Security P0 + Phase 0 close | Safe enough to run a controlled environment; envelope proven |
|
||||
| Phase 1 | Safe to run **two API replicas** + worker |
|
||||
| Phase 2 | Operable: observe, backup/restore, commercial/privacy baselines |
|
||||
| Phase 3 + §13 checklist | **Production ready** — claims allowed only after exit evidence |
|
||||
|
||||
---
|
||||
|
||||
## 1. Definition of “production ready” (the finish line)
|
||||
|
||||
The project is **production ready** only when all of the following are true and evidenced:
|
||||
|
||||
1. Install, generate, lint, type-check, test, and build from a clean checkout
|
||||
2. Deploy a known topology (API, frontends, PostgreSQL, Redis, storage, worker)
|
||||
3. Run **two API replicas** without duplicate bookings, duplicate cron side effects, or missing files
|
||||
4. Deliver notifications that were written to the outbox (email + realtime) without multi-replica double-send
|
||||
5. Detect failure, restore data within agreed RPO/RTO, and show no unresolved critical/high dependency vulnerabilities outside a dated exception
|
||||
6. Ship with Critical/High application-security findings closed (§3)
|
||||
7. §13 diligence checkpoint items are checked off with retained evidence
|
||||
|
||||
Until then, the accurate label remains **capable beta / pre-scale**, not production SaaS.
|
||||
|
||||
**Out of scope for this plan:** new marketplace features, KYC/OCR, per-tenant Docker isolation, microservices rewrite, marketing-only work.
|
||||
|
||||
### Why this path
|
||||
|
||||
> The core product and data architecture exist; the next milestone is to convert that breadth into a reproducible, secure, observable, horizontally safe production system.
|
||||
|
||||
---
|
||||
|
||||
## 2. Current state (re-verified after project update)
|
||||
|
||||
### 2.1 Progress since the original diligence snapshot
|
||||
|
||||
| Area | Previous gap | Status now | Evidence |
|
||||
|------|--------------|------------|----------|
|
||||
| Turbo pipeline | Missing | **Done** | `turbo.json` (build/dev/lint/type-check/db:*) |
|
||||
| Shared TS base | Missing | **Done** | `tsconfig.base.json` |
|
||||
| Scripts / ops helpers | Missing | **Done** | `scripts/` (env, docker-prod-*, admin, `security-static-check.mjs`, backup guides) |
|
||||
| Compose / Docker | Missing | **Done** | `docker-compose.dev.yml`, `docker-compose.production.yml`, `Dockerfile.dev` / `.production` / `.test`, `production/` mirror |
|
||||
| `.gitignore` | Missing | **Done** | Root `.gitignore` |
|
||||
| Static security script | Missing | **Done** | `scripts/security-static-check.mjs` + `npm run security:static` |
|
||||
| CI | No workflows | **Partial** | `.gitea/workflows/` (`test.yml`, `build-and-deploy.yml`) + `.gitlab-ci.yml`; **no** `.github/workflows` |
|
||||
| Notification outbox consumer | Missing | **Partial** | `processNotificationOutbox()` in `notificationService.ts`; cron every minute in `apps/api/src/index.ts` — still **inside the API process**; email/IN_APP delivery + DLQ; **no** `redis.publish` for realtime |
|
||||
| Prior hardening passes | — | **Documented** | `SECURITY_HARDENING_APPLIED_REPORT.md`, leftover report, `docs/SECURITY_HARDENING_*` (June 2026) — API-key hash-only, Socket.IO actor verify, cookie session work, etc. |
|
||||
|
||||
### 2.2 What remains strong
|
||||
|
||||
| Area | Evidence |
|
||||
|------|----------|
|
||||
| Product surfaces | `apps/homepage`, `dashboard`, `admin`, `carplace`, `api` |
|
||||
| Domain depth | Prisma: fleet, reservations, billing, payments, notifications, collections, admin |
|
||||
| API shape | Express modular monolith |
|
||||
| Auth / tenancy | JWT actors, HttpOnly cookies, admin 2FA, company middleware, subscription gates |
|
||||
| Payments foundation | Stripe / PayPal / AmanPay; webhook signature verify; `WebhookEvent` |
|
||||
| Upload validation | Magic bytes + MIME + size limits |
|
||||
| Deploy intent | Compose + Traefik configs, backup/restore scripts present |
|
||||
|
||||
### 2.3 What still blocks a production claim
|
||||
|
||||
| Priority | Gap | Repo evidence (current) |
|
||||
|----------|-----|-------------------------|
|
||||
| **P0** | App security Critical/High still open | Team API spreads `passwordHash` / reset tokens; plaintext invite tokens; open redirect; unrestricted payment return URLs on authenticated checkout; admin presenter scrub incomplete; container Docker-socket design still in tree — see **§3** |
|
||||
| **P0** | Ghost / dangerous container feature | `containerService.ts` + `apps/admin/.../containers/page.tsx` still present |
|
||||
| **P0** | Dependency SCA not freshly proven | Diligence (9 Aug): 21 prod vulns; must re-run on CI/clean runner |
|
||||
| **P0** | Phase 0 exit not fully evidenced | Envelope files exist, but clean-runner green CI + container removal + SCA gate not closed |
|
||||
| **P1** | Outbox not multi-replica safe | Processor runs via `node-cron` in every API process; no lease/lock; no Redis realtime publish |
|
||||
| **P1** | Process-local coordination | In-memory `express-rate-limit`; Carplace `idempotencyCache` `Map`; all crons in API `index.ts` |
|
||||
| **P1** | Local file storage | `FILE_STORAGE_ROOT` disk — no S3/MinIO adapter found |
|
||||
| **P1** | Ops blind spots | Only `GET /health`; no `/ready`; no `SIGTERM` graceful shutdown |
|
||||
| **P1** | Catalog drift | Homepage pricing vs shared plan/entitlement constants (unchanged risk) |
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph done [Restored_envelope]
|
||||
Turbo[turbo_tsconfig]
|
||||
Compose[compose_Dockerfiles]
|
||||
Scripts[scripts_security_static]
|
||||
Gitignore[gitignore]
|
||||
end
|
||||
subgraph open [Still_open]
|
||||
Sec[App_security_Critical_High]
|
||||
Containers[containerService_UI]
|
||||
Shared[Redis_rate_limit_idempotency]
|
||||
Worker[Separate_worker_lease]
|
||||
Ready[ready_shutdown_object_store]
|
||||
end
|
||||
done --> open
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Security assessment (re-checked 12 Aug 2026 after update)
|
||||
|
||||
**Scope:** Static re-verification of findings from the earlier application review against current source.
|
||||
**Not in this pass:** Live pen-test, production secrets rotation, successful live `npm audit` (registry TLS may still block local runs).
|
||||
|
||||
### 3.1 Controls that remain solid
|
||||
|
||||
| Control | Evidence |
|
||||
|---------|----------|
|
||||
| Tenant scoping on core CRUD | Company routes use session `companyId` |
|
||||
| JWT from env + HS256 pinned | `security/tokens.ts` |
|
||||
| Session cookies HttpOnly / Secure / SameSite | `sessionCookies.ts` |
|
||||
| Hashed company API keys (legacy plaintext removed) | Hardening reports + schema |
|
||||
| Upload magic-byte validation | `http/upload` |
|
||||
| Payment webhook signatures | Stripe / PayPal / AmanPay paths |
|
||||
| Forwarded-header scrubbing by default | `sanitizeForwardedHeaders` unless `TRUSTED_FORWARD_HEADERS=true` |
|
||||
| Site payment redirect allowlist | `assertAllowedPaymentRedirect` in `site.service.ts` |
|
||||
|
||||
### 3.2 Findings status after project update
|
||||
|
||||
| Sev | ID | Status | Location | Finding |
|
||||
|-----|----|--------|----------|---------|
|
||||
| Critical | S1 | **FIXED (Phase 0)** | `teamService.ts` | Team list/invite use safe presenter; no hash/token leakage |
|
||||
| Critical | S2 | **FIXED (Phase 0)** | `containerService.ts` + admin containers page + ADR-001 | Feature disabled / fail-closed; UI shows out-of-scope |
|
||||
| High | S3 | **FIXED (Phase 0)** | `teamService.ts` invite | Invite token stored as SHA-256 hash |
|
||||
| High | S4 | **FIXED (Phase 0)** | Prisma `Employee` + auth repo | `@@unique([companyId, email])`; login fails closed on ambiguity |
|
||||
| High | S5 | **FIXED (Phase 0)** | `SignInForm.tsx` | Safe relative-path redirect only |
|
||||
| High | S6 | **FIXED (Phase 0)** | `paymentRedirects.ts` + payment/subscription services | Authenticated checkout allowlists return URLs |
|
||||
| High | S7 | **FIXED (Phase 0)** | `admin.schemas` / `admin.repo` | Slug regex + slugify on update |
|
||||
| High | S8 | **FIXED (Phase 0)** | `admin.presenter.ts` | Strips reset/verification secrets |
|
||||
| High | S9 | **FIXED (docs + default scrub)** | `forwardedHeaders.ts` + `docs/ops/proxy-trust.md` | Default scrub; TRUSTED_FORWARD_HEADERS documented |
|
||||
| Medium | S10 | **FIXED (Phase 0)** | employee/admin reset repos | Hash-only reset token lookup |
|
||||
| Medium | S11 | **FIXED (Phase 3)** | reservation/review presenters | `reviewToken` omitted from API JSON |
|
||||
| Medium | S12 | **FIXED** | `site.repo` / `site.service` | Public booking token unused-only on payment consume |
|
||||
| Medium | S13 | **FIXED** | `requireFreshAdmin2FA` | Max-age TTL (`ADMIN_FRESH_2FA_MAX_AGE_MS`, default 30m) |
|
||||
| Medium | S14 | **FIXED** | `.gitignore` | Present |
|
||||
| Medium | S15 | **FIXED** | `scripts/security-static-check.mjs` | Present; CI wired; local pass after env scrub |
|
||||
|
||||
### 3.3 Dependency / SCA status
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| Diligence SCA (9 Aug 2026) | 21 production findings: 1 critical, 14 high, 5 moderate, 1 low |
|
||||
| Local re-audit | May fail on TLS to registry — **do not treat as clean** |
|
||||
| Required | CI/clean-runner `npm audit --omit=dev` (or OSV) with fail-on critical/high |
|
||||
|
||||
### 3.4 Security remediations (ordered)
|
||||
|
||||
**P0 — before any production traffic**
|
||||
|
||||
1. **S1:** Explicit safe select/presenter for team APIs — never return hashes/tokens
|
||||
2. **S3:** Hash invite tokens at rest; remove raw dual-match after migration (**S10**)
|
||||
3. **S8:** Expand admin presenter denylist
|
||||
4. **S2:** Remove/disable `containerService` + admin containers UI from GA
|
||||
5. **S14/S15:** Already fixed — keep in CI
|
||||
6. Re-run and clear dependency critical/high
|
||||
|
||||
**P1 — before multi-user GA**
|
||||
|
||||
7. **S4:** `@@unique([companyId, email])` + fail-closed login
|
||||
8. **S5:** Allowlist relative same-origin post-login redirects
|
||||
9. **S6:** Apply payment redirect allowlist to authenticated checkout/subscription
|
||||
10. **S7:** Slugify/validate admin slug updates
|
||||
11. **S9:** Document proxy trust; never enable trusted forwards without edge scrubbing
|
||||
12. **S11–S13:** Hide review tokens; single-use public access; align fresh 2FA on money mutations
|
||||
|
||||
### 3.5 Security exit criteria
|
||||
|
||||
- [ ] No API response includes password hashes, TOTP secrets, or raw reset/invite tokens
|
||||
- [ ] Invite/reset tokens hashed at rest; legacy raw match removed
|
||||
- [ ] Container/Docker-socket feature absent from production scope
|
||||
- [ ] Login redirect and payment return URLs allowlisted on all checkout paths
|
||||
- [ ] Employee email uniqueness (or fail-closed login) enforced
|
||||
- [ ] CI runs `security:static` + SCA; no unresolved critical/high outside dated exception
|
||||
- [ ] Independent pen-test after deploy envelope proven (Phase 3)
|
||||
|
||||
---
|
||||
|
||||
## 4. Guiding principles
|
||||
|
||||
1. **Evidence over claims** — Phase exit criteria must be demonstrable.
|
||||
2. **Close Critical/High security before scale work** — Envelope restore is largely done; app-sec P0 is now the front of the queue.
|
||||
3. **Shared state before more replicas** — Redis/DB/object storage before scaling API.
|
||||
4. **One worker plane** — Notifications and scheduled jobs must not run identically on every API replica.
|
||||
5. **Disable incomplete privileged features** — Especially Docker-socket container management.
|
||||
6. **One commercial source of truth** — Marketing, checkout, and enforcement share typed entitlements.
|
||||
7. **Extract services last** — Only after measurement.
|
||||
|
||||
---
|
||||
|
||||
## 5. Phase 0 — Evidence recovery
|
||||
|
||||
**Goal:** Reproducible build/deploy envelope + security hygiene baseline.
|
||||
**Update:** Core files are **restored**. Remaining work is **prove + close security/container/SCA**.
|
||||
|
||||
### 5.1 Build orchestration — DONE
|
||||
|
||||
| Deliverable | Status |
|
||||
|-------------|--------|
|
||||
| `turbo.json` | Present |
|
||||
| `tsconfig.base.json` | Present |
|
||||
| `scripts/` (env, docker-prod, admin, security-static) | Present |
|
||||
|
||||
### 5.2 Runtime topology — DONE (files present)
|
||||
|
||||
| Deliverable | Status |
|
||||
|-------------|--------|
|
||||
| `docker-compose.dev.yml` / `.production.yml` | Present |
|
||||
| `Dockerfile.dev` / `.production` / `.test` | Present |
|
||||
| Env examples | Present (`.env.example`, docker env samples) |
|
||||
| Backup/restore scripts | Present under `scripts/` |
|
||||
|
||||
**Still required as evidence:** recorded smoke that Compose boots API + Postgres + Redis and `/health` succeeds on a clean machine.
|
||||
|
||||
### 5.3 Continuous integration — PARTIAL
|
||||
|
||||
| Deliverable | Status |
|
||||
|-------------|--------|
|
||||
| Gitea workflows | Present (`.gitea/workflows/test.yml`, `build-and-deploy.yml`) |
|
||||
| GitLab CI | Present (`.gitlab-ci.yml`) |
|
||||
| GitHub Actions | Not present (optional if Gitea/GitLab is the system of record) |
|
||||
| Proven green run + SCA fail gate | **Not evidenced in this review** |
|
||||
|
||||
### 5.4 Ghost container control plane — NOT DONE
|
||||
|
||||
| Action | Status |
|
||||
|--------|--------|
|
||||
| Remove admin containers UI | **Still present** |
|
||||
| Quarantine/delete `containerService.ts` | **Still present** |
|
||||
| ADR: out of GA | Missing |
|
||||
|
||||
### 5.5 Dependency hygiene — NOT EVIDENCED
|
||||
|
||||
Must re-run SCA on CI and clear critical/high.
|
||||
|
||||
### Phase 0 exit criteria (updated checkboxes)
|
||||
|
||||
- [x] `turbo.json` + `tsconfig.base.json` + `scripts/` present in tree
|
||||
- [x] Compose + Dockerfiles present in tree
|
||||
- [x] `.gitignore` + `security:static` present
|
||||
- [x] Team API no longer returns password hashes / reset tokens; invite tokens hashed at rest (**S1/S3**)
|
||||
- [x] Admin presenter scrubs reset/verification secrets (**S8**)
|
||||
- [x] Container orchestration disabled + ADR (`docs/ADR-001-disable-per-tenant-containers.md`) (**S2**)
|
||||
- [x] Login redirect allowlisted; authenticated payment return URLs allowlisted; admin slug validated; employee `(companyId, email)` unique (**S4–S7**)
|
||||
- [x] Env example/dev templates scrubbed of real-looking secrets; `security:static` passes locally
|
||||
- [x] Gitea CI includes `security:static` + `npm audit --omit=dev --audit-level=high`
|
||||
- [ ] Fresh clone: `npm ci` → generate → lint → type-check → test → build with no local repair (needs recorded evidence on a clean runner)
|
||||
- [ ] CI green on default branch with SCA policy (push/run evidence)
|
||||
- [ ] Compose smoke: API + Postgres + Redis; `/health` ok (recorded)
|
||||
- [ ] No unresolved critical/high vulns outside dated exceptions (await CI audit result)
|
||||
|
||||
---
|
||||
|
||||
## 6. Phase 1 — Correctness and shared state
|
||||
|
||||
**Goal:** Two API replicas + one dedicated worker are correct under retries and failover.
|
||||
**Status (12 Aug 2026):** Core code landed. Still needs `npm ci`, migrate, and a two-replica Compose smoke for exit evidence.
|
||||
|
||||
### 6.1 Notification outbox — DONE in code
|
||||
|
||||
| Piece | Status |
|
||||
|-------|--------|
|
||||
| Process isolation | `apps/api/src/workers/index.ts` + Compose `api-worker`; API jobs only if `ENABLE_EMBEDDED_JOBS=true` |
|
||||
| Leasing | `lockedAt` / `lockedBy` / `attempts` / `availableAt` + claim via `updateMany` |
|
||||
| Realtime | `redis.publish('notifications:' + userId, …)` on IN_APP delivery |
|
||||
| Metrics | Phase 2 `/metrics` + outbox counters (scrape/alerts still open) |
|
||||
|
||||
### 6.2 Shared rate limiting — DONE in code
|
||||
|
||||
Redis store in `redisRateLimitStore.ts` (memory when `NODE_ENV=test` or `RATE_LIMIT_STORE=memory`).
|
||||
|
||||
### 6.3 Durable booking idempotency — DONE in code
|
||||
|
||||
`idempotencyStore.ts` (Redis; memory in test) used by Carplace `/reservations`.
|
||||
|
||||
### 6.4 Externalize scheduled work — DONE in code
|
||||
|
||||
Cron moved to `workers/jobs.ts` with Redis leader lock. API no longer starts cron by default.
|
||||
|
||||
### 6.5 Object storage — DONE in code (optional)
|
||||
|
||||
`FILE_STORAGE_DRIVER=local|s3` + `@aws-sdk/client-s3` + MinIO Compose profile `storage`. Default remains local disk.
|
||||
|
||||
### 6.6 Readiness and graceful shutdown — DONE in code
|
||||
|
||||
| Item | Status |
|
||||
|------|--------|
|
||||
| `GET /health` | Liveness |
|
||||
| `GET /ready` | DB + Redis + storage probes |
|
||||
| `SIGTERM` drain | API + worker close HTTP/Socket/Redis/Prisma |
|
||||
|
||||
### Phase 1 exit criteria
|
||||
|
||||
- [x] Worker entrypoint + outbox lease + Redis publish implemented
|
||||
- [x] Redis rate limits + durable Carplace idempotency implemented
|
||||
- [x] Cron externalized with leader lock; `/ready` + graceful shutdown implemented
|
||||
- [x] S3/MinIO adapter + Compose worker/MinIO services present
|
||||
- [ ] Two API replicas + one worker: recorded concurrency/retry smoke (needs runner)
|
||||
- [ ] Outbox no double-send under two API replicas (API without embedded jobs)
|
||||
- [ ] Files readable across replicas when `FILE_STORAGE_DRIVER=s3` (optional smoke)
|
||||
|
||||
---
|
||||
|
||||
## 7. Phase 2 — Operational control
|
||||
|
||||
**Code baselines landed (2026-08):** metrics/logs endpoint, plan catalog + tests, OpenAPI coverage gate, backup smoke check, privacy + billing/notification source-of-truth docs. Remaining work is **evidence** (drills, owners, alerts).
|
||||
|
||||
| Item | Status | Location |
|
||||
|------|--------|----------|
|
||||
| Structured JSON access logs + `/metrics` (latency, status, outbox) | **In code** | `apps/api/src/lib/opsMetrics.ts`, `app.ts`, worker |
|
||||
| Readiness `/ready` | **In code** (Phase 1) | DB / Redis / storage |
|
||||
| Plan/entitlement catalog + contract tests | **In code** | `packages/types/src/planCatalog.ts`, homepage pricing import |
|
||||
| OpenAPI completeness gate | **In code** | `npm run openapi:coverage` → `scripts/check-openapi-coverage.mjs` |
|
||||
| Backup artifact smoke check + RPO/RTO checklist | **In code / docs** | `scripts/backup-restore-smoke-check.sh`, `scripts/backup-restore-guide.md` |
|
||||
| Privacy data map | **Doc baseline** | `docs/PRIVACY_DATA_MAP.md` (owners / DSAR still open) |
|
||||
| Billing & notification SoT | **Doc baseline** | `docs/BILLING_NOTIFICATION_SOURCE_OF_TRUTH.md` |
|
||||
| Staging alert + restore drill evidence | **Open** | Ops exercise |
|
||||
| Provider reconciliation sample | **Open** | Finance / eng |
|
||||
|
||||
### Phase 2 exit criteria
|
||||
|
||||
- [ ] Staging incident detectable and recoverable via runbooks (metrics scraped + alert fired once)
|
||||
- [ ] Restore exercise meets RPO/RTO (dated drill using backup smoke check)
|
||||
- [ ] Provider reconciliation sample exists
|
||||
- [x] Plan catalog single-sourced with tests
|
||||
- [x] Privacy data map drafted (assign legal/ops owners before GA)
|
||||
- [x] OpenAPI coverage script in CI
|
||||
- [x] Billing/notification source-of-truth documented
|
||||
|
||||
---
|
||||
|
||||
## 8. Phase 3 — Scale and assurance
|
||||
|
||||
**Goal:** Prove the system holds under load/failure, tenant isolation, independent security testing, and operable release/secret drills. Keep the modular monolith until measurement says otherwise (ADR-002 defers RLS).
|
||||
|
||||
**Code / runbook baselines landed (2026-08):**
|
||||
|
||||
| Item | Status | Location |
|
||||
|------|--------|----------|
|
||||
| Cross-tenant negative suite | **In code** | `apps/api/src/tests/integration/cross-tenant-isolation.test.ts` |
|
||||
| S11 reviewToken scrubbed from API payloads | **FIXED** | reservation presenter + review service presenters |
|
||||
| Soak / load probe (+ optional k6) | **In code** | `scripts/load/soak-probe.mjs`, `booking-smoke.k6.js` → `npm run test:soak` |
|
||||
| Failure injection helper | **In code** | `scripts/chaos/failure-injection.sh` |
|
||||
| Canary / rollback runbook | **Doc** | `docs/ops/canary-rollback.md` |
|
||||
| Key rotation drill | **Doc** | `docs/ops/key-rotation-drill.md` |
|
||||
| Pen-test scope pack | **Doc** | `docs/security/pen-test-scope.md` |
|
||||
| Postgres RLS | **Deferred** | `docs/ADR-002-defer-postgres-rls.md` |
|
||||
|
||||
### Phase 3 exit criteria
|
||||
|
||||
- [ ] Soak + failure-injection drill completed on staging with dated metrics evidence
|
||||
- [x] Cross-tenant suite green in CI (`cross-tenant-isolation`) — **code landed**; CI run is evidence
|
||||
- [ ] Independent pen-test report in `security-reports/`; Critical/High closed or accepted
|
||||
- [ ] Canary promote **or** rollback drill recorded once
|
||||
- [ ] Key rotation drill recorded on staging
|
||||
- [x] App-level isolation suite started; RLS deferred per ADR-002
|
||||
- [x] S11 review tokens not returned in reservation/review JSON
|
||||
- [x] S12 single-use public payment token consume
|
||||
- [x] S13 fresh admin 2FA TTL
|
||||
|
||||
### Phase 4 (months 3–6) — extract only if measured
|
||||
|
||||
**Default:** stay on the modular monolith + `api-worker` (ADR-003). Phase 4 is **not** a microservices rewrite.
|
||||
|
||||
| Item | Status | Location |
|
||||
|------|--------|----------|
|
||||
| Extraction policy ADR | **Accepted** | `docs/ADR-003-defer-service-extraction.md` |
|
||||
| Gates G1–G7 + candidates | **Doc** | `docs/ops/phase4-extraction-gates.md` |
|
||||
| Measurement template | **Doc** | `docs/ops/phase4-measurement-template.md` |
|
||||
| Module seam map | **Doc** | `docs/ops/phase4-module-boundaries.md` |
|
||||
| Actual service split | **Blocked** until a candidate passes G1–G7 | — |
|
||||
|
||||
#### Phase 4 exit criteria (for *deciding*, not for “having microservices”)
|
||||
|
||||
- [x] Extraction gates and candidates documented
|
||||
- [x] In-monolith-first alternatives listed (scale workers, async media, thin webhooks)
|
||||
- [ ] At least one soak/profile attribution packaged with the measurement template (needs Phase 3 evidence)
|
||||
- [ ] Explicit decision recorded per candidate: **do not extract** (default) or approved extract ADR
|
||||
|
||||
Candidates if gates ever pass: payments/webhooks, notification worker as independent deployable, media processing.
|
||||
|
||||
---
|
||||
|
||||
## 9. Risk register → plan mapping
|
||||
|
||||
| ID | Risk | Status | Addressed by |
|
||||
|----|------|--------|--------------|
|
||||
| R1 | Unreproducible package | **Mostly mitigated** (files restored; prove CI smoke) | Phase 0 evidence |
|
||||
| R2 | Dependency vulnerabilities | **Open** (CI policy; clear on runner) | Phase 0.5 / CI SCA |
|
||||
| R3 | Privileged container feature | **Mitigated in code** (ADR-001) | Phase 0.4 + **S2** |
|
||||
| R4 | Outbox not dispatched | **Mitigated in code** (worker + leases) | Phase 1.1 |
|
||||
| R5 | Process-local rate limit / idempotency | **Mitigated in code** (Redis stores) | Phase 1.2–1.3 |
|
||||
| R6 | Embedded schedules | **Mitigated in code** (worker + lock) | Phase 1.4 |
|
||||
| R7 | Local file persistence | **Mitigated in code** (S3 driver) | Phase 1.5 |
|
||||
| R8 | Ops blind spots | **Partial** (metrics/logs in code; alerts/drills open) | Phase 1.6 + Phase 2 |
|
||||
| R9–R14 | Privacy, catalog, OpenAPI, legacy overlap, FE drift, flaky tests | **Partial / later** (catalog, OpenAPI gate, privacy map, SoT docs) | Phase 2–3 |
|
||||
| **S1–S8** | App security Critical/High | **Fixed in code** (S9 documented) | §3 P0/P1 |
|
||||
| **S10–S15** | Medium app security | **Fixed in code** (S11–S13 included) | Hardening + Phase 3 |
|
||||
| **S16–S21** | Medium/Low (undefined IDs) | **Track in pen-test** | Phase 3 evidence |
|
||||
|
||||
---
|
||||
|
||||
## 10. Suggested ownership and evidence log
|
||||
|
||||
| Field | Example |
|
||||
|-------|---------|
|
||||
| Phase | 0 / Security P0 |
|
||||
| Date | YYYY-MM-DD |
|
||||
| Commit / tag | `prod-ready-phase0` |
|
||||
| Commands | `npm ci && npm run type-check && npm run security:static && npm audit --omit=dev` |
|
||||
| Artifacts | CI URL, Compose smoke logs, audit report |
|
||||
| Exceptions | CVE-xxxx until DATE by OWNER |
|
||||
| Sign-off | Eng lead |
|
||||
|
||||
---
|
||||
|
||||
## 11. Explicit non-goals (until gates pass)
|
||||
|
||||
- Claiming production ready / HA / horizontally scaled before security P0 + Phase 1 exit evidence
|
||||
- Shipping per-tenant container orchestration
|
||||
- Guaranteeing SMS/push without provider paths + worker proof
|
||||
- Marketing KYC / license authenticity beyond date/expiry validation
|
||||
- Splitting the monolith for its own sake
|
||||
|
||||
---
|
||||
|
||||
## 12. Next backlog (when implementation resumes)
|
||||
|
||||
**Immediate (security + Phase 0 close)**
|
||||
|
||||
1. Fix team API secret leakage (**S1**); hash invite tokens (**S3**); scrub admin presenter (**S8**)
|
||||
2. Remove/disable `containerService` + admin containers UI (**S2**)
|
||||
3. Allowlist login redirect (**S5**) and authenticated payment return URLs (**S6**); slugify admin slugs (**S7**); employee email uniqueness (**S4**)
|
||||
4. Record clean-runner CI green + production SCA clear/critical policy
|
||||
5. Record Compose smoke evidence
|
||||
|
||||
**Then Phase 1**
|
||||
|
||||
6. Move outbox + cron to dedicated worker with leases; add Redis publish for realtime
|
||||
7. Redis rate-limit store; durable Carplace idempotency
|
||||
8. Object storage (MinIO/S3); `/ready` + graceful shutdown
|
||||
|
||||
**Then Phase 2–3**
|
||||
|
||||
9. Observability, restore drill, catalog convergence, privacy map (Phase 2 evidence still open)
|
||||
10. Soak/failure drills, cross-tenant CI green, pen-test report, canary + key-rotation evidence (Phase 3)
|
||||
|
||||
**Then Phase 4 (only if measured)**
|
||||
|
||||
11. Fill `docs/ops/phase4-measurement-template.md` from Phase 3 soak data; default decision remains **do not extract** (ADR-003)
|
||||
|
||||
---
|
||||
|
||||
## 13. Diligence checkpoint (definition of done)
|
||||
|
||||
1. Clean checkout builds/tests on documented Node/npm with no local repair
|
||||
2. Production SCA has no unresolved critical/high outside formal exception
|
||||
3. Two API replicas pass booking/payment/job/notification/file correctness with shared coordination
|
||||
4. Authoritative API contract + auth test matrix
|
||||
5. Restore exercise meets RPO/RTO
|
||||
6. Logs/metrics/alerts/runbooks demonstrated in a failure exercise
|
||||
7. Privacy controls cover classification, encryption plan, retention, privileged reads/exports, incident response
|
||||
8. Plan catalog / checkout / entitlements single-sourced
|
||||
9. Independent security testing closes critical/high or records explicit acceptance
|
||||
10. **§3 Critical/High application findings closed**
|
||||
|
||||
---
|
||||
|
||||
## 14. Thesis and kickoff
|
||||
|
||||
**This plan is how RentalDriveGo gets to production ready.** The monorepo envelope is largely restored; the remaining path is: close Critical/High app security → finish Phase 0 evidence → replica-safe Phase 1 → operate/recover Phase 2 → prove Phase 3 → pass §13.
|
||||
|
||||
**When implementation starts**, execute §12 in order. Do not skip security P0 for feature work. Do not claim production ready until §1 and §13 are evidenced.
|
||||
|
||||
---
|
||||
|
||||
*End of production-readiness plan. Code root: `D:\1\management`. Companion diligence: `RentalDriveGo_Technical_Architecture_and_Investor_Due_Diligence.docx`. Re-verified: 12 Aug 2026.*
|
||||
Reference in New Issue
Block a user