Skip to content

[finding] field-value.zod.ts docblock over FILE_REFERENCE_TYPES still says the stored schema "deliberately admits both until D3 lands" — the classifier has admitted only the sys_file id since D3 wave 2 PR-5a (17.0.0) #15769

Description

@claude

Found while measuring #15041 (the FILE_REFERENCE_TYPES column fork). Out of scope there: #15041 is a measurement card and does not edit field-value.zod.ts. Filed unassigned; observation class, no severity asserted.

The stale sentence

Measured on origin/main 8e500f23e (2026-09-05T06:58Z), packages/spec/src/data/field-value.zod.ts:

  • :177-181 — the docblock over FILE_REFERENCE_TYPES still reads: "Stored form TODAY is the legacy inline metadata object ({url, name?, size?, ...}) or an opaque file-id/url string; ADR-0104 D3 (file-as-reference) narrows this to a sys_file id. The stored schema below deliberately admits both until D3 lands."
  • :515-522 — the classifier branch if (FILE_REFERENCE_TYPES.has(t)) returns FileReferenceIdValueSchema for form === 'stored' and the [FileReferenceIdValueSchema, FileValueSchema] union only for 'expanded'.
  • :411FileReferenceIdValueSchema is z.string().regex(...) (id-shaped, 1-64 word characters or hyphen).

valueSchemaFor({ type: 'file' }, 'stored').safeParse(...) on the same ref, run through both the source and the built dist/data/index.mjs (verdicts byte-identical): an inline {url, name, size} object is REJECTED ("Invalid input: expected string, received object"), a bare URL is REJECTED ("Expected an opaque sys_file id"), a sys_file id is OK. Same verdicts for all five members. The spec's own pin says so too: field-value.test.ts "D3 wave 2: the STORED media form is an opaque sys_file id" (bad({ type: 'file' }, { url: ..., name: ..., size: 1024 })).

So "deliberately admits both until D3 lands" has been false since D3 wave 2 PR-5a (fe67e34, spec 17.0.0, changelog: "The stored form of a media field narrows to an opaque sys_file id"). What the stored schema admits is the id; the object is the expanded READ form. The sentence is load-bearing prose: #15041 was filed on it ("the spec's own class doc states both at once"), and its triage quoted it as current.

Sibling: FileLikeValueSchema (:425, "the TRANSITIONAL union that was the stored contract before wave 2", @deprecated) has zero consumers outside this file (git grep FileLikeValueSchema -- 'packages/**/src/**' hits only its definition; the same grep for FileValueSchema finds objectql/src/engine.ts and spec/src/contracts/approval-service.ts, so the zero is a reading).

What a fix looks like

Rewrite the :177-181 docblock to state the shipped contract (stored = FileReferenceIdValueSchema; expanded = the union; the runtime admission of legacy values is the warn-first posture in objectql/src/validation/record-validator.ts, not the schema), and decide whether the unconsumed FileLikeValueSchema stays exported. packages/spec docblocks land in content/docs/references/, so gen:schema && gen:docs ride along.

Not a behaviour change; the classifier is correct as shipped.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions