{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://foray.dunin7.com/schema/foray-transaction-v4_2.schema.json",
  "title": "FORAY Protocol v4.2 Transaction (canonical shape)",
  "$comment": "Successor conformance artifact to schema/foray-transaction-v4_1.schema.json, authored at the D8 schema stage as the sole owner of wire names. Governing instrument: FORAY_Protocol_v4_2_F_Wire_Migration_Amendment-v0_4.md (ACCEPTED, in force 2026-07-24); catalog: foray-root-naming-ratification-decision-sheet-v1_1.md (F1-F29); rulings: foray-root-naming-ratification-addendum-fwire-oq-walk-v1_0.md. Wire keys are F-codes (D-W); the wire is flat (OQ-4) -- every Root-substance key matches ^F[0-9]+$ and every other key is envelope apparatus, enforced here by exhaustive enumeration with additionalProperties:false at every fact-bearing object (which also rejects unknown F-codes, retired 4.1 spellings, foray_* register names, and residue outside F25 per VAL-NEW-2/-3/-4). Requiredness carries the 4.1 canonical shape's parity re-keyed, plus F2 (OQ-7); the 4.1 schema's deliberate under-requiring for named-culprit validator errors (Anticipation F27/F28, Action F9 -- the E4/E5 pattern) is carried, so those remain validator-enforced, not schema-required. NOT expressible in JSON Schema and therefore delegated to the validator and FORAY formatter per the schema-stage contract note: the 15-significant-digit decimal profile and canonical spelling (OQ-2; magnitude shadow bounds |v| < 1e15 appear below where expressible), canonical member order (OQ-11 -- JSON objects are unordered at the data-model level this schema validates), the F8 inheritance resolution (OQ-9 -- this schema permits F8 absence at any single level because the chain resolves), F2 equality semantics (OQ-7 -- only presence/non-emptiness is structural), the exact-decimal allocation-sum rule (section 7.1.5), and dangling-reference resolution.",
  "type": "object",
  "required": [
    "schema_version",
    "timestamp",
    "F1",
    "F2",
    "F3",
    "F7",
    "F8",
    "F26",
    "arrangements",
    "accruals",
    "anticipations",
    "actions",
    "component_hashes",
    "merkle_root",
    "blockchain_anchor"
  ],
  "properties": {
    "schema_version": { "const": "4.2" },
    "timestamp": { "type": "string" },
    "F1": {
      "type": "string",
      "minLength": 1,
      "$comment": "Evidence record identifier. Post-migration, F1 identifies the evidence record itself; the source-linkage role lives in F2."
    },
    "F2": {
      "type": "string",
      "minLength": 1,
      "$comment": "Source record reference -- REQUIRED, non-empty (OQ-7). Adaptor-mediated origination: the originating system's key verbatim, distinct from F1. Native origination and migrated-legacy records: F2 == F1 (equality is legal and defined; its semantics are catalog territory, not schema-checkable)."
    },
    "F3": { "$ref": "#/$defs/OwnerForm" },
    "F7": { "$ref": "#/$defs/WireNumber" },
    "F8": {
      "type": "string",
      "$comment": "Currency at transaction scope. Component elements may carry their own F8; where a component's monetary fact has no component-level F8, this value governs (OQ-9 inheritance -- resolution is validator work; the schema only permits the members)."
    },
    "F15": { "type": "string" },
    "F25": { "$ref": "#/$defs/Residue" },
    "F26": { "type": "string" },
    "arrangements": { "type": "array", "items": { "$ref": "#/$defs/Arrangement" } },
    "accruals": { "type": "array", "items": { "$ref": "#/$defs/Accrual" } },
    "anticipations": { "type": "array", "items": { "$ref": "#/$defs/Anticipation" } },
    "actions": { "type": "array", "items": { "$ref": "#/$defs/Action" } },
    "attestations": {
      "type": "array",
      "$comment": "Optional fifth component class (OQ-11 envelope enumeration position 7). Interior not structurally validated, carrying the 4.1 artifact's documented posture forward unchanged."
    },
    "component_hashes": { "type": "object" },
    "merkle_root": { "type": "string" },
    "blockchain_anchor": {
      "type": "object",
      "$comment": "Envelope apparatus; inner keys are envelope structure, unchanged (section 2.2). Interior unconstrained at 4.1 parity."
    },
    "audit_data_anchor": { "type": "object" },
    "privacy_metadata": { "type": "object" }
  },
  "additionalProperties": false,
  "$defs": {
    "OwnerForm": {
      "type": "string",
      "minLength": 1,
      "oneOf": [
        { "pattern": "^sha256:[0-9a-f]{64}$" },
        { "not": { "pattern": "^sha256:" } }
      ],
      "$comment": "F3 single-form rule (OQ-8): exactly one of two catalog-defined forms -- cleartext (any non-empty string not beginning with the reserved prefix), or the salted digest as 'sha256:' + exactly 64 lowercase hex. A value beginning 'sha256:' that is not a well-formed digest is illegal in both forms. Dual carriage is retired; there is no second field."
    },
    "WireNumber": {
      "type": "number",
      "exclusiveMinimum": -1e15,
      "exclusiveMaximum": 1e15,
      "$comment": "Expressible shadow of the OQ-2 decimal profile: the ruled bound is 'at most 15 significant decimal digits', which JSON Schema cannot state; the magnitude bound |v| < 1e15 is its schema-expressible consequence for the integer part. Full precision enforcement (significant digits, canonical shortest-round-trip plain-notation spelling, no exponent/trailing-zero/-0 forms) is the validator's and the FORAY formatter's, per the schema-stage contract."
    },
    "Residue": {
      "type": "object",
      "$comment": "F25, the sole residue home (D6; positions per OQ-6: transaction top level and each component element, nowhere else -- the 'nowhere else' is enforced by every other object's closed property set). Interior keys are free residue, hashed and tamper-evident but not Root-validated (R7); interior serialization is JCS-lexicographic (section 7.1.3)."
    },
    "RefArray": {
      "type": "array",
      "items": { "type": "string", "minLength": 1 },
      "$comment": "F22/F23/F24 cross-component reference arrays. Presence-when-empty rules of v4.1.5 section 4.3 carry forward under the new keys; dangling-reference resolution is validator work."
    },
    "Arrangement": {
      "type": "object",
      "required": ["id", "F4", "F5", "F11"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "F4": { "type": "string" },
        "F5": {
          "type": "array",
          "$comment": "Parties. Entry interior is catalog-defined F5 structure ({role, name, jurisdiction} per the value-structure rule, OQ-9) -- deliberately not closed here at 4.1 parity; see the schema-stage contract note's finding on party-entry structure and protected party forms (catalog cadence)."
        },
        "F7": { "$ref": "#/$defs/WireNumber" },
        "F8": { "type": "string" },
        "F11": { "type": "string" },
        "F14": {
          "type": "string",
          "$comment": "Period end at Arrangement scope: the OQ-5 catalog broadening -- a term maturity is F14 where the term is a period."
        },
        "F25": { "$ref": "#/$defs/Residue" },
        "F29": {
          "type": "array",
          "$comment": "Digest-identified external artifact references (D3.4). Arrangement scope at migration; catalog may broaden."
        }
      },
      "additionalProperties": false,
      "$comment": "4.1-parity requireds re-keyed (type->F4, effective_date->F11, parties->F5) minus the retired 'terms' (OQ-5: its content is residue -> F25). 'description', 'dependencies', 'terms', and the 'foray_core' wrapper are all rejected by the closed property set."
    },
    "Accrual": {
      "type": "object",
      "required": ["id", "F22"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "F4": { "type": "string" },
        "F7": { "$ref": "#/$defs/WireNumber" },
        "F8": { "type": "string" },
        "F13": { "type": "string" },
        "F14": { "type": "string" },
        "F17": { "type": "string" },
        "F18": {
          "type": "string",
          "pattern": "^hash_[0-9a-f]{32}$",
          "$comment": "D5: pattern-constrained formula identifier. The salted formula ID proves definition retention, never execution correctness (F-18 rider)."
        },
        "F19": {
          "type": "object",
          "$comment": "D5: object keyed by input name. Input names are F19 structure (engagement-governed per Root section 7.2); values are not structurally constrained here."
        },
        "F20": { "$ref": "#/$defs/WireNumber" },
        "F22": { "$ref": "#/$defs/RefArray" },
        "F25": { "$ref": "#/$defs/Residue" }
      },
      "additionalProperties": false,
      "$comment": "4.1-parity required set re-keyed (arrangement_refs->F22). The 'period' wrapper is retired (flatten); F13/F14 are flat facts."
    },
    "Anticipation": {
      "type": "object",
      "required": ["id", "F22", "F23"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "F4": { "type": "string" },
        "F8": { "type": "string" },
        "F10": { "$ref": "#/$defs/WireNumber" },
        "F22": { "$ref": "#/$defs/RefArray" },
        "F23": { "$ref": "#/$defs/RefArray" },
        "F25": { "$ref": "#/$defs/Residue" },
        "F27": { "type": "string" },
        "F28": { "$ref": "#/$defs/WireNumber" }
      },
      "additionalProperties": false,
      "$comment": "F27 and F28 are the ruled canonical facts but are deliberately NOT schema-required, carrying the 4.1 artifact's E4 posture: the validator enforces them itself so it can name the specific culprit. 'condition' remains retired (v4.1.5 section 5.3) and is rejected by the closed property set."
    },
    "Action": {
      "type": "object",
      "required": ["id", "F22", "F23", "F24"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "F4": { "type": "string" },
        "F6": { "type": "string" },
        "F8": { "type": "string" },
        "F9": { "$ref": "#/$defs/WireNumber" },
        "F12": { "type": "string" },
        "F15": { "type": "string" },
        "F16": { "type": "string" },
        "F21": {
          "type": "array",
          "items": { "$ref": "#/$defs/Allocation" }
        },
        "F22": { "$ref": "#/$defs/RefArray" },
        "F23": { "$ref": "#/$defs/RefArray" },
        "F24": { "$ref": "#/$defs/RefArray" },
        "F25": { "$ref": "#/$defs/Residue" }
      },
      "additionalProperties": false,
      "$comment": "F9 is the ruled canonical settled-amount fact but is deliberately NOT schema-required, carrying the 4.1 artifact's E5 posture (validator names the culprit). The exact-decimal allocation-sum rule (sum of F21 entry amounts == F9, section 7.1.5) is a cross-field rule enforced in validator code, not here."
    },
    "Allocation": {
      "type": "object",
      "required": ["ref", "ref_type", "amount", "currency"],
      "properties": {
        "ref": { "type": "string", "minLength": 1 },
        "ref_type": { "enum": ["anticipation", "accrual", "arrangement"] },
        "amount": { "$ref": "#/$defs/WireNumber" },
        "currency": { "type": "string" },
        "allocation_type": { "enum": ["full", "partial", "overpayment"] },
        "remaining_balance": { "$ref": "#/$defs/WireNumber" }
      },
      "additionalProperties": false,
      "$comment": "F21 entry structure (OQ-9): named keys, catalog-defined, never independently F-coded; 'amount'/'currency' semantics inherit F7/F8 by catalog cross-reference. Closed (additionalProperties:false) -- unlike the open 4.1 definition -- because an extra key inside an entry is residue outside F25's two ruled positions (VAL-NEW-4)."
    }
  }
}
