Skip to content

Extend the tool-schema wire-key guard to SchemaRelationship, EdgeField and nested SchemaField items #2836

Closed

Description

@malibio

Summary

PR #2834 added schema_tool_field_keys_are_accepted_schema_field_wire_keys, which round-trips every field-property key create_schema/update_schema declare through the real SchemaField deserializer. That closes the hole #2801 fell through, but only for fields/add_fields item properties.

Three sibling surfaces carry the identical exposure and remain unguarded. No bug is known on any of them today — every key is currently spelled correctly. This is about making that a guarantee rather than luck, since the same class of mistake has now occurred three times (#2788, #2801, #2809).

Why these are exposed the same way

EdgeField (packages/nodespace-types/src/schema.rs:224-226) carries the same #[serde(rename_all = "camelCase", deny_unknown_fields)] pair as SchemaField, and reaches the same handler nested under SchemaRelationship::edge_fields. A wrong key there is rejected identically — a hard unknown field, not a silently-ignored key.

SchemaRelationship is the higher-risk one by count: it declares four multi-word keys (targetType, reverseName, reverseCardinality, edgeFields), each a drift candidate. Single-word keys are spelled the same in both conventions, so multi-word keys are the entire risk surface.

Unguarded surfaces

Surface Declared at Struct
create_schema relationship items packages/agent/src/local_agent/tools.rs:~1387 SchemaRelationship
update_schema relationship items packages/agent/src/local_agent/tools.rs:~1510 SchemaRelationship
edgeFields item schemas (both tools) nested in the above EdgeField

Also not covered: SchemaField's own recursive fields/itemFields (nested SchemaField arrays), which the current guard probes with [] rather than descending into.

Suggested fix

Generalize the existing test rather than copy-pasting it per surface — walk each declared item-schema and round-trip it through its corresponding struct. The probe-value helper and its unknown field discrimination (added in #2834 while addressing review) are already written to be reused.

Note the helper currently understands string/boolean/array/object shapes only; a relationship's direction/cardinality are enum-typed strings, so it will need an arm for those — the unknown field check turns that into an explicit "teach the helper" message rather than a misleading failure, which is the intended workflow.

Complexity estimate

Small — roughly an hour. One test generalization, no production-code change expected unless the sweep turns up an actual misspelling.

Found via

/pragmatic-code-review on PR #2834 (finding 2, Important). The reviewer confirmed all current keys on these surfaces are correct, so this is preventive hardening, not a live defect.

Activity

  1. malibio commented on Sep 25, 2026

    @malibio
    CollaboratorAuthor

    Frontend baseline: 5292 passed, 1 failed (architecture-benchmarks.test.ts render-scaling, known machine-load flake)

  2. self-assigned this
    on Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions