first commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
---
|
||||
name: sp-drive-storage-zip
|
||||
description: ZIP archive adapter for drive — parses EOCD/ZIP64, local headers, and CDR; supports store/deflate, AES-256 decryption, and read-only/copy-on-write/rewrite modes.
|
||||
---
|
||||
|
||||
# ZIP Archive Storage for Suaveplan
|
||||
|
||||
ZIP archive adapter that exposes archive entries as a `DriveStorage`-compatible key-value store. Reads and writes standards-compliant ZIP through the structural `DriveStorage` view, with support for ZIP64, split volumes, WinZip AE-2 AES-256 decryption, and three explicit mutation modes.
|
||||
|
||||
## Architecture
|
||||
|
||||
| Component | Responsibility |
|
||||
|-----------|---------------|
|
||||
| `ZipArchiveStorage` | `DriveStorage`-compatible adapter exposing ZIP entries via `get`, `set`, `list`, `flush`, etc.; extends `AbstractStorage`. |
|
||||
| `ZipArchiveStorage.open()` | Static factory that discovers EOCD, promotes ZIP64, reassembles split volumes, and parses the full central directory. |
|
||||
| `encodeZip` | Encodes plaintext entries into a complete, standards-compliant ZIP byte buffer for `flush()` and `rewrite` mode. |
|
||||
| `normalizePath` | Validates and canonicalises entry paths before write, defending against traversal attacks. |
|
||||
| `parser` namespace | Full parser surface: EOCD/ZIP64 discovery, central-directory walk, local-header decode, store/deflate (de)compression, CRC-32, AES decrypt. |
|
||||
| `ZIP_CODES` + `ZipError` | Structured error registry via `defineCodes("ZIP", [...])`; ten codes covering structural, cryptographic, and write-path failures. |
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
networking/drive/drive-storage-zip/
|
||||
src/parser/ # EOCD, ZIP64, CDR, local headers, compression, AES, CRC-32, signatures
|
||||
src/storage/ # ZipArchiveStorage, encodeZip, normalizePath
|
||||
src/errors/ # ZIP_CODES, ZipError
|
||||
src/types/ # Parser and storage type definitions
|
||||
```
|
||||
|
||||
Sibling packages:
|
||||
- `@suaveplan/drive-storage-archive-core` — provides the conformance harness, mutation overlay, password hook, and `AbstractStorage` base that this adapter extends.
|
||||
- `@suaveplan/drive` — the top-level drive runtime that consumes `DriveStorage` adapters.
|
||||
- `@suaveplan/storage` — host storage types (e.g. `MemoryStorage`) used as the backing store for split-volume reassembly.
|
||||
|
||||
## Patterns
|
||||
|
||||
### Quick Start
|
||||
|
||||
```typescript
|
||||
import { ZipArchiveStorage } from "@suaveplan/drive-storage-zip";
|
||||
|
||||
const storage = await ZipArchiveStorage.open({
|
||||
source: archiveBytes,
|
||||
mode: "read-only",
|
||||
});
|
||||
const payload = await storage.get("docs/readme.md");
|
||||
```
|
||||
|
||||
### Copy-on-Write with Split Volumes
|
||||
|
||||
```typescript
|
||||
import { ZipArchiveStorage } from "@suaveplan/drive-storage-zip";
|
||||
import { MemoryStorage } from "@suaveplan/storage";
|
||||
import { zipSiblingResolver } from "@suaveplan/drive-storage-archive-core";
|
||||
|
||||
const host = new MemoryStorage();
|
||||
await host.set("archive.zip", terminalVolume);
|
||||
await host.set("archive.z01", firstVolume);
|
||||
|
||||
const storage = await ZipArchiveStorage.open({
|
||||
source: host,
|
||||
sourceKey: "archive.zip",
|
||||
mode: "copy-on-write",
|
||||
password: async () => process.env.ZIP_PASSWORD!,
|
||||
resolveSibling: zipSiblingResolver(host, "archive.zip"),
|
||||
});
|
||||
|
||||
await storage.set("notes.txt", new TextEncoder().encode("hello"));
|
||||
await storage.flush();
|
||||
```
|
||||
|
||||
## Constraints
|
||||
|
||||
- The adapter is read-only for AES-encrypted entries in v0.1.0; write support is stubbed for v0.2.0.
|
||||
- `copy-on-write` keeps the original archive bytes unchanged until `flush()`; on flush it eagerly decompresses every unread entry so the encoder can emit a fresh archive.
|
||||
- `rewrite` mode skips the overlay entirely — every mutation triggers a synchronous `rebuildAndPersist` so `getBuffer()` always returns the most recent bytes.
|
||||
- Path traversal is rejected at write time by `normalizePath`; malformed paths throw `ZIP_CODES.PATH_INVALID`.
|
||||
|
||||
## Checklist
|
||||
|
||||
1. Verify `ZipArchiveStorage.open()` handles EOCD, ZIP64, and split-volume reassembly correctly for the target archive.
|
||||
2. Confirm mutation mode (`read-only` / `copy-on-write` / `rewrite`) matches the intended use case — read-only is safest for untrusted archives.
|
||||
3. If AES decryption is needed, provide a `password` hook; it is invoked lazily and only for encrypted entries.
|
||||
4. Check that `@suaveplan/drive-storage-archive-core` is available as a runtime dependency.
|
||||
Reference in New Issue
Block a user