{
  "contract_id": "negative-transfer-rejection-v1",
  "purpose": "Observe both returned rejection and forbidden durable partial effects on an actual SQLite transfer implementation.",
  "units": {
    "money": "integer cents",
    "balances": "nonnegative SQLite INTEGER cents",
    "transfer_count": "rows in transfers",
    "case": "one fresh on-disk SQLite database, one transfer invocation, and one new-connection state observation"
  },
  "input_domain": {
    "amount_cents": "Python int excluding bool; implementation accepts 1..1000000 inclusive. Executed amounts are -1, 0, 2000, 10000, 10001.",
    "source_id": "alice in all executed requests",
    "destination_id": [
      "bob",
      "ghost"
    ],
    "executed_requests": "Exactly the seven rows in cases.json, not their Cartesian product.",
    "fault_hook": "fail_after_debit is a test-only implementation seam, not an external request field and not evidence of attacker reachability."
  },
  "allowed_starting_states": [
    {
      "id": "S0",
      "accounts": [
        [
          "alice",
          10000
        ],
        [
          "bob",
          2500
        ]
      ],
      "transfers": [],
      "transaction_active": false,
      "description": "Every scenario starts from a new independent database in exactly S0; no previous transfer IDs, concurrent requests, triggers, or pending transactions."
    }
  ],
  "rules": [
    "For each of the five declared rejection scenarios, return its exact declared response, leave both accounts and all transfer records equal to S0, and return with no open transaction.",
    "For each of the two declared successful controls, return accepted with transfer_id 1, persist the exact declared debit and credit, record exactly one matching transfer row, and return with no open transaction.",
    "Zero and negative amounts are invalid. The insufficient-balance example is 10001 cents against an available 10000 cents. The unknown destination is ghost.",
    "The test-only failure runs a real INSERT of zero amount into transfers immediately after the real debit. SQLite rejects that INSERT with IntegrityError due to its CHECK constraint; the operation must reject as processing_failed and restore the prior state."
  ],
  "transaction_policy": {
    "connection": "sqlite3.connect(path, isolation_level=None), with autocommit=sqlite3.LEGACY_TRANSACTION_CONTROL explicitly pinned when available (Python >=3.12); Python3.10/3.11 use legacy behavior. All transaction boundaries are explicit SQL. No active transaction may be supplied.",
    "pragmas": {
      "foreign_keys": "ON",
      "journal_mode": "DELETE",
      "synchronous": "FULL"
    },
    "baseline": "No BEGIN. Individual statements autocommit. Catching the later SQL error does not undo the preceding committed debit.",
    "corrected": "BEGIN IMMEDIATE; validate source, destination and balance; debit, optional injected SQL error, credit and transfer record; COMMIT only on success. Rejections explicitly ROLLBACK. SQL exceptions explicitly ROLLBACK before returning processing_failed.",
    "exception_scope": "The caught sqlite3.Error is outside the transaction body in an explicit try/except; no connection context-manager rollback is assumed.",
    "begin_failure_scope": "BEGIN IMMEDIATE is outside the write-body try/except. Acquisition failures can propagate and are excluded by the uncontended single-connection fixture preconditions."
  },
  "oracle": {
    "response_only": "Compare exact expected response only (plus fixture setup), while retaining observed states for diagnosis.",
    "strengthened": "Compare exact response, test-owned SQL observation of both balances AND every transfer row after closing/reopening the database, and no open transaction. Expectations are literal JSON values.",
    "non_vacuity": "Run reject-all implementation against both successful controls; both must fail acceptance."
  },
  "exclusions": [
    "No claim of idempotency, at-most-once request processing, or repeated-request semantics.",
    "No email, notification, network call, or external side effect is modeled or claimed atomic.",
    "No concurrency, locking contention, crash/power-loss recovery, disk-full, database corruption, busy-timeout behavior, authorization or attacker-reachability claim.",
    "No proof of every possible input, starting state, exception, or production system. This is an original instructional fixture, not a discovered customer defect."
  ]
}
