@jeffusion/bungee-core 5.9.0 → 5.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/main.js +31348 -17337
  2. package/dist/plugins/ai-transformer/index.js.map +2 -2
  3. package/dist/plugins/anthropic-request-sanitizer/index.js.map +2 -2
  4. package/dist/plugins/anthropic-tool-name-transformer/index.js.map +2 -2
  5. package/dist/plugins/chatgpt-oauth/control.js +513 -1
  6. package/dist/plugins/chatgpt-oauth/control.js.map +12 -4
  7. package/dist/plugins/chatgpt-oauth/index.js +511 -4
  8. package/dist/plugins/chatgpt-oauth/index.js.map +13 -5
  9. package/dist/plugins/chatgpt-oauth/manifest.json +19 -0
  10. package/dist/plugins/deepseek-reasoning-fix/index.js.map +2 -2
  11. package/dist/plugins/key-access/control.js.map +1 -1
  12. package/dist/plugins/key-access/index.js.map +3 -3
  13. package/dist/plugins/key-access/ingress.js.map +1 -1
  14. package/dist/plugins/key-rate-limit/index.js.map +2 -2
  15. package/dist/plugins/local-accounts/control.js +68 -18
  16. package/dist/plugins/local-accounts/control.js.map +4 -4
  17. package/dist/plugins/local-accounts/index.js.map +2 -2
  18. package/dist/plugins/local-accounts/manifest.json +48 -2
  19. package/dist/plugins/local-accounts/ui/Settings.svelte +73 -1
  20. package/dist/plugins/model-mapping/control.js +72 -17741
  21. package/dist/plugins/model-mapping/control.js.map +6 -58
  22. package/dist/plugins/model-mapping/index.js +32 -17433
  23. package/dist/plugins/model-mapping/index.js.map +6 -58
  24. package/dist/plugins/model-mapping/manifest.json +30 -14
  25. package/dist/plugins/models-dev/control.js +1042 -0
  26. package/dist/plugins/models-dev/control.js.map +16 -0
  27. package/dist/plugins/models-dev/index.js +15418 -0
  28. package/dist/plugins/models-dev/index.js.map +134 -0
  29. package/dist/plugins/models-dev/manifest.json +199 -0
  30. package/dist/plugins/models-dev/ui/ModelsDevSettings.svelte +120 -0
  31. package/dist/plugins/openai-messages-to-chat/index.js.map +2 -2
  32. package/dist/plugins/signature-repair/index.js.map +2 -2
  33. package/dist/plugins/token-budget/control.js +524 -9
  34. package/dist/plugins/token-budget/control.js.map +12 -4
  35. package/dist/plugins/token-budget/index.js +519 -12
  36. package/dist/plugins/token-budget/index.js.map +13 -6
  37. package/dist/plugins/token-budget/manifest.json +16 -2
  38. package/dist/plugins/token-metering/index.js +93 -2
  39. package/dist/plugins/token-metering/index.js.map +12 -6
  40. package/dist/plugins/token-stats/control.js +174 -312
  41. package/dist/plugins/token-stats/control.js.map +7 -7
  42. package/dist/plugins/token-stats/index.js +283 -486
  43. package/dist/plugins/token-stats/index.js.map +16 -12
  44. package/dist/plugins/token-stats/manifest.json +99 -12
  45. package/dist/plugins/token-stats/ui/ClientModelPicker.svelte +76 -0
  46. package/dist/plugins/token-stats/ui/PriceModelPicker.svelte +87 -0
  47. package/dist/plugins/token-stats/ui/TokenStatsSettings.svelte +136 -80
  48. package/dist/plugins/token-stats/ui/client-model-search.test.ts +58 -0
  49. package/dist/plugins/token-stats/ui/client-model-search.ts +16 -0
  50. package/dist/plugins/token-stats/ui/model-search.ts +45 -0
  51. package/dist/plugins/token-stats/ui/pricing-catalog.test.ts +114 -0
  52. package/dist/plugins/token-stats/ui/pricing-catalog.ts +17 -0
  53. package/package.json +2 -2
@@ -3,7 +3,7 @@
3
3
  "sources": ["../../../../../plugins/key-access/server/control.ts", "../../../src/plugin-extensions.ts", "../../../../../plugins/key-access/server/policy.ts"],
