/** * Who is reporting, and where that is remembered. * * Two identifiers, because they answer two different questions and conflating * them would make the answers wrong: * * - `machineId` — one developer's machine. Lives beside the cloud credentials * in `~/.rebase/`, so it survives across every project they scaffold. * - `projectId` — one *checkout*. Lives in the project's gitignored * `.rebase/`, next to `cloud.json` and `state.json`. * * Without the split, a developer trying five templates in an afternoon reads as * five installations. With it, that is one machine and five projects, which is * the shape the funnel actually needs. * * ## Why `projectId` is not committed * * `rebase.json` is checked in, and a stable identifier sitting in a public * repository is a correlation handle for anyone who finds it — it ties a named * organisation to whatever that id did. `.rebase/` is gitignored, so the id * stays on the machine that generated it. It also makes the unit honest: what * is being counted is a developer working on a project, not the project. * * ## Why both are random * * Neither is derived from a hostname, a database name, an email or a machine * fingerprint. Hashing any of those only *looks* anonymous — the space of real * hostnames is small enough to brute-force a salted hash back to the original * in minutes. A random UUID carries no information at all and does the same job. */ /** Bumped when the stored shape changes in a way old CLIs cannot read. */ export declare const TELEMETRY_CONFIG_VERSION = 1; export type TelemetryConfig = { version: number; /** * `undefined` means never asked — which is *not* the same as declining, and * is the only state in which anything may prompt. */ enabled?: boolean; machineId?: string; /** When the choice was made, so a later release can tell stale consent from fresh. */ decidedAt?: string; }; export declare function configPath(): string; export declare function readConfig(): TelemetryConfig; export declare function writeConfig(config: TelemetryConfig): void; /** * The machine's id, generating and persisting one on first use. * * Only called once consent exists — an id written before the user agreed would * be a record we had no right to create, even unsent. */ export declare function ensureMachineId(): string; /** * The checkout's id, generating one if this project has none. * * The directory is created when it is missing, but **only** where a * `rebase.json` proves this really is a project root. An earlier version * required `.rebase/` to already exist, on the assumption that `rebase init` * created it — it does not. It is written only when a scaffold is linked to * Rebase Cloud, so every self-hosted project reported no `projectId` at all, * for ever. That silently broke the funnel this id exists for, on exactly the * population the telemetry is meant to learn about. * * The `rebase.json` check is what keeps the fix from being "scatter `.rebase/` * wherever a command happens to run": no manifest, no project, no directory, * and the event simply reports no project. */ export declare function ensureProjectId(projectRoot: string): string | undefined;