Fix/invoice delivery and payment accounts (#1116)

* fix: reconcile annual reports with final closing entries

* test: cover annual report depreciation and VAT balances

* Merge remote-tracking branch 'origin/main' into fix/usr-fdbck-ch

* fix: show exact invoice delivery details

* fix: use currency account in invoice emails

* fix: address invoice delivery review feedback

* fix: harden invoice delivery and payment accounts

* test: assert RLS-denied zero-row updates

* fix: close remaining invoice compliance gaps

* fix: harden invoice archive authorization

* fix: close invoice delivery review findings

* fix: verify delivery finalization results

* fix: cap combined invoice email recipients

* fix: close final invoice compliance findings

* fix: prevent stale payment account saves

* test: prove invoice delivery isolation

* fix: close invoice privacy review findings

* test: normalize delivery retention dates
This commit is contained in:
Mattsson
2026-07-23 09:54:02 +02:00
committed by GitHub
parent 321e684523
commit 466e55a015
83 changed files with 6619 additions and 671 deletions
+27
View File
@@ -283,3 +283,30 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
[2026-07-22] Stuck-committing recovery sweep (#843) rejects rows without positive evidence instead of reverting to pending, and only three op types (categorize_transaction, link_transaction_journal_entry, match_transaction_invoice) can recover to committed: no generic side-effect -> pending_op linkage exists yet (that is #842's posted-ids work), so evidence is limited to types whose params identify a target row with an unambiguous posted state; reverting to pending risks re-executing side-effects that posted without a trace (duplicate entries/emails).
[2026-07-22] MCP briefing recommended_tools (#1098) ships as a STATIC per-workflow loadout list, not state-gated: the briefing does not query workflow state (unbooked counts, open periods) today, so gating would add reads to the session-bootstrap hot path for marginal honesty; drift protection is a module-init assert against the tool registry + workflow-skill slugs, pinned by tests.
[2026-07-22] failed_partial (#842) is a TERMINAL, immutable pending_operations status, never released back to pending: the executor already posted an irreversible voucher/credit note, so a retry would double-post and a status rewrite would violate BFL 7 kap.; recovery is a manual storno guided by result_data.posted_ids. Exception kept: AccountsNotInChartError in match_transaction_invoice still releases to pending because that executor is re-entrant past the storno.
[2026-07-22] Give statutory annual reports a dedicated final-closing exclusion while preserving the broad year_end exclusion used by operational tax, disposition, and cash-flow reports: the annual report must retain booked depreciation, appropriations, and tax; closed legacy periods without a linked final closing entry are backfilled only when the canonical entry is unambiguous and otherwise fail explicitly.
[2026-07-22] Present tax and domestic VAT settlement accounts by net economic sign in statutory annual reports without rewriting posted entries: a debit on 2650 is a current receivable, while a credit remains a current liability.
[2026-07-22] Store invoice payment instructions as a currency-keyed company setting and keep legacy bank fields as the SEK compatibility mirror: invoice instructions must work without a bank integration, exact currency matching prevents foreign invoices from inheriting an unsafe SEK account, and archived delivery PDFs remain the historical snapshot.
[2026-07-22] Extend the immutable invoice delivery record with BCC instead of adding a second invoice event log: one delivery record now remains the source of truth for channel, status, time, recipients, message, and exact archived PDF.
[2026-07-22] Keep exact invoice delivery payloads as immutable server-side evidence while returning only masked To and CC domains plus operational metadata in the routine list: BCC and message content are confidential, and archived PDFs provide active-company-scoped document evidence without widening the list response.
[2026-07-23] Resolve the invoice currency's payment account inside the shared invoice email template: every dashboard, API, recurring, and queued send path must render the same payment instructions as its PDF, and central resolution prevents a foreign-currency email from leaking the legacy SEK account when a caller passes raw company settings.
[2026-07-23] Add a new migration before the currency-account backfill instead of editing the failed migration: immutable migration history is preserved, clean preview branches gain the legacy SEK columns before backfill, and environments that already have the columns remain safe through IF NOT EXISTS.
[2026-07-23] Restrict fixed and per-send invoice CC and BCC changes to owner and admin roles: an external copy is a separate disclosure decision, so both the API and database reject lower-role configuration changes before persistence, rendering, or invoice-number allocation.
[2026-07-23] Do not rewrite the already-replayed invoice recipient and payment-account migrations to add NOT VALID: immutable migration history takes precedence, and a later migration cannot remove the original deployment-time validation scan.
[2026-07-23] Exact invoice delivery payload is sender-only under RLS: all other active-company members use a SECURITY DEFINER summary that masks To and CC and omits BCC and message content.
[2026-07-23] Route invoice delivery writes through service-only RPCs and allow another sender to reclaim only a payload-free reservation older than 15 minutes: browser PostgREST clients cannot forge evidence, while a crashed render cannot permanently block vacation cover.
[2026-07-23] Keep complete invoice delivery evidence in the statutory archive through an owner/admin-only server client, while deferred booking receives only the latest sent document ID: company-wide accounting workflows remain complete without reopening exact browser payload access.
[2026-07-23] Treat fixed invoice CC and BCC addresses as owner/admin-approved company routing that applies to every authorized sender, while per-send additions require owner/admin on each request: configured routing supports vacation cover without letting members introduce a new recipient.
[2026-07-23] Require a usable payment account for every payable invoice currency, including SEK, before rendering or number allocation, and restrict payment-instruction changes to owner/admin: a numbered invoice must not be issued with blank or member-controlled remittance details.
[2026-07-23] Identify statutory current-year result rows with stable semantic keys while retaining label fallback for older snapshots: K2 and K3 presentation wording cannot bypass the annual-report result-integrity gate.
[2026-07-23] Keep exact invoice delivery payload in the owner/admin statutory archive instead of applying routine-list masking, and verify membership again with explicit user and company predicates before using the stateless service role: the archive preserves BFL evidence while the second guard limits cross-tenant impact from an RLS regression.
[2026-07-23] Preserve the legacy sender-email CC fallback and load the authenticated email in the send dialog preview: the user sees the same fixed recipient that the dashboard send route will resolve.
[2026-07-23] Require the current currency payment account on resends as well as first sends: resends render a new PDF from current settings, so allowing a missing account would distribute newly generated payment instructions that are blank or invalid.
[2026-07-23] Return only To and CC counts from the normal invoice-send response: fixed BCC routing applies to authorized senders but its existence and cardinality remain confidential outside the exact delivery archive.
[2026-07-23] Treat an unexpected delivery ID from a terminal delivery RPC exactly like an RPC error: the email outcome is already irreversible, so callers receive a reconciliation warning and failed-send cleanup never deletes an archive unless the expected row was actually finalized.
[2026-07-23] Cap the final de-duplicated To, CC, and BCC set at 20 before any delivery reservation, render, or number allocation: separate per-field limits could exceed the provider-safe total when fixed and per-send recipients were combined.
[2026-07-23] Mark invoice delivery, PDF, and statutory archive responses private and non-cacheable on success and failure, and omit BCC from both dashboard and v1 send responses: operational identifiers and blind recipients belong only in the restricted exact archive.
[2026-07-23] Block payment-account saves after server values change while local edits are dirty until the user explicitly reloads: silently preserving and later saving stale form state could overwrite another administrator's update.
[2026-07-23] Reconcile annual-report rounding residuals independently for each balance-sheet side and fail closed when a side cannot reach its own rounded exact total: cross-side netting could hide an incorrect reported fact behind a balanced grand total.
[2026-07-23] Validate preview-PDF payment settings before fetching customer data using the requested currency and document type: this preserves the same exemption semantics while minimizing personal-data processing for requests that cannot render.
[2026-07-23] Retain an exact pending delivery snapshot when the provider succeeds but the terminal evidence RPC cannot be confirmed, and keep it outside the preparing-only reservation lock: inventing a sent state would be unsafe, while immutable payload, PDF, operator warnings, and later explicit resend availability preserve evidence and recovery.
[2026-07-23] Keep the invoice-delivery DPIA as a documented screening rather than fabricating a full Article 35 assessment or DPO sign-off: the screened processing does not meet the high-risk threshold, and the implemented controls minimize routine access while preserving statutory evidence.