Optionaloptions: ImplicitAccountStoreOptions<TCtxMeta>ReadonlyresolutionHow buyers reference accounts on this platform. Three onboarding models, aligned with the account-reference taxonomy clarified upstream in adcp#5062:
| Mode | Roster owner | Discovery | Durable wire reference |
|---|---|---|---|
'explicit' (default) |
Seller (you) | none required — IDs issued out-of-band, or list_accounts when you wire it |
{ account_id } or the { brand, operator } natural key |
'implicit' |
Buyer-declared | sync_accounts |
{ brand, operator } natural key |
'derived' |
Upstream platform you front | list_accounts (required) |
{ account_id } |
'explicit' — a seller-owned account-id namespace. You issue the ids
(Snap, Meta, GAM via Network/Company id, a publisher storefront table).
The framework applies no reference-shape constraint: both union arms
reach accounts.resolve.'implicit' — buyer-declared accounts. The buyer must sync_accounts
first; subsequent requests resolve from the auth principal's pre-synced
linkage (LinkedIn, some retail-media operators). Framework refuses
inline account_id references for these platforms — emits
AdcpError('INVALID_REQUEST', { field: 'account.account_id' }) before
reaching accounts.resolve. The brand+operator union arm is permitted
(it is the durable key for this mode); only account_id-shaped
references are rejected.'derived' — an upstream-managed account-id namespace. The agent
fronts a platform that owns its own roster (Meta / Snap business
accounts, AudioStack workspaces, a retail-media proxy). Roster size is
an operational property of the upstream, not a different SDK pattern:
N=1 and N=many adopters share one wire contract. The buyer calls
list_accounts to discover ids, then passes { account_id } on every
account-scoped request. Framework refuses the brand+operator arm for
these platforms — AdcpError('INVALID_REQUEST', { field: 'account.brand' }) with a list_accounts suggestion — because the
natural key is not a durable reference into someone else's namespace.
accounts.list is required (createAdcpServerFromPlatform throws
PlatformConfigError without it); accounts.resolve MUST verify that
a buyer-supplied account_id is one the caller's credential can
actually reach. createDerivedAccountStore does both for you.Changed in SDK 14 (breaking, adcp-client#1647). 'derived' used to
be documented as "single-tenant; no account_id on the wire" and the
framework refused inline account_id for it. That was inverted: it made
the mode unusable for the upstream-managed adopters it exists for, and
left buyers who called list_accounts with ids that every subsequent
call rejected. Agents that genuinely have no discoverable namespace and
hand out ids out-of-band belong in 'explicit'.
The mode keeps the name 'derived' even though the spec calls the
shape an upstream-managed account-id namespace — see
AccountResolutionMode for why no alias is offered.
Defaults to 'explicit' when omitted.
Return the number of principal → accounts linkages currently stored.
Resolve the caller's account from the auth-principal→account mapping
populated by a prior sync_accounts call.
Returns null (→ ACCOUNT_REQUIRED on an account-required operation
whose request omitted account) when:
sync_accounts was called for this principalttlMsctx.authInfo is absent or carries no extractable keySupplied references match the complete stored natural key. An omitted reference retains the historical first-account selection.
Optionalctx: ResolveContextProcess a sync_accounts payload: build accounts from refs and store
them under the caller's auth key.
The auth key is extracted from ctx.authInfo via keyFn. When the
key cannot be derived (no credential or unrecognized credential kind),
all refs are returned as SYNC_FAILED rows — a silent-success-then-
mystery-failure sequence is worse than an explicit error. Check your
authenticate callback and keyFn if you see this error.
When ctx.authInfo is absent (unauthenticated call), all refs fail
with UNAUTHENTICATED. Your authenticate callback in
serve({ authenticate }) should reject unauthenticated requests before
reaching this method.
Optionalctx: ResolveContextRevoke a single reference for this principal without clearing other brands.
Optionalctx: ResolveContextRemove all stored sync linkages.
Return the auth key that would be derived from authInfo.
Useful in tests to assert that a specific principal's linkage was stored.
In-memory
AccountStoreforresolution: 'implicit'platforms.Wire contract:
sync_accounts→ framework callsupsert()→ store recordsauthKey → accounts[].create_media_buy) withoutext.account_ref→ framework callsresolve(undefined, ctx)→ store looks up byauthKey.resolve()returnsnull→ framework emitsACCOUNT_REQUIRED. Do NOT returnAUTH_REQUIRED— that signals missing credentials, not a missing pre-sync.This class is intentionally minimal. Copy-and-adapt for durable stores (Postgres, Redis); see
docs/guides/account-resolution.mdfor the DDL reference and the key-derivation rationale.Example