Add authenticated case intake and completed-case return API

This commit is contained in:
Nico committed 2026-10-21 14:36:26 +02:00
1 parent 830dabe870
commit 27feda6d7f
14 files changed
+1098 -1

No files matched your search

+168
View File
@@ -0,0 +1,168 @@
# Übergabe-API v1
Die API erstellt interne Case-Pakete und veröffentlicht sie atomar in der Inbox.
Externe Programme liefern Metadaten und Dateien; sie erzeugen und bearbeiten keine
internen Manifeste. Die API führt keine Analyse und keine LLM-Aufrufe aus. Ein
dauerhaft laufender Analyseworker und die allgemeine Weboberfläche sind folgende
Ausbauschritte. Bis dahin übernimmt der vorhandene Inbox-Prozessor die Aufnahme.
## Lokaler Start
```powershell
.\.venv\Scripts\python.exe -m pip install -e '.[api]'
Copy-Item config/api.example.toml config/api.local.toml
$env:VBA_INTAKE_TOKEN = [Convert]::ToHexString([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32))
.\.venv\Scripts\python.exe -m viano_bug_analysis.api check --config config/api.local.toml
.\.venv\Scripts\python.exe -m viano_bug_analysis.api serve --config config/api.local.toml
```
Der API-Token ist ein eigener Zugangsschlüssel, kein Gemini-Key. Programme erhalten
je einen Client und einen Token aus einer serverseitigen Umgebungsvariable. Der
Token benötigt 32–256 Zeichen aus `A-Z a-z 0-9 _ -`. Auf älterem Windows PowerShell
kann ein solcher Token über einen Passwortmanager erzeugt und als Variable gesetzt
werden. Der Beispielstart bindet nur an `127.0.0.1:8080`. Für entfernte Nutzung sind
HTTPS und ein passend konfigurierter Reverseproxy erforderlich. Tokens nicht in
URLs oder Git-Konfiguration ablegen. Zugriff auf das Workspace-Dateisystem bleibt
auf den Dienst und vertrauenswürdige Betreiber beschränkt.
`projects` ist die serverseitige Freigabeliste. Jeder Auftrag benennt `project_id`
und `profile_id`. Er kann keine Repository-URLs, DB-Zugänge, Budgets oder
Konfigurationspfade überschreiben. Optionale `projects.settings` halten die spätere
Worker-Konfiguration bereit; die Eingangsschicht verwendet diese Dateien nicht für
Analysen. Aktuell ist der Importadapter `vcore` für `wow/vcore` implementiert.
Weitere Projekte benötigen passende Adapter/Profile, keine separat gepflegten Forks.
## Endpunkte
| Methode/Pfad | Bedeutung |
|---|---|
| `GET /healthz` | Minimale öffentliche Erreichbarkeitsprüfung |
| `GET /v1/profiles` | Für diesen Client freigegebene Projekte/Profile |
| `GET /v1/schema` | Öffentliches JSON-Schema der Übergabemetadaten |
| `POST /v1/submissions` | Multipart-Upload, `201` bei neuer Einreihung, `200` bei Wiederholung |
| `GET /v1/submissions/{id}` | Quittung und aktueller verwalteter Zustand |
| `GET /v1/submissions/{id}/package` | Abgeschlossene Akte herunterladen; sonst `409` |
Alle Endpunkte außer Health benötigen `Authorization: Bearer TOKEN`.
POST benötigt zusätzlich `Idempotency-Key: frei-gewaehlte-eindeutige-id` (1–128
Zeichen, Buchstaben/Ziffern sowie Punkt, Unterstrich, Bindestrich; erstes Zeichen
alphanumerisch). Derselbe Client/Schlüssel mit denselben Metadaten und Dateiinhalten
liefert dieselbe Quittung, auch nach einem Neustart. Abweichender Inhalt ergibt
`409 API_IDEMPOTENCY_CONFLICT`. Dateinamen und Multipart-Grenzen zählen nicht als
Inhaltsänderung; Rollen und Reihenfolge der Dateien zählen. Ein zweiter neuer
Auftrag für dasselbe Projekt und dieselbe Case-ID wird zurückgewiesen.
## Neuer Auftrag
`metadata` ist ein UTF-8-JSON-Textfeld, kein Datei-Upload. Dateien: genau einmal
`wowdiag`, optional einmal `wowsrc`, optional mehrfach `attachments`. Für Vcore muss
die Case-ID dem Bug des Erfassungsarchivs entsprechen (`BUG-000020`). Beide
Erfassungsarchive müssen zueinander passen. Beispiel `submission.json`:
```json
{
"kind": "new_case",
"project_id": "viano-core",
"profile_id": "vcore",
"case_id": "BUG-000020",
"report": {
"title": "Wolpertinger fehlen",
"observations": ["Nach Questannahme waren im untersuchten Gebiet keine Tiere sichtbar."],
"expected_behavior": ["Fangbare Tiere sind im Gebiet vorhanden."]
},
"versions": {
"reported_server": "commit-des-gemeldeten-serverstands",
"capture_server": "commit-des-erfassungsstands"
}
}
```
```powershell
curl.exe --fail-with-body -H "Authorization: Bearer $env:VBA_INTAKE_TOKEN" -H "Idempotency-Key: bug20-capture-001" -F "metadata=<submission.json" -F "wowdiag=@wowdiag.tar.gz" -F "wowsrc=@wowsrc.tar.gz" http://127.0.0.1:8080/v1/submissions
```
Versionsangaben werden als unbestätigte Angaben des Einlieferers gespeichert, nicht
als verifizierte technische Fakten. Sie ersetzen keine Prüfung des Deployments.
Zusätzliche Anhänge werden unter generierten internen Namen unverändert erhalten;
sie werden nicht ausgeführt. Originalarchive bleiben ebenfalls erhalten.
## Rückläufer nach Abschluss
Dateien: genau einmal `case_package` (unveränderte abgeschlossene ZIP-Akte), optional
mehrfach `attachments`. Kein erneutes Erzeugen interner JSON-Dateien nötig:
```json
{
"kind": "case_return",
"project_id": "viano-core",
"profile_id": "vcore",
"case_id": "BUG-000020",
"feedback": {
"outcome": "patch_failed",
"summary": "Der Patch wurde getestet, das Verhalten besteht weiter.",
"observations": ["Die Tiere bleiben auch nach Neustart unsichtbar."],
"patch_id": "pr-123",
"tested_build": "commit-des-getesteten-builds"
}
}
```
```powershell
curl.exe --fail-with-body -H "Authorization: Bearer $env:VBA_INTAKE_TOKEN" -H "Idempotency-Key: bug20-patch123-feedback" -F "metadata=<return.json" -F "case_package=@case.zip" http://127.0.0.1:8080/v1/submissions
```
Zulässig sind `OUTPUT_READY`, `HANDED_OFF`, `FAILED_TO_ANALYZE`. Die API übernimmt
bei `OUTPUT_READY` die interne Übergabemarkierung, ergänzt Feedback, Bericht und
Anhänge und wechselt anschließend nach `REOPENED`. Die Paketidentität bleibt,
`analysis_revision` steigt genau einmal. Bisherige Artefakte bleiben erhalten und
der Casebuilder sieht die neuen Beobachtungen. Das neue Paket wird in die Inbox
gelegt; `QUEUED` bedeutet ausschließlich angenommen, nicht erfolgreich analysiert.
Ein verwalteter Fall darf nur mit seiner exakten aktuellen Akte zurückgegeben
werden. Veraltete/divergierende Akten und parallele Rückgaben werden abgewiesen.
Ohne lokale Fallhistorie ist eine gültige abgeschlossene, passend zugeordnete Akte
importierbar. Alte manuelle Testpakete ohne `project.id` benötigen vorerst eine
betreiberseitige Migration; sie werden nicht stillschweigend einem Projekt zugeordnet.
BLOCKED-Fälle, laufende Fälle und asynchrone Testerantworten innerhalb einer
Untersuchung sind keine Abschlussrückläufer und werden hier nicht wiedereröffnet.
## Grenzen und Wiederanlauf
Standard: 768 MiB gesamter HTTP-Body, 512 MiB je Datei, 64 KiB Metadaten, 12 Dateien,
120 Sekunden Uploadzeit und zwei gleichzeitige Uploads pro Prozess. Konfigurierbar
über `[limits]` mit den Feldnamen aus `IntakeLimits`. Die existierenden Import- und
ZIP-Validatoren setzen zusätzlich ihre eigenen Grenzen durch (Vcore-Import ist
enger begrenzt). Dies sind Betriebsschutzwerte, keine fachlichen Analysebudgets.
Uploads werden vor dem Parsen authentifiziert. Auch Requests ohne Content-Length
werden anhand tatsächlich empfangener Bytes begrenzt. Multipart-Spools werden bei
Fehler/Timeout geschlossen, eigene temporäre Arbeitskopien wieder entfernt. Der
Dienst prüft freien Speicher vor Aufnahme und Paketbau. Für den ersten Betrieb
einen einzelnen Uvicorn-Prozess verwenden; die Upload-Parallelitätsgrenze gilt pro
Prozess. Der Workspace verwendet zusätzlich OS-Dateisperren für Veröffentlichung.
Unter `runtime/intake/requests` bleiben kleine Quittungen und Hashes. Vor der
atomaren Inbox-Veröffentlichung wird eine PREPARED-Quittung mit fertigem Paket
gesichert. Beim Neustart werden solche Veröffentlichungen fortgesetzt. Nach
Einreihung wird die zusätzliche Paketkopie entfernt. Bereits vom Worker übernommene
Pakete werden über ihre Checkpoint-Kette erkannt und nicht erneut eingereiht.
Nach hartem Prozessabbruch können verwaiste Arbeitsverzeichnisse unter
`runtime/intake/staging` und Betriebssystem-Temporärdateien verbleiben; deren
betriebliche Bereinigung/Retention gehört zum folgenden Worker-/Dienst-Ausbau.
Fehlerantworten enthalten stabile Codes, keine Dateipfade oder Secrets. Wesentliche
Fälle: `401` Zugriff, `403` Projektfreigabe, `409` Konflikt/Zustand, `413` Größe,
`422` ungültige Metadaten/Archive, `503` beschäftigt/Speicherfehler, `507` freier
Speicher zu gering. Bei `503` mit demselben Idempotenzschlüssel wiederholen.
## Lokale Prüfung
```powershell
.\.venv\Scripts\python.exe -m pip install -e '.[api,api-test]'
.\.venv\Scripts\python.exe -m pytest tests/profiles/vcore/test_intake_api.py -q
```
Die Tests verwenden künstliche Erfassungsarchive und HTTP-Testtransport. Sie prüfen
auch Feedbackübernahme durch den echten Casebuilder, Idempotenz, veraltete
Rückläufer, Uploadgrenzen sowie Abstürze vor und nach Queue-Veröffentlichung. Es
finden keine kostenpflichtigen LLM-Aufrufe statt.