content/docs/permissions/attachments-access.mdx:19-21 tells a reader that Field.file / Field.image store a file URL in the record's own column:
Field.file / Field.image are a separate path — those store a file URL
in the record's own column and never create a sys_attachment row, so nothing
on this page applies to them.
The second half is correct and is the sentence's actual job (no sys_attachment row, so the page does not apply). The stored form in it is stale: since ADR-0104 D3 the stored value is an opaque sys_file id, not a URL.
The probe
packages/spec/src/data/field-value.zod.ts is the declaring surface, and it says the opposite in two places:
valueSchemaFor gives every member of FILE_REFERENCE_TYPES the FileReferenceIdValueSchema in its stored form (the expanded form is the union with the metadata object).
isFileIdToken's own docblock, verbatim: "A minted id is uuid/nanoid-shaped: word characters and -, nothing else. A URL — https://…, /api/…, data:…, blob:… — always carries a :, / or . and so can never match."
So on any deployment past os migrate files-to-references --apply, the value in that column is an id and cannot be a URL. A URL survives only as a legacy value on a deployment that has not run the migration — which content/docs/protocol/objectql/types.mdx states correctly, and conditionally, in its own callout:
Deployments predating the file-as-reference migration may still hold the inline metadata object (or a bare URL) as the stored value. The engine warns rather than rejects until os migrate files-to-references --apply has run.
⇒ The two pages state the same fact with opposite defaults: types.mdx states the post-migration form and scopes the legacy one; attachments-access.mdx states the legacy form unconditionally.
Why it is worth a card rather than a note
It is an error rather than an omission, and it is load-bearing on this page specifically: the page's whole subject is who may read what, and a reader building or auditing an access rule on "that column holds a URL" gets it wrong on every migrated deployment — including every store created since 17.0, which is attested at birth.
Scope
One clause on one line. ⛔ Deliberately not folded into #15989's PR (#17403): touching content/docs pulls the Build Docs job into that PR's check set, which is a verification surface its diff otherwise does not have, and the driver card is fenced to driver-sql + cli.
Found while spot-checking the doc pages adjacent to #15989; that card's own PR needed no doc edit, and the measurement behind that decision is recorded in its body.
Generated by Claude Code
content/docs/permissions/attachments-access.mdx:19-21tells a reader thatField.file/Field.imagestore a file URL in the record's own column:The second half is correct and is the sentence's actual job (no
sys_attachmentrow, so the page does not apply). The stored form in it is stale: since ADR-0104 D3 the stored value is an opaquesys_fileid, not a URL.The probe
packages/spec/src/data/field-value.zod.tsis the declaring surface, and it says the opposite in two places:valueSchemaForgives every member ofFILE_REFERENCE_TYPEStheFileReferenceIdValueSchemain its stored form (the expanded form is the union with the metadata object).isFileIdToken's own docblock, verbatim: "A minted id is uuid/nanoid-shaped: word characters and-, nothing else. A URL —https://…,/api/…,data:…,blob:…— always carries a:,/or.and so can never match."So on any deployment past
os migrate files-to-references --apply, the value in that column is an id and cannot be a URL. A URL survives only as a legacy value on a deployment that has not run the migration — whichcontent/docs/protocol/objectql/types.mdxstates correctly, and conditionally, in its own callout:⇒ The two pages state the same fact with opposite defaults:
types.mdxstates the post-migration form and scopes the legacy one;attachments-access.mdxstates the legacy form unconditionally.Why it is worth a card rather than a note
It is an error rather than an omission, and it is load-bearing on this page specifically: the page's whole subject is who may read what, and a reader building or auditing an access rule on "that column holds a URL" gets it wrong on every migrated deployment — including every store created since 17.0, which is attested at birth.
Scope
One clause on one line. ⛔ Deliberately not folded into #15989's PR (#17403): touching
content/docspulls theBuild Docsjob into that PR's check set, which is a verification surface its diff otherwise does not have, and the driver card is fenced todriver-sql+cli.Found while spot-checking the doc pages adjacent to #15989; that card's own PR needed no doc edit, and the measurement behind that decision is recorded in its body.
Generated by Claude Code