Captures the owner's requirements and decisions from the planning conversation, current branch/worktree state, open tasks 17-19, pending owner decisions and the controller's rulings so a new agent can resume. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1.4 KiB
Task 7 report
Built packages/core/src/{crypto,attachments}.ts with tests in packages/core/test; TODO line added under "Next".
RED: bun test packages/core/test failed (cannot find ../src/crypto.ts). GREEN: SQLite 8 pass; Postgres 12 pass. Typecheck clean.
Decisions: each storeAttachment call creates a new attachment row + link (file deduped on disk); unlinkAttachment(db, dataDir, userId, attachmentId, entity, entityId) deletes the row when no links remain and the file when no row shares the sha; readAttachment returns null for non-owner/missing; HKDF salt "sttracker-v1", info "sttracker-credentials", 12-byte IV; malformed blob -> CryptoError.
Concerns: none.
Fix round 1
Changes: per-sha in-process keyed mutex (withLock) held across store's exists/write/insert and unlink's delete-row/shared-check/rm; atomic write via <final>.tmp-<id> + rename (tmp removed on failure); image/svg+xml rejected, mime normalized (lowercase, params stripped) and stored normalized; CryptoError now gets { cause }.
Tests added: tampered ciphertext -> CryptoError; IV is 12 bytes; svg/normalization; cross-user shared bytes survive other's unlink; foreign unlink no-op; listAttachments user-scoped; concurrent store/unlink; no temp files left.
Commands: bun test packages/core/test/attachments.test.ts packages/core/test/crypto.test.ts -> 16 pass 0 fail (SQLite); with TEST_POSTGRES_URL -> 26 pass 0 fail; bun run typecheck clean.