import { Alepha, Static } from "alepha";
import { IssuerPrimitive, JwtProvider, UserAccount } from "alepha/security";
import { CryptoProvider } from "alepha/crypto";
import { DateTimeProvider } from "alepha/datetime";
//#region ../../src/api/oauth/entities/oauthClientEntity.d.ts
/**
 * A registered OAuth 2.1 client application.
 *
 * Rows are created by Dynamic Client Registration (RFC 7591) when an MCP
 * client (e.g. Claude) first connects. `source` records who created the
 * client; for DCR it is always `"dcr"` and `createdByUserId` is null until
 * a user completes an authorization.
 */
declare const oauthClientEntity: import("alepha/orm").EntityPrimitive<import("zod").ZodObject<{
  id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>;
  createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
  updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
  clientId: import("zod").ZodString;
  clientName: import("zod").ZodString;
  redirectUris: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>;
  scopes: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>;
  realm: import("zod").ZodString;
  type: import("alepha/orm").PgAttr<import("zod").ZodEnum<{
    confidential: "confidential";
    public: "public";
  }>, typeof import("alepha/orm").PG_DEFAULT>;
  trusted: import("alepha/orm").PgAttr<import("zod").ZodBoolean, typeof import("alepha/orm").PG_DEFAULT>;
  clientSecretHash: import("zod").ZodOptional<import("zod").ZodString>;
  source: import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_DEFAULT>;
  createdByUserId: import("zod").ZodOptional<import("zod").ZodString>;
  lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
  revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>>;
type OAuthClientEntity = Static<typeof oauthClientEntity.schema>;
//#endregion
//#region ../../src/api/oauth/services/OAuthClientService.d.ts
/**
 * The user projection a realm's `loadUser` hands to the OAuth module —
 * a `UserAccount` plus the OIDC profile extras the id_token mints
 * (`email_verified`; `firstName`/`lastName` map to `given_name`/`family_name`).
 */
interface OidcIssuerUser extends UserAccount {
  emailVerified?: boolean;
}
interface RegisterClientOptions {
  realm: string;
  /**
   * Explicit client id (OIDC clients registered by Platform). When omitted,
   * a `mcp_<uuid>` id is generated (Dynamic Client Registration).
   */
  clientId?: string;
  clientName?: string;
  redirectUris: string[];
  scopes?: string[];
  /**
   * `confidential` clients require a `secret` (stored hashed) and authenticate
   * at the token endpoint. Defaults to `public` (PKCE only).
   */
  type?: "public" | "confidential";
  /** First-party client — skip the consent screen (see the entity field). */
  trusted?: boolean;
  /** Raw secret for a confidential client; stored as a scrypt hash. */
  secret?: string;
  source?: "dcr" | "user" | "admin";
  createdByUserId?: string;
}
/**
 * Core OAuth 2.1 service backing the authorization server.
 *
 * Responsibilities:
 * - Client registration (RFC 7591 Dynamic Client Registration) and lookup,
 *   with exact-match redirect_uri validation.
 * - Stateless PKCE authorization codes: minting short-lived signed JWTs that
 *   carry the grant, and verifying/consuming them (replay, expiry, client and
 *   redirect_uri checks, S256 PKCE).
 * - Realm issuer registry: realms register an issuer + user loader so the
 *   token endpoint can mint access tokens without depending on realm wiring.
 */
declare class OAuthClientService {
  protected readonly alepha: Alepha;
  protected readonly dateTime: DateTimeProvider;
  protected readonly log: import("alepha/logger").Logger;
  protected readonly repo: import("alepha/orm").Repository<import("zod").ZodObject<{
    id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>;
    createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
    updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
    clientId: import("zod").ZodString;
    clientName: import("zod").ZodString;
    redirectUris: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>;
    scopes: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>;
    realm: import("zod").ZodString;
    type: import("alepha/orm").PgAttr<import("zod").ZodEnum<{
      confidential: "confidential";
      public: "public";
    }>, typeof import("alepha/orm").PG_DEFAULT>;
    trusted: import("alepha/orm").PgAttr<import("zod").ZodBoolean, typeof import("alepha/orm").PG_DEFAULT>;
    clientSecretHash: import("zod").ZodOptional<import("zod").ZodString>;
    source: import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_DEFAULT>;
    createdByUserId: import("zod").ZodOptional<import("zod").ZodString>;
    lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
    revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
  }, import("zod/v4/core").$strip>>;
  protected readonly jwt: JwtProvider;
  protected readonly crypto: CryptoProvider;
  /**
   * Codes already redeemed in this process. Single-use enforcement only
   * needs to cover the ~60s code lifetime, so a bounded in-memory set is
   * sufficient even on serverless — an expired code fails JWT verification
   * regardless.
   */
  protected readonly usedCodes: Set<string>;
  /**
   * Registry of realm issuers used to mint access tokens. Populated by
   * `$realm` (via `registerIssuer`) so the OAuth module does not depend on the
   * realm wiring directly.
   */
  protected readonly issuers: Map<string, {
    issuer: IssuerPrimitive;
    loadUser: (userId: string) => Promise<OidcIssuerUser>;
  }>;
  /**
   * Register a realm issuer and a user loader. Called by `$realm` so the
   * OAuth token endpoint can mint access tokens for that realm.
   */
  registerIssuer(realm: string, issuer: IssuerPrimitive, loadUser: (userId: string) => Promise<OidcIssuerUser>): void;
  /**
   * Mint an access token for a consumed authorization-code grant, using the
   * issuer registered for `realm`. Throws if the realm has no issuer.
   */
  issueAccessToken(realm: string, grant: {
    userId: string;
    scopes: string[];
    resource?: string;
    clientId?: string;
  }): Promise<{
    access_token: string;
    expires_in?: number;
    refresh_token?: string;
  }>;
  /**
   * Mint an OIDC `id_token` for a consumed grant, signed by the realm's issuer
   * key (asymmetric when configured). Claims: iss, sub, aud (client_id), exp,
   * iat, nonce (when present), plus the standard profile claims the loader
   * provides: email, email_verified, name, given_name, family_name,
   * preferred_username, picture.
   */
  issueIdToken(realm: string, params: {
    userId: string;
    clientId: string;
    issuer: string;
    nonce?: string;
  }): Promise<string>;
  /**
   * Exchange a refresh token for a fresh access token (OAuth 2.1
   * `refresh_token` grant), using the issuer registered for `realm`. Lets an
   * MCP client stay connected for the refresh token's full lifetime without
   * re-running the authorization flow. Throws if the realm has no issuer or
   * the refresh token is invalid/expired.
   */
  refreshAccessToken(realm: string, refreshToken: string): Promise<{
    access_token: string;
    expires_in?: number;
    refresh_token?: string;
    /** Subject of the refreshed session — lets the token endpoint re-mint an
     * OIDC `id_token` for relying parties that forward it as the Bearer. */
    userId: string;
  }>;
  /**
   * Register a new OAuth client. Used by the RFC 7591 DCR endpoint and,
   * later, by user/admin UIs (via the `source` field).
   */
  register(options: RegisterClientOptions): Promise<OAuthClientEntity>;
  /**
   * Idempotently align a registered client's redirect_uri allowlist with the
   * given list. No-op when the client is unknown or the list already matches —
   * safe to call from post-deploy seeders (allowlist changes ship as code, and
   * `register` alone would leave existing rows stale).
   */
  updateRedirectUris(clientId: string, redirectUris: string[]): Promise<void>;
  /**
   * Verify a confidential client's secret against its stored scrypt hash.
   * Returns false for unknown/revoked/public (no-hash) clients.
   */
  verifySecret(clientId: string, secret: string): Promise<boolean>;
  /**
   * Validate a registered redirect_uri. https (or http://localhost) only, and
   * at most a single `*` which must live inside the host (see
   * `redirectUriMatches` for the matching rule).
   */
  protected assertValidRedirectUri(uri: string): void;
  /**
   * Look up a client by its public `clientId`. Returns null if unknown.
   */
  findByClientId(clientId: string): Promise<OAuthClientEntity | null>;
  /**
   * Narrow the scopes a client asks for to those it is actually registered
   * for. The requested scope string is attacker-controlled, so it must never
   * be trusted verbatim — a client registered for `["mcp"]` that asks for
   * `mcp admin` must only be granted `mcp`. When nothing (usable) is
   * requested, the client's full registered set is the default grant.
   * Requested order is preserved and duplicates are dropped.
   */
  intersectScopes(requested: string[] | undefined, allowed: string[]): string[];
  /**
   * Redirect_uri check. A registered pattern is matched byte-exact unless it
   * contains a single `*`, which matches exactly ONE host label (no dots).
   * E.g. `https://*.alepha.club/auth/callback` matches
   * `https://b14.alepha.club/auth/callback` but NOT `https://alepha.club/...`
   * nor `https://a.b.alepha.club/...`.
   */
  isRedirectUriAllowed(client: OAuthClientEntity, redirectUri: string): boolean;
  protected redirectUriMatches(pattern: string, candidate: string): boolean;
  /**
   * Mint a stateless authorization code: a short-lived signed JWT
   * (`typ: "oauth_code"`) carrying the grant. No server-side code storage.
   */
  createAuthorizationCode(realm: string, grant: {
    userId: string;
    clientId: string;
    redirectUri: string;
    codeChallenge: string;
    scopes: string[];
    resource?: string;
    nonce?: string;
  }): Promise<string>;
  /**
   * Verify and atomically consume an authorization code. Throws on expiry,
   * replay, client/redirect mismatch, or PKCE failure.
   */
  consumeAuthorizationCode(realm: string, code: string, check: {
    clientId: string;
    redirectUri: string;
    codeVerifier: string;
  }): Promise<{
    userId: string;
    scopes: string[];
    resource?: string;
    nonce?: string;
  }>;
}
//#endregion
//#region ../../src/api/oauth/controllers/OAuthController.d.ts
/**
 * Configuration for the OAuth authorization server.
 * `realm` is the issuer realm whose JWTs are minted as access tokens;
 * `resource` is the path of the protected MCP endpoint;
 * `loginPath` is the app-level login page unauthenticated users are
 * redirected to from the authorize endpoint.
 */
declare const oauthOptions: import("alepha").Atom<import("zod").ZodObject<{
  realm: import("zod").ZodString;
  resource: import("zod").ZodString;
  loginPath: import("zod").ZodString;
}, import("zod/v4/core").$strip>, "alepha.api.oauth.options">;
/**
 * OAuth 2.1 authorization server endpoints: discovery metadata and
 * RFC 7591 dynamic client registration. Authorize/token routes are added
 * separately.
 */
declare class OAuthController {
  protected readonly log: import("alepha/logger").Logger;
  protected readonly options: Readonly<{
    realm: string;
    resource: string;
    loginPath: string;
  }>;
  protected readonly clients: OAuthClientService;
  protected readonly jwt: JwtProvider;
  /**
   * Absolute origin of the current request, e.g. https://app.com.
   */
  protected baseUrl(url: URL): string;
  metadata: import("alepha/server").RoutePrimitive<import("alepha/server").RequestConfigSchema>;
  protectedResource: import("alepha/server").RoutePrimitive<import("alepha/server").RequestConfigSchema>;
  openidConfiguration: import("alepha/server").RoutePrimitive<import("alepha/server").RequestConfigSchema>;
  jwks: import("alepha/server").RoutePrimitive<import("alepha/server").RequestConfigSchema>;
  register: import("alepha/server").RoutePrimitive<{
    body: import("zod").ZodObject<{
      client_name: import("zod").ZodOptional<import("zod").ZodString>;
      redirect_uris: import("zod").ZodArray<import("zod").ZodString>;
      scope: import("zod").ZodOptional<import("zod").ZodString>;
      grant_types: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
      token_endpoint_auth_method: import("zod").ZodOptional<import("zod").ZodString>;
    }, import("zod/v4/core").$strip>;
  }>;
  /**
   * GET /oauth/authorize — OAuth 2.1 authorization request. If the user
   * has no session, redirect to the realm login page with a return URL.
   * If authenticated, render the consent screen.
   */
  authorize: import("alepha/server").RoutePrimitive<{
    query: import("zod").ZodObject<{
      response_type: import("zod").ZodString;
      client_id: import("zod").ZodString;
      redirect_uri: import("zod").ZodString;
      code_challenge: import("zod").ZodString;
      code_challenge_method: import("zod").ZodString;
      scope: import("zod").ZodOptional<import("zod").ZodString>;
      state: import("zod").ZodOptional<import("zod").ZodString>;
      resource: import("zod").ZodOptional<import("zod").ZodString>;
      prompt: import("zod").ZodOptional<import("zod").ZodString>;
      nonce: import("zod").ZodOptional<import("zod").ZodString>;
    }, import("zod/v4/core").$strip>;
  }>;
  /**
   * POST /oauth/authorize — consent decision. On "allow", mint an
   * authorization code and redirect back to the client's redirect_uri.
   *
   * CSRF: this route carries no CSRF token and relies solely on the session
   * cookie to identify the user. This is a deliberate MVP/MCP tradeoff — a
   * forged consent submit can still only issue an authorization code to an
   * already-registered client, and that code is bound by PKCE, so the
   * attacker cannot redeem it without the matching code_verifier.
   */
  authorizeDecision: import("alepha/server").RoutePrimitive<{
    body: import("zod").ZodObject<{
      decision: import("zod").ZodString;
      response_type: import("zod").ZodString;
      client_id: import("zod").ZodString;
      redirect_uri: import("zod").ZodString;
      code_challenge: import("zod").ZodString;
      code_challenge_method: import("zod").ZodString;
      scope: import("zod").ZodOptional<import("zod").ZodString>;
      state: import("zod").ZodOptional<import("zod").ZodString>;
      resource: import("zod").ZodOptional<import("zod").ZodString>;
      nonce: import("zod").ZodOptional<import("zod").ZodString>;
    }, import("zod/v4/core").$strip>;
  }>;
  /**
   * POST /oauth/token — supports the `authorization_code` grant (verifies
   * PKCE, mints an access token via the realm issuer) and the
   * `refresh_token` grant (exchanges a refresh token for a fresh access
   * token, so a client stays connected without re-running the flow).
   */
  token: import("alepha/server").RoutePrimitive<{
    body: import("zod").ZodObject<{
      grant_type: import("zod").ZodOptional<import("zod").ZodString>;
      code: import("zod").ZodOptional<import("zod").ZodString>;
      client_id: import("zod").ZodOptional<import("zod").ZodString>;
      redirect_uri: import("zod").ZodOptional<import("zod").ZodString>;
      code_verifier: import("zod").ZodOptional<import("zod").ZodString>;
      refresh_token: import("zod").ZodOptional<import("zod").ZodString>;
      client_secret: import("zod").ZodOptional<import("zod").ZodString>;
    }, import("zod/v4/core").$strip>;
  }>;
}
//#endregion
//#region ../../src/api/oauth/helpers/oidcMetadata.d.ts
/**
 * OpenID Connect Discovery 1.0 — provider metadata document
 * (`/.well-known/openid-configuration`). `baseUrl` is the absolute origin of
 * the OIDC provider (e.g. https://alepha.club).
 */
declare const buildOpenIdConfiguration: (baseUrl: string) => {
  issuer: string;
  authorization_endpoint: string;
  token_endpoint: string;
  jwks_uri: string;
  registration_endpoint: string;
  response_types_supported: string[];
  grant_types_supported: string[];
  subject_types_supported: string[];
  id_token_signing_alg_values_supported: string[];
  code_challenge_methods_supported: string[];
  token_endpoint_auth_methods_supported: string[];
  scopes_supported: string[];
};
//#endregion
//#region ../../src/api/oauth/index.d.ts
/**
 * OAuth 2.1 authorization server module for MCP.
 *
 * **Features:**
 * - OAuth 2.1 authorization code flow with PKCE (RFC 7636)
 * - Dynamic Client Registration (RFC 7591)
 * - Authorization server metadata discovery (RFC 8414)
 * - Stateless authorization codes (short-lived signed JWTs)
 * - Single-use code enforcement
 *
 * **Integration:**
 * Register the module and configure the realm + protected resource path:
 *
 * ```ts
 * const app = Alepha.create()
 *   .with(AlephaOAuth)
 *   .set(oauthOptions, { realm: "users", resource: "/mcp" });
 * ```
 *
 * @module alepha.api.oauth
 */
declare const AlephaOAuth: import("alepha").Service<import("alepha").Module>;
//#endregion
export { AlephaOAuth, type OAuthClientEntity, OAuthClientService, OAuthController, type RegisterClientOptions, buildOpenIdConfiguration, oauthClientEntity, oauthOptions };
//# sourceMappingURL=index.d.ts.map