You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Scoped slice of #277, which asks for the remaining typed response shapes to be brought onto the #266 schema layer and notes that "one PR per coherent group of shapes is fine". This issue tracks the account surfaces group so the umbrella #277 can stay open for the read, write and http.ts-helper groups.
Problem
All three GET /me callers go through the generic client.get, which still blind-casts the body:
auth status / whoami (auth.ts) renders m.scopes.join(', ') and computes missing scopes via m.scopes.includes(...), both unguarded. A /me body without scopes throws a raw TypeError: Cannot read properties of undefined (reading 'join') and exits 1.
Under --output json it is worse: the text renderer closure never runs, so nothing throws — the CLI prints the partial identity and exits 0. An agent reading error.code sees nothing and reads scopes as undefined.
usage / credits (usage.ts) feeds credits and creditsPerRun into Math.floor(credits / creditsPerRun) for the "can trigger ~N runs" pre-flight hint, so a non-numeric balance reaches the arithmetic unchecked.
Point the CLI at a server returning a 200 /me body with no scopes:
$ testsprite auth status
Error: Cannot read properties of undefined (reading 'join')
$ testsprite auth status --output json
{ "userId": "u-1", "keyId": "k-1", "env": "development" } # exit 0
Proposed fix
Add ME_RESPONSE_SCHEMA and USAGE_RESPONSE_SCHEMA, wire the stubbed ME_IDENTITY_SCHEMA into doctor, and alias doctor's MeIdentity to the schema's wire type so the two cannot drift again. Follow the #266 policy unchanged: looseObject throughout so additive server fields pass through to --output json, env validated as an open string so a new deployment tier cannot hard-fail, and required-vs-optional decided from fixture evidence rather than from the TypeScript interface alone.
The pre-write /me ping in runConfigure should stay unvalidated — it discards the body and only checks that the key was accepted, so validating it would let an unrelated /me change block credential setup.
Scope
Account surfaces only: MeResponse, MeIdentity, UsageResponse. The other #277 groups (CliTest, CliTestCode, CliProject, CliCreateTestResponse, CliFailureSummary, and the remaining as T casts in the http.ts helpers) are follow-ups under the umbrella.
Scoped slice of #277, which asks for the remaining typed response shapes to be brought onto the #266 schema layer and notes that "one PR per coherent group of shapes is fine". This issue tracks the account surfaces group so the umbrella #277 can stay open for the read, write and
http.ts-helper groups.Problem
All three
GET /mecallers go through the genericclient.get, which still blind-casts the body:auth status/whoami(auth.ts) rendersm.scopes.join(', ')and computes missing scopes viam.scopes.includes(...), both unguarded. A/mebody withoutscopesthrows a rawTypeError: Cannot read properties of undefined (reading 'join')and exits 1.Under
--output jsonit is worse: the text renderer closure never runs, so nothing throws — the CLI prints the partial identity and exits 0. An agent readingerror.codesees nothing and readsscopesasundefined.usage/credits(usage.ts) feedscreditsandcreditsPerRunintoMath.floor(credits / creditsPerRun)for the "can trigger ~N runs" pre-flight hint, so a non-numeric balance reaches the arithmetic unchecked.doctor(doctor.ts) reads a fully-optional identity projection. Its localMeIdentityinterface has already drifted from theME_IDENTITY_SCHEMAstub that feat(http): validate API responses at runtime with valibot instead of blind casts #266 left in place: the interface carriesv3Enabled, the schema does not.Repro
Point the CLI at a server returning a 200
/mebody with noscopes:Proposed fix
Add
ME_RESPONSE_SCHEMAandUSAGE_RESPONSE_SCHEMA, wire the stubbedME_IDENTITY_SCHEMAintodoctor, and alias doctor'sMeIdentityto the schema's wire type so the two cannot drift again. Follow the #266 policy unchanged:looseObjectthroughout so additive server fields pass through to--output json,envvalidated as an open string so a new deployment tier cannot hard-fail, and required-vs-optional decided from fixture evidence rather than from the TypeScript interface alone.The pre-write
/meping inrunConfigureshould stay unvalidated — it discards the body and only checks that the key was accepted, so validating it would let an unrelated/mechange block credential setup.Scope
Account surfaces only:
MeResponse,MeIdentity,UsageResponse. The other #277 groups (CliTest,CliTestCode,CliProject,CliCreateTestResponse,CliFailureSummary, and the remainingas Tcasts in thehttp.tshelpers) are follow-ups under the umbrella.