feat(gitsync): synka wiki-repot mot remote över SSH

- ed25519-deploy-nyckel genereras av servern (config-volymen, 0600),
  GIT_SSH_COMMAND med egen known_hosts (accept-new)
- inställningar: remote-URL, live-gren, read-only, auto-synk-intervall
- bakgrundssynk: endast fast-forward, flaggar attention vid merge-behov
- pull/push, skapa/byt gren, merge-popup (ours/theirs per fil eller allt),
  abort, reset från remote med automatisk backup-gren
- headless-konfig via config.json eller updateGitSync-mutationen
- openssh-client tillagd i runtime-imagen; mutex kring alla git-operationer

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-02 23:10:34 +02:00
parent 952ff5f951
commit e181e8e68e
11 changed files with 1506 additions and 1 deletions

View File

@@ -254,6 +254,35 @@ resolveDBPath(configPath):
└─ Annars → <config-katalog>/archivum.db (dev-miljö)
```
### Git-synk mot remote (SSH)
Wiki-repot kan synkas mot ett remote git-repo (t.ex. Gitea) över SSH.
Implementation: `internal/git/sync.go` (remote-operationer + mutex) och
`internal/graph/gitsync.go` (GraphQL-handlers, nyckelhantering, bakgrunds-
ticker). Admin-UI: `frontend/src/components/GitSyncSection.vue` med
`MergeConflictDialog.vue` som popup vid konflikter.
- **SSH-nyckel:** servern genererar själv ett ed25519-nyckelpar vid första
aktivering, lagrat i `<config-dir>/ssh/` (0600). Publika nyckeln visas i
admin-panelen och registreras som deploy key hos git-värden. `GIT_SSH_COMMAND`
pekar på nyckeln + egen `known_hosts` (accept-new) eftersom appen kör utan
hemkatalog. Privata nyckeln exponeras aldrig via API:t.
- **Live-gren** (`live_branch`): grenen som bakgrundssynken håller uppdaterad.
Bakgrundssynk (intervall i `auto_sync_minutes`, 0 = manuell) gör endast
fast-forward-pulls; allt som kräver riktig merge flaggas för admin
(`attention` i `gitSyncStatus`).
- **Read-only** (`read_only`): pull tillåts men aldrig push (spärras i backend).
- **Grenar:** skapa och byt gren i admin-panelen; remote-grenar spåras
automatiskt vid byte.
- **Merge-konflikter:** pull lämnar mergen öppen och UI:t visar en popup där
man väljer lokal/remote per fil eller för allt; alternativt avbryt mergen.
- **Reset från remote:** tvingar lokala grenen att matcha remoten; lokalt
läge sparas alltid först i en backup-gren (`backup/<timestamp>`). Används
också för bootstrap när historikerna är orelaterade (`UNRELATED_HISTORIES`).
- **Headless-konfiguration:** allt kan sättas via `config.json`-sektionen
`git_sync` + omstart, eller via GraphQL-mutationen `updateGitSync` — inget
webbgui krävs.
### Konfiguration
`config.json` hanteras av `internal/config`:
@@ -263,6 +292,8 @@ resolveDBPath(configPath):
- `listen_addr` — TCP-adress att lyssna på, t.ex. `:4000`
- `public_url` — extern bas-URL (t.ex. `https://archivum.brasse-pc.eu`), används
för att härleda OIDC-redirect-URI
- `git_sync` — se avsnittet ovan: `enabled`, `remote_url`, `live_branch`,
`read_only`, `auto_sync_minutes`
- `oidc` — valfri OIDC/SSO-konfiguration (Authentik):
- `enabled`, `issuer`, `client_id`, `client_secret`, `redirect_url`
- `groups_claim` (default `groups`), `username_claim` (default `preferred_username`)