RRetailAgentOS
All Specs
RAOS-0008Draft · RFCv1.0.0June 2026

Trust, Provenance & Freshness

com.os.retailagent.shopping.trust

Plane 0 · Foundation · Tier 0 · Discoverable · Reference implementation in Playground

Crypto is SIMULATED — the signing interface is real; the implementation uses a deterministic hash (no real cryptography). Every simulated envelope carries trustMode: "asserted" and the signature prefix sim:. The swap to real HMAC-SHA256 or ECDSA is mechanical (one function body in trust.ts). See WP-19.
The real-crypto algorithm (OQ#1), per-field freshness model (OQ#2), and clock-skew tolerance for QUOTE stage (OQ#3) are genuine design forks. See the open questions →

Abstract

RAOS-0008 operationalizes the provenance and freshness envelope that RAOS-0000 §9 defined at contract level. It answers three questions every trust-conscious agent must ask:

  1. Is this data from who it claims to be from? — The signed payload envelope: issuer, key identifier, and a deterministic signature.
  2. Is this data still current? — Per-stage TTL defaults (price 300s, inventory 60s, eligibility 3600s). Staleness has a behavior matrix: refuse for QUOTE, degrade+flag for advisory.
  3. Can I trust the key? — Merchant manifest carries keys[] with validity windows. Key rotation is a first-class concept.

How long is data considered fresh?

StageDefault TTL
ELIGIBILITY / VISIBILITY3600s (1h)
PRICE300s (5m)
INVENTORY60s (1m)
QUOTEverified at use

Reason code registry

One namespace, six codes. Four are synthetic-only (require injected failures; tested in trust.test.ts).

CodeMeaningSeverityResolvable?
TRUST_SIMULATED
Crypto is simulated. Every envelope produced while B3/D2 is in effect carries this INFO code. Always emitted — it is the "this is not real security" label that prevents simulation being mistaken for production trust.INFO
Advisory / not resolvable
DATA_STALE
Data has exceeded its TTL. For advisory stages (PRICE, ELIGIBILITY): degrade and flag. For QUOTE stage: refuse. The agent must re-fetch before acting.CONDITION
Re-fetch and re-evaluate with a fresh envelope
SIGNATURE_INVALID
synthetic-only
Signature does not match the canonicalized payload. The payload may have been tampered with. Most-restrictive: BLOCK.BLOCK
Advisory / not resolvable
ISSUER_UNKNOWN
synthetic-only
The keyId in the envelope does not match any key in the merchant's published keys[]. Cannot verify provenance of this data.BLOCK
Advisory / not resolvable
KEY_EXPIRED
synthetic-only
Key found in merchant manifest but validTo < now (±60s skew allowance). The merchant must rotate to a new key.BLOCK
Merchant rotates to a new key in keys[]; re-issue envelope with new keyId
CLOCK_SKEW_SUSPECTED
synthetic-only
computedAt is in the future beyond the clock-skew tolerance (±60s). The agent and merchant clocks may be out of sync.CONDITION
Re-synchronize agent clock; re-request with correct now

What attacks does this prevent?

AttackDefeated by
Spoofed merchant
keyId lookup in merchant keys[]. Unknown key → ISSUER_UNKNOWN BLOCK. The agent rejects data from issuers it cannot verify.
Replayed envelope
computedAt + TTL freshness. Replayed envelopes expire. At QUOTE stage all stale envelopes are refused (not just flagged).
Stale promo served as fresh
computedAt comes from injected now (never wall-clock). Manipulating computedAt is detectable via CLOCK_SKEW_SUSPECTED if the agent's clock differs.
Tampered price
signEnvelope canonicalizes the entire payload including unitPrice. A single-character change → different signature → SIGNATURE_INVALID BLOCK.

Open questions

These are genuine forks. Tell me I'm wrong.

#1Real crypto seam — HMAC-SHA256 or ECDSA-P256?

The interface is real; the simulation is the placeholder. WP-19 swaps in real crypto. HMAC-SHA256 is simpler (shared secret per merchant); ECDSA-P256 enables decentralized verification (public key published in manifest, no shared secret distribution).

Leaning: HMAC-SHA256 for v1 (simpler key management for small merchants), ECDSA as a v2 upgrade path. The seam makes either mechanical.

#2Per-field freshness vs per-result freshness

The envelope today attaches to each ExtensionResult (per-evaluator). A richer model would expose per-field freshness (price is fresh, inventory is stale within the same result). WP-05 already has per-item freshness on ComputedAvailability. Should the outer envelope gain a fieldFreshness slot?

Defer to WP-07 (Quote Integrity) which has the most pressing need for field-level trust. Quote tokens need to know whether the price they are locking was fresh at issue time.

#3Clock-skew tolerance: ±60s uniform or tighter for QUOTE?

Banking systems use ±5s; mobile agents in intermittent connectivity can drift more. ±60s may be generous for high-stakes data (QUOTE). Should the tolerance be configurable per stage?

Leaning: tighten to ±30s for QUOTE-stage data, ±60s for advisory stages. Stage-configurable tolerance is cleaner than one global value.

#4DATA_STALE vs STOCK_STALE disambiguation

RAOS-0008 emits DATA_STALE (trust namespace) and RAOS-0005 emits STOCK_STALE (inventory namespace). Both can fire in the same evaluation. Are they additive? Does one supersede the other?

Additive — they are genuinely different signals. STOCK_STALE is the inventory-domain code (the data source is stale); DATA_STALE is the trust-domain code (the pipeline evaluation result is stale). Agents reading both get richer information.

Have a view on any of these?

The real-crypto algorithm and clock-skew tolerance questions are the most consequential. If you've operated a distributed commerce system and dealt with clock drift or key rotation in production, your experience is exactly what this spec needs.

rikbanerjee007@gmail.com

Why this is foundational

Freshness and provenance are not premium features. An agent that doesn't know whether its data is current or authenticated cannot safely act. RAOS-0008 is Tier 0 because every other spec produces data that can go stale — without this spec, there is no protocol-level way to signal staleness to the agent. WP-07 (Quote Integrity) directly depends on the signing seam: a quote token is only as tamper-resistant as the envelope it carries. The TTL defaults are themselves a data model — they encode the merchant's implicit promise about data freshness.