{
  "schema_version": 1,
  "evidence_type": "executed synthetic operations",
  "command": "python operations_rehearsal.py",
  "passed": true,
  "checks": [
    {
      "id": "crash.ingest",
      "description": "Abrupt exit before ingest commit leaves every business table empty",
      "expected": {
        "exit": 86,
        "rows": 0
      },
      "observed": {
        "exit": 86,
        "rows": 0
      },
      "passed": true,
      "method": "Child os._exit after event, entry, posting, totals and audit writes but before SQLite commit."
    },
    {
      "id": "crash.response",
      "description": "Committed ingest survives process exit and replay creates no extra quantity",
      "expected": {
        "exit": 87,
        "duplicate": true,
        "quantity": "1.125"
      },
      "observed": {
        "exit": 87,
        "duplicate": true,
        "quantity": "1.125"
      },
      "passed": true,
      "method": "Child exits after commit. Parent reopens the database and retries the original identity."
    },
    {
      "id": "load.idempotency",
      "description": "Eight concurrent writers turn 800 requests into 400 source events",
      "expected": {
        "new": 400,
        "duplicate": 400,
        "matches": true
      },
      "observed": {
        "new": 400,
        "duplicate": 400,
        "matches": true
      },
      "passed": true,
      "method": "Separate SQLite connections ingest every synthetic event identity twice."
    },
    {
      "id": "load.exact-total",
      "description": "Concurrent exact quantities sum without rounding",
      "expected": "450.000",
      "observed": "450.000",
      "passed": true,
      "method": "400 unique events x 1.125 minutes = 450.000 minutes using integer base units."
    },
    {
      "id": "load.corrections",
      "description": "Ten corrections append reversals and replacements with the expected net",
      "expected": "447.500",
      "observed": "447.500",
      "passed": true,
      "method": "450.000 - 10 x (1.125 - 0.875) = 447.500 minutes."
    },
    {
      "id": "close.rollback",
      "description": "Crash before close commit leaves period open and no frozen version",
      "expected": {
        "exit": 86,
        "status": "open",
        "closes": 0
      },
      "observed": {
        "exit": 86,
        "status": "open",
        "closes": 0
      },
      "passed": true,
      "method": "Child exits after writing the close, period status and audit row but before commit."
    },
    {
      "id": "close.immutability",
      "description": "Late event and correction leave the frozen January digest unchanged",
      "expected": "cfa9e8ea751f8921176b347023e120d2b8d93a7e481e2bcf4c418b56f3046231",
      "observed": "cfa9e8ea751f8921176b347023e120d2b8d93a7e481e2bcf4c418b56f3046231",
      "passed": true,
      "method": "Post-close input stays pending. Export rebuild uses the stored posting cutoff."
    },
    {
      "id": "api.isolation",
      "description": "Other-account read and viewer mutation are rejected",
      "expected": [
        403,
        403
      ],
      "observed": [
        403,
        403
      ],
      "passed": true,
      "method": "Real HTTP requests use a demo-scoped operator token and a viewer token."
    },
    {
      "id": "api.boundary",
      "description": "Foreign Host and Origin are rejected",
      "expected": [
        403,
        403
      ],
      "observed": [
        403,
        403
      ],
      "passed": true,
      "method": "Otherwise authorized real loopback requests."
    },
    {
      "id": "api.storage",
      "description": "Storage failure returns HTTP 503 without inventing success",
      "expected": 503,
      "observed": 503,
      "passed": true,
      "method": "Inject sqlite3.OperationalError before domain ingestion; retry keeps the stable event identity."
    },
    {
      "id": "restore.frozen-export",
      "description": "Restored January export matches every frozen row and digest",
      "expected": {
        "sha256": "cfa9e8ea751f8921176b347023e120d2b8d93a7e481e2bcf4c418b56f3046231",
        "entries": 420,
        "identical": true
      },
      "observed": {
        "sha256": "cfa9e8ea751f8921176b347023e120d2b8d93a7e481e2bcf4c418b56f3046231",
        "entries": 420,
        "identical": true
      },
      "passed": true,
      "method": "Restore the pre-late-input snapshot into a new directory and rebuild the canonical export."
    },
    {
      "id": "restore.point-in-time",
      "description": "Snapshot correctly excludes the two records received after backup",
      "expected": 0,
      "observed": 0,
      "passed": true,
      "method": "This expected loss demonstrates a nonzero backup recovery-point gap."
    },
    {
      "id": "restore.source-replay",
      "description": "Stable upstream identities restore two lost records exactly once",
      "expected": 2,
      "observed": 2,
      "passed": true,
      "method": "Replay the retained synthetic input journal twice against the restored snapshot."
    },
    {
      "id": "restore.carry-forward",
      "description": "Recovered late usage and correction close February at 2.625 minutes",
      "expected": "2.625",
      "observed": "2.625",
      "passed": true,
      "method": "3.125 late minutes - (1.125 - 0.625) correction = 2.625, posted after the immutable January close."
    },
    {
      "id": "restore.closed-digest",
      "description": "Recovery and carry-forward preserve the January digest",
      "expected": "cfa9e8ea751f8921176b347023e120d2b8d93a7e481e2bcf4c418b56f3046231",
      "observed": "cfa9e8ea751f8921176b347023e120d2b8d93a7e481e2bcf4c418b56f3046231",
      "passed": true,
      "method": "Rebuild January again after February approval and close."
    },
    {
      "id": "restore.corruption",
      "description": "Modified snapshot is rejected before destination creation",
      "expected": true,
      "observed": true,
      "passed": true,
      "method": "Change six bytes without changing checksum manifest."
    },
    {
      "id": "restore.no-overwrite",
      "description": "Existing restore destination is preserved",
      "expected": true,
      "observed": true,
      "passed": true,
      "method": "Attempt recovery into an occupied folder."
    },
    {
      "id": "integrity.final",
      "description": "Recovered database passes integrity and foreign-key checks",
      "expected": {
        "integrity": "ok",
        "foreign_key_errors": 0
      },
      "observed": {
        "integrity": "ok",
        "foreign_key_errors": 0
      },
      "passed": true,
      "method": "PRAGMA integrity_check and foreign_key_check after replay, approval and close."
    },
    {
      "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": "9d2452798732d05d7aa13889f51ad8bb9437fbe235553291870c113039578abb",
    "ledger.py": "9dc1df23ebb05d60d6854df7cf20ec955145fb62690f1ca1796417e0c3bb8e39",
    "operations.py": "8a843a53bcc3770b898f119a67fdccec39d072e699dd265f12ea2b9a7c004646",
    "operations_rehearsal.py": "1332f9b39111f7a7744ade24145801d261ecefdf6ce347d78f02703673ab8ec0",
    "operations_report.py": "c29103f60dc45531b0fc9ea943d6b760800e49a5861c8d7873c41f08d4df4539",
    "backup_schedule.py": "4442ac5c844508d8198a3f2577d4864cb03882a920cea42b6f2549b9a7403851"
  },
  "report": "operations-report.html",
  "limitations": [
    "The crash drill terminates a process before or after commit. It does not simulate disk firmware, physical power loss or media failure.",
    "All usage and tokens are synthetic. No invoice, tax, currency or payment conclusion follows from these quantities.",
    "Point-in-time recovery deliberately loses post-snapshot events until replay. Recovery requires a separately retained source journal with stable identities; the service cannot reconstruct absent source data.",
    "Snapshot checksum verification detects corruption, not malicious replacement of both database and manifest. Protect or encrypt backups where required.",
    "The local timing and 15-minute backup scenario are evidence and assumptions respectively, not a service-level agreement or enabled schedule."
  ],
  "metrics": {
    "concurrent_ingestion": {
      "writers": 8,
      "requests": 800,
      "unique_events": 400,
      "elapsed_seconds": 0.8952,
      "requests_per_second": 893.67,
      "qualification": "Finite local synthetic run with repeated connection initialization, not a production rate guarantee."
    },
    "recovery": {
      "snapshot_bytes": 245760,
      "snapshot_seconds": 0.004807,
      "restore_seconds": 0.006143,
      "snapshot_source_events": 410,
      "events_after_snapshot": 2,
      "upstream_replay_operations": 4,
      "new_events_after_replay": 2,
      "nominal_backup_interval_seconds": 900,
      "theoretical_max_unbacked_events_at_2_per_second": 1800,
      "assumption": "At most two events per second, successful backup every 15 minutes. This is a capacity/RPO scenario, not measured customer traffic."
    }
  },
  "python": "3.12.14",
  "elapsed_seconds": 1.804
}
