4.4 KiB
4.4 KiB
admin-api
Admin-only HTTP service for ProofedMesh. Currently covers one concern:
Verwaltung der Per-Diem-Pauschalen (per_diem_rates), die vom
agent-per-diem-calculator deterministisch angewandt werden
(siehe docs/architecture/v1.1.md §6.2 und ADR-0003).
Status: Skelett. Datenbankanbindung (pgx) und Signing-Service-Call sind Stubs mit expliziten Fehlern; HTTP-Handler, HTML-Templates, Modell-Typen und Store-Interface sind vollständig und getestet. Prod-Deployment folgt nach Phase-1-Trust-Core.
Scope
- Admin-Oberfläche
/admin/per-diem-rates— Liste + Neuanlage + „Retire" (valid_tosetzen) über HTML + HTMX-ähnlichen simple-POST-Flow. - JSON-API hinter denselben Pfaden für Automatisierung (
Accept: application/json). - Jede Create/Retire-Operation erzeugt eine Rate Change Attestation über den Signing Service — predicateType
https://basicstack.de/attestations/rate_change/v1. Rückgabe-Hash wird inper_diem_rates.rate_change_attestation_refsowie inper_diem_rate_changespersistiert. - Keine Delete-Operation. Historie ist unveränderlich (Schema-Trigger erzwingt das).
Auth
- OIDC via Pocket ID (Authorization-Code-Flow, Session-Cookie).
- Autorisierung: Gruppenmitgliedschaft
proofedmesh-adminwird aus dem ID-Token gelesen und ist Pflicht für alle Endpunkte außer Login. - Hintergrund-Dienste rufen die API nicht — Admin-API ist Human-only. Deshalb kein
client_credentials-Pfad.
HTTP-Endpunkte (geplant)
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /admin/per-diem-rates/ |
Liste aller Rates (gefiltert nach Country, aktiv/retired) |
| GET | /admin/per-diem-rates/{rate_id} |
Detailansicht einer Rate |
| POST | /admin/per-diem-rates/ |
Neue Rate anlegen (JSON oder Form) |
| POST | /admin/per-diem-rates/{rate_id}/retire |
valid_to setzen (Rate ablaufen lassen) |
Content-Negotiation per Accept-Header: text/html → Templates, application/json → JSON.
Layout
services/admin-api/
├── README.md — diese Datei
├── go.mod
├── cmd/admin-api/main.go — HTTP-Entry (bind + router + graceful shutdown)
├── internal/
│ ├── model/rate.go — Rate struct, validation
│ ├── store/
│ │ ├── store.go — RateStore interface
│ │ ├── memory.go — in-memory impl (für Tests + Dev)
│ │ ├── memory_test.go
│ │ └── postgres.go — pgx impl, derzeit Stub
│ ├── httpapi/
│ │ ├── rates.go — Handler
│ │ └── rates_test.go — Handler-Tests gegen in-memory store
│ └── attest/
│ └── ratechange.go — Signing-Service-Client, derzeit Stub
└── web/
└── templates/per_diem_rates.html
Lokal bauen (sobald Code vollständig)
cd services/admin-api
go test ./...
# Dev-Modus mit in-memory store, kein Postgres:
go run ./cmd/admin-api -store=memory -listen=:8080
# Prod-Modus (sobald postgres.go fertig):
go run ./cmd/admin-api -store=postgres \
-db="postgres://trust:…@trust-postgres:5432/trust?sslmode=verify-full"
Rate Change Attestation (Entwurf)
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{ "name": "per_diem_rate/PDR-42", "digest": { "sha256": "<content hash>" } }
],
"predicateType": "https://basicstack.de/attestations/rate_change/v1",
"predicate": {
"change_kind": "create",
"rate_id": "PDR-42",
"country": "DE",
"city": null,
"currency": "EUR",
"full_day": "28.00",
"partial_day_min8h": "14.00",
"arrival_day": "14.00",
"departure_day": "14.00",
"valid_from": "2026-01-01",
"valid_to": null,
"source_regulation": "BMF-Schreiben …",
"performed_by": {
"iss": "https://auth.basicstack.de",
"sub": "user-admin-42",
"session_id": "SES-admin-…"
},
"performed_at": "2026-10-25T18:30:00Z"
}
}
Signiert vom Signing Service, Attestations-Hash wandert zurück in die Tabellen per_diem_rates.rate_change_attestation_ref und per_diem_rate_changes.rate_change_attestation_ref.