mirror of
https://github.com/saltbo/zpan.git
synced 2026-08-28 15:51:29 +08:00
1b1b1db772
Enforce owner/admin management, terminal expired/revoked lifecycle, explicit workspace scopes, current membership rechecks, and authenticated management UI.
59 lines
2.0 KiB
TypeScript
59 lines
2.0 KiB
TypeScript
import type { ApiKeyScope } from '@shared/api-key-templates'
|
|
import type { ApiKeyPermissions, AuthorizationScope } from '@shared/authorization'
|
|
import type { AgentApiKey, AgentApiKeyCreated, AgentGrantableScope } from '@shared/schemas'
|
|
import type { Database } from '../../platform/interface'
|
|
|
|
export interface VerifiedApiKey {
|
|
id: string
|
|
configId: string
|
|
referenceId: string
|
|
scope: ApiKeyScope
|
|
permissions: ApiKeyPermissions | null
|
|
}
|
|
|
|
// Structural view of better-auth used by the gateway. Keeps the port free of the
|
|
// better-auth framework type while letting callers pass the real `Auth`.
|
|
export interface ApiKeyAuth {
|
|
api: Record<string, unknown>
|
|
}
|
|
|
|
// Thrown by the gateway when better-auth reports the key is rate limited. The
|
|
// http layer (business routes + WebDAV) maps it to 429 with Retry-After.
|
|
export class ApiKeyRateLimitError extends Error {
|
|
constructor(
|
|
message: string,
|
|
public readonly retryAfterMs?: number,
|
|
) {
|
|
super(message)
|
|
this.name = 'ApiKeyRateLimitError'
|
|
}
|
|
}
|
|
|
|
export interface ApiKeyGateway {
|
|
verifyApiKey(auth: ApiKeyAuth, db: Database, key: string, configId?: string): Promise<VerifiedApiKey | null>
|
|
verifyApiKeyForPermission(
|
|
auth: ApiKeyAuth,
|
|
db: Database,
|
|
key: string,
|
|
resource: string,
|
|
action: string,
|
|
configId?: string,
|
|
): Promise<VerifiedApiKey | null>
|
|
hasApiKeyPermission(permissions: ApiKeyPermissions | null | undefined, resource: string, action: string): boolean
|
|
hasApiKeyScope(permissions: ApiKeyPermissions | null | undefined, scope: AuthorizationScope): boolean
|
|
listAgentApiKeys(db: Database, userId: string, orgId: string, now: Date): Promise<AgentApiKey[]>
|
|
getAgentApiKey(db: Database, userId: string, orgId: string, keyId: string, now: Date): Promise<AgentApiKey | null>
|
|
issueAgentApiKey(
|
|
db: Database,
|
|
input: {
|
|
name: string
|
|
userId: string
|
|
orgId: string
|
|
scopes: AgentGrantableScope[]
|
|
expiresAt: Date
|
|
revokeKeyId?: string
|
|
},
|
|
): Promise<AgentApiKeyCreated>
|
|
revokeAgentApiKey(db: Database, keyId: string): Promise<void>
|
|
}
|