You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
intent_bridge: normalize integer-by-value timestamps (authorized_at, expires_at, observed_at) to int and bound now by JCS_SAFE_INTEGER #568
On main (e1560f3), src/agentrust_trace/intent_bridge.py has two defects in its timestamp handling:
Whole-valued float timestamps (100.0, 150.0) are validated by _integer_value but not normalized to int:
In verify_bridge (lines 410-421), _integer_value(authorization[field], f"authorization.{field}") validates authorized_at and expires_at per §3.2.2 (accepting 100.0 and 200.0), but discards the returned int, leaving float values in the returned authorization dict.
In _bind_successor_observation (lines 275-285), observed_at = _integer_value(after["observed_at"], "successor envelope observed_at") validates after["observed_at"], but _bind_successor_observation returns after with after["observed_at"] still a float.
Because sign_successor_artifact (lines 111-118) sets "observed_at": bound["observed_at"], calling sign_successor_artifact with after={"observation": {...}, "observer": "obs-1", "observed_at": 150.0} emits a signed artifact whose observed_at is 150.0 (float instead of int).
And in verify_successor_artifact (line 216), bound["observed_at"] in the returned dictionary remains 150.0 (float).
verify_bridge does not bound now by JCS_SAFE_INTEGER:
Unlike successor_observation.evaluate_successor_observation (which checks 0 <= now <= JCS_SAFE_INTEGER), verify_bridge (lines 422-424) accepts now = 10**20 (above JCS_SAFE_INTEGER). Notice in tools/sweep_public_surface.py that successor_observation.evaluate_successor_observation.now rejects 10**20, whereas intent_bridge.verify_bridge did not check now > JCS_SAFE_INTEGER.
Reproduction on main (e1560f3):
fromagentrust_traceimportgenerate_keyfromagentrust_trace.intent_bridgeimportsign_successor_artifactkey=generate_key()
after= {"observation": {"ok": True}, "observer": "obs-1", "observed_at": 150.0}
artifact=sign_successor_artifact("auth-1", after, "key-1", key)
asserttype(artifact["observed_at"]) isfloat# 150.0 instead of int 150!
_bind_successor_observation and verify_bridge should return a shallow copy with observed_at, authorized_at, and expires_at normalized to int (without mutating the caller's input dictionary in place), so sign_successor_artifact, verify_successor_artifact, and verify_bridge always emit/return int timestamps.
verify_bridge should reject now > JCS_SAFE_INTEGER with IntentBridgeError("now must be a non-negative integer Unix timestamp within the JCS safe-integer range").
Impact
Prevents float timestamps from leaking out of sign_successor_artifact, verify_successor_artifact, and verify_bridge when whole-valued float timestamps (100.0, 1.76e9) are supplied, and aligns verify_bridge's now bound with JCS_SAFE_INTEGER.
Activity
intent_bridge: normalize integer-by-value timestamps to int and bound…