@horizonmedia/blu-sdk 0.0.0-stage → 1.8.4
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.
- package/README.md +552 -2
- package/bin/blu.js +343 -0
- package/chunks/chunk-CSQHQLB7.js +163 -0
- package/chunks/chunk-M7GVSOGQ.js +179 -0
- package/dev.js +374 -0
- package/frame.js +134 -0
- package/index.js +34 -0
- package/package.json +54 -4
- package/server.js +466 -0
- package/types/dev.d.ts +48 -0
- package/types/frame.d.ts +139 -0
- package/types/index.d.ts +176 -0
- package/types/server.d.ts +448 -0
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
/** True when `policy` admits this principal's entry point with all required permissions. */
|
|
2
|
+
declare function policyAllows(policy: any, principal: any): any;
|
|
3
|
+
/**
|
|
4
|
+
* @param {{ name: string, version: string, authenticate: Function | Function[], tools: ModuleTool[], manifest?: object }} opts
|
|
5
|
+
* manifest — the module's blu.module.json. When given, the tools in code must
|
|
6
|
+
* match its `mcp.tools` exactly (name, read-only flag, requirements) or this
|
|
7
|
+
* throws at start-up: the API won't run with an undeclared or mis-declared
|
|
8
|
+
* tool, so what the Admin approved is what actually runs.
|
|
9
|
+
* @returns {import("express").Router-like handlers} mount with `app.post("/mcp", ...createMcpEndpoint(...))`
|
|
10
|
+
*/
|
|
11
|
+
declare function createMcpEndpoint({ name, version, authenticate, tools, manifest }: {
|
|
12
|
+
name: string;
|
|
13
|
+
version: string;
|
|
14
|
+
authenticate: Function | Function[];
|
|
15
|
+
tools: ModuleTool[];
|
|
16
|
+
manifest?: object;
|
|
17
|
+
}): any;
|
|
18
|
+
/**
|
|
19
|
+
* The same MCP endpoint for Web-standard handlers — e.g. a Next.js route
|
|
20
|
+
* handler: `export const POST = createMcpWebHandler({ … })`. Same tools shape,
|
|
21
|
+
* same per-caller tool filtering, same manifest drift check and link checks.
|
|
22
|
+
*
|
|
23
|
+
* @param {{ name: string, version: string, verify: (request: Request) => Promise<object>, tools: ModuleTool[], manifest?: object }} opts
|
|
24
|
+
* verify — e.g. createModuleAuth(…).verifyRequest; throws an error with `status`/`code` to refuse
|
|
25
|
+
* @returns {(request: Request) => Promise<Response>}
|
|
26
|
+
*/
|
|
27
|
+
declare function createMcpWebHandler({ name, version, verify, tools, manifest }: {
|
|
28
|
+
name: string;
|
|
29
|
+
version: string;
|
|
30
|
+
verify: (request: Request) => Promise<object>;
|
|
31
|
+
tools: ModuleTool[];
|
|
32
|
+
manifest?: object;
|
|
33
|
+
}): (request: Request) => Promise<Response>;
|
|
34
|
+
declare function link(route: any, params: any, label: any): {
|
|
35
|
+
route: any;
|
|
36
|
+
params: any;
|
|
37
|
+
label: any;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* A Zod schema, from Zod 3.25+ or Zod 4: whichever your API uses (the MCP SDK accepts both). Use Zod
|
|
41
|
+
* 4.6.6 or later: earlier versions can exhaust memory validating oversized input (GHSA-mrhx-c7xc-m3w5).
|
|
42
|
+
*/
|
|
43
|
+
type ZodSchema = {
|
|
44
|
+
parse(data: unknown): unknown;
|
|
45
|
+
safeParse(data: unknown): unknown;
|
|
46
|
+
};
|
|
47
|
+
type ModuleTool = {
|
|
48
|
+
name: string;
|
|
49
|
+
title: string;
|
|
50
|
+
/**
|
|
51
|
+
* Written for the model: when to use it, what it returns.
|
|
52
|
+
*/
|
|
53
|
+
description: string;
|
|
54
|
+
/**
|
|
55
|
+
* zod raw shape for arguments (Zod 4.6.6+ recommended; 3.25+ works)
|
|
56
|
+
*/
|
|
57
|
+
input?: Record<string, ZodSchema>;
|
|
58
|
+
policy: Partial<Record<"blu" | "service" | "team" | "api-key", string[]>>;
|
|
59
|
+
annotations?: {
|
|
60
|
+
readOnlyHint?: boolean;
|
|
61
|
+
destructiveHint?: boolean;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* principal: the normalized caller (req.principal)
|
|
65
|
+
*/
|
|
66
|
+
run: (principal: any, args: any) => Promise<{
|
|
67
|
+
summary: string;
|
|
68
|
+
data: unknown;
|
|
69
|
+
links?: ReturnType<typeof link>[];
|
|
70
|
+
}>;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* A user signed in with Blu — in a Blu shell, through the Concierge, or in this
|
|
75
|
+
* module's own standalone app ("Sign in with Blu"). Blu mints these tokens for
|
|
76
|
+
* ONE module (audience `blu-module:<moduleId>`), only while the module is
|
|
77
|
+
* enabled for the token's client, so a token issued for another module — or
|
|
78
|
+
* the shell's own session token — is refused here. The token carries the
|
|
79
|
+
* user's global Blu role on that client; `roleMap` turns it into permissions.
|
|
80
|
+
*
|
|
81
|
+
* @param {{ issuer: string, jwksUrl: string, moduleId: string,
|
|
82
|
+
* roleMap: Record<string, string[]> }} opts
|
|
83
|
+
* roleMap — TEAM-OWNED: Blu role ("viewer" | "analyst" | "owner") → this API's permissions.
|
|
84
|
+
*/
|
|
85
|
+
declare function bluPlatformAuth({ issuer, jwksUrl, moduleId, roleMap }: {
|
|
86
|
+
issuer: string;
|
|
87
|
+
jwksUrl: string;
|
|
88
|
+
moduleId: string;
|
|
89
|
+
roleMap: Record<string, string[]>;
|
|
90
|
+
}): {
|
|
91
|
+
mode: string;
|
|
92
|
+
kind: string;
|
|
93
|
+
issuer: string;
|
|
94
|
+
accepts: (claims: any) => boolean;
|
|
95
|
+
authenticate(token: any): Promise<{
|
|
96
|
+
authMode: string;
|
|
97
|
+
kind: string;
|
|
98
|
+
issuer: string;
|
|
99
|
+
subject: any;
|
|
100
|
+
key: string;
|
|
101
|
+
devIdentity: any;
|
|
102
|
+
displayName: any;
|
|
103
|
+
email: any;
|
|
104
|
+
provider: any;
|
|
105
|
+
via: any;
|
|
106
|
+
actor: any;
|
|
107
|
+
clientId: any;
|
|
108
|
+
allowedClients: any;
|
|
109
|
+
roles: any;
|
|
110
|
+
permissions: any[];
|
|
111
|
+
}>;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Another backend calling with a Blu-issued client-credentials token. Its scopes
|
|
115
|
+
* are exactly what the Blu Admin granted it on THIS module (audience
|
|
116
|
+
* `blu-module:<moduleId>`). It names the client per call with X-Client-Id, from
|
|
117
|
+
* the clients this module is enabled for.
|
|
118
|
+
*
|
|
119
|
+
* @param {{ issuer: string, jwksUrl: string, moduleId: string }} opts
|
|
120
|
+
*/
|
|
121
|
+
declare function bluServiceAuth({ issuer, jwksUrl, moduleId }: {
|
|
122
|
+
issuer: string;
|
|
123
|
+
jwksUrl: string;
|
|
124
|
+
moduleId: string;
|
|
125
|
+
}): {
|
|
126
|
+
mode: string;
|
|
127
|
+
kind: string;
|
|
128
|
+
issuer: string;
|
|
129
|
+
accepts: (claims: any) => boolean;
|
|
130
|
+
authenticate(token: any, req: any): Promise<{
|
|
131
|
+
authMode: string;
|
|
132
|
+
kind: string;
|
|
133
|
+
issuer: string;
|
|
134
|
+
subject: any;
|
|
135
|
+
key: string;
|
|
136
|
+
displayName: any;
|
|
137
|
+
clientId: any;
|
|
138
|
+
allowedClients: any;
|
|
139
|
+
roles: any[];
|
|
140
|
+
permissions: string[];
|
|
141
|
+
clientFromRequest: boolean;
|
|
142
|
+
}>;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* The team owns this IdP (Cognito, Auth0, homegrown — anything that issues JWTs
|
|
146
|
+
* with a JWKS). `toPrincipal` maps the team's claim shape onto the common one.
|
|
147
|
+
*
|
|
148
|
+
* @param {{ issuer: string, jwksUrl: string, audience: string,
|
|
149
|
+
* toPrincipal?: (payload: object) => Partial<Principal> }} opts
|
|
150
|
+
*/
|
|
151
|
+
declare function teamIdpAuth({ issuer, jwksUrl, audience, toPrincipal }: {
|
|
152
|
+
issuer: string;
|
|
153
|
+
jwksUrl: string;
|
|
154
|
+
audience: string;
|
|
155
|
+
toPrincipal?: (payload: object) => Partial<Principal>;
|
|
156
|
+
}): {
|
|
157
|
+
mode: string;
|
|
158
|
+
kind: string;
|
|
159
|
+
issuer: string;
|
|
160
|
+
accepts: () => boolean;
|
|
161
|
+
authenticate(token: any): Promise<{
|
|
162
|
+
authMode: string;
|
|
163
|
+
kind: string;
|
|
164
|
+
issuer: string;
|
|
165
|
+
/**
|
|
166
|
+
* user id, or api-key id
|
|
167
|
+
*/
|
|
168
|
+
subject?: string;
|
|
169
|
+
/**
|
|
170
|
+
* stable identity across requests: `<authMode>|<issuer>|<subject>`.
|
|
171
|
+
* Key your own records (audit, ownership, preferences) on this —
|
|
172
|
+
* a Blu user needs no account in your system first.
|
|
173
|
+
*/
|
|
174
|
+
key: string;
|
|
175
|
+
displayName?: string;
|
|
176
|
+
email?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Blu only: the app that obtained the token ("blu-host",
|
|
179
|
+
* "blu-concierge", or your own standalone app)
|
|
180
|
+
*/
|
|
181
|
+
via?: string;
|
|
182
|
+
/**
|
|
183
|
+
* Blu only: software acting for the user (e.g. "blu-concierge")
|
|
184
|
+
*/
|
|
185
|
+
actor?: string;
|
|
186
|
+
/**
|
|
187
|
+
* active client (from the credential, never the request — except see api keys)
|
|
188
|
+
*/
|
|
189
|
+
clientId?: string | null;
|
|
190
|
+
allowedClients?: string[];
|
|
191
|
+
roles?: string[];
|
|
192
|
+
/**
|
|
193
|
+
* resolved; may contain "*"
|
|
194
|
+
*/
|
|
195
|
+
permissions?: string[];
|
|
196
|
+
devIdentity: any;
|
|
197
|
+
} | {
|
|
198
|
+
subject: any;
|
|
199
|
+
displayName: any;
|
|
200
|
+
email: any;
|
|
201
|
+
clientId: any;
|
|
202
|
+
allowedClients: any;
|
|
203
|
+
roles: any[];
|
|
204
|
+
permissions: any;
|
|
205
|
+
authMode: string;
|
|
206
|
+
kind: string;
|
|
207
|
+
issuer: string;
|
|
208
|
+
key: string;
|
|
209
|
+
devIdentity: any;
|
|
210
|
+
}>;
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Keys are stored only as SHA-256 hashes, each scoped to clients + permissions
|
|
214
|
+
* and rate-limited. Browsers are refused outright: a key in a web page is a key
|
|
215
|
+
* anyone can copy.
|
|
216
|
+
*
|
|
217
|
+
* @param {{ keys: { id: string, name: string, hash: string, clients: string[],
|
|
218
|
+
* permissions: string[], ratePerMinute?: number }[] }} opts
|
|
219
|
+
*/
|
|
220
|
+
declare function apiKeyAuth({ keys }: {
|
|
221
|
+
keys: {
|
|
222
|
+
id: string;
|
|
223
|
+
name: string;
|
|
224
|
+
hash: string;
|
|
225
|
+
clients: string[];
|
|
226
|
+
permissions: string[];
|
|
227
|
+
ratePerMinute?: number;
|
|
228
|
+
}[];
|
|
229
|
+
}): {
|
|
230
|
+
mode: string;
|
|
231
|
+
kind: string;
|
|
232
|
+
authenticate(presented: any, req: any): Promise<{
|
|
233
|
+
authMode: string;
|
|
234
|
+
kind: string;
|
|
235
|
+
issuer: string;
|
|
236
|
+
subject: string;
|
|
237
|
+
key: string;
|
|
238
|
+
displayName: string;
|
|
239
|
+
clientId: any;
|
|
240
|
+
allowedClients: string[];
|
|
241
|
+
roles: any[];
|
|
242
|
+
permissions: string[];
|
|
243
|
+
clientFromRequest: boolean;
|
|
244
|
+
}>;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* @param {{ strategies: ReturnType<typeof bluPlatformAuth|typeof teamIdpAuth|typeof apiKeyAuth>[], apiUrl?: string }} opts
|
|
248
|
+
* apiUrl — this API's own public URL, as configured. Tokens from local-only
|
|
249
|
+
* (passwordless) sign-ins are accepted only when it's on this machine; leave
|
|
250
|
+
* it out and they're always refused.
|
|
251
|
+
*/
|
|
252
|
+
declare function createModuleAuth({ strategies, apiUrl }: {
|
|
253
|
+
strategies: ReturnType<typeof bluPlatformAuth | typeof teamIdpAuth | typeof apiKeyAuth>[];
|
|
254
|
+
apiUrl?: string;
|
|
255
|
+
}): {
|
|
256
|
+
authenticate: (req: any, res: any, next: any) => Promise<any>;
|
|
257
|
+
verifyRequest: (request: any) => Promise<{
|
|
258
|
+
authMode: string;
|
|
259
|
+
kind: string;
|
|
260
|
+
issuer: string;
|
|
261
|
+
subject: any;
|
|
262
|
+
key: string;
|
|
263
|
+
devIdentity: any;
|
|
264
|
+
displayName: any;
|
|
265
|
+
email: any;
|
|
266
|
+
provider: any;
|
|
267
|
+
via: any;
|
|
268
|
+
actor: any;
|
|
269
|
+
clientId: any;
|
|
270
|
+
allowedClients: any;
|
|
271
|
+
roles: any;
|
|
272
|
+
permissions: any[];
|
|
273
|
+
} | {
|
|
274
|
+
authMode: string;
|
|
275
|
+
kind: string;
|
|
276
|
+
issuer: string;
|
|
277
|
+
/**
|
|
278
|
+
* user id, or api-key id
|
|
279
|
+
*/
|
|
280
|
+
subject?: string;
|
|
281
|
+
/**
|
|
282
|
+
* stable identity across requests: `<authMode>|<issuer>|<subject>`.
|
|
283
|
+
* Key your own records (audit, ownership, preferences) on this —
|
|
284
|
+
* a Blu user needs no account in your system first.
|
|
285
|
+
*/
|
|
286
|
+
key: string;
|
|
287
|
+
displayName?: string;
|
|
288
|
+
email?: string;
|
|
289
|
+
/**
|
|
290
|
+
* Blu only: the app that obtained the token ("blu-host",
|
|
291
|
+
* "blu-concierge", or your own standalone app)
|
|
292
|
+
*/
|
|
293
|
+
via?: string;
|
|
294
|
+
/**
|
|
295
|
+
* Blu only: software acting for the user (e.g. "blu-concierge")
|
|
296
|
+
*/
|
|
297
|
+
actor?: string;
|
|
298
|
+
/**
|
|
299
|
+
* active client (from the credential, never the request — except see api keys)
|
|
300
|
+
*/
|
|
301
|
+
clientId?: string | null;
|
|
302
|
+
allowedClients?: string[];
|
|
303
|
+
roles?: string[];
|
|
304
|
+
/**
|
|
305
|
+
* resolved; may contain "*"
|
|
306
|
+
*/
|
|
307
|
+
permissions?: string[];
|
|
308
|
+
devIdentity: any;
|
|
309
|
+
} | {
|
|
310
|
+
subject: any;
|
|
311
|
+
displayName: any;
|
|
312
|
+
email: any;
|
|
313
|
+
clientId: any;
|
|
314
|
+
allowedClients: any;
|
|
315
|
+
roles: any[];
|
|
316
|
+
permissions: any;
|
|
317
|
+
authMode: string;
|
|
318
|
+
kind: string;
|
|
319
|
+
issuer: string;
|
|
320
|
+
key: string;
|
|
321
|
+
devIdentity: any;
|
|
322
|
+
} | {
|
|
323
|
+
authMode: string;
|
|
324
|
+
kind: string;
|
|
325
|
+
issuer: string;
|
|
326
|
+
subject: string;
|
|
327
|
+
key: string;
|
|
328
|
+
displayName: string;
|
|
329
|
+
clientId: any;
|
|
330
|
+
allowedClients: string[];
|
|
331
|
+
roles: any[];
|
|
332
|
+
permissions: string[];
|
|
333
|
+
clientFromRequest: boolean;
|
|
334
|
+
}>;
|
|
335
|
+
allows: (policy: any, principal: any, askedClientId: any) => any;
|
|
336
|
+
authorize: (policy: Partial<Record<"blu" | "service" | "team" | "api-key", string[]>>) => (req: any, res: any, next: any) => any;
|
|
337
|
+
requirePermission: (permission: any) => (req: any, res: any, next: any) => any;
|
|
338
|
+
modes: string[];
|
|
339
|
+
};
|
|
340
|
+
/**
|
|
341
|
+
* Who this API has seen, keyed by `principal.key` — so a person signed in with
|
|
342
|
+
* Blu needs no account in the team's own user store first. The team records
|
|
343
|
+
* them on first sight (just-in-time) and can attach its own data to that key:
|
|
344
|
+
* "flagged by", audit trails, preferences. Nothing is linked to the team's own
|
|
345
|
+
* users; a Blu user and a team-IdP user are different principals.
|
|
346
|
+
*
|
|
347
|
+
* In-memory here; a real team keeps this in its own database.
|
|
348
|
+
*
|
|
349
|
+
* const people = createPrincipalDirectory();
|
|
350
|
+
* app.get("/x", [authenticate, people.remember], authorize({...}), handler)
|
|
351
|
+
*/
|
|
352
|
+
declare function createPrincipalDirectory(): {
|
|
353
|
+
remember: (req: any, _res: any, next: any) => void;
|
|
354
|
+
get: (key: any) => any;
|
|
355
|
+
list: () => any[];
|
|
356
|
+
};
|
|
357
|
+
/** Parse AUTH_MODES="blu,service,team,api-key" into a Set (defaults to all). */
|
|
358
|
+
declare function enabledModes(value: any, all?: string[]): Set<any>;
|
|
359
|
+
/**
|
|
360
|
+
* Explicit-allowlist CORS. Written out (rather than `cors()`) so the mechanics
|
|
361
|
+
* are visible: echo only allowlisted origins, `Vary: Origin`, answer preflights
|
|
362
|
+
* for the Authorization header. Unlisted origins get no CORS headers at all, so
|
|
363
|
+
* the *browser* refuses to hand the response to the calling page.
|
|
364
|
+
*
|
|
365
|
+
* `origins` may be an array or a (possibly async) function, for allowlists that
|
|
366
|
+
* come from live config such as the registry.
|
|
367
|
+
*
|
|
368
|
+
* @param {{ origins: string[] | (() => string[] | Promise<string[]>), credentials?: boolean }} opts
|
|
369
|
+
*/
|
|
370
|
+
declare function corsAllowlist({ origins, credentials }: {
|
|
371
|
+
origins: string[] | (() => string[] | Promise<string[]>);
|
|
372
|
+
credentials?: boolean;
|
|
373
|
+
}): (req: any, res: any, next: any) => Promise<any>;
|
|
374
|
+
/** Tiny request logger that shows who is calling and how — handy in the demo. */
|
|
375
|
+
declare function originLogger(name: any): (req: any, _res: any, next: any) => any;
|
|
376
|
+
/**
|
|
377
|
+
* @typedef {object} Principal
|
|
378
|
+
* @property {"blu"|"service"|"team"|"api-key"} authMode
|
|
379
|
+
* @property {"user"|"service"} kind
|
|
380
|
+
* @property {string} issuer
|
|
381
|
+
* @property {string} subject user id, or api-key id
|
|
382
|
+
* @property {string} key stable identity across requests: `<authMode>|<issuer>|<subject>`.
|
|
383
|
+
* Key your own records (audit, ownership, preferences) on this —
|
|
384
|
+
* a Blu user needs no account in your system first.
|
|
385
|
+
* @property {string} displayName
|
|
386
|
+
* @property {string} [email]
|
|
387
|
+
* @property {string} [via] Blu only: the app that obtained the token ("blu-host",
|
|
388
|
+
* "blu-concierge", or your own standalone app)
|
|
389
|
+
* @property {string} [actor] Blu only: software acting for the user (e.g. "blu-concierge")
|
|
390
|
+
* @property {string|null} clientId active client (from the credential, never the request — except see api keys)
|
|
391
|
+
* @property {string[]} allowedClients
|
|
392
|
+
* @property {string[]} roles
|
|
393
|
+
* @property {string[]} permissions resolved; may contain "*"
|
|
394
|
+
*/
|
|
395
|
+
declare class AuthError extends Error {
|
|
396
|
+
constructor(status: any, code: any, detail: any);
|
|
397
|
+
status: any;
|
|
398
|
+
code: any;
|
|
399
|
+
}
|
|
400
|
+
declare function hashApiKey(key: any): any;
|
|
401
|
+
type Principal = {
|
|
402
|
+
authMode: "blu" | "service" | "team" | "api-key";
|
|
403
|
+
kind: "user" | "service";
|
|
404
|
+
issuer: string;
|
|
405
|
+
/**
|
|
406
|
+
* user id, or api-key id
|
|
407
|
+
*/
|
|
408
|
+
subject: string;
|
|
409
|
+
/**
|
|
410
|
+
* stable identity across requests: `<authMode>|<issuer>|<subject>`.
|
|
411
|
+
* Key your own records (audit, ownership, preferences) on this —
|
|
412
|
+
* a Blu user needs no account in your system first.
|
|
413
|
+
*/
|
|
414
|
+
key: string;
|
|
415
|
+
displayName: string;
|
|
416
|
+
email?: string;
|
|
417
|
+
/**
|
|
418
|
+
* Blu only: the app that obtained the token ("blu-host",
|
|
419
|
+
* "blu-concierge", or your own standalone app)
|
|
420
|
+
*/
|
|
421
|
+
via?: string;
|
|
422
|
+
/**
|
|
423
|
+
* Blu only: software acting for the user (e.g. "blu-concierge")
|
|
424
|
+
*/
|
|
425
|
+
actor?: string;
|
|
426
|
+
/**
|
|
427
|
+
* active client (from the credential, never the request — except see api keys)
|
|
428
|
+
*/
|
|
429
|
+
clientId: string | null;
|
|
430
|
+
allowedClients: string[];
|
|
431
|
+
roles: string[];
|
|
432
|
+
/**
|
|
433
|
+
* resolved; may contain "*"
|
|
434
|
+
*/
|
|
435
|
+
permissions: string[];
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Blu's public addresses, per environment ("dev", "staging" or "prod"). Configure your API from these
|
|
440
|
+
* instead of copying URLs: what to trust (the issuer), who may call you (the shell origins), and where your
|
|
441
|
+
* pipeline registers releases (the registry).
|
|
442
|
+
*/
|
|
443
|
+
/** Where every module's pipeline registers its releases, for every environment. Permanent. */
|
|
444
|
+
declare const REGISTRY_URL: "https://registry.blu-ce.horizonmedia.com";
|
|
445
|
+
declare function bluShellOrigins(stage: "dev" | "staging" | "prod"): string[];
|
|
446
|
+
declare function bluIssuer(stage: "dev" | "staging" | "prod"): string;
|
|
447
|
+
|
|
448
|
+
export { AuthError, REGISTRY_URL, apiKeyAuth, bluIssuer, bluPlatformAuth, bluServiceAuth, bluShellOrigins, corsAllowlist, createMcpEndpoint, createMcpWebHandler, createModuleAuth, createPrincipalDirectory, enabledModes, hashApiKey, link, originLogger, policyAllows, teamIdpAuth };
|