trading-system-docs/tolaria/c5-sync-service/delete_executor_core.py
Red Queen 10761f52b2 AUTH.3E: Executor Command Channel + Runtime Boundary Contract
- 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.
2026-08-27 10:03:32 +00:00

186 lines
7.3 KiB
Python

"""
AUTH.3E — delete_executor_core.py
==================================
DELETE-Executor-Logik (DELETE-only, AUTH.3D-Validierung).
Eigenschaften:
* DELETE-only: claimt NUR C5_DELETE_OBJECT-Jobs
* Der DELETE-Job selbst ist KEINE Approval
* AUTH.3D-Composition: VALID_JOB AND VALID_STATE AND VALID_AUTH3D_SIGNATURE
AND VALID_NONCE AND VALID_EXPIRY AND NOT_CONSUMED AND VALID_OBJECT AND
VALID_PATH AND VALID_COMMIT AND VALID_PROVENANCE AND DELETE_CREDENTIAL
* Kein Faktor ersetzt einen anderen
* Fail-closed: kein HTTP ohne DELETE-Credential
* OUTCOME_UNKNOWN bei unklarem HTTP-Ergebnis (kein blinder Retry)
* Ein gestarteter DELETE wird bei Lease-Expiry NICHT blind wiederholt
Isoliert implementiert (KEIN produktiver Container). Nutzt job_store + job_schema.
"""
from __future__ import annotations
from typing import Any, Callable, Dict, Optional
from job_schema import JOB_TYPE_DELETE
from job_store import JobStore
# ---------------------------------------------------------------------------
# Result-Codes
# ---------------------------------------------------------------------------
RC_OK = "OK"
RC_CREDENTIAL_MISSING = "CREDENTIAL_MISSING"
RC_APPROVAL_MISSING = "APPROVAL_MISSING"
RC_APPROVAL_INVALID = "APPROVAL_INVALID"
RC_APPROVAL_EXPIRED = "APPROVAL_EXPIRED"
RC_APPROVAL_CONSUMED = "APPROVAL_CONSUMED"
RC_APPROVAL_MISMATCH = "APPROVAL_MISMATCH"
RC_OBJECT_MISMATCH = "OBJECT_MISMATCH"
RC_PATH_MISMATCH = "PATH_MISMATCH"
RC_COMMIT_MISMATCH = "COMMIT_MISMATCH"
RC_PROVENANCE_MISMATCH = "PROVENANCE_MISMATCH"
RC_MISSION_MISMATCH = "MISSION_MISMATCH"
RC_DELETE_DENIED = "DELETE_DENIED"
RC_OUTCOME_UNKNOWN = "OUTCOME_UNKNOWN"
RC_REJECTED = "REJECTED"
class DeleteExecutorError(Exception):
pass
class DeleteExecutorCore:
"""
DELETE-Executor. worker_scope="DELETE" (nur DELETE-Jobs claimbar).
approval_loader: Callable[[str], Optional[Dict[str, Any]]] — lädt die
AUTH.3D-Approval (approval_id) -> dict oder None.
approval_verify: Callable[[Dict[str, Any]], Dict[str, Any]] — verifiziert die
AUTH.3D-Signatur (Ed25519 PUBLIC KEY ONLY) -> {"valid": bool, "reason": str}.
tolaria_delete: Callable[[str], Dict[str, Any]] — führt den Tolaria-DELETE aus
(vault_path) -> {"status": "ok"|"error", "uncertain": bool}.
Muss fail-closed sein (kein HTTP ohne Credential).
"""
def __init__(
self,
store: JobStore,
approval_loader: Callable[[str], Optional[Dict[str, Any]]],
approval_verify: Callable[[Dict[str, Any]], Dict[str, Any]],
tolaria_delete: Callable[[str], Dict[str, Any]],
):
if store.worker_scope != "DELETE":
raise DeleteExecutorError("DeleteExecutorCore requires worker_scope='DELETE'")
self.store = store
self.approval_loader = approval_loader
self.approval_verify = approval_verify
self.tolaria_delete = tolaria_delete
# -- Hauptverarbeitung --------------------------------------------------
def process_job(self, job_id: str, worker_id: str) -> Dict[str, Any]:
"""
Verarbeitet einen DELETE-Job durch die State Machine.
Ablauf:
1. Job laden (muss existieren)
2. Job-Type-Scope prüfen (nur DELETE)
3. READY -> CLAIMED (atomarer Claim)
4. CLAIMED -> EXECUTING
5. AUTH.3D-Composition validieren (Job + Approval exakt zusammenpassen)
6. Tolaria-DELETE ausführen
7. Ergebnis: SUCCEEDED / FAILED / OUTCOME_UNKNOWN / REJECTED
"""
job = self.store.get_job(job_id)
if job is None:
raise DeleteExecutorError(f"job not found: {job_id}")
# Scope: nur DELETE-Jobs
if job["job_type"] != JOB_TYPE_DELETE:
self.store.mark_rejected(job_id, RC_REJECTED)
return self.store.get_job(job_id)
# Atomarer Claim
try:
self.store.claim_job(job_id, worker_id)
except Exception:
# Nicht claimbar (bereits geclaimt) -> kein Doppel-Delete
return self.store.get_job(job_id)
self.store.begin_execution(job_id, worker_id)
# AUTH.3D-Composition (alle Faktoren, keiner ersetzt einen anderen).
# Job NACH dem Claim neu lesen, damit eine Payload-Manipulation nach
# dem Claim (TOCTOU) erkannt wird — Defense in depth.
job = self.store.get_job(job_id)
if job is None:
self.store.mark_failed(job_id, RC_DELETE_DENIED, worker_id)
return self.store.get_job(job_id)
gate = self._validate_auth3d_composition(job)
if gate["valid"] is not True:
self.store.mark_failed(job_id, gate["code"], worker_id)
return self.store.get_job(job_id)
# Tolaria-DELETE ausführen (fail-closed)
result = self.tolaria_delete(job["vault_path"])
status = result.get("status")
if status == "ok":
self.store.mark_succeeded(job_id, worker_id)
elif status == "error" and result.get("uncertain"):
self.store.mark_outcome_unknown(job_id, worker_id)
else:
self.store.mark_failed(job_id, result.get("code", RC_DELETE_DENIED), worker_id)
return self.store.get_job(job_id)
# -- AUTH.3D-Composition -------------------------------------------------
def _validate_auth3d_composition(self, job: Dict[str, Any]) -> Dict[str, Any]:
"""
Validiert die AUTH.3D-Composition. Alle Faktoren müssen gelten:
VALID_JOB AND VALID_STATE AND VALID_AUTH3D_SIGNATURE AND VALID_NONCE
AND VALID_EXPIRY AND NOT_CONSUMED AND VALID_OBJECT AND VALID_PATH
AND VALID_COMMIT AND VALID_PROVENANCE AND DELETE_CREDENTIAL
Rückgabe: {"valid": True} oder {"valid": False, "code": RC_...}
"""
# VALID_JOB (Schema bereits beim Erzeugen validiert)
# VALID_STATE (EXECUTING — bereits durch begin_execution)
# Approval laden
approval = self.approval_loader(job["approval_id"])
if approval is None:
return {"valid": False, "code": RC_APPROVAL_MISSING}
# VALID_AUTH3D_SIGNATURE (Ed25519 PUBLIC KEY ONLY)
sig = self.approval_verify(approval)
if sig.get("valid") is not True:
return {"valid": False, "code": RC_APPROVAL_INVALID}
# VALID_NONCE / VALID_EXPIRY / NOT_CONSUMED
if approval.get("expired"):
return {"valid": False, "code": RC_APPROVAL_EXPIRED}
if approval.get("consumed"):
return {"valid": False, "code": RC_APPROVAL_CONSUMED}
# VALID_OBJECT
if approval.get("object_id") != job["object_id"]:
return {"valid": False, "code": RC_OBJECT_MISMATCH}
# VALID_PATH
if approval.get("vault_path") != job["vault_path"]:
return {"valid": False, "code": RC_PATH_MISMATCH}
# VALID_COMMIT
if approval.get("expected_commit") != job["expected_commit"]:
return {"valid": False, "code": RC_COMMIT_MISMATCH}
# VALID_PROVENANCE
if approval.get("expected_provenance_hash") != job["expected_provenance_hash"]:
return {"valid": False, "code": RC_PROVENANCE_MISMATCH}
# VALID_MISSION
if approval.get("mission_id") != job["mission_id"]:
return {"valid": False, "code": RC_MISSION_MISMATCH}
# DELETE_CREDENTIAL (fail-closed — tolaria_delete prüft selbst)
return {"valid": True}