Skip to content

test: add confidential workflow acceptance harness core - #214

Merged
imran-siddique merged 23 commits into
agentrust-io:mainfrom
altrudev:issue-199-confidential-workflow-harness-v2
Sep 28, 2026
Merged

imran-siddique merged 23 commits into
agentrust-io:mainfrom
altrudev:issue-199-confidential-workflow-harness-v2

Conversation

@altrudev

@altrudev altrudev commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Implements the focused synthetic/software harness core requested in #199.

Scope

This PR adds:

  • a fixed harness core with explicit boundary outcomes for authorization, delivery, receipt, admission, execution, response verification, and release;
  • machine-readable run-manifest and result schemas;
  • deterministic software adapters;
  • paired valid controls and weakened-gate mutation proofs;
  • explicit waiting_on_release handling;
  • branch-preserving retry observations so a later retry cannot overwrite an earlier unknown main-lineage outcome;
  • causal provenance fields on observations.

Maintainer clarification incorporated

The test suite keeps these as separate controls:

  1. a negative case that the guard must refuse or leave unknown at the affected boundary;
  2. a separately valid comparison case;
  3. the same negative case with only the relevant safety check weakened, which must become accepted.

The weakened-gate mutation is therefore not treated as the valid control.

Covered deterministic cases now include workload substitution, key substitution, policy substitution, software downgrade, replay, missing execution evidence, bypass egress, forbidden disclosure, response-binding failure, revocation before use, timeout after dispatch, retry lineage preservation, and a blocked-release marker.

Reproduction

cd integrations/agentrust-confidential-workflow-harness
python -m unittest discover -s tests -v

Local result before submission/update: 15 tests passed.

Release boundary

The harness records the intended released-package targets:

  • cmcp-runtime==0.5.0
  • ca2a-runtime==0.2.0

This PR does not claim cMCP or cA2A conformance. Protocol-specific adapters that require unreleased surfaces remain blocked and must be represented as waiting_on_release; a blocked required case keeps the software milestone incomplete.

Live-peer and hardware acceptance remain explicitly outside this PR.

Closes no milestone by itself; contributes the approved core/schemas/deterministic-adapter step toward #199.

@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

🔴 Contributor Check: HIGH

Check Result
Profile HIGH
Credential LOW
Overall HIGH

Automated check by AgenTrust Contributor Check.

@github-actions github-actions Bot added the needs-review:HIGH Contributor check flagged HIGH risk label Sep 21, 2026

@imran-siddique imran-siddique left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@altrudev, all 15 tests pass locally. I found three cases to fix before approval:

  • An adapter returning no observations still gets passed. Missing required evidence must remain unknown or incomplete.
  • A recipient listed as both permitted and forbidden still passes. Please reject conflicting lists or enforce the prohibition.
  • The version check accepts 1.0.0-rc.1 against a 1.0.0 minimum because it compares text. Please use version-aware comparison.

Please add regression tests for these cases, fix the export lint errors, and regenerate the README integration index.

Signed-off-by: Imran Siddique <imran.siddique@opaque.co>
@imran-siddique

Copy link
Copy Markdown
Member

Fixed the three review findings: missing main-lineage evidence stays unknown, forbidden recipients override permission, and the version gate uses SemVer precedence. Added regression and weakened-gate controls, fixed the exports, regenerated the index, and added the harness tests to CI. All 18 tests and the repository lint rules pass locally. The shared DecisionAssure link failure is still tracked in #213. Our code changes need independent review.

Signed-off-by: Imran Siddique <imran.siddique@opaque.co>

Copy link
Copy Markdown
Contributor Author

Independent DDC radial pass on current head 97bfe13.

The three prior findings look correctly addressed: missing main-lineage evidence remains unknown, forbidden recipients override permission, and the version floor now follows SemVer precedence for the covered cases.

One evidence/causality defect remains in the deterministic adapter:

response-binding always records caused_by="execution-check", but that source does not exist on every main-lineage path.

Examples:

  • timeout_after_dispatch=True: execution is emitted from source receipt-timeout, then response verification points to nonexistent execution-check.
  • dispatch=False: execution is emitted from source not-dispatched, then response verification again points to nonexistent execution-check.

So the run can claim causal provenance that cannot be resolved inside its own evidence graph.

I would keep this bounded: derive the response-verification parent from the actual main-lineage execution observation (or otherwise make the parent explicit), and add a regression asserting that every non-null caused_by resolves to an observation in the same lineage. That would also protect retry/alternate-lineage separation from future regressions.

I did not find a reason to reopen the three earlier findings.

@imran-siddique

Copy link
Copy Markdown
Member

@carloshvp @pforest could one of you review this harness and the follow-up fixes? The missing-evidence, recipient and version checks are fixed, with 18 tests passing. There is still an open finding from @altrudev: response-binding points to execution-check even on the timeout and no-dispatch paths, where that observation does not exist (#214 (comment)). That needs resolving before approval. One independent review is enough; no need for both of you to repeat it.

Signed-off-by: Imran Siddique <imran.siddique@opaque.co>
Signed-off-by: Imran Siddique <imran.siddique@opaque.co>
@imran-siddique

Copy link
Copy Markdown
Member

@altrudev fixed the causal-reference finding in 5e76981. Response verification now points to the actual main-lineage execution observation, including timeout and no-dispatch paths. Retry authorization is recorded within its own lineage, so every non-null parent resolves to an earlier observation in the same lineage.

The two new regression tests failed before the fix; all 20 harness tests now pass. Deliberately restoring the hard-coded parent, selecting retry execution as main, or removing retry authorization each makes the suite fail. The 28 repository validation tests, manifest/compatibility checks, generated catalog/index checks and lint also pass locally. Merged current main and regenerated the index to resolve the conflict; the new head is b97befc.

@carloshvp @pforest the outstanding code fix is now ready for independent review. GitHub CI is running; one review is enough.

@carloshvp carloshvp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I validated b97befc. The 20 harness tests pass, as do manifest/compatibility validation, generated index/catalog checks, compileall, diff checks, and the hosted checks. The earlier missing-evidence, recipient, SemVer, and deterministic causal-reference cases are fixed.

One core evidence-integrity blocker remains. HarnessRunner trusts arbitrary adapter observations, and summarize() uses last-write-wins for repeated main-lineage boundaries. A replaceable adapter can emit execution=unavailable, later emit execution=established with caused_by="does-not-exist", and the runner returns status=passed. It never validates causal parents or protects an earlier decision boundary from same-lineage post-action contamination. The deterministic timeout/no-dispatch paths also reuse receipt-timeout or not-dispatched as the source for 3 or 4 observations, so response-binding does not identify one unambiguous execution parent.

Please enforce these invariants in the fixed core before summarization: every non-null parent must resolve to exactly one earlier observation in the same lineage, and a later observation must not silently upgrade/overwrite an earlier boundary outcome. Unique observation IDs or unique (lineage, source) values would make causal references unambiguous. Add adversarial StubAdapter regressions for unresolved parents, duplicate parent identifiers, and unavailable-then-established execution in one lineage.

Also reject unsupported mutation names or derive gate_weakened from a mutation that was actually applied. Today mutation="typo" on the positive scenario returns passed with {gate_weakened: true}.

Signed-off-by: Imran Siddique <imran.siddique@opaque.co>
@imran-siddique

Copy link
Copy Markdown
Member

Fixed in 3e274dd. The core rejects ambiguous causal references, repeated boundary outcomes and unsupported mutations. The new regressions fail before the fix; all 22 harness tests and 40 subtests now pass, along with 28 repository validation tests. All 17 technical CI checks pass. Please recheck the new head.

@carloshvp carloshvp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes on 3e274dd40c29e1d366f3a2ce76941b6d649cbd7e.

The earlier causal-lineage, overwrite, and unsupported-mutation blockers are resolved. I confirmed that missing, future, self, and cross-lineage parents; duplicate sources; repeated boundaries; and empty source or lineage identifiers are rejected. The 22 harness tests pass, as do the 28 repository validation tests, manifest and compatibility validation, generated index and catalog checks, Ruff, compileall, diff checks, and a clean merge simulation against current main (f6e8c8b).

One core verdict issue remains. status() treats not_applicable as success. A replaceable adapter can emit one structurally valid main-lineage observation for every boundary with Outcome.NOT_APPLICABLE, preserve a valid causal chain, and the runner returns status="passed". Replacing only the execution outcome with NOT_APPLICABLE in an otherwise valid history also returns passed.

That lets an adapter bypass required execution or release evidence without producing unknown or refused. Issue #199 requires the positive control's required software boundaries to be established, and Scenario currently has no required-boundary declaration that could justify not_applicable for those boundaries.

Please make passed require established for every required boundary. Either all seven fixed-workflow boundaries should be required, or the scenario should explicitly declare required versus optional boundaries and the verdict should validate not_applicable against that declaration. Please add StubAdapter regressions for execution-only not_applicable and an all-not_applicable history.

Signed-off-by: Imran Siddique <imran.siddique@opaque.co>

@carloshvp carloshvp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at 80ef64bcff8a8837c5d5c637c8115b6097485eaa.

The required-boundary verdict issue from my prior review is resolved. The fixed workflow now requires established evidence at all seven main-lineage boundaries before returning passed. I exercised a replaceable adapter with each boundary individually set to NOT_APPLICABLE, all seven set to NOT_APPLICABLE, partial and empty histories, contradicted execution, and malformed causal or repeated-boundary histories. The verdicts and rejections matched the documented semantics.

Validation in an isolated checkout: 23 harness tests passed; integration and compatibility validation passed (42 integrations, 0 failures); the targeted repository validation tests passed (4 tests); generated index and catalog checks, Ruff, compileall, and git diff --check passed. A merge simulation against current main was clean. The hosted technical checks are green. The remaining gate failure reflects the maintainer approval requirement.

This approves the deterministic synthetic harness core. It does not establish live-peer or hardware acceptance or complete issue #199's full acceptance criteria.

@carloshvp

Copy link
Copy Markdown
Member

@imran-siddique I reviewed the current head 80ef64bcff and approved the deterministic harness core. The missing-evidence, forbidden-recipient, and SemVer findings from your earlier changes request have been addressed, along with the later causal-provenance and required-boundary findings. My review includes the focused and adversarial validation results.

Your earlier CHANGES_REQUESTED review is still active, so #214 remains blocked despite the passing checks. Could you re-review this head and submit an approval if your findings are resolved? If anything still needs work, please identify the remaining blocker on this PR.

@imran-siddique imran-siddique left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 80ef64bc. My three findings (missing evidence passing, permitted-and-forbidden recipients, text version compare) are fixed with regressions, and carloshvp's causal-lineage and required-boundary findings are closed. Trial merge against current main: index and catalog current, validate_integrations 42/0, 23 harness tests pass.

@imran-siddique
imran-siddique merged commit 44d0344 into agentrust-io:main Sep 28, 2026
20 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review:HIGH Contributor check flagged HIGH risk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants