Skip to content

feat(web_core): bind and validate code catalog entries through their documents - #47

Draft
louis-bompart wants to merge 1 commit into
claude/zod4/02-zod4-depfrom
claude/zod4/03-core-reads-documents
Draft

louis-bompart wants to merge 1 commit into
claude/zod4/02-zod4-depfrom
claude/zod4/03-core-reads-documents

Conversation

@louis-bompart

Copy link
Copy Markdown
Collaborator

Description

With a loaded catalog now behaving like its code catalog, this PR makes the core use the JSON for catalogs defined in code too: it reads every entry's schema from the catalog's own toJson() document, the way Catalog.fromJson loads it. A code catalog then behaves exactly like the document it publishes.

  1. entry_schema.ts (internal): componentSchemaOf(catalog, entry) and functionSchemaOf(catalog, fn) return the schema derived from the catalog's document, reloaded once per catalog. An entry loaded from JSON, or whose schema is a JSON Schema object, is returned as is.
  2. NodeResolver, the Lit A2uiController, PayloadValidator, the function argument checks of DataContext, the child reference map and the catalog's function invoker read entries this way.
  3. Code-only checks still run: safeParseEntry validates with the document's schema first, then with the entry's own schema, so a .refine() still applies. A function receives its arguments as its own schema parses them.
  4. Catalog.toJson() writes a child reference whose description was replaced, such as ComponentIdSchema.describe('The child.'), as a $ref to ComponentId or ChildList, so the reloaded catalog still recognizes the child.
  5. mcp: a callMcpTool call with a server argument now fails validation, as the published catalog closes args.

A payload that the document rejects is now rejected even where the Zod schema alone accepted or stripped it. The changelog marks this as breaking.

Validation

  1. yarn build in typescript/core/web_core, then node --test "dist/**/*.test.js": 1316 tests, 0 failing.
  2. node tests/conformance/conformance_test.mjs: every vector passes.
  3. yarn lint in typescript/core/web_core: 0 errors.
  4. yarn build and yarn test in typescript/catalogs/mcp, typescript/catalogs/vegachart, typescript/renderers/markdown-it, typescript/renderers/lit, typescript/renderers/react and typescript/agents/a2ui_agent: all pass.
  5. yarn build in typescript/renderers/angular, tools/composer, tools/editor and tools/inspector. The Angular tests were not run: the local Java is too old for the Closure Compiler step.

Regroups #20.

Part of a2ui-project#2160.

🤖 Generated with Claude Code

…documents

The core now reads the schema of an entry defined in code from its
catalog's own toJson() document, as Catalog.fromJson loads it, so a
code catalog behaves as the catalog it publishes. NodeResolver, the Lit
A2uiController, PayloadValidator, function argument checks, the child
reference map and the function invoker all go through the new
componentSchemaOf and functionSchemaOf.

Validation runs the document's schema first, then the entry's own Zod
schema (safeParseEntry), so refinements only code expresses still run
and functions still receive their arguments as their own schema parses
them. Entries loaded from JSON, and entries whose schema is plain JSON
Schema, are read as before.

The Zod-to-JSON conversions now write a described child reference
(ComponentIdSchema.describe(...), optionally) as a $ref to ComponentId
or ChildList, so the reloaded entry still sees the child.

As a result, callMcpTool rejects a server argument, as its published
catalog closes args.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant