Uh oh!
There was an error while loading. Please reload this page.
client: typed security.explain() request gains the recordIds batch spelling - #8795
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 11 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also reference the affected code. These are read-only:
|
qq9340100
commented
Aug 15, 2026
ACCEPT — PM review, |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#8480
What
security.explain()'s typed request literal inpackages/client/src/index.tsnowdeclares the optional
recordIds?: string[]batch spelling alongside the existingrecordId?: string, so a typed-client consumer can reach the batch record-grainedexplain form the REST endpoint has accepted since #8326 (PR #8452) without a cast.
Type-level and TSDoc only, additive:
recordIds?: string[]to the inline request type. Every existing member(
object,operation?,userId?,recordId?) is unchanged.ExplainRequestSchemain@objectstack/spec: the batch form answers 1-200 ids in one round trip(
decision.records[i]answersrecordIds[i]), and is mutually exclusive withrecordId(server refuses both/neither-of-cap with a 400).POST — no client-side validation of the cap, no mutual-exclusion check, no
recordIdshandling logic added. The server (ExplainRequestSchema+rest-server.ts) owns those refusals, as it already does.Why the schema's wording, not the issue's
The issue text summarized the constraint as "cap 200" / "mutual exclusion with
recordId". Read against the actual schema(
packages/spec/src/security/explain.zod.ts), that is exactly right:recordIds: z.array(z.string()).min(1).max(EXPLAIN_BATCH_MAX_RECORD_IDS)(200) plusa
superRefinethat rejects a request carrying bothrecordIdandrecordIds. TheTSDoc added here is written from the schema directly (including the empty-array
refusal the issue didn't mention), not paraphrased from the issue body.
Verification
pnpm --filter '@objectstack/client^...' build— dependency closure (confirmsrecordIdsis live in the built@objectstack/specdist this client compilesagainst).
pnpm --filter @objectstack/client test— 23 test files / 301 tests pass,including a new pin (
client.test.ts) assertingrecordIdsforwards verbatimover POST, unmodified.
pnpm --filter @objectstack/client typecheck— clean (tsc --noEmit+check:test-typecheck).recordIds?: string[]removed from the type,pnpm --filter @objectstack/client typecheckfails on the new test(
client.test.ts: 1 type error(s)); restoring the field makes it green again —confirms the type change is what makes the batch spelling reachable, not a
pre-existing
any.dist/index.js/dist/index.mjsbuilt with vs. without thechange differ ONLY in the TSDoc comment text carried into the bundle — zero
functional/runtime diff, confirming the type annotation is fully erased.
@objectstack/client(
pnpm --filter '...@objectstack/client'):@objectstack/client-reacttypechecks clean;
@objectstack/cli's typecheck fails, but only on 23 pre-existingCannot find moduleerrors for sibling packages outside this diff's dependencyclosure (
@objectstack/setup,@objectstack/cloud-connection,@objectstack/service-storage,@objectstack/driver-turso, etc. — none of itexplain/recordId-related, unrelated to this change);@objectstack/dogfood'stwo
security.explain(...)hits are the unrelated server-side security service(
stack.kernel.getService('security'), typedany), not this SDK method.node scripts/check-cross-package-test-inputs.mjs— OK.node scripts/check-nul-bytes.mjs— OK (5803 files scanned, 0 raw control bytes).node scripts/check-type-check-coverage.mjs(structural) — OK;@objectstack/clientis COVERED + REAL + TESTS_COVERED (not a DEBT/TEST_DEBT ledger entry).
f1eae3ee5:pnpm --filter @objectstack/client test && pnpm --filter @objectstack/client typecheck— green(301/301 tests, clean typecheck).
check:type-check-debt(the full-repo ratchet--re-measure) is NOT MEASURED:it refuses outright without a full
pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*'across all 77 workspace packages, and 23 of those areoutside this diff's dependency closure entirely (
@objectstack/setup,@objectstack/plugin-email,@objectstack/driver-turso, ...).@objectstack/clientis not a DEBT/TEST_DEBT ledger entry, so nothing in this diff can move that ratchet;
CI's full-suite run is the right place to confirm that formally.
Changeset
.changeset/client-explain-recordids-batch-spelling.md—@objectstack/client: minor(additive public-surface field, non-breaking; no ADR-0087 marker needed — nothing
authorable is added/renamed/retired).
Generated by Claude Code