Repository navigation
docs(qa): P0 sweep follow-through — re-point query-contract-matrix, correct the run's checklist findings, extend two pins - #21111
Merged
objectstack-fleet[bot] merged 17 commits intoOct 1, 2026
Conversation
…fusal answers acceptance[5] expected 400 INVALID_FILTER on the POST query door for a scalar list comparand; since the request schema took that refusal, the POST door answers 400 VALIDATION_FAILED with a located fields[] entry in both spellings, and only GET $filter still answers INVALID_FILTER. Also records that a dotted fields entry is refused INVALID_FIELD by design (prescribing expand), and moves the widening negative off `filter`, which is a declared transport spelling of `where`. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…/explain The checklist item this file pins names six surface families; the batch and security-explain families were checked only by hand. Both are REST routes opening with enforceAuth, so they join the rest-flat rows of the envelope classification, with a member contrast that proves each route is registered. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
crud-permission-matrix: counts re-measured from access-matrix.json (47 rows; the pin's 164 cells, 87 allow / 77 deny), client_liaison added to the variants, the sys_user 405 cells named, the guest intake clause recorded unobservable on stock, and the delegate pin no longer read as vouching for the dev boot. write-path-guards: updateMany drops a locked field per row, reported on results[i]. rls-both-sides and owd-sharing-matrix: the private D11 handle is disambiguated from FOLLOW-UPS section 7c's public D11 row, and clause numbering is stated. anonymous-deny-surfaces: automated.ref names the six families the pin now drives. The qa-contributor-bound-member recipe and the P0 member items mint personas invite-first under the invite_only default. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…the boot splash The smoke listed 31 of the 49 destinations showcase_app serves; the 18 others are added. Its non-chart check passed on the console's boot splash, whose text is non-empty; the wait now treats the splash as not-yet-rendered and the assertion refuses a surface stuck on it. The config read a hard-coded :3000: SMOKE_API_URL, which global-setup already signs in against, now also drives baseURL and the booted server's port, and OS_TEST_CHROMIUM_EXECUTABLE_PATH lets a container point Playwright at its installed chromium. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
Revenue Pulse draws line/column/donut/bar widgets and the Hours by Status chart report draws a bar chart, so both take the laid-out-chart check the other three chart surfaces take. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
… pin and verify digits nav-surfaces-render names the 49 destinations the smoke now drives, the boot-splash rule, and the SMOKE_API_URL / OS_TEST_CHROMIUM_EXECUTABLE_PATH overrides. RUNNER's environment facts carry the re-measured verify digits (15 verified, 1 needs-fixture, 8 skipped; 10 of 10 positions) and the smoke's new test count and browser override. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…what a stock boot prints At the default warn level a healthy boot prints no SeedLoader success line, so both seed reads now name the level-immune Seeds banner row. boot-health's no-warning clause names the misauthored flow classes, since a stock boot lists its policy-disabled scheduled flows with a warning glyph. packaged-action-disabled-dispatch records that the MCP endpoint is drivable live on a stock boot. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…wire and the host command No showcase persona carries both RLS-hidden rows and an FLS-masked field on one object, so the item names a contributor-bound member for RLS and a client_liaison-bound member for FLS. The aggregate refusal is scored on its message, since neither wire serializes forbiddenFields. Step 1 hosts the transport with os start: measured on a stock boot, os dev prints a 15-line banner to the stdout the stdio channel owns, os start prints none. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…t codes and the banner caveat Three steps write into the app directory they run in, so they need one no other runner boots. The exit-code capture now states what to expect (SIGINT 0, --fresh SIGINT 130, no config 1), and the Dev admin banner row is no longer readable as seeding evidence, since it reprints on later boots while the default password still works. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…ock boot serves The wizard refuses an alias-spelled credential 400, so planting a legacy row needs a stopped-server metadata write; the admin door updates by PATCH (PUT answers 405) and is the one carrying hasSecret and redactedConfigKeys; the metadata read path is spelled out; and the two refusal entries the source list missed are added. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…k boot renders console-login: the expiry clause verifies after the server-side sign-out its own step prescribes, and the landing page is the header plus launcher without a sidebar by design. builtin-apps-nav-render: Setup 45 and Account 8 destinations re-measured on a stock dev boot, the member persona is the seeded plain persona (a fresh sign-up is refused), and the marketplace catalog's cloud egress dependency is a known gap. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…he restricted delete No showcase object gives the clone clause a populated readonly column, so that half is recorded unobservable with the system-side way to make it observable. An own-row invoice pointing at the run's account turns the later delete into a 409, so the recipe and the delete step say to point it at a seeded account. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
…b vocabularies and a readable row The locale clause names the zh-CN option the showcase offers, the tab clause lists both locales' labels, the record-link clause needs a row the persona can read, and the fixture asks for a sign-off launched after the persona holds its positions. The seeded personas are loginable; the reason to provision one is their positions. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
The object is named with the package namespace prefix, the New object dialog carries a pre-selected sharing-model choice, a new app's nav is scaffolded by default, the read-only negative probe is a forged request because the console hides authoring there, and the cited objectui pin targets testids absent at the pin. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
Contributor
📓 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. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
This was referenced Oct 1, 2026
…rs that mint a member A stock showcase declares no audience, so an uninvited sign-up answers 403 SELF_REGISTRATION_CLOSED and no item can mint a member by a fresh sign-up. One Environment-facts bullet names the posture, the refusal site, and the two doors (invite-member then sign-up, or admin create-user then change-password), with the shared contributor-bound recipe as the worked example. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
Resolves the two conflicts with the analytics anonymous-deny change by keeping both sides: the dogfood pin carries the analytics faces and the /batch + /security/explain cases; access-security.anonymous-deny-surfaces keeps main's revision-2 analytics entry, takes revision 3 for this branch's entry, and its automated.ref names all seven families. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
objectstack-fleet
Bot
deleted the
claude/issue-21060-p0-sweep-checklist
branch
October 1, 2026 08:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #21060
Clause-②: no
This finishes QA run #21056 (the 2026-10-01 P0 release sweep). It re-points the one stale red row and corrects the run's checklist-accuracy findings, citing source or a local measurement for each one. It also brings two pins up to date. No product code changes. The run's product defects stay on their own cards: #21052, #21057, #21058, objectstack-ai/objectui#11326 and objectstack-ai/objectui#11327.
1. The re-point:
api-backend.query-contract-matrix(rev 2 → 3)$ninon POST/queryanswers400 INVALID_FILTERin both spellings400 VALIDATION_FAILEDwith a locatedfields[]entry (query.where.status.$ninfor the object body,query.wherefor the AST). GET$filter:400 INVALID_FILTER. Never a 500, never a widened 200. A GET twin probe is added to step 8FilterConditionSchema.superRefine(checkFilterConditionComparands)andlowerFoldedTransportValues(spec). The POST door answers aFindDataRequestSchemafailure asVALIDATION_FAILED+fields[](rest-server.ts). Local parse of both bodies refused at exactly those two paths. The POST-door posture is pinned byrest-server-repeated-filter-param.test.tsandanalytics-filter-refusal-envelope.test.tsfields: ['account.name']counted as narrowing400 INVALID_FIELDby design, with the message namingexpandprotocol.ts#assertProjectionFieldsExist{"filter": …}filteris a declared transport spelling ofwhere, so it is served. The probes are now a mistyped clause (400 VALIDATION_FAILED) and an undeclared key (400 INVALID_FIELD)QueryTransportParamsSchema;protocol.ts#assertQueryParamsAreFields;request-schema-gate.conformance.test.tsA residual for the maintainer (not a defect): the same condition answers
VALIDATION_FAILEDon POST andINVALID_FILTERon GET (the #8001 family).2. Checklist-accuracy findings: what changed, old → new
access-security.crud-permission-matrix(3 → 4).showcase_*+ 6 delegatesys_*), and the pin's 164 cells (87 allow / 77 deny). The same 9 cells are granted only by the baseline. All of this was recomputed fromaccess-matrix.jsonwith the pin's union rule.showcase_client_liaisonjoins the variants and the seeded-set list.405 OBJECT_API_METHOD_NOT_ALLOWEDforsys_usercreate/delete, for every caller. Source:sys_userapiMethodsis get/list/update/bulk, andenforceApiAccesshas no admin bypass.automated.refno longer reads the permission-zoo pin as covering the dev boot ([finding] The delegated-admin gate resolves an EMPTY subtree on a stockobjectstack devboot — seeded business units are organization-less while every session carries an active organization, so every in-scope delegated write is refused #21057).owner_only_writes/owner_only_deletes).access-security.write-path-guards(2 → 3).results[i].droppedFields. Source:updateManyDatacallsengine.updateper row with its own drop listener.access-security.rls-both-sides(4 → 5) andaccess-security.owd-sharing-matrix(2 → 3), plusFOLLOW-UPS.md§7c.acceptance[N], and a run record's A(N+1).access-security.anonymous-deny-surfaces(1 → 2).automated.refnow names all six families the pin drives (see §3).searchrecipeqa-contributor-bound-member.invite_only(migration entryaudience-posture-default-invite-only), and an uninvited sign-up answers403 SELF_REGISTRATION_CLOSED.ai.mcp-stdio-fail-closed(3 → 4).readable: falsegrants are client_liaison's, onpublic_read_writeshowcase_project.details.forbiddenFieldson the wire. REST'sPERMISSION_DENIEDarm answers{error, code, object}.os start. Measured:os devprinted 15 banner lines to stdout, andos startprinted 0.api-backend.packaged-action-disabled-dispatch(2 → 3). The MCP door is drivable live: the stock banner printsMCP: …/api/v1/mcp.platform-core.boot-health(5 → 6) andplatform-core.seed-integrity(2 → 3).Seeds:banner row. At the default warn level, a healthy boot prints no SeedLoader line (seed-summary.ts).printAutomationSummary).cli.dev-boot-contract(2 → 3).devwith the child's code (0).--freshSIGINT exits 130 (dev.ts,ServeRestartCoordinator).🔑 Dev adminbanner reprints on later boots and is not seeding evidence (maybeReportExistingSeedAdmin).integration-system.datasource-credential-refusal-matrix(1 → 2).POST /api/v1/datasourceswithpasswdanswered400 DATASOURCE_ADMIN_ERROR.hasSecret/redactedConfigKeys.GET /api/v1/meta/datasource/NAME. Measured: 200.sourcegains the mongo composed-branch twin and the nested-options spelling entry.platform-core.console-login(3 → 4)./_console/homerenders the header and the launcher, with no sidebar by design (objectuiHomeLayout).platform-core.builtin-apps-nav-render(3 → 4).nav_connect_agent.demo-personas.ts).records-forms.crud-roundtrip(7 → 8).showcase_account, noapproval_statusanywhere, andlead_scoreis null on every seeded contact.409 DELETE_RESTRICTED. Cause: a required lookup turnsset_nullintorestrict(engine.ts).approvals.account-app-entry(1 → 2).zh-CNoption is 中文(中国), and there is no barezh.RecordCell, href null).finance.studio-authoring.first-run-loop(2 → 3). Each point below was grounded in objectui at the pin:repairs_repair_ticket, because the dialog prefixes the package namespace (prefixObjectName).package-id-input/package-name-input, which no source file declares at the pin.RUNNER.mdEnvironment facts.15 verified, 0 gaps, 0 FAILED, 1 needs-fixture, 8 skipped.verify --rlsprobes10 of 10positions, and the all-personas line is unchanged.objectstack verify --rlson this branch.3. The two pins
showcase-anonymous-deny-surfaces.dogfood.test.ts.POST /batch(empty operation list) andGET /security/explainat 401, each with a member contrast (not 401, not 404).286870908c): merged with main's analytics anonymous-deny change (security (P0 suspect): a non-system caller who resolves no permission set — an unauthenticated one included — is admitted to aggregate any object at an analytics door, object admission and row scope skipped #21061), keeping both sides. The pin now runs 61 cases (this PR's 6 plus its 13 analytics cases), and all 61 passed on the rebuilt closure.showcase-smoke.spec.ts+playwright.config.ts.showcase_appserves. The 18 added ones are derived fromsrc/ui/apps/index.ts, including the three filter slices spelled the way objectui's nav renderer builds them. Revenue Pulse and the Hours by Status chart report are chart surfaces.SMOKE_API_URLfor baseURL and the booted server's-p.global-setup.tsalready signs in against that URL. It also readsOS_TEST_CHROMIUM_EXECUTABLE_PATHfor the browser. Unset, everything stays on port 3000 exactly as before (CI sets neither).Tests (union re-run on
de73aa8444, after mergingorigin/main)pnpm check:platform-checklist. Before, on the base6f578888a8: exit 1, with one problem, the pre-existingidentity-auth#twoFactorrow. After, onde73aa8444: exit 0,15 areas, 269 items.node scripts/check-platform-checklist.mjs --self-test: exit 0 (221 assertions).pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/showcase-anonymous-deny-surfaces.dogfood.test.ts. Result:48 passed (48), on a rebuilt closure.scripts/ablation-replace.mjs. Each mutation was proven on disk, and each restore was proven by blob == HEAD:expected 404 to be 401,expected 404 not to be 404).SMOKE_API_URL=http://localhost:43871 OS_TEST_CHROMIUM_EXECUTABLE_PATH=/opt/pw-browsers/chromium pnpm exec playwright test e2e/showcase-smoke.spec.ts, against a console built at the pin (e420df310f5b). Result:49 passed (2.6m). The server booted on 43871 and was down afterwards.pnpm --filter @objectstack/dogfood typecheckandpnpm --filter @objectstack/example-showcase typecheck: exit 0. Both programs include the edited files.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 55 families, all run. 54 exit 0. NOT MEASURED:check:dual-build-cjs-loads, reason "PREREQUISITE NOT MET": 8 untouched packages have nodist/in this container.check:type-check-debtexit 0 on a clean standalone re-run; an earlier run's log was clobbered by a timed-out batch.Card findings NOT acted on, and why
owd-sharing-matrixstep 1 / crud persona recipe ("grant the position, not the set directly"). The reason is withheld pending the maintainer (RUNNER rule 2, [showcase][security] An owner-isolation policy in the showcase's contributor permission set does not hold for every way a member can hold the set — detail withheld pending maintainer #21052). It cannot be grounded publicly, so it is left untouched.identity-auth.json(open-PR concurrency). That sweep is left for the PM: an open question, a RUNNER fact versus a per-item sweep.db092de284): the residual items are now covered by one RUNNER "Environment facts" bullet. It states the stockinvite_onlyposture, the403 SELF_REGISTRATION_CLOSEDrefusal, and the two doors (invite-member then sign-up, or admin create-user then change-password), withsearch:qa-contributor-bound-memberas the worked example. This follows the seat's ACCEPT on the open question, option A.records-forms.crud-roundtrip"list quick-search text persists across reloads". I could not confirm this from objectui source at the pin, so it is not written as fact.Acceptance notes
datasource-credential-redaction.tsdocblock still says the wizard persists through a structural name/label check. A live probe refuses an alias key 400, so this is comment drift; no carrier found.external.credentialsRefbound + discrete mongo fields naming nousernameis the same silent no-op, unrefused #9147. This is spec registry text, outside this ledger.Line budget
15 files changed: +375 / −130 against
origin/main. Breakdown:Generated by Claude Code