Skip to content

[finding] three live consumers still read reference_to as a tolerated alias of reference — the fourth and fifth doors #11567's "one key, one answer" never reached #13250

Description

@os-zhuang

Found while measuring #13222 (driver-mongodb's lookup index gate). Filed unassigned, out of scope for that card's PR.

What is there

#11567 landed the ruling that reference is the only relationship spelling @objectstack/spec declares, and reference_to is a rejected aliasFieldSchema answers unrecognized_keys with "Did you mean reference_toreference?". Its changeset put it as "One key, one answer, on both doors." It closed the authoring door and the SQL DDL door.

Three other live consumers still read the rejected alias as an accepted fallback:

file line reader
packages/lint/src/data-model-rules.ts 167 return def?.reference || def?.reference_to;
packages/plugins/plugin-security/src/security-plugin.ts 5846 const ref = (f) =. f?.reference ?? f?.reference_to ?? f?.referenceTo;
packages/verify/src/derive.ts 103 const ref = f?.reference ?? f?.reference_to ?? f?.referenceTo;

(The arrow in the middle row is written =. so the body survives GitHub's sanitizer; the source spells it as a normal arrow function.)

Why this is a defect and not harmless breadth

The repo already made the opposite call one door over, deliberately and in writing. packages/lint/src/validate-security-posture.ts:208 records it:

reference ?? reference_to ?? referenceTo; refOf here accepts only …

— i.e. one lint reader was narrowed on purpose to canonical-only, and the reason is in that file. The three above were not, so the same repo now answers one key two ways depending on which consumer sees it.

Concretely, data-model-rules.ts:167 is a lint rule: it exists to catch authoring mistakes, and it currently treats a field spelled reference_to as having a valid relationship target. So the one component whose job is to tell an author their metadata is wrong is the component that accepts the wrong spelling.

This is the shape the platform's own contract-first rule names: a tolerant consumer is where AI-authored metadata mistakes hide and spread. reference_to is exactly a key AI authors reach for — the published @objectstack/driver-mongodb README taught it until #13224 (in flight).

Measured

FieldSchema.safeParse({ name:'company_id', type:'lookup', reference_to:'company' })
  success: false
  code: unrecognized_keys
  message: Unrecognized key(s) on this field: `reference_to`. Did you mean
           `reference_to` → `reference`? Until this shape was closed these were
           dropped silently — the field was still created, minus whatever the
           key was meant to constrain, protect or compute.

FieldSchema.safeParse({ name:'company_id', type:'lookup', reference:'company' })
  success: true

Run against @objectstack/spec@dist built from 9e0ba21a1.

Not proposed here

Whether to narrow all three, or to narrow some and keep a documented tolerance where stored legacy metadata is genuinely in play, is a triage call — each reader has a different population. verify/src/derive.ts and security-plugin.ts may be reading raw registered metadata (registerObject deliberately skips Zod, #3896), which is the one population where the alias can actually appear; data-model-rules.ts is a lint rule over authored source, where it cannot.

Related

#11567 (the ruling) · PR #12287 (where it landed) · #13222 (driver-mongodb's own copy of the same defect) · #13224 (removing the README that taught the key)


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions