# Tasks: drive-template-v1 **Change ID**: drive-template-v1 **Capability**: `drive-template` (new) + surface additions to `drive` **New package**: `@suaveplan/drive-template` (types + codecs + validators; zero runtime side effects beyond signature verification) **Target paths**: `packages/drive/drive-template/`, plus surface additions in `packages/drive/drive/` and `packages/drive/drive-plugin-chunks/` **Prerequisite packages on Verdaccio**: `@suaveplan/types`, `@suaveplan/error`, `@suaveplan/bitpacker`, `@suaveplan/bitpacker-schema`, `@suaveplan/bitpacker-network`, `@suaveplan/crypto`, `@suaveplan/crypto-vault`, `@suaveplan/drive-mesh-protocol` (after `drive-mesh-protocol-v1` lands) > Every checkbox MUST reflect work actually done in this change. Do not retroactively tick boxes for work that was already in main when this change opened. > **Scope note (this commit):** The `@suaveplan/drive-template` package surface (Sections 0–2, 5, 7.1–7.2, 8.1–8.3, 8.8, 9.2–9.4, 9.6–9.7, 12.1, 12.4–12.5) is implemented and shipped. The `@suaveplan/drive` surface additions (Section 3), the `@suaveplan/drive-plugin-chunks` inline-sig modification (Section 4), the drive-side integration tests (Section 6), and the cross-package archive folds (Sections 7.3–7.4, 8.4–8.7, 9.1, 9.5, 10, 11.2–11.4, 12.2–12.3) require touching sibling packages and are deferred to follow-up changes (`drive-template-drive-surface`, `drive-plugin-chunks-inline-sig`). --- ## 0. Prerequisite - [x] 0.1 `drive-mesh-protocol-v1` is archived (this proposal references its `cd:request`/`cd:response` envelopes for hydration) - [x] 0.2 `enterprise-types-cross-cutting` is archived (provides `ChunkRef`, `HealthStatus`, `MiddlewareHandler` used by hydration) - [x] 0.3 `drive-port` is archived (provides the thin VFS core that `hydrateFrom` extends) ## 1. Spec authoring - [x] 1.1 Read `openspec/AGENTS.md` Sections 0, 11, 13, 14 - [x] 1.2 Draft `proposal.md` - [x] 1.3 Draft `specs/drive-template/spec.md` with 26 ADDED requirements - [x] 1.4 Every requirement carries a `**Verified by:**` line - [x] 1.5 Source mapping section completed (genesis-original; antecedents listed) - [x] 1.6 Parity Checklist completed (genesis-original — no upstream) - [x] 1.7 Impact section enumerates 8 affected dependents - [x] 1.8 Migration section names new error codes, behavior changes, and search commands ## 2. Implementation — `@suaveplan/drive-template` package - [x] 2.1 Create package skeleton at `packages/drive/drive-template/` - [x] 2.2 `package.json` — workspace, type:module, sideEffects:false, catalog deps - [x] 2.3 `src/types/template.ts` — `DriveTemplate`, `FolderTemplate`, `FileTemplate`, `GlobalPolicy`, `PerFilePolicy` (filed at `src/types/template.types.ts` rather than `template.ts` to match the genesis-wide `.types.ts` convention) - [x] 2.4 `FileEncryption`, `KeyDistribution`, `KeyGrantPayload` (collapsed into `template.types.ts` rather than a separate `encryption.ts` file — they share the same wire-type vocabulary) - [x] 2.5 `CdnFallbackConfig`, `CdnUploadToken` (same — collapsed into `template.types.ts`) - [x] 2.6 `RetentionPolicy` union (same — collapsed into `template.types.ts`) - [x] 2.7 `src/codec/canonical.ts` — `canonicalSerialize(template)` via a hand-rolled big-endian byte writer (genesis-pinned: `bitpacker-schema` does NOT yet ship a sufficient surface for this byte stream so the codec is hand-rolled with the same determinism guarantees) - [x] 2.8 `src/codec/sign.ts` / `src/codec/verify.ts` — Ed25519 wrapping `canonicalSerialize` output - [x] 2.9 `src/validate/order.ts` — 8-step validation pipeline (per `DTP-05`) - [x] 2.10 `src/validate/replay.ts` — nonce LRU cache (1024 entries) - [x] 2.11 `src/validate/depth.ts` — folder depth limit (32) - [x] 2.12 `src/validate/file.ts` — per-file consistency checks - [x] 2.13 `src/cdn/url-builder.ts` — reversed-ID URL builder (parameterized levels + padding) - [x] 2.14 `src/cdn/upload-token.ts` — `CdnUploadToken` issue + verify - [x] 2.15 `src/key/grant-validator.ts` — `KeyGrantEnvelope` Ed25519 verification against template's `keyAuthority` - [ ] 2.16 ~~`src/key/wrap-unwrap.ts` — X25519 sealed-box wrap/unwrap helpers around `@suaveplan/crypto`~~ — N/A in this commit. The retroactive grant validator (DTP-21) verifies the issuer signature; the actual sealed-box unwrap is the consumer's responsibility once the key material is delivered. Adding the wrap/unwrap helpers here would force the package to depend on `@suaveplan/crypto-vault` for `OpaqueKeyHandle`, which is undesirable for a types-and-validators-only package. - [x] 2.17 `src/error-codes.ts` — `defineCodes("DTP", [...])` registry (10 codes; `INLINE_SIG_INVALID` deferred to drive-plugin-chunks per the modification scope) - [x] 2.18 `src/index.ts` — barrel - [x] 2.19 Subpath exports: `./types`, `./codec`, `./validate`, `./cdn`, `./key`, `./schemas`, `./errors` - [x] 2.20 Sibling `.md` for every implementation `.ts` - [x] 2.21 Root `README.md` with Quick start + Modules ## 3. Implementation — `@suaveplan/drive` surface additions (DEFERRED) - [ ] 3.1 `src/drive/hydrate-from.ts` — `Drive.hydrateFrom(template, options)` orchestrator - [ ] 3.2 `src/drive/get-key-status.ts` — `Drive.getKeyStatus(path)` returning the three-state union - [ ] 3.3 `src/drive/get-presence.ts` — `Drive.getPresence(path)` returning `ChunkPresence` - [ ] 3.4 Update `src/file-operations/list.ts` — DirEntries carry optional `keyStatus` and `presence` - [ ] 3.5 Update `src/types/drive.types.ts` — extend `DirEntry`, add `HydrateOptions`, `HydrateResult`, `HydrateProgressEvent` - [ ] 3.6 Add `bus:key:grant` listener registration during `hydrateFrom` for `kind: 'retroactive'` files - [ ] 3.7 Cache-eviction loop honoring `RetentionPolicy` per file (chunk-granularity LRU) - [ ] 3.8 Sibling `.md` updates for every modified `.ts` ## 4. Implementation — `@suaveplan/drive-plugin-chunks` inline-sig (DEFERRED) - [ ] 4.1 Update `FileLocation.storageHints` `kind: 'inline'` schema to require `sig: Uint8Array` - [ ] 4.2 Inline-write path computes `Ed25519-sign(driveSecretKey, fileId ‖ bytes)` - [ ] 4.3 Inline-read path verifies sig before returning bytes - [ ] 4.4 Backward-compat shim: old inline entries (no sig) read with warning, rewritten on next write - [ ] 4.5 Update sibling `.md` ## 5. Tests — `@suaveplan/drive-template` package - [x] 5.1 `tests/template-roundtrip.test.ts` - [x] 5.2 `tests/template-replay.test.ts` - [x] 5.3 `tests/template-expired.test.ts` - [x] 5.4 `tests/template-stale.test.ts` - [x] 5.5 `tests/template-tampered.test.ts` (fast-check) - [x] 5.6 `tests/template-untrusted-issuer.test.ts` - [x] 5.7 `tests/template-too-deep.test.ts` - [x] 5.8 `tests/template-malformed.test.ts` - [x] 5.9 `tests/cdn-reverse-id-url.test.ts` - [ ] 5.10 ~~`tests/cdn-bad-sig.test.ts`~~ — N/A in this commit. The CDN bad-sig fall-back-to-mesh contract (DTP-18) is exercised by the `Drive.read()` fall-back path that lives in `@suaveplan/drive`; the standalone template package has no read path to test. - [x] 5.11 `tests/cdn-upload-token.test.ts` - [x] 5.12 `tests/key-grant-validator.test.ts` - [x] 5.13 `tests/spec-conformance.test.ts` — covered by per-DTP spec-tied test files - [x] 5.14 `tests/error-codes.spec-conformance.test.ts` ## 6. Tests — `@suaveplan/drive` integration (DEFERRED) - [ ] 6.1 `tests/hydrate-from.test.ts` — successful hydration - [ ] 6.2 `tests/policy-meshallowed-false.test.ts` — bus interceptor verifies no `cd:request` - [ ] 6.3 `tests/policy-cdnallowed-false.test.ts` — drive-transport-https not invoked - [ ] 6.4 `tests/policy-autodownload.test.ts` — eager fetch scheduling - [ ] 6.5 `tests/retention-lru.test.ts` - [ ] 6.6 `tests/retention-max-age.test.ts` - [ ] 6.7 `tests/inline-key-unlock.test.ts` - [ ] 6.8 `tests/retroactive-key-grant.test.ts` - [ ] 6.9 `tests/key-grant-untrusted-issuer.test.ts` - [ ] 6.10 `tests/key-grant-replay.test.ts` - [ ] 6.11 `tests/get-key-status.test.ts` - [ ] 6.12 `tests/get-presence.test.ts` - [ ] 6.13 `tests/list-with-presence.test.ts` - [ ] 6.14 `tests/inline-file-sig.test.ts` ## 7. Documentation - [x] 7.1 Sibling `.md` for every implementation `.ts` (excludes barrels, `.types.ts`, tests) - [x] 7.2 `@suaveplan/drive-template` root `README.md` - [ ] 7.3 ~~Update `@suaveplan/drive` `README.md` Modules section with new files~~ — DEFERRED (drive surface) - [ ] 7.4 ~~Update `@suaveplan/drive-plugin-chunks` `README.md` for inline-sig change~~ — DEFERRED - [x] 7.5 Cross-link `docs/drive/dehydrated-drives.md` from the new package READMEs ## 8. Pre-archive verification (the 5-gate triple) - [x] 8.1 `bun run check` — Biome 0/0/0 across the package - [x] 8.2 `bunx turbo lint typecheck test --filter=@suaveplan/drive-template` — green (90 tests across 14 files) - [x] 8.3 `bunx turbo test:coverage --filter=@suaveplan/drive-template` — 100/100/100/100 - [ ] 8.4 ~~`bunx turbo lint typecheck test --filter=@suaveplan/drive` (drive surface additions)~~ — DEFERRED - [ ] 8.5 ~~`bunx turbo test:coverage --filter=@suaveplan/drive` — 100/100/100/100~~ — DEFERRED - [ ] 8.6 ~~`bunx turbo lint typecheck test --filter=@suaveplan/drive-plugin-chunks` (inline-sig)~~ — DEFERRED - [ ] 8.7 ~~`bunx turbo test:coverage --filter=@suaveplan/drive-plugin-chunks` — 100/100/100/100~~ — DEFERRED - [x] 8.8 `bun scripts/openspec-conformance.ts @suaveplan/drive-template` — exit 0 (8 advisory schemas-at-boundaries warnings on the consumer-facing schemas; 0 errors) - [x] 8.9 `bunx turbo build --filter=@suaveplan/drive-template` — green ## 9. Pre-archive 7-row checklist (AGENTS.md §13) - [ ] 9.1 ~~Generics threaded; `expectTypeOf` assertions on `Drive` extensions~~ — N/A in this commit (drive surface additions deferred) - [x] 9.2 Zod schemas for every public option type (`DriveTemplateSchema`, `CdnFallbackConfigSchema`, `CdnUploadTokenSchema`, `FileTemplateSchema`, `FolderTemplateSchema`, `KeyGrantPayloadSchema`, `GlobalPolicySchema`, `FileEncryptionSchema`) - [x] 9.3 Frozen `DTP_CODES` registry; every thrown error extends `SuaveplanError` - [x] 9.4 Strict-mode behaviors tested (every rejection path has an explicit test) - [ ] 9.5 ~~OTel instruments: `drive.hydrate.duration_ms`, `drive.cache.evicted_bytes`, `drive.key.granted` (counter), `drive.template.verified` (counter)~~ — N/A in this commit; instruments live on the `@suaveplan/drive` surface and ship with Section 3. - [x] 9.6 Lifecycle dedup: nonce LRU bounded; key grant duplicate detection covered by issuer/recipient/sig/expiry order - [x] 9.7 No retroactive tick — every box reflects work done in this change ## 10. Dependent sweep (AGENTS §13 step 10) (DEFERRED) - [ ] 10.1 `bunx turbo test --filter=...@suaveplan/drive-template` — all dependents green - [ ] 10.2 `bunx turbo test --filter=...@suaveplan/drive` — all dependents green (foundation-tier ripple) - [ ] 10.3 `bunx turbo test --filter=...@suaveplan/drive-plugin-chunks` — inline-sig consumers verified ## 11. Behavior-change propagation (AGENTS §13a) - [x] 11.1 No spec wording shifted during implementation; `docs/drive/dehydrated-drives.md` already aligned - [ ] 11.2 ~~Search dependents for old inline-without-sig patterns~~ — DEFERRED with Section 4 - [ ] 11.3 ~~Search consumers using `Drive.list()` for places that should now read `keyStatus` / `presence`~~ — DEFERRED with Section 3 - [x] 11.4 Migration note in `proposal.md` lists all five behavior changes with search commands ## 12. Archive - [x] 12.1 Fold spec delta into `openspec/specs/drive-template/spec.md` (new top-level capability spec) - [ ] 12.2 ~~Fold drive surface additions into `openspec/specs/drive/spec.md` (DRIVE-10..12 new requirements)~~ — DEFERRED with Section 3 - [ ] 12.3 ~~Fold inline-sig requirement into `openspec/specs/drive-plugin-chunks/spec.md`~~ — DEFERRED with Section 4 - [x] 12.4 Move `openspec/changes/drive-template-v1/` → `openspec/archive/2026-05-04-drive-template-v1/` - [x] 12.5 Refresh `MANIFEST.md` (this package's row only; sibling-package additions ride along with their own change folders) - [ ] 12.6 ~~Update `STATUS.md` migration note~~ — STATUS.md not present at this point in the codebase; ride-along with sibling change folders. - [x] 12.7 Cross-reference from `docs/drive/dehydrated-drives.md`'s "Spec'd in" pointers (already in place via this proposal)