Skip to content

feat(protocol): the principal layer — unified webhooks, declarations, principal.changed - #7110

Merged
bokelley merged 4 commits into
mainfrom
feat/connection-layer
Aug 31, 2026
Merged

feat(protocol): the principal layer — unified webhooks, declarations, principal.changed#7110
bokelley merged 4 commits into
mainfrom
feat/connection-layer

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Replaces #7020, which GitHub auto-closed when its stacked base branch was deleted after #6966 merged. The reviewed implementation was rebased onto main; #7020 retains the original design discussion and Ladon delta reviews. Implements RFC #7015.

The model

Principal (the transport-resolved party: buyer agent or operator) → standing configuration with one seller (webhooks, destinations, declarations) → independently authorized advertiser accounts. Nothing in this layer grants account authority.

What this adds

  1. Principal-level webhook subscriptions. A caller-level subscriber may carry account-anchored event types only with explicit all_authorized_accounts: true. Authorization is re-evaluated at every delivery attempt, including retries; revocation suppresses queued account data. include_future_event_types covers only future invalidation-only types. active: false is the one-call endpoint kill switch.
  2. Declarations and negotiation readback. Callers declare async AdCP versions, verifiable signing algorithms, and experimental features. Sellers persist the declared set, accepted intersection, selected async version, and exclusions with reasons.
  3. principal.changed. A caller-anchored invalidation for seller-driven state changes, repaired through get_principal.
  4. Resolved principal_kind and assertion fence. The seller resolves buyer_agent or operator from authorization state; request content can only assert an expected kind and receives CONFLICT on mismatch.
  5. Agent-scoped operator_id destination labels. Supports per-operator isolation and offboarding without treating labels as cross-principal identity.
  6. Two-sided event offering. caller_event_types lets clients select supported events without rejection-driven probing.

The follow-up also preserves media-buy cadence reports on reporting_webhook, keeps impairment on push_notification_config, and corrects the webhook schema title to “Principal Changed Webhook.”

Verification

  • 16/16 principal contract tests
  • 28/28 MCP projection/analysis tests
  • schema and compliance builds
  • compliance source/package integrity
  • storyboard request/response validation
  • changed-doc snippet and schema-link validation
  • the pre-rebase content previously passed the full local precommit and storyboard matrices; this rebased head is gated by the full GitHub CI board before merge

Human/CODEOWNERS review remains required for the schema-source paths.

bokelley and others added 3 commits August 31, 2026 11:37
Allow caller-level webhook subscribers to carry account-anchored event
types with fire-time authorization scoping — each fire covers only
accounts the caller is authorized for at fire time — plus an explicit
include_future_event_types opt-in instead of a wildcard. Add the
declarations section: buyer-declared consumption facts (async payload
versions, verifiable webhook signing algorithms, experimental opt-ins)
with a seller-computed accepted intersection that gives webhook fires
the version-negotiation channel synchronous requests get from the
envelope. Add the caller-anchored principal.changed invalidation
webhook for seller-driven principal-state transitions, repaired through
get_principal. Report the seller-resolved principal_kind (buyer_agent
or operator) on every readback with an expected_principal_kind
assertion fence, and add the agent-scoped operator_id destination label
with a normative cross-principal non-alignment rule. Advertise
caller_event_types in capabilities so buyers select from the offering
instead of probing by rejection, and gate the destination storyboard
phases on section support.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ontract

State explicitly that the layer begins after authentication — AdCP
defines no credential-registration protocol — and add the normative
"Establishing a connection" lifecycle joining authentication, principal
configuration, account binding, and readiness. Require the explicit
all_authorized_accounts acknowledgment for account-anchored event types
on caller-level subscribers, with authorization evaluated at each
delivery attempt so revocation suppresses queued retries carrying that
account's data. Restrict include_future_event_types to types classified
invalidation-only, so the flag can never silently opt a caller into
payload-bearing events. Persist the full declarations negotiation
record: declared set, accepted intersection, the seller's
selected_async_adcp_version, and per-value exclusion reasons.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…anged-webhook title

- `scheduled`, `final`, `delayed`, `adjusted`, `window_update` fire through
  `reporting_webhook`, not `push_notification_config` — fix in
  notification-type.json description and sync_principal.mdx bullet
- `impairment` explicitly called out on `push_notification_config` as a
  decision: dependency-state change, not a cadence report
- `principal-changed-webhook.json` title corrected from
  "Connection Changed Webhook" to "Principal Changed Webhook"

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Escalate to human review

Escalate — gated schema-source paths require human/CODEOWNERS approval.

