first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
# `commands/files/files`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Local-packer file-transport commands: `prepareFileCommand`,
`validateFileCommand`, `getFileStatsCommand`, `validatePacketCommand`.
These four functions implement the operator-facing surface every file-
transport bin in `@suaveplan/server-keys` calls into. Reconstruction
lives in the sibling `serve-file.ts`. The implementation is fully local —
no HTTP, no remote file server — backed by `@suaveplan/packer`'s
whole-file `Packer` / `Unpacker` and plain Node `fs`.
The choice of a local packer (rather than an HTTP client to a remote
file-server, which the upstream package shipped) was made deliberately:
the upstream HTTP design forces operators to stand up a separate
file-server before they can prepare or serve a file, and the binary
contract is dominated by the packet wire format anyway. Owning the
format here keeps the suaveplan test surface auditable without a network
hop and removes a non-trivial deployment dependency.
## Features
- Fixed-size packetisation (`packetSize`, default 1 MiB) with a JSON
envelope per packet on disk.
- ed25519 signature per packet using the vault's `sign` slot secret;
recipient verifies against the manifest's `signerPublicKey`.
- Manifest is a single JSON document that lists every packet's
`index`, `checksum`, `filename`, and `originalSize`.
- Cooperative abort at every packet boundary via `options.signal`.
- Typed `ServerKeysError` for every failure (`INVALID_INPUT`,
`VAULT_DECRYPT_FAILED`, `PACKET_INTEGRITY_FAILED`, `FILE_NOT_FOUND`,
`ABORTED`).
## Usage: Basic
```ts
import {
prepareFileCommand,
validateFileCommand,
getFileStatsCommand,
} from "@suaveplan/server-keys/commands/files/files";
const stats = await getFileStatsCommand("/tmp/data.bin", {
packetSize: 256 * 1024,
});
console.log(stats.estimatedPackets);
await prepareFileCommand(
"/tmp/data.bin",
"/tmp/keys/server.vault",
"serverpw1234",
{ output: "/tmp/prepared", packetSize: 256 * 1024 },
);
const result = await validateFileCommand("/tmp/prepared");
expect(result.isComplete).toBe(true);
expect(result.invalidPackets).toEqual([]);
```
## Usage: Advanced
Single-packet validation against an explicit hex public key (useful for
spot-checking a remote-supplied packet without trusting the colocated
manifest):
```ts
import { validatePacketCommand } from "@suaveplan/server-keys/commands/files/files";
const r = await validatePacketCommand(
"/tmp/prepared/packet.000000.bin",
"abcd...ed25519-public-key-hex",
);
expect(r.isValid).toBe(true);
```
Detect a tampered packet:
```ts
import { promises as fs } from "node:fs";
const target = "/tmp/prepared/packet.000003.bin";
const original = await fs.readFile(target, "utf-8");
const obj = JSON.parse(original);
const bytes = Buffer.from(obj.data, "hex");
bytes[10] ^= 0xff;
obj.data = bytes.toString("hex");
await fs.writeFile(target, JSON.stringify(obj));
const r = await validateFileCommand("/tmp/prepared");
expect(r.isComplete).toBe(false);
expect(r.invalidPackets).toContain(3);
```
## API Reference
- `prepareFileCommand(filePath, vaultPath, password, options?) =>
Promise<FileManifest>`
- `validateFileCommand(packetDir, options?) =>
Promise<ValidateFileResult>`
- `getFileStatsCommand(filePath, options?) => Promise<FileStatsResult>`
- `validatePacketCommand(packetPath, verifyKeyHex, options?) =>
Promise<ValidatePacketResult>`
All take `FileCommandOptions = { output?, packetSize?, logger?,
signal? }`.
## Implementation Notes
`prepareFileCommand` constructs a new `Packer` per packet so the
underlying event bus stays scoped to a single pack call — the abstract
`Packer` is an `EventEmitter` and we don't want pack events leaking
across packets. Each packet stores its `signature`, `data`, `checksum`,
and `originalSize` in a small JSON envelope (`{ data, signature,
checksum, originalSize }`), all hex-encoded — operators inspecting
packets by hand can paste them into a hex viewer without further
tooling. The intentional `compressionLevel: 0` (no gzip) keeps each
packet's plaintext slice byte-identical to the input region; without
this, signing operates over the gzip stream and reconstruction
requires inverting it, which is an avoidable layer for the local
transport.