From 49aecc4bde5ca7151983ccb9588165ccf9af5616 Mon Sep 17 00:00:00 2001 From: "claude[bot]" Date: Fri, 4 Sep 2026 22:40:05 +0000 Subject: [PATCH] docs(adr): qualify the pre-repo ADR-0081 citations as cloud ADR-0081, letter-checked per site (#9072) Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk --- content/docs/permissions/sharing-rules.mdx | 2 +- ...3-tenancy-mode-and-membership-lifecycle.md | 22 ++++++++++++------- ...nancy-posture-and-first-class-org-scope.md | 14 +++++++----- ...ation-ownership-no-null-organization-id.md | 9 +++++--- .../areas/identity-auth.json | 10 ++++----- .../src/apps/setup-nav.contributions.ts | 4 ++-- .../src/identity/invite-entry-toolbar.test.ts | 2 +- .../src/identity/sys-member.object.ts | 2 +- .../src/identity/sys-user.object.ts | 2 +- .../plugin-auth/src/auth-plugin.test.ts | 2 +- .../src/ensure-default-organization.test.ts | 2 +- .../src/ensure-default-organization.ts | 8 +++---- .../spec/src/kernel/public-auth-features.ts | 2 +- .../verify/src/harness.org-context.test.ts | 2 +- packages/verify/src/harness.ts | 10 ++++----- scripts/publish-smoke.sh | 2 +- 16 files changed, 54 insertions(+), 41 deletions(-) diff --git a/content/docs/permissions/sharing-rules.mdx b/content/docs/permissions/sharing-rules.mdx index b80a822191..b891d613f2 100644 --- a/content/docs/permissions/sharing-rules.mdx +++ b/content/docs/permissions/sharing-rules.mdx @@ -176,7 +176,7 @@ principal: **system** contexts, and **platform operators** — a holder of `manage_platform_settings` or of the built-in `platform_admin` position administers rules across the deployment whether or not an organization is selected, which is also what a single-tenant deployment looks like before its -default organization is bootstrapped (ADR-0081 D1). +default organization is bootstrapped (cloud ADR-0081 D1). ### Switching a rule off withdraws the access it granted diff --git a/docs/adr/0093-tenancy-mode-and-membership-lifecycle.md b/docs/adr/0093-tenancy-mode-and-membership-lifecycle.md index 38e1dd727c..0b3ec608ab 100644 --- a/docs/adr/0093-tenancy-mode-and-membership-lifecycle.md +++ b/docs/adr/0093-tenancy-mode-and-membership-lifecycle.md @@ -4,7 +4,7 @@ - **Date:** 2026-07-13 - **Deciders:** ObjectStack Protocol Architects - **Implementation:** #2882 (Phase 0 — tactical create-user bind, merged) → this PR (Phases 1–3 — `tenancy` service, fail-fast boot guard, membership reconciler, consumer migration, backfill, docs). One revision from the original plan, ratified in D2: the endpoint-level create-user bind **delegates to the shared reconciler** (one implementation, two call sites) instead of being deleted. Runtime verification confirmed the hook fires for `admin.createUser`, but better-auth *defers* `user.create.after` post-commit (#1881), so the endpoint keeps its delegated call to report `organizationId` / `membershipCreated` deterministically in its response. Cloud-host semantics (personal-org hook precedence, multi-org non-binding, D5 blast radius) verified against `objectstack-ai/cloud` — see D2/D3/D5. -- **Relates to:** [ADR-0049](./0049-no-unenforced-security-properties.md) (no unenforced security properties), [ADR-0057](./0057-erp-authorization-core-business-units-and-scope-depth.md) (org-scoped identity optionality), [ADR-0068](./0068-unified-user-context-and-built-in-identity-roles.md) (platform-admin gate), [ADR-0092](./0092-sys-user-profile-field-delegation.md) (identity write guard), the default-org bootstrap (`plugin-auth/src/ensure-default-organization.ts`, referenced in code as "ADR-0081 D1" — that decision record predates this repo's ADR series), #2766 (admin user management), PR #2882 (single-org create-user membership bind — the tactical fix this ADR generalizes) +- **Relates to:** [ADR-0049](./0049-no-unenforced-security-properties.md) (no unenforced security properties), [ADR-0057](./0057-erp-authorization-core-business-units-and-scope-depth.md) (org-scoped identity optionality), [ADR-0068](./0068-unified-user-context-and-built-in-identity-roles.md) (platform-admin gate), [ADR-0092](./0092-sys-user-profile-field-delegation.md) (identity write guard), the default-org bootstrap (`plugin-auth/src/ensure-default-organization.ts`, referenced in code as "cloud ADR-0081 D1" — identified 2026-09-04: that record is **cloud ADR-0081**, *Organization Management — Open Basics, Enterprise `@objectstack/organizations`*, Accepted 2026-07-09 in the `objectstack-ai/cloud` repo's own ADR series, where its **D1** is this bootstrap; it predates *this* repo's series because it lives in that one, where it is current), #2766 (admin user management), PR #2882 (single-org create-user membership bind — the tactical fix this ADR generalizes) ## TL;DR @@ -65,8 +65,9 @@ Decision: resolves a session's `activeOrganizationId` from the caller's `sys_member` row (owner-preferred, else oldest), only when the draft lacks one, best-effort, opt-out via `autoActiveOrganization: false`. Shipped behaviour, - previously cited in code as a pre-repo "ADR-0081 D1" whose number now - collides with this repo's ADR-0081; anchored here because it reads exactly + previously cited in code as an unqualified "ADR-0081 D1" — the record is + cloud ADR-0081 (identified 2026-09-04), and written without that qualifier + the number collides with this repo's ADR-0081; anchored here because it reads exactly the invariant D1 states and D2 owns. ## Context @@ -384,7 +385,9 @@ admin surfaces. different, larger decision — refused here to keep this ADR mechanical. 2. **The dual frontend flags keep their meaning.** `features.organization` (member management available) vs `features.multiOrgEnabled` (org management - available) is a deliberate ADR-0081-D1 distinction; only their *backing + available) is a deliberate cloud ADR-0081 D1/D2 distinction — D1 keeps + basic member management OPEN, D2 closes multi-org into the enterprise + `@objectstack/organizations` package; only their *backing fact* moves to the tenancy service. 3. **better-auth keeps owning `sys_member` CRUD.** The reconciler writes through the system context exactly as `ensureDefaultOrganization` does; no @@ -398,12 +401,15 @@ admin surfaces. > **This decision is a RECORDING, not a new ruling.** The behaviour below has > shipped since before this ADR, and nothing about it changes. What changes is > that it now has an anchor. The code carried it as **"ADR-0081 D1"**, a label -> inherited from a decision record that predates this repo's ADR series (the -> same pre-repo record the *Relates to* line names for the default-org -> bootstrap). That number now collides with this repo's +> inherited from **cloud ADR-0081** — *Organization Management — Open Basics, +> Enterprise `@objectstack/organizations`*, Accepted 2026-07-09 in the +> `objectstack-ai/cloud` repo's ADR series (identified 2026-09-04; the same +> record the *Relates to* line names for the default-org bootstrap). Written +> without that qualifier the number collides with this repo's > [ADR-0081](./0081-trusted-react-page-tier.md) — the trusted `kind:'react'` > page tier — so a reader following the citation landed in a document about -> React pages with no signal they were in the wrong record. The decision is +> React pages with no signal they were in the wrong record; the surviving +> citations elsewhere in this repo now carry the `cloud ` qualifier. The decision is > restated here because this is the record that owns the fact it depends on: > `sys_member` and the membership lifecycle (D1/D2). diff --git a/docs/adr/0105-group-tenancy-posture-and-first-class-org-scope.md b/docs/adr/0105-group-tenancy-posture-and-first-class-org-scope.md index f00bdc27d7..77cf0e47fa 100644 --- a/docs/adr/0105-group-tenancy-posture-and-first-class-org-scope.md +++ b/docs/adr/0105-group-tenancy-posture-and-first-class-org-scope.md @@ -340,11 +340,15 @@ org lifecycle management, grouping/registry UI, scoped invitations UX, cross-org approval templates, master-data distribution management, per-org seed/config replay, org analytics, and the D13 promotion tooling. -> **Citation note (2026-08-16) — hygiene, not a decision.** Code and tests -> carried this entitlement as **"ADR-0081 D2"**, a label inherited from a -> decision record that predates this repo's ADR series — the same pre-repo -> record whose "ADR-0081 D1" label [ADR-0093](./0093-tenancy-mode-and-membership-lifecycle.md) -> D9 names. That number now collides with this repo's +> **Citation note (2026-08-16; record identified 2026-09-04) — hygiene, not a +> decision.** Code and tests carried this entitlement as **"ADR-0081 D2"**, a +> label inherited from **cloud ADR-0081** — *Organization Management — Open +> Basics, Enterprise `@objectstack/organizations`*, Accepted 2026-07-09 in the +> `objectstack-ai/cloud` repo's ADR series, which is the record the *Builds on* +> line above already cites by that name, and the same one whose "ADR-0081 D1" +> label [ADR-0093](./0093-tenancy-mode-and-membership-lifecycle.md) +> D9 names; its **D2** is the multi-org entitlement decision. Written without +> that qualifier the number collides with this repo's > [ADR-0081](./0081-trusted-react-page-tier.md), the trusted `kind:'react'` > page tier, whose Decision section is numbered 1–4 and has no D-numbered > decisions at all — so a reader following the citation landed in a document diff --git a/docs/adr/0131-total-organization-ownership-no-null-organization-id.md b/docs/adr/0131-total-organization-ownership-no-null-organization-id.md index 2f93aacc22..dec40ef669 100644 --- a/docs/adr/0131-total-organization-ownership-no-null-organization-id.md +++ b/docs/adr/0131-total-organization-ownership-no-null-organization-id.md @@ -825,9 +825,12 @@ stamp-and-backfill repair (#12929, #13180, #13527, #13572, #13565, #14726) and # - The issue body of #13564 cites the arm by a bare line number (7320) that had drifted by ~4,600 lines before the first census read it; on `origin/main` `2514d49f3` the arms are inside `applyTenantScope` (~12016–12066) and there are **two**. This record cites symbols. -- `ensure-default-organization.ts` cites "ADR-0081 D1" for the Default Organization; in this - repository `docs/adr/0081` is the trusted React page tier — the "0081" is cloud's numbering. The - framework record is [ADR-0093](./0093-tenancy-mode-and-membership-lifecycle.md). +- `ensure-default-organization.ts` cites "cloud ADR-0081 D1" for the Default Organization; in this + repository `docs/adr/0081` is the trusted React page tier — the "0081" is cloud's numbering, and the + record is **cloud ADR-0081** (*Organization Management — Open Basics, Enterprise + `@objectstack/organizations`*, Accepted 2026-07-09), identified 2026-09-04, so the citations now carry + the qualifier rather than resolving here. The framework record is + [ADR-0093](./0093-tenancy-mode-and-membership-lifecycle.md). - `resolve-authz-context.ts` already resolves positions **by name** (`{ name: { $in: grants.positions } }` against `sys_position`); D4 changes where that lookup goes first, not what it is keyed on. - `template-loader.ts` resolves by `(name, locale)`; a grep for `organization` / `tenant` in it returns diff --git a/docs/qa/platform-checklist/areas/identity-auth.json b/docs/qa/platform-checklist/areas/identity-auth.json index ff128bfd06..fd66840863 100644 --- a/docs/qa/platform-checklist/areas/identity-auth.json +++ b/docs/qa/platform-checklist/areas/identity-auth.json @@ -754,12 +754,12 @@ "fixtures": { "app": "showcase", "requires": [ - "the organization capability mounted (always mounted per ADR-0081 D1; plugin-auth's default-org bootstrap guarantees an org to manage) and a session with an active organization so {current_org_id} resolves", + "the organization capability mounted (always mounted per cloud ADR-0081 D1; plugin-auth's default-org bootstrap guarantees an org to manage) and a session with an active organization so {current_org_id} resolves", "at least two members in the org so role changes and removals have a target that is not the admin" ] }, "steps": [ - "sign in as the org owner/admin and open Setup → People & Org → Organization (nav_organization: type object, objectName sys_organization, recordId {current_org_id}, ADR-0081); screenshot the org record page and confirm {current_org_id} resolved to the session's active org (not the list fallback)", + "sign in as the org owner/admin and open Setup → People & Org → Organization (nav_organization: type object, objectName sys_organization, recordId {current_org_id}, cloud ADR-0081 D3); screenshot the org record page and confirm {current_org_id} resolved to the session's active org (not the list fallback)", "confirm the record page exposes the Members / Invitations / Teams tabs with the better-auth row actions (GET list-members, list-invitations, list-teams feed them)", "change a member's role: POST /api/v1/auth/organization/update-member-role (client organizations.updateMemberRole) to one of the ADR-0108 closed 4-name vocabulary {owner, admin, delegated_admin, member}; read the membership back and confirm the new role", "prove the vocabulary is CLOSED, not merely conventional: attempt the same call with role 'guest' (and with any stack-declared position/permission-set name, e.g. showcase's 'contributor') — better-auth's role check refuses it (400 ROLE_NOT_FOUND) before any insert, and no membership/invitation row is left behind", @@ -771,7 +771,7 @@ ], "acceptance": [ { - "clause": "{current_org_id} resolves to the session's active organization: the Organization nav opens that org's record page (Members/Invitations/Teams tabs), not the raw sys_organization list — the ADR-0081 active-org token is wired", + "clause": "{current_org_id} resolves to the session's active organization: the Organization nav opens that org's record page (Members/Invitations/Teams tabs), not the raw sys_organization list — the cloud ADR-0081 D3 active-org token is wired", "oracle": "screenshot", "verify": "the org record page renders for the active org id (cross-checked against GET /api/v1/auth/organization/get-active-member / get-full-organization); the three management tabs are present", "evidence": "the org-page screenshot + the get-active/get-full response" @@ -817,11 +817,11 @@ "an org management surface where the affordance is hidden but the forged endpoint succeeds for a non-admin is a FAIL — the server is the authority (ADR-0124 D1)", "remove-member that drops the roster row but leaves the ex-member's org-scoped access intact is a FAIL — removal must change authorization", "a role written outside the {owner, admin, delegated_admin, member} vocabulary is a FAIL — including a stored 'guest': the closed list is the write-side guardrail that makes an ungoverned capability grant unrepresentable (ADR-0108), so a 2xx that persists 'guest' is a regression of the closure, not a vocabulary difference. A role change that does not flip any gate is equally a FAIL", - "the Organization nav landing on the raw sys_organization list because {current_org_id} did not resolve (when an active org exists) is a FAIL of the ADR-0081 wiring" + "the Organization nav landing on the raw sys_organization list because {current_org_id} did not resolve (when an active org exists) is a FAIL of the cloud ADR-0081 D3 wiring" ], "traps": ["wrong-persona", "dispatcher-vs-hono-route", "hydration-race"], "source": [ - "packages/platform-objects/src/apps/setup-nav.contributions.ts#nav_organization (nav_organization recordId {current_org_id}, ADR-0081; Teams/Invitations always mounted per ADR-0081 D1)", + "packages/platform-objects/src/apps/setup-nav.contributions.ts#nav_organization (nav_organization recordId {current_org_id}, cloud ADR-0081 D3; Teams/Invitations always mounted per cloud ADR-0081 D1)", "packages/plugins/plugin-auth/src/auth-route-ledger.ts (organization family: update-member-role, remove-member, update, create-team, add-team-member, list-members/teams/invitations, get-active-member, get-full-organization)", "packages/spec/src/identity/membership-role.ts#BUILTIN_MEMBERSHIP_ROLES (BUILTIN_MEMBERSHIP_ROLES / BUILTIN_MEMBERSHIP_ROLE_OPTIONS — THE role vocabulary: owner/admin/delegated_admin/member, ADR-0108; 'nothing widens these at boot any more')", "docs/adr/0108-membership-grade-is-not-a-capability-channel.md (why the list is closed: a grade decides what you can REACH, never a bundle of what you may do)", diff --git a/packages/platform-objects/src/apps/setup-nav.contributions.ts b/packages/platform-objects/src/apps/setup-nav.contributions.ts index fa40ab2c56..e732d1fbef 100644 --- a/packages/platform-objects/src/apps/setup-nav.contributions.ts +++ b/packages/platform-objects/src/apps/setup-nav.contributions.ts @@ -71,12 +71,12 @@ export const SETUP_NAV_CONTRIBUTIONS: NavigationContribution[] = [ { id: 'nav_users', type: 'object', label: 'Users', objectName: 'sys_user', icon: 'user' }, // The ACTIVE organization's record page (Members / Invitations / Teams // tabs with the better-auth row actions), rendered inside the app shell - // (ADR-0081). `{current_org_id}` resolves from the session's active + // (cloud ADR-0081 D3). `{current_org_id}` resolves from the session's active // organization; unresolved (e.g. org-less admin before bootstrap) it // falls back to the sys_organization list — one row in single-org. { id: 'nav_organization', type: 'object', label: 'Organization', objectName: 'sys_organization', recordId: '{current_org_id}', icon: 'building-2' }, { id: 'nav_business_units', type: 'object', label: 'Business Units', objectName: 'sys_business_unit', icon: 'building', requiresObject: 'sys_business_unit' }, - // Teams / Invitations no longer gate on `org-scoping` (ADR-0081 D1): + // Teams / Invitations no longer gate on `org-scoping` (cloud ADR-0081 D1): // the better-auth organization capability is always mounted, and // plugin-auth's single-org default-org bootstrap guarantees an org to // invite into — these are the OPEN member-management basics. Only the diff --git a/packages/platform-objects/src/identity/invite-entry-toolbar.test.ts b/packages/platform-objects/src/identity/invite-entry-toolbar.test.ts index 92e4613ce9..191e61f78c 100644 --- a/packages/platform-objects/src/identity/invite-entry-toolbar.test.ts +++ b/packages/platform-objects/src/identity/invite-entry-toolbar.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. // // #11544 — the email-invite entry was UNREACHABLE from where admins actually -// look. The org record page (ADR-0081) opens on tab-0 **Members** +// look. The org record page (cloud ADR-0081 D3) opens on tab-0 **Members** // (`sys_member`), whose toolbar carried exactly one action — `add_member`, // which attaches an ALREADY-REGISTERED user by id. `invite_user` lived only on // tab-1 Invitations. The maintainer, looking to "invite a teammate by email", diff --git a/packages/platform-objects/src/identity/sys-member.object.ts b/packages/platform-objects/src/identity/sys-member.object.ts index 57f2bbe856..44cfc464d1 100644 --- a/packages/platform-objects/src/identity/sys-member.object.ts +++ b/packages/platform-objects/src/identity/sys-member.object.ts @@ -44,7 +44,7 @@ export const SysMember = ObjectSchema.create({ { // THIRD mirror of `invite_user` (sys_user, sys_invitation are the other // two — keep all three consistent). It is here because the org record - // page (ADR-0081) opens on tab-0 **Members**, and the email-invite entry + // page (cloud ADR-0081 D3) opens on tab-0 **Members**, and the email-invite entry // used to live only on tab-1 Invitations: an admin looking to "invite a // teammate by email" landed on Members, saw only "Add Member" (attach an // existing user by id), and concluded the product had no invite entry. diff --git a/packages/platform-objects/src/identity/sys-user.object.ts b/packages/platform-objects/src/identity/sys-user.object.ts index 775b0aae6f..66d497be78 100644 --- a/packages/platform-objects/src/identity/sys-user.object.ts +++ b/packages/platform-objects/src/identity/sys-user.object.ts @@ -86,7 +86,7 @@ export const SysUser = ObjectSchema.create({ locations: ['list_toolbar'], type: 'api', target: '/api/v1/auth/organization/invite-member', - // Gated on the org CAPABILITY, not multi-org (ADR-0081 D1): the + // Gated on the org CAPABILITY, not multi-org (cloud ADR-0081 D1): the // better-auth organization plugin is always mounted, and single-org // mode now bootstraps a Default Organization (plugin-auth) so the // endpoint's active-org resolution works there too. This is THE diff --git a/packages/plugins/plugin-auth/src/auth-plugin.test.ts b/packages/plugins/plugin-auth/src/auth-plugin.test.ts index f746d6818f..5c6921e194 100644 --- a/packages/plugins/plugin-auth/src/auth-plugin.test.ts +++ b/packages/plugins/plugin-auth/src/auth-plugin.test.ts @@ -1256,7 +1256,7 @@ describe('AuthPlugin', () => { }); }); - // ADR-0081 D1 — single-org default-organization bootstrap. + // cloud ADR-0081 D1 — single-org default-organization bootstrap. describe('Single-org default-org bootstrap', () => { const OLD_ENV = process.env.OS_MULTI_ORG_ENABLED; let hookCapture: ReturnType; diff --git a/packages/plugins/plugin-auth/src/ensure-default-organization.test.ts b/packages/plugins/plugin-auth/src/ensure-default-organization.test.ts index 0b34e8f5e6..f85d4b970f 100644 --- a/packages/plugins/plugin-auth/src/ensure-default-organization.test.ts +++ b/packages/plugins/plugin-auth/src/ensure-default-organization.test.ts @@ -1,6 +1,6 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. -// ADR-0081 D1 — the default-org bootstrap helper (open home: plugin-auth). +// cloud ADR-0081 D1 — the default-org bootstrap helper (open home: plugin-auth). // Covers the idempotency short-circuits, the create/reuse paths, and the // injectable seed-ownership step (enterprise injects it; open path omits it). diff --git a/packages/plugins/plugin-auth/src/ensure-default-organization.ts b/packages/plugins/plugin-auth/src/ensure-default-organization.ts index a9f99eb0af..c3e296dbf7 100644 --- a/packages/plugins/plugin-auth/src/ensure-default-organization.ts +++ b/packages/plugins/plugin-auth/src/ensure-default-organization.ts @@ -1,15 +1,15 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. /** - * ensureDefaultOrganization — default-org bootstrap helper (ADR-0081 D1). + * ensureDefaultOrganization — default-org bootstrap helper (cloud ADR-0081 D1). * * The platform admin needs at least one `sys_organization` so their sessions * can carry an `activeOrganizationId`. Without it: * - multi-org: the default `tenant_isolation` RLS policy filters everything * to zero rows and the admin sees an empty console; * - single-org: better-auth `organization/invite-member` has no active org - * to resolve, so there is NO way to add a user at all — the gap ADR-0081 - * closes. + * to resolve, so there is NO way to add a user at all — the gap + * cloud ADR-0081 D1 closes. * * This helper HOME is plugin-auth (the open member-management basics). The * enterprise organizations package reuses it for the multi-org bootstrap and @@ -351,7 +351,7 @@ export async function ensureDefaultOrganization( '[default-org] the Default Organization row was NOT created — the platform admin has no ' + 'organization, so under multi-org the default tenant_isolation RLS policy filters their ' + 'console to zero rows, and under single-org better-auth has no active org to resolve, so ' - + 'there is no way to add a user at all (ADR-0081 D1). NOTHING ELSE FAILS AND THE BOOT GOES ' + + 'there is no way to add a user at all (cloud ADR-0081 D1). NOTHING ELSE FAILS AND THE BOOT GOES ' + 'ON LOOKING HEALTHY: this line is the only notice. Remedy: make the sys_organization ' + 'insert land — check the write permission and driver connectivity, and whether a legacy ' + 'unique index on `slug` is refusing `default`; the bootstrap re-runs on every ' diff --git a/packages/spec/src/kernel/public-auth-features.ts b/packages/spec/src/kernel/public-auth-features.ts index 8d27ce4d2e..90ec38b213 100644 --- a/packages/spec/src/kernel/public-auth-features.ts +++ b/packages/spec/src/kernel/public-auth-features.ts @@ -122,7 +122,7 @@ export const PUBLIC_AUTH_FEATURES = { 'sys_team_member.actions.add_team_member', 'sys_team_member.actions.remove_team_member', ], - notes: 'Org CAPABILITY gate, not multi-org (ADR-0081 D1).', + notes: 'Org CAPABILITY gate, not multi-org (cloud ADR-0081 D1).', }, multiOrgEnabled: { surface: 'crud', diff --git a/packages/verify/src/harness.org-context.test.ts b/packages/verify/src/harness.org-context.test.ts index 1f124c5424..0d4b0f6643 100644 --- a/packages/verify/src/harness.org-context.test.ts +++ b/packages/verify/src/harness.org-context.test.ts @@ -180,7 +180,7 @@ describe('bootStack orgContext (#7762)', () => { async () => { // The dangerous half. `'posture-only'` requests the `isolated` posture, // and the open default-org bootstrap abstains under every walled posture - // (ADR-0081 D1), so the combination would hand back an org-LESS admin + // (cloud ADR-0081 D1), so the combination would hand back an org-LESS admin // from a call that reads as org-bound — vacuity wearing the mask of // coverage, which is the entire defect class #7762 exists to close. await expect(bootStack(app, { orgContext: true, multiTenant: 'posture-only' })).rejects.toThrow( diff --git a/packages/verify/src/harness.ts b/packages/verify/src/harness.ts index a2a21a56f6..fe454e7f4b 100644 --- a/packages/verify/src/harness.ts +++ b/packages/verify/src/harness.ts @@ -178,7 +178,7 @@ export interface BootOptions { * every request of theirs resolves CARRIES an `organizationId`. Default * `false`. * - * Mechanically it is one flip: `AuthPlugin`'s ADR-0081 D1 default-org + * Mechanically it is one flip: `AuthPlugin`'s cloud ADR-0081 D1 default-org * bootstrap (`autoDefaultOrganization`), which the harness otherwise pins * OFF (see the AuthPlugin registration below). The bootstrap mints a * `sys_organization` and binds the platform admin to it as `owner`; the @@ -235,7 +235,7 @@ export interface BootOptions { * - with `multiTenant: 'posture-only'`, it would be a NO-OP that looks like * a feature. That mode requests the `isolated` posture, and the open * default-org bootstrap deliberately abstains under every WALLED posture - * (`postureEnforcesWall`, ADR-0081 D1) — the open package never + * (`postureEnforcesWall`, cloud ADR-0081 D1) — the open package never * bootstraps an organization for a deployment whose multi-organization * runtime it does not provide. The admin would resolve org-less while the * fixture read as org-bound: vacuity, which is the whole defect class @@ -334,7 +334,7 @@ export async function bootStack( `verify: orgContext:true does not compose with multiTenant:${JSON.stringify(opts.multiTenant)}. ` + (opts.multiTenant === 'posture-only' ? "'posture-only' requests the `isolated` posture, and the open default-org bootstrap abstains " + - 'under every walled posture (ADR-0081 D1) — the admin would resolve org-less while the fixture ' + + 'under every walled posture (cloud ADR-0081 D1) — the admin would resolve org-less while the fixture ' + 'read as org-bound. Drop one of the two options; a posture-gated seam that also needs an ' + 'org-bound caller needs the real @objectstack/organizations package.' : 'the enterprise @objectstack/organizations package owns the org bootstrap under multiTenant:true ' + @@ -415,7 +415,7 @@ export async function bootStack( // Service plugins `objectstack dev` auto-loads for an app of this shape. await kernel.use(new SettingsServicePlugin()); await kernel.use(opts.analytics ?? new AnalyticsServicePlugin()); - // `autoDefaultOrganization: false` (ADR-0081 D1): the harness proves the two + // `autoDefaultOrganization: false` (cloud ADR-0081 D1): the harness proves the two // ENDS of the isolation spectrum — pure single-tenant (no org, no scoping) // and, via `opts.multiTenant`, full multi-org (the enterprise plugin owns // the org bootstrap). AuthPlugin's single-org default-org bootstrap is a @@ -653,7 +653,7 @@ export async function bootStack( 'activeOrganizationId and every org-scoped assertion in this fixture would be vacuous.' : 'No sys_user row resolved for that address — check `opts.admin` against the app the ' + "harness actually seeded, since the default-org bootstrap targets the platform admin.") + - ' (ADR-0081 D1 `ensureDefaultOrganization` is best-effort by design; this is the harness ' + + ' (cloud ADR-0081 D1 `ensureDefaultOrganization` is best-effort by design; this is the harness ' + 'refusing to hand back a stack that quietly means less than it reads.)', ); } diff --git a/scripts/publish-smoke.sh b/scripts/publish-smoke.sh index 4ef12a1e0c..496ed6e17d 100644 --- a/scripts/publish-smoke.sh +++ b/scripts/publish-smoke.sh @@ -887,7 +887,7 @@ if [ "$AUDIENCE_POSTURE" = "invite_only" ]; then # BY INVITATION, and a self-serve sign-up whose address holds a pending, # unexpired `sys_invitation` row is admitted under every posture (the # invitation carve-out). The route runs as the signed-in admin against the - # default organization their session carries — ADR-0081 bootstraps that org + # default organization their session carries — cloud ADR-0081 D1 bootstraps that org # precisely so this path exists on a single-org install. # # Chosen over `POST /auth/admin/create-user` — the other operator path named