{
  "schema_version": 1,
  "evidence_type": "executed synthetic operations",
  "command": "python operations_rehearsal.py",
  "passed": true,
  "checks": [
    {
      "id": "crash.reclaim",
      "description": "Claim survives abrupt exit and a new worker replaces the expired owner",
      "expected": {
        "exit": 86,
        "same_job": true,
        "new_token": true,
        "attempt": 2
      },
      "observed": {
        "exit": 86,
        "same_job": true,
        "new_token": true,
        "attempt": 2
      },
      "passed": true,
      "method": "Child persists a lease then os._exit. A declared clock advances from 1000 to 1002 seconds, past its one-second lease."
    },
    {
      "id": "crash.fence",
      "description": "Old worker completion rejected; replacement completion accepted",
      "expected": [
        false,
        true
      ],
      "observed": [
        false,
        true
      ],
      "passed": true,
      "method": "Call completion with persisted old and new ownership tokens after restart."
    },
    {
      "id": "http.delivery",
      "description": "Four workers deliver all 80 accepted jobs",
      "expected": {
        "delivered": 80
      },
      "observed": {
        "delivered": 80
      },
      "passed": true,
      "method": "Forty normal and forty first-response-loss events, two in-flight requests per endpoint, real signed loopback HTTP."
    },
    {
      "id": "http.deduplication",
      "description": "120 requests cause exactly 80 receiver business effects",
      "expected": {
        "requests": 120,
        "effects": 80
      },
      "observed": {
        "requests": 120,
        "effects": 80
      },
      "passed": true,
      "method": "Receiver stores a fingerprint and one effect per endpoint/event identity. Forty first responses are deliberately closed after commit."
    },
    {
      "id": "http.attempts",
      "description": "Attempt history contains the expected first failures and successful retries",
      "expected": {
        "retry": 40,
        "delivered": 80
      },
      "observed": {
        "retry": 40,
        "delivered": 80
      },
      "passed": true,
      "method": "Count persisted terminal outcomes after every worker has drained."
    },
    {
      "id": "api.authorization",
      "description": "Missing administrator token is rejected",
      "expected": 401,
      "observed": 401,
      "passed": true,
      "method": "Real loopback HTTP without bearer authorization."
    },
    {
      "id": "api.boundary",
      "description": "Foreign Host and Origin requests are rejected",
      "expected": [
        403,
        403
      ],
      "observed": [
        403,
        403
      ],
      "passed": true,
      "method": "Authenticated requests with foreign Host or Origin."
    },
    {
      "id": "api.storage",
      "description": "Storage failure returns retryable HTTP 503 without accepting an event",
      "expected": 503,
      "observed": 503,
      "passed": true,
      "method": "Inject sqlite3.OperationalError at acceptance, before the transaction starts; error response contains no payload or credential."
    },
    {
      "id": "restore.at-least-once",
      "description": "Restoring an older queue snapshot redelivers without duplicate receiver effect",
      "expected": {
        "requests": 2,
        "effects": 1,
        "status": "delivered"
      },
      "observed": {
        "requests": 2,
        "effects": 1,
        "status": "delivered"
      },
      "passed": true,
      "method": "Snapshot a ready job, deliver it, restore the older snapshot into a new directory and deliver again to the same durable receiver."
    },
    {
      "id": "restore.identity",
      "description": "Restored acceptance still recognizes the same event identity",
      "expected": true,
      "observed": true,
      "passed": true,
      "method": "Replay the accepted event through the restored domain API."
    },
    {
      "id": "restore.corruption",
      "description": "Corrupt snapshot rejected before destination creation",
      "expected": true,
      "observed": true,
      "passed": true,
      "method": "Change stored bytes without changing checksum manifest."
    },
    {
      "id": "restore.no-overwrite",
      "description": "Existing restore directory remains untouched",
      "expected": true,
      "observed": true,
      "passed": true,
      "method": "Attempt restore into a nonempty directory."
    },
    {
      "id": "integrity.final",
      "description": "Queue integrity and foreign-key checks pass",
      "expected": {
        "integrity": "ok",
        "foreign_key_errors": 0
      },
      "observed": {
        "integrity": "ok",
        "foreign_key_errors": 0
      },
      "passed": true,
      "method": "Check live workload database after all worker threads stop."
    },
    {
      "id": "theory.retry-budget",
      "description": "Declared four-attempt timeout/backoff calculation totals 15 seconds",
      "expected": 15,
      "observed": 15,
      "passed": true,
      "method": "Compute 4 x 2 + (1 + 2 + 4); exclude DNS, scheduling and lock waiting explicitly."
    },
    {
      "id": "backup.schedule",
      "description": "Finite scheduler creates two checked snapshots and stops",
      "expected": {
        "exit": 0,
        "snapshots": 2,
        "valid": 2
      },
      "observed": {
        "exit": 0,
        "snapshots": 2,
        "valid": 2
      },
      "passed": true,
      "method": "Run the supplied CLI in a subprocess with two snapshots and a 10 ms interval. This exercises scheduling without leaving a background process."
    }
  ],
  "source_sha256": {
    "app.py": "134c5811c2f36f33a6e6f6e2f92bf4b763683880ad49aea39b6b36a40849f11c",
    "delivery_queue.py": "1172712417d5cb823266345308c6be37a759efd526a9f8ca05dd25f1c15a6d00",
    "receiver.py": "c2d50c17e8cdc3524f4440dc75f5a4c17de327ce62e2295b298669bfb9b6df7a",
    "operations.py": "8a843a53bcc3770b898f119a67fdccec39d072e699dd265f12ea2b9a7c004646",
    "operations_rehearsal.py": "1e4cf2aab734a08d4495e41fd23fd0a50df0b7e1796ede64b5171ed884f05abe",
    "operations_report.py": "c29103f60dc45531b0fc9ea943d6b760800e49a5861c8d7873c41f08d4df4539",
    "backup_schedule.py": "4442ac5c844508d8198a3f2577d4864cb03882a920cea42b6f2549b9a7403851"
  },
  "report": "operations-report.html",
  "limitations": [
    "The child crash is real process termination, but lease time is deliberately advanced by an injected clock. It is not machine power-loss testing.",
    "All destinations and events are local synthetic fixtures. No live external destination, DNS outage or public TLS ingress was exercised.",
    "The restore drill preserves the receiver database. Losing receiver deduplication while replaying a queue can duplicate external effects.",
    "Snapshots contain endpoint signing secrets. They require restricted storage and encryption at rest where the environment needs it; the checksum is not a signature.",
    "The theoretical retry calculation excludes unbounded OS DNS timing and scheduler delays. Single-host SQLite provides no automatic failover."
  ],
  "metrics": {
    "http_workload": {
      "jobs": 80,
      "workers": 4,
      "http_attempts": 120,
      "elapsed_seconds": 0.4144,
      "delivered_jobs_per_second": 193.07,
      "qualification": "A finite local synthetic workload, not internet latency or sustained capacity."
    },
    "recovery": {
      "snapshot_bytes": 45056,
      "snapshot_seconds": 0.003724,
      "restore_seconds": 0.002835,
      "queue_backup_rpo_seconds": 300,
      "receiver_requirement": "Receiver deduplication records must outlive the longest queue replay or backup retention horizon."
    },
    "theoretical_outage_envelope": {
      "attempts": 4,
      "per_attempt_seconds": 2,
      "retry_delays_seconds": [
        1,
        2,
        4
      ],
      "elapsed_if_every_request_uses_timeout_seconds": 15,
      "excluded_from_bound": [
        "DNS resolver latency",
        "worker scheduling delay",
        "SQLite lock wait"
      ],
      "arrival_jobs_per_second": 2,
      "outage_seconds": 600,
      "generated_jobs": 1200,
      "conclusion": "A ten-minute outage exceeds this retry envelope. Jobs become dead letters and need deliberate replay; a queue does not guarantee automatic delivery after arbitrary outages."
    }
  },
  "python": "3.12.14",
  "elapsed_seconds": 1.761
}
