From b9fe0e82b345271da54b08dbff01a921ef8a870a Mon Sep 17 00:00:00 2001 From: zemion Date: Mon, 6 Jul 2026 14:38:53 +0200 Subject: [PATCH] Sync Repo-docs-handover from project files --- Repo-docs-handover.-.md | 1506 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1506 insertions(+) create mode 100644 Repo-docs-handover.-.md diff --git a/Repo-docs-handover.-.md b/Repo-docs-handover.-.md new file mode 100644 index 0000000..c64e234 --- /dev/null +++ b/Repo-docs-handover.-.md @@ -0,0 +1,1506 @@ + + +> Mirrored from `/mnt/DATA/git/mousehold/docs/handover.md`. +> Origin: `repository`. +> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context. + +--- +# Handover note: household finance ledger platform + +## 1. Goal of the project / conversation + +Build a household finance platform that combines transaction import, manual entry, document/email capture, project budgeting, promised-payment tracking, recurring-expense tracking, categorization, budgeting, debt/savings planning, and explainable settlement between household members. + +The platform should handle a real-world household setup with: + +```text +- shared household account(s) +- personal bank accounts +- extra fourth bank account +- personal credit card +- PayPal accounts +- Klarna Card / Pay Later style obligations +- recurring bills and memberships +- project-based budgets, e.g. holidays, renovation, moving +``` + +The user wants this to become useful as: + +```text +- an API/backend +- a web frontend +- a mobile app +- local-first or privacy-preserving connectors where possible +``` + +A key privacy goal is that **bank connections should ideally happen locally**, so the central server does not need to store plaintext or unencrypted banking credentials, tokens, or sensitive banking connection material. + +The conceptual core is not “transaction import.” The core is a **household financial ledger** that distinguishes: + +```text +cash movement +purchase / consumption event +liability +promised future payment +recurring commitment +refund +reimbursement +settlement between household members +project budget item +source evidence +``` + +## 2. Current state + +No code, files, repository, database schema, or artifacts have been created yet in this conversation. + +The project is at the **architecture and product-definition stage**. + +The following concepts have been agreed as important: + +```text +- manual entry must be first-class +- imports/connectors are useful but incomplete +- duplicate detection is central +- IMAP ingestion is useful for PayPal, Klarna, invoices, receipts, subscriptions +- receipt/photo scanning is useful but should be reviewed by the user +- AI/categorization/OCR should run locally +- projects should be first-class, not just tags +- project budgets must track budgeted, committed, paid, reconciled, settled, and still-due amounts separately +- settlement must be explainable +- private and shared visibility must be handled carefully +``` + +Known external access situation from earlier discussion: + +```text +German bank accounts: + FinTS/HBCI and/or PSD2 aggregators are plausible. + +GLS/comdirect: + FinTS likely relevant. + +comdirect: + also has its own API, but it is not bank-independent. + +Klarna Bank Account / Guthaben: + likely accessible through PSD2/AIS route. + +Klarna Card as credit/BNPL card: + no known public consumer transaction API. + Treat as weak/incomplete data source. + Fallbacks: IMAP, statements/PDFs, GDPR export, manual entry, bank-side repayment reconciliation. + +PayPal: + possible routes include PayPal API, CSV export, and IMAP/email parsing. + Third-party/multi-user API access may require partner status. +``` + +## 3. Important decisions already made + +### Product decisions + +The platform should be modeled as an **evidence-to-ledger system**, not as direct transaction import. + +Recommended flow: + +```text +raw source observation + -> extraction/parsing + -> candidate event + -> duplicate/link/reconciliation engine + -> accepted household ledger event + -> categorization + -> project assignment + -> split/settlement logic + -> budget and cash-flow views +``` + +Every imported or manually entered item should first become a **raw observation** or **candidate**, not an immediately final expense. + +### Accounting decisions + +Do not collapse these concepts: + +```text +expense +payment +cash settlement +promised future payment +liability +recurring commitment +refund +reimbursement +transfer +project budget item +``` + +A bank debit from PayPal 30 days after a purchase is usually **not a new expense**. It may settle a previously recorded PayPal/Klarna obligation. + +A credit card bill payment is usually **not a new expense**. It reduces card liability. + +A reimbursement between household members is usually **not income**. It settles an interpersonal balance. + +### Privacy/security decisions + +Bank connections should ideally happen locally. + +The server should avoid storing: + +```text +- plaintext bank login credentials +- unencrypted bank tokens +- TAN/SCA secrets +- unnecessary raw banking payloads outside encrypted storage +``` + +Potential model: + +```text +local connector agent + -> connects to FinTS/PSD2/file imports locally + -> normalizes/encrypts data + -> sends sanitized observations/events to backend +``` + +The backend can still store encrypted raw observations if needed, but the design should support local-only sensitive connectors. + +### Import decisions + +Manual entry, CSV import, IMAP, PDF import, receipt photo OCR, and API connectors should all feed the same raw observation pipeline. + +CSV and manual import are not fallback-only features; they are primary ingestion methods. + +### Project budgeting decisions + +Projects are first-class entities. + +A project must support: + +```text +budget lines +planned items +actual events +partial payments +future due payments +recurring project-related payments +participants +split rules +settlement +evidence +open actions +scenario estimates +``` + +Projects should work for: + +```text +holidays +renovations +moving +large purchases +weddings/events +debt repayment +savings goals +child/pet/medical/education expenses +``` + +## 4. Files, code, or artifacts involved + +None yet. + +There is no repository, package structure, codebase, database migration, OpenAPI spec, UI design file, or generated artifact from this conversation. + +The new coding agent should start by creating the initial repository structure. + +## 5. Relevant architecture / data model / APIs / commands + +### Recommended high-level architecture + +Suggested initial architecture: + +```text +monorepo/ + apps/ + web/ # web frontend + mobile/ # app later; can be deferred + api/ # backend API + local-agent/ # local bank/import connector agent + packages/ + domain/ # shared domain types, validation schemas + importers/ # CSV, IMAP, PDF/OCR parsers + matching/ # deduplication and reconciliation logic + categorization/ # local rules/classifier interfaces + ui/ # shared UI components, optional + infra/ + docker/ + migrations/ +``` + +No specific stack has been chosen yet. For fast development, a reasonable starting assumption would be: + +```text +Language: + TypeScript for API/web/shared domain. + +Backend: + Node.js with Fastify, NestJS, or similar. + +Frontend: + React / Next.js. + +Database: + PostgreSQL for server mode. + SQLite for local-agent/local-first mode or test fixtures. + +Mobile: + Defer initially; later React Native, Expo, Flutter, or native app. + +Local agent: + TypeScript or Python. + Python may be better for FinTS, OCR, PDF parsing, IMAP prototypes. + TypeScript may be better for shared validation and app packaging. + +AI/OCR: + local only. + No cloud AI dependency. +``` + +These are assumptions, not confirmed choices. + +### Core domain entities + +Use explicit domain entities. Do not store everything as one flat transaction table. + +#### `User` + +```text +id +display_name +email +household_id +created_at +``` + +#### `Household` + +```text +id +name +default_currency +created_at +``` + +#### `Account` + +Represents checking accounts, shared accounts, PayPal, credit cards, Klarna, cash wallets, or virtual liability accounts. + +```text +id +household_id +owner_user_id nullable +name +account_type # checking, shared_checking, paypal, credit_card, klarna, cash, liability, savings +institution_name +currency +visibility_mode # private, shared_summary, shared_full, settlement_only +is_active +created_at +``` + +#### `RawObservation` + +Every imported file row, email, PDF, receipt photo, API transaction, notification, or manual draft. + +```text +id +household_id +source_type # bank_csv, fints, paypal_csv, paypal_email, klarna_email, receipt_photo, pdf_invoice, manual, api +source_account_id nullable +owner_user_id nullable +observed_at nullable +received_at +raw_hash +raw_text nullable +raw_file_path nullable +raw_payload_json nullable +parsed_json nullable +parser_name nullable +parser_version nullable +confidence +status # new, parsed, candidate_created, ignored, duplicate_source, error +created_at +``` + +#### `FinancialEvent` + +The accepted or candidate economic event. + +```text +id +household_id +event_type # expense, income, transfer, liability_payment, promised_payment, refund, reimbursement, fee, interest, adjustment +status # candidate, confirmed, pending, booked, settled, cancelled, ignored +event_date +booking_date nullable +due_date nullable +amount +currency +merchant nullable +counterparty nullable +description +category_id nullable +project_id nullable +created_by_user_id nullable +created_at +updated_at +``` + +Important: `FinancialEvent` is not necessarily a bank transaction. + +#### `EventObservationLink` + +Links evidence to event. + +```text +id +event_id +observation_id +relation # evidence_for, duplicate_source, imported_from, parser_source, statement_source +confidence +created_at +``` + +#### `EventRelation` + +Links events to each other. + +```text +id +from_event_id +to_event_id +relation_type # duplicate_of, same_economic_event_as, settles, funds, reimburses, refunds, reverses, replaces_pending_authorization, part_of_statement +confidence +created_by # system, user +created_at +``` + +#### `SplitLine` + +Represents economic responsibility. + +```text +id +event_id +user_id +share_amount +share_percent nullable +reason # equal_split, custom, private, income_ratio, project_default, manual +created_at +``` + +#### `Category` + +Use hierarchical categories. + +```text +id +household_id +parent_id nullable +name +path # e.g. "holiday > restaurant" +is_active +``` + +#### `Tag` + +Use tags for flexible labels. Do not use tags as project replacement. + +```text +id +household_id +name +``` + +#### `Project` + +First-class project/budget object. + +```text +id +household_id +name # e.g. "Stockholm 2026" +description +start_date nullable +end_date nullable +default_split_rule_id nullable +status # idea, planning, active, completed, cancelled, archived +currency +created_at +updated_at +``` + +#### `ProjectParticipant` + +```text +id +project_id +user_id +role +default_share_percent nullable +``` + +#### `ProjectBudgetLine` + +Budget category within project. + +```text +id +project_id +category_id nullable +name # Transport, Accommodation, Food, Souvenirs, Buffer +budgeted_amount +committed_amount_cached nullable +paid_amount_cached nullable +sort_order +notes +``` + +#### `ProjectPlannedItem` + +Planned or committed project item. + +```text +id +project_id +budget_line_id nullable +description +estimated_amount +committed_amount nullable +expected_date nullable +due_date nullable +expected_payer_account_id nullable +split_rule_id nullable +planning_status # idea, estimated, committed, cancelled +payment_status # unpaid, partially_paid, paid, refunded, partially_refunded +reconciliation_status # no_evidence, email_seen, receipt_seen, bank_matched, statement_matched, manually_confirmed +settlement_status # not_shared, unsettled, partially_settled, settled, ignored +notes +created_at +updated_at +``` + +#### `PaymentLine` + +Partial payments for project items or events. + +```text +id +planned_item_id nullable +event_id nullable +amount +currency +date +paid_by_user_id nullable +payment_account_id nullable +source_observation_id nullable +status # expected, scheduled, paid, reconciled, failed, cancelled +created_at +``` + +#### `RecurringCommitment` + +For insurance, memberships, subscriptions, rent, direct debits, standing orders. + +```text +id +household_id +provider +description +amount_expected +amount_min nullable +amount_max nullable +currency +interval # monthly, yearly, quarterly, weekly, custom +next_due_date +payer_account_id nullable +split_rule_id nullable +category_id nullable +project_id nullable +notice_period nullable +renewal_date nullable +status # active, paused, cancelled, unknown +matching_rule_json nullable +created_at +updated_at +``` + +#### `PromisedPayment` + +May be separate from `FinancialEvent`, or implemented as event type `promised_payment`. Prefer separate table only if extra lifecycle detail is needed. + +```text +id +household_id +related_event_id nullable +provider # Klarna, PayPal, credit_card, insurance, manual +amount +currency +created_date +due_date +expected_funding_account_id nullable +responsible_user_id nullable +status # expected, scheduled, debited, reconciled, failed, cancelled +source_observation_id nullable +created_at +updated_at +``` + +#### `ImportConnection` + +For connectors and local agent configuration metadata. Do not store plaintext secrets. + +```text +id +household_id +owner_user_id +connection_type # fints, psd2_aggregator, imap, paypal_api, csv_folder, local_folder +display_name +status # active, needs_auth, error, disabled +last_sync_at nullable +last_error nullable +secret_storage_ref nullable +runs_locally boolean +created_at +updated_at +``` + +### Key services/classes/components discussed + +#### Backend/domain services + +```text +ObservationIngestionService + accepts raw inputs and stores RawObservation + +ParserRegistry + selects parser by source_type, sender, file type, MIME type, CSV header, etc. + +CandidateEventService + turns parsed observations into candidate FinancialEvents + +DeduplicationService + exact hash/ID-based duplicate detection + +SemanticMatchingService + fuzzy matching across observations/events + +ReconciliationService + links PayPal/Klarna/bank/card lifecycle events + +LedgerService + confirms events, updates split lines, creates relations + +SettlementService + calculates who owes whom globally or per project + +BudgetService + calculates category and project budget states + +ProjectBudgetService + calculates budgeted/committed/paid/due/settled/reconciled values + +RecurringCommitmentService + tracks recurring expenses and expected future payments + +PromisedPaymentService + tracks PayPal/Klarna/credit card/direct debit future cash movements + +CategorizationService + rules first, local ML later, local LLM suggestions only if available + +PrivacyVisibilityService + filters events by account visibility and user permissions + +AuditLogService + records merges, edits, category changes, settlement changes +``` + +#### Importer/connectors + +```text +ManualEntryImporter +CsvImporter +BankCsvImporter +PayPalCsvImporter +ImapImporter +KlarnaEmailParser +PayPalEmailParser +PdfInvoiceImporter +ReceiptPhotoImporter +FintsConnector +Psd2AggregatorConnector +LocalAgentSyncClient +``` + +#### Matching functions + +```text +computeRawObservationHash(input): string + +computeNormalizedTransactionFingerprint(parsed): string + +findExactDuplicates(observation): DuplicateCandidate[] + +findSemanticMatches(candidateEvent): MatchCandidate[] + +scoreEventMatch(a, b): number + +linkEvents(from, to, relationType, confidence): EventRelation + +markDuplicate(source, duplicateOf): void + +reconcilePromisedPaymentWithBankDebit(promisedPayment, bankEvent): ReconciliationResult + +reconcilePayPalPurchaseWithFundingDebit(paypalEvent, bankEvent): ReconciliationResult + +reconcileCreditCardPurchaseWithStatementPayment(cardEvent, bankEvent): ReconciliationResult +``` + +#### Project functions + +```text +createProject(input): Project + +createProjectFromTemplate(templateName, participants): Project + +addProjectBudgetLine(projectId, input): ProjectBudgetLine + +addProjectPlannedItem(projectId, input): ProjectPlannedItem + +linkEventToProject(eventId, projectId, budgetLineId?): void + +addPaymentLine(input): PaymentLine + +calculateProjectBudget(projectId): ProjectBudgetSummary + +calculateProjectSettlement(projectId): SettlementSummary + +calculateProjectCashForecast(projectId): CashForecast + +calculateProjectOpenActions(projectId): ActionItem[] +``` + +#### UI components + +```text +DashboardPage +ImportInboxPage +RawObservationReviewQueue +CandidateEventReviewCard +DuplicateMatchReviewCard +HouseholdLedgerPage +Transaction/EventDetailPage +ProjectListPage +ProjectDetailPage +ProjectBudgetTable +ProjectTimeline +ProjectSettlementPanel +PromisedPaymentsCalendar +RecurringCommitmentsPage +SettlementOverview +ManualEntryForm +ReceiptUploadForm +ImapConnectionSettings +LocalAgentStatusPanel +AccountVisibilitySettings +``` + +### Duplicate/linking relationships + +Use relationship types instead of one boolean duplicate flag: + +```text +duplicate_of +same_economic_event_as +settles +funds +reimburses +refunds +reverses +part_of_statement +replaces_pending_authorization +``` + +### Matching strategy + +Use layered matching: + +```text +Layer A: exact technical deduplication + - source transaction ID + - message ID + - file hash + - attachment hash + - raw payload hash + - CSV import fingerprint + +Layer B: semantic matching + - amount + - currency + - date window + - merchant/counterparty similarity + - order ID + - invoice number + - PayPal transaction ID + - Klarna reference + - IBAN + - card last four digits + - receipt total + - due date + - email sender domain + +Layer C: confidence thresholds + >= 0.98: auto-link if safe + 0.75 - 0.98: review queue + < 0.75: keep separate +``` + +Conservative rule: a bad merge is worse than a missed merge. + +### Source authority hierarchy + +Use source confidence. + +```text +High authority: + booked bank/card/PayPal transaction + official statement + imported CSV from provider + +Medium authority: + invoice PDF + Klarna/PayPal email + merchant receipt + recurring contract register + +Low authority: + push notification + OCR line item + manual draft + browser capture +``` + +### Project budget calculations + +Each project should calculate: + +```text +budgeted_total +committed_total +paid_total +reconciled_total +settled_total +due_later_total +remaining_uncommitted_budget +current_settlement_balance +forecast_settlement_balance +open_actions +``` + +Example target output: + +```text +Project: Stockholm 2026 + +Budgeted total: 2,350 € +Committed so far: 1,455 € +Already paid: 775 € +Still due: 680 € +Remaining uncommitted: 895 € + +Current settlement: + B owes A 187.50 € + +Forecast settlement: + B will owe A 527.50 € if A pays all remaining committed items. + +Open items: + hotel balance due 2026-08-12 + accommodation receipt missing + 3 restaurant receipts uncategorized + local transport not yet budgeted +``` + +### Local AI/OCR assumptions + +Everything AI-related should run locally. + +Suggested local stack: + +```text +OCR: + Tesseract and/or PaddleOCR + +PDF extraction: + text extraction first + OCR only for scanned PDFs + +Invoice extraction: + template/rule-based parser first + invoice2data-style approach + +Categorization: + deterministic rules first + local classifier second + local embeddings for similarity third + local LLM only as assistant/suggester + +Local LLM: + optional + use only for structured suggestions + must not directly mutate confirmed ledger state +``` + +Categorization order: + +```text +1. deterministic user rules +2. previous merchant/account/category memory +3. local supervised classifier +4. local embeddings/similarity +5. local LLM suggestion +6. user review +``` + +## 6. Bugs, open questions, and TODOs + +### Bugs + +No code exists yet, so there are no known software bugs. + +### Unresolved compile/runtime issues + +None yet. + +No build system, package manager, database, migrations, Docker setup, test runner, or runtime has been created. + +### Open product questions + +These should be resolved soon, but do not block initial domain modeling: + +```text +- Exact tech stack: TypeScript/Node vs Python backend vs mixed. +- Whether the local connector agent is mandatory in v1 or introduced after local imports. +- Whether mobile app starts as PWA or native app. +- Whether backend is single-household self-hosted first or multi-tenant from day one. +- Whether data is encrypted field-by-field, database-level, or local-only for sensitive payloads. +- Whether raw observations are stored centrally, locally, or optionally both. +- Whether FinTS connector is Python local-agent only or backend-capable. +- Whether IMAP credentials are stored in local agent or backend encrypted vault. +- Which user authentication system to use. +- Whether project budgeting should support multiple currencies in v1. +``` + +### Important technical TODOs + +```text +- Choose initial stack. +- Create repository scaffold. +- Define domain schema and migrations. +- Implement RawObservation ingestion first. +- Implement manual entry first. +- Implement candidate event review. +- Implement exact deduplication. +- Implement event relations. +- Implement split lines and settlement calculation. +- Implement project model and project budget summary. +- Add CSV import. +- Add IMAP import. +- Add PDF/receipt import after core ledger works. +- Add local categorization rules. +- Add local-agent architecture before real bank connectors. +``` + +## 7. Constraints, preferences, naming conventions, style rules + +### Constraints + +```text +- AI must be local-only. +- Categorization must be local-only. +- OCR should be local-only. +- Bank connection should ideally happen locally. +- Server should not store plaintext banking credentials. +- Klarna Card cannot be assumed to have API access. +- CSV/manual/PDF/email imports must be treated as first-class sources. +- Duplicate detection and reconciliation are central. +- Privacy modes are required for multi-user support. +``` + +### Product preferences + +```text +- Explainability over opaque automation. +- Conservative deduplication. +- User review for uncertain matches. +- Raw evidence retained. +- Manual corrections should improve future suggestions. +- Project budgets should be explicit and useful for planning. +- Settlement calculations should show reasoning. +``` + +### Naming conventions + +Suggested names: + +```text +RawObservation: + untrusted/raw source item. + +FinancialEvent: + economic event or candidate event in ledger. + +EventRelation: + semantic relationship between events. + +EventObservationLink: + evidence relationship between observation and event. + +PromisedPayment: + known or inferred future cash movement. + +RecurringCommitment: + subscription/contract/standing expected payment. + +Project: + first-class budgeting/planning object. + +ProjectBudgetLine: + high-level budget bucket. + +ProjectPlannedItem: + planned/committed item inside project. + +PaymentLine: + partial payment attached to item/event. + +SplitLine: + economic responsibility allocation. + +SettlementSummary: + who owes whom and why. +``` + +Do not name everything `Transaction`. Reserve `Transaction` only for provider/bank-specific imported rows if needed, or avoid the term entirely in domain code. + +Better terms: + +```text +BankTransactionObservation +PayPalTransactionObservation +FinancialEvent +LedgerEntry +PaymentLine +``` + +### UI style preference + +No detailed UI style was decided. Functional preference: + +```text +- review queues +- explainable cards +- budget tables +- project timelines +- settlement panels +- confidence indicators +- evidence links +``` + +## 8. Exact next steps + +### Step 1: Create the initial repo + +Create a minimal monorepo. + +Recommended initial structure: + +```text +household-finance/ + apps/ + api/ + web/ + packages/ + domain/ + matching/ + db/ + migrations/ + docs/ + handover.md +``` + +Defer mobile and local-agent folders until the first backend/web skeleton exists, unless the chosen stack strongly favors creating them immediately. + +### Step 2: Add the handover note + +Save this handover as: + +```text +docs/handover.md +``` + +### Step 3: Define the domain package + +Create shared schemas/types for: + +```text +Household +User +Account +RawObservation +FinancialEvent +EventObservationLink +EventRelation +SplitLine +Category +Tag +Project +ProjectParticipant +ProjectBudgetLine +ProjectPlannedItem +PaymentLine +RecurringCommitment +PromisedPayment +ImportConnection +``` + +Use validation schemas if using TypeScript, e.g. Zod. Use Pydantic if using Python. + +### Step 4: Define database schema + +Create initial migrations for: + +```text +households +users +accounts +raw_observations +financial_events +event_observation_links +event_relations +split_lines +categories +tags +event_tags +projects +project_participants +project_budget_lines +project_planned_items +payment_lines +recurring_commitments +promised_payments +import_connections +audit_log +``` + +### Step 5: Implement minimal API + +Minimum endpoints: + +```text +POST /households +GET /households/:id + +POST /accounts +GET /accounts + +POST /observations/manual +GET /observations/inbox + +POST /events +GET /events +GET /events/:id +PATCH /events/:id + +POST /events/:id/confirm +POST /events/:id/relations +POST /events/:id/splits + +GET /settlement/summary + +POST /projects +GET /projects +GET /projects/:id +POST /projects/:id/budget-lines +POST /projects/:id/planned-items +GET /projects/:id/summary +GET /projects/:id/settlement +``` + +### Step 6: Implement manual entry flow + +Manual entry should create: + +```text +RawObservation(source_type = "manual") + -> Candidate FinancialEvent + -> optional SplitLine + -> optional Project assignment +``` + +Manual entry fields: + +```text +amount +currency +date +merchant/counterparty +description +paid_by account/user +event_type +category +project +tags +split rule +due date if promised payment +attachment optional +``` + +### Step 7: Implement exact deduplication + +Start with: + +```text +raw_hash +source_type + provider_transaction_id +message_id for email +file hash +normalized amount/date/merchant fingerprint +``` + +Create reviewable duplicate candidates. Do not auto-delete. + +### Step 8: Implement settlement calculation + +Start simple: + +```text +confirmed shared expenses only +single currency +equal split or explicit SplitLine amounts +exclude pending/promised by default +optionally include promised payments later +``` + +Settlement output must include explanation: + +```text +payer totals +share totals +net owed +events included +events excluded +pending/promised handling +``` + +### Step 9: Implement project budgeting v1 + +Project v1 should support: + +```text +project creation +participants +budget lines +planned items +manual payment lines +linking existing events to project +summary calculation +project settlement calculation +``` + +Do not wait for bank imports before building projects. + +### Step 10: Add importers + +After manual/project/settlement core works: + +```text +CSV importer v1 +IMAP importer v1 +PayPal email parser +Klarna email parser +PDF invoice importer +receipt photo OCR importer +``` + +### Step 11: Add local agent design + +Define but do not overbuild: + +```text +local-agent registers with backend +local-agent stores connector secrets locally +local-agent runs imports/connectors locally +local-agent submits RawObservations or normalized candidate events +backend never receives connector passwords +``` + +Possible local-agent API: + +```text +POST /local-agent/register +POST /local-agent/sync/observations +GET /local-agent/config +POST /local-agent/heartbeat +``` + +### Step 12: Add local categorization + +First version: + +```text +merchant/counterparty rules +IBAN rules +amount + recurrence rules +project context rules +manual correction memory +``` + +Only later add: + +```text +local classifier +local embeddings +local LLM structured suggestions +``` + +## 9. Anything that should not be repeated or reopened unless necessary + +Do not reopen the question of whether Klarna Card has a clean public transaction API unless new evidence is needed. Current working assumption: + +```text +Klarna Card API access is unavailable or unreliable. +Use IMAP, statements/PDFs, manual entry, GDPR export, and bank repayment reconciliation. +``` + +Do not design the platform as a plain transaction viewer. + +Do not treat PayPal/Klarna bank debits as ordinary expenses by default. They may settle prior obligations. + +Do not treat credit card bill payments as ordinary expenses by default. + +Do not let local AI or categorization directly mutate confirmed ledger entries without review or rules. + +Do not assume imported rows are final truth. Store them as observations/evidence. + +Do not overload categories with project names. Use: + +```text +category: holiday > restaurant +project: Stockholm 2026 +tags: optional flexible labels +``` + +Do not assume all users should see all transactions. Privacy modes are part of the design. + +Do not delay manual entry until connectors are ready. Manual entry is core. + +Do not delay project budgeting until imports are ready. Project budgeting is core. + +## 10. Assumptions about runtime/build/deployment environment + +These are starting assumptions for development, not confirmed requirements. + +```text +Development mode: + local machine development first. + +Deployment mode: + self-hosted or private household deployment first. + multi-tenant SaaS later only if regulatory/compliance issues are handled. + +Backend: + API server with relational database. + +Database: + PostgreSQL preferred for backend. + SQLite acceptable for early prototype/local-agent/testing. + +Frontend: + web app first. + +Mobile: + defer; possibly PWA first. + +Local connector agent: + separate process/app running on user-controlled machine. + stores secrets locally. + talks to backend through authenticated API. + +Bank connector: + not implemented in first coding pass. + architecture should allow FinTS/PSD2 connectors later. + +AI/OCR: + local process only. + no cloud OCR/LLM/categorization dependency. +``` + +## 11. Minimum viable development target + +The first useful prototype should not connect to banks yet. + +MVP target: + +```text +1. Create household and users. +2. Create accounts. +3. Manually enter expense/payment/promised payment. +4. Assign category, project, tags. +5. Attach raw evidence placeholder. +6. Split expense between users. +7. Detect exact duplicates among manual/CSV-like observations. +8. Show ledger. +9. Show settlement summary. +10. Create project with budget lines and planned items. +11. Show project budget summary: + budgeted / committed / paid / due later / settled. +``` + +This validates the domain model before spending time on connectors. + +## 12. Suggested first implementation milestone + +Milestone name: + +```text +M0: Local household ledger skeleton +``` + +Acceptance criteria: + +```text +- Repository builds. +- Database migrations run. +- API starts. +- Web app starts. +- User can create household, users, accounts. +- User can create manual RawObservation. +- System creates candidate FinancialEvent. +- User can confirm event. +- User can split event between users. +- Settlement summary shows who owes whom. +- User can create project. +- User can add project budget lines and planned items. +- User can link event to project. +- Project summary calculates budgeted, committed, paid, due later. +- Basic duplicate hash detection exists. +- Tests cover settlement and project summary calculations. +``` + +## 13. Suggested test cases + +### Settlement test + +```text +A pays 120 € groceries, common 50/50. +Expected: + A share = 60 € + B share = 60 € + B owes A = 60 € +``` + +### Shared account test + +```text +Shared account pays 100 € common expense. +If shared account is neutral household wallet: + no direct A/B reimbursement generated. +``` + +### Reimbursement test + +```text +B transfers A 60 € after A paid 120 € common. +Expected: + reimbursement settles previous imbalance. + transfer is not income. +``` + +### PayPal promised payment test + +```text +PayPal email creates 84 € promised payment due in 30 days. +Later bank debit from PayPal for 84 €. +Expected: + bank debit settles promised payment. + no duplicate expense created. +``` + +### Credit card test + +```text +Card purchase 50 € restaurant. +Later bank payment 50 € to card issuer. +Expected: + purchase is expense. + card payment is liability payment, not second expense. +``` + +### Project partial payment test + +```text +Hotel planned item: + budgeted 800 € + committed 760 € + deposit paid 200 € + due later 560 € +Expected: + committed = 760 € + paid = 200 € + due_later = 560 € +``` + +### Project settlement test + +```text +Project has 420 € transport paid by A and 200 € hotel deposit paid by B. +Split 50/50. +Expected: + A paid 420 € + B paid 200 € + total = 620 € + each share = 310 € + B owes A = 110 € +``` + +### Duplicate observation test + +```text +Same manual input imported twice with same raw hash. +Expected: + second observation flagged duplicate_source. + no second confirmed event unless user overrides. +``` + +## 14. Final note for the next coding agent + +Start with the domain model and ledger semantics. Connectors, OCR, IMAP, and local AI are important, but they should plug into the same `RawObservation -> CandidateEvent -> Ledger` pipeline later. + +The first code should prove that the platform can correctly answer: + +```text +What happened? +Who paid? +Who benefited? +Is it private or shared? +Is it already paid? +Is it still due? +Is it reconciled with evidence? +Is it settled between household members? +Which project/budget does it belong to? +What should happen next? +``` + +No blocking clarification is required before scaffolding a prototype. The main implementation choice still open is the tech stack; absent other instructions, a TypeScript monorepo with API, web app, shared domain package, PostgreSQL migrations, and a future local-agent package is the most straightforward starting point.