Repository navigation
QA run · identity-auth.api-key-ui-lifecycle (1/1) · e1e711ae · 2026-10-16 · 1 PASS / 0 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #24011
Description
Run record for the re-run #23992 asks for, after the item's stale revoke oracle was re-pointed (step 4 and acceptance[2]: 401 → 403 with error.code API_KEY_REVOKED and no rows). Runner: an os-dev subagent dispatched by the domain:devx seat 2 PM (session session_016PVjjuVPte5XEJvaQx1E4t). Protocol: .claude/skills/checklist-test/SKILL.md + docs/qa/platform-checklist/RUNNER.md. Executed sequentially (no subagent tool in this runner).
Environment fingerprint
- framework:
e1e711ae259c785a4b87009a0576a64546ee8764, the tip of branchclaude/issue-23992-api-key-ui-revoke-oracleat run time. Its product tree isorigin/maine18b23fac; the branch changesdocs/qa/platform-checklist/areas/identity-auth.jsononly. Built withpnpm install --frozen-lockfile && pnpm build(75/75 tasks green). .objectui-sha:f8267df93aba8fb09cc1cc0692eadc0c8c5a5e56. The console was built from that pin bypnpm objectui:buildin this tree;pnpm check:console-shareads "Console dist matches the objectui pin (objectui@f8267df93aba)".- host:
objectstack dev --ui --seed-admin -p 41873 -d file:(run dir)/data.dbfromexamples/app-showcase, withOS_PORT=41873. Fresh DB, seeded admin. - browser: Playwright through
/opt/pw-browsers/chromium(Chromium 141.0.7390.37), headless, one browser context per persona. - personas: the seeded admin (platform admin); two members minted by invite + sign-up (
POST /api/v1/auth/organization/invite-member, thenPOST /api/v1/auth/sign-up/email), the key owner and a second member; a second pair minted the same way for the two-owner scoping leg. - timestamps: 2026-10-16, 18:28Z to 18:32Z.
Scope
Selector identity-auth.api-key-ui-lifecycle resolves to 1 runnable item: identity-auth.api-key-ui-lifecycle at revision 2, P1, surface mixed. Revision 2 is the revision #23992's branch carries. The item has no automated.ref, so every clause was driven (Tier 2).
Per-clause verdicts
| item | # | clause (short) | verdict | evidence |
|---|---|---|---|---|
| identity-auth.api-key-ui-lifecycle | 0 | secret shown exactly once | pass | POST /api/v1/keys (owner) 201 with data keys id, name, prefix, key, active_organization_id, expires_at, raw key 47 chars; owner GET /api/v1/data/sys_api_key/KEY_ID 200 with no key field (prefix osk_qJhGmHRe); admin get-by-id 200, no key field; the owner's user_id-filtered list 200, 1 row, raw value absent; console: Generate key on the Integrations page answered 201, the dialog showed the raw value, and after Done the raw value is absent from the page |
| identity-auth.api-key-ui-lifecycle | 1 | key authenticates as its owner, not a superuser | pass | GET /api/v1/data/showcase_task with x-api-key 200, 10 rows; the owner's session read 200, 10 rows, identical id set. Discriminating object showcase_inquiry: admin 3 rows, owner session 0, owner key 200 with 0 |
| identity-auth.api-key-ui-lifecycle | 2 | revoke immediate, server-side, 403 API_KEY_REVOKED |
pass | owner PATCH /api/v1/data/sys_api_key/KEY_ID {"revoked": true} 200 (row reads back revoked: true); the very next x-api-key read 403, body {"error": {"code": "API_KEY_REVOKED", "message": …}}, no rows; repeated: same. Through the console row action Revoke API Key (confirm "Revoke this API key? …" → Continue): the request was PATCH /api/v1/data/sys_api_key/KEY_ID body {"revoked":true}, 200; the next two x-api-key reads 403 API_KEY_REVOKED, no rows. Control: an unrecognised osk_ key 401 UNAUTHENTICATED. The message's wording was not scored |
| identity-auth.api-key-ui-lifecycle | 3 | restore reversible (200) | pass | owner PATCH … {"revoked": false} 200; next x-api-key read 200, 10 rows, same id set as the session read. Through the console row action Restore API Key: PATCH body {"revoked":false} 200; next read 200, 10 rows |
| identity-auth.api-key-ui-lifecycle | 4 | mine-view scoped; admin all_keys shows every user's | pass | the second member: user_id-filtered (mine) list 200, 0 rows, owner key absent; unfiltered list 200, owner key absent; get-by-id of the owner key 404. Two-owner leg: each member's mine list holds its own key and not the other's; the admin's list 200, 3 keys across 3 owners, both included. Console: the member's app list is showcase_app, account (no Setup); Setup → API Keys (all_keys) as admin lists 4 keys across 3 owners |
| identity-auth.api-key-ui-lifecycle | 5 | dialog and list render (screenshot) | pass | dialog: title "Your new API key", "Copy this now — for your security it will not be shown again.", the secret in a monospace field beside a Copy button, Done. The re-opened list (account app, My Keys, mine view) shows name + prefix rows (osk_c1auWsef, osk_qJhGmHRe), no secret; request GET /api/v1/data/sys_api_key 200 |
Negatives: none hit. No raw secret on any second read (list, get-by-id, re-opened page); no revoked key answered 200 or served a row; no post-revoke refusal was a generic 401 or carried another code; the key read no more than its owner's session; no key appeared in another member's mine view.
Traps ruled out: wrong-persona (the key owner and the second member are plain members, not admins; the admin persona is used only for the all_keys leg); hydration-race (every list and dialog verdict was read after the network settled and after a screenshot confirmed the surface rendered).
Derived item verdict
identity-auth.api-key-ui-lifecycle r2: pass (6 of 6 clauses).
Notes, not defects of this item:
- The first API attempt sent no
Originheader from127.0.0.1and Better Auth refused sign-in 403INVALID_ORIGIN; withOrigin: http://localhost:41873every call went through. That was the driver, not the product. - Checklist accuracy (not a fail of this run): the item's
sourcerow forsys-api-key.object.tssaysapiMethods ['get','list']; the object declares['get', 'list', 'update'](update is what the revoke/restore PATCH rides). Handed to the dispatching seat, not extracted.
Timing: environment about 17 minutes (pnpm build 8m42s and pnpm objectui:build 8m07s under the verify lock), legs about 4 minutes.
Nothing is extracted from this record.
Activity
objectstack-fleet commentedon Oct 17, 2026
Close-out (
domain:devxseat 2): every clause PASS; nothing to extract. The re-pointed item landed with #24012 (fd0e72abc2), Fixes #23992.Generated by Claude Code