@dudousxd/nestjs-agent-dashboard 0.9.0 → 0.10.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.
@@ -194,12 +194,35 @@ interface DashboardSessionUser {
194
194
  roles?: string[];
195
195
  }
196
196
 
197
- /** Host hook: validates submitted credentials for the built-in login screen. */
197
+ /**
198
+ * Host hook for Mode A: validates the host's own auth on the raw request POSTed to
199
+ * `<basePath>/auth/session`. Return the session user to grant access, or `null` to deny.
200
+ */
201
+ type SessionHook = (request: unknown) => Promise<DashboardSessionUser | null> | DashboardSessionUser | null;
202
+ /** Host hook for Mode B: validates submitted credentials for the built-in login screen. */
198
203
  type LoginHook = (username: string, password: string) => Promise<DashboardSessionUser | null> | DashboardSessionUser | null;
204
+ /**
205
+ * Re-checks a LIVE session when the cookie is slid forward. Runs at most once per `ttl/2` PER
206
+ * COOKIE GENERATION, per in-flight request — the gate is on the inbound cookie's `iat`, so every
207
+ * request still carrying a not-yet-renewed cookie invokes this hook, not just the first: a page
208
+ * load that fires N parallel API calls can trigger up to N calls before the refreshed cookie lands
209
+ * on the client. Bounded and cheap for typical console traffic, but not a per-session-lifetime
210
+ * cap — a slow or expensive check should debounce/cache on its own. Return `false` to revoke (the
211
+ * cookie is cleared and the request denied). Distinct from `session`: that hook reads the host's
212
+ * auth off a fresh request, which a console XHR does not carry — this one receives the
213
+ * already-minted session.
214
+ */
215
+ type RevalidateHook = (session: DashboardSessionUser) => Promise<boolean> | boolean;
216
+ /** Which `dashboardAuth` hook(s) a resolved config was given — see `resolveDashboardAuth`. */
217
+ type AuthMode = 'session' | 'login';
199
218
  /**
200
219
  * Author-facing `dashboardAuth` option (see `AgentDashboardOptions.dashboardAuth`). Gates the
201
- * console (SPA + API) behind a built-in cookie-session login screen — no host frontend changes,
202
- * no SSO required. Mirrors `@dudousxd/nestjs-telescope`'s `dashboardAuth` Mode B (`login`).
220
+ * console (SPA + API) behind a signed session cookie. Two ways to mint that cookie: Mode A
221
+ * (`session`) — the host frontend, already carrying its own auth, POSTs to
222
+ * `<basePath>/auth/session` and the host hook decides — or Mode B (`login`) — the built-in,
223
+ * dependency-free server-rendered login screen. Mirrors `@dudousxd/nestjs-telescope`'s
224
+ * `dashboardAuth` two-mode shape. At least one of the two is required so an un-mintable gate is a
225
+ * boot error, not a silently-open (or silently-stuck) console.
203
226
  */
