Files
zpan/server/usecases/oauth-grants.ts
T
Jasper Van 2657f82ef1 feat(auth): add contextual OAuth workspace grants (#550)
* feat(auth): add contextual OAuth workspace grants

* fix(auth): register RFC 9396 detail types

* fix(openapi): restore delegated CLI auth profile

* fix(store): recover paid capacity fulfillment

* fix(auth): close OAuth contract gaps

* fix(store): resume verified x402 settlements

* chore(deps): update zpan cloud sdk to 2.5.2

* test(store): cover verified settlement recovery

* fix(auth): localize standard consent scopes

* fix(docker): include dependency patches before install

* fix(store): harden x402 purchase responses

* test(auth): cover OAuth authorization boundaries

* docs: add PR 550 verification screenshots

* chore: remove temporary verification screenshots

* docs(openapi): document exhausted capacity response
2026-08-02 13:33:15 -04:00

47 lines
1.4 KiB
TypeScript

import {
type OAuthGrant as OAuthGrantDTO,
type OAuthResourceScope,
oauthGrantDTO,
oauthResourceScopeSchema,
} from '@shared/schemas'
import type { Database } from '../platform/interface'
import type { Deps } from './deps'
import { notFound } from './ports'
export async function listOAuthGrants(
deps: Pick<Deps, 'oauth' | 'org'>,
db: Database,
input: { userId: string },
): Promise<{ items: OAuthGrantDTO[] }> {
const items = await deps.oauth.listGrants(db, input.userId)
const workspaceIds = [...new Set(items.flatMap((item) => item.workspaceIds))]
const orgNames = await deps.org.getOrgNames(workspaceIds)
return {
items: items.map((item) => {
const { workspaceIds: itemWorkspaceIds, ...grant } = item
return oauthGrantDTO({
...grant,
scopes: item.scopes.filter(isOAuthResourceScope),
workspaces: itemWorkspaceIds.map((id) => ({ id, name: orgNames.get(id) ?? null })),
})
}),
}
}
function isOAuthResourceScope(scope: string): scope is OAuthResourceScope {
return oauthResourceScopeSchema.safeParse(scope).success
}
export async function revokeOAuthGrant(
deps: Pick<Deps, 'oauth'>,
db: Database,
input: { userId: string; grantId: string; now?: Date },
): Promise<void> {
const revoked = await deps.oauth.revokeGrant(db, {
userId: input.userId,
grantId: input.grantId,
now: input.now ?? new Date(),
})
if (!revoked) throw notFound('OAuth grant not found')
}