trading-system-docs/tolaria/c5-sync-service
2026-08-26 05:03:19 +00:00
..
.gitignore feat(tolaria): add C5 sync state machine 2026-08-26 05:03:19 +00:00
README.md feat(tolaria): add C5 sync state machine 2026-08-26 05:03:19 +00:00
rq_c5a.py feat(tolaria): add C5 sync state machine 2026-08-26 05:03:19 +00:00
rq_c5a_cli.py feat(tolaria): add C5 sync state machine 2026-08-26 05:03:19 +00:00
test_c5a.py feat(tolaria): add C5 sync state machine 2026-08-26 05:03:19 +00:00

C5A — CONTRACT & STATE MACHINE v1

Phase: C5A (erste Phase des C5 Sync Service) Status: DONE (Contract & State Machine) — INAKTIV, NO-WRITE Architektur: FORGEJO MASTER → C5 SYNC SERVICE → TOLARIA DERIVED → SEARCH FULL REBUILD

C5A implementiert ausschließlich den Contract + die Sync State Machine + die persistente Progress-State-Struktur. Es ist eine deterministische, inaktive Python-Library + CLI + Testsuite — es führt keine externen Writes aus.


NO-WRITE GUARANTEE (verbindlich)

C5A kann NOCH NICHT:

  • Tolaria schreiben
  • Search rebuilden
  • Forgejo schreiben
  • produktiv pollen
  • Netzwerk-Mutationen ausführen

Es gibt keine Netzwerk-/HTTP-/Socket-/Subprocess-Mutationsfunktionen in C5A. Die No-Write-Guarantee wird statisch per assert_no_write_guarantee() bewiesen (keine requests/urllib/http/socket/subprocess-Imports) und durch den Test test_no_write_guarantee abgesichert.


State Machine

Normalzustände

DISCOVERED → VALIDATING → READY → PROPAGATING_TOLARIA → VERIFYING_TOLARIA → UPDATING_SEARCH → VERIFYING_SEARCH → APPLIED

Fehlerzustände

RETRY_PENDING, FAILED, DEAD, HUMAN_REVIEW_REQUIRED

Ordering

WAITING_FOR_PREDECESSOR — Commits werden nur in korrekter Reihenfolge verarbeitet (parent_sha / last_applied_commit). Lücken werden nicht übersprungen.

Kerninvariante

last_applied_commit wird NUR nach vollständigem Tolaria+Search PASS fortgeschrieben (mark_applied wird nur nach VERIFYING_SEARCH → APPLIED aufgerufen).


Commit Contract

Eine Verarbeitungseinheit = ein Forgejo Commit:

Feld Beschreibung
commit_sha Primärschlüssel
parent_sha Vorgänger (Ordering)
discovered_at Zeitstempel
sequence Reihenfolge
status Sync-Zustand
retry_count Retry-Zähler
last_error / last_error_code Fehler + Reason Code
created_at / updated_at Zeitstempel

Pro Changed Object

object_id, path_before, path_after, operation, content_hash_before, content_hash_after, metadata_hash_before, metadata_hash_after, representation, state


Operation Model

CREATE, CONTENT_UPDATE, METADATA_UPDATE, STATE_UPDATE, RENAME, MOVE, SOURCE_CANONICAL_RELATION_UPDATE, TAGS_UPDATE, SUPERSEDE, DELETE_REQUEST

DELETE_REQUEST bleibt Human-Gate — kein automatisches Hard Delete.


Idempotenz

Basis: commit_sha + object_id + operation + Hash-Checks.

Ergebnis Bedeutung
ALREADY_APPLIED Commit bereits vollständig angewendet
ALREADY_AT_TARGET Ziel-Hash bereits erreicht
RETRY_SAFE Noch nicht angewendet, sicher zu verarbeiten
CONFLICT Existiert, aber Hash weicht ab

Doppelte Commit-Erkennung ist deterministisch.


Ordering

Commits nur in korrekter Reihenfolge. Fehlender Vorgänger → WAITING_FOR_PREDECESSOR (Reason Code OUT_OF_ORDER_COMMIT). Nach Anwendung des Vorgängers wird der Commit erneut validiert.


