Skip to content

v3.0.0-rc.4: migrate to reallocation_threshold + human_review_required (breaking) #185

Description

@bokelley

Summary

AdCP 3.0-rc.4 (unreleased, targeting GA) introduces a breaking change to the campaign governance plan schema and adds several new fields across policy, brand, and brand-ref schemas. This issue tracks the SDK work needed to support it.

Resolves the SDK-side implications of adcontextprotocol/adcp#2310.

Spec changes land in adcp PR [bokelley/policy-framework-2310 branch]; release notes in docs/reference/release-notes.mdx under 3.0.0-rc.4.

Breaking changes (must migrate)

  1. budget.authority_level is removed. The enum (agent_full | agent_limited | human_required) is gone. Replace with two orthogonal fields:

    • budget.reallocation_threshold: number ≥ 0 — budget reallocation autonomy, denominated in budget.currency
    • budget.reallocation_unlimited: true — explicit full-autonomy sentinel (mutually exclusive with threshold)

    Migration mapping:

    authority_level: 'agent_full'     → reallocation_unlimited: true
    authority_level: 'agent_limited'  → reallocation_threshold: <positive value>
    authority_level: 'human_required' → plan.human_review_required: true
                                        (+ reallocation_threshold: 0 if strict)
    
  2. Exactly one of reallocation_threshold / reallocation_unlimited is required. Budget now has a oneOf constraint.

New fields

  • plan.human_review_required: boolean — every plan action escalates for human review under GDPR Art 22 / EU AI Act Annex III
  • plan.human_override: { reason, approver, approved_at? } — artifact required to downgrade human_review_required true → false on re-sync
  • plan.policy_categories: string[] — already existed but now cross-validated
  • policy-entry.json gains requires_human_review: boolean
  • policy-category-definition.json gains requires_human_review: boolean
  • brand.json gains data_subject_contestation: { url?, email?, languages? } at brand and house levels
  • brand-ref.json gains inline industries and data_subject_contestation for callers who don't control brand.json
  • restricted-attribute enum adds age and familial_status
  • objectives has maxLength: 2000; policy-entry.policy has maxLength: 5000; description has maxLength: 500

Cross-field invariants

The schema enforces two if/then rules that some codegen tools drop:

  • If policy_categories contains fair_housing | fair_lending | fair_employment | pharmaceutical_advertising, then human_review_required: true is required
  • If policy_ids contains eu_ai_act_annex_iii, then human_review_required: true is required

These are load-bearing invariants — regulated-vertical campaigns cannot opt out of human oversight. Codegen that drops if/then (e.g., datamodel-code-generator in strict mode) will fail to enforce this client-side.

SDK tasks

Required

  • Regenerate types from the 3.0.0-rc.4 schemas
  • Update MIGRATING.md (or equivalent) with the authority_levelreallocation_threshold / reallocation_unlimited / human_review_required mapping as the top migration item
  • Update every sync_plans example, test fixture, and quickstart that currently uses authority_level
  • Ensure oneOf on budget (threshold XOR unlimited) is enforced either by the validator or by a client-side check
  • Verify that age and familial_status are accepted as restricted-attribute values (any hardcoded 8-value lists need expanding)

Recommended

  • Add a client-side validator for the policy_categories ∋ regulated-vertical → human_review_required: true invariant (specifically important if your codegen drops if/then)
  • Add a helper for building Annex III plans — one-liner that sets policy_categories, human_review_required, and nudges the caller about data_subject_contestation
  • Add a helper for building human_override artifacts (validates reason length, email format)
  • Add typed accessors for check_governance response fields: escalation.reason, humanReviewAutoFlippedBy (if the server surfaces it), and the new findings: data_subject_contestation_missing, annex_iii_industry_advisory

For governance-agent implementors using the SDK

  • Ensure your governance agent auto-flips human_review_required based on resolved policy_categories, policy_ids, and custom_policies
  • Emit a critical data_subject_contestation finding when the plan requires human review but no contestation contact is discoverable
  • Resolve contestation in order: plan.brand inline → brand.json → brand.json.house → missing
  • Do not allow mode: advisory | audit to downgrade denied/escalated when human_review_required: true
  • Require human_override artifact for re-sync downgrades (reason ≥20 chars, email approver)
  • Append-only plan revisions — do not silently replace prior state

References

One-line pitch for your SDK README

AdCP is the first open advertising protocol where GDPR Article 22 and EU AI Act Annex III are load-bearing schema invariants, not policy PDFs — regulated-vertical campaigns cannot opt out of human oversight, and every decision is audit-logged by default.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions