Skip to content

docs(permissions): attachments-access states the stored form of a file field as the sys_file id - #17695

Merged
os-bill merged 1 commit into
mainfrom
claude/issue-17406-attachments-access-stored-form
Sep 11, 2026
Merged

docs(permissions): attachments-access states the stored form of a file field as the sys_file id#17695
os-bill merged 1 commit into
mainfrom
claude/issue-17406-attachments-access-stored-form

Conversation

@os-bill

@os-bill os-bill commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Part of #17406

content/docs/permissions/attachments-access.mdx told a reader that Field.file / Field.image store a file URL in the record's own column. Since ADR-0104 D3 the stored value is an opaque sys_file id; the { id, name, size, mimeType, url } object is the derived read form. Only that stored-form clause changes.

  • Clause-②: no

What changed

-`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.
+`Field.file` / `Field.image` are a **separate** path — those store an opaque
+`sys_file` id in the record's own column (ADR-0104 D3; the
+`{ id, name, size, mimeType, url }` shape is derived at read time, never
+stored) and never create a `sys_attachment` row, so nothing on this page
+applies to them.

The premise, re-measured on origin/main (6465cc0) rather than inherited

ADR-0104 D3, verbatim (docs/adr/0104-field-runtime-value-shape-contract.md, section ### D3 — File-as-reference: field values point into sys_file):

  • Stored form: an opaque fileId string (array when multiple) into
    sys_file — the same shape discipline as lookup. The inline
    {url, name, size} blob is retired from the write path.
  • Expanded form: a spec-owned FileValueSchema
    { id, name, size, mimeType, url }, produced at read/expand time from the
    sys_file row. url is derived, never stored

D3 wave 2 restates it: "File field value becomes an opaque sys_file id; the expanded read form is the spec-owned FileValueSchema (url derived via /files/:fileId, never stored)."

The declaring surface agrees. packages/spec/src/data/field-value.zod.ts:551-557 returns FileReferenceIdValueSchema alone for form === 'stored', and its FILE_REFERENCE_TYPES docblock 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_attachment row, 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 via grep -o | wc -l, not grep -c):

reading before after
never create a + backtick-sys_attachment-backtick + row, so nothing on this page applies to them 1 1
stores? (a|the) file URL 1 0
URL in the record'?s own column 1 0
store an opaque + backtick-sys_file-backtick + id in the record's own column 0 1
dark control (impossible token) 0 0

Census — 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 .mdx files under content/docs/**, enumerated with git 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:

pattern occurrences carriers
stores? (a|the) file URL 1 permissions/attachments-access.mdx
URL in the record'?s own column 1 permissions/attachments-access.mdx
(file|image) (field|column)…stores?…URL 0
stores? the URL 0
column…holds?…URL 0
(stored )?value is (a|the) URL 0
lit control Field.file 4 this page + releases/v14, v15, v16
lit control sys_file 25 15 files
lit control ADR-0104 26 13 files
dark control (impossible token) 0

The 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.file mentions in content/docs/releases/v14|v15|v16.mdx make no stored-form claim — they are feature notes (FILES_DISABLED independence, 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-1168 states 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.ts returns @objectstack/spec, so a zero from it is a reading. content/ is covered by no pnpm-workspace.yaml glob and is owned only by the root manifest, which is private: true. The skip-changeset label 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 with node 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

…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 os-bill added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 11, 2026 — with Claude
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Sep 11, 2026
@os-bill
os-bill marked this pull request as ready for review September 11, 2026 15:06
@os-bill
os-bill enabled auto-merge September 11, 2026 15:06
@os-bill
os-bill added this pull request to the merge queue Sep 11, 2026
Merged via the queue into main with commit d82da04 Sep 11, 2026
37 checks passed
@os-bill
os-bill deleted the claude/issue-17406-attachments-access-stored-form branch September 11, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants