Skip to content

feat(hosted): close the hosted review hardening gaps from the #119 track#134

Merged
BunsDev merged 1 commit into
mainfrom
hosted-119-gaps
Jul 7, 2026
Merged

feat(hosted): close the hosted review hardening gaps from the #119 track#134
BunsDev merged 1 commit into
mainfrom
hosted-119-gaps

Conversation

@BunsDev

@BunsDev BunsDev commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

Context

Changes

  • core/hosted_review.rs: HostedReviewScope::validate() and CanonicalRepoIdentity::validate() reject empty/whitespace identity components; namespace-distinctness tests for two repos under one installation.
  • core/memdir.rs, core/session_storage.rs: hosted memory/transcript path derivation validates the scope before keying anything; delete_memory_file() writes a deleted_at tombstone instead of removing the file; tests prove the same repo at two paths maps to one hosted namespace, different repos at one path map to different namespaces, two repos under one installation cannot see each other's memory, and branch-domain content cannot leak into a default-branch load.
  • core/claudemd.rs: hosted loads floor the trust of entries missing source provenance (public effective_memory_trust); unattributed managed rules can no longer self-attest system_policy.
  • core/team_memory_sync.rs: TeamMemorySync::hosted() is fallible and validates the full scope; remote tombstones always apply, local tombstones are never resurrected, locally deleted files are not re-created (RemoteOnly now emitted and tested); keys with unresolved conflict records are blocked from pull (UnresolvedConflictPending) until resolve_conflict(); pending_conflicts() exposes the gate.
  • core/settings_sync.rs, core/git_utils.rs: verified_local_project_id() derives the project id from the origin remote and fails closed on missing/ambiguous remotes or mismatched claimed ids; collect_local_entries/apply_to_local verify caller-claimed project ids; collect_hosted_entries validates the scope.
  • query/session_memory.rs: durable persists carry provenance: session:<id>;source:<origin> next to the trust label (persist_with_provenance); candidate approval keeps its recorded provenance.
  • cli/headless.rs, cli/main.rs: ReviewResult gains a memory report (domains_loaded + per-entry id/trust/visibility/scope), collected from the same load options as the live context build and emitted in the v2 result envelope.
  • commands/lib.rs: /review now injects the loaded memory ids and trust labels into the review prompt and validates the returned review's citations (validate_review_memory_citations) — unknown ids and memory-dependent findings without memory_refs are surfaced as warnings in the output.
  • Contract artifacts: result.schema.json declares the optional review.memory object, result.example.json updated, docs/headless-contract.md §3.2 documents it; docs/advanced.md documents the new hosted invariants.

Validation

  • git diff --check — clean
  • cargo fmt --all — clean
  • cargo check --workspace — clean, no warnings
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • cargo test --workspace — all green (568 core, 102 commands, 101 query, 57+4+1 cli incl. ACP smoke, 653 tui, plus integration suites)
  • Targeted/manual checks: npx ajv-cli validate --spec=draft2020 -s result.schema.json -d result.example.jsonresult.example.json valid
  • Not run: release builds (not needed for this change)

PR Readiness

  • Diff is limited to the intended files.
  • Generated files were not edited by hand.
  • User-facing docs/help were updated (docs/advanced.md, docs/headless-contract.md).
  • No secrets, credentials, local paths, or unrelated logs are included (one gitleaks false positive on a fake mem_... test id, annotated inline).
  • Remaining risks or follow-up work are listed below.

Risks / follow-ups

  • review.memory is a new always-serialized property on the v2 result envelope. The schema copy in this repo declares it (optional, additionalProperties: false inner objects); the coven-github adapter's schema copy needs the same additive declaration before it strictly validates results produced by this build.
  • Team-memory sync conflict gating is enforced at the pull layer and inspectable via pending_conflicts(); there is still no live command path that drives team sync, so no UI surfaces the gate yet.

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>
Copilot AI review requested due to automatic review settings July 7, 2026 05:26
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview Jul 7, 2026 5:26am

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Closes the remaining hardening gaps for Hosted Review Mode by tightening hosted scope/project identity validation, improving memory provenance/trust handling, hardening team-memory sync deletion/conflict semantics, and enforcing/recording memory usage and citations in both /review and headless artifacts.

Changes:

  • Fail-closed hosted scoping: validate non-empty tenant/installation/repo/canonical identity before deriving hosted namespaces (memory + transcripts) and before hosted settings/team sync keying.
  • Memory hardening: persist durable memories with provenance attribution, floor trust for hosted loads missing provenance, and add tombstone-based deletion semantics (propagated through sync).
  • Review/audit surfaces: headless results now include a review.memory audit report; /review injects loaded memory IDs and validates returned review citations against what was loaded; schema + docs updated.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src-rust/crates/core/src/hosted_review.rs Adds validate() for hosted scope and canonical repo identity; extends tests for namespace distinctness.
src-rust/crates/core/src/memdir.rs Validates hosted scope before deriving hosted memory paths; adds tombstone-based delete_memory_file(); adds isolation/leak-prevention tests.
src-rust/crates/core/src/session_storage.rs Validates hosted scope before deriving hosted transcript paths.
src-rust/crates/core/src/claudemd.rs Floors trust for hosted loads when provenance is missing; ensures managed rules carry source.
src-rust/crates/core/src/team_memory_sync.rs Makes hosted constructor fallible + scope-validating; adds tombstone precedence and conflict gating on pull; exposes conflict inspection helpers.
src-rust/crates/core/src/git_utils.rs Adds fail-closed verified_local_project_id() derived from origin remote; includes tests.
src-rust/crates/core/src/settings_sync.rs Verifies claimed project id before applying/collecting project-scoped settings/memory; hosted collection validates scope and is now fallible.
src-rust/crates/query/src/session_memory.rs Adds persist_with_provenance() and routes approvals/hosted persistence through it; adds tests proving provenance persistence.
src-rust/crates/commands/src/lib.rs /review now lists loaded memory IDs/trust in-prompt and validates output citations (mem_...) against the loaded set.
src-rust/crates/cli/src/headless.rs Adds ReviewResult.memory report; collects loaded memory entries/domains; introduces build_result_with_memory().
src-rust/crates/cli/src/main.rs Switches to build_result_with_memory() and includes collected review memory in v2 envelope.
src-rust/crates/cli/tests/headless_contract/result.schema.json Extends schema with optional review.memory object (domains_loaded + entries).
src-rust/crates/cli/tests/headless_contract/result.example.json Updates example to include empty review.memory.
docs/headless-contract.md Documents review.memory fields and intent (audit + citation cross-check).
docs/advanced.md Documents additional hosted invariants (scope validation, trust flooring, tombstones, conflict gating, citation enforcement, memory reporting).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +3475 to +3480
block.push_str(&format!(
"- {} (trust: {}, from {})\n",
claurst_core::claudemd::memory_id(file),
trust,
file.path.display()
));
/// Extract `mem_...` citation tokens from free-form review text.
pub fn extract_memory_citations(text: &str) -> Vec<String> {
let mut cited: Vec<String> = Vec::new();
for token in text.split(|c: char| !(c.is_ascii_alphanumeric() || c == '_')) {
Comment on lines +511 to +514
let provenance_label = provenance
.filter(|p| !p.trim().is_empty())
.map(|p| format!(", provenance: {}", p))
.unwrap_or_default();
Comment on lines +669 to +672
fn conflict_record_path(team_dir: &Path, key: &str) -> PathBuf {
let safe_key = key.replace('/', "__");
team_dir.join(".conflicts").join(format!("{safe_key}.json"))
}
@BunsDev BunsDev merged commit 0491621 into main Jul 7, 2026
4 checks passed
@BunsDev

BunsDev commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Reviewed the full diff plus a security pass on the isolation boundaries. Two findings, both fixed in f1f259d:

  1. High — remote tombstone injection. apply_remote_entries wrote remote tombstone bodies verbatim, and tombstones bypass BothChanged conflict protection by design. A hostile write to the sync namespace could clobber local team memory with arbitrary content (reaching reviewer prompts in non-hosted loads, where format_memory_file_for_prompt only stubs redactions when hosted is true). Remote tombstones now persist a locally-synthesized canonical stub only; timestamps pass through only when they parse as plausible timestamps. Regression test: remote_tombstone_body_cannot_inject_content.

  2. Medium — review.memory audit fidelity. The report used load_all_memory_files_with_options while the live context uses the ContextBuilder ancestor walk — over-reporting managed/.coven-code entries that are never injected and under-reporting ancestor AGENTS.md files that are. It was also computed post-run. Both paths now share claudemd::enumerate_context_memory_files and the report snapshots before the run starts.

Remaining caveats for the issue track (not blockers):

Verified locally at f1f259d: fmt, cargo check --workspace, clippy --all-targets -D warnings, and the full workspace test suite all pass.

@BunsDev

BunsDev commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Note: this PR merged while the fixes were being verified, so f1f259d (pushed to the branch just after the squash) did not make the merge commit. The same change landed on main directly as 3dad66c, verified against the merged tree (fmt, clippy -D warnings, full workspace tests).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants