15af0cd7eadcecafd6d17618d04bf67b4f736fd2
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0521c385d2 |
feat(transactions): underlag status badges + attach dialog; auto-expire stale pending ops (#712)
* feat(transactions): per-row underlag status + attach-document dialog
- New "Matcha mot underlag" dialog on /transactions (inbox pick or fresh
upload), the tx→doc mirror of the Documents view's matcher
- Per-row Underlag/Underlag saknas badges on booked history rows, driven
by computeJeUnderlagStatus — same posted-only, exemption-aware scope as
the worklist count so badge and count never disagree
- attach-document route + commit dispatcher now propagate the doc onto
the verifikation when the tx is already booked (BFL 5 kap 6 §), with a
409 guard for docs consumed by a different verifikation, idempotent
re-attach (no same-value rewrite under period lock), and an honest 409
when the period-lock trigger blocks the propagation
- Booking-dialog doc links also pin the doc to the transaction row
(first linked doc wins) via the link route's new transaction_id param
messages/{sv,en}.json also carries the strings for the pending-ops
expiry UI that lands in the next commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(pending-operations): auto-expire stale staged operations after 30 days
- New daily cron (02:30 UTC, vercel.json + both docker crontabs) flips
>30-day-old pending ops to rejected with the dispatcher's
{ auto_rejected: true, reason: 'expired' } result_data shape — rows are
never deleted, the table is the audit trail
- /pending renders an "Utgick automatiskt" badge + detail line for these,
orders terminal tabs by resolved_at so a fresh expiry sweep isn't
buried, and adds a first-time-reviewer explainer
- Origin labels spell out where a proposal came from (AI chat, MCP key,
API, cron) instead of the raw actor_label
- agent_chat actor type added to PendingOperationActorType/AuditLogEntry
(DB CHECK already widened in 20260519090000) and to the agent filter
- ApprovalCard notes that ignoring a proposal is safe
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(mcp): surface the client telemetry marker in connect instructions
Tag the connector URLs shown in ApiKeysPanel, the connect-claude doc and
the gnubok-mcp README with ?client=<surface> (claude-connector /
claude-code) and GNUBOK_CLIENT=claude-desktop for the npm bridge.
Telemetry-only — the server already reads the param/header; this just
lets us measure which Claude surface connected.
The claude mcp add copy blocks quote the URL: an unquoted ? in the query
string trips zsh globbing ("no matches found").
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* review: fix stale-closure badge flip + zod-validate link route body (PR #712)
- handleDocumentAttached read journal_entry_id off the render-time
transactions snapshot; if the list changed while the attach dialog was
open the optimistic badge flip was silently skipped. Read it off the
dialog's own subject (attachDocTx) instead.
- POST /api/documents/[id]/link now validates the body against the new
LinkDocumentSchema (uuid-strict, all four fields) instead of a bare
presence check on journal_entry_id — same canonical VALIDATION_ERROR
envelope. Test fixtures switched to real UUIDs accordingly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
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>
|
||
|
|
3c85082f3a |
fix(docs): replace dead gnubok.app domain with app.gnubok.se across public docs (#683)
gnubok.app has no DNS delegation (the .app TLD returns no NS records for it), so every https://gnubok.app/... link in the public docs was dead — including the OAuth connector URL a Claude Connectors Directory reviewer would paste from the new Connect-with-Claude page (#682), and the docs links in the gnubok-mcp npm README that ships in the tarball. app.gnubok.se is the live production domain (the MCP endpoint there correctly answers 401 unauthenticated) and was already the default GNUBOK_URL in the npm bridge and the branding-service appUrl fallback. Mechanical swap: 55 occurrences across 11 files, all https:// URL form (verified no emails or identifiers). Docs content only — no code paths. Also resolves the greptile domain-mismatch finding on #682. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a894af11d0 |
feat(mcp): tool titles + Connect-with-Claude docs for Connectors Directory readiness (P0-4) (#682)
* feat(mcp): tool titles + Connect-with-Claude docs for Connectors Directory readiness Add a top-level Tool.title (MCP spec 2025-06-18) to all 92 MCP tools and flow it through the tools/list serializer for the Claude Connectors Directory. Trim the ~10 longest tool descriptions toward 180-200 chars (semantics + agent hints preserved) to partly offset the added bytes, and raise the payload-size bench ceiling 32K → 36K with headroom reserved for upcoming Skatteverket tools. Ship a "Connect with Claude" docs page (OAuth 2.1 connector + npx gnubok-mcp stdio bridge, sample sandbox prompts, 10-minute reviewer test, support pointer), wire it into the docs nav, and add a README to the packages/gnubok-mcp npm bridge. Bump one categorized sandbox business expense above 4 000 kr so the VAT close-check demo surfaces a high-value receipt-less expense. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mcp): restore six spaces lost in the description-trimming pass Review finding (Greptile P2): the trim deleted single spaces in six tool descriptions ("Stages foruser", "länkatill", "kundfordran(1510)", …), producing malformed text in tools/list. All six were pure space deletions with no token gain — restored verbatim. Swept all 92 descriptions for residual merge artifacts; the two remaining matches are pre-existing function-call notation from main. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(compliance): correct BFL citation in seed + mark 4000 kr as app heuristic Swedish compliance review findings: - The seed comment cited BFL 5 kap 6§ as requiring verifikat on high-value affärshändelser; 6§ governs verifikationens innehåll. Rephrased: BFL 5 kap 6-7§ require every affärshändelse to be documented — the 4 000 kr cut-off is the tool's own heuristic, not a statutory threshold. - The connect-claude docs read as though 4 000 kr were a legal floor (conflatable with the förenklad faktura ceiling, ML 17 kap 26-28§). Clarified that BFL requires underlag regardless of amount. Dismissed as by-design: the gnubok_sk_test_... README placeholders (standard practice; the prefix schema is already public in llms.txt). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
53d1807e8f |
feat: gnubok-mcp npm package for Claude Desktop (#78)
* feat: add gnubok-mcp npm package for Claude Desktop Published as gnubok-mcp@1.0.0 on npm. Users configure Claude Desktop with `npx gnubok-mcp` + their API key. Zero dependencies, 1.3 KB. Works as a stdio-to-HTTP bridge while Claude Desktop's OAuth connector feature is in beta. Updated settings panel instructions to show the npx approach instead of the OAuth connector flow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: harden gnubok-mcp bridge (v1.0.1) - Rename URL → MCP_URL to avoid shadowing built-in URL constructor - Wrap non-2xx responses in JSON-RPC error instead of forwarding raw HTTP body (prevents CDN HTML pages from corrupting stdio stream) - Restore select-all on Claude Desktop config snippet Published as gnubok-mcp@1.0.1. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |