You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/STATUS.md
+16-3Lines changed: 16 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Taskdeck Status (Source of Truth)
2
2
3
-
Last Updated: 2026-04-15
3
+
Last Updated: 2026-04-16
4
4
<br>
5
5
Status Owner: Repository maintainers
6
6
Authoritative Scope: Current implementation, verified test execution, and active phase progress
@@ -135,6 +135,16 @@ Current constraints are mostly hardening and consistency:
135
135
-**INT-06 integrations registry foundation** (`#340`/`#841`): full-stack integrations registry with domain entities (`IntegrationConnector`, `ConnectorEvent` with `ConnectorType`/`ConnectorDirection`/`ConnectorStatus` enums), application service (`IntegrationRegistryService` with `IIntegrationConnectorRepository`/`IConnectorEventRepository`), EF Core infrastructure (repositories + `AddIntegrationConnectorsAndEvents` migration), API (`IntegrationsController` with 7 endpoints — CRUD + enable/disable, all `[Authorize]`), frontend (`IntegrationsView.vue` at `/workspace/integrations` with `integrationStore` and `integrationsApi` with enum normalization), connector taxonomy (inbound/context/outbound per GP-06 — inbound connectors route through capture), architecture documentation at `docs/architecture/INTEGRATIONS_REGISTRY.md`; 60 new tests (24 domain + 12 application + 15 API + 9 frontend)
- PROD-00 production-readiness round-2 hardening wave (2026-04-16, PRs `#884`–`#891`, 8 issues from PROD-00 tracker `#881`, each PR received two rounds of adversarial review with bot-findings triage):
139
+
-**SEC-28 SECURITY.md vulnerability disclosure policy** (`#853`/`#884`): repo-root `SECURITY.md` with responsible-disclosure contact (GitHub private vulnerability reporting + fallback email), 48h acknowledgement target, supported-versions scope (`main` guaranteed; latest pre-1.0 tag best-effort), in-scope/out-of-scope breakdown, and safe-harbor language; README cross-link; round-2 enabled the private vulnerability reporting feature and reconciled supported-versions prose with the table
140
+
-**DOC-06 CONTRIBUTING.md onramp** (`#873`/`#885`): repo-root `CONTRIBUTING.md` covering prerequisites, cross-platform local setup (Windows/macOS/Linux), Windows-specific notes (`check-git-env.sh`, Cygwin-git pitfall, PowerShell chaining, stale `index.lock`), default URLs, test commands (backend xUnit, frontend typecheck/build/vitest/lint, Playwright E2E), commit conventions, and PR process; README cross-link; AGENTS.md remains the authoritative contributor protocol
141
+
-**DOC-07 CONFIGURATION_REFERENCE appsettings schema** (`#874`/`#887`): `docs/platform/CONFIGURATION_REFERENCE.md` documents every configuration section in `backend/src/Taskdeck.Api/appsettings.json` and every typed `*Settings.cs` binding (JWT, GitHub OAuth, OIDC, MFA, LLM provider/tool-calling/quota/kill-switch/abuse-detection, Workers, Outbound webhook security, CORS, Forwarded headers, Rate limiting, Cache, SignalR backplane, Security headers, Observability/Sentry/Telemetry/Analytics, Connection strings, Export/import, First run, Development sandbox, Logging, MCP server) with key/type/default/description/required flags and environment-variable override conventions; cross-linked from `CLAUDE.md` Key Docs and `docs/platform/README.md`; `deploy/.env.example` aligned
142
+
-**PERF-09 response compression** (`#845`/`#886`): `AddTaskdeckResponseCompression()` registers Brotli + Gzip providers with `EnableForHttps = true`; `UseResponseCompression()` wired in `PipelineConfiguration` after forwarded headers and before CORS/static/routing so controllers, SPA assets, and `index.html` fallback all emit compressed bodies when the client opts in via `Accept-Encoding`; compressible MIME set extended to include `application/problem+json`; 3 integration tests in `ResponseCompressionApiTests` (gzip encoding, brotli encoding, no-compression baseline); **round-2 correction**: BREACH threat-model analysis caught that JWTs are in fact returned in `/api/auth/login` and `/api/auth/register` response bodies (contradicting the inline comment assuming JWTs only appeared in `Authorization` headers); compression level downgraded from `CompressionLevel.Optimal` to `CompressionLevel.Fastest` to reduce BREACH/CRIME oracle surface while preserving bandwidth wins
143
+
-**PERF-10 composite DB indexes** (`#846`/`#888`): EF Core migration `20260416161303_AddPerfIndexes` adds three composite indexes — `IX_Cards_BoardId_ColumnId` replaces the single-column `IX_Cards_BoardId` (SQLite satisfies leftmost-prefix via the composite; `FK_Cards_Boards_BoardId` remains enforced by the FOREIGN KEY schema; `IX_Cards_ColumnId` retained), `IX_AuditLogs_UserId_Timestamp` accelerates `AuditLogRepository.GetByUserAsync`, and `IX_AuditLogs_EntityId_Timestamp` accelerates `AuditLogRepository.GetByBoardAsync`; **explicit deviations from issue AC documented**: `AuditLog.EntityId` is used instead of the aspirational `BoardId` (AuditLog uses polymorphic `EntityId` targeting, not a dedicated `BoardId`), and `IX_LlmRequests_UserId_Status` was confirmed pre-existing so no new migration was required
144
+
-**OPS-29 Docker container hardening** (`#866`/`#889`): backend and frontend containers now run non-root end-to-end; backend Dockerfile uses `setpriv` entrypoint to chown `/app/data` and drop to `appuser` (UID 10001) for upgrade-safe volume ownership on existing root-owned `taskdeck-db` volumes; backend HEALTHCHECK against `/health/ready`; frontend runs on `nginxinc/nginx-unprivileged` with HEALTHCHECK against `/healthz` (dedicated nginx location); docker-compose gains `mem_limit`/`cpus` (classic-compose compatible), `logging` driver with `max-size: 10m`/`max-file: 3`, `init: true`, `no-new-privileges`, and unprivileged proxy image; **round-2 shipbreaker caught**: initial frontend HEALTHCHECK used `localhost`, which BusyBox's resolver preferred as `::1` (IPv6) while nginx bound IPv4 only, so the healthcheck never transitioned to healthy; fixed by pinning the probe to `127.0.0.1`
145
+
- **FE-15 HTTP retry with exponential backoff** (`#854`/`#890`): Axios retry interceptor in `httpRetry.ts` with max 3 attempts, exponential backoff (1s/2s/4s ± 25% jitter), idempotent methods only (GET, HEAD, OPTIONS, PUT, DELETE — POST/PATCH never retried), 5xx + network + 408/429/503 retryable (501/505 excluded), 429 honours `Retry-After` (seconds or HTTP-date) capped at a sane upper bound, no retry on 401/403/404/409/422, respects `axios.isCancel` for navigation aborts, backoff races against `AbortSignal`, logging gated behind `import.meta.env.DEV`; **round-2 fixes**: `parseRetryAfter('-5')` was returning 0 because the HTTP-date branch required only letter presence as a guard — fixed with a proper letter-guard to return `null`; `skipRetry` opt-out introduced on `RetryableRequestConfig` so pre-existing PR `#725` baseline tests (which assert retry-less 5xx semantics) and two Playwright specs with first-request-fails mocks can opt out without being silently retried; case-insensitive `Retry-After` header parsing via `AxiosHeaders`
146
+
-**FE-14 Vue error boundary for crash prevention** (`#852`/`#891`): `ErrorBoundary.vue` uses `onErrorCaptured` to catch descendant render/lifecycle errors and render a recoverable fallback (Reload + Go-to-Home actions); `App.vue` wraps `<RouterView />` in an outer `ErrorBoundary` backstop, and `AppShell.vue` wraps its inner `<router-view />` in a nested `ErrorBoundary` for per-view crash containment so a crashed view does not take down the shell; `main.ts` installs `app.config.errorHandler` plus `window` listeners for `error` and `unhandledrejection`; optional Sentry passthrough via `window.Sentry?.captureException` (no hard dependency); dev-only stack trace display, prod-safe messaging; **round-2 fix**: the `crashedError === null` sentinel would collide if a descendant threw a literal `null` — replaced with an explicit `hasCrashed: boolean` flag; null-throw and Sentry-info-context coverage added to tests
147
+
138
148
Target experience metrics for the capture direction:
139
149
- capture action to saved artifact should feel under 10 seconds in normal use
140
150
- capture artifact to reviewed/applicable proposal should be achievable inside a ~60-second loop
@@ -149,7 +159,7 @@ Direction guardrails (explicit):
- Persistence: EF Core 8.0.14 + SQLite (aligned to net8.0 TFM as of `#760`/`#767`)
162
+
- Persistence: EF Core 8.0.14 + SQLite (aligned to net8.0 TFM as of `#760`/`#767`); composite indexes delivered via migration `20260416161303_AddPerfIndexes` (`#846`/`#888`) — `IX_Cards_BoardId_ColumnId` replaces the single-column `IX_Cards_BoardId`, `IX_AuditLogs_UserId_Timestamp` accelerates `GetByUserAsync`, and `IX_AuditLogs_EntityId_Timestamp` accelerates `GetByBoardAsync` (AuditLog uses polymorphic `EntityId`, not a dedicated `BoardId`)
@@ -163,6 +173,7 @@ Direction guardrails (explicit):
163
173
-`AuthenticatedControllerBase` for claim extraction and authenticated-user guardrails
164
174
- request correlation middleware (`X-Request-Id`) with response echo and log scope propagation
165
175
- development CORS origin policy keeps localhost defaults (`http://localhost:5173`, `http://localhost:5174`), adds fallback localhost dev ports (`http://localhost:4173`, `http://localhost:5001`), and supports additive `Cors:DevelopmentAllowedOrigins` config overrides
176
+
- response compression (`#845`/`#886`): `AddTaskdeckResponseCompression()` registers Brotli + Gzip providers at `CompressionLevel.Fastest` (BREACH-aware downgrade from `Optimal`) with `EnableForHttps = true`; `UseResponseCompression()` wired in `PipelineConfiguration` after forwarded headers and before CORS/static/routing; compressible MIME set includes `application/problem+json` alongside JSON defaults
166
177
- Implemented automation stack:
167
178
-`AutomationProposalService`, `AutomationPlannerService`, `AutomationPolicyEngine`, `AutomationExecutorService` (decomposed into `OperationParameterParser`, `ExecutionAuditRecorder`, `OperationHandlerRegistry`)
168
179
-`ArchiveRecoveryService` (decomposed into `ArchiveConflictDetector`, `RestorePlanner`, `RestoreExecutor`)
@@ -232,6 +243,8 @@ Direction guardrails (explicit):
232
243
- Cross-cutting UI infrastructure:
233
244
- command palette with global search (Ctrl+K): live cross-board search for boards and cards via `/api/search`, with 200ms debounced queries, abort-on-supersede, and keyboard-first grouped results navigation
- HTTP retry interceptor (`#854`/`#890`): `httpRetry.ts` Axios interceptor retries 5xx/network/408/429/503 on idempotent methods only (GET/HEAD/OPTIONS/PUT/DELETE — POST/PATCH never retried), max 3 attempts with exponential backoff (1s/2s/4s ± 25% jitter), honours `Retry-After` (seconds + HTTP-date, case-insensitive) with a sane upper bound, races backoff against `AbortSignal`, respects `axios.isCancel`; `skipRetry` opt-out on `RetryableRequestConfig` for test baselines and error-state E2E mocks
247
+
- Vue error boundary for crash prevention (`#852`/`#891`): `ErrorBoundary.vue` uses `onErrorCaptured` with an explicit `hasCrashed` boolean sentinel (null-throw safe) to render a recoverable fallback (Reload + Go-to-Home); `App.vue` wraps `<RouterView />` as outer backstop while `AppShell.vue` wraps its inner `<router-view />` as per-view crash containment; `main.ts` installs `app.config.errorHandler` plus `window` listeners for `error` and `unhandledrejection`; optional Sentry passthrough via `window.Sentry?.captureException`
235
248
- shared UI primitives foundation (UI-02): 15 TdButton/TdInput/TdDialog/TdDropdown/TdTooltip/TdBadge/etc. primitives built on Reka UI via shadcn-vue ownership model with WAI-ARIA keyboard foundation; stack decision documented in `docs/analysis/ui-primitive-stack-decision-spike.md`
236
249
- appshell premium reskin: shell sidebar, topbar, command palette, and keyboard help components now use `--td-*` design token system with focus-visible accessibility rings and glass morphism effects
237
250
- board/card surface polish: board canvas, toolbar, action rail, column lanes, and card components now use design-token-based styling with standardized interactive states and accessibility focus rings
@@ -1027,7 +1040,7 @@ Automation and data:
1027
1040
1028
1041
Observability and scalability:
1029
1042
- frontend/CI baseline is now Node 24.13.1 (LTS) to align with Vite 7 engine requirements and longer support runway
1030
-
- containerized deployment baseline is now shipped (`#69`): backend/frontend Dockerfiles, compose profile, reverse proxy compression/security headers posture, and CI image artifacts
1043
+
- containerized deployment baseline is now shipped (`#69`): backend/frontend Dockerfiles, compose profile, reverse proxy compression/security headers posture, and CI image artifacts; **container hardening delivered** (`#866`/`#889`): backend and frontend containers now run non-root end-to-end — backend uses a `setpriv` entrypoint that chowns `/app/data` and drops to `appuser` (UID 10001) for upgrade-safe volume ownership on existing root-owned `taskdeck-db` volumes with HEALTHCHECK on `/health/ready`; frontend runs on `nginxinc/nginx-unprivileged` with HEALTHCHECK on `/healthz` (dedicated nginx location; probe pinned to `127.0.0.1` because BusyBox's `localhost` resolver preferred IPv6 `::1` while nginx bound IPv4 only); docker-compose adds `mem_limit`/`cpus`, `logging` rotation (`max-size: 10m`/`max-file: 3`), `init: true`, `no-new-privileges`, and unprivileged proxy image
1031
1044
- Terraform IaC baseline is now shipped (`#102`): reusable AWS single-node environment templates (`dev`/`staging`/`prod`), host bootstrap for the existing Docker workload layer, JWT secret retrieval from a pre-created SecureString SSM parameter instead of raw EC2 user-data injection, a dedicated persistent EBS data volume for `/var/lib/taskdeck`, instance replacement on bootstrap changes without discarding the SQLite path, stop-before-detach protection for planned data-volume attachment changes, protected data-volume destroy defaults for `staging`/`prod`, backup-bucket noncurrent-version expiry with explicit versioning dependency, and an operator drift-check workflow
1032
1045
- multi-tenancy strategy ADR is now documented (`#71`) with shared-schema + `TenantId` as the default rollout target; tenant isolation implementation slices remain pending
1033
1046
- local developer MCP posture now includes a Docker Marketplace server bundle with a stable default gateway set (`docker,docker-docs,openapi,time,jetbrains,filesystem,SQLite,terraform`) and optional integrations staged behind credentials/config (`postman`, `dockerhub`, `kubernetes`, `semgrep`)
0 commit comments