Commit 912496d
Five rule types in `data-protocol.ts` were hand-written interfaces labelled
`(ObjectStack Spec v2.0.1)` while the installed spec was 17.0.0-rc.0. Nothing
bound them to the spec, so fifteen majors of drift accumulated with `tsc` silent
and the comment still vouching for it — the planted-premise failure class
objectstack#4115 was filed for.
They are now `z.input` derivations of the spec's schemas. `z.input`, not
`z.infer`: objectui consumes AUTHORED metadata off `/meta`, before the spec's
defaults and ExpressionInput canonicalization run, so `condition` really is
`string | {dialect, source}` and `active`/`events`/`priority` really can be
absent.
What the copies had drifted into, and what each cost the user — the engine is a
client PRE-CHECK of rules `objectql/src/validation/rule-validator.ts` enforces,
so every one of these is a disagreement with the authority:
- Predicate POLARITY was inverted. The server violates a rule when the
predicate is TRUE; the engine violated it when FALSE. Every spec-authored
`script`/`cross_field` rule got the opposite verdict.
- `conditional` read `condition` + `rules[]` where the spec says `when` +
`then`/`otherwise` → silent no-op, and `otherwise` never ran at all.
- `format` read `pattern` where the spec says `regex` → `undefined.test()`
threw into a catch that reported a VIOLATION, blocking writes the server
accepts.
- Envelope-valued conditions hit `expression.trim()`, threw, and read as
"passes" → silent no-op.
- An absent `active` disabled the rule; an absent `events` threw. Both arrive
absent because the spec defaults them at parse time.
- `initialStates` (objectstack#3165) and `priority` were missing entirely;
`events: 'delete'` was still advertised after objectstack#3184 retired it.
`unique`/`async`/`range` have no spec counterpart — the spec removed the first
two deliberately (uniqueness → a unique index, since SELECT-then-INSERT is racy;
async → the form layer) — and are now @deprecated, with a test proving the
spec's union rejects them, so the comment is load-bearing rather than decorative.
Gates, each mutation-tested: the compile-time pins in
`validation-rule-spec-parity.test.ts` (live because tsconfig.test.json compiles
it, #3009) go TS1360 when a derivation is reverted, and the engine suite goes red
for polarity, envelope coercion, `otherwise`, `initialStates` and the spec
defaults. `ConditionalValidation.then/otherwise` carry one pinned divergence —
the spec's published types erase them to `unknown` (objectstack#4171) — with an
inverted pin that fails the day upstream fixes it.
Canonicity now rides on the import and the gate, not the comment: `grep
"Spec v2.0.1" packages/types/src/data-protocol.ts` is empty, and objectstack#4115's
ledger drops 120 -> 115.
Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent de2e748 commit 912496d
9 files changed
Lines changed: 1594 additions & 712 deletions
File tree
- .changeset
- packages
- core/src/validation
- __tests__
- validators
- types/src
- __tests__
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
0 commit comments