chore(cloud): dev-only probe of the org the Orca Cloud token claims (GH-LIST-MISSING diagnostics)

Dev builds only: globalThis.__orcaCloudTokenClaims() in the main process returns { org, orgRole,
sub } from the current sandbox token's payload, never the token. Packaged builds install nothing.
This commit is contained in:
Neil
2026-11-12 16:53:54 -08:00
parent 9c18966cba
commit b89e292ec9
3 changed files with 70 additions and 0 deletions
@@ -0,0 +1,31 @@
import { afterEach, describe, expect, it } from 'vitest'
import { installDevTokenClaimsProbe, tokenOrgClaims } from './dev-token-claims-probe'
const encode = (value: unknown): string => Buffer.from(JSON.stringify(value)).toString('base64url')
const jwt = (claims: unknown): string => `${encode({ alg: 'ES256' })}.${encode(claims)}.sig`
describe('dev token claims probe (GH-LIST-MISSING)', () => {
afterEach(() => {
Reflect.deleteProperty(globalThis, '__orcaCloudTokenClaims')
})
it('reads only org, role and user from the payload', () => {
expect(tokenOrgClaims(jwt({ sub: 'u1', org: 'o1', org_role: 'owner', exp: 1 }))).toEqual({
org: 'o1',
orgRole: 'owner',
sub: 'u1'
})
expect(tokenOrgClaims(jwt({ sub: 'u1' }))).toEqual({ org: null, orgRole: null, sub: 'u1' })
expect(tokenOrgClaims('not-a-token')).toEqual({ org: null, orgRole: null, sub: null })
})
it('exists only in dev builds, and never hands back the token', async () => {
expect(installDevTokenClaimsProbe(async () => jwt({ sub: 'u1', org: 'o1' }), true)).toBeNull()
expect('__orcaCloudTokenClaims' in globalThis).toBe(false)
const probe = installDevTokenClaimsProbe(async () => jwt({ sub: 'u1', org: 'o1' }), false)
expect('__orcaCloudTokenClaims' in globalThis).toBe(true)
const answer = await probe?.()
expect(answer).toEqual({ org: 'o1', orgRole: null, sub: 'u1' })
expect(JSON.stringify(answer)).not.toContain('sig')
})
})
@@ -0,0 +1,37 @@
// GH-LIST-MISSING diagnostics, dev builds only: which org the Orca Cloud token in use claims, next
// to the team the app shows. A token minted for another team (or none) explains an empty GitHub
// list after an owner → member → owner switch. Never the token itself, and never in packaged builds.
type ClaimsProbe = () => Promise<{ org: string | null; orgRole: string | null; sub: string | null }>
/** Reads the claims of a JWT's payload without verifying it; nothing else of the token leaves. */
export function tokenOrgClaims(token: string): Awaited<ReturnType<ClaimsProbe>> {
const payload = token.split('.')[1]
let claims: Record<string, unknown> = {}
try {
const parsed: unknown = JSON.parse(Buffer.from(payload ?? '', 'base64url').toString('utf8'))
if (parsed && typeof parsed === 'object') {
claims = { ...parsed }
}
} catch {
// Not a JWT: report nothing rather than guess.
}
const text = (value: unknown): string | null => (typeof value === 'string' ? value : null)
return { org: text(claims.org), orgRole: text(claims.org_role), sub: text(claims.sub) }
}
/**
* Dev builds: `globalThis.__orcaCloudTokenClaims()` in the main process (the harness's inspector)
* answers the org, role and user the current sandbox token claims.
*/
export function installDevTokenClaimsProbe(
getAccessToken: () => Promise<string>,
packaged: boolean
): ClaimsProbe | null {
if (packaged) {
return null
}
const probe: ClaimsProbe = async () => tokenOrgClaims(await getAccessToken())
Object.assign(globalThis, { __orcaCloudTokenClaims: probe })
return probe
}
@@ -1,3 +1,4 @@
import { installDevTokenClaimsProbe } from './dev-token-claims-probe'
import { cloudDevSigningAllowed, withCloudBuildDefaults } from '../cloud-build-defaults'
import {
findCloudRuntimeBySandboxId,
@@ -132,6 +133,7 @@ export function installHostedSandbox(
// A cloud list refresh or a not-found status read asks for the prune now (LC-2).
setCloudGonePruneRunner(() => accountBackfill.run({ force: true }))
installLocalCommands(userDataPath)
installDevTokenClaimsProbe(() => config.getAccessToken(), app.isPackaged)
const mcpSync = installCloudMcpSync(userDataPath, {
baseUrl: config.controlPlaneUrl,
getAccessToken: config.getAccessToken