Skip to content

Commit 5421de5

Browse files
authored
docs: post-merge sweep for 10 PRs (2026-04-22) (#925)
* docs: update STATUS.md and AUDIT.md for 10-PR post-merge sweep Add delivery wave entry for PRs #914--#924 covering CI/hardening (SAST, migration validation, performance regression gate, circuit breaker), frontend decomposition (ReviewView, InboxView, AutomationChatView), ops (alerting rules), docs (data model ERD), and UX (session timeout warning). Mark resolved items in AUDIT.md: oversized views, session timeout, SAST, alerting rules, data model reference, performance regression tests. * docs: update IMPLEMENTATION_MASTERPLAN.md with wave 27 delivery history Add delivery wave 27 for PRs #914--#924 covering CI/hardening (SAST, migration validation, performance regression gate, circuit breaker), frontend decomposition (ReviewView, InboxView, AutomationChatView), ops (alerting rules), docs (data model ERD), and session timeout warning. Note ADR-0031 and ADR-0032. Update wave 26 to cross-reference view decomposition resolution. * docs: mark 10 issues delivered in ISSUE_EXECUTION_GUIDE.md Add Stage 7 with all 10 issues from PRs #914--#924 marked as delivered. Update Stage 6 execution note to reflect view decomposition is now resolved. * docs: add ADR-0031 and ADR-0032 to decisions index ADR-0031: SAST Scanning with Semgrep (from PR #915, CI-01) ADR-0032: Circuit Breaker for External API Calls (from PR #924, HARD-01) Note: Both PRs originally created ADR-0031. Renumbered the circuit breaker ADR to ADR-0032 to resolve the conflict. * docs: update TESTING_GUIDE.md with new CI gates and test totals Add migration-validation job to ci-required, SAST scanning and performance regression gate to ci-extended, and both to ci-nightly. Update test counts for circuit breaker (23 backend) and session timeout (19 frontend) tests. * docs: update CLAUDE.md frontend architecture description Reflect view decomposition pattern (thin shells + extracted composables/components) and add examples of view-specific composables and component directories. * docs: mark resolved items in EXPANSION_ROADMAP and HARDENING docs Mark view decomposition (ReviewView, InboxView, AutomationChatView) and monitoring/alerting setup as resolved in both roadmap files. * fix: format STATUS.md Last Updated line to pass docs governance check The governance regex requires the line to end after the date (YYYY-MM-DD) with only optional whitespace. Move the parenthetical sweep note to its own line. * fix: correct OPS-27 and PERF-12 issue numbers across docs OPS-27 (config validation) is GitHub issue #863, not #858. PERF-12 (board list pagination) is GitHub issue #848, not #859. The wrong numbers (#858/#859) belong to FE-17 and FE-18 respectively. Fixes references in STATUS.md, IMPLEMENTATION_MASTERPLAN.md, ISSUE_EXECUTION_GUIDE.md, AUDIT.md, HARDENING_AND_PERFORMANCE.md, TESTING_GUIDE.md, and CONFIGURATION_REFERENCE.md.
1 parent 12bf091 commit 5421de5

9 files changed

Lines changed: 92 additions & 38 deletions

CLAUDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ Tests mirror this layout in `backend/tests/` (`Domain.Tests`, `Application.Tests
7575

7676
### Frontend -- `frontend/taskdeck-web/src/`
7777

78-
- **views/**: Route-level pages (BoardView, InboxView, ReviewView, TodayView, HomeView, etc.)
78+
- **views/**: Route-level pages (BoardView, InboxView, ReviewView, AutomationChatView, TodayView, HomeView, etc.). Large views are decomposed into thin shells (<300 lines) that delegate to extracted components and composables.
7979
- **store/**: Pinia stores -- boardStore, captureStore, queueStore, sessionStore, workspaceStore, notificationStore, etc.
8080
- **api/**: HTTP client modules for backend communication
81-
- **composables/**: Shared Vue composition functions
82-
- **components/**: Reusable UI components
81+
- **composables/**: Shared Vue composition functions (including view-specific orchestrators like useReviewProposals, useInboxOrchestrator, useAutomationChat, useBoardDragDrop, useSessionTimeout, etc.)
82+
- **components/**: Reusable UI components (shared Td* primitives in `components/ui/`, plus view-specific components extracted from decomposed views)
8383
- **router/**: Vue Router configuration
8484

8585
Uses Tailwind CSS, TypeScript, and Vue 3 composition API (`<script setup>`).

docs/AUDIT.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
6363
| Severity | Issue | Location |
6464
|----------|-------|----------|
6565
| ~~CRITICAL~~ RESOLVED | ~~Only 1 EF migration in source control — fresh environments cannot bootstrap~~ 21 migrations in source control; full chain applies cleanly to fresh SQLite; `MigrationBootstrapTests` guard regression; workflow documented in `docs/platform/EF_MIGRATION_WORKFLOW.md` (`#864`/PR `#907`) | `backend/src/Taskdeck.Infrastructure/Migrations/` |
66-
| ~~CRITICAL~~ RESOLVED | ~~No configuration validation at startup (`ValidateOnStart()`)~~ data annotations on 15 settings classes + 4 `IValidateOptions<T>` cross-property validators + `ValidateOnStart()` via `RegisterValidatedOptions<T>` helper; 34 `OptionsValidationTests` (OPS-27 `#858`/PR `#908`) | `Program.cs`, all settings classes |
66+
| ~~CRITICAL~~ RESOLVED | ~~No configuration validation at startup (`ValidateOnStart()`)~~ data annotations on 15 settings classes + 4 `IValidateOptions<T>` cross-property validators + `ValidateOnStart()` via `RegisterValidatedOptions<T>` helper; 34 `OptionsValidationTests` (OPS-27 `#863`/PR `#908`) | `Program.cs`, all settings classes |
6767
| HIGH | No API versioning strategy — breaking changes have no compatibility path | All controllers |
6868
| MEDIUM | MCP mode duplicates DI registration from web mode | `Program.cs` lines 72-91 |
6969
| MEDIUM | No value objects for Email/Username — validation scattered | Domain entities |
@@ -88,7 +88,7 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
8888

8989
| Severity | Issue | Details |
9090
|----------|-------|---------|
91-
| CRITICAL | Views over 1,500 lines | ReviewView (1,659), InboxView (1,527), AutomationChatView (1,523) |
91+
| ~~CRITICAL~~ | ~~Views over 1,500 lines~~ | ~~ReviewView (1,659), InboxView (1,527), AutomationChatView (1,523)~~ RESOLVED: all 3 decomposed in PRs #920, #921, #923 |
9292
| CRITICAL | No error boundary | Component render errors crash entire app |
9393
| HIGH | No request retry/backoff | Network failures not recovered gracefully |
9494
| HIGH | Modals oversized | StarterPackCatalogModal (1,253), CardModal (681) |
@@ -97,7 +97,7 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
9797
| MEDIUM | No loading skeleton consistency | TdSkeleton exists but not used in all views |
9898
| MEDIUM | No offline mutation queue | Changes made while offline are lost |
9999
| MEDIUM | Virtual scrolling in only 2 of 16 list views | ReviewView, ActivityView need it |
100-
| LOW | No session timeout warning | Token expires silently |
100+
| ~~LOW~~ | ~~No session timeout warning~~ | ~~Token expires silently~~ RESOLVED: `useSessionTimeout` composable + `SessionTimeoutWarning.vue` (PR #919); backend refresh endpoint not yet implemented |
101101

102102
### Production Readiness: 65%
103103

@@ -145,7 +145,7 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
145145
| **No response compression** — 5-10MB responses uncompressed | 90% bandwidth reduction | 1 hour | Open |
146146
| **Missing database indexes** — AuditLog, LlmRequest, Card | 10-100x query speedup on large tables | 1 hour | Open |
147147
| **Sync I/O in WorkspaceService**`.Result` blocking async | Prevents thread pool starvation | 30 min | RESOLVED (PERF-11 `#847`/PR `#904`) |
148-
| **No pagination on board list** — returns ALL boards | Blocks team-scale (100+ boards) | 2 hours | RESOLVED (PERF-12 `#859`/PR `#909`) |
148+
| **No pagination on board list** — returns ALL boards | Blocks team-scale (100+ boards) | 2 hours | RESOLVED (PERF-12 `#848`/PR `#909`) |
149149
| **AuditLog in-memory filtering** — should be SQL-level | 50ms+ per activity load eliminated | 2 hours | RESOLVED (PERF-13 `#849`/PR `#903`) |
150150

151151
### Architectural Bottlenecks
@@ -200,7 +200,7 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
200200
### Test Gaps
201201
- Frontend views >1,000 lines are harder to test thoroughly
202202
- Virtual scrolling not tested under load
203-
- No performance regression tests in CI gate
203+
- ~~No performance regression tests in CI gate~~ RESOLVED: k6 thresholds + bundle size checks in `ci-extended`/`ci-nightly` (CI-03 `#872`/PR `#918`)
204204
- E2E cross-browser is advisory, not required
205205

206206
---
@@ -233,11 +233,11 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
233233
| Production readiness | Basic | Missing migration safety, secrets rotation, alerting |
234234

235235
### Critical Gaps for Production
236-
1. No SAST (static analysis security testing) in CI
236+
1. ~~No SAST (static analysis security testing) in CI~~ RESOLVED: Semgrep with custom C#/TypeScript rules, advisory mode in `ci-extended`/`ci-nightly` (CI-01 `#870`/PR `#915`)
237237
2. ~~No database migration validation in CI~~ RESOLVED: `MigrationBootstrapTests` verify fresh-bootstrap + model drift on every run (OPS-28 `#864`/PR `#907`)
238238
3. No Terraform `plan` validation in CI
239239
4. ~~No secrets detection (Gitleaks or equivalent)~~ RESOLVED: advisory PR scan in `ci-extended.yml`, blocking full-history scan in `ci-release.yml` (CI-02 `#871`/PR `#902`)
240-
5. No monitoring/alerting rules defined
240+
5. ~~No monitoring/alerting rules defined~~ RESOLVED: 10 alert rules with severity tiers (P1/P2), Grafana/CloudWatch/PagerDuty integration paths documented (OPS-30 `#868`/PR `#914`)
241241
6. No on-call runbook or escalation policy
242242
7. Docker containers run as root (no USER instruction)
243243

@@ -256,7 +256,7 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
256256
| Testing guide | 9/10 | Comprehensive totals, category breakdown, commands |
257257
| Security docs | 8/10 | OWASP, secrets, rate limiting, redaction, incidents |
258258
| Configuration reference | 4/10 | No appsettings.json schema, no env var docs |
259-
| Data model reference | 3/10 | No entity docs, no ERD |
259+
| ~~Data model reference~~ | ~~3/10~~ 9/10 | ~~No entity docs, no ERD~~ RESOLVED: `docs/architecture/DATA_MODEL.md` (855 lines, 37 entities, Mermaid ERD) (DOC-08 `#875`/PR `#917`) |
260260
| Contributor guide | 7.5/10 | Split across AGENTS.md, CLAUDE.md; no CONTRIBUTING.md |
261261
| **Overall** | **8.5/10** | Strong governance, targeted gaps |
262262

@@ -297,10 +297,10 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
297297

298298
### Tier 2: Before Production Launch (This Month)
299299

300-
6. **Decompose oversized views** ReviewView, InboxView, AutomationChatView — 8 hours each — Open
300+
6. ~~**Decompose oversized views**~~ RESOLVED: ReviewView (PR #923), InboxView (PR #921), AutomationChatView (PR #920) — all decomposed to <250-line shells + extracted components/composables
301301
7. **Implement error boundary** — catch render errors with fallback UI — 2 hours — Open
302-
8. ~~**Add configuration validation at startup**~~ RESOLVED (OPS-27 `#858`/PR `#908`)
303-
9. **Add API response pagination** — board list RESOLVED (PERF-12 `#859`/PR `#909`); audit, activity still Open
302+
8. ~~**Add configuration validation at startup**~~ RESOLVED (OPS-27 `#863`/PR `#908`)
303+
9. **Add API response pagination** — board list RESOLVED (PERF-12 `#848`/PR `#909`); audit, activity still Open
304304
10. **Create `SECURITY.md`** vulnerability disclosure policy — 1 hour — Open
305305

306306
### Additional Tier 2 work delivered in the 2026-04-22 wave

docs/EXPANSION_ROADMAP.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ These items block shipping to real users.
4343
|------|--------|--------|---------|
4444
| Implement Vue error boundary | S | Prevents full-app crashes | Vue 3 error handler in main.ts |
4545
| Add HTTP request retry with exponential backoff | M | Handles transient network failures | Axios interceptor pattern |
46-
| Decompose ReviewView (1,659 lines) | M | Maintainability, testability | Split into 3-4 focused components |
47-
| Decompose InboxView (1,527 lines) | M | Maintainability, testability | Split into 3-4 focused components |
48-
| Decompose AutomationChatView (1,523 lines) | M | Maintainability, testability | Split into 3-4 focused components |
46+
| ~~Decompose ReviewView (1,659 lines)~~ | ~~M~~ | ~~Maintainability, testability~~ | DONE (PR #923) — 148-line shell + 6 components + 2 composables |
47+
| ~~Decompose InboxView (1,527 lines)~~ | ~~M~~ | ~~Maintainability, testability~~ | DONE (PR #921) — 222-line shell + 2 panels + 1 composable + utils |
48+
| ~~Decompose AutomationChatView (1,523 lines)~~ | ~~M~~ | ~~Maintainability, testability~~ | DONE (PR #920) — 235-line shell + 7 components + 1 composable |
4949

5050
### 1.4 Documentation
5151
| Item | Effort | Impact | Details |

docs/HARDENING_AND_PERFORMANCE.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ CREATE INDEX IX_Cards_BoardId_ColumnId ON Cards(BoardId, ColumnId);
6666

6767
### 1.4 Paginate Board List Endpoint
6868

69-
**RESOLVED** (PERF-12 `#859`/PR `#909`): `GET /api/boards` accepts `offset`/`limit` query parameters (default 50, server-clamped `[1, 200]`); response is now `PaginatedResult<BoardDto>` with `items`/`totalCount`/`hasMore`/`offset`/`limit`. Authorization filter is applied before pagination so `totalCount` reflects only boards the caller is authorised to see. `BoardRepository.SearchIdsAsync` uses stable ordering (`CreatedAt DESC`, `Id` tiebreaker) so offset-based pages do not overlap. Frontend `boardsApi.getBoards` delegates to `getBoardsPaginated` and returns `.items` for backward compatibility. 11 new `BoardPaginationApiTests` cover cross-user isolation, limit clamping, empty list, and full-page iteration.
69+
**RESOLVED** (PERF-12 `#848`/PR `#909`): `GET /api/boards` accepts `offset`/`limit` query parameters (default 50, server-clamped `[1, 200]`); response is now `PaginatedResult<BoardDto>` with `items`/`totalCount`/`hasMore`/`offset`/`limit`. Authorization filter is applied before pagination so `totalCount` reflects only boards the caller is authorised to see. `BoardRepository.SearchIdsAsync` uses stable ordering (`CreatedAt DESC`, `Id` tiebreaker) so offset-based pages do not overlap. Frontend `boardsApi.getBoards` delegates to `getBoardsPaginated` and returns `.items` for backward compatibility. 11 new `BoardPaginationApiTests` cover cross-user isolation, limit clamping, empty list, and full-page iteration.
7070

7171
**Follow-up (still open)**: audit and activity endpoints also need pagination.
7272

@@ -80,7 +80,7 @@ CREATE INDEX IX_Cards_BoardId_ColumnId ON Cards(BoardId, ColumnId);
8080

8181
### 2.1 Configuration Validation at Startup
8282

83-
**RESOLVED** (OPS-27 `#858`/PR `#908`): data annotations (`[Required]`, `[Range]`, `[MinLength]`, `[RegularExpression]`, `[Url]`) added to 15 settings classes — `JwtSettings`, `WorkerSettings`, `CacheSettings`, `RateLimitingSettings`, `LlmProviderSettings`, `OpenAiProviderSettings`, `GeminiProviderSettings`, `ObservabilitySettings`, `SentrySettings`, `SecurityHeadersSettings`, `TelemetrySettings`, `LlmQuotaSettings`, `LlmToolCallingSettings`, `AbuseDetectionSettings`, `MfaPolicySettings`. Four cross-property `IValidateOptions<T>` validators enforce: `WorkerSettings.RetryBackoffSeconds.Length >= MaxRetries`, `JwtSettings.SecretKey` non-empty + minimum length, `SentrySettings.Dsn` required when `Enabled`, and `RateLimitingSettings` nested policy ranges. All wired via a new `RegisterValidatedOptions<T>` helper that calls `ValidateDataAnnotations()` + `ValidateOnStart()`. `LlmProvider`/`CacheProvider` regex patterns use `(?i)` flag to match the runtime case-insensitive comparison. `JwtSettings.SecretKey` is intentionally not `[Required]` because `FirstRunBootstrapper` generates it before validation runs. 34 `OptionsValidationTests` cover data-annotation boundaries and cross-property rules.
83+
**RESOLVED** (OPS-27 `#863`/PR `#908`): data annotations (`[Required]`, `[Range]`, `[MinLength]`, `[RegularExpression]`, `[Url]`) added to 15 settings classes — `JwtSettings`, `WorkerSettings`, `CacheSettings`, `RateLimitingSettings`, `LlmProviderSettings`, `OpenAiProviderSettings`, `GeminiProviderSettings`, `ObservabilitySettings`, `SentrySettings`, `SecurityHeadersSettings`, `TelemetrySettings`, `LlmQuotaSettings`, `LlmToolCallingSettings`, `AbuseDetectionSettings`, `MfaPolicySettings`. Four cross-property `IValidateOptions<T>` validators enforce: `WorkerSettings.RetryBackoffSeconds.Length >= MaxRetries`, `JwtSettings.SecretKey` non-empty + minimum length, `SentrySettings.Dsn` required when `Enabled`, and `RateLimitingSettings` nested policy ranges. All wired via a new `RegisterValidatedOptions<T>` helper that calls `ValidateDataAnnotations()` + `ValidateOnStart()`. `LlmProvider`/`CacheProvider` regex patterns use `(?i)` flag to match the runtime case-insensitive comparison. `JwtSettings.SecretKey` is intentionally not `[Required]` because `FirstRunBootstrapper` generates it before validation runs. 34 `OptionsValidationTests` cover data-annotation boundaries and cross-property rules.
8484

8585
### 2.2 Database Migration Infrastructure
8686

@@ -152,9 +152,9 @@ axiosRetry(http, {
152152

153153
| View | Current Lines | Decomposition Strategy |
154154
|------|--------------|----------------------|
155-
| ReviewView | 1,659 | Extract ProposalList, ProposalDetail, ProposalDiff |
156-
| InboxView | 1,527 | Extract CaptureList, CaptureDetail, BatchActionBar |
157-
| AutomationChatView | 1,523 | Extract MessageList, ChatInput, ToolStatusPanel |
155+
| ~~ReviewView~~ | ~~1,659~~ 148 | DONE (PR #923) — 6 components + 2 composables |
156+
| ~~InboxView~~ | ~~1,527~~ 222 | DONE (PR #921) — 2 panels + 1 composable + utils |
157+
| ~~AutomationChatView~~ | ~~1,523~~ 235 | DONE (PR #920) — 7 components + 1 composable |
158158
| MetricsView | 920 | Extract MetricsCharts, MetricsTable, ForecastPanel |
159159
| HomeView | 804 | Extract WorkspaceSummary, QuickActions, RecentActivity |
160160

@@ -383,10 +383,10 @@ services.AddHttpClient("llm-provider")
383383
16. ~~Import file magic byte validation (3h)~~ RESOLVED (SEC-30 PR `#910`)
384384

385385
### This Quarter (100 hours)
386-
17. View decomposition — remaining oversized views (24h)
386+
17. ~~View decomposition — remaining oversized views (24h)~~ RESOLVED (PRs #920, #921, #923)
387387
18. Responsive design for mobile (16h)
388388
19. PostgreSQL migration (40h)
389-
20. Monitoring/alerting setup (16h)
389+
20. ~~Monitoring/alerting setup (16h)~~ RESOLVED (OPS-30 PR `#914`)
390390
21. Distributed rate limiting (8h)
391391

392392
---

0 commit comments

Comments
 (0)