- job_schema: geschlossene Job-Type-Allowlist (C5_SAVE_OBJECT/C5_DELETE_OBJECT), Pfad-/Längen-Validierung - job_state_machine: deterministische States (CREATED/READY/CLAIMED/EXECUTING/SUCCEEDED/FAILED) - job_claim: atomare Claim-/Lease-/Recovery-Logik (kein TOCTOU) - job_store: getrennte SQLite-Inbox-DBs (c5a_save.db/c5a_delete.db), delegiert an job_claim - save_executor_core: SAVE-only, Content-Rekonstruktion, Provenance-Validierung - delete_executor_core: DELETE-only, AUTH.3D-Composition, TOCTOU-Defense (Re-Read nach Claim) - test_job_channel: T1-T40 + adversarial (72 Tests) - test_job_channel_adversarial: adversarial + Substitution + DB-Manipulation - sensitivity_proof_auth3e: Mutationen A-L (12/12 Invarianten PRESENT) - AUTH3B/3C/3D/3E_DESIGN: autoritative Security-Dokumentation (e25 Reconciliation) COMMAND != AUTHORIZATION. Kein generischer Dispatcher. RQ credential-free. Keine produktive Mutation. Keine echten Credentials. |
||
|---|---|---|
| .. | ||
| .gitignore | ||
| approval_payload.py | ||
| approval_signature.py | ||
| approval_state.py | ||
| approval_verifier.py | ||
| auth3a-sensitivity.sh | ||
| C5_DELETE_EXECUTION_ARCHITECTURE_DECISION.md | ||
| C5D_SEARCH_SOURCE_PIPELINE_ARCHITECTURE_DECISION.md | ||
| delete_executor_core.py | ||
| job_claim.py | ||
| job_schema.py | ||
| job_state_machine.py | ||
| job_store.py | ||
| README.md | ||
| rq_c5_cli.py | ||
| rq_c5_delete.py | ||
| rq_c5a.py | ||
| rq_c5a_cli.py | ||
| rq_c5b.py | ||
| rq_c5c.py | ||
| rq_c5d.py | ||
| rq_c5e.py | ||
| save_executor_core.py | ||
| sensitivity_proof.py | ||
| sensitivity_proof_auth3e.py | ||
| test_approval_auth3d.py | ||
| test_approval_helpers.py | ||
| test_c5_auth3a.py | ||
| test_c5_delete.py | ||
| test_c5_delete_fresh_checker.py | ||
| test_c5_delete_integration.py | ||
| test_c5a.py | ||
| test_c5b.py | ||
| test_c5c.py | ||
| test_c5d.py | ||
| test_c5d_adoption.py | ||
| test_c5d_provenance.py | ||
| test_c5d_source_pipeline.py | ||
| test_c5e.py | ||
| test_c5g_acceptance.py | ||
| test_job_channel.py | ||
| test_job_channel_adversarial.py | ||
C5 SYNC SERVICE — CONTRACT & STATE MACHINE (C5A) + FORGEJO POLLING & CHANGE DETECTION (C5B)
Phase: C5A (Contract & State Machine) + C5B (Forgejo Polling & Change Detection) Status: C5A = DONE · C5B = DONE (Polling & Change Detection) — 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. C5B baut darauf die Forgejo Polling & Change Detection Engine (read-only). Beide sind deterministische, inaktive Python-Libraries + CLI + Testsuite — sie führen keine externen Writes aus.
NO-WRITE GUARANTEE (verbindlich, C5A + C5B)
C5A + C5B können NOCH NICHT:
- Tolaria schreiben
- Search rebuilden
- Forgejo schreiben
- produktiv pollen (kein Poll-Daemon)
- Netzwerk-Mutationen ausführen
C5A hat keine Netzwerk-/HTTP-/Socket-/Subprocess-Mutationsfunktionen
(assert_no_write_guarantee()).
C5B führt ausschließlich read-only git-Befehle gegen den lokalen Clone aus
(strikte Whitelist: rev-parse, log, show, diff-tree, ls-tree,
cat-file, merge-base, rev-list, diff). Jeder Write-Befehl
(push/commit/add/reset/checkout/merge/rebase) wird mit
GitWriteBlockedError blockiert. Die No-Downstream-Write-Guarantee wird statisch
per assert_no_downstream_write() bewiesen (keine HTTP-Mutationsimporte, keine
/api/vault/save-//api/search/rebuild-Endpoints im Code, keine Git-Write-Befehle
in der Whitelist) und durch den Test test_no_downstream_write abgesichert.
C5B — FORGEJO POLLING & CHANGE DETECTION ENGINE
FORGEJO_READ_METHOD
A) lokale Git-Mirror/Clone-Analyse (bevorzugt).
- AUTH_REQUIREMENT: KEIN (read-only gegen lokalen Clone; kein Write-Token)
- NETWORK_DEPENDENCY: KEIN (lokale
.git-Objekte; kein HTTP)
POLLING_MODEL
- Default: 60 Sekunden
- Environment-konfigurierbar:
C5_POLL_INTERVAL_SECONDS(z.B.=120) - C5B implementiert die Polling-Logik, startet aber KEINEN dauerhaften
Produktions-Daemon. Tests führen einzelne kontrollierte
poll_once-Zyklen aus.
HEAD_DISCOVERY
get_current_head() → Commit-SHA + parent/timestamp/message. Bei nicht
erreichbarem Forgejo: RC_FORGEJO_UNAVAILABLE, kein State-Fortschritt.
COMMIT_RANGE_MODEL
Aus last_seen_commit (C5B-Baseline) bis HEAD deterministisch alle fehlenden
Commits in chronologischer (parent-korrekter) Reihenfolge. Kein Überspringen,
keine Doppelerfassung. Merge-Commits werden explizit behandelt (alle Parents).
Divergenz/History-Rewrite wird erkannt.
Wichtig: C5B-Baseline ist
last_seen_commit.last_applied_commitbleibt laut C5A-Contract für die spätere Propagation (C5C) reserviert und wird von C5B NIE fortgeschrieben.
HISTORY_SAFETY
Wenn last_seen_commit kein Ancestor von HEAD ist: FAIL CLOSED
(RC_OUT_OF_ORDER_COMMIT). Keine automatische Rebase-/Reset-Logik.
DIFF_MODEL
Für jeden neuen Commit: git diff-tree -r --name-status -M -C --root →
ADDED / MODIFIED / DELETED / RENAMED / MOVED. Bei unsicherer
Rename-Detection wird nicht geraten — Ambiguität wird sauber klassifiziert
(Human Review).
KNOWLEDGE_SCOPE_MODEL
Nicht jede Forgejo-Datei ist automatisch Tolaria-Knowledge:
- IN_SCOPE: Markdown im Repo-Root ODER unter
notes/trading/system-docs/ - OUT_OF_SCOPE:
tolaria/,a2-5/,red-queen-architecture/,notion-safety-brain/,notion-command-center/,backup_patches/,notes/reference/, Nicht-Markdown, Build-Artefakte - LEGACY_SPECIAL:
README.md(x2, KEEP_DISTINCT) +vps.md(DEFERRED) - HUMAN_REVIEW: Knowledge-Objekt ohne gültige
object_id
Keine Secrets/Build-Artefakte in Sync-Change-Sets. Nicht blind .md = Sync.
OBJECT_ID_MODEL
object_id wird aus dem Frontmatter gelesen (id: object/<FULL_UUID>),
nicht aus dem Pfad erzeugt, nicht neu generiert, nicht geraten. Ohne gültige ID:
UNKNOWN_OBJECT_ID / UNKNOWN_LEGACY_OBJECT → Human Gate.
HASH_MODEL
content_hash: SHA-256 des fachlichen Bodies (nach Frontmatter)metadata_hash: SHA-256 der relevanten Knowledge-Schema-Metadaten (id,type,role,representation,state,derived_from,tags,knowledge_schema). Pfad ist separat.- Deterministisch und testbar.
CHANGE_CLASSIFICATION
Aus Before/After deterministisch: CREATE, CONTENT_UPDATE,
METADATA_UPDATE, STATE_UPDATE, RENAME, MOVE,
SOURCE_CANONICAL_RELATION_UPDATE, TAGS_UPDATE, SUPERSEDE,
DELETE_REQUEST. Bei mehreren geänderten Aspekten in EINEM Objekt werden
mehrere ObjectChange-Einträge erzeugt (keine Information verloren).
RENAME_MOVE_MODEL
Rename/Move nur automatisch, wenn gleiche object_id + eindeutige
Git-/Content-Evidence. ID bleibt stabil. Rename = Dateiname geändert (gleiches
Verzeichnis); Move = Verzeichnis geändert. Bei Ambiguität: Human Gate.
DELETE_MODEL
Git-Delete wird NIEMALS zu automatischem Hard Delete. C5B erzeugt
DELETE_REQUEST → C5A führt es in Human Review. Keine Tolaria-Aktion.
PAIR_MODEL
Wenn Root/source + canonical gemeinsam verändert werden, erkennt C5B die
Pair-Beziehung (derived_from). Ordnung für spätere C5C: Source zuerst,
Canonical danach. Noch nicht propagiert — Output enthält genug Information für
C5C.
SECRET_SAFETY
C5B schreibt keine Secret-Inhalte in Logs/SQLite/Evidence. Bei
Secret-/Forbidden-Dateien: nur sichere Metadaten (path, reason_code,
commit_sha). Enthält ein Knowledge-Dokument einen möglichen Secret-Wert:
RC_SECRET_DETECTED FAIL CLOSED. Kein Wert wird ausgegeben.
C5A_INTEGRATION
C5B speist gefundene Commits + ObjectChanges in den C5A Store ein (nur
State/Persistence, kein Network Write downstream). Flow: Poll once → discover
commits → classify changes → register commit → add object changes → Status
DISCOVERED/VALIDATING (bzw. HUMAN_REVIEW_REQUIRED). Nicht weiter zu
PROPAGATING_TOLARIA.
OBSERVABILITY
C5B erweitert sichere Statusdaten: last_seen_commit, poll_timestamp,
commits_discovered, objects_discovered, out_of_scope_count,
last_poll_status, last_poll_error_code. Keine Content-Logs.
State Machine (C5A)
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 / 16Sekunden (gekappt) - Nach Max →
DEADoderHUMAN_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
export C5_REPO=/path/to/forgejo-clone # default: .
export C5_POLL_INTERVAL_SECONDS=60 # default: 60
# C5A
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
# C5B (rq_c5_cli.py)
python3 rq_c5_cli.py poll-once # ein kontrollierter Poll-Zyklus (read-only)
python3 rq_c5_cli.py show-pending # ausstehende Commits anzeigen
python3 rq_c5_cli.py show-commit <sha> # Details eines Commits anzeigen
python3 rq_c5_cli.py dry-run-diff <sha> # Diff eines Commits anzeigen (read-only)
python3 rq_c5_cli.py health # Health-Contract anzeigen
python3 rq_c5_cli.py no-write-check # No-Downstream-Write-Guarantee pruefen
Kein daemon/start-forever-Befehl in C5B — der produktive Poll-Daemon kommt
erst beim Deployment (C5).
Tests
python3 test_c5a.py # 25 PASS / 0 FAIL
python3 -m unittest test_c5b -v # 39 PASS / 0 FAIL
C5A 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.
C5B abgedeckte Fälle: head discovery, single commit, multi commit, added knowledge object, content update, metadata update, state update, tags update, relation update, rename, move, delete request, out-of-scope file, legacy object, unknown ID, secret detection, duplicate poll, lost poll, ordering, Forgejo unavailable, history divergence, C5A persistence integration, no downstream write, poll interval config.
Dateien
rq_c5a.py— C5A Kern-Library (Store + State Machine + No-Write-Check)rq_c5a_cli.py— C5A CLItest_c5a.py— C5A Testsuite (25 Tests)rq_c5b.py— C5B Kern-Library (GitReader + Scope + Classifier + Poller + No-Downstream-Write-Check)rq_c5_cli.py— C5 CLI (C5A + C5B: poll-once, show-pending, show-commit, dry-run-diff, health, no-write-check)test_c5b.py— C5B Testsuite (39 Tests)README.md— diese Datei