Skip to content

[finding] fileValueForSubmit still submits the legacy inline blob when the upload adapter surfaces no fileId — the one client path still producing the pre-D3 stored shape #7699

Description

@claude

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpm:blockedpriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions