86 lines
6.7 KiB
Markdown
86 lines
6.7 KiB
Markdown
# Add @suaveplan/server-keys — full-parity port of the 18-bin CLI
|
|
|
|
**Package**: `@suaveplan/server-keys`
|
|
**Status**: PROPOSED
|
|
**Type**: migration (full parity with main) + enterprise stack additions
|
|
|
|
- **Spec delta**: ./specs/server-keys/spec.md
|
|
- **Target path**: `packages/security/server-keys/`
|
|
|
|
## Why
|
|
|
|
Operator-facing CLI bundle for the Suaveplan server-key lifecycle: root + server keychain generation (with hierarchical `ChainedKeySigner` chains via `@suaveplan/crypto-keys`), encrypted vault persistence, key rotation, vault/key viewing, signed file packet preparation/serving/validation, and a license-key issuance bin (uses the just-shipped `@suaveplan/license`). Upstream at `../suaveplan/packages/server/server-keys/` ships 18 bin entry points + 3 command modules + a shared prompt utility (3,122 LOC total). This migration ports all 18 bins verbatim at the CLI-surface level so operator scripts that invoke `create-root-keys`, `roll-server-keys-chain`, `prepare-file`, etc. continue to work byte-compatibly.
|
|
|
|
Genesis enterprise stack layered on top: `SuaveplanError`-typed errors with a `SERVER_KEYS.*` code registry, Zod boundary validation for CLI options, OpenTelemetry spans on the long-running operations (file prep/serve/validate, keychain ops), sibling `.md` docs ≥200 words per implementation file, fast-check property tests where pure-data functions exist (packet manifests, key-chain encode/decode), and 100/100/100/100 coverage. Upstream uses `@suaveplan/keys` (the old umbrella package); genesis-side calls are re-pointed to `@suaveplan/crypto` + `@suaveplan/crypto-keys` (the post-split surface) without changing the wire formats.
|
|
|
|
## What changes
|
|
|
|
Net-new package at `0.1.0`, ships under `packages/security/server-keys/`. ADDED:
|
|
|
|
### 18 bin entry points (verbatim CLI surface)
|
|
|
|
- **Key + chain bins** (`@suaveplan/crypto-keys` chain signer): `create-root-keys`, `create-root-keys-chain`, `create-server-keys`, `create-server-keys-chain`, `roll-server-keys`, `roll-server-keys-chain`, `verify-key-chain`
|
|
- **Viewer bins**: `view-keys`, `view-vault`, `view-public-key-file`, `view-chain-public`
|
|
- **File transport bins** (`@suaveplan/packer` + `@suaveplan/storage`): `prepare-file`, `serve-file`, `validate-file`, `get-file-stats`, `validate-packet`
|
|
- **License bin** (`@suaveplan/license`): `license` — issues / validates / inspects software-license keys
|
|
- **Top-level dispatcher**: `suaveplan` (single `commander` entry routing to all 17 sub-commands)
|
|
|
|
### Internal command modules (the library surface the bins call into)
|
|
|
|
- `commands/keys/keys.ts` — `createRootKeysCommand`, `createServerKeysCommand`, `rollServerKeysCommand`, `createRootKeysChainCommand`, `createServerKeysChainCommand`, `rollServerKeysChainCommand`, `verifyKeyChainCommand`, viewers
|
|
- `commands/files/files.ts` — `prepareFileCommand`, `validateFileCommand`, `getFileStatsCommand`, `validatePacketCommand`
|
|
- `commands/files/serve-file.ts` — `serveFileCommand`
|
|
- `commands/license/license.ts` — `licenseCommand` (wraps `@suaveplan/license` `LicenseManager`)
|
|
- `prompt/prompt.ts` — `promptForPassword`, `promptForNewPassword` (`@inquirer/prompts`)
|
|
- `run-function.ts` — top-level error-handling wrapper for `.action(...)` callbacks
|
|
|
|
### Enterprise stack (additive over upstream)
|
|
|
|
- `error-codes.ts` — `SERVER_KEYS_*` code registry via `defineCodes("SERVER_KEYS", [...])`, `ServerKeysError extends SuaveplanError<ServerKeysErrorCode>`. Codes cover vault decrypt failures, password mismatch, missing root vault, chain verification failure, packet integrity failure, file IO failures, unknown command, plus license-bin pass-throughs.
|
|
- Zod boundary schemas for every CLI option bag.
|
|
- OpenTelemetry: counter `server_keys.command_total{command}`, histogram `server_keys.command_duration_ms{command}`, span per command.
|
|
- `LoggerLike` from `@suaveplan/types` injectable through every command (defaults to console).
|
|
- `AbortSignal` plumbing for long-running file ops.
|
|
|
|
### Bin registration in `package.json`
|
|
|
|
The full 18-bin `bin` map matches upstream verbatim so `bun link` / `npm install -g` exposes every operator command. Names:
|
|
|
|
```text
|
|
suaveplan, license, create-root-keys, create-server-keys, roll-server-keys,
|
|
create-root-keys-chain, create-server-keys-chain, roll-server-keys-chain,
|
|
verify-key-chain, view-keys, view-vault, view-public-key-file,
|
|
view-chain-public, prepare-file, serve-file, validate-file, get-file-stats,
|
|
validate-packet
|
|
```
|
|
|
|
### Subpath exports
|
|
|
|
Library subpaths so downstream packages can call the command functions directly (e.g. test harnesses, integration tests): `./commands/keys/keys`, `./commands/files/files`, `./commands/files/serve-file`, `./commands/license/license`, `./prompt/prompt`, `./error-codes`, `./run-function`.
|
|
|
|
## Out of scope
|
|
|
|
- **Daemon / always-on serve-file mode.** Upstream's `serve-file` is one-shot reconstruction; genesis preserves that. A long-running HTTP serve mode belongs in a separate `@suaveplan/server-keys-http` follow-up.
|
|
- **Re-implementing the upstream wire formats.** The keychain encoding, packet header, and license payload formats all come from their respective packages (`@suaveplan/crypto-keys`, `@suaveplan/packer`, `@suaveplan/license`). server-keys is the CLI wrapper, not the format owner.
|
|
- **Cross-platform binary distribution.** Bins run under Bun/Node; we do not ship pkg/nexe-style standalone binaries.
|
|
- **Telemetry exporter wiring.** OTel instruments are registered against `@opentelemetry/api`; concrete exporter (OTLP/Prometheus/Jaeger) is the operator's choice.
|
|
|
|
## Source mapping
|
|
|
|
| Capability | Upstream source | Notes |
|
|
|---|---|---|
|
|
| 18 bin entry points + commander routing | `../suaveplan/packages/server/server-keys/src/bin/*.ts` + `bin/index.ts` | verbatim CLI surface |
|
|
| Key + chain commands (628 LOC) | `src/commands/keys/keys.ts` | re-pointed from `@suaveplan/keys` → `@suaveplan/crypto-keys` `ChainedKeySigner` |
|
|
| File transport commands (311 LOC) | `src/commands/files/files.ts` + `serve-file.ts` | uses `@suaveplan/packer` + `@suaveplan/storage`/`storage-file` |
|
|
| Password prompts | `src/prompt/prompt.ts` | `@inquirer/prompts` |
|
|
| License bin | `src/bin/license.ts` + `src/commands/license/license.types.ts` | wraps `@suaveplan/license` `LicenseManager` |
|
|
| `runFunction` error wrapper | `src/runFunction.ts` | verbatim |
|
|
| Enterprise audit (Zod, OTel, structured errors, 100% coverage, sibling .md) | `../suaveplan/enterprise/server-keys.md` | all addressed |
|
|
| `ServerKeysError` + `SERVER_KEYS_*` code registry | genesis-original | genesis policy — upstream throws plain `Error` |
|
|
|
|
## Impact
|
|
|
|
### Affected dependents
|
|
|
|
None today — net-new on genesis. First downstream will be operator scripts (out-of-repo) and CI workflows that issue/rotate server keys. The `license` bin transitively pulls in `@suaveplan/license` (shipped today).
|