Commit Graph
9 Commits
Author SHA1 Message Date
MattssonandClaude Fable 5 db8983ba9e Add/bokslut (#718)
* feat(arcim-migration): Briox provider with SIE-over-API import

- Briox auth via account ID + application token (no app-level
  credentials); both tokens rotate on refresh and are persisted
- New sie-fetcher pulls the general ledger as SIE through the
  provider API for Fortnox, Briox and Bjorn Lunden
- Wizard stops on a failed SIE import and surfaces the real errors
  instead of proceeding to the misleading migrate-guard message
- PROVIDER_SIE_ONLY_FORTNOX renamed to PROVIDER_SIE_NOT_SUPPORTED;
  new PROVIDER_TOKEN_INVALID for rejected provider credentials

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(bookkeeping): per-line accruals (periodisering) on invoices and supplier invoices

Defer revenue/costs per invoice line to 29xx/17xx interim accounts with
automatic monthly dissolution (nightly cron + catch-up at registration),
schedule cancellation on credit, year-end auto-detect exclusion for
already-scheduled invoices, invoice-inbox service-period extraction for
prefill, and an MCP tool to list schedules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(bokslut): iXBRL arsredovisning generation and Bolagsverket digital filing

Generate the annual report as iXBRL from a generated taxonomy registry
(K2 element lists, taxonomy:generate/check scripts + CI guard), expose it
via the fiscal-period API, and add the bolagsverket extension for digital
submission to eget utrymme with webhook-driven status tracking
(submissions table + pg tests, lifecycle events, year-end wizard UI).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(mcp): raise origin-guard test timeout to 20s

The dynamic import pulls in the full server module; the parse alone
flirts with the 5s default under full-suite parallel load.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Add new scripts and documentation for K2 AB taxonomy generation and validation

- Introduced `generate-taxonomy-registry.ts` to automate the generation of the iXBRL taxonomy concept registry from official element lists and tuple models.
- Added `validate-ixbrl.mjs` for validating generated iXBRL reports against the official taxonomy package using Arelle.
- Included new documentation files:
  - `k2-ab-arsredovisning-elementlista-2024-09-12_rev20250312_sv.xlsx`
  - `tuple-innehallsmodell-arsredovisning-k2-2024-09-12.xlsx`
  - `taxonomi-paket-2024-09-12_rev20250312.zip`

* Add tests for bookkeeping accruals dissolution and supplier invoices

- Implement tests for the POST /api/bookkeeping/accruals/[id]/dissolve route, covering success and error scenarios.
- Add tests for the DELETE /api/supplier-invoices/[id] route, including authentication checks and validation of invoice deletion conditions.
- Introduce tests for the Arcim migration provider client, ensuring token handling and error classification.
- Create tests for the Bolagsverket extension, validating submission role enforcement and environment settings.
- Add Zod schemas for Bolagsverket response payloads to ensure proper validation.
- Implement tests for MCP server's list accrual schedules, confirming registration and scope mapping.
- Add consistency tests for IXBRL document generation, ensuring duplicate facts and XML escaping are handled correctly.
- Introduce typed domain errors for accrual schedules to improve error handling in the service.
- Add tests for resolving consent with Briox token refresh concurrency, ensuring proper token management and error handling.

* fix(tests): update payload size guard comments to reflect recent changes in tool descriptions and ceiling adjustments

* fix(gitattributes): mark generated JSON files in bokslut taxonomy as linguist-generated

* feat(migrations): add backfill for invoices.journal_entry_id and fallback for next_voucher_number user_id

* feat(bokslut): enhance compliance and financial processing features with new submission details and security measures

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 16:35:30 +02:00
Jakob WennbergandClaude Fable 5 205610d200 feat(mcp): distribution-channel client marker in MCP telemetry (#706)
* feat(mcp): distribution-channel client marker in MCP telemetry

Record an optional client marker on mcp.tool_called, mcp.tools_list_called
and mcp.resource_read events so per-channel adoption (e.g. the OpenClaw
skill) is measurable in event_log (180-day TTL).

- Server reads X-Gnubok-Client header, falling back to a ?client= query
  param on the endpoint URL. Sanitized ([A-Za-z0-9._-]{1,64}, lowercased),
  telemetry-only — same trust level as Mcp-Session-Id, never auth.
- The query param works with the already-published gnubok-mcp 1.0.1 via
  GNUBOK_URL, so no npm release is required to start measuring.
- Bridge 1.1.0 additionally forwards GNUBOK_CLIENT as X-Gnubok-Client.

OAuth-path attribution via DCR client_name is a possible follow-up — DCR
is stateless today, so client_name isn't recoverable at token time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(mcp): address PR #706 compliance findings

- ropa.yaml: declare the distribution-channel marker in the mcp.telemetry
  processing activity (GDPR Art. 30 — RoPA was drifting from actual flow)
- bridge: mirror the server's allow-list on GNUBOK_CLIENT so an invalid
  value degrades to no header instead of fetch() rejecting every request
- lib/events/types.ts: annotate client as client-supplied/telemetry-only
- test: pin that the allow-list runs on the percent-decoded ?client= value

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 14:33:24 +02:00
Jakob WennbergandClaude Opus 4.8 bc61862e76 feat(agent): telemetry + CI-gate quick wins from the "AI systems that ship" audit (#677)
* feat(agent): telemetry completeness + durability, CI gates, commit_method provenance

Quick wins from the "Building AI systems that ship" audit:

- mcp.tool_called gains errorMessage (message_sv, truncated 500 chars) on
  all failure exits; new mcp.skill_loaded event on every gnubok_load_skill
  (all tiers) so atom usage is finally measurable
- event_log: (event_type, created_at) index; cleanup cron keeps
  mcp.*/agent.* telemetry 180 days (delivery events stay 30)
- CI: lint ratchet (npm run check:lint — 60 legacy errors baselined,
  fails only on NEW errors) and a pg-real coverage gate (migrations
  touching trigger/RPC/RLS/DEFERRABLE require a *.pg.test.ts change;
  escape hatch: -- pg-test: covered-by/skip)
- journal_entries.commit_method CHECK widened with 'api_key'/'agent';
  the MCP approve path records 'api_key' truthfully instead of
  'user_accept' (agent_first_vision §8 P0-1). 'agent' is reserved — ALL
  MCP traffic (incl. claude.ai OAuth, whose access_token is a minted
  API key) authenticates as api_key today

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(import): derive opening balances from prior-year #UB when SIE lacks #IB (#675)

SIE files exported without #IB 0 rows (only #UB -1) previously imported
with zero opening balances. getEffectiveOpeningBalances() now derives IB
from prior-year UB for balance-sheet accounts when explicit #IB is
absent, surfaces the derivation as an info issue in the import preview,
and excludes share-capital vouchers from opening-balance detection.
Detection regexes are shared between parser and importer so the two
checks cannot drift. 507 lib/import tests pass.

(Authored in a parallel session in this checkout; included per request.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(review): address PR #677 bot findings — RoPA entry, execFileSync, gate scope note

Triage of the compliance-swarm + Greptile findings:

Applied:
- .compliance/ropa.yaml: new mcp.telemetry processing activity declaring
  the 180-day mcp.*/agent.* retention, lawful basis, data categories, and
  the no-args/no-results minimisation (ISO A.8.10, GDPR Art.5(1)(c) —
  the retention split is now formally documented, referenced from the cron)
- check-pg-test-coverage.mjs: execFileSync with argv array — no shell, so
  a hostile base-ref can't inject (ASVS V13.2.1); verified an injection
  attempt exits 2 without executing
- check-pg-test-coverage.mjs: documented the PR-level (not per-migration)
  scope of the gate so reviewers know to check coverage per migration when
  a PR carries several risky migrations (Greptile P2)

Acknowledged, no change:
- errorMessage PII risk: messages are domain-mapped strings; event_log
  already persists far richer delivery payloads under the same RLS; now
  declared in ropa.yaml
- cron error envelope: errorResponse maps to the canonical safe envelope
  and the endpoint is CRON_SECRET-gated
- two-pass delete "partial state": TTL deletes are idempotent — the next
  daily run sweeps whatever a failed pass left behind
- skill_loaded actorLabel/sessionId: mirrors the pre-existing
  mcp.tool_called payload; sessionId is the join key the analytics exist for

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 15:47:13 +02:00
Jakob WennbergandClaude Opus 4.8 c74b19df1b Accounted rebrand + swarm-skill cleanup + bank-reconciliation fixes (#643)
* feat(reconciliation): close the bank-feed loop on voucher links and re-tag mis-typed opening balances

Two related fixes to bank reconciliation correctness:

1. Auto-reconcile on voucher link. Linking an invoice or supplier invoice to
   an existing voucher previously advanced only the invoice — the bank
   transaction that paid it kept sitting in the Transactions inbox with a null
   journal_entry_id. linkInvoiceToVoucher / linkSupplierInvoiceToVoucher now
   call autoReconcileTransactionForLinkedVoucher (lib/reconciliation), which
   links the bank transaction to the same verifikat when exactly one unbooked
   line matches it. Best-effort and post-commit: a failure here never fails the
   link. The result surfaces reconciledTransactionId; the inbox row leaves the
   list and the UI shows link_success_tx_reconciled.

2. Re-tag mis-typed opening balances. getReconciliationStatus and the GL-line
   matching RPCs identify a cash account's ingående balans solely by
   journal_entries.source_type='opening_balance'. Companies migrated from other
   systems often booked the bank IB as an ordinary voucher (source_type
   'import' or 'manual'), so it was never excluded and surfaced as a phantom
   reconciliation difference equal to the opening balance. Adds:
   - migration mark_entry_as_opening_balance: a GUC-gated carve-out in the
     immutability trigger plus a SECURITY DEFINER RPC that validates the entry
     (balance-sheet lines only, dated on a fiscal-period boundary), flips the
     source_type, and writes an audit row — no blanket data sweep.
   - POST /api/reconciliation/bank/mark-opening-balance + MarkOpeningBalanceSchema.
   - BankReconciliationView action to trigger it from the IB diff.

The gnubok_create_voucher executor now accepts a typed is_opening_balance flag
and derives source_type='opening_balance' only after validating class 1/2 lines
on the period start, so new IBs land correctly typed.

Covered by lib/reconciliation auto-reconcile tests, voucher-executors tests,
and a mark-entry-as-opening-balance pg-real test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: rebrand gnubok → Accounted and prune swarm agent skills

Product rebrand and skills housekeeping. No runtime behaviour change.

Rebrand: replace user-visible "gnubok" with "Accounted" across docs, READMEs,
in-code comments, doc-site content, MCP skill/resource prose, and the
gnubok-mcp package description. The MCP resource URI scheme is moved gnubok://
→ Accounted:// consistently across resource registrations, the event-type
comment, and the resource/skill tests. Deliberately preserved as stable
identifiers (NOT rebranded): the gnubok-company-id cookie, gnubok_sk_ / gnubok_inv_
token prefixes, the gnubok-mcp npm bridge name, and the AGI <gem:Programnamn>
value (kept 'gnubok' per its source comment — it is the software identifier sent
to Skatteverket and must not churn across visual rebrands).

Skills: remove the 27 swarm-* agent SKILL.md atoms (no longer used; already
absent from the agent_atom_registry in prod), refresh the remaining skill docs,
add the .claude/rules/ path-scoped rule set, and regenerate the
seed_agent_atom_bodies migration + .skill-body-manifest.json via
`npm run skills:generate` so the DB-backed skill bodies match the trimmed set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 10:52:01 +02:00
Jakob WennbergandClaude Opus 4.8 953980c875 Per-account bank reconciliation + overdue/inbox/privacy fixes (#619)
* feat(reconciliation): scope bank reconciliation per cash account via transactions.cash_account_id

A company with two same-currency cash accounts (e.g. checking 1930 + a
savings account) saw every SEK transaction on every account, and the
status card summed across both — reconciliation filtered transactions by
CURRENCY while filtering GL lines by ACCOUNT (issue #604).

Bind each bank transaction to the cash_accounts row it settled on:

- New nullable transactions.cash_account_id FK (ON DELETE SET NULL —
  a bank transaction is räkenskapsinformation, BFL 7 kap, and must
  survive cash-account deletion) + a best-effort 4-pass backfill.
- All reconciliation/transaction queries scope to the selected account
  with a NULL->currency fallback, so legacy/un-backfilled rows never
  disappear mid-backfill.
- ingestTransactions stamps cash_account_id from the batch's
  settlementAccount; categorize + manualLink resolve and use it.
- Bank leg now books to the transaction's actual settlement account via
  applySettlementAccount (no-op for 1930), so interest/fees on a
  savings/EUR account reconcile instead of mis-booking to 1930.
- manualLink cross-checks the transaction's account and requires a
  voucher line on the selected account (no silent cross-account links).
- BankReconciliationView: quick-book menu for any settlement account,
  in-flight request abort on account/date switch, 500-row truncation
  notice, per-account state reset.
- pg-real coverage for the FK, all backfill passes, account-scoped
  query isolation, and cross-company isolation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(supplier-invoices): stop marking paid invoices and credit notes as overdue

update_overdue_supplier_invoices() (the daily pg_cron job) flipped every
past-due 'registered'/'approved' row to 'overdue' without looking at the
outstanding balance. Credit notes — created 'registered', remaining 0,
due today — got flipped the next day, surfacing as "Förfallen" with
"kvar att betala 0 kr"; so did any fully-paid invoice left in
'registered'/'approved'.

Guard the cron on remaining_amount > 0.005 (the "fully paid" threshold
used by the payment/match paths) and is_credit_note = false, and backfill
the rows already mis-flagged (credit notes -> 'registered', paid ->
'paid' with paid_at stamped only when missing). pg-real coverage for the
guarded function and the one-off backfill.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(invoice-inbox): refresh dokumentinkorg on realtime row changes

The InvoiceInboxWorkspace only refetched on mount and on explicit
in-component actions. When an inbox item was resolved out of band — the
in-app agent sheet committing a staged create_supplier_invoice_from_inbox
/ book-direct op, the /pending page approving one, or another tab booking
it — none of those paths called fetchItems(), so the booked underlag
stayed in "Att göra" until a manual reload (issue #600).

Add invoice_inbox_items to the supabase_realtime publication (mirrors the
/pending fix in 20260520120100) and subscribe in the workspace, refetching
the whole list on any change so derived status/counts/ordering stay
authoritative. RLS scopes the channel to the user's company. fetchItems
now preserves optimistic upload placeholders so a refetch firing
mid-upload can't drop an in-flight row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(privacy): disclose EU AI inference via Amazon Bedrock (eu-north-1)

Update the privacy policy and DPA to state that AI inference, when AI
features are enabled, runs inside the EU via Amazon Bedrock (eu-north-1,
Stockholm) using Anthropic's Claude models — no transfer to a third
country, prompts not retained after the call or used for model training.
Add AWS as a subprocessor row and refresh the "last updated" dates.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(migrations): rename invoice_inbox_realtime to avoid version collision

main's #617 shipped 20260605120000_transactions_original_description.sql —
the same version this branch used for the inbox-realtime publication. The
Supabase migration tracker keys on the numeric version, not the filename, so
the preview branch failed with a duplicate-key error on
supabase_migrations.schema_migrations (version 20260605120000 already
exists). Rename to the unique version 20260605120500; the body
(ALTER PUBLICATION) is order-independent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(reconciliation): align run guard with status; harden filter interpolation

Addresses PR review (greptile + compliance swarm):

- The v1 and core bank/run routes rejected an unknown account uniformly,
  including the default '1930', while the status routes were lenient for
  '1930'. A company reconciling its primary SEK account without a
  cash_accounts row got 200 from status but 400 from run. Make run match
  status: '1930' falls back to currency-only scoping (cashAccountId
  undefined); non-default unknown accounts are still rejected. Adds a test.
- /api/transactions accepts a user-supplied `currency` query param that was
  interpolated raw into a PostgREST .or() filter. Reject anything that isn't
  a 3-letter ISO code — RLS already scopes to the company, but an
  unsanitized value could otherwise malform/widen the filter. Assert
  currency/cashAccountId shape in scopeTransactionsToAccount as well.
- categorize: log (instead of silently swallowing) a cash_accounts
  settlement-account lookup error, so a fall-back-to-1930 mis-booking is
  observable in the audit log.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(migrations): correct backfill UPDATE..FROM join; idempotent realtime publication

Two SQL errors that only surface on real Postgres (CI pg-real + Supabase
preview) — the unit suite mocks Supabase, so neither was caught locally.

- Backfill pass (a): `UPDATE transactions t ... FROM journal_entry_lines jel
  JOIN cash_accounts ca ON ca.company_id = t.company_id` referenced the UPDATE
  target `t` inside the FROM join's ON clause, which Postgres rejects ("invalid
  reference to FROM-clause entry for table t"). Move the company match to WHERE;
  the JOIN now relates jel<->ca only. Semantics unchanged.
- invoice_inbox_realtime: `ALTER PUBLICATION ... ADD TABLE` is not idempotent
  (SQLSTATE 42710 if the table is already a member). The earlier
  version-collision push partially applied it on the Supabase preview branch, so
  the re-apply errored. Guard with a pg_publication_tables existence check.

Both statements validated against a real Postgres: the single-line tx binds, the
two-bank-line transfer stays NULL, and the publication add runs twice cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(migrations): backfill pass (c) uses array_agg, not min(uuid)

Postgres has no min() aggregate for uuid, so pass (c)'s min(id) raised
"function min(uuid) does not exist" on apply (CI pg-real + Supabase). The
HAVING count(*) = 1 already guarantees one row per group, so (array_agg(id))[1]
returns that single id.

Validated the full backfill (all four passes) and the overdue migration against
a real Postgres: every pass binds / falls through as intended, and the overdue
guard + backfill produce the right statuses.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compliance): add RoPA entry for Amazon Bedrock AI inference (GDPR Art.30)

The privacy policy now discloses AI inference (transaction categorization +
document/receipt OCR) via Amazon Bedrock as a processing activity, but
.compliance/ropa.yaml had no matching Art.30 record. Add it: opt-in consent
basis, EU-region (eu-north-1) inference with no third-country transfer, prompts
not retained or used for model training. Mirrors the privacy-page disclosure
shipped in this PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 18:26:13 +02:00
Mattsson 8a6ce7093e feat: implement skattekonto drift detection and alerting (#525)
* feat: implement skattekonto drift detection and alerting

- Add skattekonto drift computation logic to compare Skatteverket's saldo with GL 1630 sum.
- Implement alerting mechanism for significant drift changes, with throttling to prevent alert spamming.
- Introduce database functions to sum GL 1630 entries and list unbooked skattekonto rows.

feat: create own account transfer detection

- Develop logic to detect transfers between a company's own cash accounts based on counterparty IBAN.
- Implement tests to validate detection logic under various scenarios, including matching and non-matching IBANs.

feat: establish cash accounts as a first-class entity

- Create cash_accounts table to manage routable cash accounts, replacing ad-hoc JSONB structures.
- Implement functions for listing, upserting, and managing cash accounts, including primary account designation.

feat: enhance GL line reconciliation functionality

- Modify get_unlinked_1930_lines RPC to accept any account number for reconciliation, improving flexibility for different currencies.
- Update related functions to ensure compatibility with the new cash_accounts structure.

feat: capture counterparty IBAN in transactions

- Add counterparty_iban column to transactions table to facilitate intra-account transfer detection.
- Create index for efficient lookups based on counterparty IBAN.

* feat: Enhance cash account handling and reconciliation processes

- Updated reconciliation routes to enforce cash account validation for all account numbers, including '1930'.
- Improved error handling for unknown cash accounts in reconciliation status and unmatched entries routes.
- Changed CashAccountSelector to use sessionStorage instead of localStorage for better data privacy.
- Fixed mapping for employer payroll taxes to route to the correct account (2730 instead of 2731).
- Added safety checks for company IDs in the guessCounterAccount function to prevent injection vulnerabilities.
- Introduced atomic RPC for setting primary cash accounts to avoid intermediate states during updates.
- Seeded default cash accounts for new companies to ensure reconciliation routes are accessible from day one.
- Updated email notifications for drift detection to avoid exposing sensitive financial data.
- Enhanced bank reconciliation logic to handle multi-currency transactions correctly.
- Renamed and updated tests to reflect changes in the underlying RPCs and ensure accurate coverage.
- Migrated existing cash account rules to correct mappings in compliance with Swedish accounting standards.
2026-05-19 16:10:18 +02:00
Mattsson a652dcae1a Skv/e2e overview (#515)
* feat(agi): refactor AGI XML generation and data handling

- Remove deprecated AGI field codes from field-codes.ts.
- Update generate-declaration.ts to include new employee fields and handle absence data with stable specification numbers.
- Enhance XML generation in xml-generator.ts to support new flags for housing benefits and adjusted benefits.
- Introduce new database migrations to support:
  - `removed_from_agi` flag for tombstoning individuppgifter.
  - `benefits_adjusted` flag for tracking adjustments to benefits.
  - `franvaro_specifikationsnummer` for stable absence event identification.
  - `housing_benefit_type` to differentiate between housing benefit types.

* feat: Implement strict validation for AGI employee data and introduce pre-flight validation schemas

- Added Zod schemas for validating employee data in AGI declarations to ensure all required fields are present and correctly typed, preventing silent errors during processing.
- Introduced AGI pre-flight validation schemas for Skatteverket endpoints to validate individual and head unit submissions before sending to the API.
- Created a new audit log table for tracking all outbound calls to Skatteverket, ensuring compliance and traceability for AGI and moms submissions.
- Implemented advisory locks in the database to manage concurrent updates to absence specification numbers, enhancing data integrity.
- Added compliance documentation for GDPR processing activities related to AGI and moms submissions, detailing data handling and retention policies.

* feat: Extend DELETE RLS policy to protect 'declined' signatures in årsredovisning

* fix: Update date handling in salary absence migrations to use immutable year-month key

* fix: Update SELECT policy in skatteverket_api_audit_log to use IN clause for company_id

* feat: Add skatteverket_api_audit_log and salary_absence_franvaro_audit tables with RLS policies and immutable triggers
2026-05-17 23:52:49 +02:00
MattssonandClaude Opus 4.7 a53a119a2e Fix/vat parent accounts (#438)
* feat(enable-banking): add support for account selection and syncing

- Updated StoredAccount interface to include an 'enabled' flag for account syncing preferences.
- Enhanced ensureFiscalPeriod function to handle overlapping fiscal periods with posted entries and opening balances.
- Added tests for fiscal period validation and account syncing logic.
- Implemented AccountPickerDialog component for user account selection.
- Created API routes for PATCH /accounts and POST /sync to manage account syncing.
- Introduced 'pending_selection' status for bank connections to allow user account selection before syncing.
- Updated database migration to support new connection status and backfill existing accounts with enabled=true.

* feat(enable-banking): implement account selection and consent event logging

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:12:00 +02:00
Jakob WennbergandClaude Opus 4.7 97989285c2 chore(compliance): consume erp-mafia/compliancemaxx@v1 (#418)
* chore(compliance): consume erp-mafia/compliancemaxx@v1

Adds the consumer side of the new compliancemaxx orchestrator:

  - .github/workflows/compliance-pr.yml — single-job advisory check
    that calls `uses: erp-mafia/compliancemaxx@v1` on every PR.
    Threshold + skill selection live in .compliance/config.yml.
    `fail-on-findings: false` keeps it strictly advisory while findings
    bed in; flip to true after triage.

  - .compliance/config.yml — bootstrap config: all 5 skills enabled
    (oss-license, owasp-asvs-v5, iso-27001-2022, soc2, gdpr),
    severity_threshold_to_block=critical, no suppressions yet.

The orchestrator code, skill manifests, and reference docs live in the
new public repo: https://github.com/erp-mafia/compliancemaxx

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: retrigger compliance check

* chore(compliance): add full-swarm workflow (nightly + dispatch + label)

Adds the LLM-powered deep_audit alongside the existing PR-mode advisory
check. Triggers:
  - 02:00 UTC nightly cron
  - workflow_dispatch (manual)
  - PRs labeled `compliance:full-audit`

Authenticates to AWS Bedrock via the existing AWS_ACCESS_KEY_ID/SECRET
repo secrets (same path swedish-compliance-review.yml already uses).
`fail-on-findings: false` keeps it observational while findings bed in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 22:11:33 +02:00