Repository navigation
fix(platform-objects,spec)!: sys_organization no longer declares change_slug, whose door only cloud mounts - #24657
Conversation
…ge_slug, whose door only cloud mounts
The platform object declared `change_slug` at `record_header`, gated on
`multiOrgEnabled`, with a target (`/api/v1/cloud/organizations/{id}/change-slug`)
no package in this repository serves. An open-source multi-organization
composition offered Change Slug and answered `404 ENDPOINT_NOT_FOUND`.
The composition that serves the route declares the action itself, bound to
`sys_organization` by `objectName`, which the registry attaches to the
served object. The four generated locales are regenerated, and
`multiOrgEnabled`'s `gatedInputs` row for the action, the platform objects'
own census, is removed.
Claude-Session: https://claude.ai/code/session_015mj2S1LnzLNur4rJeZuMbN
Co-authored-by: Claude <noreply@anthropic.com>
…s_organization, and a cloud-shaped binding served gated Claude-Session: https://claude.ai/code/session_015mj2S1LnzLNur4rJeZuMbN Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015mj2S1LnzLNur4rJeZuMbN Co-authored-by: Claude <noreply@anthropic.com>
…rrows Claude-Session: https://claude.ai/code/session_015mj2S1LnzLNur4rJeZuMbN Co-authored-by: Claude <noreply@anthropic.com>
…ange-slug-to-cloud
Claude-Session: https://claude.ai/code/session_015mj2S1LnzLNur4rJeZuMbN Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 4 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 143 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin bb1389f0b5efb952c5f320e0e438791bab652344 && git checkout bb1389f0b5efb952c5f320e0e438791bab652344
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin bfc1539fe00a33bc3215614a8d6c76a05eb8e8aa 473c6ff949110fbc6f4c5e12ee3116cc895128a1 && git checkout -B drift-repro bfc1539fe00a33bc3215614a8d6c76a05eb8e8aa && git merge --no-ff 473c6ff949110fbc6f4c5e12ee3116cc895128a1
node scripts/docs-audit/affected-docs.mjs --json bfc1539fe00a33bc3215614a8d6c76a05eb8e8aa
|
Contract reviewServed-tier: ① Derived judgmentsThe removal — right. The diff's three hunks in The cloud-shaped binding — right, with one unstated qualifier. The transition — right. While cloud's pin still carries the platform copy:
The translations — right. Each of the four bundles loses exactly the The pins — right, with one bare deletion and one CI gap. ② Semver level
③ Boundary flags
Implemented-by: VERDICT: FAIL Seat note ·
|
…state, and the no-collision case carries its own positive control Claude-Session: https://claude.ai/code/session_015mj2S1LnzLNur4rJeZuMbN Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: This is a delta review on record 6278606056 (head ① Derived judgmentsThe delta — two hunks and nothing else. The new parenthetical — true, word by word. Line 13 now reads: "A declared action leaves a published platform object, shipped as
Nothing else in either changeset moves. Platform-objects changeset on the head: frontmatter The dogfood pin's positive control — it has teeth, and the right ones. The old precondition
Carry-over. The baseline's ① judgments on the removal, the binding, the transition, ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
席位核对 ·
|
| Item | Reading |
|---|---|
| Shape | Draft PR → main. The body opens Fixes #24318. 16 files, +306/−121. Not governed: check-governed-merges matched 0 of 16 paths. |
| Scope | Shape B of the release 6255698861. sys_organization stops declaring change_slug, whose door exists only in cloud's orchestrator. The four locales lose its keys (regenerated), and multiOrgEnabled.gatedInputs loses its row. Measured: before, open-source multi-org served Change Slug and its click answered 404. After, the record serves only better-auth doors. A cloud-shaped foreign declaration bound by objectName is attached and served once, with the same target, params and lowered multiOrgEnabled gate, in the overflow where the platform copy sat. |
| Seat's own read | The fix commit is two hunks. The parenthetical now matches .changeset/pre.json (exit since c46b5f14cf) and the guard's RC-exemption docblock. The new pin's control asserts the capture saw [ObjectQLPlugin] boot lines, the prefix a collision report carries. The PR body was not edited and needs no patch: its cloud section matches the pointer sent. |
| Review | CONTRACT_REVIEW_TIER. Record 6278606056 was FAIL on ② alone (the changeset's false pre-mode sentence). The delta 6279401940 is PASS on this head. |
| Declaration | Clause-②: no (narrowing) on the claim, the PR body and both changesets: @objectstack/platform-objects and @objectstack/spec, both minor with BREAKING, each with an adr-0087: not-required (no-migration-prescription) marker. No export, public member or accepted key is added. |
| Cross-lane | Declared, with no objection on the card or the seat posts: • domain:spec, for public-auth-features.ts (6278359654 on #6017, 6278366197 on #18549);• domain:cli, for the runtime and qa/dogfood test files (6278372177 on #6024, 6278381067 on #22648).The repo:cloud#2 seat's pointer was sent before landing (6278628061 on #24145). |
| Gates | Dev: 88 derived, 88 run, all exit 0 at 91dc52d3e. On 473c6ff94: the changeset gates, the dogfood typecheck, and both dogfood files (7/7, 5/5). The dogfood family does not run on a pull request, so those two runs are the dev's claim; the records judge both files right from the code. |
| CI | At this read on 473c6ff949: ci-failure GREEN, all 41 check-runs completed, none failed. |
Disposition:
open_questions: both accepted as A, per record 6278606056 ③ and the delta:- cloud's copy is the platform's former declaration byte for byte, with no
order; - the cloud seat measures its bundle's reach on cloud's boot.
- cloud's copy is the platform's former declaration byte for byte, with no
deviations: all accepted (records 6278606056 ③ and 6279401940 ③).out_of_scope_findings: none.- Non-blocking notes:
action-confirm-one-dialog.test.tsloses a row with no new assertion; the absence is pinned in four other files.- The new pin's
ERRORarm reads stdout, where noERRORline goes; the collision report is awarn, so the live arm is the right one.
Downstream: cloud declares its own change_slug before, or with, its pin bump past this landing (pointer 6278628061).
Landing: ordinary queue (pr_ready + automerge_enable through the relay). Fixes #24318 then closes the card.
Generated by Claude Code
Fixes #24318
Clause-②: no (narrowing) (a platform object stops declaring an action whose door exists only in cloud; owes a
CONTRACT_REVIEW_TIERreview on the narrowing face before the queue, and therepo:cloud#2seat's pointer before landing)Dev session
session_015mj2S1LnzLNur4rJeZuMbN, dispatched by thedomain:engineseat 1 (session_01JtSQQ3EWsbNPzyYMug1tXy) under claim 6275837047. Shape B of the release 6255698861: the composition that serves/api/v1/cloud/organizations/{id}/change-slugdeclareschange_slugitself, through the top-level action bound byobjectNamethat PR #24458 attaches, andsys_organizationstops declaring it.What changes
packages/platform-objects/src/identity/sys-organization.object.ts:change_slugis removed with its comments. The comments onleave_organizationandrename_organizationnow say what is true: the header carries Invite User, Set Active and Rename Organization inline and Leave Organization in the overflow, and the slug action is declared by the composition that serves its route. The action order is unchanged.defaultRowScope(PR feat(platform-objects)!: the identity objects declare their default row scope, and the registry refuses an extend that sets one #24623's region) is not touched.sys_organization._actions.change_slug, regenerated withnode scripts/check-i18n-bundles.mjs --write(20 lines removed, nothing else moved).packages/spec/src/kernel/public-auth-features.ts: themultiOrgEnabled.gatedInputsrowsys_organization.actions.change_slugis removed. It is the platform objects' own census:feature-gate-guard.test.tswalks only the platform-objects modules, and its forward direction reds when a booked path names an action that no longer exists. It is not a gate on other packages (measured below), so cloud does not need it.packages/platform-objects/src/pages/sys-organization.page.ts: the docblock that listed Change Slug in the header overflow (comment only). Outside the claim's file surface; the removal made it false.Measured on a booted multi-organization showcase (M)
The harness:
bootShowcase({ multiTenant: 'posture-only' }),/auth/configservingmultiOrgEnabled: true. The cloud-shaped composition adds oneAppPluginwhose stack declares a top-levelchange_slugwithobjectName: 'sys_organization'and the platform's former declaration byte for byte (target,method: 'POST',record_header, the oneslugparam,requiresFeature: 'multiOrgEnabled', description, success message).Before, on
origin/main1e8b6284c0:change_slugservedvisiblePOST /api/v1/cloud/organizations/org_x/change-slugfeatures.multiOrgEnabled != false404ENDPOINT_NOT_FOUND404sameActionDeclarationreads one declaration)Change Slug(the platform's)404WARN: declared twice,com.objectstack.plugin-authserved,com.measure.cloud-shapednot listedAfter, on this branch:
change_slugservedvisiblefeatures.multiOrgEnabled != false, the same lowering as the platform's ownrequiresFeatureactions⋯overflow, where the platform copy satChange Slug (cloud))Nothing refuses a non-platform action that declares
requiresFeature: 'multiOrgEnabled': the boot succeeds, the sugar is lowered at parse like any action's, and nogatedInputsrow is consulted at runtime.What the cloud repository needs (for the
repo:cloud#2seat's pointer)objectName:objects.sys_organization._actions.change_slug):Whether a translation bundle in cloud's package reaches another package's object's
_actionswas not measured here; the cloud seat owns that check.3. Land it before, or with, cloud's pin bump past this PR. Until then cloud's record page has no Change Slug. If cloud declares it while this platform copy is still in its pin, the identical declaration is served once and nothing is reported; a declaration that differs is reported at boot and the platform's copy is the one served.
Pins
Pin sweep:
git grep -n "change_slug\|change-slug"over the tree. Every hit outside CHANGELOGs and landed.changeset/preentries moved:sys-organization-rename-action.test.ts: the header order is now asserted exactly (invite, set active, rename inline; leave in the overflow). Thechange_slugcontrol is replaced by "every api action targets better-auth'sorganization/routes, none the cloud orchestrator, and nochange_slugis declared".platform-objects.test.ts: thechange_sluglowering row is removed, and a new case holds the matrix'sSysOrganizationrows equal to every action the object gates onmultiOrgEnabled.action-confirm-one-dialog.test.ts: thesys_organizationentry leaves the converted map (13 of platform-objects: 16 more actions declare bothconfirmTextandparams, so one click opens two sequential dialogs (same shape as #7278) #7309's 14 remain platform declarations).confirm-question-carryover.test.ts: the pair leaves the set, and a new case asserts 13 pairs and that no locale bundle (en included) carriessys_organization.change_slug, withrename_organizationas the control.runtime/action-execution-destructive.test.ts: the flipped set is 5 and the full set is 13, and a new case assertsSysOrganizationdeclares nochange_slug.qa/dogfood/org-record-admin-reach.dogfood.test.ts: theUNDECIDEDhold-out is gone. The served set is asserted equal to the seven graded actions, and the door probe calls every api action the record serves, so the record offers no action whose target answers404(the first new pin of the claim).qa/dogfood/org-change-slug-bound-action.dogfood.test.tsboots the showcase with the cloud-shaped package and assertschange_slugis served once with the orchestrator target,POST,record_headerand its oneslugparam; itsvisibleequalsfeatureGatePredicate('multiOrgEnabled')andleave_organization's; undercelEngineit is admitted with multi-org on and hidden with it off; it sorts after rename and before leave; and the boot names no collision for it (the second new pin).Verification
Tests (head
91dc52d3e, after mergingorigin/main7c7741dcb, unless noted):pnpm --filter @objectstack/platform-objects test: 78 files, 1191 tests passed.pnpm --filter @objectstack/spec test: 701 files, 21313 passed, 1 todo (pre-merge head048de3158).pnpm --filter @objectstack/runtime test: 425 files, 6668 passed, 19 skipped (pre-merge head048de3158).org-record-admin-reachandorg-change-slug-bound-action: 2 files, 12 tests passed.pnpm --filter @objectstack/core test:repo: 6 files, 82 passed.@objectstack/platform-objects,@objectstack/spec,@objectstack/runtime,@objectstack/dogfood(after the merge).pnpm --filter @objectstack/spec check:generated: all 14 artifacts up to date (after the merge and a spec rebuild).node scripts/check-i18n-bundles.mjs: exit 0.Ablation (
scripts/ablation-replace.mjs, trap-restored; dist proved byscripts/ablation-dist-preflight.mjs): the platform copy put back intosys-organization.object.tsand platform-objects rebuilt (marker present in 6 built files):org-record-admin-reach: red, 2 cases ("every grade is served the same action set", and "every api action ... none answers ENDPOINT_NOT_FOUND").feature-gate-guard's reverse direction, which reds because the row is gone).org-change-slug-bound-actionstays green under the ablation, as expected: with an identical platform copy present the served declaration is the same bytes.Restored:
git diff HEADempty and the blob hash equals HEAD's; rebuilt, marker absent from all 66 built files; the dogfood pair green again (12/12).Gates:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 88 families; all 88 ran on91dc52d3ewith exit 0, and--ranreconciled "88 derived, 88 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero)".check:dual-build-cjs-loadsfirst exited 3 (eight packages had nodist/); they were built and it passed. The last commit,44da7fe8d, touches only the two changesets (the claim'sClause-②line carried verbatim), and the nine changeset families were re-run on it, all exit 0.Acceptance notes
sys-organization.page.tsis outside the claim'sFile surface:list; its docblock named Change Slug in the header overflow, which this change made false.org-record-admin-reachis, and it reds.sys_organization._actionsof another package's object; cloud's own boot with the declaration.Generated by Claude Code