Skip to content

fix: enforce maxProperties in generated schemas - #69

Merged
carolinerg1 merged 1 commit into
Universal-Commerce-Protocol:mainfrom
FanouZeng-TT:fix/enforce-max-properties
Sep 4, 2026
Merged

fix: enforce maxProperties in generated schemas#69
carolinerg1 merged 1 commit into
Universal-Commerce-Protocol:mainfrom
FanouZeng-TT:fix/enforce-max-properties

Conversation

@FanouZeng-TT

Copy link
Copy Markdown
Contributor

Description

location_serves.json (UCP release 2026-08-25) declares both bounds for the
service-target map:

"minProperties": 1,
"maxProperties": 1

Its description is unambiguous — "A one-entry map ... The Platform MUST supply
exactly one target form" — but inject-schema-constraints.mjs only carries the
lower bound. CONSTRAINT_KEYS, the descriptor, the object-level index, and the
refine renderer all handle minProperties and nothing else, so the generated
schema lets two representations through:

export const LocationServesSchema = z
  .object({ address: ..., point: ... })
  .catchall(z.any())
  .refine((value) => Object.keys(value).length >= 1, { ... });
// point and address, or point plus an extension key, both parse

Fix: mirror the existing minProperties path for maxProperties — the
constraint keyword, the field-level descriptor, an object-level index with the
same ambiguity guard, and a <= refinement. The object-level splices for both
bounds render through one chained edit, because a .refine(...) result no
longer exposes .catchall; two independently rendered bounds that each prepend
it would throw at parse time. Regenerated against the pinned 2026-08-25
release; LocationServesSchema is the only generated schema that changes.

Before/after on LocationServesSchema:

{}                                        rejected (minProperties, unchanged)
{ point }                                 accepted
{ "com.example/area": "..." }             accepted
{ point, "com.example/area": "..." }      accepted before -> rejected now
{ "com.example/a": "...", "com.example/b": "..." }  accepted before -> rejected now

Category (Required)

  • Core Protocol: Changes to the base communication layer, global context, or breaking refactors. (Requires Technical Council approval)
  • Governance/Contributing: Updates to GOVERNANCE.md, CONTRIBUTING.md, or CODEOWNERS. (Requires Governance Council approval)
  • Capability: New schemas (Discovery, Cart, etc.) or extensions. (Requires Maintainer approval)
  • Documentation: Updates to README, or documentations regarding schema or capabilities. (Requires Maintainer approval)
  • Infrastructure: CI/CD, Linters, or build scripts. (Requires DevOps Maintainer approval)
  • Maintenance: Version bumps, lockfile updates, or minor bug fixes. (Requires DevOps Maintainer approval)
  • SDK: Language-specific SDK updates and releases. (Requires DevOps Maintainer approval)
  • Samples / Conformance: Maintaining samples and the conformance suite. (Requires Maintainer approval)
  • UCP Schema: Changes to the ucp-schema tool (resolver, linter, validator). (Requires Maintainer approval)
  • Community Health (.github): Updates to templates, workflows, or org-level configs. (Requires DevOps Maintainer approval)

Related Issues

N/A

Checklist

  • I have followed the Contributing Guide (including Conventional Commits title requirements and ! for breaking changes).
  • I have updated the documentation (if applicable).
  • My changes pass all local linting and formatting checks.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • (For Core/Capability) I have included/updated the relevant JSON schemas.
  • I have regenerated Python Pydantic models by running generate_models.sh under python_sdk.

Screenshots / Logs (if applicable)

N/A — the before/after matrix in the description is the repro.

@damaz91 damaz91 added the status:needs-triage Signal that the PR is ready for human triage label Sep 3, 2026
@carolinerg1 carolinerg1 added devops status:under-review and removed status:needs-triage Signal that the PR is ready for human triage labels Sep 3, 2026
@carolinerg1
carolinerg1 merged commit dbd0dbe into Universal-Commerce-Protocol:main Sep 4, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants