Dependency Locks¶
Stand: 2026-05-26
Ziel¶
Dependency Locks verhindern parallele oder widerspruechliche Execution Chains auf denselben Objekten. Sie schuetzen vor Race Conditions zwischen Execution, Cleanup und Reconciliation.
Lock-Modell¶
Pflichtfelder:
| Feld | Zweck |
|---|---|
lock_id |
eindeutige Lock-ID |
object_id |
Zielobjekt, z. B. pve/lxc/124 |
object_type |
Objekttyp |
source_system |
Quellsystem |
lock_type |
Zweck des Locks |
lock_owner |
Besitzer |
chain_id |
Chain-Kontext |
approval_id |
Approval-Kontext |
created_at |
Erstellzeitpunkt |
expires_at |
Ablaufzeitpunkt |
status |
Lifecycle-Status |
reason |
Begruendung |
scope |
Geltungsbereich |
blocking_level |
Blockierstufe |
release_condition |
Freigabebedingung |
Lock Types¶
executioncleanup_preparecleanup_executereconciliationmanual_holdemergency_hold
Status¶
activereleasedexpiredfailed_releaseorphaned
Blocking Levels¶
read_warningwrite_blockdestructive_blockglobal_block
Storage¶
Operationaler Store ist SQLite:
- DB:
/var/lib/lanstyle-agent/controlled-execution/locks/locks.db - Tabelle:
active_locks - Tabelle:
lock_events - WAL Mode: aktiv
busy_timeout: aktiv
JSONL bleibt als Audit-Trail erhalten:
- Legacy JSONL:
/var/lib/lanstyle-agent/controlled-execution/locks/locks.jsonl - Audit:
/var/log/lanstyle-agent/dependency-locks.jsonl
Dateirechte sind 0600. Es werden keine Secrets gespeichert.
Falls SQLite nicht verfuegbar ist, arbeitet die Lock-Schicht fail-closed. Es gibt keinen automatischen Fallback auf ungesicherten JSONL-Write.
API¶
GET /dependency-locks/policyGET /dependency-locksGET /dependency-locks/lxc-124-templatePOST /dependency-locks/acquirePOST /dependency-locks/validatePOST /dependency-locks/releasePOST /dependency-locks/expirePOST /dependency-locks/orphan
Diese API veraendert nur Lock-Records, keine Infrastruktur.
Enforcement¶
Vor Execution muss geprueft werden:
- aktiver Lock auf Zielobjekt
- aktiver destruktiver Lock
- globaler Lock auf
source_system - abgelaufene aktive Locks
- orphaned Locks
- Chain-/Approval-Ownership
Rueckgabe:
execution_allowedblocked_reasonblocking_locksstale_lockslock_recommendation
Chain Lifecycle Enforcement¶
Dependency Locks sind jetzt direkt in den Chain-Lifecycle eingebunden.
Preflight:
- ermittelt Zielobjekte
- berechnet Lock-Kandidaten
- meldet Konflikte
- setzt keinen dauerhaften Lock, ausser
preflight_lock_requested=trueunddry_run=false
Execute:
- erwirbt vor dem ersten Step automatisch einen Lock
- prueft
chain_id,approval_idund Zielobjekt - bricht vor Step 1 ab, wenn ein fremder Lock blockiert
- released den Lock erst nach erfolgreicher Verification und Audit
- markiert den Lock bei Chain-Failure als
orphaned - markiert Release-Probleme als
failed_release - behandelt abgelaufene aktive Locks als blockierend, nicht als sichere Freigabe
Ein eigener Lock darf nur weiterverwendet werden, wenn chain_id und approval_id exakt passen.
Atomic Acquire/Release¶
acquire_lock nutzt eine SQLite-Transaktion mit BEGIN IMMEDIATE. Dadurch koennen parallele Acquires auf dasselbe Objekt nicht gleichzeitig gewinnen.
Validierter Concurrency-Test:
- 10 parallele Acquire-Versuche auf
pve/lxc/124 - genau 1 Lock gewinnt
- 9 Versuche werden blockiert
- nach Release gewinnt ein neuer Acquire
SQLite verhindert Race Conditions operational. JSONL dient nur noch als Audit-/Historienquelle.
Recovery¶
Orphaned, failed-release, stale, expired und emergency-hold Locks duerfen nicht blind released oder geloescht werden. Recovery laeuft ueber einen eigenen Approval-Flow:
- Recovery Preflight
- Recovery Approval Request
- Verification
- Recovery Execute
- Audit
Details: Lock Recovery.
Timeout bedeutet nicht automatisch sicher. Ein stale Lock blockiert weitere Chains auf demselben Objekt, bis ein Operator mindestens inspect_lock, inspect_chain_status, state_drift_check und recovery_preflight ausgefuehrt hat. Erst danach darf mit eigener Recovery-Approval release_after_verification oder expire_after_verification ausgefuehrt werden.
Operator UX¶
Lock-Informationen werden in unified_operator_response.lock_summary gespiegelt. OpenCode soll anzeigen:
- aktive Locks
- Lock-Kandidaten
- Blocker
lock_ownerexpires_atrelease_required- stale/orphan/failed-release Warnungen
Bei blockierendem Lock ist der Workflow-State blocked oder recovery_required. OpenCode darf dann keinen Execute anbieten, sondern muss Recovery oder manuelle Pruefung empfehlen.
Kompakte Operator Summary bei Lock-Konflikt:
- Gesamtentscheidung:
blocked_by_lock - Warum blockiert: aktiver, stale, orphaned oder failed-release Lock
- Sicher als naechstes: Lock inspizieren, Chain-Status pruefen, State/Drift pruefen, Recovery-Preflight starten
- Nicht tun: kein automatisches Release, keine automatische Folge-Chain, keine Fortsetzung nur wegen Timeout
LXC 124¶
Fuer pve/lxc/124 wurde ein Lock-Testpfad vorbereitet:
- Acquire Lock
- zweite konkurrierende Chain blockiert
- Release Lock
- danach wieder allowed
- Expired Lock Simulation
- Chain B bleibt bei Konflikt blockiert und wird nicht automatisch nach Lock-Freigabe fortgesetzt
- Orphaned Lock Simulation
Es findet keine Proxmox-Aenderung statt.