Skip to content

feat(decisioning): Account v3 projection helpers — bank-details write-only guard (#356)#366

Merged
bokelley merged 1 commit intomainfrom
bokelley/v3-tier2-account-projection
May 2, 2026
Merged

feat(decisioning): Account v3 projection helpers — bank-details write-only guard (#356)#366
bokelley merged 1 commit intomainfrom
bokelley/v3-tier2-account-projection

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

@bokelley bokelley commented May 2, 2026

Summary

The AdCP v3 spec marks `BusinessEntity.bank` as write-only. The schema describes the rule in a docstring but doesn't structurally enforce it — `model_dump()` round-trips `bank` like any other field. This PR ships the structural guard.

  • `adcp.decisioning.project_account_for_response(account)` — returns a copy of Account with `billing_entity.bank` cleared.
  • `adcp.decisioning.project_business_entity_for_response(entity)` — same posture for standalone payloads.
  • `adcp.types.BusinessEntity` is now publicly re-exported (was `_generated`-only).
  • Original input is never mutated.

Closes #356.

Test plan

  • 11 new projection tests (incl. JSON-serialization output, no-mutation guarantee, idempotent double-projection)
  • Full suite: 3070 passed (was 3059; +11)
  • Public API snapshot regenerated
  • ruff/mypy/black clean

🤖 Generated with Claude Code

…-only guard (#356)

The AdCP v3 spec marks ``BusinessEntity.bank`` as write-only —
adopters accept it on inbound ``sync_accounts`` requests for B2B
invoicing but MUST omit it from any response payload. The schema
*describes* this rule in a docstring, but doesn't structurally
enforce it; Pydantic round-trips ``bank`` on ``model_dump()`` like
any other field. This PR ships the structural guard.

* ``adcp.decisioning.account_projection`` — new module:
  - ``project_account_for_response(account)`` — returns a copy of
    Account with ``billing_entity.bank`` cleared. Defensive copy
    when there's nothing to strip so callers can mutate freely.
  - ``project_business_entity_for_response(entity)`` — same
    posture for standalone BusinessEntity payloads (admin APIs,
    brand-rights flows that don't go through Account).
  - Original input is never mutated.
* ``adcp.types.BusinessEntity`` is now publicly re-exported (was
  reachable via the internal ``_generated`` path only). Required
  for adopters to use the projection helper meaningfully.
* Both helpers re-exported from ``adcp.decisioning``.
* 11 tests covering: ``bank`` strip, no-mutation guarantee, JSON
  serialization output, idempotent double-projection, all
  no-op corners. Plus a regression-guard skip that documents the
  reason this helper exists (Pydantic doesn't enforce the spec's
  write-only rule structurally).
* Public API snapshot regenerated.

Closes #356.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit 5d898b6 into main May 2, 2026
12 checks passed
@bokelley bokelley deleted the bokelley/v3-tier2-account-projection branch May 2, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(types): Account v3 projection helpers (billing_entity write-only bank-details guard, reporting_bucket)

1 participant