Skip to main content
The protocol does not mandate what a buyer must share with a counterparty. It does give you the primitives to produce two distinct views of the same audit trail:
  • An internal view — the buyer’s full record of every check, finding, budget movement, and human review. Used for self-protection, regulator audits, and internal compliance review.
  • A shareable view — a scoped subset, addressed to one counterparty (a seller, an agency, a third-party auditor). Reveals only what that party needs to verify their own action.
Both are produced from get_plan_audit_logs. The split is a matter of filtering and field selection, not a separate protocol.

Why split at all

Three reasons buyers maintain distinct views:
  1. Strategy leakage. Total authorized budget, channel allocation, and remaining headroom across all sellers are competitive signals. Note that derived ratios are not safer than raw amounts — budget.utilization_pct is a one-step inverse problem if a seller knows their own committed share. A single seller does not need to know the buyer’s full plan to verify their own buy.
  2. Cross-counterparty isolation. Seller A has no business seeing the findings, governance contexts, or outcomes for Seller B. A shareable view is always scoped to the requesting party’s governance_context values.
  3. Internal review fields. Human review reasons, drift metrics, and oversight thresholds are the buyer’s own governance posture. They protect the buyer in a regulator audit; they are not addressed to a counterparty.

Field tagging

The table below classifies every field in the get_plan_audit_logs response by who can safely see it.

Producing a shareable view

To answer “what should I share with Seller X?”, filter the audit query to the contexts that belong to that seller and drop plan-level aggregates. Request scoped to one seller’s actions:
This narrows governed_actions and entries to the requested contexts. The buyer is still responsible for stripping budget.*, channel_allocation.*, summary.findings_count, summary.statuses, and summary.drift_metrics before forwarding — those summaries cover the entire plan and reveal totals across other sellers. Minimum compliance attestation (no entries): For counterparties who only need proof that a buy was governed — not the full trail — share a four-field attestation derived from the audit response:
The seller can verify the plan_hash against the plan revision they signed under, and the policies_evaluated list confirms which registry policies were applied. Nothing else about the buyer’s portfolio is disclosed.

Regulator and auditor views

A regulator typically asks for one of three things:
  1. Did human oversight occur where required? Share summary.human_reviews[] and the requires_human_review flag from the resolved policies. Reasons may be redacted or summarized; resolutions and timestamps should be intact.
  2. Did the buy comply with a specific regulation? Share entries scoped by policies_evaluated containing the regulation’s policy_id (e.g., us_coppa). Include plan_hash so the regulator can verify against the plan revision.
  3. Are oversight metrics within thresholds? Share summary.drift_metrics and the policy-derived thresholds. A human_review_rate below human_review_rate_min is a signal worth explaining.
The protocol does not define a regulator API. Counterparty rules govern the disclosure; the audit trail makes the disclosure possible.

Worked example: a clean buy

A plan with 500KauthorizedforanOLV/displaycampaign.Theorchestratorrunsanintentcheckongetproducts,thenanexecutioncheckoncreatemediabuyfor500K authorized for an OLV/display campaign. The orchestrator runs an intent check on `get_products`, then an execution check on `create_media_buy` for 150K, then reports the outcome. The full internal audit response:
The seller’s shareable view of the same trail is the governed_actions[] entry and the entries[] filtered to governance_context = 11ab64d0.... Plan-level budget.authorized, budget.remaining, and the summary aggregate stay buyer-side.

What violations look like

Findings are how the audit trail communicates risk. Two patterns worth knowing:

Security-shaped finding: an unauthorized seller

The plan declares approved_sellers: ["https://ads.seller-approved.example"]. A different seller calls check_governance and gets denied:
The corresponding plan summary records statuses.denied: 1 and findings_count: 1. The unauthorized seller’s governance_context is still recorded — the trail captures the attempt, not just the success.

Coaching-shaped finding: an Annex III prerequisite is missing

A plan with policy_categories: ["fair_lending"] (mortgage, consumer credit, etc.) auto-flips human_review_required: true. If the brand profile doesn’t expose a contestation contact, the check fails closed with an actionable explanation:
The denial is also a coaching moment — the operator sees exactly what to fix. This is the shape good governance findings should take: a category, a severity, and a path forward.

The operator’s dial: enforce / advisory / audit

mode is set on the plan via sync_plans and is the operator’s primary lever. The same caller, same payload, same finding produces three different outcomes depending on mode. mode: "enforce" — the buy is blocked at the governance layer:
mode: "advisory" — the buy proceeds; the operator gets a critical finding to act on post-hoc:
mode: "audit" — the buy proceeds silently; the finding is in the log for retrospective analysis:
The trade-off: A plan can shift modes between revisions — the governance decisions in the audit trail tell the truth about how each historical buy was governed. The operating mode should be visible on every audit entry; today it appears on the per-check_governance response but not consistently on get_plan_audit_logs responses (#3156).

What the protocol guarantees

Two invariants you can rely on when designing your shareable view:
  • plan_hash is verifiable. It is base64url_no_pad(SHA-256(JCS(plan_payload))) over the plan revision the check was evaluated against. Any party with the plan revision can recompute and byte-compare the digest. See Plan binding and audit.
  • Inline policies cannot relax registry policies. A buyer’s bespoke policy entries can only add restrictions on top of registry-sourced policies. So when a shareable view shows policies_evaluated: ["us_coppa"], the counterparty can trust that the registry version of us_coppa was applied at its declared enforcement level — the buyer did not silently downgrade it. See Policy Registry.