Skip to content

Commit f254b85

Browse files
committed
docs(masterplan): add entry 135 for PROD-00 round-2 hardening wave
Adds a delivery entry for the 8 PROD-00 PRs merged on 2026-04-16 (#884 SEC-28, #885 DOC-06, #887 DOC-07, #886 PERF-09, #888 PERF-10, #889 OPS-29, #890 FE-15, #891 FE-14) with round-2 adversarial review findings: BREACH JWT-in-body correction (compression level Optimal -> Fastest), IPv6/IPv4 healthcheck fix, null-throw sentinel fix, skipRetry opt-out for baseline tests, setpriv entrypoint for upgrade-safe volume ownership. Also bumps the Last Updated date.
1 parent 19a51eb commit f254b85

1 file changed

Lines changed: 13 additions & 1 deletion

File tree

docs/IMPLEMENTATION_MASTERPLAN.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Taskdeck Implementation Masterplan
22

3-
Last Updated: 2026-04-15
3+
Last Updated: 2026-04-16
44
<br>
55
Planning Horizon: Next 8 to 12 weeks
66
Companion Active Docs:
@@ -666,6 +666,18 @@ Delivered in the latest cycle:
666666
- resilience/degraded-mode tests (`#720`/`#823`): 30 tests across 3 files — LLM provider resilience, queue accumulation, frontend slow-API/storage
667667
- estimated combined total after merge: backend ~4,479+, frontend ~2,454+, combined ~6,950+
668668

669+
135. PROD-00 production-readiness round-2 hardening wave (2026-04-16, PRs `#884``#891`, 8 PROD-00 tracker `#881` items):
670+
- 8 focused PRs covering disclosure policy, contributor onramp, config reference, response compression, DB indexes, container hardening, frontend crash prevention, and HTTP retry; each PR received two rounds of adversarial review (self-review + independent cold review with bot-findings triage)
671+
- **SEC-28** SECURITY.md vulnerability disclosure policy (`#853`/`#884`): repo-root `SECURITY.md` with GitHub private advisory + fallback email, 48h acknowledgement target, supported-versions scope (`main` guaranteed; latest pre-1.0 tag best-effort), safe-harbor language; README cross-link; round-2 enabled the private vulnerability reporting feature (was disabled, would have 404'd) and reconciled prose with the supported-versions table
672+
- **DOC-06** CONTRIBUTING.md onramp (`#873`/`#885`): repo-root `CONTRIBUTING.md` covering prerequisites (.NET 8 SDK, Node.js 24.x, Git), cross-platform local setup, Windows-specific notes (`check-git-env.sh`, Cygwin-git pitfall, PowerShell chaining), default URLs, test commands, commit conventions, PR process; README cross-link; AGENTS.md remains authoritative
673+
- **DOC-07** CONFIGURATION_REFERENCE.md appsettings schema (`#874`/`#887`): `docs/platform/CONFIGURATION_REFERENCE.md` documents every `appsettings.json` section and every typed `*Settings.cs` binding with key/type/default/description/required flags and env-var override conventions; cross-linked from `CLAUDE.md` and `docs/platform/README.md`; `deploy/.env.example` aligned
674+
- **PERF-09** response compression (`#845`/`#886`): `AddTaskdeckResponseCompression()` registers Brotli + Gzip, `UseResponseCompression()` wired in `PipelineConfiguration` after forwarded headers and before CORS/static/routing; includes `application/problem+json` in compressible MIME set; 3 integration tests (`ResponseCompressionApiTests`); **round-2 BREACH correction**: threat-model analysis caught that JWTs ARE returned in `/api/auth/login` and `/api/auth/register` response bodies (contradicting inline comment assuming they only live in `Authorization` headers) — compression level downgraded from `CompressionLevel.Optimal` to `CompressionLevel.Fastest` to reduce BREACH/CRIME oracle surface while preserving bandwidth wins
675+
- **PERF-10** composite DB indexes for AuditLog and Card (`#846`/`#888`): EF Core migration `20260416161303_AddPerfIndexes` adds `IX_Cards_BoardId_ColumnId` (replaces single-column `IX_Cards_BoardId`; SQLite satisfies leftmost-prefix; FK constraint preserved by schema), `IX_AuditLogs_UserId_Timestamp`, and `IX_AuditLogs_EntityId_Timestamp`; **explicit issue-AC deviations documented**: uses `AuditLog.EntityId` instead of the aspirational `BoardId` (AuditLog uses polymorphic `EntityId` targeting), and `IX_LlmRequests_UserId_Status` was confirmed pre-existing so no new index created; no new tests (migration-only)
676+
- **OPS-29** Docker container hardening (`#866`/`#889`): non-root end-to-end; backend uses `setpriv` entrypoint to chown `/app/data` and drop to `appuser` (UID 10001) — **upgrade-safe** for existing root-owned `taskdeck-db` volumes; backend HEALTHCHECK on `/health/ready`; frontend runs `nginxinc/nginx-unprivileged` with HEALTHCHECK on `/healthz`; **round-2 shipbreaker caught**: initial frontend HEALTHCHECK used `localhost`, BusyBox resolver preferred `::1` (IPv6) but nginx bound IPv4 only — probe never transitioned to healthy; fixed by pinning to `127.0.0.1`; docker-compose gains `mem_limit`/`cpus`, `logging` rotation (`max-size: 10m`/`max-file: 3`), `init: true`, `no-new-privileges`, unprivileged proxy
677+
- **FE-15** HTTP retry with exponential backoff (`#854`/`#890`): Axios retry interceptor in `httpRetry.ts` — max 3 attempts, exponential backoff (1s/2s/4s ± 25% jitter), idempotent methods only (GET/HEAD/OPTIONS/PUT/DELETE), 5xx + network + 408/429/503 retryable (501/505 excluded), 429 honours `Retry-After` (seconds + HTTP-date, case-insensitive via `AxiosHeaders`), no retry on 401/403/404/409/422, respects `axios.isCancel`, backoff races `AbortSignal`; **round-2 fixes**: `parseRetryAfter('-5')` returned 0 because HTTP-date branch lacked a proper letter-guard — fixed to return `null`; `skipRetry` opt-out on `RetryableRequestConfig` so pre-existing PR `#725` baseline tests (asserting retry-less 5xx) and 2 Playwright specs with first-request-fails mocks can opt out; new retry tests + E2E updates
678+
- **FE-14** Vue error boundary for crash prevention (`#852`/`#891`): `ErrorBoundary.vue` uses `onErrorCaptured` to render a recoverable fallback (Reload + Go-to-Home); `App.vue` wraps `<RouterView />` as outer backstop and `AppShell.vue` wraps its inner `<router-view />` for per-view crash containment; `main.ts` installs `app.config.errorHandler` plus `window` listeners for `error`/`unhandledrejection`; optional Sentry passthrough via `window.Sentry?.captureException`; **round-2 fix**: `crashedError === null` sentinel would collide if a descendant threw literal `null` — replaced with explicit `hasCrashed: boolean`; null-throw and Sentry info-context tests added (`ErrorBoundary.spec.ts` + `errorReporting.spec.ts`)
679+
- Closes `#853`, `#873`, `#874`, `#845`, `#846`, `#866`, `#854`, `#852` — all part of PROD-00 wave tracker `#881`
680+
669681
## Current Planning Pivot (2026-03-07)
670682

671683
The 2026-03-06 MVP expansion review packages change the next-cycle emphasis without invalidating the current architecture.

0 commit comments

Comments
 (0)