docs(permissions): attachments-access states the stored form of a file field as the sys_file id - #17695
Merged
Conversation
…column
attachments-access.mdx told a reader that `Field.file` / `Field.image` keep a
file URL in the record's own column. ADR-0104 D3 narrowed the stored form to
an opaque `sys_file` id; the `{ id, name, size, mimeType, url }` object is the
derived read form, produced at read/expand time and never stored.
`valueSchemaFor` in packages/spec/src/data/field-value.zod.ts returns
`FileReferenceIdValueSchema` alone for the stored form, so past the
files-to-references backfill the column holds an id. A reader who believed the
column held a URL would dereference it directly and get it wrong.
The sentence's second half — these create no `sys_attachment` row, so nothing
on that page applies to them — is correct, is the sentence's whole job, and is
carried through unchanged.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
os-bill
marked this pull request as ready for review
September 11, 2026 15:06
os-bill
enabled auto-merge
September 11, 2026 15:06
os-bill
deleted the
claude/issue-17406-attachments-access-stored-form
branch
September 11, 2026 15:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #17406
content/docs/permissions/attachments-access.mdxtold a reader thatField.file/Field.imagestore a file URL in the record's own column. Since ADR-0104 D3 the stored value is an opaquesys_fileid; the{ id, name, size, mimeType, url }object is the derived read form. Only that stored-form clause changes.What changed
The premise, re-measured on
origin/main(6465cc0) rather than inheritedADR-0104 D3, verbatim (
docs/adr/0104-field-runtime-value-shape-contract.md, section### D3 — File-as-reference: field values point into sys_file):D3 wave 2 restates it: "File field value becomes an opaque
sys_fileid; the expanded read form is the spec-ownedFileValueSchema(urlderived via/files/:fileId, never stored)."The declaring surface agrees.
packages/spec/src/data/field-value.zod.ts:551-557returnsFileReferenceIdValueSchemaalone forform === 'stored', and itsFILE_REFERENCE_TYPESdocblock says the narrowing is where wave 2 landed.premise_still_valid: true.The half that must not move
The sentence's second half — no
sys_attachmentrow, so nothing on this page applies — is correct and is the sentence's whole job. It is carried through verbatim; only the line wrap moved. Proof (whitespace-flattened, occurrence counts viagrep -o | wc -l, notgrep -c):never create a+ backtick-sys_attachment-backtick +row, so nothing on this page applies to themstores? (a|the) file URLURL in the record'?s own columnstore an opaque+ backtick-sys_file-backtick +id in the record's own columnCensus — is the stale claim copied anywhere else?
A false sentence copied across files is this repo's recurring shape, so the count is measured, not assumed. Universe: 402 tracked
.mdxfiles undercontent/docs/**, enumerated withgit ls-files(⛔ not a content grep for a file name). Each file whitespace-flattened first, because the sentence wraps a line break. Six stale-claim patterns:stores? (a|the) file URLpermissions/attachments-access.mdxURL in the record'?s own columnpermissions/attachments-access.mdx(file|image) (field|column)…stores?…URLstores? the URLcolumn…holds?…URL(stored )?value is (a|the) URLField.filereleases/v14, v15, v16sys_fileADR-0104The zeros are readings: the same instrument returns 4 / 25 / 26 on the lit controls and 0 on the dark one.
A second pass swept every
(file|image|avatar|video|audio) … url …sentence in all 402 files for other wordings of the same claim. It surfaced no further carrier — the remaining hits are unrelated (file:libSQL URLs,os test --url, the storage-service contract) or already correct (this page's own expanded-form sentence; the 17.0 download note).The three
Field.filementions incontent/docs/releases/v14|v15|v16.mdxmake no stored-form claim — they are feature notes (FILES_DISABLEDindependence, inline-grid upload cells, an approvals attachment field). They are also release-owned and out of bounds for a code PR either way.The sibling page is already right and needed no edit:
content/docs/protocol/objectql/types.mdx:1163-1168states the post-migration form and scopes the legacy one to a conditional callout. The two pages now agree instead of stating the same fact with opposite defaults.⇒ Carrier count: 1. Corrected here.
Changeset
None owed, and the rule that says so is AGENTS.md § Post-Task Checklist step 3:
skip-changeset"is for a diff that publishes nothing from any released package."Measured rather than assumed. Of the 80 workspace packages, 70 are non-private; the edited path sits inside 0 of them. Lit control: the same containment predicate run against
packages/spec/src/data/field-value.zod.tsreturns@objectstack/spec, so a zero from it is a reading.content/is covered by nopnpm-workspace.yamlglob and is owned only by the root manifest, which isprivate: true. Theskip-changesetlabel is applied and read back.Verification
Prose-only diff: no schema, no behaviour, no
content/docs/releases/. Gate families derived from the real change set withnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(which derives the change set itself from the merge base) rather than from a hand-written path list.🤖 Generated with Claude Code
https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
Generated by Claude Code