@adcp/sdk API Reference - v7.9.0
    Preparing search index...

    Function createDerivedAccountStore

    • Build an AccountStore<TCtxMeta> for single-tenant agents whose tenant is derived from the auth principal alone (no account_id on the wire).

      The factory:

      1. Sets resolution: 'derived'.
      2. Throws AdcpError('AUTH_REQUIRED') when ctx.authInfo carries no credential (skip with skipAuthCheck: true). The check accepts the discriminated credential shape (preferred) AND the deprecated token / clientId fields populated by pre-#1269 authenticators — fail-closed only when none of the three are present.
      3. Calls toAccount(ctx) and returns the result. Buyer-supplied AccountReference is ignored — single-tenant by definition.
      4. Omits list / upsert — single-tenant adapters have nothing to enumerate or write. Adopters who want either compose via spread.

      When NOT to use this. If two different auth principals should resolve to two different account.id values, you want Shape B (createOAuthPassthroughResolver) or createTenantStore — NOT this factory. Misusing Shape D in a multi-tenant deployment routes every buyer to the same singleton id and breaks tenant isolation silently (no error, no log). The factory is single-tenant by design — toAccount(ctx) should return the same id for every principal that calls it.

      Type Parameters

      • TCtxMeta = Record<string, unknown>

      Returns AccountStore<TCtxMeta>

      import { createDerivedAccountStore } from '@adcp/sdk/server';

      const accounts = createDerivedAccountStore<AudioStackAccountMeta>({
      toAccount: (ctx) => ({
      id: 'audiostack',
      name: 'AudioStack',
      status: 'active',
      ctx_metadata: {}, // tokens stay on ctx.authInfo, not here
      }),
      });
      const accounts = createDerivedAccountStore<{ tenantId: string }>({
      toAccount: (ctx) => {
      const cred = ctx?.authInfo?.credential;
      const tenantId = cred?.kind === 'oauth' ? cred.client_id
      : cred?.kind === 'api_key' ? cred.key_id
      : 'public';
      return {
      id: 'criteo',
      name: `Criteo (${tenantId})`,
      status: 'active',
      ctx_metadata: { tenantId },
      };
      },
      });

      write path (rare for Shape D, but possible):

      const accounts: AccountStore<MyMeta> = {
      ...createDerivedAccountStore({ toAccount }),
      upsert: async (refs, ctx) => mySync(refs, ctx),
      };

      Buyer-supplied account_id is refused at the framework boundary. Since adcp-client#1468, the framework throws AdcpError('INVALID_REQUEST', { field: 'account.account_id' }) BEFORE reaching this resolver when a 'derived'-mode platform receives an inline account_id — same shape as 'implicit''s long-standing refusal (#1364), with a single-tenant message instead of the sync_accounts-first guidance. The factory itself ignores any account_id that does reach it (defensive belt + braces), but adopters can rely on the framework refusal as the canonical surface. Hand-rolled 'derived' stores get the same enforcement automatically.