What happens
Every boot of examples/app-showcase on a brand-new empty database:
[value-shape] cover has an invalid image value: Expected an opaque sys_file id — accepted for now
(ADR-0104 warn-first; run `os migrate files-to-references --apply` to migrate this deployment and enforce)
WARN [migration] NOT attesting 'adr-0104-file-references' on this new datastore: this boot already wrote
10 value(s) that the migration's own contract rejects (showcase_task.cover: Expected an opaque sys_file id).
The store was created empty, but it is no longer empty and what it now holds contradicts the claim —
the gate stays open (warn-first). Fix the data, then run `os migrate files-to-references --apply` to
close it on real evidence (ADR-0104).
Why it happens
showcase_task.cover is Field.image() (src/data/objects/task.object.ts:76),
and ADR-0104 requires an opaque sys_file id as its value.
The seed instead stores an inline SVG data URI
(src/data/seed/index.ts, placeholderCover()):
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
10 task rows carry one.
The helper's own docblock explains the motivation, and it is a good one:
Task cover seeds used to point at picsum.photos, which renders as a wall of
broken images in offline/restricted-network environments (Gallery, All Views).
A data: URI needs no network at all…
So this is a sound fix for the offline-images problem that happens to collide
head-on with ADR-0104's value contract. Both constraints are legitimate; the seed
currently satisfies one by violating the other.
Why it's worth fixing rather than tolerating
The interesting consequence is not the warning — it is the second line. ADR-0104's
attestation is designed to close automatically on a new store, on the
reasoning that a store created empty has no legacy values to migrate. The
showcase's own seed falsifies that in the same boot, so:
- a fresh install of the reference app can never auto-attest
adr-0104-file-references; the gate stays open on day one,
- the printed remedy (
os migrate files-to-references --apply) is aimed at
migrating legacy deployments, and here it would be run against data our own
seeder just wrote,
- anyone copying the showcase's image-seeding pattern inherits the same stuck gate.
It also means the warn-first gate is permanently noisy in the app most likely to
be someone's first ObjectStack experience, which erodes the signal for the
deployments the gate actually exists to catch.
Suggested direction
Seed the cover through the storage service so cover holds a real sys_file
id — keeping the offline property that motivated the data URI (the SVG bytes can
be registered as a sys_file at seed time; no network needed), and letting a
fresh store attest cleanly.
If seeding real sys_file rows is out of scope for the example, the alternative
is to drop cover from the seed and demonstrate the Gallery cover with an
explicit upload step — but that loses coverage the seed is deliberately providing,
so the first option seems better.
Related to #4888 (other showcase declarations that don't survive to runtime),
though this one is seed data rather than a declaration and its blast radius is
the platform migration gate.
Repro
cd examples/app-showcase
node ../../packages/cli/bin/run.js dev --ui --seed-admin -p 3000 -d file:/tmp/fresh.db
# both lines appear during boot, on an empty DB
Observed on main @ 0e96e46. Found while browser-sweeping showcase + Studio for #4879.
What happens
Every boot of
examples/app-showcaseon a brand-new empty database:Why it happens
showcase_task.coverisField.image()(src/data/objects/task.object.ts:76),and ADR-0104 requires an opaque
sys_fileid as its value.The seed instead stores an inline SVG data URI
(
src/data/seed/index.ts,placeholderCover()):10 task rows carry one.
The helper's own docblock explains the motivation, and it is a good one:
So this is a sound fix for the offline-images problem that happens to collide
head-on with ADR-0104's value contract. Both constraints are legitimate; the seed
currently satisfies one by violating the other.
Why it's worth fixing rather than tolerating
The interesting consequence is not the warning — it is the second line. ADR-0104's
attestation is designed to close automatically on a new store, on the
reasoning that a store created empty has no legacy values to migrate. The
showcase's own seed falsifies that in the same boot, so:
adr-0104-file-references; the gate stays open on day one,os migrate files-to-references --apply) is aimed atmigrating legacy deployments, and here it would be run against data our own
seeder just wrote,
It also means the warn-first gate is permanently noisy in the app most likely to
be someone's first ObjectStack experience, which erodes the signal for the
deployments the gate actually exists to catch.
Suggested direction
Seed the cover through the storage service so
coverholds a realsys_fileid — keeping the offline property that motivated the data URI (the SVG bytes can
be registered as a
sys_fileat seed time; no network needed), and letting afresh store attest cleanly.
If seeding real
sys_filerows is out of scope for the example, the alternativeis to drop
coverfrom the seed and demonstrate the Gallery cover with anexplicit upload step — but that loses coverage the seed is deliberately providing,
so the first option seems better.
Related to #4888 (other showcase declarations that don't survive to runtime),
though this one is seed data rather than a declaration and its blast radius is
the platform migration gate.
Repro
Observed on
main@ 0e96e46. Found while browser-sweeping showcase + Studio for #4879.