Ctrl K
ComunidadGuías…

docs/runtime-semantics-and-recovery.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Runtime semantics and recovery

This document defines operational behavior that must be explicit before production.

## 1. Grant expiry during long-running jobs

An elevated job derives an immutable job grant at start.

Default:

~~~text
job_deadline <= grant_expiry
~~~

When the grant expires:

1. stop accepting new privileged mutations from that job
2. send graceful termination to the managed process/cgroup
3. after a bounded grace period, force termination
4. persist the final state
5. emit audit

Routine Scoped jobs do not need an elevated grant.

If a specific administrative job must outlive the interactive grant, require a separate action-specific completion grant with its own bounded deadline.

## 2. SQLite concurrency

SQLite is intentionally single-writer and acceptable initially.

Rules:

- only Broker opens the DB
- transactions are short
- never keep a transaction open while shell/deploy/migration/Docker work runs
- persist transition, commit, perform external work, persist next transition
- long-lived exclusion uses logical resource locks with deadlines, not long DB transactions
- enable WAL
- use busy timeout/backoff for short contention

Migrate only if measured contention becomes material.

### Resource-lock fencing

Locks with TTL/deadline must include a monotonically increasing fencing token.

A stale job can never release a resource or commit a protected step using an older token. Release is compare-and-delete on resource + owner/action_id + fencing token.

This closes the classic ABA race:

```text
A acquires token 1
A stalls and expires
B acquires token 2
A wakes up late
A must NOT release/overwrite B
```

### Idempotency crash window

For replay-protected effects, create an operation journal row before the external side effect:

```text
PENDING -> effect -> DONE
```

If the Broker crashes after the effect but before DONE, the next attempt does not re-execute automatically. It enters action-specific reconciliation or returns an indeterminate/reconcile-required result.

## 3. Idempotency is infrastructure metadata

Do not depend on the LLM to invent a stable idempotency key.

Preferred behavior:

- Gateway/integration layer generates or derives retry identity
- bind it to subject + canonical tool + normalized request hash + invocation identity
- use a client/transport invocation identity when available
- if no stable retry identity exists, do not auto-retry state-changing operations

Identical arguments do not prove a retry; the user may legitimately request the same action twice.

## 4. Secret management

The MVP has no secret-reading tools.

Default VPS mechanisms:

- root-owned files outside the repository
- systemd credentials

Broker resolves secret_ref internally and injects the value only into the target process.

Rules:

- Gateway cannot read plaintext secret storage
- model-facing tools cannot enumerate secret values
- secrets never enter audit payloads
- redact known secrets from stdout/stderr/logs where practical

External secret managers are optional adapters when a real need appears.

## 5. Approval friction

Routine unattended work uses pre-authorized Scoped policy.

Out-of-band approval is reserved for exceptional elevation.

This avoids approval fatigue while keeping administrative access deliberate.

## 6. Recovery

### Broker restarts during a job

- jobs run in managed systemd units/cgroups where appropriate
- every job has a deadline
- Broker restart reconciles persisted state with live units/processes
- orphan jobs are adopted for monitoring or terminated by policy

### SQLite corruption

Fail closed:

1. stop new Gateway/Broker writes
2. invalidate pending approvals
3. treat elevated grants as revoked
4. preserve damaged DB
5. restore latest verified backup
6. reconcile active job units
7. re-enable only after integrity checks

### Broker audit write failure (AUD-03)

Privileged or potentially state-changing requests follow a fail-closed audit
protocol. The Broker commits an append-only hash-chain `intent` event (bound to
the request invocation ID when present) **before** invoking an external effect;
it records a separate `allow` or `deny` outcome afterward. New or unknown
tool names are **mutating by default** unless explicitly reviewed as read-only.
Potentially mutating requests are serialized through this boundary.

- If durable intent cannot be written, the Broker rejects the operation
  **before** any external mutation.
- If the effect happened but the outcome cannot be written, the response is
  `reconcile_required`, **not** a success or a claim that the effect was
  rolled back. The intent remains in the audit chain.
- On any audit append failure, the Broker latches a degraded state and refuses
  subsequent state-changing requests, even if SQLite immediately recovers.
  A new Broker process is required **after deliberate operator reconciliation**.
  An operator must not retry unsafe actions automatically or clear the database
  to bypass the fence.
- The operator should independently check the affected resource's actual
  state, match audit `intent` to its invocation ID and operation journal,
  inspect hash-chain integrity, repair storage safely, and decide whether a
  restart is warranted. For operations with idempotency keys, replays use the
  stored operation status; without stable keys, do not assume retry safety.
- Hash-chained intent and result are distinct database commits; they do not
  make an external shell command, Docker call or filesystem write an atomic
  transaction. A crash may leave a valid unmatched `intent` that requires
  explicit inspection.

Audit events contain metadata, never request-body secrets. This gate does not
replace transactional approval/grant resolution, OAuth checks or revocation.

### Erroneously issued grant

Provide an operator command outside the AI surface:

~~~text
vps-agent revoke-all
~~~

It must:

- revoke all elevated grants
- block new elevated starts
- terminate or quarantine affected active jobs according to emergency policy
- emit an audit record/checkpoint appropriate to the maturity stage

Rotate credentials separately if credential compromise is suspected.

### Gateway route compromise

Stopping/removing the MCP route must not stop application workloads.

## 7. Backups

At the stage where these assets exist, back up:

- policy configuration
- SQLite state
- audit checkpoints
- deployment unit files

Do not include plaintext secrets unless intentionally encrypted.

## 8. Readiness

### Scoped production
Require:

- Gate 0A/0B and the typed privileged path passed;
- Scoped real-stack behavior proven for the documented use case;
- recovery tested for enabled state/jobs;
- secret path tested if secrets are used;
- Gateway/Broker removal leaves workloads running;
- release compatibility/support boundaries documented;
- long-running reliability evidence appropriate to the production claim.

The release candidate satisfies the implementation/E2E gates but does not yet claim the long-running R4 reliability history.

### Full production
Additionally require:

- grant/job expiry semantics tested
- revoke-all tested
- approval flow tested
- remote audit checkpointing tested
- network elevation separation tested