[codex] Upstream hosted review dogfood stack#132
Conversation
Fixes OpenCoven#97. Fixes OpenCoven#100. - gate hosted review memory scopes behind trusted policy settings - default hosted review tools/MCP/plugins to restricted surfaces - document Phase 1 behavior and add PR-ready test notes Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Fixes OpenCoven#98. Fixes OpenCoven#99. Fixes OpenCoven#104. Fixes OpenCoven#110. - add hosted tenant/installation/repo/domain scope types - key hosted memory, transcripts, settings sync, and team memory by scoped identity - add canonical repo parsing and Windows test isolation for home-derived paths Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…enCoven#99 OpenCoven#104 OpenCoven#110) Refs OpenCoven#98. Refs OpenCoven#99. Refs OpenCoven#104. Refs OpenCoven#110. - keep hosted identity/scoping tests portable on Windows - preserve Phase 2 full-suite test coverage Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
OpenCoven#108) Fixes OpenCoven#101. Fixes OpenCoven#107. Fixes OpenCoven#108. - gate hosted durable memory writes by source trust - add hosted memory candidate approval flow - keep local memory extraction behavior unchanged Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…#106 OpenCoven#112) Fixes OpenCoven#105. Fixes OpenCoven#106. Fixes OpenCoven#112. - enforce hosted memory frontmatter scope and trust - preserve provenance metadata in hosted memory context - require structured review output to cite memory refs Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
OpenCoven#109 OpenCoven#111) Fixes OpenCoven#102. Fixes OpenCoven#103. Fixes OpenCoven#109. Fixes OpenCoven#111. - enforce secret scanning before hosted memory writes and sync - key hosted team-memory sync by structured tenant/repo scope - replace server-wins pull with conflict handling - add retention, deletion, and redaction controls Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-2 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-3 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-4 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-5 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech> # Conflicts: # src-rust/crates/core/src/claudemd.rs # src-rust/crates/tui/src/image_paste.rs
…hase-2 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech> # Conflicts: # src-rust/crates/commands/src/lib.rs # src-rust/crates/tui/src/app.rs
…hase-3 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-4 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-5 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-2 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-3 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-4 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
…hase-5 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
|
While re-checking the hosted persistence paths, I found one more path-shaped input that should be constrained in this PR. |
Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
|
Follow-up: fixed in
GitHub Actions Rust CI and TUI Tests are also passing on |
BunsDev
left a comment
There was a problem hiding this comment.
The architecture here is sound — tenant/install/repo/domain scoping, candidate gating, conflict-aware sync, and the CI/docs are solid. But two High issues undermine the security model this PR exists to provide, and two more break the locked contract. Requesting changes.
High
1. safe_component passes .. through, defeating the traversal defense for scope components
src-rust/crates/core/src/hosted_review.rs:366 — safe_component keeps ., so "." and ".." pass unchanged. tenant_id, installation_id, and repo_id are external control-plane inputs joined bare into hosted_memory_path(), transcript_dir_for_mode(), and delete_hosted_memory_for_scope() — the last one calls remove_dir_all, so tenant_id = ".." recursively deletes outside the tenant namespace. The mapping is also non-injective: tenants a/b and a_b both sanitize to a_b and collide, which is exactly the cross-tenant leakage this PR targets. This PR's own validate_session_id_component (session_storage.rs:294) rejects ./.. — scope fields need the same check, or hash the raw IDs like local_project_id_from_identity does.
2. Hosted trust gate is self-attested by the file it gates
src-rust/crates/core/src/claudemd.rs — memory_file_allowed_for_options decides admission from the memory file's own frontmatter trust:. In the hosted PR-review threat model, project AGENTS.md comes from the PR checkout and is attacker-writable: a fork PR adds trust: maintainer_approved (or system_policy) and sails through the threshold, injecting instructions into the reviewer's system prompt. Same for visibility, expires_at, deleted_at. Trust must be assigned by the loader from provenance (which ref/directory the file came from); at minimum, cap self-declared trust of review-checkout files at contributor_input/fork_input.
3. Compliant review-only address_review_comment runs are classified as failure (exit 1)
src-rust/crates/cli/src/headless.rs — every AddressReviewComment brief is now review-mode and its prompt says "Do not modify files … unless the review comment explicitly asks for code changes", but is_comment_only() still only covers RespondToMention, and classify(Completed, has_commits=false, comment_only=false) returns (Failure, AmbiguousSpec, 1). A model that follows the new prompt exactly is reported to the adapter as a non-retryable failure. classify should treat review-mode runs as comment-only.
4. v2 contract schemas reject the runtime's own I/O
session-brief.schema.jsononly had itsconstbumped to"2"; it keepsadditionalProperties: falseand defines neitherreview_contextnoraudit_instruction, so a validating adapter can never emit a brief that triggers review mode (verified with ajv againstsample_review_brief()).result.schema.json's reviewoneOfrequiresfindings(minItems 1) or a non-nullno_findings_reason, but the degraded-review path deliberately emitsfindings: [] + no_findings_reason: null— asserted by this PR's own tests (review_context_produces_structured_pr_review_evidence,generic_review_output_is_marked_partial). An envelope with both findings and a reason also failsoneOfsince both branches match. Verified with ajv.
Medium
5. Review-only enforcement is split across two signals
The 40-turn cap keys off the brief's review_context, but the write/exec tool filter and MCP/plugin lockdown key only off --hosted-review / COVEN_CODE_HOSTED_REVIEW (main.rs:1528-1580, filter_tools_for_hosted_review). The documented contract invocation has no flag, so a brief-driven review session runs with the full toolset and PermissionMode::BypassPermissions — the only "no writes" enforcement is a prompt sentence. Brief review-mode should imply at least the read-only tool filter.
6. Supporting-evidence trace counts failed reads and grep match text
headless.rs — Read paths are recorded at ToolStart and never revisited on failure; normalize_path only rejects paths that exist and are not files, so a Read of a nonexistent path counts as evidence and can flip evidence_status to Complete without any file being read. record_tool_end also mints supporting_files from any grep output line whose prefix contains a dot before a colon, including matched source text. Record Reads at ToolEnd on success (or require is_file()), and restrict grep parsing to the filename-prefix format.
7. Legitimate short no-findings justifications rejected as generic
parse_no_findings_reason drops any justification under 120 chars containing "no findings"/"no issues found" — phrases the prompt itself elicits. A concise file-backed justification gets nulled, has_substantive_review flips false, and a compliant clean review is downgraded to Partial. The file-reference requirement already guards substance; drop the generic-needle check for this section.
8. Memory body unescaped inside <memory> wrapper — trust-label forgery
claudemd.rs format_memory_file_for_prompt escapes attributes but injects the body verbatim, so a body containing </memory><memory trust="system-policy" …> forges a trusted block. The hosted-vs-local wrapper choice in build_system_prompt is also a contains("<memory id=") substring probe; derive it from MemoryLoadOptions.mode instead.
Coordination
The headless contract is bumped v1 -> v2 and declared locked/normative in this repo, so coven-github needs matching v2 support before merge — and fixing item 4 will touch the schemas again, so worth landing those together.
CI workflow itself looks good: --locked builds, minimal permissions, cache, 45-minute timeout.
…-quality-enforcement Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
Addresses BunsDev requested changes on PR OpenCoven#132 for hosted review path safety, memory trust provenance, review-only classification, evidence tracing, schema acceptance, and hosted review prompt wrappers. Refs OpenCoven#119 Refs PR OpenCoven#132 Signed-off-by: Timothy Wayne Gregg <Timothy.Gregg@complete.tech>
|
BunsDev requested changes have been addressed in Resolved items:
Verification on PR #132 head
Remaining non-code status: Vercel still requires external authorization. Ready for re-review. |
BunsDev
left a comment
There was a problem hiding this comment.
Verified all 8 items from my previous review at 8b62b4a, plus a full local run of cargo fmt --all -- --check, cargo check --workspace, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace — all pass.
High
- Fixed.
safe_componentnow injectively encodes non-[A-Za-z0-9_-]bytes (.->~2E,/->~2F, empty ->~) athosted_review.rs:374-391;..,., empty, and thea/bvsa_bcollision are all covered by tests, and every hosted path join (memdir, transcripts, delete) goes through it. - Fixed. Hosted mode caps self-declared trust of project/local/user files at
ContributorInput(claudemd.rs:387-399), below theMaintainerApprovedthreshold; frontmatter can now only further exclude, never elevate. Tests cover the fork-PR self-attestation case. - Fixed.
AddressReviewCommentmaps toReviewMode::ReviewCommentandis_comment_onlycovers all review modes;classify(Completed, false, true)returns exit 0 with a regression test. - Fixed.
session-brief.schema.jsondefinesreview_context/audit_instructionmatching the Rust structs;result.schema.jsondropped the brokenoneOf. Re-validated the checked-in examples and the degradedfindings: [] + no_findings_reason: nullcase with ajv (2020 spec) — all pass.
Medium
5–8 fixed as described in the PR comments. One residual on item 6: single-file grep output has no filename prefix, so matched source text shaped like foo.rs: ... can still mint a supporting-file entry — but normalize_path now requires an existing regular file inside the workspace, so the worst case is over-attributing a real file, not fabricating evidence. Fine as a follow-up.
Coordination
coven-github #31 (v2 contract) is merged, so the cross-repo blocker is cleared.
Issue closure scope
Cross-checked #97–#112 against the diff. This PR fully closes #97, #100, #101, #102, #105, #108. The rest land substantial groundwork but each has a remaining gap (mostly missing acceptance-criteria tests or unwired pieces, e.g. #112's memory-ref validator not called in the live /review path); I'll leave those open with scoping comments rather than close them on this merge. #119 stays open as the tracker.
Approving. Will squash-merge with the closes list above.
…ack (#134) Scope validation, provenance, sync lifecycle, conflict gating, and citation enforcement follow-ups to the hosted review stack landed in PR #132. - Validate hosted scope components everywhere a hosted namespace is derived (memory paths, transcripts, team sync, settings sync); empty components fail closed instead of collapsing tenant/repo isolation. - Verify caller-claimed local project ids against the identity derived from the origin remote; a missing or unparseable remote fails closed. - Persist source/session provenance on durable auto-extracted memories and floor hosted trust for entries that carry no provenance. - Report loaded memory domains and per-entry trust/visibility/scope in ReviewResult and the v2 result envelope (schema, example, and docs). - Propagate deletion/redaction tombstones through team-memory sync; never resurrect locally deleted or tombstoned files on pull. - Block keys with unresolved pull conflicts from sync until the persisted conflict record is resolved; exercise the RemoteOnly path. - Inject loaded memory ids into the live /review prompt and validate the returned citations against the loaded set. closes #98 closes #99 closes #103 closes #104 closes #106 closes #107 closes #109 closes #110 closes #111 closes #112 closes #119 Co-authored-by: Timothy Wayne Gregg <5861166+romgenie@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Issue tags
Refs #119
Related to #97, #98, #99, #100, #101, #102, #103, #104, #105, #106, #107, #108, #109, #110, #111, #112
Context
Changes
Validation
Record exact commands and outcomes. Mark items N/A with a reason when they do not apply.
git diff --check- passed locally; only Windows line-ending warnings were reported.cargo fmt --all- passed locally.cargo check --workspace- passed locally.cargo clippy --workspace --all-targets -- -D warnings- passed locally.cargo test --workspace- covered locally withcargo test --workspace -- --test-threads=1; passed. Serial execution was used because the TUI OSC8 tests are order-sensitive under parallel Windows execution.cargo test -p claurst-query candidate_store_rejects_traversal_candidate_idspassed;cargo test -p claurst-core transcript_paths_reject_traversal_session_idspassed; GitHub ActionsRust CIpassed ona94c1b7; GitHub ActionsTUI Testspassed ona94c1b7.PR Readiness
Remaining external blocker: the only failing status is Vercel authorization required for team
0xBuns; Rust CI and TUI checks are passing.