Skip to content

bug: trace_adapter binds an approval whose timestamps are booleans #126

Open

Description

@drk-ram

Version or commit

origin/main at ee33beaef286526c42c8106e826cf4c48b7e8471

Observed behavior

spec/schema/common.schema.json defines time_unix_nano as a decimal string (^(0|[1-9][0-9]{0,19})$). src/agentrust_telemetry/trace_adapter.py does not re-check that form. _bound_approvals and _action_approval_binding call int() on the timestamp fields.

int(True) is 1, because bool is a subclass of int. An approval request, approval, and executed action whose timestamps are all True therefore compare as the window 1 <= 1 <= 1. _bound_approvals returns that approval, and _action_approval_binding reports the action bound.

The same function rejects a real late approval: an approval at "100" for an action at "15" is contradicted. The boolean triple is not rejected; it is bound. finalize_trace derives iat with the same int() call, so a boolean timestamp also becomes iat 0.

Expected behavior

A timestamp that is not a canonical decimal string is not a window. Boolean timestamps must not satisfy requested_at <= approved_at <= expires_at, and must not make an approval-gated action bound. The failure should be the same class as a late approval: the action is not bound, and finalization does not coerce the value into iat.

Minimal reproduction

From a checkout of ee33beaef286526c42c8106e826cf4c48b7e8471, with PYTHONPATH set to src (Python 3.11.9):

from agentrust_telemetry.trace_adapter import (
    _action_approval_binding,
    _bound_approvals,
)

digest = {"algorithm": "sha256", "value": "ab" * 32}

def ev(kind, t):
    row = {
        "event_type": kind,
        "approval_id": "ap-1",
        "policy_event_id": "pol-1",
        "action_digest": digest,
        "chain_id": "chain",
        "chain_version": "1",
        "requested_at_unix_nano": t,
        "expires_at_unix_nano": t,
        "time_unix_nano": t,
    }
    if kind == "action.executed":
        row["outcome"] = "success"
    return row

late_req = ev("approval.requested", "10")
late_ap = ev("approval.approved", "100")
late_ap["requested_at_unix_nano"] = "10"
late_ap["expires_at_unix_nano"] = "200"
late_act = ev("action.executed", "15")
late_bound = _bound_approvals([late_req, late_ap])
print(
    "late",
    _action_approval_binding([late_act], {"pol-1": "challenge"}, [late_req, late_ap], late_bound),
)

req = ev("approval.requested", True)
ap = ev("approval.approved", True)
act = ev("action.executed", True)
bound = _bound_approvals([req, ap])
print(
    "bool",
    len(bound),
    _action_approval_binding([act], {"pol-1": "challenge"}, [req, ap], bound),
)
print("iat", int(True) // 1_000_000_000)

Environment and additional context

Observed output:

late contradicted
bool 1 bound
iat 0

Python 3.11.9 on Windows 11 x86_64. This is a conformance defect in trace_adapter, not a report against the policy adapters or the projection module. Synthetic ids and digests only.

Activity

  1. github-actions commented on Nov 3, 2026

    @github-actions

    🔴 Contributor Check: HIGH

    Check Result
    Profile HIGH
    Credential LOW
    Overall HIGH

    Automated check by AgenTrust Contributor Check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-review:HIGHContributor check flagged HIGH risk

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions