/** * Shared credentials file at ~/.pyre/credentials.json — read/write/delete * with cortex-specific extension. Mirrors engram's auth/credentials.ts so * that one login per machine logs the user into engram, persona, AND * cortex. * * File shape (additive across products): * { * "api_url": "https://pyre.sh", // engram/persona base * "api_key": "sk_pyre_...", * "label": "my-laptop", * "scopes": ["engram", "persona", "cortex"], * "issued_at": "2026-05-14T...", * "cortex": { // cortex-specific section * "active_tenant": "acme", * "tenants": [ * { "slug": "acme", "mcp_url": "https://acme.cortex.pyre.sh", "bearer": "sk_pyre_..." } * ] * } * } * * Cortex code MUST treat non-cortex fields as opaque pass-through. When * we write back, we preserve everything we don't touch — losing engram's * api_key on a cortex login would silently log the user out of memory. * * Env var overrides: * PRZM_CORTEX_MCP_URL — direct MCP endpoint (CI/secrets manager). * PRZM_CORTEX_MCP_TOKEN — bearer token (same). * * When both are present, mode is implicitly cloud and the file isn't * read for cortex. The shared file is still read for engram/persona. * * Path overrides: * PYRE_CREDENTIALS_FILE — explicit absolute path. Same env var engram * uses; staying symmetric so per-test or per-deploy isolation works the * same across products. */ export interface CortexTenant { slug: string; mcp_url: string; bearer: string; } export interface CortexCredentialsSection { /** Slug of the tenant cortex CLI talks to. Undefined when tenants is empty. */ active_tenant?: string; /** All tenants the user belongs to. Empty array = solo Pro user with no cortex access. */ tenants?: CortexTenant[]; /** Mode flag — `cortex use local|cloud` writes this. Default cloud when tenants present. */ mode?: CortexMode; } export interface SharedCredentialsFile { api_url?: string; api_key?: string; label?: string; scopes?: string[]; issued_at?: string; cortex?: CortexCredentialsSection; [key: string]: unknown; } export type CortexMode = "local" | "cloud"; /** Flat view of cortex credentials for runtime consumers (whoami, serve, use). */ export interface ResolvedCortexCredentials { mode: CortexMode; /** Active tenant's MCP endpoint. Cloud mode only. */ mcp_url?: string; /** Active tenant's bearer. Cloud mode only. */ bearer?: string; /** Active tenant slug. */ tenant_slug?: string; /** Login identity (engram/persona's `label` field — typically email). */ user_email?: string; /** pyre-web URL the user logged in against (engram/persona's `api_url`). */ login_server?: string; /** True when env vars supplied the values; the file may exist but isn't authoritative for cortex. */ fromEnv: boolean; /** Count of tenants the user belongs to — surfaced by whoami / login. */ tenant_count: number; } /** * Resolve the credentials file path. Symmetric with engram: * 1. explicit `path` arg * 2. PYRE_CREDENTIALS_FILE env var * 3. ~/.pyre/credentials.json */ export declare function credentialsPath(path?: string): string; /** Where the credentials live — surfaced by whoami for debuggability. */ export declare function getCredentialsPath(): string; /** * Read the shared file. Returns null when missing or unparseable. Never * throws — callers must keep working in local mode if creds are broken. */ export declare function readSharedCredentials(path?: string): SharedCredentialsFile | null; /** * Atomically write the shared file with mode 0600. Creates the parent * directory at 0700 if needed. */ export declare function writeSharedCredentials(creds: SharedCredentialsFile, path?: string): void; /** * Resolve the cortex view: env-var overrides first, then file. Returns a * stable shape (mode=local, fromEnv=false, tenant_count=0) when nothing * is configured so callers can rely on the fields being present. */ export declare function loadCortexCredentials(path?: string): ResolvedCortexCredentials; /** * Update only the cortex section of the shared file. Engram/persona * fields are preserved untouched. Pass `tenants: []` to clear all * tenants without removing the section. */ export declare function saveCortexCredentials(updates: Partial, path?: string): void; /** * Drop the cortex section entirely. Engram/persona credentials in the * same file are preserved — this is `cortex logout`, not "wipe pyre." * * If the file becomes effectively empty (no engram fields and no cortex * section), delete it. Returns true when something was removed. * * Known gotcha: engram's `engram-mcp logout` currently deletes the * whole file, which would also nuke the cortex section. That's a * cross-repo cleanup tracked separately. */ export declare function clearCortexCredentials(path?: string): boolean; /** Existence check used by whoami. Doesn't validate. */ export declare function credentialsExist(path?: string): boolean; /** Stat the file. Exported for tests asserting file mode after write. */ export declare function credentialsStat(path?: string): import("fs").Stats; /** * One-time migration: ~/.config/cortex/credentials.json → ~/.pyre/credentials.json. * * Reads the legacy file (if present), folds it into the shared shape's * cortex section as a single tenant, then deletes the legacy file. No-op * when the legacy file is missing. Errors are warned but never thrown — * a broken legacy file shouldn't block fresh logins. * * Idempotent: once the legacy file is gone, subsequent calls are a single * `existsSync` check. */ export declare function migrateLegacyCredentials(): boolean; /** Test-only — reset the once-guard so tests can re-run migration. */ export declare function _resetMigrationGuardForTests(): void; //# sourceMappingURL=credentials.d.ts.map