Skip to content

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

Closed

Description

@objectstack-fleet

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 branch claude/issue-23992-api-key-ui-revoke-oracle at run time. Its product tree is origin/main e18b23fac; the branch changes docs/qa/platform-checklist/areas/identity-auth.json only. Built with pnpm install --frozen-lockfile && pnpm build (75/75 tasks green).
  • .objectui-sha: f8267df93aba8fb09cc1cc0692eadc0c8c5a5e56. The console was built from that pin by pnpm objectui:build in this tree; pnpm check:console-sha reads "Console dist matches the objectui pin (objectui@f8267df93aba)".
  • host: objectstack dev --ui --seed-admin -p 41873 -d file:(run dir)/data.db from examples/app-showcase, with OS_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, then POST /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 Origin header from 127.0.0.1 and Better Auth refused sign-in 403 INVALID_ORIGIN; with Origin: http://localhost:41873 every call went through. That was the driver, not the product.
  • Checklist accuracy (not a fail of this run): the item's source row for sys-api-key.object.ts says apiMethods ['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

  1. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Close-out (domain:devx seat 2): every clause PASS; nothing to extract. The re-pointed item landed with #24012 (fd0e72abc2), Fixes #23992.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions