/** * Agent identity derivations (DEC-114 — agent-identity fix). * * Three orthogonal layers made explicit (perennial identity vs connection): * * - WORKSPACE — a *place*. `deriveWorkspaceId` mints a **deterministic** * `ws:` salted by **machine-id + realpath** (F6): every agent in the * same checkout on the same machine derives the *same* workspace id (so they * are groupable), while a clone/container on another machine derives a * *new* one (a copied checkout is a new workspace — the salt-by-machine * decision). The id is NOT a portable in-tree file, so it never aliases * across clones. * * - AGENT — a perennial Non-Human Identity. Its **UUID** (`mintAgentUuid` = * `node:crypto.randomUUID`) is the stable handle; the **ed25519 keypair is * the sole authority anchor** (the binding/PoP machinery lives in the CLI * store). The addressable handle is `deriveInstanceId` = * `host:slug(label):uuid12`, **frozen at mint** — a later rename changes the * display `name` only, never the handle (F5). * * - SESSION — transient liveness (out of scope here). * * Everything in this module is pure (no I/O), so it unit-tests without a * filesystem and is safe to call from both core and the CLI. The handle is * never parsed back by `:` anywhere — `slugify` guarantees the slug carries no * colon, so the composite always splits into exactly three parts, but nothing * relies on that (F5: forbid `:`-splitting). */ /** * WORKSPACE reference (DEC-114). A *place*, not an actor: a first-class traced * attribute on presence + registration. `id` disambiguates collisions (same * repo name in different checkouts; reused paths); `repo`/`path`/`label` are * descriptive attributes. */ export interface H2AWorkspaceRef { /** `ws:`; deterministic per (machine-id, realpath) — agents groupable. */ readonly id: string; /** * Absolute (realpath) of the workspace root **on this machine** — and * therefore OPTIONAL, because a reference that has left the machine has no * such path. * * It is always present on a locally-minted ref (`deriveWorkspaceId` needs a * real path to salt the id). It is absent on a ref that crossed the mirror * boundary: `runtime/mirror/sanitize.ts` withholds it, since a filesystem path * is the first thing the feed contract's opacity boundary excludes. * * It was REQUIRED until the send boundary landed, and that is precisely why * the mirror leaked: a type that makes a filesystem path mandatory on every * workspace reference cannot express a sanitized reference at all, so the * mandatory field was compelling the disclosure rather than merely permitting * it. Optionality here is what lets the wire carry `{id, host, label}`. * * Readers must treat absence as "not on this machine", never as an error: * `runtime/reporting/context.ts` (the only reader in the package) already * falls back, and `deriveWorkspaceId` mints from a path rather than reading * one back. */ readonly path?: string; /** Host CLI hint that observed this workspace (claude / codex / ...). */ readonly host: string; /** Human label (usually the path leaf / repo name). */ readonly label: string; /** Optional git remote, when resolvable. */ readonly repo?: string; } /** * Map an arbitrary human label into a greppable, collision-proof slug. * * - lowercased; * - the characters `[a-z0-9._-]` are preserved (so `a2a-cli`, `upper_under.dot` * survive verbatim once lowercased); * - every other run of characters collapses to a single `-`; * - leading/trailing `-` are trimmed; * - an empty result falls back to `"workspace"`. * * The slug **never** contains `:` so the composite `instance` handle always has * exactly two structural colons — but, per F5, no caller may parse it back. */ export declare function slugify(label: string): string; /** * The first 12 hex of a UUID (F5 widened uuid8 -> uuid12 to shrink the * birthday-collision surface). Tolerant of an already-dash-stripped value. */ export declare function uuid12(uuid: string): string; /** * Mint a fresh perennial agent UUID. Thin wrapper over `randomUUID` so callers * import one identity surface. */ export declare function mintAgentUuid(): string; export interface DeriveInstanceIdInput { readonly host: string; readonly label: string; /** The perennial agent UUID (full RFC-4122 form). */ readonly uuid: string; } /** * Compose the addressable `instance` handle: `host:slug(label):uuid12`. Frozen * at mint — addressing keeps keying on this opaque string (no lookup change), * it just stops colliding because the `uuid12` suffix is per-agent. */ export declare function deriveInstanceId(input: DeriveInstanceIdInput): string; export interface DeriveWorkspaceIdInput { /** Stable per-machine id (e.g. /etc/machine-id, or a per-host fallback). */ readonly machineId: string; /** The workspace root path; the caller passes a realpath (F6). */ readonly path: string; } /** * Derive a deterministic `ws:` for a place. The id is a UUID-shaped * SHA-256 digest over `machineId \0 path`, so: * - the same checkout on the same machine always yields the same id (every * agent there is groupable), and * - a clone/container (different machine-id) or a different path yields a new * workspace (F6: salt by machine + realpath, never a portable in-tree file). * * The digest is folded into the RFC-4122 layout (version/variant nibbles set) * purely for shape; it is a derived identifier, not a random v4 UUID. */ export declare function deriveWorkspaceId(input: DeriveWorkspaceIdInput): string; /** * Guard for `H2AWorkspaceRef` — validates the identity fields (`id`, `host`, * `label`), plus `path` / `repo` **when present**. * * `path` is checked-when-present rather than required so a SANITIZED ref * (`{id, host, label}`, produced by `runtime/mirror/sanitize.ts`) is a valid * ref. Requiring it made the leak structural: `isH2ASession` validates * `workspace` through this guard, so the hosted `writePresence` would reject * every path-free presence record and the only shape the mirror could push was * one carrying a real filesystem path. * * This narrows what the guard PROVES, not what it protects: `path` is * descriptive, `id` is the identity key (and stays required, along with `host` * and `label`), and no authorization anywhere reads `path`. */ export declare function isH2AWorkspaceRef(value: unknown): value is H2AWorkspaceRef; //# sourceMappingURL=identity.d.ts.map