import { C as AuthProvider, D as RefreshableTokenAuth, E as ReadTokenAuth, O as StaticTokenAuth, S as TokenValidationResult, T as NoAuth, _ as SendMessageRequest, a as BatchScopedTokenPayloadSchema, b as SessionScopedTokenPayloadSchema, c as CreateSessionResponse, d as ProductSchema, f as ProductSecrets, g as ReadTokenPayloadSchema, h as ReadTokenPayload, i as BatchScopedTokenPayload, l as Product, m as ProjectScopedTokenPayloadSchema, n as getTokenTTL, o as CreateSessionRequest, p as ProjectScopedTokenPayload, r as isTokenExpiringSoon, s as CreateSessionRequestSchema, t as decodeToken, u as ProductAuthInfo, v as SendMessageRequestSchema, w as CallbackAuth, x as TokenScope, y as SessionScopedTokenPayload } from "../tokens-browser-DCV3-WHc.js"; //#region src/auth/channel-access.d.ts /** * Result of channel access check. */ interface ChannelAccessResult { /** Whether access is allowed */ allowed: boolean; /** Reason for denial (if not allowed) */ reason?: string; } /** * Extract session ID from a session channel pattern. * Returns null if not a session channel. */ declare function extractSessionFromChannel(channel: string): string | null; /** * Extract project ID from a project channel pattern. * Returns null if not a project channel. */ declare function extractProjectFromChannel(channel: string): string | null; /** * Check if a session-scoped token can access a channel. * * Session tokens can access: * - session:{their-sid} * - agent:{their-sid} * - system (always allowed) * - Wildcard patterns matching their session */ declare function canSessionTokenAccessChannel(payload: SessionScopedTokenPayload, channel: string): ChannelAccessResult; /** * Check if a project-scoped token can access a channel. * * Project tokens can access: * - project:{their-projectId} * - session:* (all sessions within project - requires validation by caller) * - agent:* (all agent events within project) * - system (always allowed) */ declare function canProjectTokenAccessChannel(payload: ProjectScopedTokenPayload, channel: string): ChannelAccessResult; /** * Check if a batch-scoped token can access a channel. * * Batch tokens can access: * - project:{any of their projectIds} * - session:* (all sessions within their projects) * - agent:* (all agent events within their projects) * - system (always allowed) * - * (global wildcard - for organization-wide subscriptions) */ declare function canBatchTokenAccessChannel(payload: BatchScopedTokenPayload, channel: string): ChannelAccessResult; /** * Check if a token can access a channel. * Dispatches to scope-specific functions based on token type. * * @param payload - The token payload * @param channel - The channel to check access for * @returns Access result with allowed boolean and optional reason */ declare function canTokenAccessChannel(payload: ReadTokenPayload, channel: string): ChannelAccessResult; /** * Get the list of allowed channel patterns for a token. * Useful for informing clients what they can subscribe to. * * @param payload - The token payload * @returns Array of allowed channel patterns */ declare function getAllowedChannelPatterns(payload: ReadTokenPayload): string[]; /** * Validate channel subscription request. * Checks multiple channels and returns aggregated result. * * @param payload - The token payload * @param channels - Channels to validate * @returns Object with allowed channels and denied channels with reasons */ declare function validateChannelSubscription(payload: ReadTokenPayload, channels: string[]): { allowed: string[]; denied: Array<{ channel: string; reason: string; }>; }; //#endregion //#region src/auth/tokens.d.ts /** * Generate a cryptographically secure random string. * @param prefix - Prefix for the generated string (e.g., "orch_prod_") * @param bytes - Number of random bytes (default: 32 = 256 bits) */ declare function generateSecureToken(prefix: string, bytes?: number): string; /** * Generate a product API key. */ declare function generateApiKey(): string; /** * Generate a signing secret. */ declare function generateSigningSecret(): string; /** * Issue a read token (JWT) for WebSocket authentication. * * @param signingSecret - The product's signing secret * @param payload - Token payload (without iat/exp, those are added) * @param ttlMinutes - Token TTL in minutes */ declare function issueReadToken(signingSecret: string, payload: Omit, ttlMinutes: number): string; /** * Issue a session-scoped token (JWT) for WebSocket authentication. * Grants access to a single session's events. * * @param signingSecret - The product's signing secret * @param payload - Token payload with session ID * @param ttlMinutes - Token TTL in minutes */ declare function issueSessionScopedToken(signingSecret: string, payload: Omit, ttlMinutes: number): string; /** * Issue a project-scoped token (JWT) for WebSocket authentication. * Grants access to all sessions within a single project. * * @param signingSecret - The product's signing secret * @param payload - Token payload with project ID * @param ttlMinutes - Token TTL in minutes */ declare function issueProjectScopedToken(signingSecret: string, payload: Omit, ttlMinutes: number): string; /** * Issue a batch-scoped token (JWT) for WebSocket authentication. * Grants access to multiple projects (organization-level access). * * @param signingSecret - The product's signing secret * @param payload - Token payload with project IDs array * @param ttlMinutes - Token TTL in minutes */ declare function issueBatchScopedToken(signingSecret: string, payload: Omit, ttlMinutes: number): string; /** * The accepted values of the `cap` claim. The exported union is derived from * this list so the type a caller programs against and the set the verifier * enforces cannot drift apart. */ declare const SIDECAR_CAPABILITIES: readonly ["computer_use", "read", "debug", "terminal", "workspace", "control", "raw_input"]; /** * Capability strings carried in a sidecar token's `cap` claim. This is the * shared vocabulary the crypto layer stamps into the JWT (issueSidecarAccessToken) * and reads back out (verifySidecarToken). The route→capability authorization * policy that enforces these claims lives in the sidecar layer, not here. * Tokens with a `cap` claim are strictly limited to those capabilities; tokens * without a `cap` claim are full-scope (legacy orchestrator-internal use). * * `cap` is the claim that decides authorization, so both halves of the round * trip check it: the issuer throws and the verifier rejects unless the claim is * an array whose every entry is listed above. An empty array is valid and means * "scoped to no capability" — consumers read that as deny-everything, which is * the fail-closed direction. What must never happen is a malformed value * reaching a consumer as an *absent* claim, since absent means full scope. * * Adding a new capability: extend `SIDECAR_CAPABILITIES` above, then update the * enforcement policy (route maps + authorization check) in the sidecar-auth * package. That is a breaking change for verifiers — `verifySidecarToken` * rejects a capability it does not recognise, so every verifier must ship the * new value before any issuer stamps it. Sidecars are baked container images * that outlive an orchestrator roll, so "ship" means deployed, not merged. */ type SidecarCapability = (typeof SIDECAR_CAPABILITIES)[number]; /** * The accepted values of the `sst` claim. The exported union is derived from * this list so the type a caller programs against and the set the verifier * enforces cannot drift apart. */ declare const SIDECAR_SID_SCOPES: readonly ["session", "project"]; /** * What a sidecar token's `sid` claim holds, carried in the `sst` claim. * * `sid` is minted with two different meanings: for a session-runtime token it * is a session id, and for a project-scoped read-only token it is a project * ref. Nothing on the token distinguished them, so a consumer could not tell * whether comparing `sid` against a session id in a request path was an * authorization check or a guaranteed mismatch. * * How a consumer reads the claim on a session-addressed route: * * - `"session"` — `sid` is a session id. Compare it against the session the * request names and deny a mismatch. This is the check the claim exists for. * - `"project"` — `sid` is a project ref, so no session comparison is * possible. The route's own capability policy decides, unchanged: a * project-scoped read-only token legitimately reaches every session in its * project. * - absent — the meaning of `sid` is unknown, so enforce no session * comparison. Tokens minted before this claim existed carry no `sst`. * - a value this build does not recognise — deny. `verifySidecarToken` * rejects those already, so this is a second line for a consumer that * reads the claim from somewhere else. * * Do not collapse that to "anything but `"session"` is not a session token, * so deny it on a session route". `"project"` is a legitimate scope there, * and denying it 403s every read-only and terminal token on every session * route — the behaviour that got the first version of this guard reverted. * * The verifier does not check that `sid` looks like what `sst` declares. That * is a semantic judgement about ids this layer cannot make; it belongs to the * consumer that knows the id namespaces. * * Adding a value here is a breaking change for verifiers: `verifySidecarToken` * rejects an `sst` it does not recognise, so every verifier must ship the new * value before any issuer stamps it. */ type SidecarSidScope = (typeof SIDECAR_SID_SCOPES)[number]; /** * Generate an Ed25519 key pair for per-session JWT signing. * Private key stays in orchestrator memory. Public key is injected into * the sidecar container. Even if the sidecar is fully compromised, * the attacker cannot forge JWTs for any container. * * @returns { privateKey, publicKey } as PEM strings */ declare function generateSidecarKeyPair(): { privateKey: string; publicKey: string; }; /** * Issue a sidecar access token (JWT) using Ed25519 signing. * Scoped to a specific container via the required `cid` claim. * * @param privateKey - Ed25519 private key (PEM). If not provided, falls back to HMAC. * @param hmacFallbackSecret - HMAC secret for backward compat (used when no Ed25519 key) * @param payload - Token payload with container ID * @param ttlMinutes - Token TTL in minutes */ declare function issueSidecarAccessToken(privateKey: string, payload: { sub: string; pid: string; cid: string; sid?: string; /** * What `sid` holds. Stamp it whenever `sid` is set, so a consumer can tell * a session-bound token from a project-bound one instead of guessing from * the capability list. Omitting it leaves consumers unable to enforce a * session comparison. */ sst?: SidecarSidScope; /** * Capability allowlist. When present, the token is restricted to * routes whose required capability is in this list, as enforced by the * sidecar-auth policy layer. Absent = full scope (legacy * orchestrator-internal tokens), so pass a list or omit the key — never a * placeholder like `null`, which reads as full scope one layer down. */ cap?: SidecarCapability[]; }, ttlMinutes: number): string; /** * Verify a sidecar JWT using Ed25519 public key. Rejects non-EdDSA tokens. * Returns decoded payload on success, null on failure. */ declare function verifySidecarToken(token: string, publicKey: string, containerId: string): { sub: string; pid: string; cid: string; sid?: string; /** * What `sid` holds. Absent on tokens minted before the claim existed — * treat that as "unknown", never as a licence to skip a check. */ sst?: SidecarSidScope; typ: string; jti?: string; exp: number; /** * Capability allowlist. Guaranteed to be an array of recognised * capabilities when present — a token carrying anything else is rejected, so * a consumer may call array methods on it without a shape check of its own. * Absent means full scope, so never substitute a placeholder for a missing * claim on the way to a policy check. */ cap?: SidecarCapability[]; } | null; /** * Check if a token payload is session-scoped. * Session-scoped tokens have a sid claim and no projectId/projectIds. */ declare function isSessionScopedToken(payload: ReadTokenPayload): payload is SessionScopedTokenPayload; /** * Check if a token payload is project-scoped. * Project-scoped tokens have a projectId claim and no sid/projectIds. */ declare function isProjectScopedToken(payload: ReadTokenPayload): payload is ProjectScopedTokenPayload; /** * Check if a token payload is batch-scoped. * Batch-scoped tokens have a projectIds claim and no sid/projectId. */ declare function isBatchScopedToken(payload: ReadTokenPayload): payload is BatchScopedTokenPayload; /** * Get the scope of a token payload. * Returns null if the token has an invalid/ambiguous scope. */ declare function getTokenScope(payload: ReadTokenPayload): TokenScope | null; /** * Validate that a token payload has exactly one valid scope. * Returns an error message if invalid, null if valid. */ declare function validateTokenScope(payload: ReadTokenPayload): string | null; /** * Verify a read token against a product's signing secrets. * * @param token - The JWT token to verify * @param product - Product auth info containing secrets */ declare function verifyReadToken(token: string, product: ProductAuthInfo): TokenValidationResult; /** * Hash an API key for storage/lookup. * Uses HMAC-SHA256 for consistent, fast hashing. * * The salt can be configured via API_KEY_HASH_SALT environment variable. * WARNING: Changing the salt will invalidate all existing API key hashes. */ declare function hashApiKey(apiKey: string): string; /** * Hash an API key with an explicit salt. * Use this when you need to verify against a specific salt. */ declare function hashApiKeyWithSalt(apiKey: string, salt: string): string; /** * Verify an API key using timing-safe comparison. */ declare function verifyApiKey(provided: string, stored: string): boolean; //#endregion //#region src/auth/index.d.ts /** * Environment-based auth that reads from env vars. * Matches the server-side patterns used in sidecar/orchestrator. */ declare class EnvTokenAuth { private envVar; private fallback?; constructor(options: { envVar: string; fallback?: string; }); getToken(): Promise; } /** * Pre-configured auth for sidecar connections. * Uses SIDECAR_AUTH_TOKEN env var (matches server expectation). */ declare class SidecarAuth extends EnvTokenAuth { constructor(token?: string); } /** * Product-based auth for multi-tenant orchestrator connections. * Uses ORCHESTRATOR_API_SECRET_KEY env var. */ declare class ProductAuth extends EnvTokenAuth { constructor(apiKey?: string); } /** * Product token issuer for backend services. * * Use this in product backends to issue read tokens for WebSocket connections. * * @example * ```typescript * import { ProductTokenIssuer } from "@tangle-network/agent-core"; * * const issuer = new ProductTokenIssuer({ * productId: "vibecode", * signingSecret: process.env.ORCHESTRATOR_SIGNING_SECRET!, * ttlMinutes: { free: 15, pro: 240 }, * }); * * // Issue a token for a user session * const token = issuer.issue({ * userId: "user_123", * sessionId: "sess_abc", * tier: "pro", * }); * * // Return token to frontend for WebSocket connection * res.json({ * readToken: token.token, * expiresAt: token.expiresAt, * websocketUrl: `wss://orchestrator.example.com/session?token=${token.token}`, * }); * ``` */ declare class ProductTokenIssuer { private readonly productId; private readonly signingSecret; private readonly ttlMinutes; constructor(config: { productId: string; signingSecret: string; /** TTL in minutes for each tier (default: { free: 15, pro: 240 }) */ ttlMinutes?: { free?: number; pro?: number; enterprise?: number; }; }); /** * Issue a read token for a user session. */ issue(params: { userId: string; sessionId: string; tier?: "free" | "pro" | "enterprise"; sidecarId?: string; }): { token: string; expiresAt: number; }; /** * Get the TTL in minutes for a tier. */ getTtlMinutes(tier?: "free" | "pro" | "enterprise"): number; } //#endregion export { type AuthProvider, BatchScopedTokenPayload, BatchScopedTokenPayloadSchema, CallbackAuth, ChannelAccessResult, CreateSessionRequest, CreateSessionRequestSchema, CreateSessionResponse, EnvTokenAuth, NoAuth, Product, ProductAuth, ProductAuthInfo, ProductSchema, ProductSecrets, ProductTokenIssuer, ProjectScopedTokenPayload, ProjectScopedTokenPayloadSchema, ReadTokenAuth, ReadTokenPayload, ReadTokenPayloadSchema, RefreshableTokenAuth, SendMessageRequest, SendMessageRequestSchema, SessionScopedTokenPayload, SessionScopedTokenPayloadSchema, SidecarAuth, SidecarCapability, SidecarSidScope, StaticTokenAuth, TokenScope, TokenValidationResult, canBatchTokenAccessChannel, canProjectTokenAccessChannel, canSessionTokenAccessChannel, canTokenAccessChannel, decodeToken, extractProjectFromChannel, extractSessionFromChannel, generateApiKey, generateSecureToken, generateSidecarKeyPair, generateSigningSecret, getAllowedChannelPatterns, getTokenScope, getTokenTTL, hashApiKey, hashApiKeyWithSalt, isBatchScopedToken, isProjectScopedToken, isSessionScopedToken, isTokenExpiringSoon, issueBatchScopedToken, issueProjectScopedToken, issueReadToken, issueSessionScopedToken, issueSidecarAccessToken, validateChannelSubscription, validateTokenScope, verifyApiKey, verifyReadToken, verifySidecarToken }; //# sourceMappingURL=index.d.ts.map