Skip to content

fix(spec,platform-objects): register sys_api_key's deliberate no-batch decision, unblocking every spec PR (#7802) - #7818

Merged
os-help merged 1 commit into
mainfrom
claude/issue-7802-sys-api-key-batch-conformance
Aug 11, 2026
Merged

fix(spec,platform-objects): register sys_api_key's deliberate no-batch decision, unblocking every spec PR (#7802)#7818
os-help merged 1 commit into
mainfrom
claude/issue-7802-sys-api-key-batch-conformance

Conversation

@os-help

@os-help os-help commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Part of #7802Part of, not Fixes, on purpose: this unblocks main and
settles the object-vs-rule decision, which is the half the filer's correction
comment scoped to a bounded choice. The issue's other half (the affected-subset
CI that cannot gate a cross-package conformance scan) is untouched, so merging
this should not auto-close the card. See the last note below.

main was red for every PR touching packages/spec: #7769 gave sys_api_key
update (so the Setup UI's Revoke button had a working route) without bulk,
and api-methods-batch-conformance.test.ts enforces "a whitelist that grants
single-record writes must also grant bulk". #7769's grant is correct and is
untouched here.

The test documents exactly two resolutions. This PR takes the second — a
registered SINGLE_RECORD_WRITE_ONLY exemption carrying its evidence — rather
than widening the object.

What decided it

The test's own comment names the deciding consideration: batch denial is
invisible until a user multi-selects rows and gets a 405. So the question was
whether that surface exists. Both halves were read off the console build this
release pins (.objectui-sha 6314e87f2), not off a local objectui checkout —
the pin is newer than the local tree and the relevant files had moved.

1. No checkbox column is rendered for this object. None of sys_api_key's
four list views declares bulkActions, bulkActionDefs or selection.
ObjectGrid auto-enables multi-select only when a bulk action exists
(hasBulkActions gates selectionMode), and the only implicit one is
bulk-delete, which rides objectCanDelete — false here three times over:
managedBy: 'better-auth' denies delete by default, userActions opens edit
alone, and delete is not in apiMethods. There is no selection to batch.
(The pinned build additionally narrows this verdict by the principal's
/me/permissions allowDelete — narrowing only, so the conclusion is
unchanged.)

2. A future multi-select revoke would still not reach /batch.
revoke_api_key / restore_api_key are locations: ['list_item'] actions.
Naming one in a view's bulkActions promotes it to operation: 'custom' plus
actionDef, which useBulkExecutor fans out through the action runner as N
single-record PATCHes (PROMOTED_BULK_BATCH_SIZE = 25) against exactly the
route #7769 opened. The data-plane bulk primitive is reached only by an
update / delete bulk def, which this object neither declares nor can
acquire implicitly. So the exemption does not block the plausible product
surface; it would work on update alone.

3. No client path batches API keys today. Nothing in either repo calls
updateMany / deleteMany / /batch against sys_api_key, and the console's
API-key surfaces are the generic metadata-driven grid plus
IntegrationsPage / AgentConnectSection, which mints keys and never revokes
in bulk.

Granting bulk would therefore open POST /api/v1/data/sys_api_key/batch and
the *Many routes to every API client, on a better-auth identity table whose
authorable surface is the single revoked boolean that ADR-0092 D2's write
guard admits — capability expansion with no caller.

The third question: is anything else in the same position?

No. Walking every *.object.ts in the repo — not just under packages/,
which is the scan's own radius — 102 object files carry 58 apiMethods
whitelists, and sys_api_key is the only one granting a single-record write
without bulk. Nothing else is escaping the scan by luck.

Reverse verification

Both directions were predicted before running, and both are of the deleted-limb
kind rather than a plain re-run:

Tree state Predicted Observed
main, before the change test 3 red, one offender red: sys_api_key: [get, list, update] grants single-record writes but not 'bulk'
exemption removed, object unchanged test 3 red again red, same offender line (1 failed / 3 passed)
bulk added to the object, exemption kept test 3 green, test 4 red test 4 red: stale is ["sys_api_key"] (1 failed / 3 passed)
this PR all green 4 passed

The third row is the load-bearing one: the exemption and the grant are mutually
exclusive by construction, so the entry cannot silently outlive its reason.
Someone adding bulk later is forced to retire the exemption in the same
commit.

The "confirm you have not opened a route the identity write guard should still
refuse" check does not apply on this route — no route is opened. The guard is
untouched, and POST /data/sys_api_key/batch keeps answering 405 at the
ADR-0049 method gate, before authorization runs.

Verification

  • pnpm --filter @objectstack/spec test — 378 files / 9948 tests passed (was
    1 failed / 9947 passed on the same tree before the change).
  • pnpm --filter @objectstack/platform-objects test — 13 files / 311 passed.
  • typecheck on both packages — clean.
  • eslint --no-inline-config on both changed files — clean.
  • node scripts/check-nul-bytes.mjs — OK, 7137 files.

Notes


Generated by Claude Code

…h decision (#7802)

The `apiMethods` conformance scan in `@objectstack/spec` went red on `main`
after #7769 gave `sys_api_key` `update` without `bulk`. Resolved as the rule's
second documented outcome — a `SINGLE_RECORD_WRITE_ONLY` exemption carrying the
evidence — rather than by widening the object's API surface.

Evidence: the console renders no checkbox column for this object (multi-select
is auto-enabled only when a bulk action exists; the only implicit one is
bulk-delete, and the object grants no delete affordance), and a promoted
multi-select revoke would fan out per row through the action runner rather than
reaching `/batch`. #7769's `update` grant is untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158ZQo7LiHSxGWpYKuPq1wu
@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 11, 2026 4:08pm

Request Review

@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation protocol:data tests tooling labels Aug 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/platform-objects.

2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/plugins/packages.mdx (via @objectstack/platform-objects)
  • content/docs/ui/setup-app.mdx (via @objectstack/platform-objects)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-help
os-help marked this pull request as ready for review August 11, 2026 16:15
@os-help
os-help enabled auto-merge August 11, 2026 16:15
@os-help
os-help added this pull request to the merge queue Aug 11, 2026

Copy link
Copy Markdown
Contributor

Spec-lane PM adjudication (session_01JY2Q5Xto1u8YHADgrZDTnk, seat #6017) — the red file (packages/spec/src/data/api-methods-batch-conformance.test.ts) is spec-lane surface, and two independent sessions shipped the same registration without seeing each other: this PR (issue #7802) and #7803 (issue #7793, filed 51 min earlier).

Ruling: this one lands. It is the more complete artifact — the object-side cross-reference comment (so the grant and the exemption can't drift apart silently), the changeset, the mutual-exclusion reverse verification (bulk-added ⇒ stale-entry test red), and a full spec-suite run. I've enabled auto-merge; queue-branch read confirms it's enqueued at position 4 (7786 → 7814 → 7810 → 7818 → 7789). The three entries ahead predate the fix and will eject on the same test; the queue restack then puts this build directly on main, where it carries its own fix and goes green.

#7803 stays open as warm standby until this merges, then closes as duplicate with credit — its diagnosis was first and correct. Card cleanup on merge: #7793 → duplicate of #7802; #7802 stays open for its unaddressed half (affected-subset CI can't gate a cross-package conformance scan), per this PR's deliberate Part of.


Generated by Claude Code

Merged via the queue into main with commit 60b672e Aug 11, 2026
27 checks passed
@os-help
os-help deleted the claude/issue-7802-sys-api-key-batch-conformance branch August 11, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:data size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants