|
| 1 | +# Fail-Closed Review and Privacy Boundaries |
| 2 | + |
| 3 | +## Traceability |
| 4 | + |
| 5 | +- Spec ID: review-boundary-hardening-11-18 |
| 6 | +- Story: #11, #12, #13, #14, #15, #16, #17, #18 |
| 7 | +- Status: Implemented |
| 8 | + |
| 9 | +## Intent |
| 10 | + |
| 11 | +Make Better Harness honor its declared privacy controls and fail closed when |
| 12 | +review, filesystem, or report-integrity boundaries cannot be verified. The |
| 13 | +change fixes eight independently reproduced High findings without expanding |
| 14 | +the product surface or changing successful-path report semantics. |
| 15 | + |
| 16 | +## Acceptance Scenarios |
| 17 | + |
| 18 | +- AC-01 (#11): Secret Guard normalizes supported snake_case and camelCase tool |
| 19 | + payloads, scans secret-bearing Write/Edit/apply_patch content, blocks |
| 20 | + synthetic secrets without echoing them, and preserves existing Bash/path |
| 21 | + decisions. |
| 22 | +- AC-02 (#12): Workspace-scoped Qoder analysis excludes home-only sessions that |
| 23 | + have no verified relationship to the requested workspace across sessions, |
| 24 | + events/show, facets, insights, file-reads, and usage-summary. A matching |
| 25 | + record cannot authorize foreign-cwd records from the same home session, and |
| 26 | + cwd-less records require a workspace-linked session source instead of being |
| 27 | + assigned to the requested workspace. An explicit global-capability pass can |
| 28 | + retain home-only sessions only as `user-global` evidence. |
| 29 | +- AC-03 (#13): `report --no-sessions` executes no session probe and always uses |
| 30 | + the static `software-fluency` route even when local sessions exist. |
| 31 | +- AC-04 (#14): Blast-radius collection distinguishes an invalid/unavailable |
| 32 | + base ref from a real empty diff and returns an explicit fail-closed error. |
| 33 | +- AC-05 (#15): review-trigger argument, Git worktree probes, and runtime |
| 34 | + failures exit non-zero while successful findings retain their documented |
| 35 | + non-blocking result. |
| 36 | +- AC-06 (#16): `report --cwd` rejects empty, missing, and non-directory targets |
| 37 | + before starting evidence collectors; valid-directory fallback behavior |
| 38 | + remains available. |
| 39 | +- AC-07 (#17): findings repair never lowers `Critical` or arbitrary unknown |
| 40 | + severity to `Medium`; unsupported values fail closed or use an explicit |
| 41 | + conservative mapping. |
| 42 | +- AC-08 (#18): Git-backed cloc never follows a tracked path to a target outside |
| 43 | + the repository, reads a non-regular file, or reads a regular file beyond the |
| 44 | + configured size boundary; skipped results remain bounded and do not reveal |
| 45 | + the external target. |
| 46 | +- AC-09: Focused tests, the full Node test suite, package verification, syntax |
| 47 | + checks, and review-readiness checks pass on Linux-compatible local tooling; |
| 48 | + cross-platform path behavior remains covered by portable fixtures. |
| 49 | + |
| 50 | +## Non-goals |
| 51 | + |
| 52 | +- Do not redesign report scoring, add a new severity level to the public |
| 53 | + findings schema, or alter valid High/Medium/Low findings. |
| 54 | +- Do not add authentication or network sharing to Canvas preview. |
| 55 | +- Do not change the Medium large-untracked-file finding or architecture |
| 56 | + watchlist items from the originating review. |
| 57 | +- Do not add dependencies. |
| 58 | +- Do not refactor unrelated session, report, or Git-analysis behavior. |
| 59 | + |
| 60 | +## Plan and Tasks |
| 61 | + |
| 62 | +1. Add failing regression tests for each issue before changing implementation. |
| 63 | +2. Normalize Secret Guard tool events once, then scan only the content fields |
| 64 | + owned by matched write tools. |
| 65 | +3. Apply workspace ownership at both Qoder home-session discovery and per-event |
| 66 | + hydration, keeping explicit `user-global` behavior separate. |
| 67 | +4. Make quickstart privacy and empty/missing cwd validation explicit at its CLI |
| 68 | + boundary. |
| 69 | +5. Replace Git diff ambiguity with a structured failure from blast-radius |
| 70 | + collection. |
| 71 | +6. Separate review-trigger argument, Git-probe, and execution failures from |
| 72 | + successful non-blocking findings. |
| 73 | +7. Make severity repair conservative and make cloc file reads type-, size-, |
| 74 | + and containment-aware. |
| 75 | +8. Run focused tests per module, then the complete repository checks. |
| 76 | +9. Perform independent code-review and architecture lanes, address all |
| 77 | + Critical/High findings and any architectural Block, then run Review |
| 78 | + Readiness before commit and PR. |
| 79 | + |
| 80 | +Decision rationale: |
| 81 | + |
| 82 | +- Fail closed only when the tool cannot establish the requested boundary; |
| 83 | + preserve supported fallback behavior for valid inputs with partial evidence. |
| 84 | +- Prefer small checks at existing owner boundaries over new shared abstraction |
| 85 | + layers. |
| 86 | +- Use synthetic credentials and temporary repositories only; tests must not |
| 87 | + retain private prompts, paths, or secrets. |
| 88 | + |
| 89 | +## Test and Review Evidence |
| 90 | + |
| 91 | +- AC-01: |
| 92 | + `node --test test/agent-guardrails-secret-scan.test.mjs` |
| 93 | +- AC-02: |
| 94 | + `node --test test/session-analysis.test.mjs test/session-usage-summary.test.mjs` |
| 95 | + including mixed-cwd, cwd-less, and explicit user-global home-session cases |
| 96 | +- AC-03 and AC-06: |
| 97 | + `node --test test/harness-quickstart.test.mjs test/better-harness-cli.test.mjs` |
| 98 | +- AC-04: |
| 99 | + `node --test test/blast-radius.test.mjs` |
| 100 | +- AC-05: |
| 101 | + `node --test test/review-trigger.test.mjs`, including a non-Git directory |
| 102 | +- AC-07: |
| 103 | + `node --test test/harness-findings-repair.test.mjs test/harness-report-render-cli.test.mjs` |
| 104 | +- AC-08: |
| 105 | + `node --test test/cloc.test.mjs`, including an oversized regular file |
| 106 | +- AC-09: |
| 107 | + `npm test` |
| 108 | + `npm run pack:verify` |
| 109 | + `node --test test/doc-link-graph.test.mjs` |
| 110 | + |
| 111 | +Review evidence: |
| 112 | + |
| 113 | +- Review follow-up (2026-07-29): mixed-cwd and cwd-less home-session hydration, |
| 114 | + explicit user-global analysis, failed Git worktree probes, empty `--cwd=`, |
| 115 | + and bounded cloc reads are covered by regressions and resolved before merge. |
| 116 | +- `npm run check` passed with the full Node suite and package verification. |
| 117 | +- The review follow-up focused run passed 80 tests across Qoder session |
| 118 | + analysis, session usage summary, review-trigger, quickstart, and cloc; |
| 119 | + syntax and diff checks also passed. |
| 120 | +- Code-reviewer recommendation: `APPROVE` after both reported High findings |
| 121 | + were fixed and re-reviewed. |
| 122 | +- Architect status: non-blocking `WATCH`; the previous fail-open `BLOCK` was |
| 123 | + resolved. The remaining watch is limited to the concurrent swap-to-symlink |
| 124 | + race on platforms where `O_NOFOLLOW` is unavailable. |
| 125 | +- The final diff must contain no generated runtime state, credentials, or |
| 126 | + unrelated source changes. |
| 127 | + |
| 128 | +Risk notes: |
| 129 | + |
| 130 | +- Qoder home-session filtering can reduce previously over-broad results; tests |
| 131 | + must prove verified workspace sessions remain visible. |
| 132 | +- Hook exit-code changes can expose previously hidden configuration errors; |
| 133 | + success-path non-blocking tests guard the intended contract. |
| 134 | +- Symlink policy differs by platform; fixtures must avoid requiring privileged |
| 135 | + symlink creation where the platform does not support it. |
0 commit comments