# EventId-correlated peer invitations — inactive source candidate This document supersedes the older replay document only for the proposed paired implementation. R2's legacy suppression writer and its regression source remain unchanged. This is not a protocol/security approval, migration authorization or runtime qualification. ## Implemented source contract - Protected wire types are `peer-request-event-v1` and `peer-decision-event-v1`. They deliberately do not reuse legacy discriminants: an older reader must not act on a new request while ignoring correlation fields. Legacy parsing remains available for explicit refusal; legacy sender APIs refuse with `C01_MIGRATION_REQUIRED`. - A protected request carries `{request:{from_did,version,name,message}}`. A decision carries the entire original signed request Event as `original_request` and a tagged `decision` (`accept` with invite_code, `reject`/`cancel` with optional reason). The reference is that verified original EventId, not the decision's ID, arrival timestamp, or local UUID. These exact schema bytes are a review proposal, not coordinator-approved wire bytes. - Original proof verification checks signature/EventId, encrypted-DM kind, exactly one recipient, signer/requester, local endpoint, actual decrypted protected request, and decision actor/direction. Reject/accept run recipient-to-requester; cancel runs requester-to-recipient. No custom cryptography; proof and correlation metadata remain inside existing encrypted envelopes. - `operation_id` is a stable UUID provided by the client before RPC; `new_request` explicitly binds intent. Persist the full immutable command and exact signed event in the same atomic JSON document as the visible row BEFORE publish. Repeating an operation with changed recipient/payload/intent refuses. Retrying an identical still-live operation re-fsyncs and returns the same event bytes, not fresh encryption. A terminalized command returns an explicit terminal error rather than publishing again. - C1 keeps distinct generations as separate UUID rows. Grouping by peer must not collapse protocol identity. Delayed A decisions locate only A, never the current row for the same peer B. - Local terminal state and encrypted signed decision outbox commit together. Notification opt-out persists and excludes background delivery. Replies retry the exact signed envelope. Incoming approval claims the exact generation durably before `restrict_discovery_invite` / `accept_invite` / mesh effects. A partial/uncertain acceptance is visibly marked recovery-required; it is NOT automatically reexecuted, because the existing membership routine can replace nodes and append invite records. Cross-store acceptance reconciliation is an explicit remaining engineering exit. - Early cancellation admits only a verified original request proof in the existing signed admission horizon. Its generation consumes a reserved slot without creating a visible pending row; subsequent arrival is suppressed. Known terminal updates do not require a new slot. Protected generations are not pruned or evicted in this candidate, preventing cancellation revival from speculative GC. ## Explicit activation and migration boundary `require_activation()` unconditionally returns `C01_POLICY_PENDING`; there is no environment/file switch, test bypass, or hidden production default. Connect/poll/approve/reject/cancel/retry/publication entrypoints are gated. Discovery and existing mesh/federation connectivity are not disabled. List-pending exposes migration/policy and acceptance-recovery status; mutation RPC errors are explicit. Frontend and shared dispatch/session/RBAC/CSRF sources are untouched. This is not a claim that an unmodified old remote UI can render a new refusal. M1 requires coordinated upgraded clients/peers, a durable migration/rollback boundary, and visible frontend rendering before activation. Current frontend lacks stable operation-ID submission and the new status renderer. New discriminants prevent legacy action, but alone do not implement capability negotiation or remote error presentation. No ambiguous legacy decision is sent as a compatibility fallback. ## Current adopted policy and incomplete implementation The coordinator's `C01-D4-COORDINATOR-ADOPTION.md` now adopts the exact recommendations in `c01-d4-security-disposition-v1/DISPOSITION.md` only with mandatory D4-C1 through D4-C5. Older statements that numeric quotas, L1/L2 or retry policy await selection are superseded. This recovery does not implement those requirements merely by documenting them, and cannot be activated. The source still reuses the old wall-clock admission check and ledger count ceilings. That is not the adopted clock/fence authority or the required independent known/unknown/byte/resource-reservation accounting. There is no protected GC, authenticated nonrenewable command deadline, qualified clock/rollback recovery, encrypted bounded snapshot/control store, aggregate pre-parse receive adapter, launcher downgrade fence, fair globally paced retry scheduler, or final-effect L2 revalidation. Existing `claim_replies` has no original-request cutoff; approval retry still uses receipt age. None of those behaviors is approved by the fail-closed activation gate. Exact adopted parameters are bound by the coordinator adoption and disposition rather than duplicated as incomplete runtime defaults here. The original request horizon is L2 inclusive `[c,c+2592000]`, future allowance zero; retention is through `H+300`. Same logical validated time and atomic nondecreasing watermark, non-ratcheting monotonic trajectory, final-effect expiry and unresolved-effect retention are mandatory. Unknown early cancel is independent of known generations. Resource-holding terminal outboxes retain their allocated slots. Commands cannot become new operations after GC. Transport limits are aggregate across relays and must precede allocation. Serialized snapshot/control ceilings and launcher-enforced downgrade refusal require concrete storage/transport/platform integration, not just constant declarations. ## Migration consumer recovery Recovery consumes lane44's fixed consumer contract. `MIGRATION_REQUIRED` and `POLICY_PENDING` now use the existing `Not supported` sanitizer prefix, ASCII text under its 200-byte truncation limit, and no known frontend transport-retry trigger words. This corrects synchronous error preservation without changing dispatch, auth/CSRF or frontend files. A Rust test targets the actual sanitizer, but is UNRUN. The offline RED/GREEN source-contract check is not Rust execution, mounted UI evidence, durable background refusal or actual old-peer interoperability. Lane44's remaining application-error retry classifier, map pre-ack animation, operation-ID submission, status projection/readback and refresh ownership still require the frontend owner. Do not parse poll `skipped` as public migration messages or infer remote approval from relay delivery. Existing notification defaults and unrelated connectivity remain unchanged. ## Evidence and test transition Rust regression sources cover signed endpoint/proof rejection, delayed accept/reject/cancel A versus B, prepared-before-publish reload and exact retry, conflicting commands, early cancellation, first terminal wins, uncertainty after acceptance claim, capacity, no-notify and legacy/policy refusal. They have NOT been compiled or executed. Store reload / simulated lost completion are not process-death, power-loss or fsync fault-injection tests. The two historical RPC transport tests and the historical legacy replay RPC test asserted legacy emission/automatic acceptance that M1 now prohibits. Their original bytes are retained in the packet baseline. Current sources assert visible refusal/no mutation; signed positive store/wire tests cover the new primitives. Positive managed-relay send/ack/timeout, peer-invite DID/trust integration and real RPC replay/crash tests must be ported and run after selected policy/activation admission. The unrelated metrics test and all R2 tests are unchanged. This transition does not inherit or replace the old transport qualification. Independent exact protocol/storage/security review, native isolated tests, actual crash/reordering/mixed-version migration, packaged/multi-node/operator qualification remain required. Do not integrate this inactive candidate as finished C01. ## Lane55 bounded D4 schema/caller successor (not activated) The command operation key is now a **canonical UUIDv7**, not an arbitrary UUID. Its embedded Unix milliseconds, floored to integer seconds, are the immutable origin `c`. No retry parameter or current receipt time can replace that origin. `H=c+2592000` and `H+300` use checked arithmetic. The authenticated local connect RPC signs the request with `created_at=c`; encrypted `RequestCommandBinding` contains the exact operation key, explicit-new intent and `c` alongside the immutable request payload. Recipient remains the signed envelope recipient. No private command metadata is added to public Nostr tags. The original signed request **EventId**, never this UUID or a timestamp, remains decision identity. Absent commands require `new_request=true`; identical retry resubmits that same immutable command, including its original true intent. Changed fields conflict. The key's original horizon is checked before looking up a binding, so absence following future safe GC cannot renew the same key. Changing the timestamp bits is a different operation key and needs explicit new intent. All command bindings are currently retained indefinitely; this patch introduces **no GC**. Client UUIDv7 creation/retry UI and migration negotiation remain unimplemented; UUIDv4 input refuses rather than being silently converted. This encoding needs independent exact-schema review, not renewed numeric-policy selection. Known accounting uses authenticated remote keys (recipient for outbound, requester for inbound), 4096/256 combined known ceilings, 5 inbound plus 5 outbound live rows, and 1024 resource slots including every full terminal Generation. Unknown authenticated cancels use a separate 512/16 compact tuple pool with exact first terminal decision identity and a 2048-byte bound, never the known pool. Actual compact serialization is measured before correlation commits; pending slots reserve a maximum terminal event plus metadata. Raw event objects remain objects. Terminal state never lends its resource slot. **Safe compaction/release is not implemented**: even reconciled generations retain their proof/command resources and can cause earlier visible refusal. This conservative limitation must be resolved before activation, not called full D4-C1 completion. Initial, manual-retry and background approvals share exact-row/original-horizon, nonempty-DID, removed-peer and existing-member eligibility. Explicit removal now holds the correlation decision guard. Incoming acceptance checks the removed DID and original horizon again immediately before calling accept_invite. Publication checks the original horizon after connecting. These are caller-boundary checks, not an atomic external-effect journal: accept_invite's internal asynchronous mutation boundary, every other membership/removal writer, partial effects and reconciliation remain open. Clock use is still provisional wall time; sibling57 qualified time/fence integration is required before activation or GC. The actual protected encrypted store and bounded pre-parse transport remain sibling56/58 integration work. Legacy R2 persistence/suppression is unchanged. The accounting wrapper does not convert that plaintext pretty-JSON writer into a protected store. Exact maximum signed fixtures, pre-sign complete prospective reservation, frozen clocks, process-death/GC races and independent review are open. Rust test sources are UNRUN under this source-only admission. No full C01, build or runtime pass.