feat(schema): asset_type discriminator + governance plan_id scoping (#2776, #2777)#2795
Merged
Merged
Conversation
…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
This was referenced Apr 22, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bundles #2776 (governance plan_id scoping doc fix) and #2777 (creative asset discriminator) into one PR.
#2777 — asset_type discriminator on creative assets
asset_typeconst to all 14 asset schemas (image,video,audio,vast,daast,text,url,html,javascript,webhook,css,markdown,brief,catalog).anyOfincore/creative-manifest.json,core/creative-asset.json,core/offering-asset-group.json, andcreative/list-creatives-response.jsontooneOf+discriminator: { propertyName: \"asset_type\" }.discriminator: trueopt-in in the storyboard lint (scripts/lint-storyboard-sample-request-schema.cjs) and the docs JSON-schema validator (tests/json-schema-validation.test.cjs).sales-social#catalog_driven_dynamic_ads/sync_dpa_creativeallowlist entry collapses from 60+ fingerprints to 2 (just the actualuriformat issue). Overall storyboard allowlist shrinks by 85 lines.webhook-asset.supported_macrositems fromoneOftoanyOf(the universal-macro enum overlaps with plain string —anyOfis the correct shape). Updates the asset-types registry prose to reflect thatasset_typeis now declared in the payload. Updatesdocs/creative/creative-manifests.mdxand 7 other doc blocks to match.#2776 — governance plan_id scoping doc fix
plan_id(singular) inreport-plan-outcome-request.jsonandcheck-governance-request.json, and onplan_ids(array) inget-plan-audit-logs-request.json, explaining that the plan uniquely scopes account and operator and that an explicitaccountfield is rejected byadditionalProperties: false.accountfield from two governance storyboard fixtures (protocols/governance/index.yaml#report_outcome/report_plan_outcome,#audit_trail/get_plan_audit_logs).plan_id:scalar to the requiredplan_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.account/outcomefingerprints no longer mentioned.test:openapicannot be run in this dev env withoutWORKOS_API_KEY; unchanged by this PR.Test plan
test:schemas,test:examples,test:json-schema,test:composed,test:storyboard-sample-request-schema.asset_typefield (fixtures and examples in-tree all carry it).Closes #2776 and #2777.
🤖 Generated with Claude Code