204
227
  interface DashboardAuthOptions {
205
228
  /** REQUIRED HMAC-SHA256 signing key (32+ bytes recommended). Missing/empty => boot error (fail closed). */
@@ -207,23 +230,36 @@ interface DashboardAuthOptions {
207
230
  /** Cookie TTL (duration string `'<n><ms|s|m|h|d>'`, e.g. `'30m'`, `'7d'`). Default `'8h'`. */
208
231
  ttl?: string;
209
232
  /**
210
- * Validates submitted username/password. Return the session user to grant access, or `null` to
211
- * deny — the login endpoint responds identically (generic failure) for an unknown user and a
212
- * wrong password, so it never reveals which one was wrong.
233
+ * Mode A: validates the host's own auth on the raw request POSTed to `<basePath>/auth/session`.
234
+ * Return the session user to grant access, or `null` to deny. No credential reaches this
235
+ * library — the host decides from whatever it already has (a header, an SSO cookie, ...).
213
236
  */
214
- login: LoginHook;
237
+ session?: SessionHook;
238
+ /**
239
+ * Mode B: validates submitted username/password. Return the session user to grant access, or
240
+ * `null` to deny — the login endpoint responds identically (generic failure) for an unknown user
241
+ * and a wrong password, so it never reveals which one was wrong.
242
+ */
243
+ login?: LoginHook;
244
+ /** Re-checks a live session on sliding renewal; see `RevalidateHook`. Not a mode — it cannot
245
+ * mint a session, only revoke one already minted by `session`/`login`. */
246
+ revalidate?: RevalidateHook;
215
247
  }
216
248
  /** Resolved, validated `dashboardAuth` config used by the guards/controller. */
217
249
  interface ResolvedDashboardAuth {
218
250
  secret: string;
219
251
  ttlMs: number;
220
- login: LoginHook;
252
+ modes: AuthMode[];
253
+ session?: SessionHook;
254
+ login?: LoginHook;
255
+ revalidate?: RevalidateHook;
221
256
  }
222
257
  /**
223
258
  * Validate + resolve `dashboardAuth`. Returns `null` when unconfigured (behavior unchanged — the
224
259
  * console stays open, front it with your own `guards`). Throws at boot (fail closed) when
225
- * configured but missing a secret or a `login` hook — the host learns immediately rather than
226
- * shipping an open or un-mintable console.
260
+ * configured but missing a secret, when neither `session` nor `login` is given, or when a given
261
+ * hook isn't a function — the host learns immediately rather than shipping an open, stuck, or
262
+ * un-mintable console.
227
263
  */
228
264
  declare function resolveDashboardAuth(options: DashboardAuthOptions | undefined): ResolvedDashboardAuth | null;
229
265
 
@@ -248,32 +284,36 @@ interface LoginFormBody {
248
284
  * built-in gates check for, so they can never be made to require the very auth they grant. Mirrors
249
285
  * `@dudousxd/nestjs-telescope`'s own auth controller staying outside its `stampGuards` call.
250
286
  *
251
- * A dependency-free, server-rendered login form (GET/POST) rather than a JSON API + client-side
252
- * screen — the bundled React SPA in this package is a built Vite artifact with no auth-aware UI of
253
- * its own, so gating the actual page navigation needs a self-contained flow that doesn't touch it.
254
- *
255
- * 404s every route when `dashboardAuth` is unconfigured (`DASHBOARD_AUTH` resolves to `null`) — no
256
- * dangling login page when the feature is off.
287
+ * Two ways to mint that cookie, matching `resolveDashboardAuth`'s modes: Mode A (`session`) — the
288
+ * host frontend, already carrying its own auth, POSTs to `<basePath>/auth/session` and the host
289
+ * hook decides — or Mode B (`login`), a dependency-free, server-rendered login form (GET/POST) —
290
+ * the bundled React SPA in this package is a built Vite artifact with no auth-aware UI of its own,
291
+ * so gating the actual page navigation needs a self-contained flow that doesn't touch it. Each
292
+ * mode's routes 404 when that mode isn't configured (`auth.session`/`auth.login` absent), and
293
+ * every route 404s outright when `dashboardAuth` is unconfigured (`DASHBOARD_AUTH` resolves to
294
+ * `null`) — no dangling login page when the feature is off.
257
295
  */
258
296
  declare class AgentDashboardAuthController {
259
297
  private readonly auth;
260
298
  private readonly basePath;
261
299
  private readonly logger;
262
- /** Warn once (not per request) so a broken hook can't be used to flood the logs. */
263
- private warnedLoginHookThrow;
300
+ /** Warn once PER HOOK KIND (not per request) so a broken hook can't be used to flood the logs. */
301
+ private readonly warnedHooks;
264
302
  constructor(auth: ResolvedDashboardAuth | null, basePath: string);
265
303
  loginPage(req: AuthPageRequest, res: AuthPageResponse, returnToQuery?: string, error?: string): string;
266
304
  login(body: LoginFormBody, req: unknown, res: AuthPageResponse): Promise<string>;
267
305
  logout(req: unknown, res: AuthPageResponse): string;
306
+ session(request: unknown, response: unknown): Promise<void>;
307
+ sessionRequiredPage(): string;
268
308
  /** Uniform failure: same redirect (generic error flag) whether the user is unknown or the password is wrong. */
269
309
  private redirectToLoginError;
270
310
  private currentSession;
271
311
  /**
272
- * Run the host's `login` hook defensively: a throw (sync or async) is treated as a denial
273
- * (`null`) and warn-logged ONCE, so a buggy/unreachable hook never 500s the endpoint into a
274
- * stack-trace leak nor floods the logs.
312
+ * Run a host hook (`login` or `session`) defensively: a throw (sync or async) is treated as a
313
+ * denial (`null`) and warn-logged ONCE PER KIND, so a buggy/unreachable hook never 500s the
314
+ * endpoint into a stack-trace leak nor floods the logs on repeated bad attempts.
275
315
  */
276
- private runLoginHook;
316
+ private runHook;
277
317
  private requireAuth;
278
318
  }
279
319
 
@@ -355,21 +395,36 @@ interface AgentDashboardOptions<TReq = unknown> {
355
395
  */
356
396
  approvalActorRef?: (req: TReq) => string | undefined;
357
397
  /**
358
- * Gate the console (SPA + API) behind a BUILT-IN cookie-session login screen — the simplest way
359
- * to protect `basePath` when the host has no ready-made guard (e.g. header-only auth that a
360
- * browser navigation can't attach). Omit to leave the console open, or fronted only by
361
- * {@link guards}. When set, an unauthenticated page navigation is redirected (302) to
362
- * `<basePath>/auth/login`; an unauthenticated API call gets a `401`. Composes with `guards` —
363
- * BOTH gates must pass. See `DashboardAuthOptions` for the `secret`/`ttl`/`login` shape.
398
+ * Gate the console (SPA + API) behind a built-in, signed session cookie. Two ways to mint it:
399
+ *
400
+ * - **Mode A (`session`, recommended)**: your host app already has its own auth (SSO/OIDC/
401
+ * whatever) — the host frontend, carrying that auth, POSTs to `<basePath>/auth/session`, your
402
+ * `session` hook validates the raw request and returns the session user, and this library
403
+ * mints its cookie from that. No credential this library understands ever exists; you keep
404
+ * your own identity provider as the source of truth. A page-level request with no valid
405
+ * session (and only Mode A configured) gets a small server-rendered instruction page telling
406
+ * the visitor to sign in through your host app, since there is no login page to redirect to.
407
+ * - **Mode B (`login`, standalone fallback)**: no host frontend/IdP to lean on — the console
408
+ * serves its own small, dependency-free, server-rendered login page (`GET
409
+ * <basePath>/auth/login`) and your `login` hook validates submitted username/password. A
410
+ * missing/invalid/expired session redirects a page-level request to that login page with
411
+ * `?returnTo=<original url>`.
412
+ *
413
+ * Either mode can be used alone, or both together (e.g. Mode A for normal use, Mode B as a
414
+ * break-glass fallback) — at least one is required, or `forRoot`/`forRootAsync` throws at boot
415
+ * (an un-mintable gate is a boot error, not a silently-open or silently-stuck console). An
416
+ * unauthenticated API call always gets a plain `401`, regardless of mode — the caller reads the
417
+ * status code, not HTML. Composes with `guards` — BOTH gates must pass. See
418
+ * `DashboardAuthOptions` for the `secret`/`ttl`/`session`/`login` shape.
364
419
  */
365
420
  dashboardAuth?: DashboardAuthOptions;
366
421
  }
367
422
  /**
368
- * Async variant of {@link AgentDashboardOptions}, for a `login` hook that needs injected services
369
- * (e.g. an EntityManager to check credentials against a DB). Everything else stays static/sync —
370
- * `basePath`/`apiBasePath`/`guards` are needed at module-build time (the same constraint
371
- * `@dudousxd/nestjs-telescope`'s and `@dudousxd/nestjs-media`'s own `forRootAsync`s document), so
372
- * only the auth piece itself is resolved through DI.
423
+ * Async variant of {@link AgentDashboardOptions}, for a `session`/`login` hook that needs injected
424
+ * services (e.g. an EntityManager to check credentials against a DB). Everything else stays
425
+ * static/sync — `basePath`/`apiBasePath`/`guards` are needed at module-build time (the same
426
+ * constraint `@dudousxd/nestjs-telescope`'s and `@dudousxd/nestjs-media`'s own `forRootAsync`s
427
+ * document), so only the auth piece itself is resolved through DI.
373
428
  */
374
429
  interface AgentDashboardAsyncOptions<TReq = unknown> {
375
430
  basePath?: string;
@@ -404,13 +459,15 @@ declare class AgentApiModule {
404
459
  }
405
460
  /**
406
461
  * Mounts the AI-gateway governance console: the bundled React SPA at `basePath` and its JSON + SSE
407
- * API at `apiBasePath` (default `<basePath>/api`), plus the built-in login screen's routes at
408
- * `<basePath>/auth/*` when {@link AgentDashboardOptions.dashboardAuth} is set.
462
+ * API at `apiBasePath` (default `<basePath>/api`), plus the built-in `dashboardAuth` routes at
463
+ * `<basePath>/auth/*` when {@link AgentDashboardOptions.dashboardAuth} is set — `POST
464
+ * <basePath>/auth/session` for Mode A (the host mints the session from its own auth) and/or `GET`/
465
+ * `POST <basePath>/auth/login` for Mode B (the built-in login screen).
409
466
  *
410
467
  * Import via `AgentDashboardModule.forRoot(...)` alongside your `@dudousxd/nestjs-agent` module
411
468
  * (global), which must provide `AGENT_GOVERNANCE_QUERIES` (bound by a store adapter). Front the
412
469
  * routes with the first-class `guards` option (plus `imports` for the guards' own dependencies) —
413
- * see {@link AgentDashboardOptions.guards} — and/or the built-in `dashboardAuth` cookie login.
470
+ * see {@link AgentDashboardOptions.guards} — and/or the built-in `dashboardAuth` session cookie.
414
471
  *
415
472
  * Inertia hosts: the console is a full-page app, not an Inertia page. An in-app `<Link>` visit to
416
473
  * `basePath` (an XHR carrying `X-Inertia`) is bounced with the protocol's own external-redirect
@@ -530,4 +587,4 @@ declare const DASHBOARD_APPROVAL_ACTOR_REF: unique symbol;
530
587
  */
531
588
  declare const DASHBOARD_AUTH: unique symbol;
532
589
 
533
- export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, type AgentDashboardAsyncOptions, AgentDashboardAuthController, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_AUTH, DASHBOARD_BASE_PATH, type DashboardAuthOptions, DashboardService, type LiveAgentEvent, type LoginHook, type ReliabilityOverview, type ResolvedDashboardAuth, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadSpendRowWithLabel, type WithActorLabel, agentDashboardMountPaths, parsePriceInput, resolveDashboardAuth };
590
+ export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, type AgentDashboardAsyncOptions, AgentDashboardAuthController, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, type AuthMode, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_AUTH, DASHBOARD_BASE_PATH, type DashboardAuthOptions, DashboardService, type LiveAgentEvent, type LoginHook, type ReliabilityOverview, type ResolvedDashboardAuth, type RevalidateHook, type SessionHook, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadSpendRowWithLabel, type WithActorLabel, agentDashboardMountPaths, parsePriceInput, resolveDashboardAuth };
@@ -194,12 +194,35 @@ interface DashboardSessionUser {
194
194
  roles?: string[];
195
195
  }
196
196
 
197
- /** Host hook: validates submitted credentials for the built-in login screen. */
197
+ /**
198
+ * Host hook for Mode A: validates the host's own auth on the raw request POSTed to
199
+ * `<basePath>/auth/session`. Return the session user to grant access, or `null` to deny.
200
+ */
201
+ type SessionHook = (request: unknown) => Promise<DashboardSessionUser | null> | DashboardSessionUser | null;
202
+ /** Host hook for Mode B: validates submitted credentials for the built-in login screen. */
198
203
  type LoginHook = (username: string, password: string) => Promise<DashboardSessionUser | null> | DashboardSessionUser | null;
204
+ /**
205
+ * Re-checks a LIVE session when the cookie is slid forward. Runs at most once per `ttl/2` PER
206
+ * COOKIE GENERATION, per in-flight request — the gate is on the inbound cookie's `iat`, so every
207
+ * request still carrying a not-yet-renewed cookie invokes this hook, not just the first: a page
208
+ * load that fires N parallel API calls can trigger up to N calls before the refreshed cookie lands
209
+ * on the client. Bounded and cheap for typical console traffic, but not a per-session-lifetime
210
+ * cap — a slow or expensive check should debounce/cache on its own. Return `false` to revoke (the
211
+ * cookie is cleared and the request denied). Distinct from `session`: that hook reads the host's
212
+ * auth off a fresh request, which a console XHR does not carry — this one receives the
213
+ * already-minted session.
214
+ */
215
+ type RevalidateHook = (session: DashboardSessionUser) => Promise<boolean> | boolean;
216
+ /** Which `dashboardAuth` hook(s) a resolved config was given — see `resolveDashboardAuth`. */
217
+ type AuthMode = 'session' | 'login';
199
218
  /**
200
219
  * Author-facing `dashboardAuth` option (see `AgentDashboardOptions.dashboardAuth`). Gates the
201
- * console (SPA + API) behind a built-in cookie-session login screen — no host frontend changes,
202
- * no SSO required. Mirrors `@dudousxd/nestjs-telescope`'s `dashboardAuth` Mode B (`login`).
220
+ * console (SPA + API) behind a signed session cookie. Two ways to mint that cookie: Mode A
221
+ * (`session`) — the host frontend, already carrying its own auth, POSTs to
222
+ * `<basePath>/auth/session` and the host hook decides — or Mode B (`login`) — the built-in,
223
+ * dependency-free server-rendered login screen. Mirrors `@dudousxd/nestjs-telescope`'s
224
+ * `dashboardAuth` two-mode shape. At least one of the two is required so an un-mintable gate is a
225
+ * boot error, not a silently-open (or silently-stuck) console.
203
226
  */
204
227
  interface DashboardAuthOptions {
205
228
  /** REQUIRED HMAC-SHA256 signing key (32+ bytes recommended). Missing/empty => boot error (fail closed). */
@@ -207,23 +230,36 @@ interface DashboardAuthOptions {
207
230
  /** Cookie TTL (duration string `'<n><ms|s|m|h|d>'`, e.g. `'30m'`, `'7d'`). Default `'8h'`. */
208
231
  ttl?: string;
209
232
  /**
210
- * Validates submitted username/password. Return the session user to grant access, or `null` to
211
- * deny — the login endpoint responds identically (generic failure) for an unknown user and a
212
- * wrong password, so it never reveals which one was wrong.
233
+ * Mode A: validates the host's own auth on the raw request POSTed to `<basePath>/auth/session`.
234
+ * Return the session user to grant access, or `null` to deny. No credential reaches this
235
+ * library — the host decides from whatever it already has (a header, an SSO cookie, ...).
213
236
  */
214
- login: LoginHook;
237
+ session?: SessionHook;
238
+ /**
239
+ * Mode B: validates submitted username/password. Return the session user to grant access, or
240
+ * `null` to deny — the login endpoint responds identically (generic failure) for an unknown user
241
+ * and a wrong password, so it never reveals which one was wrong.
242
+ */
243
+ login?: LoginHook;
244
+ /** Re-checks a live session on sliding renewal; see `RevalidateHook`. Not a mode — it cannot
245
+ * mint a session, only revoke one already minted by `session`/`login`. */
246
+ revalidate?: RevalidateHook;
215
247
  }
216
248
  /** Resolved, validated `dashboardAuth` config used by the guards/controller. */
217
249
  interface ResolvedDashboardAuth {
218
250
  secret: string;
219
251
  ttlMs: number;
220
- login: LoginHook;
252
+ modes: AuthMode[];
253
+ session?: SessionHook;
254
+ login?: LoginHook;
255
+ revalidate?: RevalidateHook;
221
256
  }
222
257
  /**
223
258
  * Validate + resolve `dashboardAuth`. Returns `null` when unconfigured (behavior unchanged — the
224
259
  * console stays open, front it with your own `guards`). Throws at boot (fail closed) when
225
- * configured but missing a secret or a `login` hook — the host learns immediately rather than
226
- * shipping an open or un-mintable console.
260
+ * configured but missing a secret, when neither `session` nor `login` is given, or when a given
261
+ * hook isn't a function — the host learns immediately rather than shipping an open, stuck, or
262
+ * un-mintable console.
227
263
  */
228
264
  declare function resolveDashboardAuth(options: DashboardAuthOptions | undefined): ResolvedDashboardAuth | null;
229
265
 
@@ -248,32 +284,36 @@ interface LoginFormBody {
248
284
  * built-in gates check for, so they can never be made to require the very auth they grant. Mirrors
249
285
  * `@dudousxd/nestjs-telescope`'s own auth controller staying outside its `stampGuards` call.
250
286
  *
251
- * A dependency-free, server-rendered login form (GET/POST) rather than a JSON API + client-side
252
- * screen — the bundled React SPA in this package is a built Vite artifact with no auth-aware UI of
253
- * its own, so gating the actual page navigation needs a self-contained flow that doesn't touch it.
254
- *
255
- * 404s every route when `dashboardAuth` is unconfigured (`DASHBOARD_AUTH` resolves to `null`) — no
256
- * dangling login page when the feature is off.
287
+ * Two ways to mint that cookie, matching `resolveDashboardAuth`'s modes: Mode A (`session`) — the
288
+ * host frontend, already carrying its own auth, POSTs to `<basePath>/auth/session` and the host
289
+ * hook decides — or Mode B (`login`), a dependency-free, server-rendered login form (GET/POST) —
290
+ * the bundled React SPA in this package is a built Vite artifact with no auth-aware UI of its own,
291
+ * so gating the actual page navigation needs a self-contained flow that doesn't touch it. Each
292
+ * mode's routes 404 when that mode isn't configured (`auth.session`/`auth.login` absent), and
293
+ * every route 404s outright when `dashboardAuth` is unconfigured (`DASHBOARD_AUTH` resolves to
294
+ * `null`) — no dangling login page when the feature is off.
257
295
  */
258
296
  declare class AgentDashboardAuthController {
259
297
  private readonly auth;
260
298
  private readonly basePath;
261
299
  private readonly logger;
262
- /** Warn once (not per request) so a broken hook can't be used to flood the logs. */
263
- private warnedLoginHookThrow;
300
+ /** Warn once PER HOOK KIND (not per request) so a broken hook can't be used to flood the logs. */
301
+ private readonly warnedHooks;
264
302
  constructor(auth: ResolvedDashboardAuth | null, basePath: string);
265
303
  loginPage(req: AuthPageRequest, res: AuthPageResponse, returnToQuery?: string, error?: string): string;
266
304
  login(body: LoginFormBody, req: unknown, res: AuthPageResponse): Promise<string>;
267
305
  logout(req: unknown, res: AuthPageResponse): string;
306
+ session(request: unknown, response: unknown): Promise<void>;
307
+ sessionRequiredPage(): string;
268
308
  /** Uniform failure: same redirect (generic error flag) whether the user is unknown or the password is wrong. */
269
309
  private redirectToLoginError;
270
310
  private currentSession;
271
311
  /**
272
- * Run the host's `login` hook defensively: a throw (sync or async) is treated as a denial
273
- * (`null`) and warn-logged ONCE, so a buggy/unreachable hook never 500s the endpoint into a
274
- * stack-trace leak nor floods the logs.
312
+ * Run a host hook (`login` or `session`) defensively: a throw (sync or async) is treated as a
313
+ * denial (`null`) and warn-logged ONCE PER KIND, so a buggy/unreachable hook never 500s the
314
+ * endpoint into a stack-trace leak nor floods the logs on repeated bad attempts.
275
315
  */
276
- private runLoginHook;
316
+ private runHook;
277
317
  private requireAuth;
278
318
  }
279
319
 
@@ -355,21 +395,36 @@ interface AgentDashboardOptions<TReq = unknown> {
355
395
  */
356
396
  approvalActorRef?: (req: TReq) => string | undefined;
357
397
  /**
358
- * Gate the console (SPA + API) behind a BUILT-IN cookie-session login screen — the simplest way
359
- * to protect `basePath` when the host has no ready-made guard (e.g. header-only auth that a
360
- * browser navigation can't attach). Omit to leave the console open, or fronted only by
361
- * {@link guards}. When set, an unauthenticated page navigation is redirected (302) to
362
- * `<basePath>/auth/login`; an unauthenticated API call gets a `401`. Composes with `guards` —
363
- * BOTH gates must pass. See `DashboardAuthOptions` for the `secret`/`ttl`/`login` shape.
398
+ * Gate the console (SPA + API) behind a built-in, signed session cookie. Two ways to mint it:
399
+ *
400
+ * - **Mode A (`session`, recommended)**: your host app already has its own auth (SSO/OIDC/
401
+ * whatever) — the host frontend, carrying that auth, POSTs to `<basePath>/auth/session`, your
402
+ * `session` hook validates the raw request and returns the session user, and this library
403
+ * mints its cookie from that. No credential this library understands ever exists; you keep
404
+ * your own identity provider as the source of truth. A page-level request with no valid
405
+ * session (and only Mode A configured) gets a small server-rendered instruction page telling
406
+ * the visitor to sign in through your host app, since there is no login page to redirect to.
407
+ * - **Mode B (`login`, standalone fallback)**: no host frontend/IdP to lean on — the console
408
+ * serves its own small, dependency-free, server-rendered login page (`GET
409
+ * <basePath>/auth/login`) and your `login` hook validates submitted username/password. A
410
+ * missing/invalid/expired session redirects a page-level request to that login page with
411
+ * `?returnTo=<original url>`.
412
+ *
413
+ * Either mode can be used alone, or both together (e.g. Mode A for normal use, Mode B as a
414
+ * break-glass fallback) — at least one is required, or `forRoot`/`forRootAsync` throws at boot
415
+ * (an un-mintable gate is a boot error, not a silently-open or silently-stuck console). An
416
+ * unauthenticated API call always gets a plain `401`, regardless of mode — the caller reads the
417
+ * status code, not HTML. Composes with `guards` — BOTH gates must pass. See
418
+ * `DashboardAuthOptions` for the `secret`/`ttl`/`session`/`login` shape.
364
419
  */
365
420
  dashboardAuth?: DashboardAuthOptions;
366
421
  }
367
422
  /**
368
- * Async variant of {@link AgentDashboardOptions}, for a `login` hook that needs injected services
369
- * (e.g. an EntityManager to check credentials against a DB). Everything else stays static/sync —
370
- * `basePath`/`apiBasePath`/`guards` are needed at module-build time (the same constraint
371
- * `@dudousxd/nestjs-telescope`'s and `@dudousxd/nestjs-media`'s own `forRootAsync`s document), so
372
- * only the auth piece itself is resolved through DI.
423
+ * Async variant of {@link AgentDashboardOptions}, for a `session`/`login` hook that needs injected
424
+ * services (e.g. an EntityManager to check credentials against a DB). Everything else stays
425
+ * static/sync — `basePath`/`apiBasePath`/`guards` are needed at module-build time (the same
426
+ * constraint `@dudousxd/nestjs-telescope`'s and `@dudousxd/nestjs-media`'s own `forRootAsync`s
427
+ * document), so only the auth piece itself is resolved through DI.
373
428
  */
374
429
  interface AgentDashboardAsyncOptions<TReq = unknown> {
375
430
  basePath?: string;
@@ -404,13 +459,15 @@ declare class AgentApiModule {
404
459
  }
405
460
  /**
406
461
  * Mounts the AI-gateway governance console: the bundled React SPA at `basePath` and its JSON + SSE
407
- * API at `apiBasePath` (default `<basePath>/api`), plus the built-in login screen's routes at
408
- * `<basePath>/auth/*` when {@link AgentDashboardOptions.dashboardAuth} is set.
462
+ * API at `apiBasePath` (default `<basePath>/api`), plus the built-in `dashboardAuth` routes at
463
+ * `<basePath>/auth/*` when {@link AgentDashboardOptions.dashboardAuth} is set — `POST
464
+ * <basePath>/auth/session` for Mode A (the host mints the session from its own auth) and/or `GET`/
465
+ * `POST <basePath>/auth/login` for Mode B (the built-in login screen).
409
466
  *
410
467
  * Import via `AgentDashboardModule.forRoot(...)` alongside your `@dudousxd/nestjs-agent` module
411
468
  * (global), which must provide `AGENT_GOVERNANCE_QUERIES` (bound by a store adapter). Front the
412
469
  * routes with the first-class `guards` option (plus `imports` for the guards' own dependencies) —
413
- * see {@link AgentDashboardOptions.guards} — and/or the built-in `dashboardAuth` cookie login.
470
+ * see {@link AgentDashboardOptions.guards} — and/or the built-in `dashboardAuth` session cookie.
414
471
  *
415
472
  * Inertia hosts: the console is a full-page app, not an Inertia page. An in-app `<Link>` visit to
416
473
  * `basePath` (an XHR carrying `X-Inertia`) is bounced with the protocol's own external-redirect
@@ -530,4 +587,4 @@ declare const DASHBOARD_APPROVAL_ACTOR_REF: unique symbol;
530
587
  */
531
588
  declare const DASHBOARD_AUTH: unique symbol;
532
589
 
533
- export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, type AgentDashboardAsyncOptions, AgentDashboardAuthController, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_AUTH, DASHBOARD_BASE_PATH, type DashboardAuthOptions, DashboardService, type LiveAgentEvent, type LoginHook, type ReliabilityOverview, type ResolvedDashboardAuth, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadSpendRowWithLabel, type WithActorLabel, agentDashboardMountPaths, parsePriceInput, resolveDashboardAuth };
590
+ export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, type AgentDashboardAsyncOptions, AgentDashboardAuthController, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, type AuthMode, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_AUTH, DASHBOARD_BASE_PATH, type DashboardAuthOptions, DashboardService, type LiveAgentEvent, type LoginHook, type ReliabilityOverview, type ResolvedDashboardAuth, type RevalidateHook, type SessionHook, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadSpendRowWithLabel, type WithActorLabel, agentDashboardMountPaths, parsePriceInput, resolveDashboardAuth };