Skip to content

Commit f0eb9bb

Browse files
qa(checklist): 18.2.0 sweep ledger edits — i18n, search, studio-authoring, ux-conventions, RUNNER (#26109)
<!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi9YMBrR5rVpt7qn3c2Z88yrb)_ Fixes #25842 Fixes #25847 Fixes #25848 Part of #25849 (4 of its 5 findings; the write-feedback acceptance[1] reading waits on a maintainer ruling, so the card stays open) Fixes #25850 Clause-②: no Metadata-protocol: none Checklist-accuracy findings from the 18.2.0 release sweep, applied to five ledger files, one commit per card. Wave anchor: #25807 (it stays open; this PR only links it). Docs only: nothing under `packages/`, `ui/` or any governed surface moves, so the PR carries `skip-changeset`. Every JSON edit revises the item text, bumps its `revision`, and appends a `history` row that names the run record the finding came from (QA runs #25815 `release-18.2.0-tier1` and #25817 `release-18.2.0-manual-set`, both at `6679644a`; #25812 and #25823 for RUNNER). Each finding was re-read against `origin/main` at `cc378e93` first, with objectui paths read under `ui/`. ## Per card **#25842, `areas/i18n.json` (9 findings, all applied, 5 items).** - `i18n.flow-copy-translation-and-host-override`: the ref adds the three `packages/cli/test/i18n-flow-*-coverage` tests; the verify for the extract clause says they prove `extractTranslations`, not the command's file write; the validate clause says `translation.test.ts` pins the rule and its remedy while the exit code stays the run's. - `i18n.surface-matrix`: the ref says the two objectui pins cover the confirm copy and the successMessage handed to the toast, under stubbed action, confirm and toast handlers (no round-trip), so the network clause stays the run's. It also says acceptance 6, 7 and 9 have no pin: the anonymous-deny dogfood's member 200 control asserts none of the locale set, the group vocabulary or the zz-ZZ shape. - `i18n.strict-translation-key-rejection`: the steps name a snake_case item (the conventional name `zh-CN` is refused first with 400 `INVALID_REQUEST`), and the clause scores 422 `INVALID_METADATA`. A3 cites ADR-0049 and spec 17.0.0, as the live text does. A5 reads the singular label on the record-page badge and the New dialog, and `pluralLabel` on the list header and nav. - `i18n.notification-localized-and-clears`: the steps and the clause read the server's `unreadCount` (GET /api/v1/notifications), never the header badge, which also counts pending approvals. **#25847, `areas/search.json` (6 findings, all applied, 4 items).** - `search.cross-field-object-search`: the pin proves the name-hit control by substring, not by naming Acme Retail. - `search.field-scoped-narrowing`: the ref is scoped to acceptance 0. The pin has no `$searchFields` refusal case and drives only the POST spelling, so acceptance 1 to 3 and both negatives are the run's. The route-handler INVALID_FIELD evidence in `packages/rest` is named as corroboration. - `search.global-search-skips-unreadable`: the dogfood pin runs on planted `skipsearch_*` objects, not the showcase objects, and its unscoped case asserts no `totalObjects`. - `search.pinyin-flag-both-sides`: the run's own paths must not spell `pinyin` (they polluted the zero-hit grep), and the 6679644 counts are recorded (53 on, 52 off). **#25848, `areas/studio-authoring.json` (9 findings, all applied).** Each `automated.ref` now says which clauses its pins score: jsdom and unit pins that stop above HTTP score only the test-oracle clause. Affected items are `expression-editors`, `meta-save-preconditions-and-draft-rows`, `metadata-diagnostics-sweep` (its pin's `[#8924]` describe is named as protocol-layer evidence for acceptance 3 and negative 0), `object-designer-roundtrip` (F4 is corroboration under a different fixture), `org-override-registry-gate` and `save-door-runs-authoring-rules`. In `permission-matrix-editor-ux`, the ref adds `PermissionMatrixEditor.artifactTier.test.tsx` for the artifact gate. In `record-page-roundtrip`, the ref names the run's objectui pin `b41ed7f68956` beside `cf153eb2e535`. **#25849, `areas/ux-conventions.json` (5 findings: 4 applied, 1 answered).** `write-feedback`: - Import Undo works in create and update modes, so the Undo clause is scored on the import instead of `blocked(fixture)`. - Discard draft is an in-app dialog. - The approvals route has no drawer: a request opens on its record page. - The member's refusal row is Mark Done, because the console offers a member no inline edit, selection or drag. - **Not applied:** the run asks for a ruling on object-only success strings ("Task created successfully", "Settings saved", `Flow "Reassign Task" completed`) under acceptance 1. That is a maintainer decision, so the clause is unchanged and the question is raised in the report on #25842. **#25850, `RUNNER.md` (3 findings, all applied; re-read on top of #26052).** - Walled boot: `examples/app-showcase/package.json` declares `@objectstack/organizations`, so a walled run boots from the tree with three variables and no scratch copy. - Playwright: `/opt/pw-browsers` holds chromium 1243, matching playwright-core 1.63.0, and the alias resolves there (re-read in this container at `cc378e93`). The entry now describes a mismatch as the case to check for. - `OS_PORT`: `os dev` serves the prebuilt `dist/objectstack.json`, so the connector metadata's `baseUrl` can carry the build-time value while the live dispatch reaches the exported port. The Check now reads the self-ping flow's run. - Walled personas: after #25626, Create User joins the operator's current organization, so the operator creates an organization and runs `set-active` before minting personas. **Retired objectui-pin wording in the same files** (#26035 left the area JSON to these cards). `.objectui-sha`, `objectui:refresh` and "not runnable from this checkout" are rewritten to `ui/` paths and `pnpm console:build`. That covers `i18n.studio-follows-app-locale`, `studio-authoring.first-run-loop`, `packaged-automation-studio-lock`, `packaged-display-class-direct-edit`, `doc-on-app-menu`, `picklist-bound-select`, the four "AUTOMATION IS PINNED IN THE objectui REPO" knownGaps in `studio-authoring.json`, and RUNNER's objectui-ref standing fact. Re-scan of the five files' non-history text for `objectui:(build|refresh|bump|clean)`, `build-console.sh`, `.objectui-sha`, `objectui checkout` and "PINNED IN THE objectui REPO": 0 hits. History rows are records and are left as written. ## Acceptance notes - **Same stale knownGap in other files, out of scope here.** 15 items in `records-forms.json` (12), `automation.json` (2) and `attachments-storage.json` (1) still say their objectui pins are not runnable from this checkout. RUNNER's rewritten fact now tells a runner to read that wording as stale. The items themselves belong to their files' cards, and the report on #25842 names this for the seat. - `packages/qa/dogfood/test/search-conformance.ledger.ts` names `showcase-search.dogfood.test.ts` as the proof for `search-fields-override` (400 INVALID_FIELD), but that file has no refusal case. Noted, not filed. - `examples/app-showcase/src/system/self-url.ts`'s header still says the `os dev` value follows the live environment; at `6679644a` the served metadata did not. This goes to the seat with the OS_PORT finding. ## Verification At head `bc394208`: - `pnpm check:platform-checklist`: exit 0, "OK — 16 areas, 329 items". - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derives 13 families. All 13 ran with exit 0: `check:doc-formula-expressions` refused with exit 3 until `@objectstack/formula` and `@objectstack/lint` were built, then passed. - `--ran` reconciliation: 13 derived, 13 run, 0 NOT-MEASURED. - `node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD`: 5 commits, no card relation, no model identifier. --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8de7c50 commit f0eb9bb

