# @suaveplan/server-keys - Operator-facing CLI bundle for the Suaveplan server-key lifecycle: 18 bins covering root + server keychain generation (including hierarchical ChainedKeySigner chains), encrypted vault persistence via @suaveplan/crypto-vault, key rotation, vault/key viewing, signed file packet preparation/serving/validation via @suaveplan/packer + @suaveplan/storage-file, and license issuance via @suaveplan/license. suaveplan-enterprise additions: SuaveplanError-typed SERVER_KEYS_* codes, OTel command counter + duration histogram, Zod boundary validation, injectable AbortSignal, LoggerLike injection, 100% coverage. Operator-facing CLI bundle for the Suaveplan server-key lifecycle: 18 bins covering root + server keychain generation (including hierarchical `ChainedKeySigner` chains via `@suaveplan/crypto-keys`), encrypted vault persistence via `@suaveplan/crypto-vault`, key rotation, vault / public-key / chain inspection, signed file packet preparation / serving / validation via `@suaveplan/packer`, and license issuance via `@suaveplan/license`. suaveplan-enterprise additions: `SuaveplanError`-typed `SERVER_KEYS_*` codes, OTel command counter + duration histogram, Zod-style input validation, `AbortSignal` threading, injectable `LoggerLike`. ## Documentation tree - [create-root-keys-chain](./src/bin/create-root-keys-chain.md) — Commander entry point for the `create-root-keys-chain` operator command. Parses CLI flags, prompts for any required pas… - [create-root-keys](./src/bin/create-root-keys.md) — Commander entry point for the `create-root-keys` operator command. Parses CLI flags, prompts for any required passwords… - [create-server-keys-chain](./src/bin/create-server-keys-chain.md) — Commander entry point for the `create-server-keys-chain` operator command. Parses CLI flags, prompts for any required p… - [create-server-keys](./src/bin/create-server-keys.md) — Commander entry point for the `create-server-keys` operator command. Parses CLI flags, prompts for any required passwor… - [get-file-stats](./src/bin/get-file-stats.md) — Commander entry point for the `get-file-stats` operator command. Parses CLI flags, prompts for any required passwords v… - [index](./src/bin/index.md) — Commander entry point for the `index` operator command. Parses CLI flags, prompts for any required passwords via `@suav… - [license](./src/bin/license.md) — Commander entry point for the `license` operator command. Parses CLI flags, prompts for any required passwords via `@su… - [prepare-file](./src/bin/prepare-file.md) — Commander entry point for the `prepare-file` operator command. Parses CLI flags, prompts for any required passwords via… - [roll-server-keys-chain](./src/bin/roll-server-keys-chain.md) — Commander entry point for the `roll-server-keys-chain` operator command. Parses CLI flags, prompts for any required pas… - [roll-server-keys](./src/bin/roll-server-keys.md) — Commander entry point for the `roll-server-keys` operator command. Parses CLI flags, prompts for any required passwords… - [serve-file](./src/bin/serve-file.md) — Commander entry point for the `serve-file` operator command. Parses CLI flags, prompts for any required passwords via `… - [validate-file](./src/bin/validate-file.md) — Commander entry point for the `validate-file` operator command. Parses CLI flags, prompts for any required passwords vi… - [validate-packet](./src/bin/validate-packet.md) — Commander entry point for the `validate-packet` operator command. Parses CLI flags, prompts for any required passwords… - [verify-key-chain](./src/bin/verify-key-chain.md) — Commander entry point for the `verify-key-chain` operator command. Parses CLI flags, prompts for any required passwords… - [view-chain-public](./src/bin/view-chain-public.md) — Commander entry point for the `view-chain-public` operator command. Parses CLI flags, prompts for any required password… - [view-keys](./src/bin/view-keys.md) — Commander entry point for the `view-keys` operator command. Parses CLI flags, prompts for any required passwords via `@… - [view-public-key-file](./src/bin/view-public-key-file.md) — Commander entry point for the `view-public-key-file` operator command. Parses CLI flags, prompts for any required passw… - [view-vault](./src/bin/view-vault.md) — Commander entry point for the `view-vault` operator command. Parses CLI flags, prompts for any required passwords via `… - [files](./src/commands/files/files.md) — Local-packer file-transport commands: `prepareFileCommand`, `validateFileCommand`, `getFileStatsCommand`, `validatePack… - [files](./src/commands/files/files.md) — Local-packer file-transport commands: `prepareFileCommand`, `validateFileCommand`, `getFileStatsCommand`, `validatePack… - [packet-io](./src/commands/files/packet-io.md) — Shared on-disk format helpers for the file-transport commands. Holds the canonical packet envelope `{ data, signature,… - [serve-file](./src/commands/files/serve-file.md) — Reconstructs the original file from a directory of prepared packets by verifying each packet's ed25519 signature + sha2… - [keys](./src/commands/keys/keys.md) — Non-chain key-lifecycle commands for `@suaveplan/server-keys`. These functions are the library surface every key/view b… - [keys-chain](./src/commands/keys/keys-chain.md) — Hierarchical `ChainedKeySigner`-backed key-lifecycle commands. Each chain command wraps the matching crypto-vault orche… - [keys-io](./src/commands/keys/keys-io.md) — Private I/O and orchestration-layer helpers shared by every public keys command. Extracted from `keys.ts` to keep each… - [keys](./src/commands/keys/keys.md) — Non-chain key-lifecycle commands for `@suaveplan/server-keys`. These functions are the library surface every key/view b… - [license](./src/commands/license/license.md) — Wraps `@suaveplan/license` `LicenseManager` into the five sub-commands the operator-facing `license` bin exposes: `keyg… - [hex](./src/commands/license/hex.md) — Tiny shared hex encode/decode helpers used by the license sub-commands to serialise and deserialise the secp256k1 key m… - [license](./src/commands/license/license.md) — Wraps `@suaveplan/license` `LicenseManager` into the five sub-commands the operator-facing `license` bin exposes: `keyg… - [error-codes](./src/error-codes/error-codes.md) — Defines the stable `SERVER_KEYS_*` error-code registry used throughout `@suaveplan/server-keys`. Each code is a namespa… - [error-codes](./src/error-codes/error-codes.md) — Defines the stable `SERVER_KEYS_*` error-code registry used throughout `@suaveplan/server-keys`. Each code is a namespa… - [otel](./src/otel/instruments.md) — Registers the OpenTelemetry counter and histogram that every CLI command in `@suaveplan/server-keys` emits exactly once… - [instruments](./src/otel/instruments.md) — Registers the OpenTelemetry counter and histogram that every CLI command in `@suaveplan/server-keys` emits exactly once… - [prompt](./src/prompt/prompt.md) — Thin, test-injectable wrappers around `@inquirer/prompts`' password prompt for the two interactive flows every server-k… - [prompt](./src/prompt/prompt.md) — Thin, test-injectable wrappers around `@inquirer/prompts`' password prompt for the two interactive flows every server-k… - [run-function](./src/run-function/run-function.md) — `runFunction` is the single wrapper every server-keys CLI bin uses for its commander `.action(...)` body. It standardis… - [run-function](./src/run-function/run-function.md) — `runFunction` is the single wrapper every server-keys CLI bin uses for its commander `.action(...)` body. It standardis… ## Install ```bash bun add @suaveplan/server-keys # or, to install all 18 bins globally: bun link ``` ## Commands | Bin | Purpose | | --- | --- | | `suaveplan` | Top-level dispatcher routing to the 17 sub-commands below | | `create-root-keys` | Create root keychain (vault + signed public-key file) | | `create-root-keys-chain` | Create root keychain with self-signed chain | | `create-server-keys` | Derive a server keychain from a root vault | | `create-server-keys-chain` | Derive a chained server keychain | | `roll-server-keys` | Rotate a server keychain to `currentVersion + 1` | | `roll-server-keys-chain` | Rotate a chained server keychain to `currentVersion + 1` | | `verify-key-chain` | Verify a chain file against a trusted root file | | `view-keys` | Decrypt a vault and print a keychain summary | | `view-vault` | Print vault file metadata without decryption | | `view-public-key-file` | Decode and print a signed public-key file | | `view-chain-public` | Decode a public-key file with optional signature verification | | `prepare-file` | Pack a file into signed packets under an output directory | | `serve-file` | Reconstruct a file from prepared packets (byte-identical) | | `validate-file` | Walk every packet in a prepared directory and verify integrity | | `get-file-stats` | Print file packing statistics without packing | | `validate-packet` | Validate a single packet against an explicit verify key | | `license` | Generate / validate / parse / revoke software license keys | ## Programmatic-API quick-start ```ts import { createRootKeysCommand, createServerKeysCommand, } from "@suaveplan/server-keys/commands/keys/keys"; import { prepareFileCommand, } from "@suaveplan/server-keys/commands/files/files"; import { serveFileCommand } from "@suaveplan/server-keys/commands/files/serve-file"; import { keygen, generate, validate, } from "@suaveplan/server-keys/commands/license/license"; import { runFunction } from "@suaveplan/server-keys/run-function"; // Provision keys await createRootKeysCommand("rootpw1234", { output: "./keys" }); await createServerKeysCommand( "./keys/root.vault", "rootpw1234", "serverpw1234", { output: "./keys" }, ); // Prepare + serve a file with cooperative abort const ac = new AbortController(); await prepareFileCommand( "./data.bin", "./keys/server.vault", "serverpw1234", { output: "./prepared", packetSize: 256 * 1024, signal: ac.signal }, ); await serveFileCommand("./prepared", { output: "./reconstructed.bin", signal: ac.signal, }); // License lifecycle const kp = await keygen("./lic/keys.json", 1); const lic = await generate({ signingKeyPath: "./lic/keys.json", productId: 42, tier: 2, expirationDays: 365, }); const checked = await validate(lic.key, { publicKeysPath: "./lic/public-keys.json", }); // Top-level wrapper for custom CLI integrations await runFunction("custom-cmd", async (signal) => { // ...your work; OTel + exit(1)-on-fail handled for you }); ``` ## Modules - [`error-codes`](src/error-codes/error-codes.md) — `SERVER_KEYS_*` registry + `ServerKeysError`. - [`otel/instruments`](src/otel/instruments.md) — counter + histogram + `recordCommand`. - [`run-function`](src/run-function.md) — top-level `.action(...)` wrapper with OTel + structured error + abort plumbing. - [`prompt/prompt`](src/prompt/prompt.md) — `promptForPassword`, `promptForNewPassword` with injectable seam for tests. - [`commands/keys/keys`](src/commands/keys/keys.md) — non-chain keys commands. - [`commands/keys/keys-chain`](src/commands/keys/keys-chain.md) — chain variants + `verifyKeyChainCommand`. - [`commands/keys/keys-io`](src/commands/keys/keys-io.md) — shared I/O - decryption helpers. - [`commands/files/files`](src/commands/files/files.md) — local-packer `prepare` / `validate` / `stats` / `validate-packet`. - [`commands/files/serve-file`](src/commands/files/serve-file.md) — reconstruction. - [`commands/files/packet-io`](src/commands/files/packet-io.md) — packet wire format helpers. - [`commands/license/license`](src/commands/license/license.md) — `keygen` / `generate` / `validate` / `parse` / `revoke`. - [`commands/license/hex`](src/commands/license/hex.md) — hex encode / decode helpers. ## Architectural decisions - **Local packer for file-transport bins.** Upstream's `prepare-file` / `serve-file` / `validate-file` / `get-file-stats` / `validate-packet` are HTTP clients pointed at a separate `file-server`. Ships these as local packers backed by `@suaveplan/packer`'s whole-file `Packer` / `Unpacker` + plain Node `fs`. No network hop, no separate deployment dependency, byte-name stable manifest + packet artefacts. - **suaveplan-native vault wire format.** Vault and signed-public-key files are NOT byte-compatible with the upstream `@suaveplan/keys` BitPacker-based format — the crypto-vault orchestration is the format owner. A future `@suaveplan/keys-migration` package will ship the conversion path. - **Plain Node `fs` instead of `@suaveplan/storage-file` for vault I/O.** storage-file appends `.data` / `.meta` extensions to every key on write, which would force operator scripts to address artefacts by `root.vault.data` instead of the conventional `root.vault`. The CLI contract is byte-name-stable across upstream and suaveplan. - **Vault sign slot = ed25519, license sign slot = secp256k1.** The license format requires secp256k1; the vault's sign slot is ed25519. The license bin therefore uses its own `keygen` sub-command rather than trying to reuse the vault's signing key.