ledgerctl — årsarkiv, checksummor, GPG och Git-förankring

[2026-07-19 Sun]

Syfte

När ett budget- och bokföringsår är färdigt kan ledgerctl archive försegla året i en separat katalog. Målet är både ordning och verifierbarhet:

Förkontroller

Kör innan arkivering:

ledgerctl reconcile
ledgerctl audit
ledgerctl report unknown
ledgerctl budget doctor

Kontrollera även att årets importer inte innehåller block som sträcker sig över två kalenderår. Ett importblock med både december och januari vägras eftersom en splittring skulle bryta blockets innehållshash.

Dry-run är standard

ledgerctl archive 2026

Det visar planen utan att ändra arbetsytan. Granska särskilt:

Utför arkiveringen

ledgerctl archive 2026 --commit

Utan särskilda flaggor är den normala policyn:

  1. skapa lokalt årarkiv,
  2. skapa en anchor-commit i ett separat Git-repo,
  3. pusha denna commit till konfigurerad remote.

Om ingen remote kan hittas misslyckas standardläget hellre än att tyst ge ett svagare skydd.

Arkivets layout

Efter en lyckad arkivering:

~/budget/2026/
  2026-kassabok.journal
  imports/
  snapshots/
    routes.conf
    merchant-db.json
    merchant-db.json
    envelopes.conf
    funding.journal
  SHA256SUMS
  SHA256SUMS.asc       # endast med --sign
  ARCHIVE-INFO.txt

Filer som saknas i arbetsytan hoppas över. Budgetens envelopes.conf och funding.journal kopieras som snapshots; den kumulativa budgethistoriken flyttas inte årsvis.

Vad flyttas och vad kopieras

Flyttas ur den aktiva arbetsytan

Kopieras som snapshot

Merchantdatabasen stannar kvar i arbetsytan så att nästa år fortsätter med den inlärda kunskapen.

Rörs inte

Kraschsäker publicering

Arkiveringen byggs först i en dold YYYY.partial-katalog. Källjournalen och CSV-filerna lämnas orörda under byggfasen. När arkivet är komplett byter katalogen atomärt namn till YYYY/. Först därefter städas källan.

Det innebär att en krasch i normalfallet lämnar för mycket data kvar, inte för lite. Kör alltid verifiering innan du städar manuellt efter en avbruten arkivering.

GPG-signering

Signera med standardnyckeln:

ledgerctl archive 2026 --commit --sign

Välj nyckel explicit:

ledgerctl archive 2026 --commit --sign 3AA5C0F1B2E4D7...

Signaturen blir en fristående ASCII-armored SHA256SUMS.asc. GPG behövs inte när --sign utelämnas.

Extern Git-förankring

Anchor-repot innehåller endast:

2026/SHA256SUMS
2026/ARCHIVE-INFO.txt

Bankens CSV, journal och merchantdatabas skickas inte till remote. Den externa kopian gör att någon som kan ändra det lokala arkivet inte lika enkelt kan skriva om både data och manifest utan att lämna spår i Git-historiken.

Konfiguration i ledgerctl.conf:

LEDGERCTL_ANCHOR_DIR=/home/jonix/.ledgerctl/anchors
LEDGERCTL_ANCHOR_REMOTE=git@codeberg.org:Jonix/ledgerctl-anchors.git

Standardkatalogen är annars ~/.ledgerctl/anchors.

Remote kan även anges för en körning:

ledgerctl archive 2026 --commit --push-to origin

eller som URL:

ledgerctl archive 2026 --commit \
  --push-to git@codeberg.org:Jonix/ledgerctl-anchors.git

Medvetet svagare lägen

Lokal anchor utan push:

ledgerctl archive 2026 --commit --only-local

Ingen anchor alls:

ledgerctl archive 2026 --commit --no-anchor

--only-local skyddar inte mot en angripare med åtkomst till samma filsystem. --no-anchor lämnar endast arkivets egna checksummor och eventuell GPG-signatur.

Verifiera ett arkiv

Grundkontroll:

ledgerctl verify ~/budget/2026

Det räknar om alla hashar och verifierar en signatur om den finns och GPG är tillgängligt.

Kräv signatur:

ledgerctl verify ~/budget/2026 --require-signature

Kräv en viss signerare:

ledgerctl verify ~/budget/2026 --signer 3AA5C0F1B2E4D7...

--signer innebär automatiskt att en signatur krävs. En giltig signatur från fel nyckel rapporteras som wrong-signer.

Kontrollera även Git-förankringen:

ledgerctl verify ~/budget/2026 --anchor

Full strikt kontroll:

ledgerctl verify ~/budget/2026 \
  --signer 3AA5C0F1B2E4D7... \
  --anchor

Signerar-pin via miljö

För skript eller återkommande verifiering:

export LEDGERCTL_ARCHIVE_SIGNER=3AA5C0F1B2E4D7...
ledgerctl verify ~/budget/2026 --anchor

Tolkning av verifieringsstatus

Status Betydelse
ok Hashar och begärda kontroller passerar
missing Signatur saknas; tillåtet om den inte krävdes
no-gpg Signatur finns men GPG kan inte köras
bad Signaturen eller manifestet är trasigt
wrong-signer Signaturen är giltig men kommer från annan nyckel än den pinnade
anchor mismatch Arkivets manifest skiljer sig från den externt förankrade kopian

En anchor mismatch eller wrong-signer ska undersökas innan arkivet betraktas som betrott.

Vanliga fel

Årskatalogen finns redan

Arkivmotorn skriver inte över en tidigare försegling. Kontrollera och verifiera den befintliga katalogen innan du ens överväger att ta bort den.

Anchor för året finns redan

Ett år får inte tyst ersätta en tidigare anchor. En avsiktlig omförsegling ska vara synlig i Git-historiken.

Push eller anchoring misslyckas efter att arkivet skrivits

Arkivet kan då finnas men ännu inte vara slutligt skrivskyddat. Läs felmeddelandet, verifiera lokala filer, åtgärda anchor-problemet och följ instruktionen att ta bort den ofullständigt förseglade årskatalogen innan en ny körning. Försök inte dölja felet genom att manuellt chmod:a katalogen.

GPG-signering misslyckas

Kontrollera:

gpg --list-secret-keys
gpg --card-status

samt att gpg-agent och eventuell YubiKey är tillgängliga.

Rekommenderad årsprocedur

cd ~/budget
ledgerctl doctor
ledgerctl reconcile
ledgerctl audit
ledgerctl report unknown
ledgerctl budget doctor

ledgerctl archive 2026
ledgerctl archive 2026 --commit --sign 3AA5C0F1B2E4D7...
ledgerctl verify 2026 --signer 3AA5C0F1B2E4D7... --anchor

Spara gärna verifieringsutskriften tillsammans med dina övriga administrativa anteckningar, men lita på det kryptografiska manifestet och den externa ankringen som den tekniska kontrollen.