Fix/supp ag fb (#1023)

* fix: prevent credit notes from entering payment flow

* fix: persist and display customer personal numbers

* feat: configure automatic invoice reminder days

* fix: issue credit notes through send flow

* chore: add repository agent guidance

* feat(mcp): route tools across user companies

* fix(articles): delete unused register entries

* feat(invoices): improve issued invoice actions

* feat(supplier-invoices): retain uploaded source documents

* docs: record implementation decisions

* feat: enhance customer personal number handling and validation

- Updated CustomerForm to allow personal numbers in the format of "********-1234" for individual customers.
- Added validation to ensure personal numbers are only accepted for individual customers in CreateCustomerSchema.
- Implemented masking and encryption for personal numbers to enhance data protection.
- Introduced new utility functions for masking and encrypting personal numbers.
- Added database migration to enforce unique constraints on credit note relationships and prevent duplicate entries.
- Enhanced error handling and logging for credit note issuance and invoice processing.
- Updated tests to cover new credit note creation guards and personal number handling.

* test: enhance list companies test with supabase query mocks
This commit is contained in:
Mattsson
2026-07-15 15:53:15 +02:00
committed by GitHub
parent a558c75678
commit 072aedeaf9
116 changed files with 5708 additions and 669 deletions
@@ -0,0 +1,25 @@
# Data Classification and Handling
## Restricted data
Swedish personal identity numbers are Restricted personal data. They are not an
Article 9 special category by themselves, but their stable government identifier
role requires heightened protection.
Controls:
- Customer personal numbers are accepted only for individual customers.
- Values are encrypted with AES-256-GCM before database storage.
- API and UI output exposes only the last four digits.
- Writes require an authenticated company member with write permission.
- RLS and explicit `company_id` filters enforce tenant isolation.
- There is no endpoint that returns the full value.
- Logs and audit event payloads must never contain the full value.
## Internal business data
Article master records are Internal business data. An unused article may be
deleted because issued invoice lines, archived invoice PDFs, journal entries,
and audit events retain the accounting evidence independently. Any article that
is referenced by an invoice line is protected by the application check and the
database foreign key.
+23
View File
@@ -0,0 +1,23 @@
# Data Subject Rights Runbook
## Customer identity data
For access, correction, restriction, portability, or erasure requests, first
verify the requester and the tenant relationship. Search the company-scoped
customer record and any retained accounting documents. Customer master data may
be corrected or erased when no legal retention duty applies. Accounting records
and issued invoice documents remain retained for the statutory period; document
the Article 17(3)(b) exception in the response.
Full personal numbers are never returned through the ordinary customer API.
Exports and support evidence must use the masked value unless a separately
approved identity-verification procedure requires otherwise.
## Article master data
Article master records are not personal data and have no independent retention
duty. The delete endpoint allows deletion only when no invoice item references
the article. Issued invoice lines contain frozen descriptions, accounts, VAT
values, and amounts, while archived PDFs and journal records remain immutable.
This preserves the verification chain and the seven-year accounting retention
period even when an unused article master row is deleted.
+35
View File
@@ -8,6 +8,41 @@
processing_activities:
- id: customer.private_identity
name: Personnummer för privatkund
purpose: >-
Identifiera en privatkund när företagets avtal, fakturering eller
kundadministration kräver en entydig identitet. Personnumret får endast
sparas på kundtypen privatkund och exponeras endast maskerat i API och UI.
lawful_basis: art_6_1_b
special_category_basis: null
controller: gnubok-tenant
processor: supabase
data_subjects:
- customer
data_categories:
- user.government_id
recipients:
- name: Supabase
country: EU
role: processor
international_transfers:
applicable: false
mechanism: null
note: EU-only processor.
retention:
duration: customer_relationship_or_7y_if_accounting_record
basis: contract_and_bfl_7_kap
stored_in:
- customers.personal_number
- retained_invoice_documents_when_required
security_measures:
- aes_256_gcm_field_encryption
- masked_api_and_ui_output_last4_only
- write_role_required
- rls_company_scoped
- no_full_value_read_endpoint
- id: agi.submit
name: AGI inlämning till Skatteverket
purpose: >-