From 221a3f5e6355fcd5d85ad66db8a1476805b0b127 Mon Sep 17 00:00:00 2001 From: Jack Zhuang <50353452+hotlong@users.noreply.github.com> Date: Wed, 30 Sep 2026 02:39:31 +0800 Subject: [PATCH 1/2] docs(client): re-anchor the dead tracker citations in packages/client/src to the commits that decided them Every comment site in packages/client/src that cited a tracker number GitHub no longer serves now cites the commit in this repository's history that decided what the line describes, and keeps saying in its own words what that commit decided (ruling C+D, form C): 19 sites in src/index.ts and 24 in test-file comments, 13 numbers onto 12 commits, plus one companion line that completes a rewritten sentence. Comment lines only: 44 out, 44 in, and every touched file keeps its line count. No code token, string literal or test assertion moves. Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289 Co-authored-by: Claude --- .../client/src/client.data-prefix.test.ts | 2 +- .../client/src/client.metadata-prefix.test.ts | 2 +- packages/client/src/client.test.ts | 20 +++++----- packages/client/src/index.ts | 38 +++++++++---------- .../src/meta-automation-descriptors.test.ts | 6 +-- .../src/meta-delete-item-carriers.test.ts | 4 +- .../client/src/return-type-precision.test.ts | 16 ++++---- 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/client/src/client.data-prefix.test.ts b/packages/client/src/client.data-prefix.test.ts index c8a4755c1b2..0dea38ea507 100644 --- a/packages/client/src/client.data-prefix.test.ts +++ b/packages/client/src/client.data-prefix.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. /** - * `crud.dataPrefix` is honoured by the SDK, not restated by it (#14879). + * `crud.dataPrefix` is honoured by the SDK, not restated by it (commit cf74a1128). * * THE CONTRACT. `crud.dataPrefix` is a live `RestServerConfig` key: REST mounts * every CRUD route under `dataPath = ${basePath}${crud.dataPrefix}` and the diff --git a/packages/client/src/client.metadata-prefix.test.ts b/packages/client/src/client.metadata-prefix.test.ts index 98b7e18da34..ae447d9a227 100644 --- a/packages/client/src/client.metadata-prefix.test.ts +++ b/packages/client/src/client.metadata-prefix.test.ts @@ -4,7 +4,7 @@ * `metadata.prefix` is honoured by the SDK, not restated by it (#16675). * * THE CONTRACT. `metadata.prefix` is a live `RestServerConfig` key, the exact - * sibling of the `crud.dataPrefix` #14879 fixed: REST mounts every metadata + * sibling of the `crud.dataPrefix` defect commit cf74a1128 fixed: REST mounts every metadata * route under `metaPath = ${basePath}${metadata.prefix}` and the discovery * handler advertises the same value as * `routes.metadata = ${realBase}${metadata.prefix}`. Three surfaces describe diff --git a/packages/client/src/client.test.ts b/packages/client/src/client.test.ts index 7e0abd0c230..4dfc73bd8c3 100644 --- a/packages/client/src/client.test.ts +++ b/packages/client/src/client.test.ts @@ -24,7 +24,7 @@ function createMockClient(body: any, status = 200) { return { client, fetchMock }; } -// [#9934] The producer-marked user-facing refusal text (`userMessage`) — the +// [commit 79c46da90] The producer-marked user-facing refusal text (`userMessage`) — the // SDK surfaces it from BOTH live envelopes' declared spots, the same // two-dialect rule as `code`/`fields`, so the console can render a marked hook // refusal and keep its generic #3821 substitution for everything unmarked. @@ -354,10 +354,10 @@ describe('ObjectStackClient', () => { // card. It used to require the slash to survive UNENCODED, so the // request would reach the compound handler // `/meta/:type/:section/:name` instead of collapsing onto the - // two-segment route. #12176 retired compound-name addressing: that + // two-segment route. Commit 7986d973f retired compound-name addressing: that // handler is gone, so `%2F` is now the correct and only spelling. // - // Encoding is a no-op for every name #12194's grammar admits (snake + // Encoding is a no-op for every name commit 311433f6b's grammar admits (snake // case, optionally dot-qualified), so this changes nothing a legal // caller sends. What it changes is a pre-grammar residue name: it now // reaches the surviving door with its slash intact as `%2F`, which Hono @@ -509,7 +509,7 @@ describe('Security explain & global search (#3587 gap closure)', () => { }); it('security.explain accepts the recordIds batch spelling and forwards it verbatim (#8480)', async () => { - // [#8480] Typed-client completion of #8326's batch spelling. The + // [commit caaae2cca] Typed-client completion of #8326's batch spelling. The // client does NOT validate the cap or the recordId/recordIds // mutual exclusion — that stays the server's job // (`ExplainRequestSchema`); this pins that the body goes over the @@ -875,7 +875,7 @@ describe('Notifications namespace', () => { }); it('[#6361] never puts a `cursor` on the query string — the SDK producer is gone', async () => { - // The retired half of #6361 asserted where it was PRODUCED. `cursor` was + // The retired half of commit 90bbf2510 asserted where it was PRODUCED. `cursor` was // never a server-read filter; what made it harmful rather than inert is // that this method appended it, so a caller paginating by the published // contract re-read the first window forever with no error. @@ -1387,7 +1387,7 @@ describe('ObjectStackClient.automation', () => { // TS2353 excess-property error, which a runtime assertion cannot reach. // This pins the RUNTIME half, which tsc cannot: an untyped caller // (plain JS, a `Record` spread, a hand-built options object) must not - // smuggle the parameter through. The same shape #6361 left behind one + // smuggle the parameter through. The same shape commit 90bbf2510 left behind one // door over. // // All THREE surfaces are swept, because all three appended it and a @@ -2162,7 +2162,7 @@ describe('ScopedEnvironmentClient', () => { it('[#14879] a custom dataPrefix no longer makes the base underivable — `routes.metadata` is the second equation (case B1)', async () => { const { client, fetchMock } = createMockClient({ types: [] }); - // WAS pinned the other way. Until #14879 this case asserted the + // WAS pinned the other way. Until commit cf74a1128 this case asserted the // convention `/api/v1/...`, because the only suffix `_apiBase()` knew // how to strip was the literal `/data`, so a custom `crud.dataPrefix` // made the base undetectable and the client fell back. @@ -2194,8 +2194,8 @@ describe('ScopedEnvironmentClient', () => { // with the conventional `/data` AND there is no `routes.metadata` to // supply the missing equation, so `{realBase}{dataPrefix}` stays one // string with two unknowns. The client must NOT guess a split — it - // falls back to the convention, byte-identical to the pre-#14879 - // behavior. + // falls back to the convention, byte-identical to the behavior before + // commit cf74a1128. (client as any)['discoveryInfo'] = { routes: { data: '/backend/api/v9/records' }, }; @@ -2866,7 +2866,7 @@ describe('[#11391] meta.saveItem query string (unscoped client)', () => { it('[#12195] a slash-bearing name is ENCODED and still gets the query string', async () => { const { client, fetchMock } = createMockClient({ success: true }); await client.meta.saveItem('object', 'views/all_leads', { label: 'All leads' }, { force: true }); - // Inverted by #12195: the slash used to be required to survive raw so + // Inverted by commit 7986d973f: the slash used to be required to survive raw so // the request reached `PUT /meta/:type/:section/:name`, which had read // `?force` since #11095. That door is retired; `%2F` reaches the // surviving door, which has always read `?force`. diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index d8c27571bae..19305adddbf 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -681,7 +681,7 @@ export interface SaveMetaItemOptions { * empty spelling would pin the write against the empty string and refuse * every save with a 409 the caller never asked for. * - * [#12195] There is ONE door now. The compound-name twin + * [commit 7986d973f] There is ONE door now. The compound-name twin * `PUT /meta/:type/:section/:name` — which this note used to pair with — * is retired, and every name reaches `PUT /meta/:type/:name` * percent-encoded, so `if-match` behaviour no longer varies by how the @@ -725,7 +725,7 @@ export interface SaveMetaItemOptions { * on the wire that the server ignores. Same shape the first-party * `@object-ui/data-objectstack` `MetadataClient.save` already uses. * - * [#12195] REACHES EVERY SAVE — the carve-out this note used to carry is + * [commit 7986d973f] REACHES EVERY SAVE — the carve-out this note used to carry is * GONE, and it is worth recording why rather than deleting it silently. * * `mode` used to reach only the single-segment `PUT /meta/:type/:name`. @@ -735,7 +735,7 @@ export interface SaveMetaItemOptions { * answered 200, with no signal at the call site (objectstack#11712). * * Two changes closed it at the source rather than from this side. Stage 1 - * (#12194) made a slash-bearing name unwritable at all, and this stage + * (commit 311433f6b) made a slash-bearing name unwritable at all, and this stage * retired the twin and unified this file on `encodeURIComponent`, so every * save now arrives at the one door that reads `mode`. A name that would * once have forked to the silent-publish door is now refused `400 @@ -796,7 +796,7 @@ function metaSaveHeaders(options?: SaveMetaItemOptions): Record /** * Request options for `meta.deleteItem` — the carriers the REST reset door - * reads, made reachable from the SDK (#12181). + * reads, made reachable from the SDK (commit cf71d73f8). * * `DELETE /meta/:type/:name` ("reset metadata item to artifact default") * reads THREE carriers. This bag declares TWO of them, and the third's @@ -817,7 +817,7 @@ function metaSaveHeaders(options?: SaveMetaItemOptions): Record * ADDS destructive reach — it drops the object's physical table after the * metadata row goes — no caller was measured needing it from this client, * and the door's repeated-parameter refusal exists because of that - * destructiveness. Maintainer-seat ruling on #12181: a destructive surface + * destructiveness. Maintainer-seat ruling, landed by commit cf71d73f8: a destructive surface * with no measured pull is not published. A caller that needs it is a * separate, separately reviewable widening. * @@ -908,7 +908,7 @@ function metaDeleteQuery(options?: DeleteMetaItemOptions): string { * * Deliberately a sibling of {@link metaSaveHeaders} rather than a call into * it: the two methods carry two separately-ruled option bags (#11713 for - * `saveItem`, #12181 for this one), so neither type may quietly acquire the + * `saveItem`, commit cf71d73f8 for this one), so neither type may quietly acquire the * other's members. The two builders are pinned IN STEP by a test instead — * one token in, identical header bytes out. */ @@ -1831,11 +1831,11 @@ export class ObjectStackClient { // omits the `headers` key altogether, so a save without `ifMatch` // hands `fetch` the same `init` it always did. const headers = metaSaveHeaders(options); - // [#12195] ENCODED, like every other `/meta` item address in this file. + // [commit 7986d973f] ENCODED, like every other `/meta` item address in this file. // This site used to leave `type`/`name` RAW so a compound name's slash // would survive into a separate path segment and reach // `PUT /meta/:type/:section/:name`. That door is retired, and encoding - // is now the single spelling: a legal name (#12194's grammar — snake + // is now the single spelling: a legal name (commit 311433f6b's grammar — snake // case, optionally dot-qualified) contains nothing `encodeURIComponent` // alters, so this is byte-identical for every name that can be written, // and a pre-grammar residue name reaches the single-segment door with @@ -1863,7 +1863,7 @@ export class ObjectStackClient { * resolved as `options.ifMatch` and the same situation answers `409 * metadata_conflict` instead — the door has always read the header * (`DeleteMetaItemRequest.parentVersion` describes it), this client just - * had no argument for it until #12181. + * had no argument for it until commit cf71d73f8. * * [#13023] READ `reset`, NEVER `deleted`. This method used to declare * `{ type, name, deleted }` — an UNINHABITED shape: the door answers @@ -2018,12 +2018,12 @@ export class ObjectStackClient { /** * ADR-0033: the published version of a metadata item. * - * [#12195] The name is percent-encoded, like every other `/meta` item + * [commit 7986d973f] The name is percent-encoded, like every other `/meta` item * address in this file. This docblock used to promise the opposite — that * a compound name passed through UNENCODED, `getPublished('lead', * 'views/all_leads')`, so its slash would reach the compound arity * `GET /meta/:type/:section/:name/published`. That arity is retired and a - * slash-bearing name is refused at the publish door (#12194), so there is + * slash-bearing name is refused at the publish door (commit 311433f6b), so there is * one spelling and one door. */ getPublished: async (type: string, name: string): Promise => { @@ -3476,7 +3476,7 @@ export class ObjectStackClient { /** * @internal The CRUD data prefix this client's server actually mounts, read - * off the advertised routes (#14879). + * off the advertised routes (commit cf74a1128). * * `crud.dataPrefix` moves the mounted CRUD paths and the advertised * discovery document TOGETHER — REST builds every data route as @@ -3549,7 +3549,7 @@ export class ObjectStackClient { * @internal The metadata prefix this client's server actually mounts, read * off the advertised routes (#16675). * - * The same defect as #14879 one key over, so deliberately the same + * The defect commit cf74a1128 fixed, one key over, so deliberately the same * derivation shape as {@link ObjectStackClient._dataPrefix}, fallback * discipline included. `metadata.prefix` moves the mounted metadata paths * and the advertised discovery document TOGETHER — REST builds every @@ -3632,7 +3632,7 @@ export class ObjectStackClient { * `routes.data`: the REST discovery endpoint advertises it as * `{realBase}{dataPrefix}` with `dataPrefix` defaulting to `/data`. This * derivation strips that advertised suffix — `_dataPrefix()` reads which - * suffix it is (#14879), so a deployment that moves `crud.dataPrefix` off + * suffix it is (commit cf74a1128), so a deployment that moves `crud.dataPrefix` off * the default no longer forces this derivation to decline. When the suffix * is not derivable either, the caller falls back to the `/api/v1` * convention — exactly today's behavior, so the change is strictly "follow @@ -4908,7 +4908,7 @@ export class ObjectStackClient { * Server policy decides which is required; pass whichever you have. * * ⚠️ NOT BOUND, and deliberately so — the one member of the `auth.*` - * family #14313 left at `Promise`, with its + * family commit b1b978c8d left at `Promise`, with its * `exported-any-returns.json` entry still open. * * The maintainer's ruling of 2026-08-12 on #7735 keeps better-auth's @@ -6376,7 +6376,7 @@ export class ObjectStackClient { * List notifications for the current user. * * Returns the newest `limit` notifications — a WINDOW, not a page. The - * `cursor` parameter was removed in protocol 17 (#6361): it was appended to + * `cursor` parameter was removed in protocol 17 (commit 90bbf2510): it was appended to * the query string here and read by nothing on the server, so a caller * paginating by it re-read the first window forever. Omit `limit` to take * the server's window (the platform inbox answers 50, clamped to 1..200); @@ -7403,7 +7403,7 @@ export class ObjectStackClient { // actually carries. error.details = errorBody?.details ?? errorBody?.error?.details ?? errorBody; if (fieldErrors) error.fields = fieldErrors; - // [#9934] The producer-marked user-facing refusal text + // [commit 79c46da90] The producer-marked user-facing refusal text // (`ApiErrorSchema.userMessage`) — read from both live envelopes' // declared spots, same two-dialect rule as `code`/`fields` above: the // flat body carries it at the top level, the wrapped one inside @@ -7533,7 +7533,7 @@ export class ScopedEnvironmentClient { } /** - * URL for a route mounted under the deployment's CRUD data prefix (#14879). + * URL for a route mounted under the deployment's CRUD data prefix (commit cf74a1128). * * Every route reached through here is mounted by REST as * `${dataPath}/...` with `dataPath = ${basePath}${crud.dataPrefix}`, so the @@ -8119,7 +8119,7 @@ export type { GetPresenceResponse, // Workflow re-exports removed (#4451, v17): the types were deleted from // @objectstack/spec/api with the retired workflow slot. - // View-management re-exports removed (#6239, v17): the five viewId-addressed + // View-management re-exports removed (commit f549a0d4a, v17): the five viewId-addressed // methods and their ten schemas were deleted from @objectstack/spec/api with // the retired `ViewProtocol` — no host implemented them and no route reached // them. A view's stored definition travels on the metadata types diff --git a/packages/client/src/meta-automation-descriptors.test.ts b/packages/client/src/meta-automation-descriptors.test.ts index 64a5459495e..7dfce63e7d8 100644 --- a/packages/client/src/meta-automation-descriptors.test.ts +++ b/packages/client/src/meta-automation-descriptors.test.ts @@ -26,9 +26,9 @@ function createMockClient(body: any, status = 200) { describe('client.meta (#3563 PR-5)', () => { it('[#12195] getPublished ENCODES the name — one spelling, one door', async () => { - // ⚠️ Inverted by #12195. This required the slash to pass through RAW so + // ⚠️ Inverted by commit 7986d973f. This required the slash to pass through RAW so // the request reached the compound arity - // `GET /meta/:type/:section/:name/published`. #12176 retired + // `GET /meta/:type/:section/:name/published`. Commit 7986d973f retired // compound-name addressing and that arity is un-mounted, so `%2F` — // which Hono decodes back to `views/all_leads` on the surviving // `/:type/:name/published` route — is the correct spelling now. @@ -40,7 +40,7 @@ describe('client.meta (#3563 PR-5)', () => { }); it('[#12195] a LEGAL name reaches getPublished byte-identically', async () => { - // The control: encoding must be a no-op for every name #12194's + // The control: encoding must be a no-op for every name commit 311433f6b's // grammar admits, so no working caller moved. const { client, fetchMock } = createMockClient({ success: true, data: {} }); await client.meta.getPublished('lead', 'all_leads'); diff --git a/packages/client/src/meta-delete-item-carriers.test.ts b/packages/client/src/meta-delete-item-carriers.test.ts index ad222aa4c63..7950f3f1d6d 100644 --- a/packages/client/src/meta-delete-item-carriers.test.ts +++ b/packages/client/src/meta-delete-item-carriers.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#12181] `meta.deleteItem` sends the carriers the REST reset door reads — + * [commit cf71d73f8] `meta.deleteItem` sends the carriers the REST reset door reads — * the `If-Match` OCC pin and `?state=draft` — on BOTH declarations. * * ## The defect @@ -262,7 +262,7 @@ describe('[#12181] the withheld third carrier', () => { const { client, fetchMock } = createMockClient(RESET_OK); await client.meta.deleteItem('view', 'shared_grid', { // `dropStorage` is deliberately NOT a member of - // `DeleteMetaItemOptions` (2026-08-28 ruling on #12181: the one + // `DeleteMetaItemOptions` (2026-08-28 ruling, landed by commit cf71d73f8: the one // carrier that ADDS destructive reach, with no measured caller). // This is the type-level half of the withholding; the runtime half // is below. Adding the member turns the directive on the next line diff --git a/packages/client/src/return-type-precision.test.ts b/packages/client/src/return-type-precision.test.ts index bc04ff849bc..a7eec8aef45 100644 --- a/packages/client/src/return-type-precision.test.ts +++ b/packages/client/src/return-type-precision.test.ts @@ -888,7 +888,7 @@ export async function returnTypePrecisionPins12104(): Promise { } /** - * [#14312 — the `oauth.*` family, card 1 of 3 of #12104] The five better-auth + * [commit e944fdb24 — the `oauth.*` family, card 1 of 3 of #12104] The five better-auth * -backed methods #12104 deliberately left alone. FOUR are bound here. The * fifth — `oauth.applications.delete` — was left at `Promise< any >` by this * card on purpose and was bound afterwards by #15451; its pins live in @@ -970,7 +970,7 @@ export async function returnTypePrecisionPins14312(): Promise { // ── the method this card deliberately left open ────────────────────── // `delete` used to be pinned here as `toEqualTypeOf< any >`, with the note - // that the line would have to be replaced when #14312's open decision + // that the line would have to be replaced when commit e944fdb24's open decision // landed. It landed as #15451, and the replacement is a whole function of // its own rather than a rewritten line, because binding this method was // not a narrowing — see `returnTypePrecisionPins15451`. @@ -978,7 +978,7 @@ export async function returnTypePrecisionPins14312(): Promise { /** * [#15451] `oauth.applications.delete` — the fifth member of the `oauth.*` - * family, and the one #14312 could not reach. + * family, and the one commit e944fdb24 could not reach. * * ## This is NOT the narrowing its four siblings were * @@ -1028,7 +1028,7 @@ export async function returnTypePrecisionPins15451(): Promise { /** - * [#14313 — the `auth.*` family, card 2 of 3 of #12104] The fourteen + * [commit b1b978c8d — the `auth.*` family, card 2 of 3 of #12104] The fourteen * better-auth-backed methods #12104 censused under `auth.*`. THIRTEEN are * bound here; the fourteenth is named below and is still `Promise< any >` * on purpose. @@ -1127,7 +1127,7 @@ export async function returnTypePrecisionPins14313(): Promise { // ── the method deliberately left open ──────────────────────────────── // `deleteUser` still resolves to `any`, so `.anythingAtAll` compiles. - // Pinned as an EQUALITY rather than a suppression, exactly as #14312 did + // Pinned as an EQUALITY rather than a suppression, exactly as commit e944fdb24 did // for `oauth.applications.delete`: when the ruling that keeps the route // off is revisited, this line is the one that must be replaced. expectTypeOf(await client.auth.deleteUser({ password: 'p' })).toEqualTypeOf(); @@ -1135,7 +1135,7 @@ export async function returnTypePrecisionPins14313(): Promise { /** - * [#14314 — the `organizations.*` family, card 3 of 3 of #12104] The twenty + * [commit 7092d63e4 — the `organizations.*` family, card 3 of 3 of #12104] The twenty * ledger entries of the family: NINETEEN unannotated `return res.json()` * members (organizations 11 · invitations 3 · teams 5) bound here, plus * `invitations.resend`, which carries no annotation of its own and inherits @@ -1391,7 +1391,7 @@ export async function returnTypePrecisionPins13023(): Promise { * close. * * 2. THE GAP THIS BLOCK USED TO PIN AS UNDECLARED IS NOW CLOSED, on the spec - * side, which is the only side allowed to close it: #13208 (issue #13155) + * side, which is the only side allowed to close it: commit 74049254d (issue #13155) * widened `DeleteMetaItemResponseSchema` to declare `seq` and * `projectionApplied` — the two wire-receipt keys `deleteMetaItem`'s * repository-delete branch always sent. This file's two `@ts-expect-error` @@ -1412,7 +1412,7 @@ export function deleteDataResponseIsNotTheMetaResetShape(): void { } export function metaResetResponseDeclaresTheWireReceipt(): void { - // #13208 declared both wire-receipt keys on the schema; these positive + // Commit 74049254d declared both wire-receipt keys on the schema; these positive // reads red as TS2339 if either is ever dropped from the bound type. void metaResetBody.seq; void metaResetBody.projectionApplied; From 5dc93b68826bfc746b200634d350b1067b8dc879 Mon Sep 17 00:00:00 2001 From: Jack Zhuang <50353452+hotlong@users.noreply.github.com> Date: Wed, 30 Sep 2026 02:44:15 +0800 Subject: [PATCH 2/2] chore(changeset): a patch changeset for the re-anchored @objectstack/client docblocks The rewritten docblocks ship: the emitted dist (index.d.ts, index.d.mts, index.js, index.mjs) carries them, so the change publishes and takes a patch changeset in the form the earlier stages used. Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289 Co-authored-by: Claude --- .changeset/client-provenance-anchors.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/client-provenance-anchors.md diff --git a/.changeset/client-provenance-anchors.md b/.changeset/client-provenance-anchors.md new file mode 100644 index 00000000000..8c594e58321 --- /dev/null +++ b/.changeset/client-provenance-anchors.md @@ -0,0 +1,10 @@ +--- +'@objectstack/client': patch +--- + +Provenance comments in `@objectstack/client` were re-anchored + +Comment and docblock lines under `src/` that cited tracker numbers which no +longer resolve on GitHub now cite the commit in this repository's history that +decided the matter, and say in their own words what was decided. Comments +only: no request, route, error code, type, export or runtime behaviour changes.