@essentialai/cogent-bridge
Version:
Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.
104 lines • 4.97 kB
TypeScript
/**
* Shape of persisted cloud session credentials.
*
* Per anti-pattern guidance: stores the bearer token (not the secret).
* The secret is only used during create/join -- the token authenticates
* subsequent requests.
*/
export interface PersistedCredentials {
endpoint: string;
/**
* The token that OWNS this cwd's peer, when it differs from `token`.
*
* 🔴 A re-join issues a NEW token, and AUD-003 ownership is proven by the token that CREATED the
* peer (or by its peerSecret). Clients before 3.23.5 destroyed the peerSecret on re-join, so
* their only remaining proof is the previous token — and overwriting `token` threw that away too,
* leaving the agent permanently locked out of its own peerId. Keeping the prior token here lets
* register-peer re-prove ownership INSTANTLY instead of waiting out the relay's 30-minute
* abandoned-peer window.
*/
ownerToken?: string;
sessionId: string;
token: string;
label?: string;
/**
* peerId of the registered peer for this cwd. Local-only; lets the Stop hook
* (check-on-stop, a separate process) identify "me" without re-deriving it,
* so it can filter directed-to-me messages and set the poll's peerId. Optional
* for back-compat: credentials written before 3.12.2 (or by create/join before
* a register) omit it, and the hook falls back to the state file.
*/
peerId?: string;
/**
* AUD-003 peer-ownership credential, issued once by the relay when this peer was first
* registered.
*
* WHY IT MUST BE PERSISTED: a peer is owned by the token that created it, and re-joining a
* channel issues a NEW token. Without this secret an agent that re-joins can never re-register
* its own peerId again — it would be locked out of its own identity by the very check that
* protects it. Stored here (0600, same file as the bearer token, same threat model) and replayed
* on register.
*
* Optional: absent for peers created before ownership existed, and absent on the common path
* where the token has not changed.
*/
peerSecret?: string;
savedAt: string;
}
/**
* Legacy global credential file used by cogent-bridge < 3.1.8.
* A single file shared across every CC session on the host -- which is
* exactly the cross-cwd "credential bleed" bug 3.1.8 fixes. Kept here
* as a constant so startup can detect-and-warn on upgrade.
*/
export declare const LEGACY_GLOBAL_CREDENTIAL_PATH: string;
/**
* Resolve the credential path with the override hierarchy:
* 1. explicit `credentialPath` arg (tests, advanced users)
* 2. process.env.COGENT_CREDENTIALS_FILE (operators with custom paths)
* 3. defaultCredentialPath(process.cwd()) (per-cwd, the new default)
*/
export declare function resolveCredentialPath(credentialPath?: string): string;
export declare function markJoinedInProcess(): void;
export declare function hasJoinedInProcess(): boolean;
/**
* Test-only reset hook. Production code should never call this.
*/
export declare function __resetJoinedInProcessForTests(): void;
export declare function markCloudAttemptInProcess(): void;
export declare function hasCloudAttemptInProcess(): boolean;
/**
* Test-only reset hook. Production code should never call this.
*/
export declare function __resetCloudAttemptInProcessForTests(): void;
/**
* Load persisted credentials from disk.
* Returns null on any error (file not found, JSON parse failure, etc.).
*/
export declare function loadCredentials(credentialPath?: string): Promise<PersistedCredentials | null>;
/**
* Save credentials to disk as pretty-printed JSON.
* Creates the parent directory if it does not exist.
*/
export declare function saveCredentials(creds: PersistedCredentials, credentialPath?: string): Promise<void>;
/**
* Persist a peerSecret the relay just issued for `peerId` in `sessionId`.
*
* 🔴 The relay returns a secret only when it MINTS one (the peer was created, re-created after an
* eviction, or adopted) and never again. Every register path must keep it: the self-heal
* re-registration and the startup presence restore used to discard it, so the next re-join (a new
* token) left the agent holding a dead secret and PEER_NOT_YOURS forever (klaire-frontend,
* 2026-09-30). Credentials for another channel are left alone.
*/
export declare function rememberIssuedPeerSecret(sessionId: string, peerId: string, peerSecret: string): Promise<void>;
/**
* Delete the credential file from disk.
* Silently ignores ENOENT (file already absent).
*/
export declare function clearCredentials(credentialPath?: string): Promise<void>;
/**
* Detect whether the legacy global credential file exists. Used by startup
* to warn the operator about the path migration on first run after upgrade.
*/
export declare function legacyGlobalCredentialsExist(): Promise<boolean>;
//# sourceMappingURL=credential-store.d.ts.map