SPEC v0.35: card purchases via Enable Banking (D-158 to D-176), plans K0 to K3

Owner request and answers of 2026-10-24: each user connects their own SJ Prio
Mastercard through Enable Banking (restricted production, BankID); only the
card holder sees the purchases; a fourth bottom destination "Kortköp"
(revises D-048); "Anslut kort" in Settings with the card artwork; one- and
two-tap linking to household expenses; web as a later plan.

FR-22, §9.12 (CP-1 to CP-14), server schema 4 (migration 0004), Room 2,
E-36 to E-44, S-23 to S-27, W-21 to W-23, OQ-7, OQ-8. PLAN-K0 describes the
test app of 2ce317f and the remaining run and report; K1 server, K2 Android,
K3 web. HANDOFF and prompts/README updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 11:39:19 +02:00
parent 2ce317f72c
commit b5114adc06
12 changed files with 885 additions and 41 deletions
+25
View File
@@ -0,0 +1,25 @@
# Start prompt: K0 Card purchases spike (local Enable Banking test app)
You are an Opus implementation agent on Kvitt (repository `/Users/jhag/projects/kvitt`), plan K0: card purchases spike. You have no context other than this prompt and the files it names.
Read PLAN-K0.md and follow it; CLAUDE.md rules apply. SPEC.md wins over both (§9.12 is the card-purchase rules, FR-22 the acceptance criteria). The test app exists (`docs/spikes/k0/app.py`, `2ce317f`); your work is running it with the owner and writing the report.
Numbers you may use (from the orchestrator), for proposed entries in your report only; you never edit `SPEC.md` or `docs/decisions.md` (CLAUDE.md › Orchestration):
- Next free decision id: {{NEXT_DECISION}}
- Spec version a proposed spec change would get: {{SPEC_VERSION}}
- Schema version for any schema change: {{SCHEMA_VERSION}}
If a value is still a `{{…}}` placeholder, write `TODO(spec)` wherever the number would go and say so in the report.
Orchestrator notes for this run:
{{ORCHESTRATOR_NOTES}}
Essentials (the plan has the detail):
- First step: from the main checkout, `git worktree add .claude/worktrees/agent-k0 -b agent-k0 main`; work only there, on branch `agent-k0`; `git reset --hard main`. Copy `docs/spikes/k0/.local/` from the main checkout if the owner's key is there (never commit it).
- Edit only `docs/spikes/k0/**` and `docs/spikes/K0-enable-banking.md`; anything else is a request to the orchestrator.
- Real purchase data shows only on the owner's screen. Never print, log, commit or report it; read the state only through `analysis_text` (PLAN-K0 §6 step 4). The application id stays out of every committed file.
- The owner's steps (PLAN-K0 §8) go to the orchestrator, worded for relay, one at a time; you never sign in anywhere yourself.
- No gate: run the checks of PLAN-K0 §7 and report what you ran.
- Stop and ask when a step could expose the owner's data, when Enable Banking's terms or control panel differ from the plan, or when the spec is ambiguous in a way that changes a decision.
- Commit on your branch, `git rebase main`. Never merge, push or remove the worktree.
Report: end with the report described in PLAN-K0.md §10: branch, head commit hash, the checks run, one answer per K0 item with proposed SPEC v0.36 text, the owner steps with their yes/no, HUMAN steps outstanding (worded for relay), requests to the orchestrator, open questions with section numbers.
+24
View File
@@ -0,0 +1,24 @@
# Start prompt: K1 Card purchases, server
You are an Opus implementation agent on Kvitt (repository `/Users/jhag/projects/kvitt`), plan K1: card purchases, server. You have no context other than this prompt and the files it names.
Read PLAN-K1.md and follow it; CLAUDE.md rules apply. SPEC.md wins over both (§9.12, FR-22, §14.1.3, §14.3.4 E-36 to E-44).
Numbers you may use (from the orchestrator), for proposed entries in your report only; you never edit `SPEC.md` or `docs/decisions.md` (CLAUDE.md › Orchestration):
- Next free decision id: {{NEXT_DECISION}}
- Spec version a proposed spec change would get: {{SPEC_VERSION}}
- Schema version for any schema change: {{SCHEMA_VERSION}} (migration 0004 is schema 4)
If a value is still a `{{…}}` placeholder, write `TODO(spec)` wherever the number would go and say so in the report.
Orchestrator notes for this run:
{{ORCHESTRATOR_NOTES}}
Essentials (the plan has the detail):
- First step: from the main checkout, `git worktree add .claude/worktrees/agent-k1 -b agent-k1 main`; work only there, on branch `agent-k1`; `git reset --hard main`. Stop and report if SPEC v0.36 (K0's answers) is not on `main`.
- Edit only `server/**`, `contracts/**`, `tools/contracts-check.py`, `infra/pi/compose.yaml`, `infra/pi/.env.example`, `infra/dev/**`, `infra/npm/kvitt.conf`, `infra/README.md` (step 4's block and the card runbook section), and `web/src/api/schema.d.ts` only to regenerate it; anything else is a request to the orchestrator.
- Never call the real Enable Banking API from a test; use a local stub. Never log a merchant text, amount, session id, `code` or `state`.
- Gate: `cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo audit && cargo test` in `server/`, `python3 tools/contracts-check.py`, `npm run check` in `web/`, the compose config checks and the nginx check of PLAN-K1 §7. Report only results you ran in this session.
- Stop and ask when the plan says so, when a step could touch the owner's real data, or when the spec is ambiguous in a way that changes a decision.
- Commit on your branch when the gate is green, `git rebase main`, rerun the gate. Never merge, push or remove the worktree.
Report: end with the report described in PLAN-K1.md §10: branch, head commit hash, gate result lines, contract files changed, deviations from the spec with proposed text, how the orchestrator notes were applied, HUMAN steps outstanding (worded for relay), requests to the orchestrator, open questions with section numbers.
+24
View File
@@ -0,0 +1,24 @@
# Start prompt: K2 Card purchases, Android
You are an Opus implementation agent on Kvitt (repository `/Users/jhag/projects/kvitt`), plan K2: card purchases, Android. You have no context other than this prompt and the files it names.
Read PLAN-K2.md and follow it; CLAUDE.md rules apply. SPEC.md wins over both (§9.12, FR-22, §13.2, §13.3 S-23 to S-27, §14.2.4 "Changes in v0.35").
Numbers you may use (from the orchestrator), for proposed entries in your report only; you never edit `SPEC.md` or `docs/decisions.md` (CLAUDE.md › Orchestration):
- Next free decision id: {{NEXT_DECISION}}
- Spec version a proposed spec change would get: {{SPEC_VERSION}}
- Schema version for any schema change: {{SCHEMA_VERSION}} (Room version 2 is this plan's)
If a value is still a `{{…}}` placeholder, write `TODO(spec)` wherever the number would go and say so in the report.
Orchestrator notes for this run:
{{ORCHESTRATOR_NOTES}}
Essentials (the plan has the detail):
- First step: from the main checkout, `git worktree add .claude/worktrees/agent-k2 -b agent-k2 main`; work only there, on branch `agent-k2`; `git reset --hard main`. Then copy `android/local.properties` and `android/app/google-services.json` from the main checkout (never commit them). Stop and report if SPEC v0.36 is not on `main`. You may start before K1 lands; rebase on K1 before the gate.
- Edit only the paths of PLAN-K2 §4 (`android/feature/cards/**` new; as a contract change `android/core/model/**`, `android/domain/**`, `android/data/**`, `android/core/fakes/**`; the named edits in `:core:design`, `:feature:account`, `:feature:expense`, `:feature:settings`, `:app`, `android/settings.gradle.kts`, `android/gradle/libs.versions.toml`; the card keys in `docs/ux/strings.csv`); anything else is a request to the orchestrator.
- Gate: `PATH=/opt/homebrew/opt/openjdk@25/bin:$PATH ../tools/gradle-serial.sh check` in `android/`. Open every changed golden. Report only results you ran in this session.
- Use the phone only if the orchestrator notes name you for it (one agent on the phone at a time); never clear or uninstall the real app's data; never log card content.
- Stop and ask when the plan says so, when a step could touch the owner's real data, or when the spec is ambiguous in a way that changes a decision.
- Commit on your branch when the gate is green, `git rebase main`, rerun the gate. Never merge, push or remove the worktree.
Report: end with the report described in PLAN-K2.md §10: branch, head commit hash, gate result lines, goldens, strings added, proposed spec text and decisions, how the orchestrator notes were applied, HUMAN steps outstanding (worded for relay), requests to the orchestrator, open questions with section numbers.
+24
View File
@@ -0,0 +1,24 @@
# Start prompt: K3 Card purchases, web
You are an Opus implementation agent on Kvitt (repository `/Users/jhag/projects/kvitt`), plan K3: card purchases, web. You have no context other than this prompt and the files it names.
Read PLAN-K3.md and follow it; CLAUDE.md rules apply. SPEC.md wins over both (§15, §9.12, FR-22, §15.6 W-21 to W-23).
Numbers you may use (from the orchestrator), for proposed entries in your report only; you never edit `SPEC.md` or `docs/decisions.md` (CLAUDE.md › Orchestration):
- Next free decision id: {{NEXT_DECISION}}
- Spec version a proposed spec change would get: {{SPEC_VERSION}}
- Schema version for any schema change: {{SCHEMA_VERSION}}
If a value is still a `{{…}}` placeholder, write `TODO(spec)` wherever the number would go and say so in the report.
Orchestrator notes for this run:
{{ORCHESTRATOR_NOTES}}
Essentials (the plan has the detail):
- First step: from the main checkout, `git worktree add .claude/worktrees/agent-k3 -b agent-k3 main`; work only there, on branch `agent-k3`; `git reset --hard main`; `npm ci` in `web/`. Stop and report if SPEC v0.36 is not on `main`. You may start before K1 and K2 land; rebase on both before the gate.
- Edit only the paths of PLAN-K3 §4 (`web/src/features/cards/**` new; the route, the sidebar entry and `web/src/lib/domain/`; the named edits in `features/expenses`, `features/accounts`, `features/settings`; the regenerated dictionaries); anything else is a request to the orchestrator.
- Gate: `npm run check` in `web/`. Report only results you ran in this session.
- Never use the owner's development stack or the Pi for checks; use a throwaway server with a stubbed Enable Banking (PLAN-K3 §6).
- Stop and ask when the plan says so, when a step could touch the owner's real data, or when the spec is ambiguous in a way that changes a decision.
- Commit on your branch when the gate is green, `git rebase main`, rerun the gate. Never merge, push or remove the worktree.
Report: end with the report described in PLAN-K3.md §10: branch, head commit hash, gate result lines, strings added, proposed spec text and decisions, how the orchestrator notes were applied, HUMAN steps outstanding (worded for relay), requests to the orchestrator, open questions with section numbers.
+5
View File
@@ -40,6 +40,10 @@ Plans in the same wave can run in parallel (they own disjoint paths, SPEC §14.7
| 5 | M2c-pi Infra on the Pi (bundle `infra/pi/`, D-100) | `M2c-pi.md` | M2c-dev, M8; runs last, after the app is proven | bundle done (`2476667`, D-103 to D-106); reshaped by the NPM rework (`4f69ae0` to `9231a1d`, D-120) and made a self-contained compose project (`6e5981d`, D-125); the plan is superseded where it names Caddy, cert-sync, scripts or `/opt/kvitt`; the owner's install on the Pi is in progress (2026-10-20) |
| 6 | M10 First release | `M10.md` | M2c-pi, M3, M4, M8 | none |
| 7 | M11 Import history | `M11.md` | M9, M10 | none |
| 8 | K0 Card purchases spike (local test app, D-176) | `K0.md` | SPEC v0.35; the owner's Enable Banking account, application and key (PLAN-K0 §8) | none; the app landed `2ce317f`, the run with the owner and the report remain |
| 9 | K1 Card purchases: server (schema 4, E-36 to E-44) | `K1.md` | SPEC v0.36 (K0's answers) | K2, K3; lands first |
| 9 | K2 Card purchases: Android (`:feature:cards`, Room 2) | `K2.md` | SPEC v0.36; rebases on K1 before its gate | K1, K3; lands after K1 |
| 9 | K3 Card purchases: web (W-21 to W-23) | `K3.md` | SPEC v0.36; rebases on K1 and K2 before its gate | K1, K2; lands after K2 (card strings) |
## Constraints the orchestrator must keep in mind
@@ -50,4 +54,5 @@ Plans in the same wave can run in parallel (they own disjoint paths, SPEC §14.7
- **M6** landed `7730a31` (D-063 to D-066): charts on `Canvas`, Expressive fallbacks against material3 1.4.0, formatting tables in code, one golden per sheet × theme × language (+200 %), which M7a to M7f follow. Its M8 contract requests are in SPEC §11.3.
- **M12** (D-054): done; the importer test `category_table_matches_the_spec` is green again since M12b (`6eaccec`). M12d (D-059) landed `557af7e` (D-060 to D-062); M7a to M7f run on top of both.
- **Phone:** M2b (one `installDebug`), M5 (only if instrumented tests), M8 and M10 use the phone; only one at a time, named in the notes. M8's on-phone test was run by the orchestrator with the owner on 2026-10-18; M12e did not use the phone; its APK needs a schema-3 server (SPEC §14.8), and the dev server already runs it.
- **K0 to K3** (D-176, SPEC §11.3): K0 runs with the owner on the Mac only; its `TODO(spec)` answers go into SPEC v0.36 through a docs agent before K1 starts. K1 owns the contract (migration 0004, OpenAPI E-36 to E-44, examples, `match_card_purchase.json`) and lands first; K2 and K3 may start on the spec and fakes and rebase before their gates. Give K1, K2 and K3 disjoint decision ranges. No agent ever prints, logs or commits a real card purchase; the owner's BankID steps are relayed in chat.
- **Outside the repository:** M2c-dev (D-022, done), M2c-pi needs none: it writes the `infra/pi/` compose project and the owner runs it on the Pi (D-100, revises D-023; D-125); M8 (dev server on the Mac), M10 and M11 (production) need the owner's allowance in the notes.