5 files changed

Lines changed: 238 additions & 160 deletions

File tree

‎docs/qa/platform-checklist/RUNNER.md‎

Lines changed: 84 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -208,27 +208,29 @@ contradicts it, and correct it here when it does.
208208
comparable** to the total rather than merely stale. Name which of the two lines you
209209
are quoting whenever you cite either.
210210

211-
- **Playwright needs an explicit `executablePath` on these containers.**
212-
`@playwright/test` 1.63.0 (the `^1.63.0` `examples/app-showcase/package.json` declares, the
213-
only version in the store) resolves chromium build **1243**; only **1194** is installed.
214-
Re-measured at `bfc1539fe0`: this entry read 1.62.1 and build 1234 until the tree moved
215-
to 1.63.0; `playwright-core` sits only in the pnpm store (there is no root
216-
`node_modules/playwright-core`), so the check reads it there.
211+
- **Playwright's chromium build must match the one the container installed — today it
212+
does, and the `/opt/pw-browsers/chromium` alias is the launch path that survives when it
213+
stops.** `@playwright/test` 1.63.0 (the `^1.63.0` `examples/app-showcase/package.json`
214+
declares, the only version in the store) resolves chromium build **1243**, and
215+
`/opt/pw-browsers` now holds `chromium-1243` / `chromium_headless_shell-1243`, with the
216+
`chromium` alias resolving into `chromium-1243` (QA run #25812 at `6679644a`; re-read at
217+
`cc378e93`). Earlier images held only build 1194, and every launch died until the run
218+
passed the alias explicitly. `playwright-core` sits only in the pnpm store (there is no
219+
root `node_modules/playwright-core`), so the check reads it there.
217220
**Check:**
218221
`grep -A2 '"name": "chromium"' node_modules/.pnpm/playwright-core@*/node_modules/playwright-core/browsers.json`
219-
against `ls $PLAYWRIGHT_BROWSERS_PATH` (`/opt/pw-browsers` here, holding
220-
`chromium-1194` / `chromium_headless_shell-1194` only). The stock
221-
`examples/app-showcase/playwright.config.ts` sets no `executablePath`, so every test
222-
dies at browser launch — the error names the **headless-shell** variant it wanted
223-
(`Executable doesn't exist at .../chromium_headless_shell-1243/...`), which is the
224-
signature to recognise. Pass `launchOptions.executablePath=/opt/pw-browsers/chromium`
225-
(for the smoke, `OS_TEST_CHROMIUM_EXECUTABLE_PATH=/opt/pw-browsers/chromium`, which the
226-
config reads since #21060) and the same specs pass (verified: Playwright launches through it, reporting Chromium
227-
141.0.7390.37, and drives a real page). ⚠️ Use that **alias**, not the versioned
228-
`chromium-1194/chrome-linux/chrome` beneath it: `/opt/pw-browsers/chromium` is a
229-
symlink maintained by the image build, so it still resolves after the image moves to
230-
1243, while the versioned literal stops existing at exactly that moment — and a dead
231-
path copied out of this section is the `absence-inference` trap one level up.
222+
against `ls $PLAYWRIGHT_BROWSERS_PATH`. While the builds agree, the stock
223+
`examples/app-showcase/playwright.config.ts` (no `executablePath`) launches as it is.
224+
When they disagree, every test dies at browser launch and the error names the
225+
**headless-shell** variant it wanted (`Executable doesn't exist at
226+
.../chromium_headless_shell-NNNN/...`), which is the signature to recognise. Then pass
227+
`launchOptions.executablePath=/opt/pw-browsers/chromium` (for the smoke,
228+
`OS_TEST_CHROMIUM_EXECUTABLE_PATH=/opt/pw-browsers/chromium`, which the config reads since
229+
#21060) and the same specs pass. ⚠️ Use that **alias**, never a versioned
230+
`chromium-NNNN/...` path beneath it: `/opt/pw-browsers/chromium` is a symlink maintained
231+
by the image build, so it follows the image from one build to the next, while a
232+
versioned literal stops existing the moment the image moves — and a dead path copied
233+
out of this section is the `absence-inference` trap one level up.
232234
**The discriminator is uniformity:** a launch/environment failure
233235
takes down the whole run at once (`showcase-smoke.spec.ts` generates one test per
234236
`SURFACES` entry — 49 today, so "49 failed" means all of them), while a product defect
@@ -273,22 +275,30 @@ contradicts it, and correct it here when it does.
273275
one is the expensive mistake: the module's own header records that #7516 burned a run
274276
proving it was an address problem by putting a TCP forwarder on 3000, and #7538 fixed
275277
the resolution but could not fix a boot that never exports the variable. **Check:**
276-
before scoring any connector clause, read the instance's own metadata —
277-
`GET /api/v1/meta/connector/showcase_status_api`, field `item.providerConfig.baseUrl`,
278-
which is the value `resolveShowcaseSelfUrl()` produced
279-
(`examples/app-showcase/src/system/connectors/index.ts`). ⛔ Not
280-
`GET /api/v1/automation/connectors`: that route lists registry descriptors — `name`,
281-
`label`, `type`, `description`, `icon`, `origin`, `state`, `degradedReason`, `actions`
282-
(`getConnectorDescriptors()`, `packages/services/service-automation/src/engine.ts`) —
283-
and carries no `baseUrl` at all. On `os dev` the value follows the serving process's
284-
environment, not the compiled artifact. Measured on `main` at `2889760a`: `-p 47311`
278+
before scoring any connector clause, prove where the live dispatch lands: create a
279+
`showcase_task`, read the `showcase_declarative_connector_ping` run it fires, and confirm
280+
it completed with a `ping.body` whose uptime matches THIS boot, not another server's.
281+
⛔ Do not read the instance metadata for it: `os dev` boots the prebuilt
282+
`dist/objectstack.json` unless `--compile` is passed (`packages/cli/src/commands/dev.ts`),
283+
so `GET /api/v1/meta/connector/showcase_status_api`'s `item.providerConfig.baseUrl` can
284+
carry the build-time value. QA run #25817 at `6679644a` measured it: with `OS_PORT=41302`
285+
exported, that read still answered `http://127.0.0.1:3000`, while the live
286+
`connector_action` reached 41302 (`ping.body` uptime matched the boot, and nothing
287+
listened on 3000) — so the metadata read misreports the fixture in both directions.
288+
⛔ Nor `GET /api/v1/automation/connectors`: that route lists registry descriptors —
289+
`name`, `label`, `type`, `description`, `icon`, `origin`, `state`, `degradedReason`,
290+
`actions` (`getConnectorDescriptors()`,
291+
`packages/services/service-automation/src/engine.ts`) — and carries no `baseUrl` at all.
292+
An older measurement, on `main` at `2889760a`, read the metadata as following the
293+
serving environment: `-p 47311`
285294
alone answered `http://127.0.0.1:3000`, and `showcase_declarative_connector_ping`
286295
(fired by a `showcase_task` create) failed `fetch failed`; `OS_PORT=47312` with
287296
`-p 47312` answered `http://127.0.0.1:47312` and the same flow completed, while
288-
`dist/objectstack.json` still held `http://127.0.0.1:3000`. Only an artifact-only boot
289-
(`os start --artifact`) freezes the value at build time (the `self-url.ts` header). If
290-
it names a port your server does not listen on, the fixture is misconfigured, not
291-
blocked. **Fix:** boot with `OS_PORT=<port>` exported (or
297+
`dist/objectstack.json` still held `http://127.0.0.1:3000`. The `self-url.ts` header
298+
still says only an artifact-only boot (`os start --artifact`) freezes the value at build
299+
time; at `6679644a` the served metadata was frozen on `os dev` too, which is why the
300+
Check reads the dispatch. If the ping does not complete, or its uptime belongs to
301+
another server, the fixture is misconfigured, not blocked. **Fix:** boot with `OS_PORT=<port>` exported (or
292302
`SHOWCASE_SELF_URL=http://127.0.0.1:<port>`) *in addition to* `-p <port>`. ⛔ Do not
293303
record a connector clause as `blocked(environment)` on the strength of `fetch failed`
294304
alone.
@@ -491,33 +501,31 @@ contradicts it, and correct it here when it does.
491501
by name and exits **1**, where it used to exit **0** in silence — the entry point is
492502
`packages/cli/bin/run.js`.
493503

494-
- **Some items carry an `automated.ref` that lives ENTIRELY in the `objectui` repo — from
495-
this checkout they are neither runnable nor pin-evidenced.** No count is kept here: the
496-
set moves with every pin re-point and every `automated` edit, and the count this line
497-
used to carry went stale with nothing to notice it (wave anchor #24579). **Find them by
498-
the rule, not by a number:** an item is in the set when its `automated.ref` names an
499-
objectui path and no path that exists in this checkout. Their refs name only
500-
objectui paths (`e2e/live/*.spec.ts`, `e2e/import-console/*`, `e2e/import-harness/*`,
501-
and unit suites under `packages/plugin-grid`, `plugin-gantt`, `plugin-calendar`,
502-
`plugin-form`, `fields`, `core`, `app-shell`). This repository builds no console bundle
503-
and holds none of those specs, so a run here can neither execute the pin nor cite its
504-
output. **Every one of those items now says so in its own `fixtures.knownGaps`** — the
505-
rediscovery this fact exists to stop (each sweep re-derived it from scratch). ⚠️ The
506-
distinction that matters is *exclusive*: items whose `automated.ref` names an
507-
objectui spec **alongside** a framework pin (`packages/qa/dogfood/**`,
508-
`packages/objectql/**`) are partly runnable here — run the framework half and score the
509-
objectui half separately, never one for the other.
504+
- **An `automated.ref` that names an `objectui` path resolves under `ui/` in this
505+
checkout.** objectui was imported into this repository: its specs and unit suites live at
506+
`ui/<path>` (`ui/e2e/live/*.spec.ts`, `ui/e2e/import-console/*`, `ui/e2e/import-harness/*`,
507+
and unit suites under `ui/packages/plugin-grid`, `plugin-gantt`, `plugin-calendar`,
508+
`plugin-form`, `fields`, `core`, `app-shell`), and the console builds from this tree with
509+
`pnpm console:build`. There is no pinned objectui revision any more. Some refs and
510+
`fixtures.knownGaps` written before the import still spell the path without `ui/`, or
511+
still say such a pin is not runnable from this checkout; read the first as `ui/<path>`
512+
and the second as stale. A jsdom unit suite runs with
513+
`pnpm --filter @object-ui/<pkg> exec vitest run --maxWorkers=2 <file>`; a live e2e spec
514+
runs from `ui/` with `pnpm test:e2e:live <spec>` against a live backend and the console
515+
dev server (`ui/playwright.live.config.ts` names both). Items whose `automated.ref`
516+
names an objectui spec **alongside** a framework pin (`packages/qa/dogfood/**`,
517+
`packages/objectql/**`) still score the two halves separately, never one for the other.
510518

511519
**Two honest options, and the run record must say which it took:** (a) drive the item
512520
**by hand** in the browser against a live boot and score it as a manual browser run —
513-
the `automated` field does not make it exempt; or (b) run the pin inside an **objectui
514-
checkout at the pinned revision** and cite that output, **naming the revision** (the
515-
17.1.0 sweep subject was `9a3daf8d37ad`). ⛔ Never record such an item as covered on the
521+
the `automated` field does not make it exempt; or (b) run the pin from this checkout and
522+
cite that output, **naming the commit**. ⛔ Never record such an item as covered on the
516523
strength of the `automated` field alone: an unrun pin is a claim, not evidence — which
517524
is the same "ticking on a label" failure clause-grained acceptance exists to prevent.
518525

519526
- **A walled boot is a fixture of its own: `os serve` boots `group` and `isolated` once the
520-
walled prerequisites are provisioned, and the stock showcase provisions none of them.**
527+
walled prerequisites are provisioned, and the stock showcase provisions only the first —
528+
the other two are environment variables the run sets.**
521529
18.0.0 boots a walled posture: under ruling record 6282882793 on the v18 epic it is
522530
published only after 18.x step 4 (#24580) has merged, and step 4 deleted the boot refusal
523531
(`walledPostureRefusal()` in `packages/cli/src/commands/serve.ts`). Of the builds published
@@ -531,17 +539,15 @@ contradicts it, and correct it here when it does.
531539
so a refusal tells the runner what is missing, never that the posture is unsupported:
532540
1. the multi-org runtime **declared by the app**: `@objectstack/organizations` in the app's
533541
own `package.json` and installed there. Reachable only through `NODE_PATH` or a hoisted
534-
store is refused on purpose (ADR-0093 D5). No example app declares it, so a walled run
535-
uses a scratch app that does: a **full copy** of `examples/app-showcase`, `src/`
536-
included (without `node_modules`, `.objectstack` or `dist`), whose own `package.json`
537-
carries every showcase dependency as a `link:` to its workspace package plus
538-
`"@objectstack/organizations": "link:<abs>/packages/plugins/organizations"`, installed
539-
from the copy with `pnpm install --ignore-workspace` (QA run #24783). A scratch config
540-
that only re-exports the showcase's `objectstack.config.ts` does not boot: a package-file
541-
reference resolves against the root being served, and the showcase's OpenAPI connector
542-
names its document that way (`spec: './src/system/connectors/status-openapi.json'` in
543-
`examples/app-showcase/src/system/connectors/index.ts`, read relative to the package
544-
root at materialization, where a missing document fails the boot);
542+
store is refused on purpose (ADR-0093 D5). `examples/app-showcase/package.json` now
543+
declares it (`workspace:*`), so a walled run boots the showcase from the tree with the
544+
posture and the two variables below exported — `OS_TENANCY_POSTURE`,
545+
`OS_PLATFORM_OWNER_EMAIL`, `OS_AUTH_MEMBERSHIP_POLICY` — and needs no scratch copy (QA
546+
run #25812 at `6679644a`). Before that, QA run #24783 booted a full scratch copy whose
547+
own `package.json` linked the runtime in; a copy that only re-exports the showcase's
548+
`objectstack.config.ts` still does not boot, because a package-file reference such as
549+
the OpenAPI connector's `spec: './src/system/connectors/status-openapi.json'` resolves
550+
against the root being served;
545551
2. `OS_PLATFORM_OWNER_EMAIL`, the deployment's platform administrators: first-registrant
546552
promotion is off under a wall;
547553
3. a declared membership policy, `OS_AUTH_MEMBERSHIP_POLICY` (for example `invite-only`).
@@ -558,7 +564,7 @@ contradicts it, and correct it here when it does.
558564
boot prints `⚠ AuthPlugin skipped — set OS_AUTH_SECRET …` and comes up
559565
`⚠ Server is ready — DEGRADED: missing core services: auth` (`printServerReady()` in
560566
`packages/cli/src/utils/format.ts`), not a FATAL: QA run #24783 measured it with
561-
`os serve --no-ui` from the scratch app, once with prerequisite 2 absent and once with
567+
`os serve --no-ui` from a scratch app, once with prerequisite 2 absent and once with
562568
prerequisite 3 absent. A production `serve` also needs a stable encryption key,
563569
`OS_SECRET_KEY` or a key file an earlier boot persisted; without one `LocalCryptoProvider`
564570
refuses the boot naming `OS_SECRET_KEY`
@@ -576,16 +582,20 @@ contradicts it, and correct it here when it does.
576582
closed: the showcase declares no `auth.audience`, so `POST /api/v1/auth/sign-up/email`
577583
answers **`403 SELF_REGISTRATION_CLOSED`** exactly as on a stock boot
578584
(`decideAudienceAdmission()` in `packages/plugins/plugin-auth/src/audience-posture.ts`; the
579-
entry "A stock showcase boot refuses self-registration" above). QA run #24783 minted every
580-
walled persona as the operator (the seeded admin, the address `OS_PLATFORM_OWNER_EMAIL`
581-
names) with `POST /api/v1/auth/admin/create-user` (`runAdminCreateUser()` in
582-
`packages/plugins/plugin-auth/src/admin-user-endpoints.ts`), then had each persona
583-
`POST /api/v1/auth/change-password`. Under `invite-only` each lands with
584-
`membershipCreated: false` and in no organization (the reconciler's `policy-skip`,
585-
`reconcileMembership()` in `packages/plugins/plugin-auth/src/reconcile-membership.ts`); a
586-
persona that needs an organization creates its own with
587-
`POST /api/v1/auth/organization/create` and switches to it with `set-active` (the next
588-
entry).
585+
entry "A stock showcase boot refuses self-registration" above). The operator (the seeded
586+
admin, the address `OS_PLATFORM_OWNER_EMAIL` names) mints every walled persona with
587+
`POST /api/v1/auth/admin/create-user` (`runAdminCreateUser()` in
588+
`packages/plugins/plugin-auth/src/admin-user-endpoints.ts`), then has each persona
589+
`POST /api/v1/auth/change-password` — but **first creates an organization and makes it
590+
current**: `POST /api/v1/auth/organization/create`, then `set-active` (the next entry).
591+
Under a wall Create User joins the new user to the operator's CURRENT organization as
592+
`member`, `invite-only` included, and an operator with no current organization is refused
593+
`400 NO_ACTIVE_ORGANIZATION` with no account created (PR #25626; QA run #25823 met it at
594+
`17f8217b`). To place personas in two organizations, switch the operator between them
595+
before each create. A persona that needs an organization of its own still creates one
596+
with `POST /api/v1/auth/organization/create` and switches to it with `set-active`. QA
597+
run #24783's reading — each persona landing with `membershipCreated: false` in no
598+
organization — predates that change.
589599

590600
Measured at `45898dbf6`: a scratch app declaring the real runtime, booted by the built CLI
591601
under `isolated` with the other two set, mounted `Organizations`, answered

0 commit comments

Comments
 (0)