@dudousxd/nestjs-agent-dashboard 0.19.0 → 0.20.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.
@@ -1,7 +1,8 @@
1
1
  import { ActorSpendRow, AgentGovernanceQueries, ActorDirectory, AgentPricingStore, AgentApprovalPort, GovernanceRange, ModelSpendRow, UsageTrendPoint, FeatureSpendRow, ThreadSpendRow, RunMetrics, RunAgentBreakdownRow, RunErrorBreakdownRow, RunTrendPoint, RecentRunRow, ToolCallActivityRow, GovernancePageQuery, ToolCallWhere, GovernancePage, RunWhere, PendingApprovalRow, ApprovalWhere, GovernanceRunDetail, GovernanceThreadDetailQuery, GovernanceThreadDetail, ThreadActivityRow, ToolStatRow, GenuiStats, ThreadWhere, CurrentModelPrice, ActorResolver, ModelPriceInput } from '@dudousxd/nestjs-agent-core';
2
2
  export { ActorDirectory } from '@dudousxd/nestjs-agent-core';
3
3
  import { Observable } from 'rxjs';
4
- import { DynamicModule, StreamableFile } from '@nestjs/common';
4
+ import { ExecutionContext, Type, Logger, DynamicModule, StreamableFile, HttpException, ExceptionFilter, ArgumentsHost, CanActivate, OnModuleInit } from '@nestjs/common';
5
+ import { ModuleRef, HttpAdapterHost } from '@nestjs/core';
5
6
 
6
7
  /** An actor-scoped row decorated with its resolved display label — `null` when unbound or unresolved. */
7
8
  interface WithActorLabel {
@@ -151,8 +152,9 @@ declare class DashboardService {
151
152
  * JSON + SSE API consumed by the AI-gateway console SPA. Mounted at `apiBasePath` (set by
152
153
  * `RouterModule` in {@link AgentDashboardModule.forRoot}), so the controller routes are relative.
153
154
  *
154
- * Who reaches it is the app's: `decorators` on `AgentDashboardModule.forRoot`, or the app mounts it
155
- * itself (`routes: false`) — with `@nestjs/authentication` / `@nestjs/authorization`.
155
+ * Who reaches it: `authorize` on `AgentDashboardModule.forRoot` (checked by `ConsoleAuthorizeGuard`,
156
+ * after the app's `decorators`). Mounted by the app itself (`routes: false`), apply
157
+ * `UseConsoleAuthorize()` to your subclass.
156
158
  */
157
159
  declare class AgentApiController {
158
160
  private readonly dashboard;
@@ -293,6 +295,72 @@ interface AgentDashboardMountPathsOptions {
293
295
  */
294
296
  declare function agentDashboardMountPaths(options?: AgentDashboardMountPathsOptions): string[];
295
297
 
298
+ /** What an `authorize` check answers. */
299
+ type ConsoleAuthorizeResult = boolean | {
300
+ allowed: true;
301
+ } | {
302
+ allowed: false;
303
+ reason?: 'unauthenticated' | 'forbidden';
304
+ } | {
305
+ redirectTo: string;
306
+ };
307
+ /** Class form: an @Injectable() provider (constructor injection works). */
308
+ interface ConsoleAuthorizer {
309
+ authorize(context: ExecutionContext): ConsoleAuthorizeResult | Promise<ConsoleAuthorizeResult>;
310
+ }
311
+ type ConsoleAuthorizerClass = Type<ConsoleAuthorizer>;
312
+ /** @nestjs/authorization policy check: policy[ability](user). */
313
+ interface ConsolePolicyCheck {
314
+ policy: Type<unknown>;
315
+ ability: string;
316
+ }
317
+ /** Who reaches the console. */
318
+ type ConsoleAuthorize = ((context: ExecutionContext) => ConsoleAuthorizeResult | Promise<ConsoleAuthorizeResult>) | ConsoleAuthorizerClass | (() => Promise<{
319
+ default: ConsoleAuthorizerClass;
320
+ }>) | ConsolePolicyCheck | string;
321
+ /** A normalized `authorize` answer. */
322
+ type ConsoleDecision = {
323
+ allowed: true;
324
+ } | {
325
+ allowed: false;
326
+ reason: 'unauthenticated' | 'forbidden';
327
+ redirectTo?: string;
328
+ };
329
+ /** What a resolved `authorize` is: called once per request, never throws. */
330
+ type ConsoleDecide = (context: ExecutionContext) => Promise<ConsoleDecision>;
331
+ /**
332
+ * The provider that resolves gate names (`authorize: 'console.agent'`), bound globally by
333
+ * `@dudousxd/nestjs-authz`'s `AuthzModule`. A registry symbol, so it is found without depending on
334
+ * that package.
335
+ */
336
+ declare const CONSOLE_GATE: unique symbol;
337
+ interface ConsoleGate {
338
+ allows(name: string, context: ExecutionContext): Promise<ConsoleAuthorizeResult>;
339
+ }
340
+ /** The one boot warning for a console with no `authorize`. Same wording in every Aviary console. */
341
+ declare const CONSOLE_AUTHORIZE_MISSING_WARNING = "[@dudousxd/nestjs-agent-dashboard] console has no `authorize` configured: it is open outside production and denies every request in production. Set `authorize` in AgentDashboardModule.forRoot().";
342
+ /** Turns any {@link ConsoleAuthorizeResult} into a {@link ConsoleDecision}. */
343
+ declare function normalizeConsoleResult(result: unknown): ConsoleDecision;
344
+ /**
345
+ * Resolves `authorize` into one function the guard calls per request. Configuration mistakes (a
346
+ * gate name without nestjs-authz, a policy without `@nestjs/authorization`) throw here, so call it
347
+ * at boot. The returned function never throws: an error is a `forbidden`.
348
+ *
349
+ * `authorize` omitted: open outside production, `forbidden` for every request in production (read
350
+ * when this runs), and one warning logged (unless `warnIfMissing: false`).
351
+ */
352
+ declare function resolveConsoleAuthorize(authorize: ConsoleAuthorize | undefined, moduleRef: ModuleRef, options?: {
353
+ logger?: Logger;
354
+ warnIfMissing?: boolean;
355
+ }): Promise<ConsoleDecide>;
356
+ /**
357
+ * `authorize` by a bearer token: allows when `Authorization: Bearer <token>` matches (compared in
358
+ * constant time), else `unauthenticated`. Header only. An empty token throws here, at config time.
359
+ */
360
+ declare function authorizeByToken(options: {
361
+ token: string | undefined;
362
+ }): (context: ExecutionContext) => ConsoleAuthorizeResult;
363
+
296
364
  /**
297
365
  * `TReq` mirrors core's `ActorResolver<TReq>` convention: the transport request type
298
366
  * {@link AgentDashboardOptions.approvalActorRef} receives. Defaults to `unknown`.
@@ -310,23 +378,28 @@ interface AgentDashboardOptions<TReq = unknown> {
310
378
  */
311
379
  apiBasePath?: string;
312
380
  /**
313
- * Who reaches the console: class decorators applied to every controller this module mounts — the
314
- * ecosystem's convention, like `@nestjs/mcp`'s `decorators` — with the official tools, e.g.
315
- * `[UseGuards(AuthenticationGuard), Can(ConsolePolicy, 'view')]` from `@nestjs/authentication` /
316
- * `@nestjs/authorization`, or a function as a guard instance, `UseGuards({ canActivate })`.
317
- * Applied to a per-registration subclass, so nothing sticks to the shared classes.
381
+ * Who reaches the console (the SPA and every API/SSE route): an inline function
382
+ * `(ctx) => boolean | { allowed } | { redirectTo }`, an `@Injectable()` `ConsoleAuthorizer` class,
383
+ * a lazy import of one, `{ policy, ability }` (`@nestjs/authorization`), or a gate name
384
+ * (`@dudousxd/nestjs-authz`). `authorizeByToken({ token })` checks a bearer token.
318
385
  *
319
- * In production (`NODE_ENV=production`) the console refuses to boot without them, unless the app
320
- * mounts the routes itself (`routes: false`): a governance console is never served open there by
321
- * default. Outside production the routes are open (and to `@nestjs/authorization`'s
322
- * deny-by-default guard: `CanAnyone()`). Static wiring.
386
+ * Omitted: open outside production; in production every request answers 403 (and a warning is
387
+ * logged at boot).
388
+ */
389
+ authorize?: ConsoleAuthorize;
390
+ /**
391
+ * Class decorators applied to every controller this module mounts, before the console's own
392
+ * `authorize` check — e.g. `[UseGuards(AuthenticationGuard)]` so `request.user` is set when
393
+ * `authorize` runs. Applied to a per-registration subclass, so nothing sticks to the shared
394
+ * classes. They do not replace `authorize`. Static wiring.
323
395
  */
324
396
  decorators?: ClassDecorator[];
325
397
  /**
326
398
  * `false` mounts none of the console's routes, while its services still run — the way NestJS's
327
399
  * own packages leave routes to you: serve them from controllers of your own, protected with the
328
400
  * official tools, by extending the exported `AgentApiController` / `AgentUiController` under your
329
- * own path and decorators (the module exports what they inject). Static wiring.
401
+ * own path and decorators (the module exports what they inject); `UseConsoleAuthorize()` applies
402
+ * this module's `authorize` to them. Static wiring.
330
403
  */
331
404
  routes?: boolean;
332
405
  /** Extra `imports` merged into the console's modules — what a decorator's guard injects. */
@@ -350,12 +423,12 @@ declare class AgentApiModule {
350
423
  decorators?: ClassDecorator[];
351
424
  routes?: boolean;
352
425
  approvalActorRef?: (req: TReq) => string | undefined;
426
+ authorize?: ConsoleAuthorize;
353
427
  }): DynamicModule;
354
428
  }
355
429
  /**
356
430
  * The AI-gateway console: the SPA at `basePath` and its JSON API at `apiBasePath`. Who reaches them
357
- * is the app's — `decorators`, or the app mounts them itself (`routes: false`) — with
358
- * `@nestjs/authentication` / `@nestjs/authorization`.
431
+ * is `authorize` (see {@link AgentDashboardOptions.authorize}).
359
432
  */
360
433
  declare class AgentDashboardModule {
361
434
  static forRoot<TReq = unknown>(options?: AgentDashboardOptions<TReq>): DynamicModule;
@@ -380,8 +453,9 @@ interface UiPageResponse {
380
453
  * `<base>/assets`). The path comes from `RouterModule` (set by
381
454
  * {@link AgentDashboardModule.forRoot}({ basePath })), so the controller routes are relative.
382
455
  *
383
- * Who reaches it is the app's: `decorators` on `AgentDashboardModule.forRoot`, or the app mounts it
384
- * itself (`routes: false`) — with `@nestjs/authentication` / `@nestjs/authorization`.
456
+ * Who reaches it: `authorize` on `AgentDashboardModule.forRoot` (checked by `ConsoleAuthorizeGuard`,
457
+ * after the app's `decorators`). Mounted by the app itself (`routes: false`), apply
458
+ * `UseConsoleAuthorize()` to your subclass.
385
459
  */
386
460
  declare class AgentUiController {
387
461
  private readonly basePath;
@@ -392,6 +466,62 @@ declare class AgentUiController {
392
466
  asset(file: string): StreamableFile;
393
467
  }
394
468
 
469
+ /** What {@link DashboardConsoleAccess} is built from (bound per `forRoot`). */
470
+ interface DashboardConsoleOptions {
471
+ authorize?: ConsoleAuthorize;
472
+ }
473
+ /** Holds the console's resolved `authorize` check for one registration. */
474
+ declare class DashboardConsoleAccess implements OnModuleInit {
475
+ #private;
476
+ private readonly options;
477
+ private readonly moduleRef;
478
+ constructor(options: DashboardConsoleOptions, moduleRef: ModuleRef);
479
+ /** Resolves `authorize` at boot: a configuration mistake fails the boot, and the warning logs once. */
480
+ onModuleInit(): Promise<void>;
481
+ /** The decision for one request. */
482
+ check(context: ExecutionContext): Promise<ConsoleDecision>;
483
+ }
484
+ /** Marks a controller or handler as serving pages: a denied browser navigation gets HTML or a 302. */
485
+ declare const CONSOLE_PAGE_METADATA = "@dudousxd/nestjs-agent-dashboard:console-page";
486
+ /**
487
+ * On a controller or a handler that serves pages: a denied `GET` that accepts HTML gets a page (or a
488
+ * 302 for `redirectTo`), not JSON.
489
+ */
490
+ declare const ConsolePage: () => ClassDecorator & MethodDecorator;
491
+ /** Thrown by {@link ConsoleAuthorizeGuard}; its body is the JSON answer even without the filter. */
492
+ declare class ConsoleAccessDenied extends HttpException {
493
+ readonly decision: Exclude<ConsoleDecision, {
494
+ allowed: true;
495
+ }>;
496
+ readonly page: boolean;
497
+ constructor(decision: Exclude<ConsoleDecision, {
498
+ allowed: true;
499
+ }>, page: boolean);
500
+ }
501
+ /**
502
+ * Runs the console's `authorize` on every route of a controller it guards. Applied by the module
503
+ * after the app's `decorators` (so authentication guards have already set `request.user`); a
504
+ * self-mounted controller (`routes: false`) applies it with {@link UseConsoleAuthorize}.
505
+ */
506
+ declare class ConsoleAuthorizeGuard implements CanActivate {
507
+ private readonly access;
508
+ constructor(access: DashboardConsoleAccess);
509
+ canActivate(context: ExecutionContext): Promise<boolean>;
510
+ }
511
+ /** Writes a console denial: JSON for API calls; a 302 or an HTML page (403 / 401) for page navigations. */
512
+ declare class ConsoleAuthorizeFilter implements ExceptionFilter<ConsoleAccessDenied> {
513
+ private readonly adapterHost;
514
+ constructor(adapterHost: HttpAdapterHost);
515
+ catch(exception: ConsoleAccessDenied, host: ArgumentsHost): void;
516
+ }
517
+ /**
518
+ * The console's access check on a controller of your own (with `routes: false`): the
519
+ * {@link ConsoleAuthorizeGuard} plus the filter that writes its denials. Write it ABOVE your own
520
+ * authentication decorators: class decorators apply bottom-up, so it then runs after them and
521
+ * `request.user` is set.
522
+ */
523
+ declare function UseConsoleAuthorize(): ClassDecorator & MethodDecorator;
524
+
395
525
  /**
396
526
  * Minimal shape guard for a `POST <api>/pricing` body — rejects junk before it reaches
397
527
  * `AgentPricingStore.upsertModelPrice`. Not a full schema validator (the store adapter owns real
@@ -455,5 +585,7 @@ declare const DASHBOARD_API_PATH: unique symbol;
455
585
  * injecting it needs no `@Optional()`.
456
586
  */
457
587
  declare const DASHBOARD_APPROVAL_ACTOR_REF: unique symbol;
588
+ /** DI token carrying the console's `authorize` (and whether to warn when it is omitted). */
589
+ declare const DASHBOARD_CONSOLE_OPTIONS: unique symbol;
458
590
 
459
- export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_BASE_PATH, DashboardService, type LiveAgentEvent, type ReliabilityOverview, type RunDetailWithLabel, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadDetailWithLabel, type ThreadSpendRowWithLabel, type WithActorLabel, agentDashboardMountPaths, parsePriceInput };
591
+ export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, CONSOLE_AUTHORIZE_MISSING_WARNING, CONSOLE_GATE, CONSOLE_PAGE_METADATA, ConsoleAccessDenied, type ConsoleAuthorize, ConsoleAuthorizeFilter, ConsoleAuthorizeGuard, type ConsoleAuthorizeResult, type ConsoleAuthorizer, type ConsoleAuthorizerClass, type ConsoleDecide, type ConsoleDecision, type ConsoleGate, ConsolePage, type ConsolePolicyCheck, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_BASE_PATH, DASHBOARD_CONSOLE_OPTIONS, DashboardConsoleAccess, DashboardService, type LiveAgentEvent, type ReliabilityOverview, type RunDetailWithLabel, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadDetailWithLabel, type ThreadSpendRowWithLabel, UseConsoleAuthorize, type WithActorLabel, agentDashboardMountPaths, authorizeByToken, normalizeConsoleResult, parsePriceInput, resolveConsoleAuthorize };
@@ -1,7 +1,8 @@
1
1
  import { ActorSpendRow, AgentGovernanceQueries, ActorDirectory, AgentPricingStore, AgentApprovalPort, GovernanceRange, ModelSpendRow, UsageTrendPoint, FeatureSpendRow, ThreadSpendRow, RunMetrics, RunAgentBreakdownRow, RunErrorBreakdownRow, RunTrendPoint, RecentRunRow, ToolCallActivityRow, GovernancePageQuery, ToolCallWhere, GovernancePage, RunWhere, PendingApprovalRow, ApprovalWhere, GovernanceRunDetail, GovernanceThreadDetailQuery, GovernanceThreadDetail, ThreadActivityRow, ToolStatRow, GenuiStats, ThreadWhere, CurrentModelPrice, ActorResolver, ModelPriceInput } from '@dudousxd/nestjs-agent-core';
2
2
  export { ActorDirectory } from '@dudousxd/nestjs-agent-core';
3
3
  import { Observable } from 'rxjs';
4
- import { DynamicModule, StreamableFile } from '@nestjs/common';
4
+ import { ExecutionContext, Type, Logger, DynamicModule, StreamableFile, HttpException, ExceptionFilter, ArgumentsHost, CanActivate, OnModuleInit } from '@nestjs/common';
5
+ import { ModuleRef, HttpAdapterHost } from '@nestjs/core';
5
6
 
6
7
  /** An actor-scoped row decorated with its resolved display label — `null` when unbound or unresolved. */
7
8
  interface WithActorLabel {
@@ -151,8 +152,9 @@ declare class DashboardService {
151
152
  * JSON + SSE API consumed by the AI-gateway console SPA. Mounted at `apiBasePath` (set by
152
153
  * `RouterModule` in {@link AgentDashboardModule.forRoot}), so the controller routes are relative.
153
154
  *
154
- * Who reaches it is the app's: `decorators` on `AgentDashboardModule.forRoot`, or the app mounts it
155
- * itself (`routes: false`) — with `@nestjs/authentication` / `@nestjs/authorization`.
155
+ * Who reaches it: `authorize` on `AgentDashboardModule.forRoot` (checked by `ConsoleAuthorizeGuard`,
156
+ * after the app's `decorators`). Mounted by the app itself (`routes: false`), apply
157
+ * `UseConsoleAuthorize()` to your subclass.
156
158
  */
157
159
  declare class AgentApiController {
158
160
  private readonly dashboard;
@@ -293,6 +295,72 @@ interface AgentDashboardMountPathsOptions {
293
295
  */
294
296
  declare function agentDashboardMountPaths(options?: AgentDashboardMountPathsOptions): string[];
295
297
 
298
+ /** What an `authorize` check answers. */
299
+ type ConsoleAuthorizeResult = boolean | {
300
+ allowed: true;
301
+ } | {
302
+ allowed: false;
303
+ reason?: 'unauthenticated' | 'forbidden';
304
+ } | {
305
+ redirectTo: string;
306
+ };
307
+ /** Class form: an @Injectable() provider (constructor injection works). */
308
+ interface ConsoleAuthorizer {
309
+ authorize(context: ExecutionContext): ConsoleAuthorizeResult | Promise<ConsoleAuthorizeResult>;
310
+ }
311
+ type ConsoleAuthorizerClass = Type<ConsoleAuthorizer>;
312
+ /** @nestjs/authorization policy check: policy[ability](user). */
313
+ interface ConsolePolicyCheck {
314
+ policy: Type<unknown>;
315
+ ability: string;
316
+ }
317
+ /** Who reaches the console. */
318
+ type ConsoleAuthorize = ((context: ExecutionContext) => ConsoleAuthorizeResult | Promise<ConsoleAuthorizeResult>) | ConsoleAuthorizerClass | (() => Promise<{
319
+ default: ConsoleAuthorizerClass;
320
+ }>) | ConsolePolicyCheck | string;
321
+ /** A normalized `authorize` answer. */
322
+ type ConsoleDecision = {
323
+ allowed: true;
324
+ } | {
325
+ allowed: false;
326
+ reason: 'unauthenticated' | 'forbidden';
327
+ redirectTo?: string;
328
+ };
329
+ /** What a resolved `authorize` is: called once per request, never throws. */
330
+ type ConsoleDecide = (context: ExecutionContext) => Promise<ConsoleDecision>;
331
+ /**
332
+ * The provider that resolves gate names (`authorize: 'console.agent'`), bound globally by
333
+ * `@dudousxd/nestjs-authz`'s `AuthzModule`. A registry symbol, so it is found without depending on
334
+ * that package.
335
+ */
336
+ declare const CONSOLE_GATE: unique symbol;
337
+ interface ConsoleGate {
338
+ allows(name: string, context: ExecutionContext): Promise<ConsoleAuthorizeResult>;
339
+ }
340
+ /** The one boot warning for a console with no `authorize`. Same wording in every Aviary console. */
341
+ declare const CONSOLE_AUTHORIZE_MISSING_WARNING = "[@dudousxd/nestjs-agent-dashboard] console has no `authorize` configured: it is open outside production and denies every request in production. Set `authorize` in AgentDashboardModule.forRoot().";
342
+ /** Turns any {@link ConsoleAuthorizeResult} into a {@link ConsoleDecision}. */
343
+ declare function normalizeConsoleResult(result: unknown): ConsoleDecision;
344
+ /**
345
+ * Resolves `authorize` into one function the guard calls per request. Configuration mistakes (a
346
+ * gate name without nestjs-authz, a policy without `@nestjs/authorization`) throw here, so call it
347
+ * at boot. The returned function never throws: an error is a `forbidden`.
348
+ *
349
+ * `authorize` omitted: open outside production, `forbidden` for every request in production (read
350
+ * when this runs), and one warning logged (unless `warnIfMissing: false`).
351
+ */
352
+ declare function resolveConsoleAuthorize(authorize: ConsoleAuthorize | undefined, moduleRef: ModuleRef, options?: {
353
+ logger?: Logger;
354
+ warnIfMissing?: boolean;
355
+ }): Promise<ConsoleDecide>;
356
+ /**
357
+ * `authorize` by a bearer token: allows when `Authorization: Bearer <token>` matches (compared in
358
+ * constant time), else `unauthenticated`. Header only. An empty token throws here, at config time.
359
+ */
360
+ declare function authorizeByToken(options: {
361
+ token: string | undefined;
362
+ }): (context: ExecutionContext) => ConsoleAuthorizeResult;
363
+
296
364
  /**
297
365
  * `TReq` mirrors core's `ActorResolver<TReq>` convention: the transport request type
298
366
  * {@link AgentDashboardOptions.approvalActorRef} receives. Defaults to `unknown`.
@@ -310,23 +378,28 @@ interface AgentDashboardOptions<TReq = unknown> {
310
378
  */
311
379
  apiBasePath?: string;
312
380
  /**
313
- * Who reaches the console: class decorators applied to every controller this module mounts — the
314
- * ecosystem's convention, like `@nestjs/mcp`'s `decorators` — with the official tools, e.g.
315
- * `[UseGuards(AuthenticationGuard), Can(ConsolePolicy, 'view')]` from `@nestjs/authentication` /
316
- * `@nestjs/authorization`, or a function as a guard instance, `UseGuards({ canActivate })`.
317
- * Applied to a per-registration subclass, so nothing sticks to the shared classes.
381
+ * Who reaches the console (the SPA and every API/SSE route): an inline function
382
+ * `(ctx) => boolean | { allowed } | { redirectTo }`, an `@Injectable()` `ConsoleAuthorizer` class,
383
+ * a lazy import of one, `{ policy, ability }` (`@nestjs/authorization`), or a gate name
384
+ * (`@dudousxd/nestjs-authz`). `authorizeByToken({ token })` checks a bearer token.
318
385
  *
319
- * In production (`NODE_ENV=production`) the console refuses to boot without them, unless the app
320
- * mounts the routes itself (`routes: false`): a governance console is never served open there by
321
- * default. Outside production the routes are open (and to `@nestjs/authorization`'s
322
- * deny-by-default guard: `CanAnyone()`). Static wiring.
386
+ * Omitted: open outside production; in production every request answers 403 (and a warning is
387
+ * logged at boot).
388
+ */
389
+ authorize?: ConsoleAuthorize;
390
+ /**
391
+ * Class decorators applied to every controller this module mounts, before the console's own
392
+ * `authorize` check — e.g. `[UseGuards(AuthenticationGuard)]` so `request.user` is set when
393
+ * `authorize` runs. Applied to a per-registration subclass, so nothing sticks to the shared
394
+ * classes. They do not replace `authorize`. Static wiring.
323
395
  */
324
396
  decorators?: ClassDecorator[];
325
397
  /**
326
398
  * `false` mounts none of the console's routes, while its services still run — the way NestJS's
327
399
  * own packages leave routes to you: serve them from controllers of your own, protected with the
328
400
  * official tools, by extending the exported `AgentApiController` / `AgentUiController` under your
329
- * own path and decorators (the module exports what they inject). Static wiring.
401
+ * own path and decorators (the module exports what they inject); `UseConsoleAuthorize()` applies
402
+ * this module's `authorize` to them. Static wiring.
330
403
  */
331
404
  routes?: boolean;
332
405
  /** Extra `imports` merged into the console's modules — what a decorator's guard injects. */
@@ -350,12 +423,12 @@ declare class AgentApiModule {
350
423
  decorators?: ClassDecorator[];
351
424
  routes?: boolean;
352
425
  approvalActorRef?: (req: TReq) => string | undefined;
426
+ authorize?: ConsoleAuthorize;
353
427
  }): DynamicModule;
354
428
  }
355
429
  /**
356
430
  * The AI-gateway console: the SPA at `basePath` and its JSON API at `apiBasePath`. Who reaches them
357
- * is the app's — `decorators`, or the app mounts them itself (`routes: false`) — with
358
- * `@nestjs/authentication` / `@nestjs/authorization`.
431
+ * is `authorize` (see {@link AgentDashboardOptions.authorize}).
359
432
  */
360
433
  declare class AgentDashboardModule {
361
434
  static forRoot<TReq = unknown>(options?: AgentDashboardOptions<TReq>): DynamicModule;
@@ -380,8 +453,9 @@ interface UiPageResponse {
380
453
  * `<base>/assets`). The path comes from `RouterModule` (set by
381
454
  * {@link AgentDashboardModule.forRoot}({ basePath })), so the controller routes are relative.
382
455
  *
383
- * Who reaches it is the app's: `decorators` on `AgentDashboardModule.forRoot`, or the app mounts it
384
- * itself (`routes: false`) — with `@nestjs/authentication` / `@nestjs/authorization`.
456
+ * Who reaches it: `authorize` on `AgentDashboardModule.forRoot` (checked by `ConsoleAuthorizeGuard`,
457
+ * after the app's `decorators`). Mounted by the app itself (`routes: false`), apply
458
+ * `UseConsoleAuthorize()` to your subclass.
385
459
  */
386
460
  declare class AgentUiController {
387
461
  private readonly basePath;
@@ -392,6 +466,62 @@ declare class AgentUiController {
392
466
  asset(file: string): StreamableFile;
393
467
  }
394
468
 
469
+ /** What {@link DashboardConsoleAccess} is built from (bound per `forRoot`). */
470
+ interface DashboardConsoleOptions {
471
+ authorize?: ConsoleAuthorize;
472
+ }
473
+ /** Holds the console's resolved `authorize` check for one registration. */
474
+ declare class DashboardConsoleAccess implements OnModuleInit {
475
+ #private;
476
+ private readonly options;
477
+ private readonly moduleRef;
478
+ constructor(options: DashboardConsoleOptions, moduleRef: ModuleRef);
479
+ /** Resolves `authorize` at boot: a configuration mistake fails the boot, and the warning logs once. */
480
+ onModuleInit(): Promise<void>;
481
+ /** The decision for one request. */
482
+ check(context: ExecutionContext): Promise<ConsoleDecision>;
483
+ }
484
+ /** Marks a controller or handler as serving pages: a denied browser navigation gets HTML or a 302. */
485
+ declare const CONSOLE_PAGE_METADATA = "@dudousxd/nestjs-agent-dashboard:console-page";
486
+ /**
487
+ * On a controller or a handler that serves pages: a denied `GET` that accepts HTML gets a page (or a
488
+ * 302 for `redirectTo`), not JSON.
489
+ */
490
+ declare const ConsolePage: () => ClassDecorator & MethodDecorator;
491
+ /** Thrown by {@link ConsoleAuthorizeGuard}; its body is the JSON answer even without the filter. */
492
+ declare class ConsoleAccessDenied extends HttpException {
493
+ readonly decision: Exclude<ConsoleDecision, {
494
+ allowed: true;
495
+ }>;
496
+ readonly page: boolean;
497
+ constructor(decision: Exclude<ConsoleDecision, {
498
+ allowed: true;
499
+ }>, page: boolean);
500
+ }
501
+ /**
502
+ * Runs the console's `authorize` on every route of a controller it guards. Applied by the module
503
+ * after the app's `decorators` (so authentication guards have already set `request.user`); a
504
+ * self-mounted controller (`routes: false`) applies it with {@link UseConsoleAuthorize}.
505
+ */
506
+ declare class ConsoleAuthorizeGuard implements CanActivate {
507
+ private readonly access;
508
+ constructor(access: DashboardConsoleAccess);
509
+ canActivate(context: ExecutionContext): Promise<boolean>;
510
+ }
511
+ /** Writes a console denial: JSON for API calls; a 302 or an HTML page (403 / 401) for page navigations. */
512
+ declare class ConsoleAuthorizeFilter implements ExceptionFilter<ConsoleAccessDenied> {
513
+ private readonly adapterHost;
514
+ constructor(adapterHost: HttpAdapterHost);
515
+ catch(exception: ConsoleAccessDenied, host: ArgumentsHost): void;
516
+ }
517
+ /**
518
+ * The console's access check on a controller of your own (with `routes: false`): the
519
+ * {@link ConsoleAuthorizeGuard} plus the filter that writes its denials. Write it ABOVE your own
520
+ * authentication decorators: class decorators apply bottom-up, so it then runs after them and
521
+ * `request.user` is set.
522
+ */
523
+ declare function UseConsoleAuthorize(): ClassDecorator & MethodDecorator;
524
+
395
525
  /**
396
526
  * Minimal shape guard for a `POST <api>/pricing` body — rejects junk before it reaches
397
527
  * `AgentPricingStore.upsertModelPrice`. Not a full schema validator (the store adapter owns real
@@ -455,5 +585,7 @@ declare const DASHBOARD_API_PATH: unique symbol;
455
585
  * injecting it needs no `@Optional()`.
456
586
  */
457
587
  declare const DASHBOARD_APPROVAL_ACTOR_REF: unique symbol;
588
+ /** DI token carrying the console's `authorize` (and whether to warn when it is omitted). */
589
+ declare const DASHBOARD_CONSOLE_OPTIONS: unique symbol;
458
590
 
459
- export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_BASE_PATH, DashboardService, type LiveAgentEvent, type ReliabilityOverview, type RunDetailWithLabel, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadDetailWithLabel, type ThreadSpendRowWithLabel, type WithActorLabel, agentDashboardMountPaths, parsePriceInput };
591
+ export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, CONSOLE_AUTHORIZE_MISSING_WARNING, CONSOLE_GATE, CONSOLE_PAGE_METADATA, ConsoleAccessDenied, type ConsoleAuthorize, ConsoleAuthorizeFilter, ConsoleAuthorizeGuard, type ConsoleAuthorizeResult, type ConsoleAuthorizer, type ConsoleAuthorizerClass, type ConsoleDecide, type ConsoleDecision, type ConsoleGate, ConsolePage, type ConsolePolicyCheck, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_BASE_PATH, DASHBOARD_CONSOLE_OPTIONS, DashboardConsoleAccess, DashboardService, type LiveAgentEvent, type ReliabilityOverview, type RunDetailWithLabel, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadDetailWithLabel, type ThreadSpendRowWithLabel, UseConsoleAuthorize, type WithActorLabel, agentDashboardMountPaths, authorizeByToken, normalizeConsoleResult, parsePriceInput, resolveConsoleAuthorize };