You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(adr): ADR-0104 addendum — the file family's stored column holds the bare sys_file id, switched per deployment on the adr-0104-file-references flag
Records the maintainer's decision-batch #49 item 1 ruling (Option A) as a
2026-09-05 addendum to ADR-0104: the media family's (image / file / avatar /
video / audio) single-value physical column is a string column holding the
bare sys_file id — the generator's VARCHAR(2048) / table.string is the ruled
end-state and the SQL driver moves to it; the encoding switch is per
deployment, keyed on the existing adr-0104-file-references sys_migration row
and never on a version, with the column move as a further step of
`os migrate files-to-references --apply` after zero blocking findings; the
dual-encoding window this implies, its invariant (column type and write
encoding never disagree on one deployment), the three populations it must
hold over, and its end (the first protocol major after the driver lands, with
a loud boot refusal for un-moved deployments); the two confidence gaps
carried from the measurement stated as gaps with what closes them; and the
sequencing behind the driver card.
Governed surface (docs/adr). No code, schema, generated artifact or changeset
moves with this commit. Anchors are symbol / file anchors only.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M59rPZZFzqhfMUPFqqZTkf
Copy file name to clipboardExpand all lines: docs/adr/0104-field-runtime-value-shape-contract.md
+288Lines changed: 288 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1020,3 +1020,291 @@ carries the aliased vocabulary's *coverage* across with its names.
1020
1020
`FileRef` scoped to `file`/`image`/`video`/`audio` would leave `avatar` on
1021
1021
the legacy inline shape, which is precisely the per-type carve-out that
1022
1022
addendum rejected.
1023
+
1024
+
## Addendum (2026-09-05) — the media family's physical column holds the bare `sys_file` id, switched per deployment on the `adr-0104-file-references` flag
1025
+
1026
+
**Provenance.** Maintainer ruling, decision batch #49 item 1, recorded on
1027
+
#15041 (comment `5551135629`) by the director seat from the maintainer's live
1028
+
reply, verbatim: 「15041 应该改为实际 id 保存。选A,其他同意」. The measurement it
1029
+
ruled on is #15041's `os-dev-report` (comment `5550175673`) and its H1 table
1030
+
(comment `5550175730`), taken on `origin/main``8e500f23e` on 2026-09-05. This
1031
+
addendum is step 1 of the ruling's execution order: it records the decisions
1032
+
about the column and the switch; no code moves with it.
1033
+
1034
+
### The fork it closes
1035
+
1036
+
D1 handed the column to the driver in one clause — "DDL column choice remains
1037
+
the driver's decision; the *classification* moves to the spec" — and D3 then
1038
+
narrowed the media family's **stored value** to an opaque `sys_file` id. Every
1039
+
declared D3 wave has landed (spec `17.0.0`); none narrowed the column, because
1040
+
nothing had scheduled that. So two readings of "the value is an id" coexisted
1041
+
on `main`, each internally consistent:
1042
+
1043
+
-**The driver: a JSON-quoted id in a JSON column.**
1044
+
`packages/drivers/driver-sql/src/sql-driver.ts#JSON_COLUMN_TYPES` seeds the
1045
+
family by spreading `FILE_REFERENCE_TYPES`, so
1046
+
`packages/drivers/driver-sql/src/sql-driver.ts#isJsonField` answers true for
1047
+
all five, `packages/drivers/driver-sql/src/sql-driver.ts#formatInput`
1048
+
JSON-stringifies the id on every dialect (the #12380 canonical encoding), and
1049
+
the column is `packages/drivers/driver-sql/src/sql-driver.ts#jsonColumn` —
1050
+
`json` on Postgres and MySQL, TEXT on SQLite. Measured on SQLite (two
1051
+
in-memory cells, 2026-09-05): an id written through the driver lands on disk
1052
+
as the quoted text `"file_01HXYZ"` and reads back as the bare string; an
1053
+
inline object written through the driver reads back as an object; a raw
1054
+
bare id inserted by hand makes the SQLite read arm's `JSON.parse` throw, the
1055
+
catch keeps the raw string, and it reads back as `file_01HXYZ` — no fault.
1056
+
The same four rows in a hand-created `VARCHAR(2048)` column read back
1057
+
byte-identical, and `initObjects` over that column left it `VARCHAR(2048)`:
1058
+
additive sync never alters a column's type. Postgres and MySQL were **not**
1059
+
measured (no live cell in the container); reasoned from the source: the
1060
+
write quotes identically, the read path has no parse arm because those
1061
+
clients parse a native `json` column, so a varchar there returns the quoted
1062
+
text verbatim, `isFileIdToken` refuses it, nothing expands it and nothing
1063
+
claims ownership. The reachable harm of a hand-run generated migration on
1064
+
those dialects is therefore write-side quoting into a varchar — silent — and
0 commit comments