/** * Attach this machine's copy of a project to Cleo Nexus and report its * presence: steps 3 to 5 of `cleo project link` with a device credential * (cleo-nexus device contract §3.6, §3.7). * * 1. `ensureProjectReplica` binds the canonical project store to a replica * once (no `sync.*` flag is set, so capture, push and pull stay off) and * returns its id. * 2. `POST /v1/projects/:projectId/replicas {deviceId, replicaId}` pins that * replica to this Nexus device. The pin never moves: a 409 `replica-copied` * whose holder is a revoked device of the same user means this machine was * re-enrolled, so the store rebinds (`device-reenrolled`) and the new id is * attached; any other holder is a genuinely copied store and fails with * `E_NEXUS_REPLICA_COPIED`. * 3. `PUT /v1/projects/:projectId/replicas/:replicaId/presence` sends the * path-free presence ({@link toReplicaPresence}) built from a local git * probe. A presence failure is a warning: the attach already stands. * * Nothing here sends a path, a hostname or a secret. * * @task T12905 * @epic T12323 */ import type { NexusReplicaAttachment } from '@cleocode/contracts'; import { type FetchLike } from './http.js'; /** Timeout of each attach or presence call. */ export declare const NEXUS_ATTACH_TIMEOUT_MS = 15000; /** The store binding the attach needs: bind once, and rebind on a re-enrolled device. */ export interface ProjectReplicaBinder { /** Bind the store if it is unbound; return the active replica id. */ ensure(): Promise<{ replicaId: string; reboundFrom?: string; }>; /** Retire the active replica and mint a new id (contract §3.7, R6). */ rebindReenrolled(): Promise<{ replicaId: string; previousReplicaId: string; }>; } /** Options for {@link attachProjectReplica}. */ export interface AttachProjectReplicaOptions { /** Resolved API origin. */ apiUrl: string; /** The device credential's bearer token (never logged). */ bearer: string; /** This machine's Nexus device id. */ deviceId: string; /** The server's project id. */ projectId: string; /** Project root, for the local git probe only (never sent). */ projectRoot: string; /** CLEO version reported in presence. */ cliVersion: string; /** Store binding; defaults to the canonical project store ({@link canonicalReplicaBinder}). */ binder?: ProjectReplicaBinder; /** `fetch` override. */ fetch?: FetchLike; /** Clock, for the presence observation time when git cannot be probed. */ now?: () => Date; /** Per-call timeout; default {@link NEXUS_ATTACH_TIMEOUT_MS}. */ timeoutMs?: number; /** * `cleo project link --rebind`: retire the store's replica and mint a new id * before attaching. The remedy when the old id is held by another device: * this machine's revoked device after a re-enrolment (when the server cannot * say so itself), or the original of a copied store. */ rebind?: boolean; } /** * The binder over the canonical project store: opens it through the * dual-scope chokepoint (never a raw file) and binds in live mode. * * @param projectRoot - Project root whose `.cleo/cleo.db` holds the replica. * @returns A binder for {@link attachProjectReplica}. */ export declare function canonicalReplicaBinder(projectRoot: string): ProjectReplicaBinder; /** * The binder over the global store (`/cleo.db`): binds its * global-scope replica, the one the account's `home:` stream knows this * device's main brain by (T12952). * * @returns A binder for {@link attachHomeReplica}. */ export declare function canonicalGlobalReplicaBinder(): ProjectReplicaBinder; /** * Attach the project store's replica to this Nexus device and report its * presence (contract §3.6 steps 3 to 5). Idempotent: a repeat attaches the * same replica id (200) and re-sends presence. * * @param opts - Origin, credential, ids, project root and test overrides. * @returns The attachment and any warnings (a failed presence report). * @throws {NexusAccountError} `E_NEXUS_REPLICA_COPIED` when another live * device or another user holds this replica id; an API error from the * attach otherwise (mapped by the caller). */ export declare function attachProjectReplica(opts: AttachProjectReplicaOptions): Promise<{ replica: NexusReplicaAttachment; warnings: string[]; }>; /** Options for {@link sendProjectPresence}. */ export interface SendProjectPresenceOptions extends Omit { /** The replica already attached from this device (the link's `replicaId`). */ replicaId: string; } /** * Re-send an attached replica's presence only (contract §3.6 step 5), without * re-attaching: the periodic refresh (T13289). Same path-free body as the * attach ({@link toReplicaPresence} over a local git probe). * * @param opts - Origin, device credential, ids, project root and overrides. * @returns The server's `presenceAt`. * @throws An API or network error; the caller treats it as best-effort. */ export declare function sendProjectPresence(opts: SendProjectPresenceOptions): Promise<{ presenceAt: string; }>; /** Options for {@link attachHomeReplica}. */ export interface AttachHomeReplicaOptions extends Omit { } /** * Attach this device's global store (the main brain) to the account's * `home:` stream and report its presence (T12952; cleo-nexus T084): the * same rules as {@link attachProjectReplica}, on `/v1/account/home/replicas`. * Presence carries no git block (the global store is not a repository). * * @param opts - Origin, credential, ids and test overrides. * @returns The attachment and any warnings. * @throws {NexusAccountError} `E_NEXUS_REPLICA_COPIED`, or an API error. */ export declare function attachHomeReplica(opts: AttachHomeReplicaOptions): Promise<{ replica: NexusReplicaAttachment; warnings: string[]; }>; //# sourceMappingURL=nexus-attach.d.ts.map