Fix causal anchor schema validation#643
Conversation
|
Warning Review limit reached
Next review available in: 12 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@codex review please Code Lawyer resolution summary:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: debc7b5c07
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if retained_roots.is_empty() { | ||
| return Err(CausalAnchorError::EmptyRetainedRoots); |
There was a problem hiding this comment.
Require an authority/evidence retained root
retained_roots.is_empty() only rejects an empty vector, so a request whose retained set contains only CasObject { role: Materialization } or a GraphFact index is admitted and digested as a recovery anchor. That violates the stated invariant in this type (EmptyRetainedRoots says the anchor must retain at least one authority or evidence root) and lets projection/cache artifacts become the sole durable basis; validate the canonical retained set's roles before computing the digest.
Useful? React with 👍 / 👎.
| let anchor_digest = compute_anchor_digest( | ||
| request.schema_version, |
There was a problem hiding this comment.
Reject unsupported causal anchor schema versions
request.schema_version is passed straight into the digest and then stored on the fact, so a caller can mint schema 0 or 2 anchors using the v1 struct and v1 digest domain. If schema changes later, old code will already have admitted facts claiming that future schema without applying its validation or canonicalization rules; compare this field with CAUSAL_ANCHOR_SCHEMA_VERSION and return a validation error for unsupported versions.
Useful? React with 👍 / 👎.
| if retained_roots | ||
| .iter() | ||
| .any(|root| materialization_roots.binary_search(root).is_ok()) |
There was a problem hiding this comment.
Compare cross-set root identities without roles
This binary_search compares the full CausalAnchorRoot, including its role, so the same underlying root can still be admitted in both sets if the role differs, e.g. a retained GraphFact { id, role: Evidence } and a materialization GraphFact { id, role: Index }. That violates the new disjointness rule documented for retained/materialization roots and allows one root id to be treated as both retained evidence and projection material; compare by root kind and id rather than the entire role-bearing value.
Useful? React with 👍 / 👎.
| let retained_roots = | ||
| canonicalize_roots(request.retained_roots, CausalAnchorRootSet::Retained)?; |
There was a problem hiding this comment.
Validate application root identity fields
Only the top-level anchor subject is checked for empty strings before roots are canonicalized and digested, so an AppSubjectRoot with an empty app_id, subject_kind, or id is accepted as retained authority/evidence. In that scenario the anchor can claim to retain an application root that cannot be scoped or resolved by the appId/subjectKind/id contract shape, so root identity fields need the same non-empty validation as the anchor subject.
Useful? React with 👍 / 👎.
Summary
This resolves the Code Lawyer follow-up findings for Echo causal anchors.
schema_versionto causal anchor requests and facts so the Rust value contract matches the documented shape.Validation
cargo fmt --all -- --check./scripts/check_spdx.shcargo test -p warp-core --test causal_anchor_testscargo test -p warp-core --libpnpm exec markdownlint-cli2 docs/topics/CausalAnchors.md docs/README.mdgit diff --checkLocal result: causal anchor tests 9 passed; warp-core lib tests 565 passed; markdownlint 0 errors.