Skip to content

bind set-initial-password into the SDK: add auth.setInitialPassword to ObjectStackClient #10974

Description

@os-warren

Maintainer ruling on the set-initial-password disposition question raised by #10534 / #10660: option C — bind the route into the SDK, then ledger it as sdk. This card is C's first half. The ledger row is the second half and is deliberately a separate card (ordering argued below).

⚠️Public-surface widening ⇒ Clause-② contract review. This card adds a method to ObjectStackClient, which is published surface. It must not be merged on a dispatching seat's own authority.

What is measured

All three readings taken on origin/main at 81845c65a.

1. The route has no SDK binding, and the zero is a real zero.

packages/client/src setInitialPassword = 0
packages/client/src set-initial-password = 0
positive controls, same corpus, same expression:
getConfig = 1
auth.me = 1
accounts = 10
changePassword = 1

Both spellings return nothing while four sibling auth members return non-zero, so the absence is an absence and not a broken pattern.

2. sdk is the ledger's rule, not one of several equals.

disposition distribution in AUTH_ROUTE_LEDGER:
sdk 54 · server-only 1 · disabled 1 · gap 0

54 of 56. server-only is a single reviewed exception, not a co-equal category to fall into by default.

3. The gap disposition is behind a shrink-only ratchet.

packages/plugins/plugin-auth/src/auth-route-ledger.conformance.test.ts

:189 it('gap and mismatch counts only shrink', () => {
:192 expect(AUTH_ROUTE_LEDGER.filter((e) => e.disposition === 'gap').length).toBeLessThanOrEqual(0);

The test is named for its own direction. Filing this route as gap would not be "recording a number" — it would be reversing a ratchet, which is the thing the ratchet exists to refuse.

Why C and not the alternatives

Scope

Add setInitialPassword to the auth namespace in packages/client/src/index.ts, shaped like its siblings already in that namespace (getConfig, changePassword, changeEmail — all this.getRoute('auth') + this.fetch(...)), hitting the route the plugin already mounts.

Out of scope, and a maintainer floor if attempted: any change to the route's own accept/reject behaviour, its admit set, or its server-side guards. This card binds a client to an already-mounted route. It does not touch what that route allows. A permission-boundary loosening is not this card's to make.

Not in this card: the AUTH_ROUTE_LEDGER row. That is the follow-up card, which will name this method.

Gates this touches — confirm both legs, do not assume

packages/client/src/client-url-conformance.test.ts sweeps the SDK surface automatically, so a new method lands inside two live assertions:

  • :363every client method is classified — driven or explicitly non-HTTP — the new method is enumerated by enumerateMethods; it must either drive cleanly or be declared in NON_HTTP (it should drive, like its siblings).
  • :373every URL the SDK builds matches a route some surface mounts — the URL this method builds must match the compiled ledger union.

On leg :373, note what it will and will not prove here. The dispatcher ledger still carries a * /auth/** prefix row, and client-url-conformance.test.ts:123-129 says in its own words that exact rows are sorted ahead of wildcard families precisely because otherwise "every /api/v1/auth/* URL would still be absorbed by the dispatcher's * /auth/** row and keep counting as weak evidence". Until the follow-up card adds the exact row, this method's URL matches on that weak evidence. Report which pattern it matched, by name, rather than reporting only that the test was green. A green here is not yet proof the wire path is right.

Ordering — why this card is first

packages/plugins/plugin-auth/src/auth-route-ledger.conformance.test.ts:152 requires every sdk-disposition row to name a client method. The ** fallback above is what makes the reverse order safe: this method can land while its exact ledger row does not yet exist, but a sdk row naming a method that does not exist would be a claim of coverage the SDK does not have — the exact failure packages/client/src/route-ledger-coverage.test.ts was written for (its header cites #3528, where "the ledger equivalent of the day would have said resume → automation.resume while no such method existed").

So: this card, then the ledger card.

Acceptance

  1. auth.setInitialPassword exists on ObjectStackClient and resolves to a function.
  2. Both conformance legs above pass, with the matched pattern named in the report.
  3. Changeset present.
  4. PR stays draft until contract review PASSes; the reviewing seat must not be the dispatching seat.

Refs

Part of #10534 · #10660 (the ledger/docs PR that surfaced the question; its body must not close #10534 while this remains open) · #10050 · #3563 / #3642 (the conformance guards above) · #3656 (the auth ledger's own charter)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions