06b0512cf8ae

record kepr 2's release and compatibility routes from kepr.uk as contract fixtures, with the GET-only script that re-records them (v3.0.19)

time
2026-09-26 18:45 UTC · 2 weeks ago
machine
Junes-MacBook-Pro.local
agent
claude-opus-5-5
session
kepr 3 implementation
parent
c2ced00ce4c7
96 files package.json+1 −1tests/fixtures/kepr2/api_haven_releases_history.body+1 −0tests/fixtures/kepr2/api_haven_releases_history.headers+3 −0tests/fixtures/kepr2/api_haven_releases_latest.body+1 −0tests/fixtures/kepr2/api_haven_releases_latest.headers+3 −0tests/fixtures/kepr2/api_kepr_releases_history.body+1 −0tests/fixtures/kepr2/api_kepr_releases_history.headers+3 −0tests/fixtures/kepr2/api_kepr_releases_latest.body+1 −0tests/fixtures/kepr2/api_kepr_releases_latest.headers+3 −0tests/fixtures/kepr2/api_koh_releases_2.1.0_linux-x86_64.headers+3 −0tests/fixtures/kepr2/api_koh_releases_2.1.0_macos-aarch64.headers+3 −0tests/fixtures/kepr2/api_koh_releases_2.1.16_linux-x86_64.body+1 −0tests/fixtures/kepr2/api_koh_releases_2.1.16_linux-x86_64.headers+2 −0tests/fixtures/kepr2/api_koh_releases_history.body+1 −0tests/fixtures/kepr2/api_koh_releases_history.headers+1 −0tests/fixtures/kepr2/api_koh_releases_latest.body+1 −0tests/fixtures/kepr2/api_koh_releases_latest.headers+2 −0tests/fixtures/kepr2/api_nina_releases_history.body+1 −0tests/fixtures/kepr2/api_nina_releases_history.headers+3 −0tests/fixtures/kepr2/api_nina_releases_latest.body+1 −0tests/fixtures/kepr2/api_nina_releases_latest.headers+3 −0tests/fixtures/kepr2/api_nowhere_releases_latest.body+1 −0tests/fixtures/kepr2/api_nowhere_releases_latest.headers+2 −0tests/fixtures/kepr2/api_peach-android_releases_history.body+1 −0tests/fixtures/kepr2/api_peach-android_releases_history.headers+3 −0tests/fixtures/kepr2/api_peach-android_releases_latest.body+1 −0tests/fixtures/kepr2/api_peach-android_releases_latest.headers+3 −0tests/fixtures/kepr2/api_peach-relay_releases_history.body+1 −0tests/fixtures/kepr2/api_peach-relay_releases_history.headers+2 −0tests/fixtures/kepr2/api_peach-relay_releases_latest.body+1 −0tests/fixtures/kepr2/api_peach-relay_releases_latest.headers+2 −0tests/fixtures/kepr2/haven_meta.body+1 −0tests/fixtures/kepr2/haven_meta.headers+2 −0tests/fixtures/kepr2/haven_releases_0.6.1_checksums.txt.body+7 −0tests/fixtures/kepr2/haven_releases_0.6.1_checksums.txt.headers+2 −0tests/fixtures/kepr2/haven_releases_0.6.1_haven-macos-aarch64.headers+3 −0tests/fixtures/kepr2/haven_releases_0.6.1_macos-aarch64.headers+3 −0tests/fixtures/kepr2/haven_releases_latest.body+0 −0tests/fixtures/kepr2/haven_releases_latest.headers+2 −0tests/fixtures/kepr2/haven_releases_latest_version.txt.body+1 −0tests/fixtures/kepr2/haven_releases_latest_version.txt.headers+2 −0tests/fixtures/kepr2/haven_update-info.body+1 −0tests/fixtures/kepr2/haven_update-info.headers+2 −0tests/fixtures/kepr2/kepr_meta.body+1 −0tests/fixtures/kepr2/kepr_meta.headers+2 −0tests/fixtures/kepr2/kepr_releases_2.0.16_checksums.txt.body+7 −0tests/fixtures/kepr2/kepr_releases_2.0.16_checksums.txt.headers+2 −0tests/fixtures/kepr2/kepr_releases_2.0.16_kepr-linux-aarch64.headers+3 −0tests/fixtures/kepr2/kepr_releases_2.0.16_linux-aarch64.headers+3 −0tests/fixtures/kepr2/kepr_releases_latest.body+0 −0tests/fixtures/kepr2/kepr_releases_latest.headers+2 −0tests/fixtures/kepr2/kepr_releases_latest_version.txt.body+1 −0tests/fixtures/kepr2/kepr_releases_latest_version.txt.headers+2 −0tests/fixtures/kepr2/kepr_update-info.body+1 −0tests/fixtures/kepr2/kepr_update-info.headers+2 −0tests/fixtures/kepr2/koh_meta.body+1 −0tests/fixtures/kepr2/koh_meta.headers+2 −0tests/fixtures/kepr2/koh_releases_2.1.0_checksums.txt.body+11 −0tests/fixtures/kepr2/koh_releases_2.1.0_checksums.txt.headers+2 −0tests/fixtures/kepr2/koh_releases_2.1.0_koh-linux-x86_64.headers+3 −0tests/fixtures/kepr2/koh_releases_2.1.0_linux-x86_64.headers+3 −0tests/fixtures/kepr2/koh_releases_latest.body+0 −0tests/fixtures/kepr2/koh_releases_latest.headers+2 −0tests/fixtures/kepr2/koh_releases_latest_version.txt.body+1 −0tests/fixtures/kepr2/koh_releases_latest_version.txt.headers+2 −0tests/fixtures/kepr2/koh_update-info.body+1 −0tests/fixtures/kepr2/koh_update-info.headers+2 −0tests/fixtures/kepr2/nina_meta.body+1 −0tests/fixtures/kepr2/nina_meta.headers+2 −0tests/fixtures/kepr2/nina_releases_3.4.14_checksums.txt.body+11 −0tests/fixtures/kepr2/nina_releases_3.4.14_checksums.txt.headers+2 −0tests/fixtures/kepr2/nina_releases_3.4.14_linux-aarch64.headers+3 −0tests/fixtures/kepr2/nina_releases_3.4.14_nina-linux-aarch64.headers+3 −0tests/fixtures/kepr2/nina_releases_latest.body+0 −0tests/fixtures/kepr2/nina_releases_latest.headers+2 −0tests/fixtures/kepr2/nina_releases_latest_version.txt.body+1 −0tests/fixtures/kepr2/nina_releases_latest_version.txt.headers+2 −0tests/fixtures/kepr2/nina_update-info.body+1 −0tests/fixtures/kepr2/nina_update-info.headers+2 −0tests/fixtures/kepr2/peach-android_meta.body+1 −0tests/fixtures/kepr2/peach-android_meta.headers+2 −0tests/fixtures/kepr2/peach-android_releases_2.17.43_android-arm64.headers+3 −0tests/fixtures/kepr2/peach-android_releases_2.17.43_checksums.txt.body+7 −0tests/fixtures/kepr2/peach-android_releases_2.17.43_checksums.txt.headers+2 −0tests/fixtures/kepr2/peach-android_releases_2.17.43_peach-android-android-arm64.headers+3 −0tests/fixtures/kepr2/peach-android_releases_latest.body+0 −0tests/fixtures/kepr2/peach-android_releases_latest.headers+2 −0tests/fixtures/kepr2/peach-android_releases_latest_version.txt.body+1 −0tests/fixtures/kepr2/peach-android_releases_latest_version.txt.headers+2 −0tests/fixtures/kepr2/peach-android_update-info.body+1 −0tests/fixtures/kepr2/peach-android_update-info.headers+2 −0tests/fixtures/kepr2/peach-relay_meta.body+1 −0tests/fixtures/kepr2/peach-relay_meta.headers+2 −0tests/fixtures/kepr2/peach-relay_update-info.body+1 −0tests/fixtures/kepr2/peach-relay_update-info.headers+2 −0tests/fixtures/kepr2/record.sh+39 −0
package.json+1 −1
@@ -1,6 +1,6 @@11 {22 	"name": "kepr",3-	"version": "3.0.18",3+	"version": "3.0.19",44 	"private": true,55 	"type": "module",66 	"scripts": {

view file

tests/fixtures/kepr2/api_haven_releases_history.body+1 −0
@@ -0,0 +1 @@1+[{"version":"0.6.1","notes":"fix wallpaper set regression and download cache"},{"version":"0.6.0","notes":"resolve remaining Haven findings"},{"version":"0.0.0","notes":"macos .app build"},{"version":"0.5.5","notes":"## Highlights\n- Release artifacts are now available for haven 0.5.5.\n\n## Fixes\n- Published haven 0.5.5 from save e2e9a1b3c4d5.\n"}]\ No newline at end of file

view file

tests/fixtures/kepr2/api_haven_releases_history.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-83+access-control-allow-origin: *

view file

tests/fixtures/kepr2/api_haven_releases_latest.body+1 −0
@@ -0,0 +1 @@1+{"version":"0.6.1","notes":"fix wallpaper set regression and download cache","platforms":{"macos-aarch64":{"url":"https://kepr.uk/haven/releases/0.6.1/macos-aarch64","blake3":"7c2ea86ca75df33ff018019395be0b6feb9a3deba1d00623e23c9ec2772eb5a8","sha256":"67b715c20b64779615564a811c58093893d6e80cc9a997b4600f3fb68cdbfce0","provenance":{"version":"0.6.1","platform":"macos-aarch64","checksum":"blake3:7c2ea86ca75df33ff018019395be0b6feb9a3deba1d00623e23c9ec2772eb5a8","source":"koh-offer"},"signature":""},"macos-x86_64":{"url":"https://kepr.uk/haven/releases/0.6.1/macos-x86_64","blake3":"73733480227ed174977af99428d3e622cdf6285836b4ef53e58bd7e120adea24","sha256":"2e844c00cdfe9efac2706c83723542ac8fc46fdb39b49da16ec98641a6fdf72a","provenance":{"version":"0.6.1","platform":"macos-x86_64","checksum":"blake3:73733480227ed174977af99428d3e622cdf6285836b4ef53e58bd7e120adea24","source":"koh-offer"},"signature":""}}}\ No newline at end of file

view file

tests/fixtures/kepr2/api_haven_releases_latest.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-83+access-control-allow-origin: *

view file

tests/fixtures/kepr2/api_kepr_releases_history.body+1 −0
@@ -0,0 +1 @@1+[{"version":"2.0.16","notes":"fix offer ingest cpu spin"},{"version":"2.0.14","notes":"auth rework protocol v2"},{"version":"1.56.155","notes":"Added \/api\/:name\/releases\/history endpoint for multi-version changelog support in the Android app."},{"version":"1.56.89","notes":"operator login rebuild"},{"version":"1.55.50","notes":"fix: Add SQLite busy timeout and busy errors (v1.55.50)\n\n- Configure every SQLite connection with a 5000ms busy timeout\n- Map SQLITE_BUSY\/LOCKED to error.Busy across prepare, exec, step, and reset paths\n- Print a human retry message for top-level busy failures\n- Add coverage that opened connections carry the busy timeout\nfix: Cap zlib decompression by manifest size (v1.55.49)\n\n- Require declared uncompressed size for object decompression and verification\n- Cap decompression at declared size plus slack, bounded by MAX_FILE_SIZE\n- Thread manifest file sizes through ingest, archive, graph, review, diff, build, and raw-file paths\n- Add regression coverage for compressed payloads that inflate beyond the declared-size slack\nfix: Make migrations transactional and monotonic (v1.55.48)\n\n- Reject databases with schema versions newer than the running binary\n- Wrap each migration and schema_version write in BEGIN IMMEDIATE\/COMMIT\n- Replace delete-then-insert version stamping with rowid upsert behavior\n- Add regression coverage for stale-binary downgrade refusal\nfix: Escape JSON script-breakout characters (v1.55.47)\n\n- Escape \u003c, \u003e, and \/ in shared JSON string output\n- Prevent \u003c\/script\u003e payloads from breaking JSON islands\n- Add regression coverage for script tag breakout strings\nfix: Block unsafe markdown URL schemes (v1.55.46)\n\n- Allow only http, https, mailto, root-relative, and relative markdown URLs\n- Render unsafe links and images as escaped plain text instead of active tags\n- Add regression coverage for javascript\/data markdown payloads\nfix: Require registered SSH keys for offers (v1.55.45)\n\n- Reject unknown SSH public keys during auth instead of accepting any ed25519 key\n- Route SSH contributor offers into pending quarantine when contributions are enabled\n- Keep operator SSH offers on the direct save path\n- Add regression coverage for SSH contributor quarantine and disabled offers\nfeat: Prefill release notes draft in repo detail (v1.55.44)\nfix: Auto-fill release notes for published builds (v1.55.43)\nfix: Remove Atlas metadata chatter (v1.55.42)\nfix: Quiet Atlas copy and tame repo metadata saves (v1.55.41)\nsmtp: fix dangling --user arg (defer freed before spawn) (v1.55.38)\nsmtp: revert segfaulting stderr pipe"},{"version":"1.43.7","notes":"add lightbox popup for screenshot attachments in issue thread (zoom-in cursor on thumbnail, dark overlay modal, Escape\/backdrop to close)"},{"version":"1.42.5","notes":""},{"version":"0.0.0","notes":""}]\ No newline at end of file

view file

tests/fixtures/kepr2/api_kepr_releases_history.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-83+access-control-allow-origin: *

view file

tests/fixtures/kepr2/api_kepr_releases_latest.body+1 −0
@@ -0,0 +1 @@1+{"version":"2.0.16","notes":"fix offer ingest cpu spin","platforms":{"linux-aarch64":{"url":"https://kepr.uk/kepr/releases/2.0.16/linux-aarch64","blake3":"4d07177c429232e6c45bb7c53dd3ecb499058ad022f5eb95d786a61ca2103436","sha256":"16f60e3d601c386bb0b7e0efdef1c17f3a7440b0020e7cc9f35e7f42c7db5383","provenance":{"version":"2.0.16","platform":"linux-aarch64","checksum":"blake3:4d07177c429232e6c45bb7c53dd3ecb499058ad022f5eb95d786a61ca2103436","source":"koh-offer"},"signature":""},"linux-x86_64":{"url":"https://kepr.uk/kepr/releases/2.0.16/linux-x86_64","blake3":"0618ffe6ed042effa0966368c232eeddd46ed23eaa5660dee324229a93f4ab13","sha256":"447a5306f383554dcaa494ad1eaddf3a10eda41ffffbd1a19edd083b8eb314ff","provenance":{"version":"2.0.16","platform":"linux-x86_64","checksum":"blake3:0618ffe6ed042effa0966368c232eeddd46ed23eaa5660dee324229a93f4ab13","source":"koh-offer"},"signature":""}}}\ No newline at end of file

view file

tests/fixtures/kepr2/api_kepr_releases_latest.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-83+access-control-allow-origin: *

view file

tests/fixtures/kepr2/api_koh_releases_2.1.0_linux-x86_64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="koh"

view file

tests/fixtures/kepr2/api_koh_releases_2.1.0_macos-aarch64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="koh"

view file

tests/fixtures/kepr2/api_koh_releases_2.1.16_linux-x86_64.body+1 −0
@@ -0,0 +1 @@1+{"error":"not_found","message":"release not found"}\ No newline at end of file

view file

tests/fixtures/kepr2/api_koh_releases_2.1.16_linux-x86_64.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 404 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/api_koh_releases_history.body+1 −0
@@ -0,0 +1 @@1+Not Found\ No newline at end of file

view file

tests/fixtures/kepr2/api_koh_releases_history.headers+1 −0
@@ -0,0 +1 @@1+HTTP/2 404 

view file

tests/fixtures/kepr2/api_koh_releases_latest.body+1 −0
@@ -0,0 +1 @@1+{"version":"2.1.0","notes":"All koh config files now live under .koh\/: root .kohconfig and .kohignore are replaced by .koh\/config and .koh\/ignore, and offer-scoping rules move to .koh\/ignore.public and .koh\/ignore.\u003cremote\u003e, so a repo root no longer accumulates koh dotfiles. Existing repos keep working — legacy root files are still read as a fallback — and koh init seeds only the new locations. Also fixes two crashes surfaced by the change: koh init no longer fails with an internal database error when a stray empty .koh directory exists (Repo.open now requires .koh\/koh.db), and koh recover works when koh.db has been deleted so it can rebuild the database from snapshot manifests. Version 2.1.0.","platforms":{"linux-x86_64":{"url":"https://kepr.uk/api/koh/releases/2.1.0/linux-x86_64","checksum":"blake3:ddee5df771bee96e5d44dc6ad6f4e52ab49e936cb507ce7600b705f35aece298","provenance":{"version":"2.1.0","platform":"linux-x86_64","checksum":"blake3:ddee5df771bee96e5d44dc6ad6f4e52ab49e936cb507ce7600b705f35aece298","source":"koh-offer"},"signature":""},"linux-aarch64":{"url":"https://kepr.uk/api/koh/releases/2.1.0/linux-aarch64","checksum":"blake3:ef867176ec7865b8f694b05999f96ca0a6143c28cb1de19ff5234f127c1c34a7","provenance":{"version":"2.1.0","platform":"linux-aarch64","checksum":"blake3:ef867176ec7865b8f694b05999f96ca0a6143c28cb1de19ff5234f127c1c34a7","source":"koh-offer"},"signature":""},"macos-x86_64":{"url":"https://kepr.uk/api/koh/releases/2.1.0/macos-x86_64","checksum":"blake3:0ffa3f7e2a5a923c01b22b0317bcfa8e18bca8c9da2551e98093f99e8784fa97","provenance":{"version":"2.1.0","platform":"macos-x86_64","checksum":"blake3:0ffa3f7e2a5a923c01b22b0317bcfa8e18bca8c9da2551e98093f99e8784fa97","source":"koh-offer"},"signature":""},"macos-aarch64":{"url":"https://kepr.uk/api/koh/releases/2.1.0/macos-aarch64","checksum":"blake3:ec20d8f749c936bed61bca70d205931055331d4d5d9ad1f5e77536a0ed169a6f","provenance":{"version":"2.1.0","platform":"macos-aarch64","checksum":"blake3:ec20d8f749c936bed61bca70d205931055331d4d5d9ad1f5e77536a0ed169a6f","source":"koh-offer"},"signature":""}}}\ No newline at end of file

view file

tests/fixtures/kepr2/api_koh_releases_latest.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/api_nina_releases_history.body+1 −0
@@ -0,0 +1 @@1+[{"version":"3.4.14","notes":"## Highlights\n- fix: Resolve fable audit pin and option leftovers (v3.4.14)\n\n## Fixes\n- Published nina 3.4.14 from save 3c9ac84ad6d7.\n"},{"version":"3.4.13","notes":"nina passthrough flag audit"},{"version":"3.4.10","notes":"man pager terminal height"},{"version":"3.4.9","notes":"fix nina update still no-op"},{"version":"3.4.8","notes":"## Highlights\n- fix nina update reporting false success on nix profile installs: nix profile upgrade re-resolves the element's own originalUrl, which the --no-write-lock-file archive install bakes a permanent narHash pin into, so upgrade was silently re-fetching the exact same locked content forever (exit 0, no warning text) instead of a real update; replace it with nix profile remove + nix profile add against the plain unpinned flake URL so HEAD is genuinely re-resolved; bump v3.4.8\n\n## Fixes\n- Published nina 3.4.8 from save 3d1160fd9b1e.\n"},{"version":"3.4.7","notes":"changelog range and clean nix update output"},{"version":"3.4.6","notes":"macos tui raw mode"},{"version":"3.4.4","notes":"add nina man"},{"version":"3.4.3","notes":"unfree install fix"},{"version":"3.4.2","notes":"fix nina update false success"},{"version":"3.4.1","notes":"Nina now detects your platform-specific Home Manager flake attribute automatically, opens your config directory with nina edit --dir, and adds nina store optimise for store deduplication. The nina edit hardware command has been removed with a clear explanation since hardware-configuration.nix is auto-generated and shouldn't be edited directly."},{"version":"3.3.1","notes":"nina can now help you initialize your home manager setup with nina home init"},{"version":"3.3.0","notes":"home init: record REAL network VM verification (init + --switch gen 1) pass in CONTINUITY\nhome init: record golden VM verification 9\/9 pass (v3.3.0) in CONTINUITY\nhome init: nina home init generates HM config, --switch activates, warns if already exists (v3.3.0)\nfix: nix update uses originalUrl as installable, add hash -r hint (v3.2.6)\nfix: progress bar tracks copies, error pipeline catches service activation failures (v3.2.5)\nfix: Render update changelog fallback (v3.2.4)\n\n- Prefer release notes from metadata, then derive changelog entries from Kepr archives when notes are missing\n- Compare semver before offering an update so newer local builds do not downgrade\n- Bump VERSION\/build.zig.zon to 3.2.4\n- Verified zig build, zig build test, live update --check, and a local missing-notes update fixture\nupgrade: live build panel during rebuild phase\napply: live build panel — single name slot, cyan\/yellow\/green bar, fetch\/build\/activate phases, non-TTY suppressed; bump v3.2.3\nerrors: expanded translation table (25 patterns + home manager), 3-layer pipeline, warning extraction; output: buildError + buildWarnings; exec: capture nixos-rebuild stderr; main: route BuildFailed through pipeline; bump v3.2.2\nverify hooks: 18\/18 pass on golden-unstable (v3.2.1)\nfix: pre-hook abort returns error.HookAborted for non-zero exit; bump v3.2.1\nfix: nina back uses switchGeneration on flake systems, not --rollback"},{"version":"3.2.6","notes":"fix: nix update uses originalUrl as installable, add hash -r hint (v3.2.6)\nfix: progress bar tracks copies, error pipeline catches service activation failures (v3.2.5)\nfix: Render update changelog fallback (v3.2.4)\n\n- Prefer release notes from metadata, then derive changelog entries from Kepr archives when notes are missing\n- Compare semver before offering an update so newer local builds do not downgrade\n- Bump VERSION\/build.zig.zon to 3.2.4\n- Verified zig build, zig build test, live update --check, and a local missing-notes update fixture\nupgrade: live build panel during rebuild phase\napply: live build panel — single name slot, cyan\/yellow\/green bar, fetch\/build\/activate phases, non-TTY suppressed; bump v3.2.3\nerrors: expanded translation table (25 patterns + home manager), 3-layer pipeline, warning extraction; output: buildError + buildWarnings; exec: capture nixos-rebuild stderr; main: route BuildFailed through pipeline; bump v3.2.2\nverify hooks: 18\/18 pass on golden-unstable (v3.2.1)\nfix: pre-hook abort returns error.HookAborted for non-zero exit; bump v3.2.1\nfix: nina back uses switchGeneration on flake systems, not --rollback\nverify hooks: record golden failures (v3.2.0)\nfeat: Add lifecycle hooks for state-changing commands (v3.2.0)\n\n- Add local ~\/.config\/nina\/hooks runner with executable checks, exit codes, and capped tail output\n- Wire pre\/post hooks into apply, back, home apply, and upgrade\n- Document hook files and bump VERSION\/build.zig.zon to 3.2.0\n- Verify zig build, zig build test, nina --version, and shimmed apply hook smoke\ndocument v3.1.9 nina update verification in CONTINUITY — changelog + self-update-completion confirmed working (build\/test green, HTTP-fixture check\/download\/checksum paths exercised); credits GPT 5.4 Mini for the code, Opus 4.8 for the verification\nfix: Surface successful self-update completion (v3.1.9)\n\n- Print the standard updated line after a successful nix-managed nina update\n- Keep the existing direct-download flow unchanged\n- Bump VERSION and build.zig.zon to 3.1.9"},{"version":"3.2.5","notes":"fix: progress bar tracks copies, error pipeline catches service activation failures (v3.2.5)\nfix: Render update changelog fallback (v3.2.4)\n\n- Prefer release notes from metadata, then derive changelog entries from Kepr archives when notes are missing\n- Compare semver before offering an update so newer local builds do not downgrade\n- Bump VERSION\/build.zig.zon to 3.2.4\n- Verified zig build, zig build test, live update --check, and a local missing-notes update fixture\nupgrade: live build panel during rebuild phase\napply: live build panel — single name slot, cyan\/yellow\/green bar, fetch\/build\/activate phases, non-TTY suppressed; bump v3.2.3\nerrors: expanded translation table (25 patterns + home manager), 3-layer pipeline, warning extraction; output: buildError + buildWarnings; exec: capture nixos-rebuild stderr; main: route BuildFailed through pipeline; bump v3.2.2\nverify hooks: 18\/18 pass on golden-unstable (v3.2.1)\nfix: pre-hook abort returns error.HookAborted for non-zero exit; bump v3.2.1\nfix: nina back uses switchGeneration on flake systems, not --rollback\nverify hooks: record golden failures (v3.2.0)\nfeat: Add lifecycle hooks for state-changing commands (v3.2.0)\n\n- Add local ~\/.config\/nina\/hooks runner with executable checks, exit codes, and capped tail output\n- Wire pre\/post hooks into apply, back, home apply, and upgrade\n- Document hook files and bump VERSION\/build.zig.zon to 3.2.0\n- Verify zig build, zig build test, nina --version, and shimmed apply hook smoke\ndocument v3.1.9 nina update verification in CONTINUITY — changelog + self-update-completion confirmed working (build\/test green, HTTP-fixture check\/download\/checksum paths exercised); credits GPT 5.4 Mini for the code, Opus 4.8 for the verification\nfix: Surface successful self-update completion (v3.1.9)\n\n- Print the standard updated line after a successful nix-managed nina update\n- Keep the existing direct-download flow unchanged\n- Bump VERSION and build.zig.zon to 3.1.9\nfeat: Show release changelog in nina update (v3.1.6)"},{"version":"3.2.4","notes":"fix: Render update changelog fallback (v3.2.4)\n\n- Prefer release notes from metadata, then derive changelog entries from Kepr archives when notes are missing\n- Compare semver before offering an update so newer local builds do not downgrade\n- Bump VERSION\/build.zig.zon to 3.2.4\n- Verified zig build, zig build test, live update --check, and a local missing-notes update fixture\nupgrade: live build panel during rebuild phase\napply: live build panel — single name slot, cyan\/yellow\/green bar, fetch\/build\/activate phases, non-TTY suppressed; bump v3.2.3\nerrors: expanded translation table (25 patterns + home manager), 3-layer pipeline, warning extraction; output: buildError + buildWarnings; exec: capture nixos-rebuild stderr; main: route BuildFailed through pipeline; bump v3.2.2\nverify hooks: 18\/18 pass on golden-unstable (v3.2.1)\nfix: pre-hook abort returns error.HookAborted for non-zero exit; bump v3.2.1\nfix: nina back uses switchGeneration on flake systems, not --rollback\nverify hooks: record golden failures (v3.2.0)\nfeat: Add lifecycle hooks for state-changing commands (v3.2.0)\n\n- Add local ~\/.config\/nina\/hooks runner with executable checks, exit codes, and capped tail output\n- Wire pre\/post hooks into apply, back, home apply, and upgrade\n- Document hook files and bump VERSION\/build.zig.zon to 3.2.0\n- Verify zig build, zig build test, nina --version, and shimmed apply hook smoke\ndocument v3.1.9 nina update verification in CONTINUITY — changelog + self-update-completion confirmed working (build\/test green, HTTP-fixture check\/download\/checksum paths exercised); credits GPT 5.4 Mini for the code, Opus 4.8 for the verification\nfix: Surface successful self-update completion (v3.1.9)\n\n- Print the standard updated line after a successful nix-managed nina update\n- Keep the existing direct-download flow unchanged\n- Bump VERSION and build.zig.zon to 3.1.9\nfeat: Show release changelog in nina update (v3.1.6)\npkg commands: resolve as nixpkgs#name consistently — fixes why\/deps\/size\/closure on flake systems (v3.1.5)"},{"version":"3.2.3","notes":"upgrade: live build panel during rebuild phase\napply: live build panel — single name slot, cyan\/yellow\/green bar, fetch\/build\/activate phases, non-TTY suppressed; bump v3.2.3\nerrors: expanded translation table (25 patterns + home manager), 3-layer pipeline, warning extraction; output: buildError + buildWarnings; exec: capture nixos-rebuild stderr; main: route BuildFailed through pipeline; bump v3.2.2\nverify hooks: 18\/18 pass on golden-unstable (v3.2.1)\nfix: pre-hook abort returns error.HookAborted for non-zero exit; bump v3.2.1\nfix: nina back uses switchGeneration on flake systems, not --rollback\nverify hooks: record golden failures (v3.2.0)\nfeat: Add lifecycle hooks for state-changing commands (v3.2.0)\n\n- Add local ~\/.config\/nina\/hooks runner with executable checks, exit codes, and capped tail output\n- Wire pre\/post hooks into apply, back, home apply, and upgrade\n- Document hook files and bump VERSION\/build.zig.zon to 3.2.0\n- Verify zig build, zig build test, nina --version, and shimmed apply hook smoke\ndocument v3.1.9 nina update verification in CONTINUITY — changelog + self-update-completion confirmed working (build\/test green, HTTP-fixture check\/download\/checksum paths exercised); credits GPT 5.4 Mini for the code, Opus 4.8 for the verification\nfix: Surface successful self-update completion (v3.1.9)\n\n- Print the standard updated line after a successful nix-managed nina update\n- Keep the existing direct-download flow unchanged\n- Bump VERSION and build.zig.zon to 3.1.9\nfeat: Show release changelog in nina update (v3.1.6)\npkg commands: resolve as nixpkgs#name consistently — fixes why\/deps\/size\/closure on flake systems (v3.1.5)\ndocs: record kyoshi try\/develop prompt smoke verification"},{"version":"3.1.9","notes":"document v3.1.9 nina update verification in CONTINUITY — changelog + self-update-completion confirmed working (build\/test green, HTTP-fixture check\/download\/checksum paths exercised)"},{"version":"3.1.8","notes":"feat: Show release changelog in nina update (v3.1.6)\npkg commands: resolve as nixpkgs#name consistently — fixes why\/deps\/size\/closure on flake systems (v3.1.5)\ndocs: record kyoshi try\/develop prompt smoke verification\ntry + develop: branded PS1 prompt and exit instruction (v3.1.4)\ndocument v3.1.3 cleanups in CONTINUITY — .\/result litter fix, useFlakeFlag trailing-slash normalization, golden home.nix enableNixpkgsReleaseCheck, module-mode verified live (5\/5 PASS on golden)"},{"version":"3.1.4","notes":"docs: record kyoshi try\/develop prompt smoke verification\ntry + develop: branded PS1 prompt and exit instruction (v3.1.4)\ndocument v3.1.3 cleanups in CONTINUITY — .\/result litter fix, useFlakeFlag trailing-slash normalization, golden home.nix enableNixpkgsReleaseCheck, module-mode verified live (5\/5 PASS on golden)"},{"version":"3.1.3","notes":"document v3.1.3 cleanups in CONTINUITY — .\/result litter fix, useFlakeFlag trailing-slash normalization, golden home.nix enableNixpkgsReleaseCheck, module-mode verified live (5\/5 PASS on golden)"},{"version":"3.0.23","notes":"add branded PS1 prompt and exit instruction to nina try and develop\nnina setup creates ~\/.nina.conf via wizard when config not found\nauto-run setup on first run when ~\/.nina.conf not found\nremove unfillable freed parameter from cleanDone"},{"version":"3.0.22","notes":"nina setup creates ~\/.nina.conf via wizard when config not found\nauto-run setup on first run when ~\/.nina.conf not found\nremove unfillable freed parameter from cleanDone"},{"version":"3.0.21","notes":"auto-run setup on first run when ~\/.nina.conf not found\nremove unfillable freed parameter from cleanDone"},{"version":"3.0.20","notes":"remove unfillable freed parameter from cleanDone"},{"version":"3.0.19","notes":"fix install command: remove #nina suffix per forum post\nadd install.sh redirect: discontinued notice + nix profile add path"},{"version":"3.0.18","notes":"fix goodbye to cleanly remove via nix profile remove"},{"version":"3.0.17","notes":"bump to 3.0.17\nfix goodbye\/update: detect nina element by storePath when element key is 'default' (tarball install via default output)\nupdate copyright holder to Asha Software\nadd MIT license\nbump to 3.0.16\nwiden action column from 12 to 16 to fit service-status without breaking alignment\nmake NixOS installer profile-only: drop generate_nixos_module + offer_config_import (no more ~\/nina.nix generation or \/etc\/nixos editing), so curl|sh does a single per-user 'nix profile add' instead of also wiring a system module — fixes the double-install"},{"version":"3.0.15","notes":""},{"version":"1ea6dc71d2a4","notes":""}]\ No newline at end of file

view file

tests/fixtures/kepr2/api_nina_releases_history.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-83+access-control-allow-origin: *

view file

tests/fixtures/kepr2/api_nina_releases_latest.body+1 −0
@@ -0,0 +1 @@1+{"version":"3.4.14","notes":"## Highlights\n- fix: Resolve fable audit pin and option leftovers (v3.4.14)\n\n## Fixes\n- Published nina 3.4.14 from save 3c9ac84ad6d7.\n","platforms":{"linux-aarch64":{"url":"https://kepr.uk/nina/releases/3.4.14/linux-aarch64","blake3":"28f7270461069a4031f0c0a047806c70b451bb8853026037a9dfa3285b789fc1","sha256":"038e90cf755fabee06e6aa7a996baa85c220911e349f318759ad6b2db5216e07","provenance":{"version":"3.4.14","platform":"linux-aarch64","checksum":"blake3:28f7270461069a4031f0c0a047806c70b451bb8853026037a9dfa3285b789fc1","source":"koh-offer"},"signature":""},"linux-x86_64":{"url":"https://kepr.uk/nina/releases/3.4.14/linux-x86_64","blake3":"3111e8dc2557e7a26359f018f65cfa527f37fa73d1f10e2a1f42b009f42417f4","sha256":"b6c2d6c534322cb2cffbd034e46901537bf55a42a556bb08ba9103c112e7b250","provenance":{"version":"3.4.14","platform":"linux-x86_64","checksum":"blake3:3111e8dc2557e7a26359f018f65cfa527f37fa73d1f10e2a1f42b009f42417f4","source":"koh-offer"},"signature":""},"macos-aarch64":{"url":"https://kepr.uk/nina/releases/3.4.14/macos-aarch64","blake3":"4e9d45baf91fc4b2eb4d6a33ec87a0c219b593ce830a2ce8f123aa75e12cbf40","sha256":"c3913dd174a6972d1b7c28ce5c22809264fc1e729f7505caf914d0d4f4c946ae","provenance":{"version":"3.4.14","platform":"macos-aarch64","checksum":"blake3:4e9d45baf91fc4b2eb4d6a33ec87a0c219b593ce830a2ce8f123aa75e12cbf40","source":"koh-offer"},"signature":""},"macos-x86_64":{"url":"https://kepr.uk/nina/releases/3.4.14/macos-x86_64","blake3":"2af6d435c3548e2b74cc3f757edf9f5c0a160f54e9a4704151b296a03015a377","sha256":"6a30801cf500ed70eb62bfbd0c48937654f17d16ab04185afd766f856a401ff4","provenance":{"version":"3.4.14","platform":"macos-x86_64","checksum":"blake3:2af6d435c3548e2b74cc3f757edf9f5c0a160f54e9a4704151b296a03015a377","source":"koh-offer"},"signature":""}}}\ No newline at end of file

view file

tests/fixtures/kepr2/api_nina_releases_latest.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-83+access-control-allow-origin: *

view file

tests/fixtures/kepr2/api_nowhere_releases_latest.body+1 −0
@@ -0,0 +1 @@1+{"error":"repo_not_found","message":"repo not found"}\ No newline at end of file

view file

tests/fixtures/kepr2/api_nowhere_releases_latest.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 404 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/api_peach-android_releases_history.body+1 −0
@@ -0,0 +1 @@1+[{"version":"2.17.43","notes":"Peach Android v2.17.43 makes encrypted Sync dependable throughout the day. Saving a login, note, card, or passkey now prompts an immediate peer check while periodic background reconciliation remains the fallback. The long-running Sync listener no longer uses Androids time-limited data-sync service category, preventing the system crashes seen on Android 15, and its notification now describes active checking without promising a connection that has not been established. This release also clears remembered unlock text before navigation, expands real-device Codex recovery assurance across a diverse 250-entry vault, and strengthens bounded cross-client diagnostics, rollback handling, and build verification."},{"version":"2.17.38","notes":"Peach Android v2.17.38 resolves four audit observations. Cloud-backup extraction now excludes the sync-generation archive consistently across cloud backup, device transfer, and legacy backup rules. Backup decode tests use generated synthetic encrypted PeachScript fixtures instead of a developer-local Downloads file. Android Argon2id coverage now includes an exact browser known-answer vector, and native provenance documentation identifies v2.17.38. Verified with the full serial JDK 17 unit-test and lint gate, XML validation, release-manifest drift gate, native provenance gate, and Kepr helper signing and metadata gates."},{"version":"2.17.35","notes":"v2.17.35 restores in-app updates for existing Peach installations. The APKs are signed with the established Peach release certificate and lineage. Release publication now also refuses temporary or replacement keystores before staging artifacts."},{"version":"2.17.34","notes":"Secure Sync reset and device-management improvements are now available. Peach clearly explains when a device needs re-pairing after a reset, lets you revoke devices during reset, and fails closed on corrupt trust data. Release validation also verifies the merged manifest, packaged native libraries, and APK signing certificate before publication."},{"version":"2.17.15","notes":"Fixed pairing with an existing device when one side still remembers a previously revoked identity. Peach now refreshes the affected device identity and completes the secure pairing session instead of ending it."},{"version":"2.17.14","notes":"## Highlights\n- Re-pairing a previously removed Chrome or Firefox device now safely requests a fresh identity, so Sync keeps every newly paired device instead of making another one disappear.\n\n## Fixes\n- Android and Browser now use matching revocation-retention and device-manifest compatibility rules, preventing stale removals and mismatched Sync steps from disrupting the device mesh."},{"version":"2.17.13","notes":"Fixes a re-pairing issue where a previously revoked browser identity could be reused and cause another mesh peer to remove the browser again. Re-pairing now rotates the identity when its device ID or long-term key is already terminally revoked, preventing stale revocation replay while preserving the authenticated retry flow."},{"version":"2.17.12","notes":"## Fixes\n- Adding Firefox, Chrome, or another copied browser profile now preserves your existing paired devices and adds the browser as a separate peer in the mesh."},{"version":"2.17.11","notes":"Highlights\n- Sync now detects an outdated paired device immediately and explains that it needs an update, instead of waiting and ending with a generic failure.\n- After unlocking once following this update, Android can resume receiving encrypted Sync changes after a restart even while the vault remains locked.\n\nFixes\n- Aligned Android Sync negotiation and encrypted entry handling with Peach Browser v5.2.24.\n- Prevented device-manifest messages from entering the wrong Sync phase."},{"version":"2.17.9","notes":"## Highlights\n\n  - Pairing a new browser no longer removes existing devices from the Android mesh.\n\n## Fixes\n\n  - Prevented concurrent pairing and sync updates from overwriting each other.\n  - Updated Android manifest compatibility checks and dependency verification."},{"version":"2.17.2","notes":"## Fixes\n- Peach passkeys sign in successfully again from both the displayed passkey row and the Sign in button.\n- A locked vault now authenticates once for the complete passkey request instead of prompting again after returning to the browser.\n- Peach keeps the selected passkey available during the protected Credential Manager handoff, preventing the immediate authentication failure seen on GitHub."},{"version":"2.16.5","notes":"## Fixes\n- Sync now derives the unlocked listener identity from the vault root, keeping relay reconnect identity consistent after unlock.\n- Passkey selection after unlocking completes sign-in reliably, including Samsung Credential Manager flows.\n- Browser inline autofill suggestions are available again in supported login fields.\n- Firefox passkey assertions use the browser-owned client-data hash when Android provides it.\n\nUpdate Android before testing sync. If an existing paired device still fails to sync after this security update, revoke that device and pair it again."},{"version":"2.16.3","notes":"## Fixes\n- Restored the request payload that made the Sign in button work in v2.16.1.\n- Passkey row taps now preserve GitHub’s biometric requirement separately, so they can prompt for verification without replacing the signed challenge."},{"version":"2.16.2","notes":"## Fixes\n- Tapping the displayed passkey now preserves GitHub’s biometric verification requirement, matching the working Sign in button path.\n- Both picker actions now run the same authenticated passkey request instead of allowing Samsung’s row callback to drop the verification prompt."},{"version":"2.16.1","notes":"## Fixes\n- The displayed passkey row and the Sign in button now use the same authenticated GitHub request, preventing one path from succeeding while the other fails.\n- Choose another Peach passkey now opens Peach even when Samsung omits the chooser request attachment, instead of refreshing the Credential Manager picker in a loop."},{"version":"2.16.0","notes":"## Highlights\n- Credential Manager now offers “Choose another Peach passkey,” with a searchable list of passkeys GitHub can accept.\n\n## Fixes\n- Tapping the picker’s Sign in button now preserves Android’s authenticated passkey request after returning from Peach, matching the already-working passkey-row path."},{"version":"2.15.10","notes":"## Fixes\n- Passkeys selected in Firefox now return a consistent browser authentication response instead of being rejected immediately by sites such as GitHub."},{"version":"2.15.9","notes":"## Fixes\n- Passkeys selected after unlocking Peach now complete sign-in instead of closing without authenticating.\n- Inline Peach autofill suggestions appear again in supported browser login fields on Gboard and Samsung Keyboard."},{"version":"2.15.7","notes":"# Peach Android 2.15.7\n\n## Fixes\n\n- Restores the Peach inline autofill picker on Samsung\/Gboard by keeping the authenticated picker dataset visible in the keyboard suggestion strip while the vault is locked.\n- Restores passkey choices after unlocking Peach through Credential Manager, so GitHub passkey sign-in can present a manual Peach selection instead of returning an empty sign-in list.\n- Keeps vault credentials protected while locked; search and the “Remember & fill” choice remain available after unlocking and selecting an entry."},{"version":"2.15.6","notes":"Peach Android 2.15.6 restores the established update workflow. The updater accepts Kepr release metadata without requiring a separate metadata-signing key while continuing to verify the downloaded APK checksum and package identity. The Credential Manager unlock handoff fix remains included."},{"version":"2.15.5","notes":"Peach Android 2.15.5 fixes the Credential Manager “Unlock Peach” handoff. When a login popup opens Peach while the vault is locked, master-password and biometric authentication now return the matching saved login to the requesting app instead of abandoning the request and requiring manual copy\/paste. Existing caller\/origin validation and secure-window protections remain in place."},{"version":"2.15.4","notes":"Peach Android 2.15.4 adds V4 vault exports while retaining V3 reads, extends password generation to 256 characters, and adds configurable memorable passphrases. Update the browser extension before using V4 exports."},{"version":"2.14.79","notes":"Fixes: the lock screen now uses the appearance you chose — text size, UI scale, and accent — instead of falling back to defaults until you authenticate. Previously the sign-in screen rendered at Auto and then resized the moment you unlocked. This follows v2.14.78, which fixed a second lock screen appearing after sign-in on wide screens when UI scale is set to Large, and v2.14.77, which rebuilt PIN unlock on device hardware and closed the autofill and site-icon findings. The in-app changelog lists everything since the version you had."},{"version":"2.14.78","notes":"Fixes: unlocking no longer bounces back to a second lock screen on wide screens when UI scale is set to Large. The screen-size setting was being applied in a way that rebuilt the whole app interface a moment after sign-in, discarding your place and asking you to authenticate again. Unfolding or rotating the device no longer interrupts sign-in. This follows v2.14.77, which rebuilt PIN unlock on device hardware and closed the autofill and site-icon findings; if you are updating from an older version, the in-app changelog lists everything since the version you had."},{"version":"2.14.77","notes":"Security: PIN unlock is rebuilt on device hardware — the vault key is sealed by the Android Keystore instead of by the PIN, and each attempt spends a hardware-limited gate, so a copied copy of app storage can no longer be used to guess your PIN offline. Autofill no longer generates or copies a two-factor code before you choose an entry, and no longer trusts a claimed website unless the requesting app is a verified browser. Site icons now ask before switching on and say that enabling them shares your vault's site list with DuckDuckGo. The encrypted sync spool is excluded from cloud backup and device transfer. Biometric escrow keys must report a hardware-backed security level. Bouncy Castle is upgraded to 1.84. Debug builds no longer log codes or entry titles. Sync handshakes reject small-order Diffie-Hellman keys. Fixes: unfolding or rotating no longer signs you out; onboarding offers create-a-vault as an explicit choice and labels pair-with-another-device with a Pro badge. PIN users: you may be asked to set your PIN up again, since the old PIN material was not hardware-protected and is removed on upgrade. Your master password is unaffected and always works; if a device cannot enforce limited PIN attempts, PIN unlock stays off there."},{"version":"2.14.64","notes":"## Highlights\n- Entry editing is cleaner: URLs stay with the URL field, password history stays with the password field, and expanded options align naturally inside the card.\n- Additional URL controls are easier to use, and the entry ghostmark keeps its original alignment while flowing naturally off-screen.\n\n## Fixes\n- The TOTP card border is now the countdown ring itself: the accent drains smoothly from right to left and refills from left to right when the code resets."},{"version":"2.14.54","notes":"## Highlights\n- Appearance now offers Compact, Auto, and Large UI sizing controls.\n- Auto sizing keeps foldables comfortably enlarged while preventing tablet controls from inflating across the screen.\n\n## Fixes\n- Entry editing no longer offers Notes as a standalone entry type; existing attached notes remain editable.\n- URL additions now stay with the URL field, and password generation\/history stay with the password field.\n- The entry ghostmark now continues naturally off the screen instead of ending at a hard clipped edge."},{"version":"2.14.51","notes":"## Highlights\n- The Notes toolbar now matches the browser with headings, quotes, lists, strikethrough, and horizontal rules.\n- Rich note formatting persists when you leave and reopen a note.\n- Entry editing has cleaner password tools and clearer tag suggestions.\n\n## Fixes\n- Launcher shortcuts now continue to New Entry, Search, or Pair after you unlock Peach.\n- Password reveal and copy actions no longer touch each other."},{"version":"2.14.49","notes":"## Fixes\n- Username and email suggestion lists in Entry Edit now scroll inside their own bounded popup instead of moving the whole editor at the same time."},{"version":"2.14.46","notes":"## Highlights\n- Add optional PIN unlock alongside the master password. PIN setup and removal are protected by master-password confirmation, and the lock screen remembers the last method you used.\n- Entry Detail is cleaner: tags stay in the Vault List, while the TOTP card uses a smooth draining and refilling accent border.\n\n## Fixes\n- Changing the master password now invalidates the PIN so it cannot unlock an older vault key."},{"version":"2.14.38","notes":"## Fixes\n- Entry details now fade content that passes behind the bottom controls, keeping the previous\/next arrows and navigation actions clear while scrolling."},{"version":"2.14.34","notes":"## Highlights\n- Entry view has a calmer, cleaner layout with one unified credential card and thumb-friendly bottom navigation.\n- Notes and Entry now share the same cohesive visual language, and the bottom action toggles directly between them.\n- Edit, Tags, Advanced, and Notes surfaces now use the same card styling and typography.\n\n## Fixes\n- Edit and Move to Trash are visible without scrolling, while Tags stays below the fold.\n- Garamond ghost marks now render consistently and without clipping.\n- Empty notes are no longer saved, the original Vault search layout is restored, and the screenshot permission toggle now works correctly.\n- Bottom-bar icon sizing, spacing, and Notes transitions are now consistent."},{"version":"2.14.18","notes":"## Highlights\n\n- The lock screen now lets the animated PeachScript background stand on its own, removing the extra static rune row beneath the unlock heading for a calmer, clearer view.\n\n## Fixes\n\n- No other behavior changes in this release."},{"version":"2.14.17","notes":"## Highlights\n\n- Sync controls and Pro lock wordmark polish: UI and interaction refinements for a cleaner, more responsive experience.\n\n## Fixes\n\n- UI and interaction polish for Sync controls and the Pro lock wordmark."},{"version":"2.14.16","notes":"## Highlights\n- Background sync can now continue safely after Peach locks. Your vault keys and plaintext entries are cleared; Sync uses only a bounded encrypted cache protected by Android Keystore.\n- Updates received while Peach is locked stay encrypted and are applied only after you unlock.\n- You can now rename paired devices in Sync settings. Nicknames stay on this device and do not change the other device, its secure identity, or sync behavior.\n\n## Fixes\n- Locked Sync now enforces a total inbox limit across repeated sessions, preventing unusual or malicious peer traffic from growing stored data without bound."},{"version":"2.14.13","notes":"## Highlights\n- The lock screen now has the same subtle animated PeachScript rune field as onboarding, adding a little more life while you unlock.\n\n## Fixes\n- No other behavior changes in this release."},{"version":"2.14.12","notes":"## Fixes\n- Peach Sync now truncates unusually long device names to 64 characters, matching the browser extension. This keeps paired-device lists and sync security notifications readable and prevents abnormal names from distorting them."},{"version":"2.14.11","notes":"## Fixes\n- Fixed a crash triggered when Facebook Messenger asks for autofill. On the Galaxy Z Fold 7 this was causing the repeated \"Peach keeps stopping\" messages. Updating fixes it — you don't need to clear the cache or any data."},{"version":"2.14.10","notes":"## Notes\n- No behavior change from v2.14.9. This release pins the lock-screen routing logic with internal unit tests so the \"+ Create new entry\" autofill fix from v2.14.9 can't quietly regress."},{"version":"2.14.9","notes":"## Fixes\n- Tapping \"+ Create new entry\" from the autofill picker used to land you back in the vault list after unlocking instead of opening the new-entry editor with the URL pre-filled. LockScreen and the NavHost were both reacting to the unlock transition; the NavHost consumed the autofill request first, which flipped the LockScreen guard key and re-fired its \"where to land?\" branch — overwriting the editor with a `popUpTo(0)`."},{"version":"2.14.7","notes":"## Highlights\n- Peach now copies the 2FA code to your clipboard the moment it auto-fills a login with TOTP, as a safety net. Long-press the 2FA field and tap Paste if the chip ever doesn't show.\n\n## Fixes\n- A clipboard-service hiccup could leave the 2FA flow with no chips at all; the clipboard copy is now wrapped defensively so the rest of the autofill flow keeps working."},{"version":"2.14.6","notes":"## Highlights\n- The 2FA chip now appears in the keyboard suggestion strip on every login page, including the 2FA-only screen that opens after a username\/password submit. Tapping it drops a fresh code into the 2FA field.\n- Removed the unused \"+ Save to Peach\" inline chip. New-entry creation lives in the picker activity's explicit action, so you can still add a login straight from autofill.\n\n## Fixes\n- The OTP chip was being buried in the keyboard overflow menu whenever the system offered only one inline suggestion slot — i.e. exactly the 2FA-only pages where you need it most. The picker and OTP chips now share the inline strip correctly on every page layout."},{"version":"2.14.5","notes":"## Highlights\n- The 2FA chip now shows the seconds left in its TOTP window directly on the chip (\"2FA · 23s\"). When the current code rolls past 0 the chip reads \"2FA · expired\"; refocusing the 2FA field rebuilds it with a fresh code.\n- Tapping the 2FA chip fills the field in one motion, the same way as the username\/password chip.\n- Creating a new login from an autofillable form lands you in the new-entry editor with the URL pre-filled (previously opened the random last-viewed entry).\n\n## Fixes\n- The \"+ Save to Peach\" chip no longer races the unlock screen — auth-then-create now lands on the new-entry editor with the origin URL prefilled instead of dropping you on a random EntryDetail.\n- 2FA \/ OTP chip detection now matches common labels in the wild (verification, security code, token, etc.)."},{"version":"2.14.4","notes":"## Highlights\n- Inline TOTP chip now reads `2FA` instead of the entry name, so the digits can't be mistaken for a password. The chip title still shows the actual 6-digit code (e.g. `482 901`) — the favicon\/initial on the left identifies the entry.\n- Passkey \/ Credential Manager is on by default for new installs. Existing users keep their stored setting.\n- Multi-part login flow keeps the smart TOTP timeout surfacing: refocusing the 2FA field after the 30-second code rotation gives the fresh chip automatically."},{"version":"2.14.3","notes":"## Highlights\n- New-note button moved to the top bar in Notes mode (right next to Search). With lots of notes you used to have to scroll past them all to start writing; now the + is always one tap away."},{"version":"2.14.1","notes":"## Fixes\n- Autofill chips now actually appear in the keyboard's suggestion row. v2.14.0 shipped the keyboard-row chips, but they were silently disabled: Peach's autofill configuration never declared inline-suggestion support, so keyboards were never offered the chip slot at all. Fixed and verified on an Android 16 emulator with Gboard; Samsung Keyboard and other Android 11+ keyboards use the same standard path."},{"version":"2.14.0","notes":"## Highlights\n- Peach now appears in Android's built-in sign-in picker on Android 14+: tap a password field and your matching Peach logins show up in the system sheet and in your keyboard's suggestion row, alongside passkeys.\n- New logins can be saved straight into Peach from the system 'Save password?' prompt, in any app or website.\n- Keyboard suggestions get a small per-site monogram icon, and the 'Search Peach…' chip now always stays reachable — even when the row is full.\n- New privacy setting 'Hide autofill previews': when on, keyboard suggestions show only Peach and the site's domain — never your entry names or usernames."},{"version":"2.10.23","notes":"## Fixes\n- The vault settings card no longer draws its rows on top of each other after yesterday's tidy-up. Entries, maintenance, and data rows now stack properly inside their collapsible groups."},{"version":"2.10.22","notes":"## Highlights\n- The vault settings card is tidied up: settings now sit in collapsible groups with clear headings, and vault history and the advanced danger-zone options stay folded away until you need them.\n- New changelog button next to check for updates — browse the release notes for every Peach update, newest first, going all the way back.\n\n## Fixes\n- The what's-new notes shown after an update now cover everything that changed since the version you were last running, not just the latest release."},{"version":"2.10.20","notes":"Maintenance release — no user-visible changes.\n\n## Fixes\n- Restored the app's automated quality checks to fully green, so every future release is verified before it ships.\n- Extended screenshot-protection coverage checks to the entry detail and editing screens (release builds were already fully protected).\n\nVault, sync, autofill, and passkey behavior are unchanged from 2.10.19."},{"version":"2.10.19","notes":"## Highlights\n- Passkeys are now locked to the site or app that created them — other apps on your device can no longer request or use your passkeys.\n\n## Fixes\n- The autofill \"Create new entry\" shortcut can no longer be launched by other apps with pre-filled details.\n- Restoring a malformed or unusually large Codex backup now fails cleanly instead of exhausting memory.\n- Entries received over sync are now validated: blank or hollow entries are dropped, and password history is kept to its 50-entry cap."},{"version":"2.10.15","notes":"## Highlights\n- New \"Site icons\" setting in Settings \u003e Appearance: turn real site icons in the vault list on or off. Off by default — the initials look is cleaner and more consistent. When on, icons are fetched through DuckDuckGo's icon service and cached on your device.\n\n## Fixes\n- Autofill no longer appears where credentials don't belong. The Peach chip could pop up on ordinary text fields — like Discord's message box — now suggestions appear only on login, signup, 2FA, and card forms."},{"version":"2.10.12","notes":"## Highlights\n- Autofill finally suggests your logins everywhere. Previously almost every site showed as \"unverified\" and Peach withheld your matches — now matching logins are shown by site domain or app name, and you decide what to fill.\n- Remember this site: when you manually search for a login in the autofill picker, Peach offers to save it for that site or app so it's suggested automatically next time.\n- Card autofill: Peach detects card payment forms and fills your saved cards.\n- Signup help: on signup forms Peach offers to generate a strong password sized to what the site accepts, and lists your saved emails\/usernames so you can tap one in.\n- Passkey import: bring in passkeys from Bitwarden JSON and Google Password Manager (CXF) exports; stray passkey-only entries are merged into their logins on unlock.\n- Advanced vault health (Peach Pro): a prioritized fix queue with per-entry scores for weak, reused, old, and breached passwords.\n- Real site favicons now appear in the vault list — fetched directly from each site itself and cached.\n- TOTP codes now fill split digit-box 2FA fields, one digit per box.\n- New text size setting (small\/medium\/large) in Settings \u003e Appearance.\n\n## Fixes\n- The password-history toggle on the entry detail screen was hidden until an entry already had history — it's always visible now.\n- The autofill save prompt was gated behind \"verified\" sites — Peach now always offers to save new logins."},{"version":"2.9.35","notes":"## Highlights\n- Changelog now shows all changes between your previous version and this one, not just the latest update.\n- Swiping between entries uses a smooth fade instead of a jarring jump.\n\n## Fixes\n- Vault-locked sync indicator is now amber (matching the browser) instead of red.\n- Settings card titles sit more balanced in the stack.\n- Entry view search bar border restored."},{"version":"2.9.34","notes":"## Highlights\n- When the notes filter is on, the + button creates a new note instead of a new entry.\n\n## Fixes\n- In-app updates no longer fail with an identity mismatch — versionCode now auto-increments with every release.\n- Screenshots work on entry screens when the toggle is enabled.\n- Scrolling content fades gently behind the search bar instead of hard-clipping."},{"version":"2.9.33","notes":"## Fixes\n- \"Allow screenshots\" now works on entry screens — they were overriding the toggle.\n- The search bar at the bottom of entry view no longer has a visible border. Scrolling content fades out gently instead of being hard-clipped."},{"version":"2.9.32","notes":"## Fixes\n- Settings deck sits 1dp above the version label now — Peach Pro card buttons should no longer clip on wide\/tall screens."},{"version":"2.9.31","notes":"## Highlights\n- New \"Allow screenshots\" toggle in Settings → Protection. Off by default; enable it if you need to capture the app for support or documentation.\n- The settings stack now sits closer to the version label — the Peach Pro card buttons are no longer clipped on wide\/tall screens (Galaxy Z Fold 7).\n\n## Fixes\n- The vault search bar no longer has a visible border that could clip entry text while scrolling."},{"version":"2.9.28","notes":"## Highlights\n- docs: continuity — long-press multi-select fixed (v2.9.28), release-notes guidance added\n\n## Fixes\n- Published peach-android 2.9.28 from save a0476f1fd4cd.\n"},{"version":"2.9.26","notes":"## Highlights\n- docs: continuity — mark Fold 7 deck fix done, record notification root cause\n\n## Fixes\n- Published peach-android 2.9.26 from save 5f2c139ad090.\n"},{"version":"2.9.22","notes":"## Highlights\n- fix: recovery escrow missing on adopted vaults + re-auth gate for viewing words (v2.9.22)\n\n## Fixes\n- Published peach-android 2.9.22 from save 5888cb598ccc.\n"},{"version":"2.9.19","notes":"## Highlights\n- fix: receiver applies device manifest during adoption (v2.9.19)\n\n## Fixes\n- Published peach-android 2.9.19 from save 6ee5aa4e778d.\n"},{"version":"2.9.20","notes":"## Highlights\n- fix: accept kepr releases\/latest blake3\/sha256 artifact fields (v2.9.20)\n\n## Fixes\n- Published peach-android 2.9.20 from save 6bc0390a2127.\n"},{"version":"2.9.14","notes":"## Highlights\n- chore: continuity for v2.9.13 (version+ABI in APK filename)\n\n## Fixes\n- Published peach-android 2.9.14 from save ad746cc8f855.\n"},{"version":"2.9.13","notes":"## Highlights\n- feat: include version+ABI in APK filename via kepr.build {version}\/{platform} tokens (v2.9.13)\n\n## Fixes\n- Published peach-android 2.9.13 from save 40ead9f75efb.\n"},{"version":"2.9.12","notes":"## Highlights\n- feat: Publish ABI-aware Android release updates (v2.9.12)\n\n## Fixes\n- Published peach-android 2.9.12 from save 65238bd4512a.\n"}]\ No newline at end of file

view file

tests/fixtures/kepr2/api_peach-android_releases_history.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-83+access-control-allow-origin: *

view file

tests/fixtures/kepr2/api_peach-android_releases_latest.body+1 −0
@@ -0,0 +1 @@1+{"version":"2.17.43","notes":"Peach Android v2.17.43 makes encrypted Sync dependable throughout the day. Saving a login, note, card, or passkey now prompts an immediate peer check while periodic background reconciliation remains the fallback. The long-running Sync listener no longer uses Androids time-limited data-sync service category, preventing the system crashes seen on Android 15, and its notification now describes active checking without promising a connection that has not been established. This release also clears remembered unlock text before navigation, expands real-device Codex recovery assurance across a diverse 250-entry vault, and strengthens bounded cross-client diagnostics, rollback handling, and build verification.","platforms":{"android-arm64":{"url":"https://kepr.uk/peach-android/releases/2.17.43/android-arm64","blake3":"079b7bd8bfdb00e37ea8deea2a7475f882444341a2dc23753d06c672a35ce6e4","sha256":"47b78fbcc70b8417bdbc166db71d267b7086d0db6d25e5361119d459a8f91ce7","provenance":{"version":"2.17.43","platform":"android-arm64","checksum":"blake3:079b7bd8bfdb00e37ea8deea2a7475f882444341a2dc23753d06c672a35ce6e4","source":"koh-offer"},"signature":""},"android-x86":{"url":"https://kepr.uk/peach-android/releases/2.17.43/android-x86","blake3":"e2b09eb809b0bf0b57b80ecde53dd805d594d415f1bc1c39f651a6be9f3c92ac","sha256":"e6fa9309018c2c039aca2eadbb61048bed9ff8ea04b76a39de5c9de98c0ef5f1","provenance":{"version":"2.17.43","platform":"android-x86","checksum":"blake3:e2b09eb809b0bf0b57b80ecde53dd805d594d415f1bc1c39f651a6be9f3c92ac","source":"koh-offer"},"signature":""}}}\ No newline at end of file

view file

tests/fixtures/kepr2/api_peach-android_releases_latest.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-83+access-control-allow-origin: *

view file

tests/fixtures/kepr2/api_peach-relay_releases_history.body+1 −0
@@ -0,0 +1 @@1+{"error":"not_found","message":"no releases"}\ No newline at end of file

view file

tests/fixtures/kepr2/api_peach-relay_releases_history.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 404 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/api_peach-relay_releases_latest.body+1 −0
@@ -0,0 +1 @@1+{"error":"not_found","message":"no releases"}\ No newline at end of file

view file

tests/fixtures/kepr2/api_peach-relay_releases_latest.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 404 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/haven_meta.body+1 −0
@@ -0,0 +1 @@1+{"repo":"haven","save_count":46,"line_count":5384,"last_save_at":1789850374,"latest_release":"0.6.1","latest_version":"v0.7.0","description":"A lightweight macOS menu bar app for finding, setting, and managing desktop wallpapers from Wallhaven.","languages":"Swift · Icns · Entitlements · Plist · Resolved","categories":"utility"}\ No newline at end of file

view file

tests/fixtures/kepr2/haven_meta.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/haven_releases_0.6.1_checksums.txt.body+7 −0
@@ -0,0 +1,7 @@1+# haven 0.6.12+# built by kepr3+4+sha256:67b715c20b64779615564a811c58093893d6e80cc9a997b4600f3fb68cdbfce0  haven-macos-aarch645+sha256:2e844c00cdfe9efac2706c83723542ac8fc46fdb39b49da16ec98641a6fdf72a  haven-macos-x86_646+blake3:7c2ea86ca75df33ff018019395be0b6feb9a3deba1d00623e23c9ec2772eb5a8  haven-macos-aarch647+blake3:73733480227ed174977af99428d3e622cdf6285836b4ef53e58bd7e120adea24  haven-macos-x86_64

view file

tests/fixtures/kepr2/haven_releases_0.6.1_checksums.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/haven_releases_0.6.1_haven-macos-aarch64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="Haven.app.zip"

view file

tests/fixtures/kepr2/haven_releases_0.6.1_macos-aarch64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="Haven.app.zip"

view file

tests/fixtures/kepr2/haven_releases_latest.body+0 −0

view file

tests/fixtures/kepr2/haven_releases_latest.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 302 2+location: /haven/releases/0.6.1

view file

tests/fixtures/kepr2/haven_releases_latest_version.txt.body+1 −0
@@ -0,0 +1 @@1+0.6.1\ No newline at end of file

view file

tests/fixtures/kepr2/haven_releases_latest_version.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/haven_update-info.body+1 −0
@@ -0,0 +1 @@1+{"head":null,"latest_build":{"version":"0.6.1","platforms":{"macos-aarch64":{"url":"https://kepr.uk/haven/releases/0.6.1/haven-macos-aarch64","blake3":"7c2ea86ca75df33ff018019395be0b6feb9a3deba1d00623e23c9ec2772eb5a8"},"macos-x86_64":{"url":"https://kepr.uk/haven/releases/0.6.1/haven-macos-x86_64","blake3":"73733480227ed174977af99428d3e622cdf6285836b4ef53e58bd7e120adea24"}}}}\ No newline at end of file

view file

tests/fixtures/kepr2/haven_update-info.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/kepr_meta.body+1 −0
@@ -0,0 +1 @@1+{"repo":"kepr","save_count":1485,"line_count":76018,"last_save_at":1788471198,"latest_release":"2.0.16","latest_version":"v2.0.19","description":"A self-hosted source hosting platform for Koh repositories. Web presence, releases, and full history for every project — on a machine you own, with nothing on infrastructure you don't control. Source hosting that's actually yours.","languages":"Zig · TypeScript · JavaScript · C · Nix · SQL · Pem","categories":"source host"}\ No newline at end of file

view file

tests/fixtures/kepr2/kepr_meta.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/kepr_releases_2.0.16_checksums.txt.body+7 −0
@@ -0,0 +1,7 @@1+# kepr 2.0.162+# built by kepr3+4+sha256:16f60e3d601c386bb0b7e0efdef1c17f3a7440b0020e7cc9f35e7f42c7db5383  kepr-linux-aarch645+sha256:447a5306f383554dcaa494ad1eaddf3a10eda41ffffbd1a19edd083b8eb314ff  kepr-linux-x86_646+blake3:4d07177c429232e6c45bb7c53dd3ecb499058ad022f5eb95d786a61ca2103436  kepr-linux-aarch647+blake3:0618ffe6ed042effa0966368c232eeddd46ed23eaa5660dee324229a93f4ab13  kepr-linux-x86_64

view file

tests/fixtures/kepr2/kepr_releases_2.0.16_checksums.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/kepr_releases_2.0.16_kepr-linux-aarch64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="kepr-linux-aarch64"

view file

tests/fixtures/kepr2/kepr_releases_2.0.16_linux-aarch64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="kepr-linux-aarch64"

view file

tests/fixtures/kepr2/kepr_releases_latest.body+0 −0

view file

tests/fixtures/kepr2/kepr_releases_latest.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 302 2+location: /kepr/releases/2.0.16

view file

tests/fixtures/kepr2/kepr_releases_latest_version.txt.body+1 −0
@@ -0,0 +1 @@1+2.0.16\ No newline at end of file

view file

tests/fixtures/kepr2/kepr_releases_latest_version.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/kepr_update-info.body+1 −0
@@ -0,0 +1 @@1+{"head":null,"latest_build":{"version":"2.0.16","platforms":{"linux-aarch64":{"url":"https://kepr.uk/kepr/releases/2.0.16/kepr-linux-aarch64","blake3":"4d07177c429232e6c45bb7c53dd3ecb499058ad022f5eb95d786a61ca2103436"},"linux-x86_64":{"url":"https://kepr.uk/kepr/releases/2.0.16/kepr-linux-x86_64","blake3":"0618ffe6ed042effa0966368c232eeddd46ed23eaa5660dee324229a93f4ab13"}}}}\ No newline at end of file

view file

tests/fixtures/kepr2/kepr_update-info.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/koh_meta.body+1 −0
@@ -0,0 +1 @@1+{"repo":"koh","save_count":519,"line_count":27860,"last_save_at":1789517611,"latest_release":"2.1.0","latest_version":"v2.1.16","description":"Version control designed for the solo developer. You can learn it in five minutes. Every koh save is a complete snapshot of your project. Every file. Reversible with one command. Two lanes: dev to experiment freely, main to ship. Extraordinarily fast. \n\nhttps:\/\/koh.asha.software","languages":"Zig · Shell · C","categories":"version control"}\ No newline at end of file

view file

tests/fixtures/kepr2/koh_meta.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/koh_releases_2.1.0_checksums.txt.body+11 −0
@@ -0,0 +1,11 @@1+# koh 2.1.02+# built by kepr3+4+sha256:73fb735db9ea6119ced2062fe8174bf95f3fb85b95323fa4b1e720e4d65b19f6  koh-linux-aarch645+sha256:b8caf8f9ffb8eadb2c9238520469d2ea8120730cba9117ad93aebd413691f163  koh-linux-x86_646+sha256:552009199e0212cd2300528b927c583547c18af96e247150c4934bc814687e32  koh-macos-aarch647+sha256:5866b6605537a823ca6e7584fabca68d3b423dc23fbb5a82972f7279227cdc44  koh-macos-x86_648+blake3:ef867176ec7865b8f694b05999f96ca0a6143c28cb1de19ff5234f127c1c34a7  koh-linux-aarch649+blake3:ddee5df771bee96e5d44dc6ad6f4e52ab49e936cb507ce7600b705f35aece298  koh-linux-x86_6410+blake3:ec20d8f749c936bed61bca70d205931055331d4d5d9ad1f5e77536a0ed169a6f  koh-macos-aarch6411+blake3:0ffa3f7e2a5a923c01b22b0317bcfa8e18bca8c9da2551e98093f99e8784fa97  koh-macos-x86_64

view file

tests/fixtures/kepr2/koh_releases_2.1.0_checksums.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/koh_releases_2.1.0_koh-linux-x86_64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="koh-linux-x86_64"

view file

tests/fixtures/kepr2/koh_releases_2.1.0_linux-x86_64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="koh-linux-x86_64"

view file

tests/fixtures/kepr2/koh_releases_latest.body+0 −0

view file

tests/fixtures/kepr2/koh_releases_latest.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 302 2+location: /koh/releases/2.1.0

view file

tests/fixtures/kepr2/koh_releases_latest_version.txt.body+1 −0
@@ -0,0 +1 @@1+2.1.0\ No newline at end of file

view file

tests/fixtures/kepr2/koh_releases_latest_version.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/koh_update-info.body+1 −0
@@ -0,0 +1 @@1+{"head":null,"latest_build":{"version":"2.1.0","platforms":{"linux-aarch64":{"url":"https://kepr.uk/koh/releases/2.1.0/koh-linux-aarch64","blake3":"ef867176ec7865b8f694b05999f96ca0a6143c28cb1de19ff5234f127c1c34a7"},"linux-x86_64":{"url":"https://kepr.uk/koh/releases/2.1.0/koh-linux-x86_64","blake3":"ddee5df771bee96e5d44dc6ad6f4e52ab49e936cb507ce7600b705f35aece298"},"macos-aarch64":{"url":"https://kepr.uk/koh/releases/2.1.0/koh-macos-aarch64","blake3":"ec20d8f749c936bed61bca70d205931055331d4d5d9ad1f5e77536a0ed169a6f"},"macos-x86_64":{"url":"https://kepr.uk/koh/releases/2.1.0/koh-macos-x86_64","blake3":"0ffa3f7e2a5a923c01b22b0317bcfa8e18bca8c9da2551e98093f99e8784fa97"}}}}\ No newline at end of file

view file

tests/fixtures/kepr2/koh_update-info.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/nina_meta.body+1 −0
@@ -0,0 +1 @@1+{"repo":"nina","save_count":179,"line_count":10578,"last_save_at":1783006630,"latest_release":"3.4.14","latest_version":"v3.4.14","description":"NixOS is powerful, but it can be a lot. Nina keeps the whole workflow — packages, options, rebuilds, services, remote machines — right at the prompt. Written in Zig, zero dependencies.\n\nhttps:\/\/nina.asha.software","languages":"Zig · Kdl","categories":"utility"}\ No newline at end of file

view file

tests/fixtures/kepr2/nina_meta.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/nina_releases_3.4.14_checksums.txt.body+11 −0
@@ -0,0 +1,11 @@1+# nina 3.4.142+# built by kepr3+4+sha256:038e90cf755fabee06e6aa7a996baa85c220911e349f318759ad6b2db5216e07  nina-linux-aarch645+sha256:b6c2d6c534322cb2cffbd034e46901537bf55a42a556bb08ba9103c112e7b250  nina-linux-x86_646+sha256:c3913dd174a6972d1b7c28ce5c22809264fc1e729f7505caf914d0d4f4c946ae  nina-macos-aarch647+sha256:6a30801cf500ed70eb62bfbd0c48937654f17d16ab04185afd766f856a401ff4  nina-macos-x86_648+blake3:28f7270461069a4031f0c0a047806c70b451bb8853026037a9dfa3285b789fc1  nina-linux-aarch649+blake3:3111e8dc2557e7a26359f018f65cfa527f37fa73d1f10e2a1f42b009f42417f4  nina-linux-x86_6410+blake3:4e9d45baf91fc4b2eb4d6a33ec87a0c219b593ce830a2ce8f123aa75e12cbf40  nina-macos-aarch6411+blake3:2af6d435c3548e2b74cc3f757edf9f5c0a160f54e9a4704151b296a03015a377  nina-macos-x86_64

view file

tests/fixtures/kepr2/nina_releases_3.4.14_checksums.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/nina_releases_3.4.14_linux-aarch64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="nina-linux-aarch64"

view file

tests/fixtures/kepr2/nina_releases_3.4.14_nina-linux-aarch64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="nina-linux-aarch64"

view file

tests/fixtures/kepr2/nina_releases_latest.body+0 −0

view file

tests/fixtures/kepr2/nina_releases_latest.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 302 2+location: /nina/releases/3.4.14

view file

tests/fixtures/kepr2/nina_releases_latest_version.txt.body+1 −0
@@ -0,0 +1 @@1+3.4.14\ No newline at end of file

view file

tests/fixtures/kepr2/nina_releases_latest_version.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/nina_update-info.body+1 −0
@@ -0,0 +1 @@1+{"head":null,"latest_build":{"version":"3.4.14","platforms":{"linux-aarch64":{"url":"https://kepr.uk/nina/releases/3.4.14/nina-linux-aarch64","blake3":"28f7270461069a4031f0c0a047806c70b451bb8853026037a9dfa3285b789fc1"},"linux-x86_64":{"url":"https://kepr.uk/nina/releases/3.4.14/nina-linux-x86_64","blake3":"3111e8dc2557e7a26359f018f65cfa527f37fa73d1f10e2a1f42b009f42417f4"},"macos-aarch64":{"url":"https://kepr.uk/nina/releases/3.4.14/nina-macos-aarch64","blake3":"4e9d45baf91fc4b2eb4d6a33ec87a0c219b593ce830a2ce8f123aa75e12cbf40"},"macos-x86_64":{"url":"https://kepr.uk/nina/releases/3.4.14/nina-macos-x86_64","blake3":"2af6d435c3548e2b74cc3f757edf9f5c0a160f54e9a4704151b296a03015a377"}}}}\ No newline at end of file

view file

tests/fixtures/kepr2/nina_update-info.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/peach-android_meta.body+1 −0
@@ -0,0 +1 @@1+{"repo":"peach-android","save_count":1081,"line_count":75375,"last_save_at":1790097880,"latest_release":"2.17.43","latest_version":"v2.17.43","description":"Mobile companion for the Free Open Source Password Manager","languages":"Kotlin · Shell · Python · Gradle · Java · Properties · Jar · Lockfile · Pro · Mmd · Keys","categories":"password manager"}\ No newline at end of file

view file

tests/fixtures/kepr2/peach-android_meta.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/peach-android_releases_2.17.43_android-arm64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="peach-android-2.17.43-android-arm64.apk"

view file

tests/fixtures/kepr2/peach-android_releases_2.17.43_checksums.txt.body+7 −0
@@ -0,0 +1,7 @@1+# peach-android 2.17.432+# built by kepr3+4+sha256:47b78fbcc70b8417bdbc166db71d267b7086d0db6d25e5361119d459a8f91ce7  peach-android-android-arm645+sha256:e6fa9309018c2c039aca2eadbb61048bed9ff8ea04b76a39de5c9de98c0ef5f1  peach-android-android-x866+blake3:079b7bd8bfdb00e37ea8deea2a7475f882444341a2dc23753d06c672a35ce6e4  peach-android-android-arm647+blake3:e2b09eb809b0bf0b57b80ecde53dd805d594d415f1bc1c39f651a6be9f3c92ac  peach-android-android-x86

view file

tests/fixtures/kepr2/peach-android_releases_2.17.43_checksums.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/peach-android_releases_2.17.43_peach-android-android-arm64.headers+3 −0
@@ -0,0 +1,3 @@1+HTTP/2 200 2+content-type: application/octet-stream3+content-disposition: attachment; filename="peach-android-2.17.43-android-arm64.apk"

view file

tests/fixtures/kepr2/peach-android_releases_latest.body+0 −0

view file

tests/fixtures/kepr2/peach-android_releases_latest.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 302 2+location: /peach-android/releases/2.17.43

view file

tests/fixtures/kepr2/peach-android_releases_latest_version.txt.body+1 −0
@@ -0,0 +1 @@1+2.17.43\ No newline at end of file

view file

tests/fixtures/kepr2/peach-android_releases_latest_version.txt.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: text/plain; charset=UTF-8

view file

tests/fixtures/kepr2/peach-android_update-info.body+1 −0
@@ -0,0 +1 @@1+{"head":null,"latest_build":{"version":"2.17.43","platforms":{"android-arm64":{"url":"https://kepr.uk/peach-android/releases/2.17.43/peach-android-android-arm64","blake3":"079b7bd8bfdb00e37ea8deea2a7475f882444341a2dc23753d06c672a35ce6e4"},"android-x86":{"url":"https://kepr.uk/peach-android/releases/2.17.43/peach-android-android-x86","blake3":"e2b09eb809b0bf0b57b80ecde53dd805d594d415f1bc1c39f651a6be9f3c92ac"}}}}\ No newline at end of file

view file

tests/fixtures/kepr2/peach-android_update-info.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/peach-relay_meta.body+1 −0
@@ -0,0 +1 @@1+{"repo":"peach-relay","save_count":99,"line_count":6507,"last_save_at":1788287181,"latest_release":null,"latest_version":"v0.3.24","description":"End to End encrypted relay for Peach Password Manager. Never reads nor stores any vault or user data.","languages":"TypeScript · Pem · Nix","categories":"utility"}\ No newline at end of file

view file

tests/fixtures/kepr2/peach-relay_meta.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/peach-relay_update-info.body+1 −0
@@ -0,0 +1 @@1+{"head":null,"latest_build":null}\ No newline at end of file

view file

tests/fixtures/kepr2/peach-relay_update-info.headers+2 −0
@@ -0,0 +1,2 @@1+HTTP/2 200 2+content-type: application/json; charset=UTF-8

view file

tests/fixtures/kepr2/record.sh+39 −0
@@ -0,0 +1,39 @@1+#!/bin/sh2+# Records Kepr 2's §22.4 compatibility routes from kepr.uk, GET only, into this folder:3+# <slug>.headers (status line plus the headers the contract tests read) and <slug>.body.4+# Downloads are recorded without their body (`--max-filesize 1` stops before the file).5+# Re-run before cutover (§28) and review the diff.6+set -eu7+out=$(cd "$(dirname "$0")" && pwd)8+raw=$(mktemp)9+rec() { # path [nobody]10+  slug=$(printf '%s' "$1" | sed 's#^/##; s#/#_#g')11+  if [ "${2:-}" = nobody ]; then12+    curl -s -D "$raw" -o /dev/null --max-filesize 1 "https://kepr.uk$1" || true13+  else14+    curl -s -D "$raw" -o "$out/$slug.body" "https://kepr.uk$1"15+  fi16+  { head -1 "$raw" | tr -d '\r'; grep -i -E '^(content-type|access-control-allow-origin|location|cache-control|content-disposition):' "$raw" | tr -d '\r' || true; } > "$out/$slug.headers"17+  echo "$1 -> $(head -1 "$out/$slug.headers")"18+}19+for r in haven kepr koh nina peach-android; do20+  rec /api/$r/releases/latest21+  rec /api/$r/releases/history22+  rec /$r/update-info23+  rec /$r/meta24+  rec /$r/releases/latest25+  rec /$r/releases/latest/version.txt26+  v=$(cat "$out/${r}_releases_latest_version.txt.body")27+  rec /$r/releases/$v/checksums.txt28+  p=$(sed 's/.*"platforms":{"\([^"]*\)".*/\1/' "$out/api_${r}_releases_latest.body")29+  rec /$r/releases/$v/$p nobody30+  rec /$r/releases/$v/$r-$p nobody31+done32+rec /api/koh/releases/latest33+for p in linux-x86_64 macos-aarch64; do rec /api/koh/releases/2.1.0/$p nobody; done34+rec /api/koh/releases/2.1.16/linux-x86_6435+rec /api/peach-relay/releases/latest36+rec /api/peach-relay/releases/history37+rec /peach-relay/meta38+rec /peach-relay/update-info39+rec /api/nowhere/releases/latest

view file