This PR modifies and adds files under static/schemas/source/**, which are under a hard, deterministic approval gate (gated_paths: true). The current review_decision is REVIEW_REQUIRED, not APPROVED, so decision-table row 2 fires: the gate is not satisfied and the PR cannot be approved or plain-commented.

The reviewer surfaced no Critical/High/Medium findings — the change is additive, internally coherent, correctly experimental, carries a minor changeset, verified schema↔docs coherence and oneOf discrimination integrity. The escalation is purely because the mandatory human/CODEOWNERS review on the protocol source-of-truth schema paths has not yet been recorded.

Escalation reasons

  • Touches gated schema-source paths (e.g. static/schemas/source/core/principal-declarations.json [added], static/schemas/source/protocol/sync-principal-response.json [modified], and 12 others) — human/CODEOWNERS review required; review_decision is REVIEW_REQUIRED.

Why human review

  • Gated paths under static/schemas/source/** are modified/added (14 files) and review_decision is REVIEW_REQUIRED, not APPROVED — human/CODEOWNERS review required before merge.
  • This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/agent-notification-config-state.json (modified) matches static/schemas/source/**; static/schemas/source/core/agent-notification-config.json (modified) matches static/schemas/source/**; static/schemas/source/core/agent-reporting-destination.json (modified) matches static/schemas/source/**; static/schemas/source/core/principal-changed-webhook.json (added) matches static/schemas/source/**; static/schemas/source/core/principal-declarations-state.json (added) matches static/schemas/source/**; static/schemas/source/core/principal-declarations.json (added) matches static/schemas/source/**; static/schemas/source/core/principal-state.json (modified) matches static/schemas/source/**; static/schemas/source/enums/notification-type.json (modified) matches static/schemas/source/**; static/schemas/source/index.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/get-adcp-capabilities-response.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/get-principal-request.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/get-principal-response.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/sync-principal-request.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/sync-principal-response.json (modified) matches static/schemas/source/**) and the current GitHub review decision is 'REVIEW_REQUIRED', not APPROVED. This is a hard gate enforced in code — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded, regardless of how clean the diff is.

@aao-secretariat aao-secretariat Bot added the ladon/needs-human-review Ladon has escalated this PR for human review. label Aug 31, 2026

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Escalate to human review

Escalate — gated schema paths require human/CODEOWNERS approval.

No blocking, Medium, or High findings. The reviewer found this to be a clean consistency refactor: two shared schema definitions (core/experimental-feature-id.json, enums/principal-kind.json, both x-status: experimental) are extracted and referenced via $ref, and the principal-declarations feature-id pattern is tightened to the documented canonical vocabulary. $ids resolve, no new oneOf introduced, changeset present, schema↔docs coherence holds, all on an experimental surface.

However, this PR modifies/adds 16 files under static/schemas/source/**, which is a hard, non-overridable approval gate (gated_paths: true). The current GitHub review_decision is REVIEW_REQUIRED, not APPROVED. Per decision-table row 2, the outcome must be escalate regardless of how clean the diff is — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded. This is consistent with the prior escalate decision; the gate persists purely on the unsatisfied review status, not on any new finding.

Escalation reasons

  • Gated paths under static/schemas/source/** (16 files modified/added) and review_decision is REVIEW_REQUIRED, not APPROVED — human/CODEOWNERS review required before merge.

Why human review

  • Gated paths under static/schemas/source/** (16 files modified/added) and review_decision is REVIEW_REQUIRED, not APPROVED — human/CODEOWNERS review required before merge.
  • This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/agent-notification-config-state.json (modified) matches static/schemas/source/**; static/schemas/source/core/agent-notification-config.json (modified) matches static/schemas/source/**; static/schemas/source/core/agent-reporting-destination.json (modified) matches static/schemas/source/**; static/schemas/source/core/experimental-feature-id.json (added) matches static/schemas/source/**; static/schemas/source/core/principal-changed-webhook.json (added) matches static/schemas/source/**; static/schemas/source/core/principal-declarations-state.json (added) matches static/schemas/source/**; static/schemas/source/core/principal-declarations.json (added) matches static/schemas/source/**; static/schemas/source/core/principal-state.json (modified) matches static/schemas/source/**; static/schemas/source/enums/notification-type.json (modified) matches static/schemas/source/**; static/schemas/source/enums/principal-kind.json (added) matches static/schemas/source/**; static/schemas/source/index.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/get-adcp-capabilities-response.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/get-principal-request.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/get-principal-response.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/sync-principal-request.json (modified) matches static/schemas/source/**; static/schemas/source/protocol/sync-principal-response.json (modified) matches static/schemas/source/**) and the current GitHub review decision is 'REVIEW_REQUIRED', not APPROVED. This is a hard gate enforced in code — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded, regardless of how clean the diff is.

@bokelley
bokelley merged commit 9753caa into main Aug 31, 2026
60 checks passed
@bokelley
bokelley deleted the feat/connection-layer branch August 31, 2026 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ladon/needs-human-review Ladon has escalated this PR for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant