Commit 333769d
* feat(lint): move the views[] visibility-predicate family to the runtime publish gate (#7220)
The four rules that judge a `views[]` conditional-visibility predicate ran on
the three CLI commands only. A `view` written through the runtime publish door
— Studio's designer, REST `/meta`, MCP — was judged by NONE of them, and that
door is the only one most tenants have and the one AI authors use. A predicate
that cannot parse saved clean and then failed OPEN in the console: the element
renders unconditionally, pixel-identical to one carrying no predicate (#5149).
Both registry entries move to `surfaces: CLI_AND_RUNTIME` with
`runtimeTypes: ['view']`, in ONE edit, on the maintainer's 2026-08-10 ruling
and sequenced after #4717's `advisories` channel landed (PR #7435). Six rule
ids cross together: `visibility-predicate-syntax`,
`visibility-predicate-over-budget`, `visibility-bare-identifier`,
`visibility-root-mislayered`, `predicate-path-unresolved` and
`predicate-path-unrooted`.
They move together on purpose. #7214's implementer wired the path rule alone,
measured the result and reverted it: a `view` refused for an unresolvable
predicate PATH while a predicate that does not parse at all walks through the
same door is less predictable than refusing neither. A half-wired wall is worse
than an unwired one, so the family property is now PINNED in
`authoring-rule-wiring.test.ts` — every id on this surface is gated at the
runtime door, or none is — rather than trusted to a prose `surfaceReason` that
goes stale silently. `RUNTIME_VISIBILITY_FAMILY_IS_CLI_ONLY`, the constant that
recorded the CLI-only state as a decision, is deleted with its last user.
Three things were measured rather than assumed:
- The gate needed no dispatch-side change. `runtimeGatedTypes()` is derived
from this registry, `TYPE_TO_STACK_KEY` already mapped `view -> views`, and
`runtime-authoring-gate.ts` passes the written type straight through — its
two `'flow'` literals belong to the gate-local #6285 rule, not to a type
allowlist. Declaring is sufficient; `runtimeGatedTypes()` now returns
`['flow', 'view']`.
- Neither rule needs a stack-wide snapshot. Both read `stack.views` and
`stack.pages` and no other collection — never `objects` — so the previous
`RUNTIME_NEEDS_FULL_SNAPSHOT` reason on `validateVisibilityPredicates` was
describing nothing about this rule. It was the reason a rule got when nobody
measured, which is the #4409/#4463 defect one layer in.
- The door and `os build` agree. `runtime-gate.test.ts` drives the real
dispatch path over an eight-input corpus and asserts the finding sets are
IDENTICAL — id, severity and path — so the move changes WHERE the rules run,
never WHAT they say. Set equality, not "both non-empty": a half-wired wall is
precisely the state where both sides are non-empty and disagree.
`visibility-root-mislayered` is `warning` on every surface, so it does not 422
— it reaches the author through the `advisories` channel on the 2xx save
response. That channel is why this move was allowed to happen at all: moving
the rules before findings could travel back would have run them and discarded
the verdicts, the exact shape #4463 exists to close.
Behaviour change on a public door (a `view` publish carrying one of these
defects is now refused), so it ships a changeset rather than skip-changeset.
Drafts are still never gated and `OS_ALLOW_UNLINTED_METADATA_WRITES=1` remains
the migration hatch.
Fixes #7220
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QpSiahE9sb96neoWajbiQz
* docs(deployment): the runtime publish gate now judges `view` writes too (#7220)
The surface table in `validating-metadata.mdx` was made wrong by the rule move
in this PR, in the two places a reader would actually rely on:
- it stated `flow` is the only metadata type any rule declares at the runtime
publish door, and that "an object, view, page or dashboard save is checked by
the schema parse and by nothing else". Both are now false for `view`;
- the `views[]` visibility-predicate family had no row at all, so the table
could not say what that door does or does not judge about a predicate.
Adds the row with a `✓ᵛ` marker for `view` writes, corrects the footnote to name
both gated types, and records WHY the family crossed together — the property the
wiring guard now pins — since a reader who takes the table as a menu of
independently-wirable rules would draw exactly the conclusion #7220 was filed to
prevent.
The rest of the page was re-read and is unchanged: the "held to the CLI's
verdicts" paragraph, the 422 envelope description and the #6285 runtime-only
exception all remain accurate.
`content/docs/releases/v17.mdx` also references `@objectstack/lint` and is
release-owned — read, left untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QpSiahE9sb96neoWajbiQz
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 36237a1 commit 333769d
6 files changed
Lines changed: 363 additions & 39 deletions
File tree
- .changeset
- content/docs/deployment
- packages/lint/src
Lines changed: 45 additions & 0 deletions
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
391 | 391 | | |
392 | 392 | | |
393 | 393 | | |
| 394 | + | |
394 | 395 | | |
395 | 396 | | |
396 | 397 | | |
397 | 398 | | |
398 | 399 | | |
399 | 400 | | |
400 | | - | |
401 | | - | |
402 | | - | |
403 | | - | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
404 | 406 | | |
405 | 407 | | |
406 | 408 | | |
407 | 409 | | |
408 | 410 | | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
409 | 420 | | |
410 | 421 | | |
411 | 422 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
448 | 448 | | |
449 | 449 | | |
450 | 450 | | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
451 | 500 | | |
452 | 501 | | |
453 | 502 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
351 | 351 | | |
352 | 352 | | |
353 | 353 | | |
354 | | - | |
355 | | - | |
356 | | - | |
357 | | - | |
358 | | - | |
359 | | - | |
360 | | - | |
361 | | - | |
362 | | - | |
363 | | - | |
364 | | - | |
365 | | - | |
366 | | - | |
367 | | - | |
368 | | - | |
369 | | - | |
370 | | - | |
371 | | - | |
372 | | - | |
373 | | - | |
374 | | - | |
375 | | - | |
376 | | - | |
377 | | - | |
378 | | - | |
379 | | - | |
380 | 354 | | |
381 | 355 | | |
382 | 356 | | |
| |||
841 | 815 | | |
842 | 816 | | |
843 | 817 | | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
844 | 849 | | |
845 | 850 | | |
846 | 851 | | |
847 | 852 | | |
848 | 853 | | |
849 | 854 | | |
850 | | - | |
851 | | - | |
| 855 | + | |
| 856 | + | |
852 | 857 | | |
853 | 858 | | |
854 | 859 | | |
| |||
871 | 876 | | |
872 | 877 | | |
873 | 878 | | |
874 | | - | |
875 | | - | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
876 | 884 | | |
877 | 885 | | |
878 | 886 | | |
| |||
0 commit comments