Skip to content

feat(decisioning): state-machine helpers + typed exception classes + refAccountId #455

@bokelley

Description

@bokelley

Parent: #452

Three small mechanical helpers bundled together because they all eliminate the same class of open-coding.

(a) State-machine transition helpers

from adcp.decisioning import (
    MEDIA_BUY_TRANSITIONS,
    assert_media_buy_transition,
    CREATIVE_ASSET_TRANSITIONS,
    assert_creative_transition,
)

assert_media_buy_transition(from_state="active", to_state="completed")  # ok
assert_media_buy_transition(from_state="completed", to_state="active")  # raises INVALID_REQUEST

MEDIA_BUY_TRANSITIONS is a dict[State, set[State]] mapping. Same shape for creatives.

(b) Typed exception classes

Subclasses of AdcpError with the correct error code + recovery semantic baked in:

  • PermissionDeniedError(action: str, **details)
  • AuthRequiredError(**details)
  • ServiceUnavailableError
  • RateLimitedError
  • MediaBuyNotFoundError
  • AccountNotFoundError
  • BillingNotPermittedForAgentError
  • ValidationError

Today adopters either raise generic AdcpError(code=...) (verbose) or hand-roll subclasses each time.

(c) ref_account_id helper

Drops 'account_id' in ref ? ref.account_id : None open-coding:

from adcp.decisioning import ref_account_id

acct_id = ref_account_id(ref)  # str | None

JS source

.changeset/auto-seed-symmetric-resolution.md and recipe #14 in 6.7 migration guide.

Acceptance criteria

  • All three helpers + 8 typed exceptions exported from adcp.decisioning.
  • Tests verify error codes match spec.
  • Will hit examples/v3_reference_seller/src/platform.py lines that hand-roll status maps; refactor demo deferred.

Note on credential-leak strip

Folding credential write-only-strip from the original "issue 11" plan into #4 (AccountStore.sync_governance(ctx)), since the strip happens at the AccountStore emit boundary.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions