Skip to content

mimeType "can never coexist" invariant is check-then-act under concurrency #142

Description

@cuibonobo

From docs/design-review-2026-08.md §A5; carries forward F3 from the July assessment, which was never resolved either direction.

Problem

checkAttachmentMimeTypeOnCreate is check-then-create with no storage-level uniqueness backstop, while §Attachments asserts conflicting mimeTypes "are rejected at write time and can never coexist" — and the download resolution's determinism argument (candidate source 3, first-recorded wins) leans on that claim. Two concurrent first uploads of the same bytes with different declared types can both land. Unreachable in practice locally; reachable on a concurrent server — which is what's being built next, so the server would be implementing to a guarantee core doesn't actually provide.

Direction (pick one)

  1. Adapter-level guard — an atomic "create _attachment@1 unless a conflicting-mimeType record exists for this fileId" primitive, same optional-method shape as deleteUnreferencedAttachmentRecords() (the Split SQLite support: native record-adapter-sqlite for Node, browser-only record-adapter-sqljs, and a StackTokenStore interface in core #46 transaction idiom). Honest fix; small contract addition.
  2. Soften the spec claim to best-effort: conflicting records are rejected when detected, first-recorded (by createdAt, ties broken by id) wins at download time regardless. One sentence, no code — but the "contradictory execution claim must not survive in the data" rationale from Served Content-Type is nondeterministic when multiple _attachment records share a fileId — make mimeType a property of the bytes #65 loses some force.

Leaning matters mostly for the server: option 1 means the server inherits the guarantee through the adapter; option 2 means the server documents the same best-effort.

Cross-refs: #65 (mimeType as property), #106, #93 (optional-capability discovery — a new optional adapter method lands in that discussion too), design-review-2026-08 §A5.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions