feat: fail-closed mobile pairing cancellation and terminal lifecycle - #15
Open
CompleteDotTech wants to merge 15 commits into
Open
feat: fail-closed mobile pairing cancellation and terminal lifecycle#15CompleteDotTech wants to merge 15 commits into
CompleteDotTech wants to merge 15 commits into
Conversation
7 tasks
…854) (OpenCoven#861) Adds one dated status/decision record for issue OpenCoven#854 in docs/superpowers/plans/. Independently verified against main @ 1364cec (2026-08-30): the coven#816 foundation series (PR OpenCoven#846, PR OpenCoven#847, parts 6-8 commits) landed the durable local scheduler core - definitions, SQLite definition/occurrence/run records with unique occurrence fencing, RRULE planning, bounded leases with expiry recovery, latest-only misfire / overlap refusal, the 60s daemon tick with scheduled dispatch, shared launch path, health and run history, non-destructive paused legacy import, and coven.automations.* control actions. Records what is still absent for v1 (versioned protocol schemas, authority/receipt binding, deterministic-time contract, SDK surface, conformance/chaos/SLO gates, live Beads mutation), the gate-by-gate verdict, and the critical path. The program issue remains open; this record closes no issue. Refs OpenCoven#854. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
marked this pull request as ready for review
August 30, 2026 16:35
…oven#815) (OpenCoven#871) * docs: plan cryptographic fresh-user and biometric assurance proofs (coven#815) Specify COVEN-ASSURANCE/1, an independently verifiable step-up proof so request authentication can satisfy FreshUserVerification/FreshBiometric grant requirements without trusting client-asserted assurance levels. The plan defines: possession/step-up key separation; binding the optional step-up authorization key and its declared assurance class into the pairing-v2 transcript; a separate authorization-key store; canonical proof bytes over device, grant, revocation epoch, exact request or DeviceActionIntent digest, server-issued single-use challenge, window, and requested assurance; server-side effective assurance computed as min(claimed, class ceiling) and passed to DeviceGrant::authorize; fail-closed possession-only degradation; rotation/revocation semantics; iOS/Android platform mapping; a self-verifying synthetic golden vector; and TypeScript/JSON Schema for implementers. Every claim cites the current mobile_memory code path it builds on. No code changes: this is the design artifact the issue asks for. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * docs(mobile): specify COVEN-ASSURANCE/1 step-up assurance proofs Add docs/design/mobile-assurance-step-up-v1.md, the plan and implementation contract for issue OpenCoven#815: a separately enrolled, platform-policy-protected step-up authorization key, bound into the pairing-v2 transcript before grant issuance, whose fresh signatures over canonical COVEN-ASSURANCE/1 bytes (device, grant, revocation epoch, exact request or DeviceActionIntent digest, single-use server challenge, validity window, requested assurance) are the only way to raise assurance above possession. The server verifies the signature, computes effective assurance itself, and passes it to DeviceGrant::authorize; absent/invalid/expired/replayed proofs fail closed. Covers storage separate from the possession key, replay protection independent of request nonces, rotation/revocation semantics, iOS/Android key-policy mapping, a security-invariant mapping, TypeScript types + JSON Schema, and a portable golden vector. Design artifact only; no behavior change. Refs OpenCoven#815 Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> --------- Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
…heck (coven#859) (OpenCoven#862) Establish the GitHub-side half of the OpenCoven#859 operational delivery graph: - docs/roadmaps/coven-automations-v1.md: program roadmap with canonical tracker roles, sync metadata, P0/P1/P2 policy, generated outcome-mapping table, dependency graph, release gates, active blockers, and drift detection usage. The mapping table block is generated by docs/roadmaps/drift-check.mjs --render and verified on every run. - docs/roadmaps/coven-automations-v1.mapping.json: machine-readable one-to-one Bead <-> GitHub mapping for OpenCoven#854, OpenCoven#816, OpenCoven#855, OpenCoven#856, OpenCoven#857, and OpenCoven#858, with explicit dependencies, acceptance gates, dispositions, and evidence links. Bead IDs stay null (warn-level W010) until provisioning lands through OpenCoven/coven-cave#5220 per the operational correction on OpenCoven#859; no competing Beads store is created in this repository. - docs/roadmaps/drift-check.mjs: credential-free, offline drift check covering state, priority, parent/dependency, evidence, generated-mirror, duplicate/missing mapping, cycle, and sensitive-payload drift classes, with --beads-export cross-checking and --selftest proving detection. - docs/superpowers/plans/2026-08-30-issue-859-coven-automations-v1-...md: dated status/decision record: what exists on main (automations series landed 2026-08-28 via PRs OpenCoven#846/OpenCoven#847), pre-change integrity report, decisions D1-D7, verdict against the OpenCoven#859 acceptance criteria, remaining work, critical path, and the initial evidence packet. Refs OpenCoven#859 fix: keep automation tracker docs scanner-safe Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 17:45
ea6883a to
d00c09c
Compare
… claims * docs: consolidate Coven security policy, threat boundary, and support claims Replace the duplicated SECURITY.md (repository policy plus a copied organization-wide disclosure addendum) with one Coven-specific operational security contract that visibly separates: - supported release family and security-supported surfaces, with experimental/disabled surfaces (AFS mount backend, OpenClaw plugin, remote transports) marked explicitly; - enforced properties today, each tied to its normative contract and verification family (Rust authority checks, capability advertisement, pre-effect validation, owner-protected local transport, redaction and artifact defaults, secret/privacy guards, explicit mutation replay); - residual risk and safe configuration (same-user trust vs sandboxing, raw-artifact opt-in, retention limits, untrusted harnesses, AgentFS mount posture synced with OpenCoven#779); - private reporting via GitHub Security Advisories as the primary path, with no personal-channel dependency and no unsupported response-time commitment, plus scoped third-party dependency/provider handling; - design goals (session/memory/agent isolation) moved out of guarantees, cross-referencing OpenCoven#803/OpenCoven#804 instead of claiming unimplemented A2A isolation. Removes the stale OpenTrust-scope addendum, the personal Discord DM reporting path, and the 48-hour/14-day response promises that no accountable process currently backs. Refs OpenCoven#808 Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * fix: document tokenized invite URL privacy rule Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> --------- Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 17:49
d00c09c to
fff22f8
Compare
…enCoven#785) (OpenCoven#867) * docs(pairing): plan TUI QR bootstrap and E2EE mobile pairing (refs OpenCoven#785) Add the implementation plan for issue OpenCoven#785: the coven device command family, canonical CBOR pairing offer with Universal Link encoding, Noise_XK handshake with QR-pinned host authentication, rendezvous relay MVP on coven-relay, six-word human verification derived from the handshake hash, scope selection and capability binding, the adversarial test matrix, and the maintainer decision points. Extends the accepted mobile-device-trust architecture and elaborates PR 3 + the rendezvous slice of PR 4 of the pairing delivery train. Docs-only change; cross-links the delivery plan to the new plan. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * chore(pairing): retrigger CI for the plan PR (no content change) The pull_request opened event raced the fork's lazy workflow registration, so no run was created. This empty commit re-emits the synchronize event; it changes no content. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> --------- Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 17:54
fff22f8 to
ad075c7
Compare
* docs: point install guidance at canonical coverage The canonical install, platform, deployment, uninstall, and install-debugging guides are merged in OpenCoven/coven-docs, so the duplicate local pages under docs/install/ become stable pointers per the Wave A cleanup plan. docs/install/development-channels.md keeps its local content because no canonical page covers pre-release channels yet. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * docs: point onboarding pages at canonical guidance Duplicate local onboarding pages (quickstart, first session, onboarding, showcase, doctor) become pointers to the canonical getting-started and doctor routes. coven-tui.md keeps its legacy-TUI contract and its root-absolute links are fixed to the retained local session-lifecycle contract and the canonical CLI reference. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * docs: shrink the README to a landing page and codify the public-docs boundary The README stops duplicating the canonical manual and keeps the landing-page facts: what Coven is, one install and quick-start path, canonical links, the source-adjacent ownership table, contributor rules, and security. DOCS-MAINTENANCE.md gains the enforceable public-doc directory boundary (canonical pointers or source-adjacent exceptions with stated ownership reasons), and docs/index.md links to it. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * ci: retrigger pull request checks after enabling fork Actions No file changes. The pull request was opened before Actions was enabled on this fork, so no workflow run was created for its head SHA. This empty commit fires a pull_request synchronize event so the CI matrix can report. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> --------- Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 18:02
ad075c7 to
229ca70
Compare
…Coven#863) Investigate issue OpenCoven#807 against main at 1364cec (2026-08-30) and record a dated status/decision document in the repo's record location (docs/superpowers/plans/). Facts recorded: the existing non-gating benchmark/chaos corpus, health and recovery surfaces, release certification (certify-release.sh, 2026-08-29), packaged-artifact journey E2E, release-stress workflow, and AFS gating posture, each with evidence links and dates; a verdict against all six acceptance criteria (not satisfied on main; partial on separation-by-convention, structured receipts, and privacy-by-design); and a dependency-ordered critical path. No measurements, targets, or SLOs are invented. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 18:09
229ca70 to
5689551
Compare
* docs: record issue 670 docs program status on main Add a dated status/decision record for OpenCoven#670 at docs/superpowers/plans/2026-08-30-issue-670-docs-program-status.md. It records, with evidence links and dates: the merged progressive-help implementation (OpenCoven#834), the merged packaged first-session E2E (OpenCoven#835, closing OpenCoven#777), the canonical journey and docs CI live in OpenCoven/coven-docs (OpenCoven#775/OpenCoven#778 state), the still-open single-source cleanup of this repository (OpenCoven#776: README shrink, residual local pages, missing CI ownership enforcement), and the open OpenCoven#779 certification matrix. It gives a per-criterion verdict against OpenCoven#670's nine acceptance criteria, what remains, and the critical path. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * chore: retrigger vehicle CI after a dropped pull_request event The fork vehicle's Actions went live at 2026-08-30T15:54Z, after PR #10 opened at 15:46Z, so the opened/ready_for_review events never started a run (0 check-runs on the head SHA ~20 minutes after creation). Push an empty signed commit to fire the synchronize event; no file changes. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * docs: keep issue 670 record clear of the privacy phone detector The Coven privacy guard's phone_number rule (E.164-like plus-digit tokens) flags the diff-stat notation (+1828), (+464), (+279), (+323), and (+2686) in the OpenCoven#670 status record. Restate those as insertion and deletion counts; no content changes. Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> --------- Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 18:15
5689551 to
cdbde9f
Compare
* test(agents): characterize input-guardrail ingress at handoff boundaries Characterizes the coven-agents runner's input-guardrail behavior so the handoff bypass in OpenCoven#803 is visible from test output before the enforcement change: - direct-entry rejection vs handoff entry to the same target (parity regression: currently the handoff target's input guardrails never run) - handoff target GuardrailChecked event ordering (after Handoff, before the target's first ModelRequested) and the exact evaluated input - multi-hop A->B->C per-boundary checks and a target rejection at hop C - input-guardrail implementation error vs policy rejection, direct and handoff (GuardrailFailed keeps its own message and source) - handoff/tool action exclusivity stays pinned Tests encode the corrected expectation and are paired with the runner change in the next commit; compile proof and green runs defer to CI (this workspace has no Rust toolchain). Refs OpenCoven#803 Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * fix(agents): enforce target input-guardrail parity across handoffs Closes the ingress bypass in Runner::run_loop (OpenCoven#803): a handoff target's input guardrails were never evaluated, so an agent reached through a model handoff could consume input that direct entry to it would reject. - extract the input-guardrail evaluation into one shared path, Runner::check_input_guardrails, used by direct starts and by every handoff boundary - evaluate the handoff target's input guardrails against the original user input — the same bounded string a direct start would check, never a serialized transcript — after the Handoff item/event is recorded and before the target's first model turn or tool execution - a target rejection or guardrail implementation error fails the run (RunFailureKind::InputGuardrail) before the target's model call, so the target receives no model request and executes no tool; the GuardrailFailed/GuardrailRejected distinction is preserved - emit GuardrailChecked with the target identity and Input stage; exactly one terminal RunCompleted/RunFailed pairing is preserved - multi-hop A->B->C now applies each hop's ingress policy at its own boundary Documented compatibility contract: target ingress is evaluated over the original/root user input only. The structured task/context manifest for delegated invocations is the successor contract in OpenCoven#804; this patch is not complete A2A security. Handoff/tool exclusivity, fail-fast topology validation, handoff limits, session semantics, and output-guardrail behavior are unchanged. cargo fmt/clippy/test verification defers to CI (no Rust toolchain in this workspace); formatting verified with a standalone rustfmt binary. Refs OpenCoven#803 Refs OpenCoven#804 Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * fix: keep handoff checks warning-free Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> --------- Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 18:26
cdbde9f to
e4469c2
Compare
Issue OpenCoven#774 asks Coven to keep default help concise, preserve every command through the grouped `coven help --all` view, and expose a deterministic JSON help contract. The executable side of that work landed in OpenCoven#834; the contract itself remained undocumented for consumers. Document the contract in the developer core-functionality guide (schemaVersion 1 payload shape, determinism and leak guarantees, drift-fails-loudly rule) and surface it to script authors in the automation JSON guide. Extend scripts/cli-docs-test.mjs so the docs guard fails when the contract documentation regresses. Refs OpenCoven#774 Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 18:40
e4469c2 to
f5fe316
Compare
…es, and changefeed Publish the coven.automations.v1 contract as spec artifacts plus a normative design document, so Cave, the SDK, Psyche adapters, runtimes, and future implementations can consume automations without importing Coven internals. spec/coven-automations/v1/ (draft 2020-12 JSON Schemas and machine-readable artifacts, following the spec/device-pairing/v1 precedent): - five object schemas (definition, occurrence, run, attempt, receipt) with monotonic revisions, integrity digests, exact-revision pinning, and fail-closed unknown-field behavior through an explicit extension bag - command/response envelope: every mutating command carries a stable adoption key (first-commit-wins replay, ADOPTION_REPLAY_MISMATCH on conflict) and expectedRevision where applicable; responses are committed/replayed/rejected only, so a domain failure can never be wrapped as accepted - typed error envelope with a frozen HTTP/control-action status mapping - versioned changefeed envelope: per-stream gapless sequences, globally unique event ids, causation, cursor expiry, compaction snapshots - state-machines.json: authoritative definition/occurrence/run/attempt machines plus the ten normative invariants - capabilities.json: positive and explicit negative variant negotiation - compatibility-matrix.json: change classes and profile-refusal rules - test-vectors.json: golden valid/invalid/unknown-field/downgrade/ unknown-variant vectors, adoption replay and revision-conflict cases, duplicate and out-of-order event replay, with pinned RFC 8785 digests - coven.automations.v1.d.ts: pinned TypeScript projection for SDK/Cave canaries docs/architecture/coven-automations-v1.md: the design document, citing the current OpenCoven#816 code paths for every gap, ratifying the lifecycle semantics, the OpenCoven#816 non-destructive migration, the Rust type mapping, and recording alternatives considered for the genuinely maintainer-owned decisions. No runtime code changes: schemas, vectors, and docs only. Refs OpenCoven#855 Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 19:10
f5fe316 to
de21f6e
Compare
* refactor: extract route/version authority gate from coven-cli api Move ApiRoute, normalize_api_route, split_path_query, and the route-version constants out of the 25k-line api.rs into a dedicated api_routes.rs gate module (issue OpenCoven#806 slice 1: extract pure request/route parsing first, behind stable contracts). - the gate keeps its exact contract: non-/api/ paths pass through borrowed, /api/v1/<route> is rewritten to /<route>, unsupported versions answer 404 invalid_request with the apiVersion and supportedApiVersions payload, other malformed /api/... shapes answer 404 not_found - characterize the pure classifier (positive, malformed, unsupported, passthrough, query-splitting, version-prefix-never-retained property) and pin the full unsupported-version rejection envelope plus the uniform 404 envelope for malformed API prefixes through handle_request - document the authority-direction invariant on the gate and publish the concentration inventory, extraction order, and where-new-behavior-belongs map in docs/authority-module-inventory.md No behavior change: handlers, routes, status codes, error envelopes, payloads, and persistence are untouched. Refs OpenCoven#806 Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> * chore: format authority gate test Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com> --------- Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
Make pairing cancellation a first-class state transition instead of
leaving a declined or abandoned pairing usable until its five-minute
expiry.
- PairingManager::cancel: bounded (sweeps expired entries like every
other operation) and idempotent; cancelling a completed pairing
reports AlreadyCompleted and never revokes the enrolled device grant
- cancellation drops transcript and device material immediately; the
tombstone answers device callers exactly like a consumed pairing
before the deadline and exactly like a naturally expired pairing
after it, so cancellation and expiry stay indistinguishable to an
untrusted mobile caller and no new mobile error class is introduced
- owner-only daemon control route POST
/api/v1/internal/mobile/pairings/{id}/cancel with a coarse
pairing_cancelled audit event (no nonce or transcript material)
- owner status distinguishes created, enrolled, partially_confirmed,
completed, cancelled, and expired without exposing secrets
- the interactive pairing flow attempts cancellation before exiting on
host decline and on Ctrl-C interruption (signal-safe flag handler,
same pattern as the daemon termination handler)
Refs OpenCoven#814
Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
Past the deadline any pairing-manager operation sweeps entries it is not addressing, so sharing one manager across the cancelled and the naturally expired pairing let the first probe evict the second before it could be addressed. Give each pairing its own harness so both see the same probe schedule without cross-pruning. Refs OpenCoven#814 Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
CompleteDotTech
force-pushed
the
agent/issue-814-plan-explicit-mobile-pairing-cancellation-and
branch
from
August 30, 2026 19:25
de21f6e to
57f4b0a
Compare
The pairing interrupt handler only latched an atomic flag while the host confirmation read could block indefinitely: std surfaces an interrupted read as ErrorKind::Interrupted, so the flag was only observed by accident and was never rechecked before the /confirm handoff, letting a Ctrl-C that raced the user pressing Enter confirm an otherwise-declined pairing. Read the confirmation through an interruptible input loop that rechecks the latched flag on every interrupted read, cancels the pending pairing, and exits without consuming further input; recheck the flag immediately before posting /confirm. Install the SIGINT handler through a scoped guard that restores the previous disposition and resets the flag on every path out of the pairing flow. Signed-off-by: CompleteDotTech <5861166+CompleteDotTech@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes pairing cancellation a first-class, fail-closed state transition (OpenCoven#814). Today, declining the confirmation prompt or abandoning
coven mobile pairleaves the pending introduction fully usable until its five-minute expiry. This slice:PairingManager::cancel— bounded (sweeps expired entries like every other manager operation, no timers/threads) and idempotent (Cancelled/AlreadyCompleted/AlreadyTerminal). Cancelling a completed pairing is a no-op that preserves the enrolled device grant — no revocation, replay window untouched.POST /api/v1/internal/mobile/pairings/{id}/cancelon the local (unix-socket) control plane only; the TLS gateway has no cancel route.…/{id}/statusnow reportscreated/enrolled/partially_confirmed/completed/cancelled/expired(distinguishing waiting-for-device from waiting-for-confirmation) without exposing nonce, transcript, or device material; the phrase remains owner-visible only while its transcript exists.pairing_cancelledevent (event name only, no pairing id / nonce / transcript material), emitted once per effective cancellation; idempotent repeats stay silent.Issue
Refs OpenCoven#814
Test plan
Local runs (checked = executed locally):
rustfmt --edition 2021 --checkon all four touched files (formatter only; no Rust build tooling per environment policy —cargo fmt/clippy/testdeferred to CI)Deferred to CI (unchecked = no Rust toolchain in the agent sandbox by policy):
cargo fmt --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspace --lockedpython scripts/check-secrets.pypython3 scripts/check-coven-privacy.py --stagedNew focused tests: 8 unit tests in
pairing.rs(cancel before enrollment / after enrollment / after one confirmation; repeated cancel idempotent + cannot resurrect; completed-pairing grant preserved; cancelled≡expired device-callable parity across the deadline; full lifecycle status; expiry status drops material) and 3 gateway tests (control-route cancel idempotent + audited once; device callers fail closed with existing error classes; cancelled ≡ consumed parity for device callers before the deadline).Scope note
Single coherent slice covering all checklist items of OpenCoven#814 on the surfaces that exist today (the "TUI" host surface in this repo is the interactive
coven mobile pairterminal flow — no other TUI pairing surface exists).