import { type CallHandler, type ExecutionContext, type NestInterceptor } from '@nestjs/common'; import type { Reflector } from '@nestjs/core'; import { Observable } from 'rxjs'; import type { AuthzContext } from '../context/authz-context'; import { type VerificationKey } from '../nats/internal-token'; import type { ReplayCache } from '../nats/replay-cache'; import type { AbilityRule, SnapshotEnvelope } from '../snapshot/snapshot.envelope'; export type InternalAuthMode = 'off' | 'shadow' | 'enforce'; /** Step 4 — fetch a snapshot envelope by the JWT `snap` claim. */ export interface SnapshotFetcher { getBySnapId(snapId: string): Promise; } export interface InternalAuthOptions { jwks: VerificationKey; replay: ReplayCache; /** This service's audience: 'skillID' | 'skillCertet'. */ serviceName: string; reflector: Reflector; /** Default reads AUTHZ_INTERNAL_AUTH_MODE, falling back to 'off'. */ mode?: InternalAuthMode; /** Compare the token cmd against the NATS subject. Default true. */ strictCmd?: boolean; /** * Step 4 runtime hydration. When both are provided and the token carries a `snap` * claim, the verified context's ability is rehydrated from the Redis snapshot so the * Prisma extension can scope queries. `hydrate` is injected (createPrismaAbility) so * this module stays free of a static @casl/prisma dependency. */ snapshotStore?: SnapshotFetcher; hydrate?: (rules: AbilityRule[]) => AuthzContext['ability']; /** * Cross-service substitution (optional). When the envelope carries raw `grants` and * both `buildRules` (buildRulesFromGrants) and this service's `registry` are provided, * scope templates are re-substituted with the LOCAL registry — so this service scopes * subjects the builder (skillID) doesn't own. Falls back to the envelope's pre-built * `rules` when absent. `buildRules`/`registry` are injected to avoid a static dep. */ buildRules?: (grants: unknown[], registry: unknown, ctx: AuthzContext) => AbilityRule[]; registry?: unknown; } export declare class InternalAuthInterceptor implements NestInterceptor { private readonly opts; private readonly logger; private readonly mode; constructor(opts: InternalAuthOptions); intercept(context: ExecutionContext, next: CallHandler): Observable; /** Returns the ALS context on success; in shadow mode returns null on failure (pass). */ private verify; /** * Step 4 — rehydrate the ability from the Redis snapshot named by the `snap` claim. * Missing/evicted snapshot in enforce → throw (fail-closed: the gateway must rebuild); * in shadow → leave ability null (the request runs unscoped, logged elsewhere). */ private hydrateSnapshot; private stripToken; private tryGetSubject; } //# sourceMappingURL=internal-auth.interceptor.d.ts.map