Failure / Retry State

  • max_retries = 5 (konfigurierbar)
  • Backoff: 1 / 2 / 4 / 8 / 16 Sekunden (gekappt)
  • Nach Max → DEAD oder HUMAN_REVIEW_REQUIRED
  • Kein Endlos-Retry

Persistence

SQLite (c5a.db), isoliert, restart-fest. Anforderungen erfüllt:

  • atomic (SQLite-Transaktionen, WAL)
  • restart-safe (neuer Store auf gleicher DB behält State)
  • inspectable (CLI health, list-commits, commit-status)
  • backupbar (einzelne Datei)
  • keine externe DB nötig
  • kein Trading-/Forgejo-DB-Coupling (eigene DB)

Bootstrap State

UNINITIALIZED → RECONCILING → BASELINE_READY → ACTIVE

Baseline darf nur aus BASELINE_READY gesetzt werden (Master↔Tolaria- Reconciliation muss sauber sein). In C5A wird keine produktive Baseline gesetzt.


Reason Codes (geschlossene Menge)

UNEXPECTED_TOLARIA_DRIFT, ID_COLLISION, UNKNOWN_OBJECT_ID, INVALID_SCHEMA, DANGLING_DERIVED_FROM, AMBIGUOUS_DELETE, UNKNOWN_LEGACY_OBJECT, AUTH_FAILURE, SEARCH_REBUILD_FAILURE, TOLARIA_UNAVAILABLE, FORGEJO_UNAVAILABLE, OUT_OF_ORDER_COMMIT, SECRET_DETECTED

Kein freier String-Wildwuchs als einziges Fehlerformat — unbekannte Reason Codes werden abgelehnt (InvalidReasonCodeError).


Security Boundary (dokumentiert, NICHT implementiert)

  • Forgejo credential: READ ONLY (C5A hält keinen Forgejo-Write)
  • Tolaria write: nur später C5 Service
  • Search rebuild: nur C5 Service Token
  • Agents: keine direkten Tolaria-/Search-Admin-Writes
  • Netzwerk-Härtung wird später beim Deployment umgesetzt, NICHT jetzt

Health Contract

status, bootstrap_state, last_seen_commit, last_applied_commit, pending_commits, failed_commits, dead_commits, human_review_required, forgejo_status, tolaria_status, search_status, drift_count, last_success_at, last_error_code

C5A führt keine echten externen Health-Probes aus (rein State-Machine) — forgejo_status/tolaria_status/search_status sind UNKNOWN.


CLI

export C5A_DB=/path/to/c5a.db   # default: ./c5a.db
python3 rq_c5a_cli.py health
python3 rq_c5a_cli.py bootstrap-state
python3 rq_c5a_cli.py bootstrap-transition --to RECONCILING
python3 rq_c5a_cli.py set-baseline --commit <sha>
python3 rq_c5a_cli.py ingest-commit --json <file>
python3 rq_c5a_cli.py process-commit --json <file>
python3 rq_c5a_cli.py list-commits [--status <s>]
python3 rq_c5a_cli.py commit-status --sha <sha>
python3 rq_c5a_cli.py no-write-check

Tests

python3 test_c5a.py   # 25 PASS / 0 FAIL

Abgedeckte Fälle: normal commit lifecycle, multi-object commit, duplicate commit, already-applied, out-of-order commit, missing predecessor, retry progression, max retry → DEAD, human gate transition, restart/reload persistence, state corruption handling, idempotency, delete request → human gate, dangling relation → human gate, unexpected drift → human gate, no-write guarantee, bootstrap lifecycle, baseline-only-from-BASELINE_READY, reason codes closed set, operations closed set, health contract fields, last_applied-only-after-full-pass, retry available bound, backoff sequence, invalid reason code rejected.


Dateien

  • rq_c5a.py — Kern-Library (Store + State Machine + No-Write-Check)
  • rq_c5a_cli.py — CLI
  • test_c5a.py — Testsuite (25 Tests)
  • README.md — diese Datei