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
docs(cli): document os migrate value-shapes alongside its sibling
The docs-drift check on the command's own PR flagged content/docs/deployment/cli.mdx,
and that one was a real gap rather than package-level noise: the file documents
`os migrate files-to-references` in full, so shipping a second gated data
migration without an entry would have left it discoverable only by reading the
source.
Covers the deliberate asymmetry (this run converts nothing — a malformed
`location` is application data whose correct value only its author knows), the
truncation rule (a partial scan cannot open the gate), and why the flag is
separate from the file migration's rather than reusing it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016zgA8CQMJeJbFEjnbib1Uv
Copy file name to clipboardExpand all lines: content/docs/deployment/cli.mdx
+44Lines changed: 44 additions & 0 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
@@ -659,6 +660,49 @@ Exit status is `0` only when the self-check passes, so CI can gate on it.
659
660
|**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. |
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
663
+
#### `os migrate value-shapes`
664
+
665
+
The same gate for the **non-media** value classes — references (`lookup`,
666
+
`master_detail`, `user`, `tree`) and structured JSON (`location`, `address`,
667
+
`composite`, `repeater`, `record`, `vector`).
668
+
669
+
```bash
670
+
os migrate value-shapes # Scan: full report, writes nothing
671
+
os migrate value-shapes --apply # Scan, then record the flag if clean (prompts)
672
+
os migrate value-shapes --apply --yes --json # CI / scripts
673
+
os migrate value-shapes --object contact # Restrict to one object (repeatable)
674
+
```
675
+
676
+
**This one converts nothing.** Its sibling rewrites legacy file values because
677
+
the platform narrowed that storage form and therefore owes the conversion; a
678
+
`location` stored as `{latitude, longitude}` instead of `{lat, lng}` is
679
+
*application* data whose correct value only its author knows. So the run reports
680
+
— object, field, type, how many records, sample record ids, and the parse issue
681
+
— and you fix the values (or the code writing them) and re-run until it is
682
+
green. Because there is nothing to convert, `--apply`'s only write is the flag
683
+
row itself.
684
+
685
+
A scan that is **truncated** (by `--max-records`) or that cannot read an object
686
+
fails the gate even with zero violations found: "none in the part we read" is
687
+
not the claim the flag makes.
688
+
689
+
| Once verified | Effect |
690
+
| :--- | :--- |
691
+
|**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. |
692
+
693
+
This flag is deliberately **separate** from the file migration's. That one
694
+
attests that file values were migrated and their ownership reconciled — it says
695
+
nothing about whether a `lookup` id or a `location` payload is well formed, so
696
+
it may not vouch for these classes. A deployment can legitimately have passed
697
+
either without the other.
698
+
699
+
<Callouttype="warn">
700
+
`OS_DATA_VALUE_SHAPE_STRICT_ENABLED=1` turns on **every** value class at once,
701
+
regardless of which migrations this deployment has run. It is the "I already
702
+
know my data" lever, not the route to strictness — the route is running the
703
+
migration that produces the evidence.
704
+
</Callout>
705
+
662
706
Other value classes are unaffected: a `lookup` or `location` value keeps its own
663
707
warn-first rollout, because this migration is evidence about *file* values and
0 commit comments