From ea9abdb786c6776d8b24c5e7dc35ff4da6c9ba92 Mon Sep 17 00:00:00 2001 From: Jacob Hagstedt Date: Sun, 25 Oct 2026 09:11:48 +0100 Subject: [PATCH] HANDOFF: v1.0.5 deployed, owner's card connected and link/unlink verified 2026-10-25 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B --- docs/HANDOFF.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index f3377a3..62ef9fd 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -3,8 +3,8 @@ Living document, rewritten in place (never a second copy). A new orchestrator session reads CLAUDE.md, then this. ## 1. Where things stand -- State as of 2026-10-25. **K0 to K3 are all landed.** `main` at `6f63751` (SPEC v0.39, K2's report, D-191 to D-200, design-spec S-23 to S-27, `agent-docs-k2`), after `faeb752` (**K3 landed**: card purchases on the web, W-21 to W-23; recorded in SPEC v0.40 by this pass), `a8f91ee` (**K2 landed**: card purchases on Android, Room 2, S-23 to S-27), `07df30d` (SPEC v0.38, K1's report), `671c00d` (**K1 landed**: card purchases on the server, schema 4, E-36 to E-44), `ae73f58` (SPEC v0.37, D-211), `8b620c8` (the K0 report, SPEC v0.36), `8fa9198` (`infra/build-images.sh` Podman detection), `f15fa23` (`infra/build-images.sh` passes `KVITT_VERSION_CODE`), `4339d01` (the owner's SJ Prio card artwork), `b5114ad` (SPEC v0.35, card purchases), `2ce317f` (the K0 card test app), `5d948f9` (SPEC v0.34) and `5305f37` (W0b web shared follow-ups); before them `07c36d2` (L-10, D-156) and `593c727` (SPEC v0.33, D-156, D-157). This pass (`agent-docs-k3`): SPEC v0.40, K3's report as D-201 to D-207 (D-208 to D-210 unused), `web/README.md` and `prompts/README.md`; `main` with this pass is pushed by the orchestrator after it lands. **Deployed** (owner's report): image `v1.0.4` (git tag `v1.0.4` = `671c00d`, K1's server, schema 4) runs on the Kvitt Pi, so K1's owner steps 1 to 4 are done; image `v1.0.5` (`faeb752`, the web card pages of K3) is being built on the Mac; release APK `kvitt-164` (K2's card screens) is on the Pi since 2026-10-25 for the in-app update. **Deployed and verified 2026-10-24** (owner, D-211): image `v1.0.3` (git tag `v1.0.3` = `8fa9198`, built on the Mac) runs on the Kvitt Pi, `server` and `backup` healthy; the web client is live at `https://kvitt.suorra.duckdns.org/app/`, paired from the laptop browser with a device invite, and the owner reports "All seems to work" for Home and an account, add, edit and delete an expense, CSV export, record and delete a payment, analytics with category drill-down and Insights, the settings pages, revoking the browser from the phone, and the Android Insights section on S-11 against the new server. W0 to W7 are landed and verified (SPEC §11.2, §15). Release 140 (`kvitt-140`, deployed 2026-10-21) ran on both phones until `kvitt-164`; whether the phones have updated is not recorded here (PLAN-K2 §8 step 1 starts with it). Gates: server 356 tests at `671c00d`; contracts-check 157 (17 `match_card_purchase` cases); Android green again at `a8f91ee` (`BUILD SUCCESSFUL`, 791 actionable tasks, 1154 tests, 0 failures; the card examples E-36 to E-44 round-trip, `VectorFilesTest` and `ExampleRoundTripTest` pass), so the pre-commit hook needs no bypass any more; web at `faeb752` 70 files, 684 tests, build ok (`match_card_purchase` ported). -- **Card purchases programme** (owner request and answers 2026-10-24, SPEC v0.35, D-158 to D-176, FR-22, §9.12): each user connects their own SJ Prio Mastercard (SEB Kort) through Enable Banking's restricted production mode with BankID; the server alone holds the key and sessions, fetches purchases up to 4 times a day in the background plus "Uppdatera", and only the card holder sees them (not in `GET /sync`, audit, push or analytics); a fourth bottom destination "Kortköp" (Översikt, Kortköp, Statistik, Inställningar, revising D-048), "Anslut kort" in Settings with the SJ Prio artwork, "Skapa utgift" prefilled into S-7, one-tap links to matching expenses (same amount, ±3 days), "Från kortköp" on account detail; server schema 4 (migration 0004), Room 2, endpoints E-36 to E-44, screens S-23 to S-27, web W-21 to W-23. Plans `PLAN-K0.md` to `PLAN-K3.md`, prompts `prompts/K0.md` to `prompts/K3.md`, written by `agent-a3b7abf183f883261`, landed `b5114ad`. **K0 done** (2026-10-24): the test app (`2ce317f`) ran with the owner on his card; report [`docs/spikes/K0-enable-banking.md`](spikes/K0-enable-banking.md); its answers are SPEC v0.36 (D-177 to D-180). Main findings: the card returns at most 100 transactions per response and never a continuation key, so history is fetched in windows of at most 30 days, split in half at 100 rows (D-178); merchant text from `remittance_information`, the date `booking_date` else `value_date`, everything in SEK, `entry_reference` on pending rows too (D-179); consent 180 days; background fetch accepted; at least 150 days of history right after BankID. **Owner's assumptions** (2026-10-24, "let's just assume it all works now given your test", D-177), verified by K1's owner steps (PLAN-K1 §8 steps 5 to 7): the partner's card links to the owner's application (fallback: her own application, D-175), a pending purchase keeps its `entry_reference` when booked (fallback: CP-8's amount-and-date rule), the session is reused the next day without BankID. The Enable Banking application exists (restricted production, redirect URL `https://kvitt.suorra.duckdns.org/cards/callback`, the owner's card linked); its key file lives only in the main checkout's git-ignored `docs/spikes/k0/.local/.pem` and reaches the Pi through K1's owner steps (`~/kvitt/secrets/cards/enable-banking.pem`, D-175), never downloaded again. The artwork is committed for Android and the web, cropped to the card (D-180). **K1 landed** `671c00d` (2026-10-24): migration 0004 (byte-identical contract and server copies), `src/cards/` with the registry, the Enable Banking adapter, the windowed fetch, the poller and the callback page, E-36 to E-44 with four new error codes and a 502 response, examples, `match_card_purchase.json` (17 cases) with its Python reference, `tests/cards_api/` (34 tests against a local Enable Banking stub; the real API is never called), the Pi compose mount of `secrets/cards/` and the NPM `/cards/callback` block; its report is SPEC v0.38 (D-181 to D-188). **K2 landed** `a8f91ee` (2026-10-24): Room version 2 (`MIGRATION_1_2` with its test, `2.json`), the card cycle after each household cycle (D-191 to D-196), `:feature:cards` S-23 to S-27 with 135 goldens, S-5 "Från kortköp", S-7 prefill and link, S-8 card line, S-13 "Anslut kort", the fourth bottom destination "Kortköp" (labels shrink to fit, D-197), 77 `strings.csv` rows, new catalog entry `androidx.browser` 1.10.0; recorded in SPEC v0.39 (D-191 to D-200, OQ-9). The phone was not attached, so nothing of K2 has run on a device yet; the orchestrator builds and installs the release APK with the card screens after landing. **K3 landed** `faeb752` (2026-10-24): W-21 `/app/cards` (every §13.3 state but offline, the S-23 sheet actions, `?attempt=` polling E-38 every 2 s, `?account=` as S-27), W-22 `/app/settings/cards` (catalogue, connect step `?provider=`), W-23 `/app/settings/cards/:id` (history, renew, disconnect with erase), W-5's `?cardPurchase=` prefill and link on save, W-6's card line with "Ta bort koppling", W-3's "Från kortköp", W-13's "Anslut kort" row, Kortköp after Översikt in the sidebar and bottom bar, the card snapshot in `web/src/api/cards.ts`, `matchCardPurchase` passing its 17 vectors; files outside PLAN-K3 §4 ratified at landing (`api/cards.ts`, `test/cards.ts`, `vite.config.ts`, the icon generator and table, `Shell.test.tsx`); recorded in SPEC v0.40 (D-201 to D-207). The key is staged at `infra/secrets/cards/enable-banking.pem` in the main checkout (git-ignored); the application id is known to the orchestrator (not written here, CP-13). +- State as of 2026-10-25. **K0 to K3 are all landed.** `main` at `6f63751` (SPEC v0.39, K2's report, D-191 to D-200, design-spec S-23 to S-27, `agent-docs-k2`), after `faeb752` (**K3 landed**: card purchases on the web, W-21 to W-23; recorded in SPEC v0.40 by this pass), `a8f91ee` (**K2 landed**: card purchases on Android, Room 2, S-23 to S-27), `07df30d` (SPEC v0.38, K1's report), `671c00d` (**K1 landed**: card purchases on the server, schema 4, E-36 to E-44), `ae73f58` (SPEC v0.37, D-211), `8b620c8` (the K0 report, SPEC v0.36), `8fa9198` (`infra/build-images.sh` Podman detection), `f15fa23` (`infra/build-images.sh` passes `KVITT_VERSION_CODE`), `4339d01` (the owner's SJ Prio card artwork), `b5114ad` (SPEC v0.35, card purchases), `2ce317f` (the K0 card test app), `5d948f9` (SPEC v0.34) and `5305f37` (W0b web shared follow-ups); before them `07c36d2` (L-10, D-156) and `593c727` (SPEC v0.33, D-156, D-157). This pass (`agent-docs-k3`): SPEC v0.40, K3's report as D-201 to D-207 (D-208 to D-210 unused), `web/README.md` and `prompts/README.md`; `main` with this pass is pushed by the orchestrator after it lands. **Deployed** (owner's report): image `v1.0.4` (git tag `v1.0.4` = `671c00d`, K1's server, schema 4) runs on the Kvitt Pi, so K1's owner steps 1 to 4 are done; **Deployed 2026-10-25** (owner: "I've added my card, tested to link and unlink! it all works as expected"): the Kvitt Pi runs `v1.0.5` (`faeb752`, K1's server schema 4 and K3's web card pages), the bank key is in `~/kvitt/secrets/cards/enable-banking.pem`, `KVITT_EB_APP_ID` is set in the Pi's `.env`, the NPM block is replaced with the current `infra/npm/kvitt.conf` (the `/cards/callback` exception and its unlogged location), and release APK `kvitt-164` (K2's card screens) is installed on the owner's phone. **Verified by the owner 2026-10-25:** PLAN-K1 §8 steps 1 to 4; PLAN-K2 §8 step 1 (own card connected with BankID, Kortköp lists purchases), step 2 (expense created from a purchase, shown under "Kopplade") and step 6 (disconnect and reconnect, "link and unlink"); PLAN-K3 §8 step 1 (laptop shows the card connected and the same purchases). **Still pending** (relayed one at a time): PLAN-K1 §8 steps 5 to 7, PLAN-K2 §8 steps 3, 4, 5, 7, PLAN-K3 §8 steps 2 and 3. **Deployed and verified 2026-10-24** (owner, D-211): image `v1.0.3` (git tag `v1.0.3` = `8fa9198`, built on the Mac) runs on the Kvitt Pi, `server` and `backup` healthy; the web client is live at `https://kvitt.suorra.duckdns.org/app/`, paired from the laptop browser with a device invite, and the owner reports "All seems to work" for Home and an account, add, edit and delete an expense, CSV export, record and delete a payment, analytics with category drill-down and Insights, the settings pages, revoking the browser from the phone, and the Android Insights section on S-11 against the new server. W0 to W7 are landed and verified (SPEC §11.2, §15). Release 140 (`kvitt-140`, deployed 2026-10-21) ran on both phones until `kvitt-164`; the owner's phone has run `kvitt-164` since 2026-10-25; whether the partner's phone has updated is not recorded here. Gates: server 356 tests at `671c00d`; contracts-check 157 (17 `match_card_purchase` cases); Android green again at `a8f91ee` (`BUILD SUCCESSFUL`, 791 actionable tasks, 1154 tests, 0 failures; the card examples E-36 to E-44 round-trip, `VectorFilesTest` and `ExampleRoundTripTest` pass), so the pre-commit hook needs no bypass any more; web at `faeb752` 70 files, 684 tests, build ok (`match_card_purchase` ported). +- **Card purchases programme** (owner request and answers 2026-10-24, SPEC v0.35, D-158 to D-176, FR-22, §9.12): each user connects their own SJ Prio Mastercard (SEB Kort) through Enable Banking's restricted production mode with BankID; the server alone holds the key and sessions, fetches purchases up to 4 times a day in the background plus "Uppdatera", and only the card holder sees them (not in `GET /sync`, audit, push or analytics); a fourth bottom destination "Kortköp" (Översikt, Kortköp, Statistik, Inställningar, revising D-048), "Anslut kort" in Settings with the SJ Prio artwork, "Skapa utgift" prefilled into S-7, one-tap links to matching expenses (same amount, ±3 days), "Från kortköp" on account detail; server schema 4 (migration 0004), Room 2, endpoints E-36 to E-44, screens S-23 to S-27, web W-21 to W-23. Plans `PLAN-K0.md` to `PLAN-K3.md`, prompts `prompts/K0.md` to `prompts/K3.md`, written by `agent-a3b7abf183f883261`, landed `b5114ad`. **K0 done** (2026-10-24): the test app (`2ce317f`) ran with the owner on his card; report [`docs/spikes/K0-enable-banking.md`](spikes/K0-enable-banking.md); its answers are SPEC v0.36 (D-177 to D-180). Main findings: the card returns at most 100 transactions per response and never a continuation key, so history is fetched in windows of at most 30 days, split in half at 100 rows (D-178); merchant text from `remittance_information`, the date `booking_date` else `value_date`, everything in SEK, `entry_reference` on pending rows too (D-179); consent 180 days; background fetch accepted; at least 150 days of history right after BankID. **Owner's assumptions** (2026-10-24, "let's just assume it all works now given your test", D-177), verified by K1's owner steps (PLAN-K1 §8 steps 5 to 7): the partner's card links to the owner's application (fallback: her own application, D-175), a pending purchase keeps its `entry_reference` when booked (fallback: CP-8's amount-and-date rule), the session is reused the next day without BankID. The Enable Banking application exists (restricted production, redirect URL `https://kvitt.suorra.duckdns.org/cards/callback`, the owner's card linked); its key file lives only in the main checkout's git-ignored `docs/spikes/k0/.local/.pem` and reaches the Pi through K1's owner steps (`~/kvitt/secrets/cards/enable-banking.pem`, D-175), never downloaded again. The artwork is committed for Android and the web, cropped to the card (D-180). **K1 landed** `671c00d` (2026-10-24): migration 0004 (byte-identical contract and server copies), `src/cards/` with the registry, the Enable Banking adapter, the windowed fetch, the poller and the callback page, E-36 to E-44 with four new error codes and a 502 response, examples, `match_card_purchase.json` (17 cases) with its Python reference, `tests/cards_api/` (34 tests against a local Enable Banking stub; the real API is never called), the Pi compose mount of `secrets/cards/` and the NPM `/cards/callback` block; its report is SPEC v0.38 (D-181 to D-188). **K2 landed** `a8f91ee` (2026-10-24): Room version 2 (`MIGRATION_1_2` with its test, `2.json`), the card cycle after each household cycle (D-191 to D-196), `:feature:cards` S-23 to S-27 with 135 goldens, S-5 "Från kortköp", S-7 prefill and link, S-8 card line, S-13 "Anslut kort", the fourth bottom destination "Kortköp" (labels shrink to fit, D-197), 77 `strings.csv` rows, new catalog entry `androidx.browser` 1.10.0; recorded in SPEC v0.39 (D-191 to D-200, OQ-9). At landing the phone was not attached; `kvitt-164` has since run on the owner's phone (2026-10-25, owner steps in §3). **K3 landed** `faeb752` (2026-10-24): W-21 `/app/cards` (every §13.3 state but offline, the S-23 sheet actions, `?attempt=` polling E-38 every 2 s, `?account=` as S-27), W-22 `/app/settings/cards` (catalogue, connect step `?provider=`), W-23 `/app/settings/cards/:id` (history, renew, disconnect with erase), W-5's `?cardPurchase=` prefill and link on save, W-6's card line with "Ta bort koppling", W-3's "Från kortköp", W-13's "Anslut kort" row, Kortköp after Översikt in the sidebar and bottom bar, the card snapshot in `web/src/api/cards.ts`, `matchCardPurchase` passing its 17 vectors; files outside PLAN-K3 §4 ratified at landing (`api/cards.ts`, `test/cards.ts`, `vite.config.ts`, the icon generator and table, `Shell.test.tsx`); recorded in SPEC v0.40 (D-201 to D-207). The key is staged at `infra/secrets/cards/enable-banking.pem` in the main checkout (git-ignored); the application id is known to the orchestrator (not written here, CP-13). - **Verified 2026-10-24** (owner, D-156): Samsung Auto Blocker was the cause of the silent update failure; turning it off let the update install, and the owner turned it back on, so every in-app update on the Samsung phones needs it off (the D-155 blocked text names it; SPEC AC-16.3, `infra/README.md`). The editor keyboard fix (S-19, S-15, S-6, `05ec3f3`) works on the device. The first backup on the Kvitt Pi ran and a snapshot pair is in the Drive folder (AC-18.1). The runner Pi's disk reached 11 of 15 GB during image builds; the owner runs `docker builder prune -af` between builds (SPEC §10.3). - **Kvitt host name** (owner decision 2026-10-19): `kvitt.suorra.duckdns.org`, a subdomain of the owner's DuckDNS family domain `suorra.duckdns.org`; NPM issues its Let's Encrypt certificate; `KVITT_PUBLIC_HOST=kvitt.suorra.duckdns.org`, so `KVITT_PUBLIC_URL=https://kvitt.suorra.duckdns.org` (port 443, D-124). It is in `infra/pi/.env.example` and `infra/pi/.env` (`KVITT_PUBLIC_HOST`) and `android/local.properties` (`kvitt.publicHost`, git-ignored). SPEC §10.1 and §10.5.1 point here. - **NPM proxy host** for `kvitt.suorra.duckdns.org` is Online with a Let's Encrypt certificate (owner, 2026-10-19). The router needs no new rule: external TCP 443 already forwards to the Home Assistant Pi (owner confirmed, D-124). @@ -79,7 +79,7 @@ Living document, rewritten in place (never a second copy). A new orchestrator se - Disk: the MacBook had about 72 GB free during the v0.20 docs pass (2026-10-19); run `tools/clean-builds.sh` when it drops under about 5 GB. ## 2. Open work (one line each, with who owns it: agent or owner) -- K1 (`671c00d`, v0.38), K2 (`a8f91ee`, v0.39) and K3 (`faeb752`, v0.40) landed and recorded. `v1.0.4` (K1) is deployed on the Pi (owner); release APK `kvitt-164` (K2) is on the Pi. Next: finish and deploy image `v1.0.5` (`faeb752`, orchestrator builds, owner deploys), then the owner steps of §3: PLAN-K2 §8 steps 1 to 7, PLAN-K3 §8 steps 1 to 3 (laptop, after `v1.0.5`), PLAN-K1 §8 steps 5 to 7 (relayed one at a time; they verify K0's three assumptions, D-177). +- K1 (`671c00d`, v0.38), K2 (`a8f91ee`, v0.39) and K3 (`faeb752`, v0.40) landed and recorded. `v1.0.5` (K1 and K3) is deployed on the Pi (owner, 2026-10-25); release APK `kvitt-164` (K2) is on the owner's phone. `v1.0.5` (K3) is deployed and `kvitt-164` (K2) is on the owner's phone (2026-10-25). Next: the pending owner steps of §3, relayed one at a time: PLAN-K1 §8 steps 5 to 7 (partner's card, next day without BankID, pending to booked; they verify K0's three assumptions, D-177), PLAN-K2 §8 steps 3, 4, 5, 7, PLAN-K3 §8 steps 2 and 3. Done and verified 2026-10-25: PLAN-K1 §8 steps 1 to 4, PLAN-K2 §8 steps 1, 2, 6, PLAN-K3 §8 step 1. - OQ-9 (owner, §4): `CardPurchase.linked` cannot tell "unlinked" from "linked to an expense not yet on the phone"; a `linkedExpenseId` field would be a contract change. - K2's dependency report (agent, next Android pass): datastore 1.2.1 → 1.3.0, kotlinx-serialization 1.11.0 → 1.12.0, roborazzi 1.76.0 → 1.77.0, firebaseBom 35.0.2 → 35.1.0 (each one minor behind); Gradle 9.8.1 → 9.8.2 (patch). - K0 test app session in `docs/spikes/k0/.local/state.json` (owner): keep it or press "9 Koppla från" in the test app (PLAN-K0 §6 step 7); K1 does not use it. The key file stays in `.local/` either way. @@ -111,13 +111,13 @@ Living document, rewritten in place (never a second copy). A new orchestrator se - The image's version code: `ARG KVITT_VERSION_CODE` in `server/Dockerfile` and the workflow's build argument (`5d948f9`); `infra/build-images.sh` since `f15fa23`. ## 3. HUMAN steps pending (relay in chat) -Done 2026-10-21: the Pi install (stack running, `v1.0.1`, both containers healthy), the public health check through NPM, bootstrap, release pairing of both phones, the Splitwise import. Done 2026-10-24: both phones on release 140 (keyed, so the old step 1 is done), the first backup on Drive (AC-18.1); `v1.0.3` deployed and the web client checked from the laptop browser, S-11's Insights on the phone (the old steps 3 and 4, D-211). +Done 2026-10-21: the Pi install (stack running, `v1.0.1`, both containers healthy), the public health check through NPM, bootstrap, release pairing of both phones, the Splitwise import. Done 2026-10-24: both phones on release 140 (keyed, so the old step 1 is done), the first backup on Drive (AC-18.1); `v1.0.3` deployed and the web client checked from the laptop browser, S-11's Insights on the phone (the old steps 3 and 4, D-211). Done 2026-10-25 (owner): `v1.0.5` deployed on the Pi (key in `~/kvitt/secrets/cards/`, `KVITT_EB_APP_ID` in `.env`, current `infra/npm/kvitt.conf` in NPM), `kvitt-164` on the owner's phone, the owner's card connected, linked and unlinked. Standing note for every in-app update on the Samsung phones: turn Auto Blocker off before tapping "Uppdatera", back on afterwards (D-156). Images are built on the Mac (D-211); only if the fallback workflow runs: `docker builder prune -af` on the runner Pi between two of its builds. 1. Gate (step 4a items 4 and 5), both phones run the keyed APK (release 140): NPM, Hosts, Proxy Hosts, Kvitt row, Edit, Advanced: paste the step 4 block with the key in place of `KVITT_APP_KEY`, Save (row Online, yes/no). Acceptance test: on home Wi-Fi Chrome opens `https://kvitt.suorra.duckdns.org/i/TEST` and the invite page shows (yes/no); with Wi-Fi off the same URL gives a connection error (yes/no); with Wi-Fi off Kvitt's About screen shows the server version (yes/no). 2. Web client gate lines (D-130, SPEC v0.28): when the NPM block is pasted (item 1, or again if the D-126 block is already in NPM), paste the current `infra/npm/kvitt.conf` content (step 4), which also lets the web client through and sets its Content-Security-Policy; Save (row Online, yes/no). The image with the web client is deployed (`v1.0.3`, D-211); acceptance test with Wi-Fi off on the phone: `https://kvitt.suorra.duckdns.org/app/` shows the Kvitt login page (yes/no) and `https://kvitt.suorra.duckdns.org/health` still gives a connection error (yes/no) (step 4a item 5 d and e). -3. Card purchases: K0's owner steps are done (2026-10-24: Enable Banking account and Terms of Service, the application, the key in `docs/spikes/k0/.local/`, the owner's card linked, the test app run); the artwork is committed (D-180). **K1's owner steps 1 to 4 are done** (owner's report: `v1.0.4` deployed on the Pi); for the record they were: step 1 is done by the orchestrator (the key staged at `infra/secrets/cards/enable-banking.pem` in the main checkout, git-ignored, mode 0600); step 2 on the Pi in `~/kvitt`: `mkdir -p secrets/cards && chmod 700 secrets/cards` before anything else (the new `compose.yaml` refuses to start without that folder, even with no card configured, D-188), `scp` the key, `chmod 600 secrets/cards/*`, copy the new `compose.yaml`, set `KVITT_EB_APP_ID=` in `.env` (the orchestrator gives the id in chat) and leave `KVITT_EB_MEMBER_APP_ID=` empty; step 3 paste the current `infra/npm/kvitt.conf` into NPM (row Online, yes/no); step 4 backup, `KVITT_TAG`, `docker compose pull && docker compose up -d` (`server` healthy, `/health` shows `"schema_version":4`, yes/no). **Pending: PLAN-K1 §8 steps 5 to 7**, relayed one at a time now that a client with the card screens exists (`kvitt-164`): the partner's card, the next-day fetch without BankID, pending to booked. -4. Card purchases on the phone (PLAN-K2 §8, all pending; K1's image runs on the Pi and `kvitt-164` is on the Pi, so the first step is the in-app update, Auto Blocker off for it and back on afterwards): 1 Inställningar › Anslut kort › SJ Prio Mastercard › 30 dagar › "Anslut med BankID", sign in BankID, back in Kvitt "Kortet är anslutet" and the Kortköp tab lists the purchases (yes/no each); 2 Kortköp › a purchase › "Skapa utgift" › "Spara": the expense is in its account and the purchase under "Kopplade" (yes/no); 3 on a purchase the partner already entered, the row's "Koppla till …" moves it to "Kopplade" (yes/no); 4 flight mode on, "Ignorera" a purchase, flight mode off: still ignored after a sync (yes/no); 5 an account › menu › "Från kortköp" › a purchase › "Spara": the expense is in that account (yes/no); 6 Inställningar › Anslut kort › SJ Prio Mastercard › "Koppla från" › "Koppla från": Kortköp shows "Anslut ditt kort", and after reconnecting the linked purchases are under "Kopplade" (yes/no); 7 on the partner's phone after she connects her card (PLAN-K1 §8 step 5): Kortköp shows only her purchases and none of the owner's (yes/no). -5. Card purchases on the laptop (PLAN-K3 §8, all pending; after image `v1.0.5` is deployed on the Pi): 1 `https://kvitt.suorra.duckdns.org/app/` › Inställningar › Anslut kort: the SJ Prio card shows "Ansluten" if the phone connected it (yes/no), and Kortköp lists the same purchases as on the phone (yes/no); 2 Kortköp › a purchase › "Skapa utgift" › "Spara": the purchase is under "Kopplade" on the laptop and on the phone after a sync (yes/no); 3 if the card is not connected yet, or after "Koppla från": Anslut kort › SJ Prio Mastercard › "Anslut med BankID": the bank's page shows a QR (yes/no), scan it with BankID on the phone (yes/no), "Tillbaka till Kvitt" opens Kortköp with the purchases (yes/no). +3. Card purchases: K0's owner steps are done (2026-10-24: Enable Banking account and Terms of Service, the application, the key in `docs/spikes/k0/.local/`, the owner's card linked, the test app run); the artwork is committed (D-180). **K1's owner steps 1 to 4 are done** (owner's report: `v1.0.4` deployed on the Pi); for the record they were: step 1 is done by the orchestrator (the key staged at `infra/secrets/cards/enable-banking.pem` in the main checkout, git-ignored, mode 0600); step 2 on the Pi in `~/kvitt`: `mkdir -p secrets/cards && chmod 700 secrets/cards` before anything else (the new `compose.yaml` refuses to start without that folder, even with no card configured, D-188), `scp` the key, `chmod 600 secrets/cards/*`, copy the new `compose.yaml`, set `KVITT_EB_APP_ID=` in `.env` (the orchestrator gives the id in chat) and leave `KVITT_EB_MEMBER_APP_ID=` empty; step 3 paste the current `infra/npm/kvitt.conf` into NPM (row Online, yes/no); step 4 backup, `KVITT_TAG`, `docker compose pull && docker compose up -d` (`server` healthy, `/health` shows `"schema_version":4`, yes/no). **Pending: PLAN-K1 §8 steps 5 to 7**, relayed one at a time (the owner's card works, 2026-10-25): step 5 the partner's card (Control Panel linking, then her phone), step 6 the next day without BankID, step 7 pending to booked (log line counts). +4. Card purchases on the phone (PLAN-K2 §8; **steps 1, 2 and 6 done and verified by the owner 2026-10-25**, `kvitt-164` installed; **pending: 3, 4, 5, 7**, relayed one at a time; the done steps stay for the record): 1 Inställningar › Anslut kort › SJ Prio Mastercard › 30 dagar › "Anslut med BankID", sign in BankID, back in Kvitt "Kortet är anslutet" and the Kortköp tab lists the purchases (yes/no each); 2 Kortköp › a purchase › "Skapa utgift" › "Spara": the expense is in its account and the purchase under "Kopplade" (yes/no); 3 on a purchase the partner already entered, the row's "Koppla till …" moves it to "Kopplade" (yes/no); 4 flight mode on, "Ignorera" a purchase, flight mode off: still ignored after a sync (yes/no); 5 an account › menu › "Från kortköp" › a purchase › "Spara": the expense is in that account (yes/no); 6 Inställningar › Anslut kort › SJ Prio Mastercard › "Koppla från" › "Koppla från": Kortköp shows "Anslut ditt kort", and after reconnecting the linked purchases are under "Kopplade" (yes/no); 7 on the partner's phone after she connects her card (PLAN-K1 §8 step 5): Kortköp shows only her purchases and none of the owner's (yes/no). +5. Card purchases on the laptop (PLAN-K3 §8; `v1.0.5` is deployed; **step 1 done and verified by the owner 2026-10-25**, **pending: 2 and 3**, step 3 only if a connect from the laptop is ever needed): 1 `https://kvitt.suorra.duckdns.org/app/` › Inställningar › Anslut kort: the SJ Prio card shows "Ansluten" if the phone connected it (yes/no), and Kortköp lists the same purchases as on the phone (yes/no); 2 Kortköp › a purchase › "Skapa utgift" › "Spara": the purchase is under "Kopplade" on the laptop and on the phone after a sync (yes/no); 3 if the card is not connected yet, or after "Koppla från": Anslut kort › SJ Prio Mastercard › "Anslut med BankID": the bank's page shows a QR (yes/no), scan it with BankID on the phone (yes/no), "Tillbaka till Kvitt" opens Kortköp with the purchases (yes/no). ## 4. Owner questions (asked, unanswered) - OQ-7 (SPEC §12): a notification for new card purchases? Default: none in this version (D-171). @@ -136,8 +136,8 @@ Standing note for every in-app update on the Samsung phones: turn Auto Blocker o ## 6. Numbering - Decisions: D-001 to D-211 used, except D-008, D-009, D-150, D-189, D-190 and D-208 to D-210 (never used); D-158 to D-176 are the card purchases (v0.35), D-177 to D-180 K0's results and the artwork (v0.36), D-211 the Mac image builds and the verified `v1.0.3` deploy (v0.37), D-181 to D-188 K1's report (v0.38), D-191 to D-200 K2's report (v0.39), D-201 to D-207 K3's report (v0.40); D-208 to D-210 unused like D-150. Next free: **D-212**. - Spec version: v0.40 written (K3's report, D-201 to D-207). Next **v0.41**. -- Release tags: `v1.0.3` = `8fa9198`, `v1.0.4` = `671c00d` (K1, deployed), `v1.0.5` = `faeb752` (K3, being built). Release APK `kvitt-164` (K2) on the Pi. -- Server schema version **4** in code (migration 0004, K1 `671c00d`); the Kvitt Pi runs it since `v1.0.4`; the dev stack still runs schema 3 until its next deploy. Room schema version **2** in code (K2 `a8f91ee`, `MIGRATION_1_2`). +- Release tags: `v1.0.3` = `8fa9198`, `v1.0.4` = `671c00d` (K1), `v1.0.5` = `faeb752` (K3; the Pi runs it since 2026-10-25). Release APK `kvitt-164` (K2) installed on the owner's phone. +- Server schema version **4** in code (migration 0004, K1 `671c00d`); the Kvitt Pi runs it (since `v1.0.4`, now `v1.0.5`); the dev stack still runs schema 3 until its next deploy. Room schema version **2** in code (K2 `a8f91ee`, `MIGRATION_1_2`). - New ids in v0.35: FR-22 (AC-22.1 to AC-22.15), US-18, US-19, CP-1 to CP-14 (§9.12), S-23 to S-27, W-21 to W-23, E-36 to E-44, OQ-7, OQ-8; plans K0 to K3. New in v0.39: OQ-9. - Sync protocol **1**, push payload **1**.