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
Copy file name to clipboardExpand all lines: content/docs/deployment/cli.mdx
+55-4Lines changed: 55 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -628,6 +628,7 @@ where the data lives.
628
628
| Command | Description |
629
629
|---------|-------------|
630
630
|`os migrate files-to-references`| Convert legacy file-field values to `sys_file` references, verify the ownership ledger, and record the deployment's migration flag |
631
+
|`os migrate value-shapes`| Scan stored reference and structured-JSON field values against the platform's value contract, and record the deployment's migration flag when clean |
631
632
632
633
```bash
633
634
os migrate files-to-references # Dry run: full report, writes nothing
@@ -660,8 +661,9 @@ Exit status is `0` only when the self-check passes, so CI can gate on it.
660
661
|**Released-file collection**| A field file whose one owning record lets go (the field is cleared or the record deleted) is tombstoned into the declared 30-day grace window; re-referencing the id within the window revives it, and after it the platform sweep reclaims the row and its bytes. Unverified deployments keep every released file forever. |
661
662
662
663
Other value classes are unaffected: a `lookup` or `location` value keeps its own
663
-
warn-first rollout, because this migration is evidence about *file* values and
664
-
says nothing about theirs.
664
+
warn-first rollout until `os migrate value-shapes` (below) supplies *their*
665
+
evidence, because this migration is evidence about *file* values and says
666
+
nothing about theirs.
665
667
666
668
<Callouttype="warn">
667
669
A dry run writes **nothing** — not the conversions, and not the flag either,
@@ -675,6 +677,53 @@ delete check re-reads the flag fresh, so a later failing run stops collection
675
677
without a restart.
676
678
</Callout>
677
679
680
+
#### `os migrate value-shapes`
681
+
682
+
The same gate for the **non-media** value classes — references (`lookup`,
683
+
`master_detail`, `user`, `tree`) and structured JSON (`location`, `address`,
684
+
`composite`, `repeater`, `record`, `vector`).
685
+
686
+
```bash
687
+
os migrate value-shapes # Scan: full report, writes nothing
688
+
os migrate value-shapes --apply # Scan, then record the flag if clean (prompts)
689
+
os migrate value-shapes --apply --yes --json # CI / scripts
690
+
os migrate value-shapes --object contact # Restrict to one object (repeatable)
691
+
```
692
+
693
+
**This one converts nothing.** Its sibling rewrites legacy file values because
694
+
the platform narrowed that storage form and therefore owes the conversion; a
695
+
`location` stored as `{latitude, longitude}` instead of `{lat, lng}` is
696
+
*application* data whose correct value only its author knows. So the run reports
697
+
— object, field, type, how many records, sample record ids, and the parse issue
698
+
— and you fix the values (or the code writing them) and re-run until it is
699
+
green. Because there is nothing to convert, `--apply`'s only write is the flag
700
+
row itself.
701
+
702
+
A scan that is **truncated** (by `--max-records`) or that cannot read an object
703
+
fails the gate even with zero violations found: "none in the part we read" is
704
+
not the claim the flag makes.
705
+
706
+
| Once verified | Effect |
707
+
| :--- | :--- |
708
+
|**Reference + structured-JSON value shapes**| A malformed value of those classes is **rejected** (`400 invalid_type`) instead of warned about. Set `OS_ALLOW_LAX_VALUE_SHAPES=1` to re-open leniency while diagnosing. |
709
+
710
+
This flag is deliberately **separate** from the file migration's. That one
711
+
attests that file values were migrated and their ownership reconciled — it says
712
+
nothing about whether a `lookup` id or a `location` payload is well formed, so
713
+
it may not vouch for these classes. A deployment can legitimately have passed
714
+
either without the other.
715
+
716
+
<Callouttype="warn">
717
+
`OS_DATA_VALUE_SHAPE_STRICT_ENABLED=1` turns on **every** value class at once,
718
+
regardless of which migrations this deployment has run. It is the "I already
719
+
know my data" lever, not the route to strictness — the route is running the
720
+
migration that produces the evidence.
721
+
</Callout>
722
+
723
+
Same writing rules as its sibling: a dry run writes **nothing**, `--apply` is
724
+
the only writing mode, a later failing run clears the verified state, and a
725
+
running server reads the flag once — **restart it** after a successful apply.
726
+
678
727
#### A database created by this version needs no migration
679
728
680
729
A deployment whose database the platform **creates from empty** records these
@@ -691,8 +740,10 @@ attests nothing and produces its evidence by running the command, because
691
740
692
741
Importing legacy values into such a deployment is rejected at the write path
693
742
rather than silently accepted. That is the intended outcome; if you must admit
694
-
them temporarily, `OS_ALLOW_LAX_MEDIA_VALUES=1` re-opens leniency, and
695
-
re-running the migration re-establishes the flag from the data itself.
743
+
them temporarily, `OS_ALLOW_LAX_MEDIA_VALUES=1` (media) and
744
+
`OS_ALLOW_LAX_VALUE_SHAPES=1` (references and structured JSON) re-open leniency
745
+
per class, and re-running the corresponding migration re-establishes its flag
0 commit comments