Skip to content

fix(prebind): replay approval-free allow as admitted #213

Description

@tcconnally

Problem

The current main branch mis-replays a valid approval-free allow prebind as denied. plutus_agent/prebind.py:122-132 computes:

approved = bool(state.get("approval_granted", prior.get("approval_ref") is not None))

When an approval is not required, approval_ref is absent and no approval_granted state is supplied, so replay defaults to approved=False. A live-main probe returned admission="not_admitted" and replayed_boundary_outcome="deny" for an unchanged approval-free allow prebind.

This contradicts the acceptance boundary recorded in #197, which explicitly requires approval-free allow coverage.

Proposed change

Represent approval requirement and approval decision distinctly during prebind construction/replay. An unchanged approval-free allow must replay as admitted/allow; approval-required cases must remain non-admitted until an explicit approval is present. Preserve the distinction among approval-free, approval-required, denied, expired, stale-evidence, and scope-changed states.

Acceptance criteria

  • An unchanged approval-free allow prebind replays as admission="admitted" and replayed_boundary_outcome="allow".
  • An approval-required prebind without approval is not admitted.
  • Denied, expired, stale-evidence, authority-changed, and scope-changed states remain non-admitted with explicit reason codes.
  • Add a truth-table test covering approval-free, approval-required, missing, denied, and expired approval states.
  • Existing receipt compatibility and hash binding remain intact.
  • No raw prompts, context, tool arguments, credentials, or secrets enter receipts.

Grounding

  • Current source: plutus_agent/prebind.py:105-132 at main commit 1a7be9a37116d9b8225b787992d38e7de0435c6.
  • Reproduction: live-main probe returned not_admitted / deny for unchanged approval-free allow.
  • Related acceptance contract: ledger#197, implemented by #198.
  • Research lead: Atlas trust-state-machine pattern.

Non-goals

  • This does not authorize actions; it corrects replay semantics for recorded state.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingresearch

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions