import type { BrandCredential } from "../../config/types.js"; /** * OAuth scopes scai's *currently shipped* Brand operations require. * * The AI APIs key can carry any of: * * - `ai.org.brd:r` / `ai.org.brd:w` — Brand Management read/write * - `ai.org.docs:r` / `ai.org.docs:w` — Documents read/write * - `ai.org.br:gen` — Brand Review generate * (NB: the OpenAPI YAML example shows `ai.orgs.br:gen` with a * plural `orgs`; verified empirically 2026-05-14 the real scope * is singular `org`. Docs typo, not a scope-name variant.) * - `ai.org:admin` — org-level admin * * Real-world quirk (verified 2026-05-14): AI APIs keys in Cloud Portal * are issued with **per-key scope subsets**, not the full grant set. * An operator can paste a credential that has `ai.org.brd:r` only, or * one that adds `ai.orgs.br:gen`, etc. If scai *requests* scopes the * client wasn't granted, Auth0 returns a 403 outright (not "filtered * to intersection"). So the OAuth mint requests **no scope** — Auth0 * grants whatever the client has — and scai validates the resulting * token's scope claim against the *minimum scai needs to run the * operations it ships today*. * * Today that minimum is just `ai.org.br:gen` (Brand Review). Brand * Management primitives, when they land, will lift this to include * `ai.org.brd:r` (read) and later `ai.org.brd:w` (write). The login * flow stays permissive — it persists any minted credential and tells * the operator what's missing — but per-operation calls will refuse * if their specific scope isn't present. */ export declare const BRAND_REQUIRED_SCOPES: readonly ["ai.org.br:gen"]; export interface AcquireBrandTokenOptions { orgId: string; /** * The `brand[orgId]` config block, if present. Optional: serverless * callers (showcase orchestrator) may have no config file at all and * supply credentials via the `SITECOREAI_BRAND_*` env vars instead. */ credential?: BrandCredential; } export declare const hasBrandScopes: (token: string) => boolean; /** * Returns a Bearer JWT for the Sitecore Brand APIs. * * Resolution order, cheapest first: * * 1. Cached Brand token in the keychain (keyed by orgId) — set * by a previous mint via this function. Reused while it still * carries the required scopes; cleared on next 401 by callers. * 2. Fresh M2M mint against the `auth.sitecorecloud.io/oauth/token` * endpoint with `audience=https://api.sitecorecloud.io`. The * `clientId` + secret + authority + audience are resolved by * `resolveBrandSecrets`, which walks: (a) the * `SITECOREAI_BRAND_*` env vars (serverless override), then * (b) the `brand[orgId]` config block + OS keychain. Successful * mints are cached. * * Refuses with `AUTH_BRAND_REQUIRED` when neither tier supplies a * credential. The error message points operators at both the OS * keychain login flow AND the serverless env-var path so the right * fix is one re-read away. */ export declare const acquireBrandToken: (options: AcquireBrandTokenOptions) => Promise;