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
feat(objectql)!: media value shapes enforce per deployment, once its file migration verified (#3438)
#3438 scheduled the strict flip for "a later minor once telemetry is quiet" —
our telemetry, deciding for their deployments. #3617 built the mechanism that
replaces that: a deployment's own migration flag. This lands the half that flag
actually covers.
A malformed media value now rejects with `invalid_type` instead of warning, but
only where `os migrate files-to-references --apply` has run and passed its
self-check. The legacy forms this rejects — inline `{url, name, …}` blobs, bare
URLs — are exactly what that migration converts, so a verified deployment has
been shown to hold none, while an unmigrated one is untouched rather than having
every media update start failing on upgrade.
## Only media, deliberately
#3438 packaged three things as one flip, and the flag covers one of them. It
asserts "this deployment's FILE values are migrated and reconciled". It says
nothing about whether a `lookup` id or a `location` payload is well formed, and
nothing at all about D2's action parameters. Gating those on it would be
borrowing evidence for a fact it does not cover — an authority answering a
question it was not asked, which is the same shape as the read-resolver defect
#3617 fixed one layer down. Reference and structured-JSON classes keep their
own warn-first rollout until something can vouch for them.
`OS_DATA_VALUE_SHAPE_STRICT_ENABLED` is unchanged (still opts every class in,
still forces media strict on an unmigrated deployment). New escape hatch
`OS_ALLOW_LAX_MEDIA_VALUES=1` re-opens media on a verified deployment; when both
are set the lenient one wins, because a warning nobody reads costs less than an
app that stops writing.
## Cost
The fact lives in the database while the validator is synchronous and per-write,
so the engine reads it once and memoizes — and stays dormant unless the written
object declares a media field, mirroring the rule the storage module already
states. One query per process for apps that store files, zero for those that
do not. Every way of not knowing (no storage service, no row, unreadable table,
malformed row) answers "not verified": a deployment whose evidence cannot be
read keeps writing rather than starting to reject.
Verified end-to-end on showcase + SQLite against one database: the same write
was accepted before the migration, rejected with `invalid_type` after it, and
accepted again under OS_ALLOW_LAX_MEDIA_VALUES.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9uWWyKq6pNPQthwCXL8ma
Copy file name to clipboardExpand all lines: content/docs/deployment/cli.mdx
+17-4Lines changed: 17 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -545,18 +545,31 @@ field instead.
545
545
546
546
The run then reconciles what records actually hold against what `sys_file`
547
547
records as each file's owner. Zero blocking discrepancies is what records the
548
-
flag — and that flag, not the version number, is what later enables features
549
-
that act irreversibly on migrated data (reclaiming the bytes of released files;
550
-
rejecting rather than warning about legacy media values). Never running it is
551
-
safe: files are simply retained forever.
548
+
flag — and that flag, not the version number, is what enables behaviour that
549
+
depends on the data actually being migrated. Never running it is safe: files
550
+
are simply retained forever, and media values keep warning instead of failing.
552
551
553
552
Exit status is `0` only when the self-check passes, so CI can gate on it.
554
553
554
+
#### What the flag turns on
555
+
556
+
| Once verified | Effect |
557
+
| :--- | :--- |
558
+
|**Media value shapes**| A malformed `file` / `image` / `avatar` / `video` / `audio` value is **rejected** (`400 invalid_type`) instead of warned about. Set `OS_ALLOW_LAX_MEDIA_VALUES=1` to re-open leniency while diagnosing. |
559
+
|**Released-file collection**| Not yet shipped — the flag is the gate it will read. |
560
+
561
+
Other value classes are unaffected: a `lookup` or `location` value keeps its own
562
+
warn-first rollout, because this migration is evidence about *file* values and
563
+
says nothing about theirs.
564
+
555
565
<Callouttype="warn">
556
566
A dry run writes **nothing** — not the conversions, and not the flag either,
557
567
even when the self-check would pass. `--apply` is the only writing mode. A
558
568
later run that *fails* its self-check clears the flag's verified state, so a
559
569
database that has drifted closes its own gate.
570
+
571
+
A running server reads the flag once; after migrating, **restart it** for
0 commit comments