Repository navigation
Ingress: separate the causal identity recipe from plain intents (#885) - #900
Conversation
Under the original recipes a plain intent hashed "ingress:" || kind || bytes and a causal intent "ingress:causal:v2\0" || kind || ...: the causal domain begins with the plain one and the kind is any 32 bytes, so a plain intent can reproduce a causal intent's hash input exactly (an encoding alias) and take its ingress and submission IDs. Envelopes now record an IngressIdentityVersion. New causal intents use the separated recipe "echo.ingress.causal.v3\0" with length prefixes and one-byte parent tags, and are retained as EINGR004. EINGR001-EINGR003 keep their bytes and identity exactly and decode as Original, plain intents included. Transition: a resend of a causal request accepted under the original recipe resolves to that submission, and staging uses its retained envelope, but only when the retained envelope states the same kind, bytes, parents, occurrence and head; an alias neither counts nor reserves the request. Missing legacy material obstructs (OriginalIngressIdentityUnverifiable), both identities of one request are IngressIdentityAmbiguous, and new admission in the original causal recipe is OriginalCausalIdentityNotAdmissible. Occurrence retries and strand inheritance use the same comparison. Witnesses include a frozen WAL written by main at 0512e9d (restart, then resend) and a direct alias construction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tity-v3 # Conflicts: # crates/warp-core/src/coordinator.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 36 minutes. View limit details
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 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3999193b74
ℹ️ 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".
…d names Review of #900: - An ingress id shared by two different requests (an alias under the original causal recipe) could be treated as a retry, or ingest could overwrite the retained request under the same submission. Both admission paths now refuse with RuntimeError::IngressIdentityAlias when the retained envelope states a different request, after the occurrence binding check so occurrence conflicts keep their own error. - When a separated-form resend resolved to a submission accepted under the original recipe that the WAL had not recorded, the host persisted the caller's envelope under the original submission id, and recovery then failed. It now persists the retained envelope that matches the handle. Witnesses a_retained_alias_is_refused_and_never_overwritten and a_legacy_resolved_resend_records_the_retained_envelope each fail without their fix and pass now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bb81443dee
ℹ️ 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".
| let Some(original) = envelope.original_identity_form() else { | ||
| return Ok(None); |
There was a problem hiding this comment.
Reject exact legacy envelopes when retention is missing
When record-only replay has restored an original-recipe causal submission without its envelope, an exact EINGR002 delivery—or the plain alias sharing its ID—takes this None branch because original_identity_form() only handles separated envelopes. refuse_retained_alias also permits the missing envelope, so ingest can accept the caller-supplied material and install it under the historical submission ID. Return OriginalIngressIdentityUnverifiable for this exact-identity path before duplicate or staging logic can manufacture retained history.
AGENTS.md reference: AGENTS.md:L13-L18
Useful? React with 👍 / 👎.
| out.extend_from_slice(if separated { | ||
| RETAINED_INGRESS_ENVELOPE_MAGIC_V4 | ||
| } else if self.occurrence.is_some() { | ||
| RETAINED_INGRESS_ENVELOPE_MAGIC_V3 |
There was a problem hiding this comment.
Correct the canonical retention-format documentation
This branch writes every newly constructed causal envelope, including one with a Continuum occurrence, as EINGR004, but the canonical spec still says occurrence envelopes use EINGR003 and envelopes without one use EINGR002 (docs/spec/canonical-inbox-sequencing.md:87-90), and docs/topics/WAL.md:109-112 repeats the EINGR003 claim. The public to_retained_bytes rustdoc at lines 546-555 is stale as well. Update these current-state claims to distinguish Original from SeparatedCausal, otherwise readers implementing or diagnosing WAL retention from the canonical owners are given the wrong wire format.
AGENTS.md reference: AGENTS.md:L146-L156
Useful? React with 👍 / 👎.
Closes #885. Implements the owner rulings recorded on the issue: Option A, the transition rules, and the ownership split.
Stacked on #890 (base
feat/strand-inherits-occurrences). The compatibility rule also governs #890's inherited-occurrence check. Retarget tomainonce #890 merges.The defect: an encoding alias, not a hash collision
The original recipes hash a plain intent as
"ingress:" || kind || bytesand a causal intent as"ingress:causal:v2\0" || kind || len || bytes || count || parents. The causal domain begins with the plain one, and a kind is any 32 bytes, so a plain intent can reproduce a causal intent's hash input byte for byte. The construction is direct and needs one envelope, with no search.a_plain_intent_aliases_the_original_causal_recipe_but_not_the_separated_onebuilds it.What changes
IngressIdentityVersion. New causal intents useSeparatedCausal:"echo.ingress.causal.v3\0" || kind || len || bytes || count || (tag || receipt_ref)*, with one-byte role tags and fixed-length refs. Plain intents are unchanged.EINGR004(theEINGR002layout plus an occurrence flag). TheEINGR001–EINGR003retention formats keep their bytes and identity interpretation exactly, and decode toOriginal, plain intents included.OriginalCausalIdentityNotAdmissible. Retained records are never rejected for that reason; historical decoding and new admission policy stay separate.Duplicatewith its original ingress id) and is staged with its retained envelope.OriginalIngressIdentityUnverifiable.IngressIdentityAmbiguous.EINGR004and the lookup are Echo-local. Nothing here is normative for Continuum.Witnesses (guarded worker)
main@0512e9d2(tests/fixtures/legacy_causal_wal, SHA-256 checked): resends resolve to the original submissions; no acceptance is written; the decided request does not run again; the pending one is staged from its retained envelope and decided once; a changed parent is a new actFull chain on the merged tree: featured 1878, default 1395 and workspace 981 tests pass. All six clippy configurations, fmt, rustdoc and the docs-model checks are clean.
Documentation
docs/spec/canonical-inbox-sequencing.mdDecision 7 (Decision 1 marked refined), CHANGELOG, and the fixture README.Local identity hardening only; not replica-scale conformance.
🤖 Generated with Claude Code