id: notification_config_event_scope
version: "1.0.0"
title: "Notification config event-scope rejection"
category: schema_validation
summary: "Validates that sync_accounts.accounts[].notification_configs[] rejects media-buy-anchored notification types."
track: core
required_tools:
  - sync_accounts

narrative: |
  `notification-type.json` historically contained both media-buy-anchored
  event types (`scheduled`, `final`, `delayed`, `adjusted`, `window_update`,
  `impairment`) and
  account-anchored event types (`creative.*`, `product.*`, `signal.*`,
  `wholesale_feed.bulk_change`). Account-level notification config schemas now
  expose only account-anchored event types so media-buy registrations fail
  closed before persistence.

  This storyboard closes that semantic gap for the account-level surface:
  `sync_accounts.accounts[].notification_configs[]` MUST reject media-buy-
  anchored event types. Those events belong on a media buy or task's
  `push_notification_config`; accepting them on account-level configs would
  imply a subscription lifecycle and payload contract the spec does not define.

  The request is schema-invalid on purpose. A conformant seller rejects it
  rather than silently persisting or dropping a subscriber for an event whose
  subscription lifecycle and payload contract belong on media-buy-scoped
  `push_notification_config`.

agent:
  interaction_model: media_buy_seller
  capabilities: []
  examples:
    - "Any AdCP agent that accepts sync_accounts"

caller:
  role: buyer_agent
  example: "Compliance test harness"

prerequisites:
  description: |
    The agent under test exposes `sync_accounts`. The sample request uses
    provisioning mode against the Acme Outdoor sandbox brand. Explicit-account
    sellers that only support settings-update mode SHOULD run the same vector
    against a pre-provisioned account reference; the invariant is identical:
    account-level `notification_configs[]` must reject media-buy-anchored
    event types.
  test_kit: "test-kits/acme-outdoor.yaml"
  controller_seeding: false

phases:
  - id: reject_media_buy_anchored_event_type
    title: "Reject media-buy-anchored event type on account config"
    narrative: |
      The buyer submits a schema-invalid notification config that asks an
      account-level subscriber to receive `scheduled` delivery reports.
      `scheduled` is media-buy anchored and belongs on
      `push_notification_config`, not on
      `sync_accounts.accounts[].notification_configs[]`. The seller must
      reject the entry rather than silently persisting or dropping the
      subscriber.

    steps:
      - id: sync_accounts_rejects_scheduled_account_notification
        title: "Submit scheduled in notification_configs[].event_types"
        task: sync_accounts
        schema_ref: "account/sync-accounts-request.json"
        response_schema_ref: "account/sync-accounts-response.json"
        doc_ref: "/accounts/tasks/sync_accounts"
        sample_request_skip_schema: true
        stateful: false
        expected: |
          Reject the per-account entry with:
          - accounts[0].action: "failed"
          - accounts[0].status: "rejected"
          - accounts[0].errors[0].code: INVALID_REQUEST or VALIDATION_ERROR
          - accounts[0].errors[0].field pointing at the invalid event_types entry

        sample_request:
          accounts:
            - brand:
                domain: "acmeoutdoor.example"
              operator: "pinnacle-agency.example"
              billing: "operator"
              sandbox: true
              notification_configs:
                - subscriber_id: "delivery-reports"
                  url: "https://example.com/webhooks/adcp/account"
                  event_types:
                    - "scheduled"
                  active: false
          idempotency_key: "$generate:uuid_v4#notification_config_event_scope_reject_scheduled"
          context:
            correlation_id: "notification_config_event_scope--reject_scheduled"

        validations:
          - check: response_schema
            description: "Response matches sync-accounts-response.json schema even on per-account failure"
          - check: field_value
            path: "accounts[0].action"
            value: "failed"
            description: "Per-account action is failed"
          - check: field_value
            path: "accounts[0].status"
            value: "rejected"
            description: "Per-account status is rejected"
          - check: field_value
            path: "accounts[0].errors[0].code"
            allowed_values: ["INVALID_REQUEST", "VALIDATION_ERROR"]
            description: "Media-buy-anchored event type is rejected as a correctable request validation error"
          - check: field_value
            path: "accounts[0].errors[0].field"
            value: "notification_configs[0].event_types[0]"
            description: "Error identifies the invalid event_types field so SDKs can correct the registration"
          - check: field_value
            path: "context.correlation_id"
            value: "notification_config_event_scope--reject_scheduled"
            description: "Context correlation_id returned unchanged on error response"
