Skip to content

Commit 2cf23a0

Browse files
committed
docs: post-merge sweep for PRs #944-#949
Update STATUS.md, IMPLEMENTATION_MASTERPLAN.md, TESTING_GUIDE.md, MANUAL_TEST_CHECKLIST.md, AUDIT.md, and HARDENING_AND_PERFORMANCE.md to reflect the mobile/security/legal/testing expansion wave: FE-19 mobile responsive, SEC-29 CSP style-src, legal drafts, TST-59 visual regression expansion, TST-60 E2E parallelization.
1 parent b0e69f2 commit 2cf23a0

6 files changed

Lines changed: 34 additions & 9 deletions

File tree

docs/AUDIT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ Taskdeck is a **mature, well-engineered product** at the end of its core build p
124124
| HIGH | No encryption at rest for SQLite database | Sensitive data accessible with file access |
125125
| MEDIUM | No role-based authorization (RBAC) | All authenticated users have equal access |
126126
| MEDIUM | No vulnerability disclosure policy (`SECURITY.md`) | No responsible disclosure path |
127-
| MEDIUM | `style-src 'unsafe-inline'` in CSP | Allows inline style injection |
127+
| MEDIUM | ~~`style-src 'unsafe-inline'` in CSP~~ | **Partially mitigated** (SEC-29/`#945`): API CSP no longer has `'unsafe-inline'` in `style-src`; reverse-proxy uses `style-src-elem 'self'` to block `<style>` injection in modern browsers; `'unsafe-inline'` remains in `style-src` fallback for Vue `:style` bindings (27 files); follow-up: migrate to CSS custom properties |
128128
| MEDIUM | No distributed rate limiting | Multi-instance bypasses in-process limits |
129129
| MEDIUM | Audit trail retention unbounded | Grows indefinitely |
130130
| LOW | No OAuth scope validation | Scope claims not checked |

docs/HARDENING_AND_PERFORMANCE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ axiosRetry(http, {
196196

197197
### 4.3 CSP Hardening
198198

199-
**Gap**: `style-src 'unsafe-inline'` allows inline style injection.
199+
**Partially mitigated** (SEC-29, `#855`/`#945`): API CSP no longer includes `'unsafe-inline'` in `style-src`. Reverse-proxy CSP adds `style-src-elem 'self'` to block inline `<style>` blocks in modern browsers. `'unsafe-inline'` remains in the `style-src` fallback for Vue's reactive `:style` bindings (27 files with `el.style.x = y` mutations).
200200

201-
**Fix**: Migrate inline styles to external CSS classes or use nonce-based CSP.
201+
**Remaining fix**: Migrate the 27 `:style` binding files to CSS custom properties (e.g., `style="--tag-color: ..."` set once on a wrapper, consumed by scoped stylesheet) so `'unsafe-inline'` can be dropped entirely from `style-src`.
202202

203203
### 4.4 Import File Validation
204204

docs/IMPLEMENTATION_MASTERPLAN.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,13 @@ Delivered in the latest cycle:
680680
- **CI-02 Gitleaks secrets detection** (`#871`/`#902`): `.gitleaks.toml` extends default rules with project-specific allowlists (test fixtures, dev placeholders, CI-only vars); `.gitleaksignore`; reusable workflow `reusable-gitleaks.yml` with `scan-mode` (`pr`/`full`) + `fail-on-findings` toggle; action pinned to commit SHA `ff98106e` (not a mutable tag); non-blocking advisory scan on every PR via `ci-extended.yml`; blocking full-history scan via CLI (event-agnostic; works on release events) in `ci-release.yml`; SARIF artefact uploaded; CI topology comment updated
681681
- total impact on audit posture: all 5 Tier 1 ("Before Any External User") items from `docs/AUDIT.md` are now resolved (response compression still outstanding outside this wave); 4 of 5 Tier 2 items resolved (view decomposition and error boundary remain); SSRF + dev-secret + content-validation gaps from the security audit closed
682682

683+
136. Mobile, security, legal, and testing expansion wave (2026-04-23, PRs `#944``#949`, 5 PRs with adversarial review per PR):
684+
- **FE-19 mobile-responsive board, toolbar, and dialog** (`#860`/`#944`): board columns stack vertically on ≤640px; `TdDialog` full-bleed with `100dvh` at mobile; 44×44px tap targets on toolbar and action rail; `--td-font-lg` token for iOS zoom prevention; `@mobile` Playwright test; WCAG 2.4.3 footer tab-order fix; scoped slot CSS penetration fix (`:deep(> *)`) and `overflow-x: clip` for spec-correct mobile overflow
685+
- **SEC-29 CSP style-src tightening (partial)** (`#855`/`#945`): removed `'unsafe-inline'` from `style-src` in API CSP; `style-src-elem 'self'` in reverse-proxy blocks inline `<style>` injection; regression test added; 4 docs updated; follow-up: migrate 27 `:style` binding files to CSS custom properties
686+
- **Legal document drafts** (`#548`/`#946`): 5 DRAFT documents in `docs/legal/` — Privacy Policy, Terms of Service, Sub-Processors (with conditional Sentry), Cookie Policy (concrete localStorage keys, OAuth cookie disclosure), and README with launch checklist; grounded in actual codebase behavior with `[LEGAL REVIEW REQUIRED]` markers
687+
- **TST-59 visual regression expansion** (`#865`/`#948`): 15 new visual regression specs (total 20 components); clock pinning, timestamp masking, font-load determinism; redundant networkidle waits removed
688+
- **TST-60 E2E parallelization** (`#867`/`#949`): `fullyParallel: true` with 2-worker default; `Cache=Shared` dropped; idempotent `.check()` for WIP toggle; `Default Timeout=30` comment corrected; WAL mode documented as follow-up
689+
683690
## Current Planning Pivot (2026-03-07)
684691

685692
The 2026-03-06 MVP expansion review packages change the next-cycle emphasis without invalidating the current architecture.
@@ -873,7 +880,7 @@ Master tracker: `#531`.
873880

874881
- `v0.3.0` **In Your Pocket** (target: Week 6-9):
875882
- ~~PWA manifest + service worker (`#540` → `#541`, `#542`)~~ — baseline delivered in `#95`: Workbox generateSW with precaching, runtime caching, SPA navigateFallback, offline banner, SW update prompt, installability-ready manifest
876-
- mobile-responsive CSS for core flows (`#543`)
883+
- ~~mobile-responsive CSS for core flows (`#543`)~~ — baseline delivered in `#944` (FE-19): board vertical stacking, TdDialog full-bleed, 44px tap targets, iOS zoom prevention; secondary-view mobile sweep remains follow-up
877884
- bottom tab navigation for mobile
878885
- touch-optimized capture modal
879886
- mobile board view (card list)

docs/MANUAL_TEST_CHECKLIST.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Use this checklist to manually validate current Taskdeck behavior on `main`.
44

5-
Last Updated: 2026-04-15
5+
Last Updated: 2026-04-23
66
Companion Active Docs:
77
- `docs/STATUS.md`
88
- `docs/IMPLEMENTATION_MASTERPLAN.md`

docs/STATUS.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Last Updated: 2026-04-23
44

5-
Post-merge sweep for PRs #936--#942.
5+
Post-merge sweep for PRs #936--#949.
66
<br>
77
Status Owner: Repository maintainers
88
Authoritative Scope: Current implementation, verified test execution, and active phase progress
@@ -174,6 +174,12 @@ Current constraints are mostly hardening and consistency:
174174
- **Test count recertification** (`#930`/`#940`): TESTING_GUIDE.md updated with verified counts — backend 4,979, frontend unit 2,607, combined 7,586+
175175
- **UserPreferences race fix** (`#931`/`#941`): replaced try-catch-retry (~105 lines) with atomic `INSERT OR IGNORE` SQLite upsert (~15 lines) in `UserPreferenceRepository`; 4 concurrency tests added
176176
- **Pre-existing CI fix** (`#942`): resolved 5 API Integration test failures — `Connectors:EncryptionKey` added to Production-mode test configuration; MCP telemetry test assertion index corrected
177+
- Mobile, security, legal, and testing expansion wave (2026-04-23, PRs `#944``#949`):
178+
- **FE-19 mobile-responsive board, toolbar, and dialog** (`#860`/`#944`): board view stacks columns vertically on ≤640px viewports with page-level scroll; `TdDialog` becomes full-bleed at ≤640px with `100dvh` height and stacked footer actions (cascades to all consumers: CardModal, BoardSettingsModal, LabelManager, StarterPackCatalog, KeyboardHelp); board toolbar and action rail enforce 44×44px tap targets on mobile; `ColumnLane` uses `--td-font-lg` token for 16px font-size to prevent iOS zoom; new `@mobile` Playwright test; WCAG 2.4.3 dialog footer tab-order fix; adversarial review addressed scoped slot CSS penetration and overflow-x interaction
179+
- **SEC-29 CSP style-src tightening (partial)** (`#855`/`#945`): removed `'unsafe-inline'` from `style-src` in API CSP entirely; added `style-src-elem 'self'` in reverse-proxy CSP to block inline `<style>` injection in modern browsers while preserving `style-src 'self' 'unsafe-inline'` fallback for Vue reactive `:style` bindings; new regression test `SecurityHeaders_CspStyleSrc_ShouldNotAllowUnsafeInline`; docs updated across `SECURITY_OWASP_BASELINE.md`, `CONFIGURATION_REFERENCE.md`, `AUDIT.md`, `HARDENING_AND_PERFORMANCE.md`; follow-up: migrate 27 files with `:style` bindings to CSS custom properties so `'unsafe-inline'` can be dropped entirely
180+
- **Legal document drafts** (`#548`/`#946`): `docs/legal/` with 5 pre-launch DRAFT documents — Privacy Policy (GDPR/CCPA-aligned, grounded in actual `DataExportService` payload), Terms of Service, Sub-Processors list (including conditional Sentry entry), Cookie Policy (with concrete `localStorage` key names and OAuth `.Taskdeck.ExternalAuth` cookie disclosure), and README with launch checklist; all marked `DRAFT — NOT LEGALLY BINDING` with `[LEGAL REVIEW REQUIRED]` on unverified claims; adversarial review corrected export scope claims, added missing localStorage entries, and flagged proposal/MFA credential retention gaps
181+
- **TST-59 visual regression expansion** (`#865`/`#948`): 15 additional Playwright visual regression specs bringing total from 5 to 20 components — auth views, TodayView, CalendarView, MetricsView, ReviewView, NotificationInboxView, SettingsView, CardModal, ColumnEditModal, board toolbar, capture/inbox views; clock pinning for calendar snapshots; timestamp masking for modal metadata; `document.fonts.ready` wait for font-load determinism; redundant `networkidle` waits removed; policy doc updated
182+
- **TST-60 E2E parallelization** (`#867`/`#949`): switched Playwright E2E from serial to parallel with `fullyParallel: true`; default 2 workers for both local and CI (overridable via `TASKDECK_E2E_WORKERS`); SQLite connection string uses `Pooling=True;Default Timeout=30` (dropped `Cache=Shared` per review — shared-cache mode increases contention); WIP-limit test fixed with idempotent `.check()` to prevent toggle oscillation under CPU contention; WAL mode documented as future follow-up
177183

178184
Target experience metrics for the capture direction:
179185
- capture action to saved artifact should feel under 10 seconds in normal use
@@ -277,7 +283,7 @@ Direction guardrails (explicit):
277283
- 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
278284
- 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
279285
- centralized JWT token storage abstraction (`utils/tokenStorage.ts`) with base64url + JSON payload validation, `isValidJwtStructure` guard, and `clearAll` helper; session-token storage ADR at `docs/analysis/session-token-storage-adr.md`
280-
- CSP hardening: removed `unsafe-inline` from `script-src` in security headers middleware; OWASP baseline doc updated
286+
- CSP hardening: removed `unsafe-inline` from `script-src` in security headers middleware; removed `unsafe-inline` from `style-src` in API CSP (SEC-29 partial); reverse-proxy CSP uses `style-src-elem 'self'` to block inline `<style>` injection in modern browsers; OWASP baseline doc updated
281287
- session timeout warning: `useSessionTimeout` composable with configurable warning-before-expiry, countdown timer, and extend/logout actions; `SessionTimeoutWarning.vue` wired into `App.vue`; backend `POST /api/auth/refresh` now implemented with rate limiting and token invalidation enforcement
282288
- performance instrumentation composable (`usePerformanceMark`) with `PERF_BUDGETS` constants; 7 latency thresholds documented in `docs/PERFORMANCE_BUDGETS.md`; 16 workspace route views converted to lazy `() => import()` for initial bundle reduction
283289
- WCAG 2.1 AA accessibility baseline: skip-to-content link, `sr-only` utility, `eslint-plugin-vuejs-accessibility` rules, ARIA landmarks and roles across HomeView/TodayView/ReviewView/InboxView/CaptureModal/ToastContainer/BoardView, and Playwright axe-core E2E regression for 6 core views

docs/TESTING_GUIDE.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,18 @@ dotnet test backend/Taskdeck.sln -c Release --filter "FullyQualifiedName~Oidc"
232232

233233
31 tests (11 domain + 20 integration) covering API key entity (`tdsk_` prefix, SHA-256 hashing), `ApiKeyMiddleware` Bearer validation, HTTP user context mapping, REST key management, and rate limiting per API key.
234234

235+
## E2E Parallelization (TST-60, `#867`/`#949`)
236+
237+
Playwright E2E suite runs in parallel (`fullyParallel: true`) with 2-worker default for both local and CI runs. Worker count is overridable via `TASKDECK_E2E_WORKERS` environment variable.
238+
239+
Per-test isolation is built into the data layer: `registerUserSession` provisions a unique user per test with `Date.now() + random` suffixes; board/column/card names follow the same pattern; data is scoped server-side by authenticated user.
240+
241+
SQLite connection string uses `Pooling=True;Default Timeout=30` for E2E runs. `Cache=Shared` was intentionally removed (increases contention vs default private-cache mode). WAL mode (`PRAGMA journal_mode=WAL`) is documented as future work for genuine concurrent-read throughput.
242+
243+
Key test patterns for parallel safety:
244+
- Use idempotent Playwright actions (`.check()` instead of `.click()`) when the dependent DOM element is `v-if`-gated on the control's reactive state
245+
- UI tests touching controls whose sibling DOM is conditionally gated should wait for the dependent element, not the control itself
246+
235247
## Platform Expansion Testing Capabilities (2026-04-09)
236248

237249
The platform expansion wave (PRs `#796``#805`) delivered four new testing capabilities:
@@ -264,9 +276,9 @@ npx playwright test --config playwright.visual.config.ts # Run visu
264276
npx playwright test --config playwright.visual.config.ts --update-snapshots # Update baselines
265277
```
266278

267-
7 visual tests: board (empty + populated), command palette (open + search), archive, inbox, home. Policy at `docs/testing/VISUAL_REGRESSION_POLICY.md`.
279+
20 visual tests (expanded from 7 in TST-59, `#865`/`#948`): board (empty + populated), command palette (open + search), archive, inbox, home, login, register, today, calendar (clock-pinned), metrics, review, notifications, settings, card modal (timestamp-masked), column edit modal (timestamp-masked), board toolbar, capture/inbox views. Clock pinning via `page.clock.install()` for date-dependent views; `document.fonts.ready` wait for font-load determinism; dynamic content hidden via `data-testid="timestamp"` + `hideDynamicContent` helper. Policy at `docs/testing/VISUAL_REGRESSION_POLICY.md`.
268280

269-
CI: `reusable-visual-regression.yml` in extended CI (testing/visual label). Uploads diff artifacts on failure.
281+
CI: `reusable-visual-regression.yml` in extended CI (testing/visual label). Uploads diff artifacts on failure. Baseline bootstrap: CI detects missing `__screenshots__/` directory, runs `--update-snapshots`, and uploads the `visual-regression-baselines` artifact for committing in a follow-up PR.
270282

271283
### Mutation Testing (TST-05, `#90`/`#796`)
272284

0 commit comments

Comments
 (0)