Skip to content

feat(schema): asset_type discriminator + governance plan_id scoping (#2776, #2777)#2795

Merged
bokelley merged 8 commits into
mainfrom
bokelley/doc-fix-and-asset-discriminator
Apr 22, 2026
Merged

feat(schema): asset_type discriminator + governance plan_id scoping (#2776, #2777)#2795
bokelley merged 8 commits into
mainfrom
bokelley/doc-fix-and-asset-discriminator

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

Bundles #2776 (governance plan_id scoping doc fix) and #2777 (creative asset discriminator) into one PR.

#2777 — asset_type discriminator on creative assets

  • Adds a required asset_type const to all 14 asset schemas (image, video, audio, vast, daast, text, url, html, javascript, webhook, css, markdown, brief, catalog).
  • Converts the 14-branch anyOf in core/creative-manifest.json, core/creative-asset.json, core/offering-asset-group.json, and creative/list-creatives-response.json to oneOf + discriminator: { propertyName: \"asset_type\" }.
  • Enables ajv 8's discriminator: true opt-in in the storyboard lint (scripts/lint-storyboard-sample-request-schema.cjs) and the docs JSON-schema validator (tests/json-schema-validation.test.cjs).
  • Payoff: validators now report errors against only the selected branch instead of every branch. The sales-social#catalog_driven_dynamic_ads/sync_dpa_creative allowlist entry collapses from 60+ fingerprints to 2 (just the actual uri format issue). Overall storyboard allowlist shrinks by 85 lines.
  • Adjacent cleanups: switches webhook-asset.supported_macros items from oneOf to anyOf (the universal-macro enum overlaps with plain string — anyOf is the correct shape). Updates the asset-types registry prose to reflect that asset_type is now declared in the payload. Updates docs/creative/creative-manifests.mdx and 7 other doc blocks to match.

#2776 — governance plan_id scoping doc fix

  • Adds description notes on plan_id (singular) in report-plan-outcome-request.json and check-governance-request.json, and on plan_ids (array) in get-plan-audit-logs-request.json, explaining that the plan uniquely scopes account and operator and that an explicit account field is rejected by additionalProperties: false.
  • Removes the redundant account field from two governance storyboard fixtures (protocols/governance/index.yaml#report_outcome/report_plan_outcome, #audit_trail/get_plan_audit_logs).
  • Converts the audit-logs fixture from the invalid plan_id: scalar to the required plan_ids: array form.

Test impact

  • test:schemas, test:examples, test:json-schema, test:composed, test:storyboard-sample-request-schema, tracking-event enum tests: all pass.
  • Storyboard allowlist: 85-line shrink; governance audit_trail entry removed entirely; account/outcome fingerprints no longer mentioned.
  • Pre-existing test:openapi cannot be run in this dev env without WORKOS_API_KEY; unchanged by this PR.

Test plan

  • CI green across test:schemas, test:examples, test:json-schema, test:composed, test:storyboard-sample-request-schema.
  • Verify no downstream consumers regress on the now-required asset_type field (fixtures and examples in-tree all carry it).
  • Confirm the storyboard allowlist shrink in reviewer view.

Closes #2776 and #2777.

🤖 Generated with Claude Code

bokelley and others added 8 commits April 21, 2026 22:13
…2776, #2777)

Adds a required asset_type const to all 14 asset schemas (image, video,
audio, vast, daast, text, url, html, css, javascript, webhook, markdown,
brief, catalog) and converts the 14-branch anyOf in creative-manifest,
creative-asset, list-creatives-response, and offering-asset-group to
oneOf + discriminator { propertyName: "asset_type" }. Enables ajv
discriminator support in the storyboard lint and the docs JSON-schema
validator so validators report errors against only the matched branch.
The sales-social sync_dpa_creative allowlist entry drops from 60+ error
fingerprints to 2; the overall storyboard allowlist shrinks by 85 lines.

Also documents on plan_id / plan_ids in governance/report-plan-outcome,
check-governance, and get-plan-audit-logs that the plan uniquely scopes
account and operator and that an explicit account field is rejected by
additionalProperties: false. Removes the redundant account field from
the two governance storyboard fixtures and converts the audit-logs
fixture to the required plan_ids array form.

Closes #2776 and #2777.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…asset-discriminator

# Conflicts:
#	tests/storyboard-sample-request-schema-allowlist.json
… + sharpen changeset

Addressing code-reviewer and protocol-expert feedback on PR #2795:

- Enable ajv `discriminator: true` in all 7 remaining ajv instances across
  the test suite (schema-validation, composed-schema-validation,
  example-validation, example-validation-simple, extension-fields,
  extension-schemas, media-buy-targeting-overlay-vectors,
  tracking-event-enums) so the branch-narrowed error reporting promised in
  the PR applies wherever these schemas are compiled, not just the two
  validators originally updated.

- Add `discriminator: { propertyName: "delivery_type" }` to the inner oneOf
  in vast-asset.json and daast-asset.json for symmetry with the outer
  asset_type discriminator on creative-manifest.

- Sharpen the changeset migration note: call the payload-author impact out
  at the top with an explicit "add asset_type to every asset" instruction
  rather than burying it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…asset-discriminator

# Conflicts:
#	tests/storyboard-sample-request-schema-allowlist.json
…a plan_ids)

CI TypeScript Build failed on `get_plan_audit_logs` missing
brand/account. Under the new `plan_ids` array form (the scalar `plan_id`
was removed when this PR fixed the fixture), identity is implicit via
the required globally-unique plan IDs — same category as check_governance
and report_plan_outcome.

Moves the task from TENANT_SCOPED_TASKS into EXEMPT_FROM_LINT bucket (c).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
From security-reviewer feedback on PR #2795: document the
server-side authorization requirement now that envelope account
is absent. Mirrors the fail-closed / uniform not-found pattern
from docs/building/implementation/security.mdx (Agent and Account
Isolation). Also widens the bucket (c) header comment in the
scoping lint to acknowledge anyOf-of-required-IDs as a valid shape,
so the next maintainer doesn't read the comment and assume a single
scalar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r pattern

From review feedback on PR #2795:

- Extend the changeset migration section to flag that `brief` asset
  payloads like `{content: "..."}` were only passing validation before
  because ajv matched the text-asset branch under `anyOf`. Under the new
  discriminator they must conform to creative-brief.json (minimum
  `asset_type: "brief"` + `name`); move free-text prompts into
  messaging.key_messages[] or a proper brief field.
- Also flag the nested-discriminator pattern used by vast/daast so
  downstream integrators don't expect a flat shape.

- Add an `architecture.nested_discriminator_pattern` section to the
  asset-types registry documenting the convention: asset schemas with
  internal variants use a two-level discriminator (outer `asset_type`,
  inner variant key) rather than splitting variants into sibling
  top-level asset_type entries. Cites vast/daast as the reference
  examples so future asset-type additions with internal variants (e.g.,
  a hypothetical "vpaid" with delivery variants) follow the same shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…asset-discriminator

# Conflicts:
#	tests/storyboard-sample-request-schema-allowlist.json
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.

Schema docs: governance report/audit schemas reject account — author intuition collides with plan_id scoping

1 participant