feat(intent-bridge): bind successor observations for #338 - #340
feat(intent-bridge): bind successor observations for #338#340altrudev wants to merge 19 commits into
Conversation
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
|
🔴 Contributor Check: HIGH
Automated check by AgenTrust Contributor Check. |
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
Signed-off-by: altrudev <266135212+altrudev@users.noreply.github.com>
rajnisht7
left a comment
There was a problem hiding this comment.
Integrity vs sufficiency split is in looks in the right direction, but there are a few gaps:
verify_bridge()still does not bind the successor When transcript_required is true, the path still ends roughly as:
if not isinstance(transcript.get("after"), dict):
raise AuthorizationMismatch(...)and there is no call to _bind_successor_observation(), and no check against a successor digest.
-
expected_successor_digestis not authenticated by the bridge evaluate_successor_observation(..., expected_successor_digest=...) only checks:
digest(after) == expected_successor_digest
That expected value is caller-supplied and it is not a field of the signed authorization, and schema/pic-trace-bridge-v1.json has no successor digest either. The module docstring even says the prototype does not decide whether that digest lives in the signed authorization, the transcript, or a detached artifact. -
#338 says that when a profile makes a successor-state claim, the verifier must establish the exact observation for this evaluation, so substituted/replayed after objects can be detected.
If the caller can also choose expected_successor_digest, a substituted observation can still be made to “match” by passing expected = digest(forged_after). Until the expected digest is tied to something authenticated (signed authorization, committed transcript field, or a detached artifact that is itself verified), requirement 1 is only partly met. -
Two meanings of after:
In verify_bridge: after = any execution-result object (dict).
In _bind_successor_observation: after = exactly {observation, observer, observed_at}. -
Docstrings still say “prototype” while the PR title is feat(...).
-
Optional tests: future observed_at, max_age_seconds == 0, empty trusted_observers (logic looks fine when tried manually).
Implements #338 as the narrow successor-observation extension accepted in the issue review.
Governing rule
The bridge must not treat a bound
transcript.afterobject as proof that a requested real-world transition occurred.This PR keeps successor integrity separate from successor sufficiency:
established,contradicted, ornot-established;not-established, never a positive result;Integration
The exact-envelope binding now lives in
agentrust_trace.intent_bridge, alongside the existing canonical-byte binding fortranscript.before.tool_call.The tri-state successor evaluator remains separate so a successful integrity check cannot silently become transition closure.
The informative PIC/TRACE bridge profile now states the assurance boundary for requirements 2, 4, and 5, including the treatment of absent
after.No TRACE Trust Record schema change. No replay semantics. No universal transition-predicate language. No application-state store.
Adversarial coverage
The existing #340 matrix covers:
AI-assistance disclosure: ChatGPT assisted with DDC radial analysis, implementation drafting, and adversarial review.
altrudevremains responsible for the contribution.