Found while measuring objectstack-ai/objectstack#15041 (how far ADR-0104 D3 file-as-reference has got). Observation class; filed unassigned, no severity asserted.
Blocked-by: objectstack-ai/objectstack#15041 — whether this fallback is retired or kept is a consequence of the D3 decision that card feeds, not a decision this card can take alone.
The path
Measured on objectui main a472b07 (2026-09-05T06:58Z), packages/fields/src/widgets/file-value.ts:
:22-29 (docblock "Submitting"): "When the upload adapter surfaced a fileId, the widget submits the bare id — the reference form. When it did not (the object-URL fallback adapter, an older backend), it submits the legacy blob unchanged."
:185-198 fileValueForSubmit(result, originalName): returns fileId when isFileIdToken(result.meta.fileId), otherwise { name, original_name, size, mime_type, url }.
That second branch is the one client path in either repo that still PRODUCES the pre-D3 inline object for a record field value. On the backend, the stored contract has been id-only since spec 17.0.0 (valueSchemaFor(field, 'stored') returns FileReferenceIdValueSchema), and the write path admits the object only warn-first — measured on objectstack 8e500f23e: validateRecord ADMITS {url, name, size} with a [value-shape] warning on a deployment that has not run os migrate files-to-references --apply, and REJECTS it (invalid_type) once the deployment's adr-0104-file-references flag is recorded or OS_DATA_VALUE_SHAPE_STRICT_ENABLED=1 is set. So against a verified deployment this fallback turns an upload into a rejected save.
providers/src/UploadProvider.tsx:268-290 (the presigned flow) always carries a fileId and POSTs /upload/complete, so today the branch fires only for an adapter that does not go through that flow (the object-URL fallback named in the docblock).
Question for triage
Which adapters still reach the legacy branch against a real backend, and is a dual-shape submit worth keeping now that the backend's stored form is settled? Under the maintainer's 2026-08-27 ruling on transitions (no staged windows at this stage) the default answer would be to retire the blob branch and make a missing fileId a loud upload error; the alternative is to keep it until every deployment has verified its file migration. Either way, the decision belongs with objectstack#15041's fork; this card only records that the producer exists.
Generated by Claude Code
Found while measuring objectstack-ai/objectstack#15041 (how far ADR-0104 D3 file-as-reference has got). Observation class; filed unassigned, no severity asserted.
Blocked-by: objectstack-ai/objectstack#15041 — whether this fallback is retired or kept is a consequence of the D3 decision that card feeds, not a decision this card can take alone.
The path
Measured on objectui
maina472b07(2026-09-05T06:58Z),packages/fields/src/widgets/file-value.ts::22-29(docblock "Submitting"): "When the upload adapter surfaced afileId, the widget submits the bare id — the reference form. When it did not (the object-URL fallback adapter, an older backend), it submits the legacy blob unchanged.":185-198fileValueForSubmit(result, originalName): returnsfileIdwhenisFileIdToken(result.meta.fileId), otherwise{ name, original_name, size, mime_type, url }.That second branch is the one client path in either repo that still PRODUCES the pre-D3 inline object for a record field value. On the backend, the stored contract has been id-only since spec
17.0.0(valueSchemaFor(field, 'stored')returnsFileReferenceIdValueSchema), and the write path admits the object only warn-first — measured on objectstack8e500f23e:validateRecordADMITS{url, name, size}with a[value-shape]warning on a deployment that has not runos migrate files-to-references --apply, and REJECTS it (invalid_type) once the deployment'sadr-0104-file-referencesflag is recorded orOS_DATA_VALUE_SHAPE_STRICT_ENABLED=1is set. So against a verified deployment this fallback turns an upload into a rejected save.providers/src/UploadProvider.tsx:268-290(the presigned flow) always carries afileIdand POSTs/upload/complete, so today the branch fires only for an adapter that does not go through that flow (the object-URL fallback named in the docblock).Question for triage
Which adapters still reach the legacy branch against a real backend, and is a dual-shape submit worth keeping now that the backend's stored form is settled? Under the maintainer's 2026-08-27 ruling on transitions (no staged windows at this stage) the default answer would be to retire the blob branch and make a missing
fileIda loud upload error; the alternative is to keep it until every deployment has verified its file migration. Either way, the decision belongs with objectstack#15041's fork; this card only records that the producer exists.Generated by Claude Code