4
4
  "sourcesContent": [
5
5
  "import { createHash, randomBytes, randomUUID } from 'node:crypto';\nimport type { ControlHostContext, PluginControl } from '../../../packages/core/src/plugin-control/contracts';\nimport type { PluginDurableState, DurableJson } from '../../../packages/core/src/plugin-durable-state';\nimport type { DataPrincipal } from '../../../packages/core/src/plugin-extensions';\nimport { validatePolicy, validatePublication, stringIds, validPrincipal, type AccessPublication, type AccessCredential } from './policy';\n\ntype ReadState = Pick<PluginDurableState, 'get' | 'list'>;\nconst empty = (): AccessPublication => ({byKey: {}, protectedRouteIds: [], credentials: []});\nfunction current(state: ReadState): AccessPublication {\n const value = state.get('policies')?.value;\n return value === undefined ? empty() : validatePublication(value);\n}\nfunction routeKeyBindings(value: AccessPublication) {\n return Object.fromEntries(value.protectedRouteIds.map(routeId => [routeId, value.credentials.filter(key => {\n const scope = validatePolicy(value.byKey[key.id] ?? null);\n return scope?.routes == null || scope.routes.includes(routeId);\n }).map(key => ({id: key.id, name: key.name}))]));\n}\nfunction metadata(key: AccessCredential) { const {digest: _digest, ...value} = key; return value; }\nfunction json(value: unknown, status = 200) { return Response.json(value, {status, headers: {'cache-control': 'no-store'}}); }\nfunction keyId(request: Request): string {\n const id = decodeURIComponent(new URL(request.url).pathname.split('/').pop() ?? '');\n if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(id)) throw new Error('invalid_key_id');\n return id;\n}\nexport function createControl(host: ControlHostContext): PluginControl {\n if (!host.durableState) throw new Error('key-access.durable_state_required');\n const state = host.durableState;\n let running = false, publishedVersion = -1;\n let writes: Promise<unknown> = Promise.resolve();\n const policy = () => ({version: state.get('policies')?.version ?? 0, value: current(state) as unknown as DurableJson});\n const ready = () => running && !host.signal.aborted && publishedVersion === policy().version;\n async function publish() {\n if (!host.publishPolicy) throw new Error('publication_unavailable');\n const next = policy();\n await host.publishPolicy(next);\n publishedVersion = next.version;\n }\n async function save(value: AccessPublication, result: Record<string, unknown>, status = 200): Promise<Response> {\n const old = state.get('policies');\n state.execute({commandId: randomUUID(), mutations: [{key: 'policies', expectedVersion: old?.version ?? 0, value: value as unknown as DurableJson}]});\n try { await publish(); return json({...result, version: policy().version, ready: ready(), published: true}, status); }\n catch { return json({...result, error: 'key-access.publication_pending', persisted: true, version: policy().version, ready: false, active: false, published: false}, 503); }\n }\n function write(operation: () => Promise<Response>): Promise<Response> {\n const task = writes.catch(() => undefined).then(async () => {\n if (!running || host.signal.aborted) return json({error: 'key-access.inactive'}, 503);\n try { return await operation(); } catch { return json({error: 'key-access.invalid_write'}, 422); }\n });\n writes = task; return task;\n }\n return {policy, rpc: [], api: [\n {path: '/credentials', methods: ['GET', 'POST'], handler: 'credentials', async invoke(ctx) {\n if (ctx.request.method === 'GET') {\n const keys = await Promise.all(current(state).credentials.map(async key => ({...metadata(key),\n ...(host.readResourceExtensions ? {extensions: await host.readResourceExtensions(key.id)} : {})})));\n return json({keys, ready: ready(), published: ready()});\n }\n return write(async () => {\n const input = await ctx.request.json() as {name: string; expiresAt?: number | null};\n if (!input || Object.keys(input).some(k => !['name', 'expiresAt'].includes(k)) || typeof input.name !== 'string'\n || !input.name.trim() || input.name.length > 128 || /[\\x00-\\x1f\\x7f]/.test(input.name)) return json({error: 'invalid_key_name'}, 422);\n const expiresAt = input.expiresAt ?? null, now = Date.now();\n if (expiresAt !== null && (!Number.isSafeInteger(expiresAt) || expiresAt <= now)) return json({error: 'invalid_expiration'}, 422);\n const next = current(state);\n if (next.credentials.some(key => key.name.trim() === input.name.trim())) return json({error: 'key_name_exists'}, 409);\n const token = `bng_data_${randomBytes(32).toString('base64url')}`;\n const key: AccessCredential = {id: randomUUID(), domain: 'data', name: input.name.trim(), prefix: token.slice(0, 17),\n digest: createHash('sha256').update(token).digest('hex'), createdAt: now, expiresAt, revokedAt: null, credentialVersion: 1};\n next.credentials.push(key);\n // A partially completed UI flow must never grant broader access.\n next.byKey[key.id] = {routes: [], models: null};\n try { await host.secretStore.compareAndSet('credential:' + key.id, null, token); }\n catch { return json({error: 'key_secret_unavailable'}, 503); }\n try { return await save(next, {key: metadata(key), token}, 201); }\n catch (error) {\n // A failed publication still persisted the credential; only clean up an uncommitted secret.\n if (!current(state).credentials.some(item => item.id === key.id)) {\n const stored = await host.secretStore.get('credential:' + key.id);\n if (stored) await host.secretStore.delete('credential:' + key.id, stored.version);\n }\n throw error;\n }\n });\n }},\n {path: '/credentials/:keyId', methods: ['GET', 'PUT', 'DELETE'], handler: 'credential', async invoke(ctx) {\n const id = keyId(ctx.request);\n if (ctx.request.method === 'GET') {\n const key = current(state).credentials.find(key => key.id === id);\n if (!key) return json({error: 'key_not_found'}, 404);\n try {\n const stored = await host.secretStore.get('credential:' + id);\n if (!stored) return json({error: 'key_secret_not_stored'}, 409);\n if (!current(state).credentials.some(key => key.id === id)) return json({error: 'key_not_found'}, 404);\n if (createHash('sha256').update(stored.value).digest('hex') !== key.digest) return json({error: 'key_secret_unavailable'}, 503);\n return json({token: stored.value});\n } catch { return json({error: 'key_secret_unavailable'}, 503); }\n }\n return write(async () => {\n const next = current(state), key = next.credentials.find(key => key.id === id);\n if (ctx.request.method === 'DELETE') {\n next.credentials = next.credentials.filter(key => key.id !== id);\n delete next.byKey[id];\n const result = await save(next, {deleted: true, id});\n try {\n const stored = await host.secretStore.get('credential:' + id);\n if (stored) await host.secretStore.delete('credential:' + id, stored.version);\n } catch { return json({...await result.json(),error:'key_secret_cleanup_pending', persisted:true, deleted:true, id}, 503); }\n return result;\n }\n if (!key || key.revokedAt !== null) return json({error:'key_not_found'}, 404);\n const input = await ctx.request.json();\n if (!input || Object.keys(input).some(k => !['name','expiresAt','routes','models'].includes(k)) || typeof input.name !== 'string'\n || !input.name.trim() || input.name.length > 128 || /[\\x00-\\x1f\\x7f]/.test(input.name)) return json({error:'invalid_key_name'},422);\n if (next.credentials.some(other => other.id !== id && other.name.trim() === input.name.trim())) return json({error: 'key_name_exists'}, 409);\n const expiresAt = input.expiresAt ?? null;\n if (expiresAt !== null && (!Number.isSafeInteger(expiresAt) || (expiresAt <= Date.now() && expiresAt !== key.expiresAt))) return json({error:'invalid_expiration'},422);\n const value = validatePolicy({routes: input.routes, models: input.models});\n if (!host.validateKeyPolicyReferences) return json({error:'reference_validator_unavailable'},503);\n if (!await host.validateKeyPolicyReferences(id,value)) return json({error:'invalid_references'},422);\n key.name = input.name.trim(); key.expiresAt = expiresAt; next.byKey[id] = value;\n return save(next,{key: metadata(key),value});\n });\n }},\n {path: '/routes', methods: ['GET', 'PUT'], handler: 'routeProtection', async invoke(ctx) {\n if (ctx.request.method === 'GET') { const value = current(state); return json({protectedRouteIds: value.protectedRouteIds, routeKeyBindings: routeKeyBindings(value), version: policy().version, ready: ready(), published: ready()}); }\n return write(async () => {\n const input = await ctx.request.json();\n if (!input || Object.keys(input).join() !== 'protectedRouteIds') return json({error: 'invalid_routes'}, 422);\n const protectedRouteIds = stringIds(input.protectedRouteIds);\n if (!host.validateRouteReferences) return json({error: 'reference_validator_unavailable'}, 503);\n if (!await host.validateRouteReferences(protectedRouteIds)) return json({error: 'invalid_references'}, 422);\n const value = current(state), bindings = routeKeyBindings(value);\n const blockedRouteIds = value.protectedRouteIds.filter(id => !protectedRouteIds.includes(id) && bindings[id]!.length > 0);\n if (blockedRouteIds.length) return json({error:'route_has_api_keys', blockedRouteIds, routeKeyBindings: bindings},409);\n const next = {...value, protectedRouteIds};\n return save(next, {protectedRouteIds, routeKeyBindings: routeKeyBindings(next)});\n });\n }},\n {path: '/route-key', methods: ['PUT'], handler: 'applyRouteKey', async invoke(ctx) {\n return write(async () => {\n const input = await ctx.request.json();\n if (!input || Object.keys(input).some(k => !['routeId','keyId','protect'].includes(k))\n || typeof input.routeId !== 'string' || typeof input.keyId !== 'string' || typeof input.protect !== 'boolean') return json({error:'invalid_binding'},422);\n const next = current(state);\n if (!next.credentials.some(key => key.id === input.keyId && key.revokedAt === null)) return json({error:'key_not_found'},404);\n if (!host.validateRouteReferences || !host.validateKeyPolicyReferences) return json({error:'reference_validator_unavailable'},503);\n if (!await host.validateRouteReferences([input.routeId])) return json({error:'invalid_references'},422);\n if (!next.protectedRouteIds.includes(input.routeId) && !input.protect) return json({error:'route_protection_confirmation_required'},409);\n const previous = validatePolicy(next.byKey[input.keyId] ?? null);\n const value = {routes: previous?.routes == null ? null : [...new Set([...previous.routes,input.routeId])], models:previous?.models ?? null};\n if (!await host.validateKeyPolicyReferences(input.keyId,value)) return json({error:'invalid_references'},422);\n next.byKey[input.keyId] = value;\n next.protectedRouteIds = [...new Set([...next.protectedRouteIds,input.routeId])];\n return save(next,{protectedRouteIds:next.protectedRouteIds,routeKeyBindings:routeKeyBindings(next)});\n });\n }},\n {path: '/keys/:keyId', methods: ['GET', 'PUT'], handler: 'keyPolicy', async invoke(ctx) {\n const id = keyId(ctx.request);\n if (ctx.request.method === 'GET') return json({keyId: id, version: policy().version, value: current(state).byKey[id] ?? null, active: ready(), ready: ready()});\n return write(async () => {\n const next = current(state);\n if (!next.credentials.some(key => key.id === id && key.revokedAt === null)) return json({error: 'key_not_found'}, 404);\n const value = validatePolicy(await ctx.request.json());\n if (!host.validateKeyPolicyReferences) return json({error: 'reference_validator_unavailable'}, 503);\n if (!await host.validateKeyPolicyReferences(id, value)) return json({error: 'invalid_references'}, 422);\n next.byKey[id] = value;\n return save(next, {keyId: id, value, active: true});\n });\n }},\n ],\n async start() { if (host.signal.aborted) throw new Error('inactive'); await publish(); running = true; },\n dispose() { running = false; },\n };\n}\nexport function readResource(resource: string, keyId: string, state: ReadState) {\n if (resource !== 'api-key') throw new Error('resource_not_supported');\n return {value: current(state).byKey[keyId] ?? null};\n}\nexport function readResourceCollection(resource: string, state: ReadState): readonly unknown[] {\n if (resource !== 'api-key') throw new Error('resource_not_supported');\n return current(state).credentials.map(metadata);\n}\nexport function readAdmissionRequirements(state: ReadState): readonly string[] { return current(state).protectedRouteIds; }\nexport function verifyDataPrincipal(principal: DataPrincipal, state: ReadState): boolean { return validPrincipal(principal, current(state), Date.now()); }\nexport default {createControl, readResource, readResourceCollection, readAdmissionRequirements, verifyDataPrincipal};\n",
6
- "import type { PluginDurableState, DurableJson } from './plugin-durable-state';\n\n/** Anonymous is an explicit, signed data identity; it carries no key authority. */\nexport type DataPrincipal = { readonly domain: string; readonly keyId: string; readonly credentialVersion: number };\nexport const ANONYMOUS_PRINCIPAL: DataPrincipal = Object.freeze({domain: 'anonymous', keyId: '', credentialVersion: 0});\nexport interface AdmissionRequirement { readonly plugin: string; readonly routeIds: readonly string[] }\n/** Public contracts. Business rules belong to the implementing plugin. */\nexport interface ManagementSubject {\n readonly id: string;\n readonly provider: string;\n readonly capabilities: readonly string[];\n readonly requiresPasswordChange?: boolean;\n}\nexport interface ManagementProvider {\n authenticate(request: Request): Promise<ManagementSubject | null>;\n authorize(subject: ManagementSubject, capability: string): boolean;\n login(request: Request): Promise<Response>;\n logout(request: Request): Promise<Response>;\n bootstrap(input: unknown): Promise<void>;\n hasIdentity(): boolean;\n revokeSessions(): void;\n validateWrite?(request: Request): void;\n csrfToken?(request: Request): string | undefined;\n}\nexport interface AdmissionTarget {\n readonly requestId: string;\n readonly attemptId: string;\n readonly principal: DataPrincipal;\n readonly routeId: string;\n readonly serviceId: string | null;\n readonly upstreamId: string;\n readonly url: string;\n readonly model: string | null;\n readonly now: number;\n}\nexport interface AdmissionDenial {\n readonly error: string;\n readonly status: 401 | 403 | 429 | 503 | 422;\n readonly retryAfter?: number;\n}\nexport interface AdmissionPlan {\n /** A complete JSON state replacement, staged by Host before the common decision. */\n readonly state?: DurableJson;\n /** Immutable policy snapshot retained by the grant for subsequent attempts. */\n readonly snapshot?: DurableJson;\n readonly denial?: AdmissionDenial;\n}\nexport interface IngressPlugin {\n /** Optional per-principal state. Policies are frozen; plans receive only this key's clones.\n * Expiry must mean absence is behaviorally equivalent to retaining the state. */\n keyedState?: {\n readonly capacity: number;\n policyForKey(policy: DurableJson, keyId: string): DurableJson;\n expiresAt(state: DurableJson): number;\n reconcile(state: DurableJson, policy: DurableJson, now: number): DurableJson;\n };\n authenticate?(request: Request, policy: DurableJson, now: number): DataPrincipal | null;\n resolveIdentity?(target: AdmissionTarget, policy: DurableJson): DataPrincipal;\n plan(target: AdmissionTarget, policy: DurableJson, state: DurableJson): AdmissionPlan;\n beforeAttempt?(target: AdmissionTarget, snapshot: DurableJson): AdmissionDenial | null;\n}\nexport interface IngressPluginModule { createIngress(): IngressPlugin }\nexport interface PluginStateRpcContext {\n readonly state: PluginDurableState;\n readonly requestId: string;\n readonly attemptId: string;\n readonly principal: DataPrincipal;\n}\nexport interface PluginPolicyPublication {\n readonly version: number;\n readonly value: DurableJson;\n}\n",
6
+ "import type { PluginDurableState, DurableJson } from './plugin-durable-state';\n\n/** Anonymous is an explicit, signed data identity; it carries no key authority. */\nexport type DataPrincipal = { readonly domain: string; readonly keyId: string; readonly credentialVersion: number };\nexport const ANONYMOUS_PRINCIPAL: DataPrincipal = Object.freeze({domain: 'anonymous', keyId: '', credentialVersion: 0});\nexport interface AdmissionRequirement { readonly plugin: string; readonly routeIds: readonly string[] }\n/** Public contracts. Business rules belong to the implementing plugin. */\nexport interface ManagementSubject {\n readonly id: string;\n readonly provider: string;\n readonly capabilities: readonly string[];\n readonly requiresPasswordChange?: boolean;\n}\nexport interface ManagementProvider {\n authenticate(request: Request): Promise<ManagementSubject | null>;\n authorize(subject: ManagementSubject, capability: string): boolean;\n login(request: Request): Promise<Response>;\n logout(request: Request): Promise<Response>;\n bootstrap(input: unknown): Promise<void>;\n hasIdentity(): boolean;\n revokeSessions(): void;\n validateWrite?(request: Request): void;\n csrfToken?(request: Request): string | undefined;\n /** Optional browser cookie renewal after successful session verification. Must not extend the server-side absolute deadline. */\n sessionCookie?(request: Request): string | undefined;\n}\nexport interface AdmissionTarget {\n readonly requestId: string;\n readonly attemptId: string;\n readonly principal: DataPrincipal;\n readonly routeId: string;\n readonly serviceId: string | null;\n readonly upstreamId: string;\n readonly url: string;\n readonly model: string | null;\n readonly now: number;\n}\nexport interface AdmissionDenial {\n readonly error: string;\n readonly status: 401 | 403 | 429 | 503 | 422;\n readonly retryAfter?: number;\n}\nexport interface AdmissionPlan {\n /** A complete JSON state replacement, staged by Host before the common decision. */\n readonly state?: DurableJson;\n /** Immutable policy snapshot retained by the grant for subsequent attempts. */\n readonly snapshot?: DurableJson;\n readonly denial?: AdmissionDenial;\n}\nexport interface IngressPlugin {\n /** Optional per-principal state. Policies are frozen; plans receive only this key's clones.\n * Expiry must mean absence is behaviorally equivalent to retaining the state. */\n keyedState?: {\n readonly capacity: number;\n policyForKey(policy: DurableJson, keyId: string): DurableJson;\n expiresAt(state: DurableJson): number;\n reconcile(state: DurableJson, policy: DurableJson, now: number): DurableJson;\n };\n authenticate?(request: Request, policy: DurableJson, now: number): DataPrincipal | null;\n resolveIdentity?(target: AdmissionTarget, policy: DurableJson): DataPrincipal;\n plan(target: AdmissionTarget, policy: DurableJson, state: DurableJson): AdmissionPlan;\n beforeAttempt?(target: AdmissionTarget, snapshot: DurableJson): AdmissionDenial | null;\n}\nexport interface IngressPluginModule { createIngress(): IngressPlugin }\nexport interface PluginStateRpcContext {\n readonly state: PluginDurableState;\n readonly requestId: string;\n readonly attemptId: string;\n readonly principal: DataPrincipal;\n}\nexport interface PluginPolicyPublication {\n readonly version: number;\n readonly value: DurableJson;\n}\n",
7
7
  "import { createHash, timingSafeEqual } from 'node:crypto';\nimport { ANONYMOUS_PRINCIPAL, type DataPrincipal, type AdmissionTarget, type AdmissionDenial, type IngressPlugin } from '../../../packages/core/src/plugin-extensions';\nimport { DataAdmissionError } from '../../../packages/core/src/data-admission/errors';\n\nexport interface AccessPolicy { routes: string[] | null; models: string[] | null }\nexport interface AccessCredential {\n id: string; domain: 'data'; name: string; prefix: string; digest: string;\n createdAt: number; expiresAt: number | null; revokedAt: number | null; credentialVersion: number;\n}\nexport interface AccessPublication {\n protectedRouteIds: string[];\n byKey: Record<string, AccessPolicy | null>;\n credentials: AccessCredential[];\n}\nexport function stringIds(value: unknown): string[] {\n if (!Array.isArray(value) || value.length > 1000 || value.some(x => typeof x !== 'string' || !x.length || x.length > 256)\n || new Set(value).size !== value.length) throw new Error('invalid_policy');\n return [...value];\n}\nexport function validatePolicy(value: unknown): AccessPolicy | null {\n if (value === null) return null;\n if (!value || typeof value !== 'object' || Array.isArray(value) || Object.keys(value).some(k => !['routes', 'models'].includes(k))) throw new Error('invalid_policy');\n const p = value as AccessPolicy;\n return {routes: p.routes === null ? null : stringIds(p.routes), models: p.models === null ? null : stringIds(p.models)};\n}\nexport function validatePublication(value: unknown): AccessPublication {\n const p = value as AccessPublication;\n if (!p || typeof p !== 'object' || !p.byKey || typeof p.byKey !== 'object' || Array.isArray(p.byKey)\n || !Array.isArray(p.credentials)) throw new Error('invalid_policy');\n const protectedRouteIds = stringIds(p.protectedRouteIds);\n for (const key of p.credentials) {\n if (!key || key.domain !== 'data' || typeof key.id !== 'string' || !key.id || !/^[a-f0-9]{64}$/.test(key.digest)\n || !Number.isSafeInteger(key.credentialVersion) || key.credentialVersion < 1\n || (key.expiresAt !== null && !Number.isSafeInteger(key.expiresAt))\n || (key.revokedAt !== null && !Number.isSafeInteger(key.revokedAt))) throw new Error('invalid_credentials');\n }\n return {...p, protectedRouteIds};\n}\nexport function validPrincipal(principal: DataPrincipal, value: AccessPublication, now: number): boolean {\n const key = value.credentials.find(key => key.id === principal.keyId);\n return principal.domain === 'data' && !!key && key.credentialVersion === principal.credentialVersion\n && key.revokedAt === null && (key.expiresAt === null || key.expiresAt > now);\n}\n/** Only * is special; every other character is literal. Match the entire model. */\nfunction matchesModel(pattern: string, model: string): boolean {\n const parts = pattern.split('*');\n if (parts.length === 1) return pattern === model;\n const first = parts[0]!, last = parts[parts.length - 1]!;\n if (!model.startsWith(first) || !model.endsWith(last)) return false;\n let cursor = first.length;\n const end = model.length - last.length;\n for (const part of parts.slice(1, -1)) {\n const index = model.indexOf(part, cursor);\n if (index < 0) return false;\n cursor = index + part.length;\n }\n return cursor <= end;\n}\nfunction check(target: AdmissionTarget, policy: AccessPolicy | null): AdmissionDenial | null {\n if (target.principal.domain === 'anonymous') return null;\n if (policy && ((policy.routes !== null && !policy.routes.includes(target.routeId))\n || (policy.models !== null && (!target.model || !policy.models.some(pattern => matchesModel(pattern, target.model!)))))) return {error: 'key-access.scope_denied', status: 403};\n return null;\n}\nexport function createIngress(): IngressPlugin { return {\n authenticate(request, value, now) {\n const p = validatePublication(value);\n const match = /^Bearer (bng_data_[A-Za-z0-9_-]{43})$/i.exec(request.headers.get('authorization') ?? '');\n if (!match) return null;\n const digest = createHash('sha256').update(match[1]!).digest('hex');\n const key = p.credentials.find(key => timingSafeEqual(Buffer.from(key.digest, 'hex'), Buffer.from(digest, 'hex')));\n if (!key) return null;\n const principal = {domain: 'data', keyId: key.id, credentialVersion: key.credentialVersion};\n return validPrincipal(principal, p, now) ? principal : null;\n },\n resolveIdentity(target, value) {\n const p = validatePublication(value);\n if (!p.protectedRouteIds.includes(target.routeId)) return ANONYMOUS_PRINCIPAL;\n if (!validPrincipal(target.principal, p, target.now)) throw new DataAdmissionError(401, 'unauthorized');\n return target.principal;\n },\n plan(target, value) {\n try {\n const p = validatePublication(value);\n if (!p.protectedRouteIds.includes(target.routeId)) return {snapshot: null};\n if (target.principal.domain === 'anonymous') return {denial: {error: 'unauthorized', status: 401}};\n const policy = validatePolicy(p.byKey[target.principal.keyId] ?? null);\n const denial = check(target, policy);\n return denial ? {denial} : {snapshot: {routeId: target.routeId, policy: policy as any}};\n } catch { return {denial: {error: 'key-access.policy_unavailable', status: 503}}; }\n },\n beforeAttempt(target, snapshot) {\n if (snapshot === null) return target.principal.domain === 'anonymous' ? null : {error: 'key-access.invalid_grant', status: 503};\n try {\n const s = snapshot as {routeId: string; policy: AccessPolicy | null};\n if (!s || s.routeId !== target.routeId) return {error: 'key-access.scope_denied', status: 403};\n return check(target, validatePolicy(s.policy));\n } catch { return {error: 'key-access.policy_unavailable', status: 503}; }\n },\n}; }\n"
8
8
  ],
9
9
  "mappings": "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",