v0.133.0 — .cat archives M1: Export you can find and trust
The first release of the .cat archives program: an export you can find, that carries everything it needs, and that never quietly links back to the server that made it. The tasks, decisions and test script are in the milestone file.
- [x] Export where you look for it. Export… on the campaign's page and card, on each map in the map list and the Library card's menu, and on the character list, not only on the Delete pages. A dialog offers Full quality (original files) or Smaller file (re-encode images).
- [x] An archive that carries its files. Format 2:
cat.ymlat the root (format, platform version, kind, when, for whom, how images were bundled); every URL in every row walked and its file bundled underassets/, content-hashed and stored once, at full quality by default; a manifest of what each file is and which rows use it. Token and character art, legacy image URLs, map snapshots, custom textures, campaign images and Treasury art all travel; no row links to the server that made it. - [x] A missing file fails loudly. The export says which files and which rows, and offers Export anyway, without them or Cancel. It never quietly writes a link.
- [x] A guard test keeps a new image column from slipping back to being a link.
- [x] Links stay links. A web page a row points at (an item's source, a "see https://…" in a bio) is kept as a link and listed in the archive's manifest; only media files are bundled.
- [x] Character archives that read back. The YAML writer wrote invalid YAML for a list of objects (a character's skills or attributes), so a
.catwith either could not be re-imported since v0.42.0. Fixed, with a round-trip test.
For self-hosters and developers
- Archives are format 2. Older archives (no
cat.yml) are format 1; the importer coming in a later release reads both. - Export routes take
?images=original|smaller(defaultoriginal) and?missing=fail|skip(defaultfail); underfaila missing file answers 409missing-assetswith the files and the rows that use them. StorageProvider.read(storagePath)on the local, S3 and GCS providers; the exporter reads bundled files through it and fetches only media URLs from elsewhere through the outbound guard.- The archive is spooled to a temp directory and streamed, so memory holds one asset at a time.