Repository navigation
QA run · release-18.1.0-browser-retest-new-pin (9/9) · d44c8936 · 2026-10-23 · 6 PASS / 2 PARTIAL / 1 FAIL / 0 BLOCKED / 0 NOT-RUN #25517
Description
This record re-drives the browser-observed items of the 18.1.0 manual sweep on the new console pin, after #25455 moved .objectui-sha 5fef032b1ada → 6fb31dcc9954 (12 objectui commits, including objectui#13370, which fixes the #25438 console build break). The first measurements are QA run #25478 (P0) and QA run #25479 (extended set), both on main 77392e9. The set was named by hand: the nine items whose verdicts read the console. Every item has a verdict (9/9), and every clause was re-measured live rather than copied.
Environment fingerprint
- framework
d44c8936b1a2(mainafter chore(console): move the objectui pin 1d178e06ac5e → 6fb31dcc9954, past objectui#13370, so the console builds against the spec again #25455)..objectui-sha=6fb31dcc9954844b2631ecfa96e999c4f73c4881. - console: built by
pnpm objectui:builddirectly on thismainat the pin, with no sibling-worktree deviation this time.packages/console/dist/.objectui-shaequals the pin.pnpm buildwas 76/76. - boots: stock showcase via
objectstack dev --ui --seed-admin, withOS_PORTexported. Each runner had its own ports (47701 / 47711–47712 / 47721–47722) and its own file DBs. Health was 200 within 14–26 s. - browser: playwright-core 1.63.0,
/opt/pw-browsers/chromium, headless, one context per persona, with identity proved throughget-session. - execution: three runner agents (login/nav/CRUD · account/first-run/feedback · approvals/actions). All servers were stopped by process group, and
git statusstayed clean.
Scope and verdicts
| item | priority | rev | verdict | vs first run |
|---|---|---|---|---|
| platform-core.console-login | P0 | 4 | PASS | same |
| platform-core.builtin-apps-nav-render | P0 | 7 | PARTIAL (marketplace catalog blocked(environment): 502 MARKETPLACE_PROXY_FAILED, egress denied) |
same |
| records-forms.crud-roundtrip | P0 | 13 | PASS | same |
| approvals.account-app-entry | P0 | 4 | PASS | same |
| studio-authoring.first-run-loop | P0 | 6 | PASS | same |
| approvals.record-page-decisions | P2 | 4 | FAIL (negative[1], objectui#13393 still reproduces) | same |
| approvals.inbox-metadata-actions | P1 | 5 | PASS | same |
| records-forms.action-location-matrix | P1 | 14 | PARTIAL (A3 fail-closed half not consultable on stock; A4 half (a) blocked(fixture), knownGaps) | same |
| ux-conventions.write-feedback | P1 | 4 | PASS | same |
Derived: 6 PASS / 2 PARTIAL / 1 FAIL / 0 BLOCKED / 0 NOT-RUN. No item verdict changed against the first run. The P0 subset is 4 PASS / 1 PARTIAL / 0 FAIL.
Per-clause evidence
platform-core.console-login
Driven on two fresh contexts with identical results.
- A1 pass: sign-in 200 sets the session cookie and lands on
/_console/home(launcher, no sidebar). - A2 pass: after a reload on a showcase route,
get-session, discovery andmeta/appall return 200 and the URL is unchanged. - A3 pass: sign-out returns 200. The same bearer then gets 401
UNAUTHENTICATED. - A4 pass: navigation redirects to
/login?redirect=…. - A5 pass: re-login lands on the same route; the data read returns 200 and the write 201.
- negatives hold: a wrong password gives 401
INVALID_EMAIL_OR_PASSWORD, sets no cookie, and shows a named alert.
platform-core.builtin-apps-nav-render
- A1 blocked(environment) on the catalog leg only. Setup renders 42/42 served destinations and Account 8/8, with 0 pageerror. Browse Marketplace shows a named "Failed to load marketplace · HTTP 502" state.
- A2 pass: the served Setup and Account nav payloads are byte-identical to the first run (9 groups with 42 leaves; 8 leaves).
- A3 pass: the member sees a named "You don't have access to this app" page (
/meta/app/com.objectstack.setup403), and Account opens on Profile. - A4 pass: forged requests as the member give
?id=setup200items:[]and the direct reads 403PERMISSION_DENIED. - A5–A6 pass: entry, service and object gates resolve to absence as before.
- A7 pass: off-capability destinations are absent.
- pin delta (objectui#13365): navigation groups now start open unless the payload declares
expanded:false. Only Setup › Advanced and Account › Developer start closed.
records-forms.crud-roundtrip
- A1 pass: create 201, every value verbatim.
- A2 pass: the PATCH body is only
annual_revenue; a full-row diff shows that field andupdated_at. - A3 pass: delete 200, then total 0 and
RECORD_NOT_FOUND. - A4 pass: the list is correct after a clean reload.
- A5 pass: History shows display values.
- A6 pass: a CJK name round-trips byte-identical, and
$searchreturns 2 hits. - A7 pass: the clone re-derives owner and autonumber, and a planted readonly
lead_scoreis reported indroppedFields. - A8 pass: a contributor cloning an RLS-invisible invoice gets 404
RECORD_NOT_FOUND. - negatives hold: empty name is blocked client-side, API missing name gives 400
VALIDATION_FAILED, and a badtax_idgives 400invalid_format.
approvals.account-app-entry
- A0 pass: the stamp equals the pin, and the entry chunk registers
approvals:inbox. - A1 pass: Avatar › Profile › Inbox › Approvals renders My Pending (2) / Submitted by me / All, with 0 pageerror. There is now exactly one
mainlandmark (objectui#13366). - A2 pass: the persona's app list is
[showcase_app, account], and setup is 403. - A3 pass: the record page bar matches the declared predicates. Approve returns 200 and progress moves from 0 of 2 to 1 of 2. The persona leaves
pending_approversand the bar is removed. - A4 pass: a cold deep link
?request=<id>redirects to the request record page on 3 fresh contexts. - A5 pass: the invoice href keeps
com.objectstack.account. - A6 pass: under zh-CN the nav reads 待我审批 and the tabs and badge are translated.
studio-authoring.first-run-loop
- A0 pass: package create returns 201 with no page load.
- A1 pass: the picklist needs options before save. Publish all returns 200, and the served options are exactly open / in_progress / done.
- A2 pass: Studio Add record returns 201 with
status:in_progress. - A3 pass: the Repair Center app nav is served, the launcher lists it, and the end-user list shows an "In Progress" chip.
- A4 pass: one boot throughout, and the listener pid was unchanged across the loop.
- A5 pass: the forged writes into
com.example.showcasegive 422WRITABLE_PACKAGE_REQUIRED(new object) and 403ITEM_LOCKED(add field). Nothing landed.
approvals.record-page-decisions
Fixtures: four project budget PATCHes. One was approved through manager_review, which opened an exec_review request with lock_record:true.
- A0 pass: the declared action bar sits above the body, not inside the header.
- A1 pass: Reject opens exactly one dialog with a comment and a file input. Nothing posts before Confirm. One POST to the request id returns 200.
- A2 pass: the decisions persist (
rejected/approved), and the action rows carry the comments. - A3 pass (admin side, as the steps scope it): lock true shows the "Locked for approval" band, Edit disabled, and 0 inline affordances. Lock false shows "In approval · editable" with affordances.
- A4 pass: a forged member approve or reject gets 403. An off-slate admin sees the Override variants. The member sees no declared actions.
- negative[1] VIOLATED, still reproduces (objectui#13393):
- A contributor member who is not a participant opens the lockRecord:true record and sees 12 inline-edit affordances, an enabled Edit and no lock band.
- Saving answers 409
RECORD_LOCKED. - Reproduced on 5 fresh loads, and again on a separate fresh-DB boot.
- The admin on the same record and script sees the lock correctly.
resolveApprovalLock(packages/react/src/context/InlineEditContext.tsx) is unchanged at 6fb31dcc. The fix is not in this pin.
- negatives [0] and [2] hold.
approvals.inbox-metadata-actions
- A0 pass: the approver's request page shows the declared approver set.
- A1 pass: the button sets differ by flags. The approver gets no Send reminder or Recall. The admin off-slate gets the Override variants. The admin as submitter gets Send reminder and Recall.
- A2 pass: every rendered set equals the declared
visibleCEL for the read's flags. - A3 pass: approve returns 200 and the request becomes
approved. Remind returns 200 and the request stayspending. - A4 pass: exactly one new
/actionsrow per decision. - negative holds.
records-forms.action-location-matrix
- A0 pass: all six surfaces render the declared placements (list_toolbar, list_item, record_header, record_more, record_related, record_section).
- A1 pass: no extra placements.
- A2 pass: all six dispatch kinds round-trip:
- flow wizard: resume 200, and the assignee is re-read.
- modal: opens.
- form page: routes to the form.
- script: Mark Done 200,
donefalse→true. - url: popup requested; it renders an egress error.
- api: recalc 200,
estimate_hours40→136.
- A3: both visible sides pass. The fail-closed half cannot be consulted on stock, because booleans are validated server-side and no throwing predicate exists.
- A4: half (b) passes, and
showcase_new_task(locations:[]) is absent everywhere. Half (a) is blocked(fixture) (knownGaps).
ux-conventions.write-feedback
- A0 pass: all 14 driven writes landed (server read) and showed non-empty feedback: create ×2, inline edit ×2, bulk delete, kanban, Mark Done, invite, approval, import, Studio autosave/publish/discard, settings save.
- A1 pass: the messages name the record, invitee or count. "Task created successfully" and "Settings saved" are the remaining object-only strings, an open ruling question unchanged from the first run.
- A2 pass: the declared success messages render verbatim.
- A3 pass: an empty title is blocked client-side with a named field error. An invalid kanban transition gives 400, a named error toast and live region, and the card reverts.
- A4 pass: a no-op edit sends 0 writes and shows no toast.
- A5 pass: import Undo restores the data in both update and create modes.
- pin deltas: toasts now render top-centre (objectui#13363). Studio Discard now confirms in-app (objectui#13368), where it used a native confirm before.
Probes (rule 8)
About 23 minutes in total, across the three boots, as admin, Mei, a contributor member and a non-override approver. Door classes tried:
- clone, PATCH and DELETE boundaries;
- session expiry inside the app;
?request=with empty, unknown and whitespace values;- re-decide and terminal-state decisions;
- non-participant levers;
- headless and unknown actions;
- RLS-invisible rows;
- Setup deletes;
- toast placement at 390 px;
- import Undo.
Findings:
- Prior cards still reproduce: plugin-approvals: reassign accepts a
tothat resolves to no principal and strands the request on an unresolvable slate #25485 (reassign to a nonexistent principal answers 200 and strands the request) and plugin-approvals: authorization-adjacent disclosure on the approval request doors (detail withheld pending maintainer) #25487 (detail withheld pending maintainer). - No new finding passed the filing gate.
Low or cosmetic observations, not filed:
GET /approvals/requests?object=X&recordId=with an emptyrecordIddrops the empty predicate. It answers all of the caller's requests, still within participant scope.- An in-app session expiry shows a named "Sign in required · Retry" state in the shell, without redirecting to login.
- The single-record delete toast is the generic "Record deleted", while bulk delete names the count.
- Import "Undo import" still uses a native
window.confirmand shows no toast. - At 390 px the top-centre toast covers the app bar while it shows.
- The seeded EXP-DEMO 2-of-3 committee has the admin in all 3 slots, so one approve closes it. This is a seed shape.
Checklist-accuracy notes (for the sweep's anchor card)
- builtin-apps-nav-render:
- steps[2]: Configuration is no longer collapsed. Only groups declared
expanded:falsestart closed. - A link-based walk counts one extra "All reports" link per app, so count from the payload.
- steps[2]: Configuration is no longer collapsed. Only groups declared
- console-login: sign-in answers 200, not 201.
- crud-roundtrip:
- The New form also submits the defaulted
industry. - The formula re-derivation is still unobservable.
- The New form also submits the defaulted
- account-app-entry:
- acceptance[6].verify: Language is now a direct avatar-menu row, not under Preferences.
- acceptance[3] still says "drawer".
- inbox-metadata-actions:
- Steps 2, 3 and 6 say "drawer"; the inbox opens the request record page.
- The tabs render as My Pending / Submitted by me / All.
- Name the Request cell, because the Record cell opens the business record.
- write-feedback:
- variants[10] "accept the native confirm" is stale, since Discard confirms in-app.
- variants[6] still says "drawer".
- knownGaps[3] "no stock surface offers Undo" is stale.
- steps[3]: the stock member has no edit affordances, so use the contributor binding.
- record-page-decisions: clause 3 is admin-scoped by its steps while negative[1] is unscoped. The scope ruling is still open.
- action-location-matrix:
- The Log Time form heading is the machine name
showcase_task.form. - The Recalculate Selection toast says "whole selection" on a single-record dispatch.
- The fail-closed half needs a packaged throwing-predicate specimen or a knownGap line.
- The Log Time form heading is the machine name
Extraction
No new product defect was found on this pin. The one FAIL is the existing card objectui#13393 (extracted from QA run #25479 as #25480 and transferred), and it is unchanged at 6fb31dcc. Its fix still has to land and then move the pin.
Environment vs test time: about 15 minutes on environment (install, build, console build, boots, personas) and about 70 minutes of runner test time across three parallel runners, including probes.
Activity