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,50 @@
# canonical
## Purpose
Implements `canonicalSerialize`, the deterministic byte-level encoding that gates every server signature on a `DriveTemplate` (DTP-03). Two implementations of the function MUST produce byte-identical output for identical input regardless of in-memory key order. JSON is deliberately rejected because object-key ordering is not portable across runtimes.
## Features
- Hand-rolled big-endian binary writer (`ByteWriter`) with `uint8` / `uint16` / `uint32` / `uint64` / `bool` / `string` / `bytes` primitives plus length-prefixed `optional*` helpers.
- Fixed field order across the entire template tree — `schemaVersion`, `driveId`, `issuer`, `issuedAt`, `expiresAt`, `nonce`, `policy`, `cdnFallback`, `rootFolder`.
- Recursive folder/file walker that tags each node with `TAG_FOLDER` (0x01) / `TAG_FILE` (0x02) so the decoder can reconstruct the tree without a separate manifest.
- Encryption-aware: `inline` and `retroactive` `KeyDistribution` variants are tagged 1 / 2 respectively; the `wrappedKey` blob and `keyAuthority` string follow.
- Excludes `serverSignature` — the bytes the issuer signs MUST not include the signature itself.
## Usage: Basic Example
```ts
import { canonicalSerialize } from "@suaveplan/drive-template";
const bytes = canonicalSerialize({
schemaVersion: 1,
driveId: "drive-1",
rootFolder: { name: "/", children: [] },
policy: { defaultPolicy: { autoDownload: false, meshAllowed: true, cdnAllowed: true } },
issuer: "00".repeat(32),
issuedAt: Date.now(),
expiresAt: Date.now() + 60_000,
nonce: new Uint8Array(16).fill(7),
});
```
## Usage: Advanced Example
```ts
import { canonicalSerialize, signTemplate } from "@suaveplan/drive-template";
// canonicalSerialize is the inputs-side; signTemplate runs Ed25519 over it.
const tpl = signTemplate(buildTemplate(), serverSecretKey);
const recanon = canonicalSerialize({ ...tpl, serverSignature: undefined as never });
console.log(`signed bytes: ${recanon.length}`);
```
## API Reference
- `canonicalSerialize(template: Omit<DriveTemplate, "serverSignature">): Uint8Array`.
- Internal-only `ByteWriter` class with explicit primitives — not exported.
## Implementation Notes
The `ByteWriter` accumulates `Uint8Array` parts and concatenates once at `finish()` to avoid quadratic growth. `optionalUint64` / `optionalUint32` / `optionalString` write a discriminator byte first so receivers know whether the field follows; this trades two bytes per optional for unambiguous parsing. The retention policy is encoded as a tag (`0` = unset, `1` = `permanent`, `2` = `lru`, `3` = `{ maxAgeMs }`) so future variants can extend the union without breaking older readers — they will see an unknown tag and reject the template through the schema-version pin.