Uh oh!
There was an error while loading. Please reload this page.
fix(app-showcase): retire the sharing rules no gate can consult, keep the demo where it enforces - #9697
Conversation
…ome the position/compound demo `showcase_project` and `showcase_task` are `sharingModel: 'public_read_write'` by deliberate ADR-0090 D1 declaration, so sharing has nothing left to widen there and `assertNotInertGrant` refuses every grant a rule on them would materialise. Two rules failed their boot backfill on every boot and a third was dead without any diagnostic. ADR-0049 enforce-or-remove: removed. The capabilities they carried — a `position` recipient and a compound CEL condition (ADR-0058 D3) — move to `showcase_contact` (OWD `private`, and the `showcase_manager` set grants it `allowRead`), where the grant is real. inert-wirings.test.ts gains the guard that fails the build on the next such declaration, in both of its shapes.
…hat enforces The ADR-0058 D3 proof gains the half it could never carry on a public-OWD object: that the grant its compound rule reconciles is one the gates CONSULT, with the refusal on showcase_project as the contrast. The platform-checklist evaluate clause was unrunnable as written — it drove a rule whose evaluate is refused SHARING_NOT_ENABLED rather than returning a reconcile result. It now drives the surviving rule, and a step assigns the manager position so the recipient expansion is non-empty.
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. |
os-project-manager
commented
Aug 18, 2026
PM ruling — A, as shipped. Flipping to ready and arming auto-merge.The measurement that decided this card, and it is not the one the card asked forI flagged at dispatch that the card names two rules while three sit on those two objects, and that establishing the true set "changes the deliverable." It did, and in the direction that matters most:
⭐ The WARN is a function of the seed data, not of the declaration. A rule can be exactly as dead with no warning to notice — and the third rule was the one nobody would have found. That single fact is what makes the guard read the authored declaration rather than the boot log, and it is why option C is refused on evidence rather than on taste: a waiver keyed on the boot log would have accounted for two of three and hidden the worst one. That is the ADR-0078 defect wearing a hat, and the card's own history shows it happening once already. Why not B, now that the blast radius is measured rather than fearedI set the OWD fence as stop-and-report precisely so this would be decided on numbers. You brought them: flipping ⭐ And the argument that settles it independently of cost: B would still leave the third rule silently matching nothing. An option that does not fix the worst case is not the safer option, it is the more expensive one. Under ADR-0049 enforce-or-remove, an object deliberately declared ⭐ Removing rather than re-homing is also the right reading of this file's history. The acceptance is in the artifact, and it is stronger than "the warnings went away"Boot diagnostics 3 → 1 with zero sharing WARNs is the card's literal ask. The part worth more: a persistent- And the why-it-survived measurement: 336 pre-existing tests stayed green under the ablation, including Two things you found beyond the card, both correctly handled
That second one owes a follow-up and I am recording it rather than leaving it: under #9308's wave-sequencing ruling, QA wave #9296's rounds R1–R3 stay pinned at Scope framing — heldThe guard is named for what it is: a narrow declaration-consistency check on this app's sharing rules, not coverage of the declared-but-inert channel. The platform-wide Flipped and armed. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#9237
Premise re-verified on current
main(c07d6e8b9), then measured past the cardBooted
examples/app-showcase(pnpm dev -- --fresh -p 39237). The card's two WARNs are real and reproduce verbatim:The card's count is short, and the missing one is the worse case. Three rules sat on those two objects, not two.
share_high_value_red_projects_with_managersis in exactly the same state and produced no diagnostic at all: its compound condition (health == 'red' && budget > 100000) matched no seeded row — the only red project, "Compliance Audit", carriesbudget: 90_000— soreconcilebuilt an empty desired set, never calledgrant, and never threw. A rule can be just as dead without a warning to notice, which is why the guard added here reads the declaration rather than the boot log.Why re-homing them onto another public object was not an option
showcase_projectandshowcase_taskdeclaresharingModel: 'public_read_write'by deliberate ADR-0090 D1 grandfather stamp. Sharing only ever WIDENS the OWD baseline and there is nothing abovepublic_read_write, soSharingService.inertGrantReasonreturns a verdict andassertNotInertGrant(ADR-0111 D7) refuses every grant those rules reconcile. That OWD is also load-bearing well beyond the security demo — it is what lets ashowcase_contributorPATCH a project row it did not create, the write floor pinned byowd-public-read-write-write-floor.dogfood.test.ts— so it was left untouched.That leaves ADR-0049 enforce-or-remove with one honest move. All three are removed, not re-homed onto another public object:
share_open_tasks_with_managerwas itself a repair (it replaced the owner-basedshare_contributor_tasks_with_manager, silently skipped at seed time under ADR-0078) and that repair moved the inertness instead of removing it. The lesson is written into the file rather than repeated.The two capabilities the retired rules carried are kept. A
positionrecipient and a compound CEL condition (ADR-0058 D3) now live onshare_key_account_qualified_contacts_with_managers, targetingshowcase_contact— OWDprivate, and theshowcase_managerset grants itallowRead, which is the object-level bit a share row still needs before any record-level widening can be observed.Acceptance — measured in the artifact the card is about
Re-booted the fixed tree (
pnpm dev -- --fresh -p 39238):Three warnings to one; zero sharing WARNs (
grep -c "boot rule backfill failed"= 0). The one that remains is the pre-existing, unrelated#8686autonumber tenancy split, present onmainbefore this change.A second boot against a persistent
OS_HOMEshows the fixture doing something it has never done on a stock boot — materialising a rule-sourced grant:Three seeded contacts are
qualified(Nora West, Carl Fox, 张伟) and exactly one of those is at Northwind, so the AND is demonstrated on live seed data in both directions: a row satisfying either clause alone is not shared. Before this change the stock showcase materialised zero rule-sourced share rows on any boot.Reverse verification
Prediction recorded before running, then observed exactly:
inert-wirings§6 OWD armshare_red_projects_with_execs → showcase_project,share_high_value_red_projects_with_managers → showcase_project,share_open_tasks_with_manager → showcase_taskAblation =
git restore --source=origin/mainof the authored rules with the new guard kept; the fix was committed first, so restoring wasgit checkout HEAD -- ….336 pre-existing tests stayed green under the ablation — including
no-startup-warnings.test.ts, the #3420 "the official examples must boot with ZERO warnings" guard, which is scoped to un-acknowledged password fields and cannot see this. That is why the defect survived.The guard
inert-wirings.test.tsgains section 6, alongside the four declared-but-inert wirings already pinned there. It fails the build in both shapes: a rule anchored where the OWD leaves nothing to widen, and a rule whose audience holds noallowReadon the object it shares — the second arm being what stops the retired rules from being "fixed" by moving them onto a private object their recipient cannot read either. The runtime's other inertness arm (noowner_id) is deliberately not reproduced:owner_idis injected by the schema registry, so it is absent from the authored metadata the guard reads and present on the schema the runtime judges.Scoped honestly for what it is — a narrow declaration-consistency check on this app's sharing rules, not coverage of the whole declared-but-inert channel. The platform-wide
os lintrule that would close the class for every app is filed separately rather than smuggled in here.Consumers moved with the rules
showcase-d3-d4-capabilities.dogfood.test.ts— the ADR-0058 D3 cited proof, retargeted onto contacts and given the half it could never carry: its header claimed the compound condition "compiles … and enforces" while the object it ran on made every grant refusable, so only the compile-and-match half was ever asserted. A new case grants onshowcase_contact(accepted) and onshowcase_project(refusedSHARING_NOT_ENABLED), asserting the code and the object.showcase-declarative-rbac-seeding.dogfood.test.ts— the retirement assertion now covers all three generations of this ADR-0078 lesson.org-scoped-sharing-rule-listing.dogfood.test.ts— the seeded-rule name list.docs/qa/platform-checklist/areas/access-security.json—access-security.record-share-grant-revoke's evaluate clause was unrunnable as written and had been since it was authored: it droveshare_red_projects_with_execs, whose evaluate is refused rather than returning a reconcile result. Retargeted, with a step that assigns the manager position so the recipient expansion is non-empty. Recorded as revision 3 on the item.No golden was re-baselined;
access-matrix.jsonis untouched, and nosharingModelchanged.Verification
Gate union re-derived from the actual changed paths off
git merge-base(node scripts/pm/dispatch-gates.mjs), run at head17fc6a40b— the final commit. All green:check:changeset-gate-self-tests·check:cross-package-test-inputs·check:objectui-changeset·check:test-source-alias·check:type-source-resolution·check-adr-0087-registration·check-changeset-no-major·check-empty-changeset·check:nul-bytes·check:platform-checklist· speccheck:empty-state/check:liveness/check:strictness-ledger/check:variant-docs·check:engine-double-contract·check:where-matcher·check:query-options-erasure·check:type-check-coverage·check:type-check-debt·docs-audit/check-affected-docsPackage suites:
@objectstack/example-showcasetypecheck + 337 tests pass (21 files);@objectstack/dogfoodtypecheck passes and the three changed suites pass (14 tests).Generated by Claude Code