Skip to content

fix(agents): enforce target input-guardrail parity across handoffs - #7

Open
CompleteDotTech wants to merge 11 commits into
mainfrom
agent/issue-803-p0-enforce-target-input-guardrail-parity
Open

fix(agents): enforce target input-guardrail parity across handoffs#7
CompleteDotTech wants to merge 11 commits into
mainfrom
agent/issue-803-p0-enforce-target-input-guardrail-parity

Conversation

@CompleteDotTech

@CompleteDotTech CompleteDotTech commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Context

  • Summary: Runner::run_loop evaluated input guardrails once, for the starting agent only. A handoff target's input guardrails never ran, so an agent reached through a model handoff could consume input that direct entry to it would reject. This PR extracts the input-guardrail evaluation into one shared path, Runner::check_input_guardrails, and runs it at every agent boundary: for the starting agent before its first model turn (unchanged), and for every handoff target after the Handoff item/event is recorded and before the target's first model turn or tool execution.
  • Files changed: crates/coven-agents/src/runner.rs (shared ingress helper + handoff boundary check), crates/coven-agents/src/guardrail.rs (trait docs), crates/coven-agents/tests/runner.rs (7 focused characterization/regression tests), docs/superpowers/specs/2026-08-14-coven-agents-rust-design.md (runner loop description).
  • Refs P0: enforce target input-guardrail parity across coven-agents handoffs OpenCoven/coven#803

Vehicle note: opened in the fork CompleteDotTech/coven as the CI vehicle — this token cannot write to OpenCoven/coven. Re-target upstream once write access is restored. Refs OpenCoven#803.

Issue

Refs OpenCoven#803 — P0: enforce target input-guardrail parity across coven-agents handoffs.

Implementation

  • Approach: one named helper, Runner::check_input_guardrails, is the single ingress path shared by direct-start and handoff semantics. In the handoff branch it runs after the RunItem::Handoff / RunEvent::Handoff are recorded (the handoff genuinely happened and stays in the failure transcript) and before continue, so the target's policy is enforced before the target's first ModelRequest.
  • Compatibility contract (precise): a handoff target's input guardrails are evaluated against the original/root user input — the exact same bounded string a direct Runner::run(target, input, …) would check. No serialized transcript, no session history, and no intermediate assistant/tool output is evaluated by the target's ingress policy. The structured task/context manifest for delegated invocations is the successor contract tracked in P1: refactor coven-agents onto invocation/delegation contracts without a second distributed runtime OpenCoven/coven#804; this patch is intentionally not complete A2A security.
  • Event semantics: GuardrailChecked is emitted per target guardrail with the target identity and GuardrailStage::Input; each run still emits exactly one terminal RunCompleted/RunFailed. A target policy rejection reports RunError::GuardrailRejected { agent: target, stage: Input }; a guardrail implementation error reports RunError::GuardrailFailed — the two remain distinguishable.
  • Security invariants: a rejected target receives no model call and executes no tool side effect; tools, authority, project scope, context, and session persistence are unchanged; handoff remains mutually exclusive with tool actions; fail-fast topology validation is untouched.
  • User-visible behavior: the only visible change is the intentional closure of the bypass — a handoff into a target that rejects the root input now fails with RunFailureKind::InputGuardrail at the boundary, returning the partial transcript (UserMessage, source items, Handoff) to the caller. Existing fail-fast limits, session load/append semantics, and output-guardrail behavior are unchanged.

Verification

  • python scripts/check-secrets.py — ran locally, passed
  • python3 scripts/check-coven-privacy.py --staged — ran locally, passed
  • rustfmt --edition 2021 --check on touched files — ran locally with a standalone rustfmt binary (workspace has no Rust toolchain); full cargo fmt --check deferred to CI
  • cargo clippy --workspace --all-targets -- -D warnings — deferred to CI (no Rust toolchain locally)
  • cargo test -p coven-agents — deferred to CI (no Rust toolchain locally)
  • cargo test --workspace --locked — deferred to CI (no Rust toolchain locally)
  • Additional manual checks: new focused tests in crates/coven-agents/tests/runner.rs make the security property visible from test output: handoff_target_enforces_the_same_input_policy_as_direct_entry (direct-vs-handoff parity, no model call / no tool execution for the rejected target), handoff_target_input_guardrail_runs_before_the_target_model_turn (event ordering + the exact evaluated input), multi_hop_handoff_enforces_input_policy_at_every_boundary (A→B→C per-boundary checks), multi_hop_handoff_target_rejection_prevents_the_target_model_turn (rejection at hop C), handoff_target_guardrail_error_is_distinguishable_from_a_rejection + failing_input_guardrail_is_distinguishable_from_a_rejection (GuardrailFailed vs GuardrailRejected), handoff_cannot_be_combined_with_tool_calls (exclusivity). Characterization-first: commit 1 lands the regression tests encoding the corrected expectation (direct-B rejection vs the current handoff-B bypass), commit 2 closes the bypass.

Risk and Rollback

  • Risk level: low-medium — a security tightening of one runner branch. Direct-start behavior is code-motion identical; no existing test encodes the bypass; limits, session, and output-guardrail paths are untouched.
  • Rollback plan: revert the fix commit (fix(agents): enforce target input-guardrail parity across handoffs); the characterization commit is additive.

Agent Handoff

CI status note (no CI exists on this vehicle): GitHub Actions is enabled on CompleteDotTech/coven, but the repository has zero workflow runs (actions/runs.total_count = 0, check-runs.total_count = 0 for the head SHA), no registered workflows, and a close/reopen re-dispatch produced no checks — this fork cannot run the repo's CI. The Rust checks (cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test -p coven-agents, cargo test --workspace --locked) are therefore not verified by CI on this vehicle and must run on an upstream PR once write access to OpenCoven/coven is restored. Local verification performed: rustfmt --edition 2021 --check on all touched files, python scripts/check-secrets.py (passed), python3 scripts/check-coven-privacy.py --staged (passed).

…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>
…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
CompleteDotTech force-pushed the agent/issue-803-p0-enforce-target-input-guardrail-parity branch from ac7b9c0 to 4122b35 Compare August 30, 2026 17:33
… 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
CompleteDotTech force-pushed the agent/issue-803-p0-enforce-target-input-guardrail-parity branch from 4122b35 to 0e3b6a1 Compare August 30, 2026 17:49
…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
CompleteDotTech force-pushed the agent/issue-803-p0-enforce-target-input-guardrail-parity branch from 0e3b6a1 to 623f375 Compare August 30, 2026 17:54
* 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
CompleteDotTech force-pushed the agent/issue-803-p0-enforce-target-input-guardrail-parity branch from 623f375 to 7996c95 Compare August 30, 2026 18:02
…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
CompleteDotTech force-pushed the agent/issue-803-p0-enforce-target-input-guardrail-parity branch from 7996c95 to 7e34659 Compare August 30, 2026 18:09
CompleteDotTech and others added 4 commits August 30, 2026 14:15
* 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>
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>
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>
Signed-off-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>
@CompleteDotTech
CompleteDotTech force-pushed the agent/issue-803-p0-enforce-target-input-guardrail-parity branch from 7e34659 to 2a95f5e Compare August 30, 2026 18:15
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.

1 participant