Keep using Photos.app like you always do. Attic quietly backs up your originals and edits to an S3 bucket you control. One-way, append-only.
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Reference new docs from README and CLAUDE.md

Remove duplicated architecture, S3 structure, and project tree content
that now lives in docs/architecture.md and docs/metadata.md.

+10 -79
+4 -15
CLAUDE.md
··· 6 6 7 7 ```bash 8 8 deno task check # Type check 9 - deno task test # Run tests (42 tests) 9 + deno task test # Run tests (44 tests) 10 10 deno task lint # Lint 11 11 deno task fmt # Format 12 12 deno task fmt:check # Check formatting ··· 23 23 src/export/ # Exporter interface + ladder subprocess integration 24 24 ``` 25 25 26 - ## Architecture 26 + ## Reference Docs 27 27 28 - - **Interface-driven**: `S3Provider`, `ManifestStore`, `Exporter` — all injected for testability 29 - - **Mocks for testing**: `createMockS3Provider()`, `createMockExporter()` — tests never hit real services 30 - - **Runtime validation at trust boundaries**: Photos.sqlite schema, manifest JSON, ladder subprocess output, S3 metadata during rebuild 31 - - **Atomic manifest writes**: temp file + rename pattern in `ManifestStore.save()` 32 - - **Credentials**: macOS Keychain via `security find-generic-password` — never in env vars or config files 33 - - **Streaming uploads**: `putObject` accepts `ReadableStream<Uint8Array>` to avoid loading large files into memory 34 - 35 - ## S3 Bucket Structure 36 - 37 - ``` 38 - originals/{year}/{month}/{uuid}.{ext} # Original photo/video files 39 - metadata/assets/{uuid}.json # Per-asset metadata JSON 40 - ``` 28 + - [Architecture](docs/architecture.md) — pipeline, reader, ladder protocol, manifest, interfaces, design boundaries 29 + - [Asset Metadata](docs/metadata.md) — per-asset JSON schema uploaded to S3 41 30 42 31 ## Conventions 43 32
+6 -64
README.md
··· 92 92 | `--rebuild-manifest` | Reconstruct the local manifest from S3 metadata files | 93 93 | `--bucket NAME` | S3 bucket name (default: `photo-cloud-storage`) | 94 94 95 - ## S3 Bucket Structure 96 - 97 - ``` 98 - photo-cloud-storage/ 99 - originals/ 100 - 2024/ 101 - 01/ 102 - <uuid>.heic 103 - <uuid>.mov 104 - 02/ 105 - ... 106 - metadata/ 107 - assets/ 108 - <uuid>.json 109 - ``` 110 - 111 - - **originals/** -- Organized by year and month (UTC) from the asset's creation date. Each file is named by its Photos library UUID with the appropriate extension. 112 - - **metadata/** -- One JSON file per asset containing original filename, dimensions, GPS coordinates, file size, UTI type, favorite status, S3 key, SHA-256 checksum, and backup timestamp. 113 - 114 - ## Local State 115 - 116 - Attic stores its state in `~/.attic/`: 117 - 118 - - `manifest.json` -- Tracks which assets have been backed up (UUID, S3 key, checksum, timestamp). The manifest is saved periodically during backup and can be rebuilt from S3 metadata via `verify --rebuild-manifest`. 119 - - `staging/` -- Temporary directory where ladder exports files before upload. Files are cleaned up after each successful upload. 120 - 121 95 ## Testing 122 96 123 97 ```bash ··· 126 100 127 101 Tests use dependency injection with mock implementations for the S3 client and exporter, so no external services or credentials are needed. 128 102 129 - ## Future Plans 103 + ## Documentation 130 104 131 - - **Scheduled backups via launchd** -- A LaunchAgent plist to run backups daily on a dedicated Mac. Includes an `--auto` flag (no prompts, file-based logging to `~/.attic/logs/`), macOS notifications on completion/failure, and `deno task install-schedule` / `deno task uninstall-schedule` commands. 105 + - [Architecture](docs/architecture.md) -- How attic works: the backup pipeline, Photos.sqlite reader, ladder protocol, manifest lifecycle, and design boundaries 106 + - [Asset Metadata](docs/metadata.md) -- Schema reference for the per-asset JSON uploaded to S3 132 107 133 - ## Project Structure 108 + ## Future Plans 134 109 135 - ``` 136 - attic/ 137 - deno.json # Workspace config and task definitions 138 - shared/ # Shared types and utilities 139 - types.ts # PhotoAsset, AssetKind, CloudLocalState 140 - s3-paths.ts # S3 key generation (originalKey, metadataKey) 141 - s3-paths.test.ts 142 - cli/ # CLI application 143 - mod.ts # Entry point and argument parsing 144 - src/ 145 - format.ts # Byte formatting utility 146 - photos-db/ 147 - reader.ts # SQLite reader for Photos.sqlite 148 - reader.test.ts 149 - storage/ 150 - s3-client.ts # Scaleway S3 client (AWS SDK) 151 - s3-client.mock.ts 152 - s3-client.test.ts 153 - export/ 154 - exporter.ts # Ladder binary wrapper 155 - exporter.mock.ts 156 - exporter.test.ts 157 - manifest/ 158 - manifest.ts # Local backup manifest (JSON) 159 - manifest.test.ts 160 - commands/ 161 - scan.ts # Library scan report 162 - status.ts # Backup status report 163 - backup.ts # Backup pipeline 164 - backup.test.ts 165 - verify.ts # Integrity verification 166 - verify.test.ts 167 - rebuild.ts # Manifest reconstruction from S3 168 - rebuild.test.ts 169 - ``` 110 + - **Scheduled backups via launchd** -- A LaunchAgent plist to run backups daily on a dedicated Mac 111 + - **Rendered edit backup** -- Detect and upload edited versions alongside originals (see `docs/plans/`)