Skip to content

[proposal] revoke_activation — canonical buyer/producer revocation primitive (signals domain) #4203

@EvgenyAndroid

Description

@EvgenyAndroid

Summary

AdCP 3.0 has no protocol-level mechanism for a buyer to stop using a signal mid-campaign once it has been activated to a destination. The existing activate_signal task accepts action: "deactivate" (schema signals/activate-signal-request.json) but:

  • No published agent in the live AdCP directory implements it (verified via federation probe against the live registry)
  • The semantics of "deactivate this signal everywhere" vs. "deactivate this specific activation" are undefined
  • Buyer-triggered revocation carries no reason code, no authorization scope, no async-safe state machine, and no audit trail
  • The only alternatives today are manual out-of-band destination action (untraceable) or producer-set validity_period (not buyer-triggered, not implemented in any 3.0.x adapter)

This is a clean greenfield gap: no existing GH issue, no in-flight RFC, no working-group thread covering this surface (verified prior-art check, May 2026).

Proposed primitive: revoke_activation

A new task in the signals domain. Design constraints:

  • Async-by-default — revocations may require producer-side propagation to downstream platforms; synchronous response is not realistic
  • Reason-coded — reason enum covers compliance, campaign-end, budget-exhausted, policy-violation, producer-request, and test (minimum viable set; open for extension)
  • Reason-scoped authorization — not every caller can invoke every reason code (e.g. producer-request may only be callable by the producing agent; policy-violation requires governance context)
  • Reuses existing AdCP infrastructure end-to-end — async polling via tasks/get, webhook delivery using the existing signed-webhook contract, no new transport / auth / persistence / envelope
  • Additive only — agents that don't implement revoke_activation degrade to today's behavior; no breaking change to activate_signal

Request sketch

{
  "task": "revoke_activation",
  "idempotency_key": "<uuid>",
  "signal_agent_segment_id": "<segment-id>",
  "activation_ref": "<activation-idempotency-key | all>",
  "destinations": ["<destination-id>"],
  "reason": "compliance | campaign-end | budget-exhausted | policy-violation | producer-request | test",
  "effective_at": "<ISO-8601 | null>",
  "context": {}
}

activation_ref: "all" targets all active destinations for the segment. A specific key targets a single activation, enabling per-activation revocation without disturbing siblings.

State machine (proposed)

pending → propagating → revoked | failed

Webhook event: signal.revocation.completed / signal.revocation.failed

Open questions for working-group triage (§14 of full proposal)

  1. Producer-initiated revocation routing — sibling tool on the buyer agent, or direct call from producer to buyer agents? What's the right topology?
  2. Cascade semantics — when a signal feeds an activation chain, does revoking the root propagate? Proposal default: explicit per-task only for v1.
  3. Pricing reconciliation — mid-billing-period revocation creates a partial-use window. In scope for protocol (e.g. a revoked_at timestamp on the activation record), or out of scope?
  4. effective_at scheduling — who is responsible for running the timer for future-dated revocations? Caller, producer, or platform?
  5. Privacy-budget restoration — when clean-room signals are revoked, should the protocol signal that budget is restorable? How?

Full proposal

Detailed spec (17 sections — request + response schemas, state machine, reason code enum, authorization matrix, worked example, conformance storyboard, test plan):
https://github.com/EvgenyAndroid/adcp-signals-adaptor/blob/master/docs/SPEC_PROPOSAL_REVOKE_ACTIVATION.md

Target milestone

3.1 minor — additive, no breaking changes, testable in <10 conformance storyboards.

Prior art

None found. activate_signal action: "deactivate" exists in schema but is semantically underspecified and unimplemented. This proposal supersedes the deactivate discriminator or can be defined as its normative complement.

Suggested labels

domain:signals, kind:proposal, priority:high

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.needs-wg-reviewBlocked on a working-group decision — surface in WG meeting agendasrfcProtocol change — auto-adds to roadmap boardsignalsIssue concerns the signals protocol domain

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions