Files
accounted/.compliance/ropa.yaml
T
Mattsson 072aedeaf9 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
2026-07-15 15:53:15 +02:00

410 lines
16 KiB
YAML

# Record of Processing Activities (GDPR Art. 30)
#
# Each entry documents one processing activity. Field shape follows EDPB
# Guidelines 9/2022 §3 (controller-side RoPA): purposes, lawful basis,
# data subject + data category, recipients, transfer mechanism, retention,
# security measures. Add an entry whenever a new flow ships that touches
# personal data: onboarding, integrations, support, or regulator filings.
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: >-
Lämna in lagstadgad arbetsgivardeklaration på individnivå (AGI) till
Skatteverket varje månad (Skatteförfarandelagen 26 kap.). Innefattar
huvuduppgift (HU) och individuppgifter (IU) per anställd. Skatteverkets
kvittens sparas i response_data inklusive signeradAv: personnummer för
den som BankID-signerade inlämningen. Ändamålet är bevis för vem som
juridiskt undertecknade deklarationen samt behandlingshistorik; BFL
5 kap. 6 § och BFNAR 2013:2 kap. 8 kräver att räkenskapsinformationen
bevarar den faktiska ingivaren, medan själva inlämningen styrs av SFL.
lawful_basis: art_6_1_c # legal obligation
special_category_basis: null
controller: gnubok-tenant
processor: anthropic-na # software supplier; Skatteverket is recipient, not processor
data_subjects:
- employee
- company_signatory # firmatecknare/deklarationsombud (BankID-signerare av kvittensen)
data_categories:
- user.government_id # personnummer (anställda i IU; signerarens i response_data.signeradAv)
- user.name
- user.financial.employment # gross salary, tax withheld, benefits
- user.financial.tax # avgifter, sjuklönekostnad
recipients:
- name: Skatteverket
country: SE
role: legal_recipient
international_transfers:
applicable: false
mechanism: null
note: >-
Sweden-to-Sweden processor-to-public-authority flow. Adequacy decision
not applicable; no third-country transfer.
retention:
duration: 7y
basis: bfl_7_kap # BFL 7 kap. 2 §: räkenskapsinformation
stored_in:
- agi_declarations.xml_content
- agi_declarations.individuppgifter
- agi_declarations.response_data # SKV kvittens incl. signeradAv (signerarens pnr); access via company-membership RLS
- skatteverket_api_audit_log
security_measures:
- encryption_at_rest_supabase
- rls_company_scoped
- tls_1_3_to_skatteverket
- bankid_signing_required_for_filing
- immutable_audit_log
- personnummer_at_rest_encryption
- id: agi.kontrollera.preflight
name: AGI pre-flight kontrollera (HU/IU)
purpose: >-
Skicka enskild HU eller IU som JSON till Skatteverkets kontrollera-
ändpunkt (v1.7 §7/§8) för dry-run-validering av felmeddelanden och
STOPP-/AVVISANDE-status innan ett fullständigt underlag laddas upp.
Skatteverket lagrar inget från denna kontroll; svaret driver vår UI
som låter användaren rätta felaktigheter i lönekörningen lokalt.
lawful_basis: art_6_1_c # legal obligation (ancillary to AGI filing)
special_category_basis: null
controller: gnubok-tenant
processor: anthropic-na
data_subjects:
- employee
data_categories:
- user.government_id # personnummer (BetalningsmottagarId)
- user.financial.employment # gross salary, tax withheld, benefits
recipients:
- name: Skatteverket
country: SE
role: legal_recipient
international_transfers:
applicable: false
mechanism: null
note: Sweden-to-Sweden flow; no third-country transfer.
retention:
# Skatteverket retains nothing for kontrollera calls. Our outbound
# audit row in skatteverket_api_audit_log records who-called-what-when
# but NOT the payload body, minimising at-rest footprint.
duration: 7y
basis: bfl_7_kap
stored_in:
- skatteverket_api_audit_log
security_measures:
- strict_zod_allow_list_input_validation
- request_size_cap_64kb
- rbac_company_member_role_check
- rls_company_scoped
- tls_1_3_to_skatteverket
- immutable_audit_log
- no_payload_body_persisted
- id: moms.declaration
name: Momsdeklaration till Skatteverket
purpose: >-
Lämna in lagstadgad momsdeklaration (utkast, lås och signering) till
Skatteverkets momsdeklaration-API (Mervärdesskattelagen 17 kap. 24 §).
lawful_basis: art_6_1_c
special_category_basis: null
controller: gnubok-tenant
processor: anthropic-na
data_subjects:
- business_owner
data_categories:
- user.government_id # orgnummer (juridiska personer) eller pnr
- user.financial.tax # rutor 05-62
recipients:
- name: Skatteverket
country: SE
role: legal_recipient
international_transfers:
applicable: false
mechanism: null
note: Sweden-to-Sweden flow; no third-country transfer.
retention:
duration: 7y
basis: bfl_7_kap
stored_in:
- extension_data (utkast metadata)
- skatteverket_api_audit_log
security_measures:
- rls_company_scoped
- tls_1_3_to_skatteverket
- bankid_signing_required_for_filing
- immutable_audit_log
- id: psd2.cash_account_mirror
name: PSD2-konton speglas till cash_accounts
purpose: >-
När en bank-anslutning via Enable Banking returnerar kontolista efter
lyckad PSD2-consent kopieras kontometadata (IBAN, valuta, kontonamn,
external_uid) till cash_accounts så att avstämning, motkontoresolver
och __PRIMARY_SEK__-sentinel kan rutta verifikat utan att läsa JSONB
från bank_connections.accounts_data vid varje fråga.
lawful_basis: art_6_1_b # contract (PSD2 consent + bookkeeping service)
special_category_basis: null
controller: gnubok-tenant
processor: anthropic-na
data_subjects:
- business_owner
data_categories:
- user.financial.bank_account # IBAN
- user.contact # account name (kontotitel)
recipients:
- name: Supabase
country: EU
role: processor
international_transfers:
applicable: false
mechanism: null
note: EU-only processor; no third-country transfer.
retention:
duration: consent_lifetime
basis: psd2_consent
stored_in:
- cash_accounts
- bank_connections.accounts_data
security_measures:
- rls_company_scoped
- data_minimization_no_balance_on_callback
- failure_emitted_to_event_log
- id: transactions.counterparty_iban
name: Motpartens IBAN på transaktioner
purpose: >-
Spara motpartens IBAN på transaktionsraden så att own-account-detector
kan identifiera överföringar mellan företagets egna konton (1930 → 1932
etc.) och bokföra båda benen automatiskt istället för att felbokföra
utflödet som extern kostnad. Krävs även för payment-matchning mot
leverantörsfakturor.
lawful_basis: art_6_1_b # contract (bookkeeping service)
special_category_basis: null
controller: gnubok-tenant
processor: anthropic-na
data_subjects:
- business_owner
- counterparty
data_categories:
- user.financial.bank_account # counterparty IBAN
recipients:
- name: Supabase
country: EU
role: processor
international_transfers:
applicable: false
mechanism: null
note: EU-only processor.
retention:
duration: 7y
basis: bfl_7_kap
stored_in:
- transactions.counterparty_iban
security_measures:
- rls_company_scoped
- immutable_after_post
- id: skattekonto.drift_alert
name: Skattekonto-drift via e-post
purpose: >-
Underrätta företagets kontaktadress när det cachade Skatteverket-saldot
avviker från GL 1630 utöver konfigurerad tolerans (> 1 SEK), så
bokföraren kan granska skattekonto-raderna. E-postmeddelandet
innehåller ingen finansiell siffra utan en länk till autentiserad
dashboard; mottagaren valideras mot company_members innan utskick.
lawful_basis: art_6_1_f # legitimate interest (bookkeeping accuracy)
special_category_basis: null
controller: gnubok-tenant
processor: resend
data_subjects:
- business_owner
- company_member
data_categories:
- user.contact.email
recipients:
- name: Resend
country: US
role: processor
international_transfers:
applicable: true
mechanism: scc_2021_c2p
note: >-
Resend (US): SCC Module 2 (controller-to-processor). Outbound
payload limited to ett notifieringsmail utan finansiella belopp;
TIA dokumenterad i .compliance/tia/resend.md.
retention:
duration: 30d
basis: event_log_ttl
stored_in:
- event_log
security_measures:
- recipient_membership_check_before_send
- no_financial_figures_in_body
- tls_to_resend
- rls_company_scoped
- id: ai.inference
name: AI-inferens (kategorisering + dokumenttolkning) via Amazon Bedrock
purpose: >-
Föreslå bokföringskategori för banktransaktioner och tolka/extrahera
uppladdade underlag (kvitton, leverantörsfakturor) med Anthropic
Claude-modeller körda i Amazon Bedrock. Endast aktiv när tenanten
uttryckligen aktiverat AI-funktioner: kärntjänsten (bokföring, fakturor,
moms, rapporter) fungerar fullt ut utan AI.
lawful_basis: art_6_1_a # consent: opt-in, AI features off by default
special_category_basis: null
controller: gnubok-tenant
processor: aws-bedrock
data_subjects:
- business_owner
- counterparty # namn/belopp på uppladdade underlag
data_categories:
- user.financial # transaktionsdata skickad för kategorisering
- user.document # uppladdade kvitton/fakturor för OCR/extraktion
recipients:
- name: Amazon Web Services (Amazon Bedrock)
country: EU
role: processor
international_transfers:
applicable: false
mechanism: null
note: >-
Inferens körs i AWS-regionen eu-north-1 (Stockholm): ingen överföring
till tredje land. AWS DPA + SCC + DPF-certifiering finns som
skyddsmekanism. Prompter lagras ej hos Bedrock efter anropet och används
ej till modellträning.
retention:
duration: none_at_processor
basis: no_retention_bedrock # prompt not persisted by Bedrock post-inference
stored_in:
- ai_usage_tracking # usage metadata only (tokens/cost), no payload body
security_measures:
- opt_in_consent_required
- eu_region_inference_eu_north_1
- prompts_not_retained_after_inference
- not_used_for_model_training
- rls_company_scoped
- tls_to_bedrock
- id: mcp.telemetry
name: MCP/agent-telemetri i event_log
purpose: >-
Varje MCP-verktygsanrop loggar metadata (verktygsnamn, felkod,
felmeddelande max 500 tecken, latens, aktör, session, frivillig
distributionskanal-markör, t.ex. 'openclaw' via X-Gnubok-Client-header
eller ?client=-parameter, sanerad mot allow-list och aldrig använd för
auktorisation) och varje skill-laddning loggar slug/tier till event_log.
Syftet är tillförlitlighetsanalys av agentgränssnittet: felfrekvens per
verktyg, adoption per distributionskanal, korrelation mellan laddade
skills och efterföljande fel, samt agenters egenrapporterade feedback
(agent.feedback). Inga verktygsargument eller verktygsresultat
persisteras.
lawful_basis: art_6_1_f # legitimate interest (service reliability/improvement)
special_category_basis: null
controller: gnubok-tenant
processor: supabase
data_subjects:
- business_owner
data_categories:
- user.unique_id # userId, actorId (API-nyckel-id), sessionId
- user.contact # actorLabel (användarvald API-nyckeletikett)
recipients:
- name: Supabase
country: EU
role: processor
international_transfers:
applicable: false
mechanism: null
note: EU-only processor; no third-country transfer.
retention:
# Differentiated TTL via /api/events/cleanup/cron: mcp.*/agent.*-rader
# behålls 180 dagar (felfrekvens-trender kräver mer än leveransfönstret);
# övriga event_log-rader (leveranshändelser) 30 dagar.
duration: 180d
basis: legitimate_interest_reliability
stored_in:
- event_log
security_measures:
- rls_user_scoped_select # event_log SELECT: auth.uid() = user_id
- service_role_only_writes
- error_message_truncated_500_chars
- no_tool_args_or_results_persisted
- id: arsredovisning.bolagsverket.submit
name: Digital inlämning av årsredovisning till Bolagsverket
purpose: >-
Lämna in årsredovisningen (iXBRL) digitalt till Bolagsverkets eget
utrymme (ÅRL 8 kap.). Avsändarens och undertecknarens personnummer
krävs av Bolagsverkets API (skapa-inlamningtoken, lamna-in) och
används transient i anropen; i databasen sparas endast
företagssaltade SHA-256-hashar. Fastställelseintyget signeras med
e-legitimation hos Bolagsverket, aldrig i appen.
lawful_basis: art_6_1_c # legal obligation (ÅRL filing duty)
special_category_basis: null
controller: gnubok-tenant
processor: anthropic-na # software supplier; Bolagsverket is recipient, not processor
data_subjects:
- business_owner # avsändare/undertecknare (styrelseledamot, VD)
data_categories:
- user.government_id # personnummer (transient; at rest only salted SHA-256 hash)
- user.name # undertecknarens namn
- user.contact # undertecknarens/kvittens e-post
- user.financial # årsredovisningens finansiella innehåll
recipients:
- name: Bolagsverket
country: SE
role: legal_recipient
international_transfers:
applicable: false
mechanism: null
note: Sweden-to-Sweden flow to a public authority; no third-country transfer.
retention:
duration: 7y
basis: bfl_7_kap # filed .xhtml archived as räkenskapsinformation
stored_in:
- arsredovisning_submissions # status, idnummer, checksums, PNR hashes only
- document_attachments # the exact filed iXBRL bytes (WORM)
security_measures:
- mtls_client_certificate_to_bolagsverket
- mtls_key_env_only_injected_from_secret_manager # never in settings/DB; see .env.example custody note
- pinned_endpoint_allowlist_per_environment # HOSTS map in client.ts; not env-configurable
- personnummer_never_persisted_plaintext_salted_sha256_only
- personnummer_never_logged
- webhook_secret_constant_time_validation
- rls_company_scoped
- immutable_status_machine_trigger