{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://flowrs.openie.dev/schemas/form-contract-1.json",
  "title": "flowRS form contract",
  "description": "The FORM.json every flowRS export carries: for one generated program, each of the form contract's properties, what enforces it, its status for this program (computed from the program and flowRS's code when it was exported, never written by hand), why, and the evidence. The properties are explained at the `explained` page.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "$schema",
    "format",
    "explained",
    "program",
    "counts",
    "properties"
  ],
  "properties": {
    "$schema": {
      "const": "https://flowrs.openie.dev/schemas/form-contract-1.json"
    },
    "format": {
      "const": 1
    },
    "explained": {
      "const": "https://flowrs.openie.dev/docs/form-contract/"
    },
    "program": {
      "$ref": "#/$defs/program"
    },
    "counts": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "live",
        "partial",
        "not_yet",
        "not_applicable"
      ],
      "properties": {
        "live": {
          "type": "integer",
          "minimum": 0,
          "maximum": 16
        },
        "partial": {
          "type": "integer",
          "minimum": 0,
          "maximum": 16
        },
        "not_yet": {
          "type": "integer",
          "minimum": 0,
          "maximum": 16
        },
        "not_applicable": {
          "type": "integer",
          "minimum": 0,
          "maximum": 16
        }
      }
    },
    "properties": {
      "type": "array",
      "minItems": 16,
      "maxItems": 16,
      "prefixItems": [
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 1
                },
                "key": {
                  "const": "memory_safety"
                },
                "property": {
                  "const": "Memory safety; no data race between an interrupt and the main loop"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "rustc's borrow checker (with Send and Sync); the generated runtime never enables an interrupt"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 2
                },
                "key": {
                  "const": "no_heap"
                },
                "property": {
                  "const": "No heap: no_std, every buffer sized from the graph"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "the MCU generator (flowrs-core codegen::mcu), then rustc"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 3
                },
                "key": {
                  "const": "closed_node_set"
                },
                "property": {
                  "const": "A closed node set: nothing silently skipped"
                },
                "layer": {
                  "const": "structure"
                },
                "enforcer": {
                  "const": "the generators, which refuse by name any node they cannot lower"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 4
                },
                "key": {
                  "const": "pin_allocation"
                },
                "property": {
                  "const": "Pins and buses allocated without collision"
                },
                "layer": {
                  "const": "structure"
                },
                "enforcer": {
                  "const": "codegen::mcu::bind, against the flowrs-boards model and the chip's signal tables"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 5
                },
                "key": {
                  "const": "peripheral_ownership"
                },
                "property": {
                  "const": "Exclusive peripheral ownership; no use before configuration"
                },
                "layer": {
                  "const": "structure"
                },
                "enforcer": {
                  "const": "the generated Board: the peripherals taken once, the init order as a chain of typestates (codegen::board)"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 6
                },
                "key": {
                  "const": "static_schedule"
                },
                "property": {
                  "const": "A static schedule and bounded queues"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "codegen: one pass of straight-line calls in the graph's order; the partitioner's compile-time link slots"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 7
                },
                "key": {
                  "const": "loop_timing"
                },
                "property": {
                  "const": "Loops never faster than their edges allow"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "the partitioner's 10x rule, against tails measured by tools/perfbench"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 8
                },
                "key": {
                  "const": "units_and_clocks"
                },
                "property": {
                  "const": "Units and clocks agree on every wire that carries a number"
                },
                "layer": {
                  "const": "structure"
                },
                "enforcer": {
                  "const": "the wire type check (flowrs-core graph::quantity), with units carried along the wires (graph::units); a mismatch is refused until a conversion node sits between"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 9
                },
                "key": {
                  "const": "register_configuration"
                },
                "property": {
                  "const": "Register configuration matches the chip"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "flowrs-regdb's register check (rung 1) and processor-in-the-loop runs on the twin (flowrs-pil)"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 10
                },
                "key": {
                  "const": "tier_parity"
                },
                "property": {
                  "const": "The same behaviour in the browser and in the compiled program"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "one implementation at both tiers; tier-differential tests; scipy and MNE oracles"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 11
                },
                "key": {
                  "const": "instrument_safe_state"
                },
                "property": {
                  "const": "Instruments always returned to a safe state"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "codegen::handles::audit, which refuses any program that could skip an instrument handle's destructor"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 12
                },
                "key": {
                  "const": "mcu_error_path"
                },
                "property": {
                  "const": "Defined behaviour when a HAL call fails on the microcontroller"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "the generated runtime's failure path (codegen::board, flowrs_hal::rt)"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 13
                },
                "key": {
                  "const": "no_panic_proof"
                },
                "property": {
                  "const": "The generated program cannot panic or overflow"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "Kani"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 14
                },
                "key": {
                  "const": "human_approval"
                },
                "property": {
                  "const": "No hardware action without a person's approval"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "flowRS's approval envelope: approve-by-hash, server-held leases, signed policies, a hash-chained audit log"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 15
                },
                "key": {
                  "const": "reproducible_build"
                },
                "property": {
                  "const": "The export builds the same way anywhere, under open licences"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "the export's Cargo.lock, from flowRS's own; tools/appexport-verify.sh builds it --locked with no credentials; the licence audits"
                }
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/property"
            },
            {
              "properties": {
                "id": {
                  "const": 16
                },
                "key": {
                  "const": "hardware_confirmed"
                },
                "property": {
                  "const": "Behaviour confirmed on the physical device"
                },
                "layer": {
                  "const": "conformance"
                },
                "enforcer": {
                  "const": "a recorded run on a leased bench"
                }
              }
            }
          ]
        }
      ],
      "items": false
    },
    "board": {
      "$ref": "#/$defs/fidelity"
    },
    "sbom": {
      "$ref": "#/$defs/sbom"
    }
  },
  "if": {
    "properties": {
      "program": {
        "properties": {
          "kind": {
            "const": "firmware"
          }
        }
      }
    }
  },
  "then": {
    "required": [
      "board"
    ],
    "properties": {
      "program": {
        "required": [
          "board",
          "target",
          "triple"
        ]
      }
    }
  },
  "else": {
    "not": {
      "required": [
        "board"
      ]
    },
    "properties": {
      "program": {
        "not": {
          "anyOf": [
            {
              "required": [
                "board"
              ]
            },
            {
              "required": [
                "target"
              ]
            },
            {
              "required": [
                "triple"
              ]
            }
          ]
        }
      }
    }
  },
  "$defs": {
    "program": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "package",
        "flowrs_rev",
        "nodes",
        "node_types"
      ],
      "properties": {
        "kind": {
          "enum": [
            "host_app",
            "linux_app",
            "firmware",
            "library"
          ]
        },
        "package": {
          "type": "string",
          "minLength": 1
        },
        "flowrs_rev": {
          "type": "string",
          "minLength": 1
        },
        "nodes": {
          "type": "integer",
          "minimum": 0
        },
        "node_types": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "uniqueItems": true
        },
        "board": {
          "type": "string",
          "minLength": 1
        },
        "target": {
          "enum": [
            "embassy",
            "rtic"
          ]
        },
        "triple": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "property": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "key",
        "property",
        "layer",
        "enforcer",
        "status",
        "reason",
        "evidence"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "minimum": 1,
          "maximum": 16
        },
        "key": {
          "type": "string",
          "pattern": "^[a-z][a-z_]*$"
        },
        "property": {
          "type": "string",
          "minLength": 1
        },
        "layer": {
          "enum": [
            "structure",
            "conformance"
          ]
        },
        "enforcer": {
          "type": "string",
          "minLength": 1
        },
        "status": {
          "enum": [
            "live",
            "partial",
            "not_yet",
            "not_applicable"
          ]
        },
        "reason": {
          "type": "string",
          "minLength": 1
        },
        "evidence": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/evidence"
          }
        }
      },
      "if": {
        "properties": {
          "status": {
            "enum": [
              "live",
              "partial"
            ]
          }
        }
      },
      "then": {
        "properties": {
          "evidence": {
            "minItems": 1
          }
        }
      }
    },
    "evidence": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "name"
      ],
      "properties": {
        "kind": {
          "enum": [
            "test",
            "proof",
            "tool",
            "census",
            "check"
          ]
        },
        "name": {
          "type": "string",
          "minLength": 1
        },
        "at": {
          "type": "string",
          "minLength": 1
        },
        "found": {
          "type": "string",
          "minLength": 1
        }
      },
      "if": {
        "properties": {
          "kind": {
            "const": "check"
          }
        }
      },
      "then": {
        "required": [
          "found"
        ],
        "not": {
          "required": [
            "at"
          ]
        }
      },
      "else": {
        "required": [
          "at"
        ]
      }
    },
    "fidelity": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "board",
        "name",
        "part",
        "census",
        "level",
        "engine",
        "timing",
        "time_base",
        "model",
        "modelled",
        "not_modelled",
        "missing",
        "coverage",
        "measured"
      ],
      "properties": {
        "board": {
          "type": "string",
          "minLength": 1
        },
        "name": {
          "type": "string",
          "minLength": 1
        },
        "part": {
          "type": "string"
        },
        "census": {
          "type": "string"
        },
        "level": {
          "enum": [
            "None",
            "CoreOnly",
            "Partial",
            "Full"
          ]
        },
        "engine": {
          "type": "string"
        },
        "timing": {
          "type": "string"
        },
        "time_base": {
          "description": "How the twin keeps time, as labels: what one instruction costs (`rate`), what the timers, PWM and serial ports count (`peripheral_clock`), and what a frequency measured off a pin the CPU drives rests on (`software_timing`). Null when nothing runs the board.",
          "oneOf": [
            {
              "type": "null"
            },
            {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "rate",
                "peripheral_clock",
                "software_timing"
              ],
              "properties": {
                "rate": {
                  "enum": [
                    "cycle_table",
                    "emulator_cycles",
                    "instruction_is_cycle",
                    "fixed_ns_per_instruction",
                    "clock_per_byte"
                  ]
                },
                "ns_per_instruction": {
                  "type": "integer",
                  "minimum": 1
                },
                "peripheral_clock": {
                  "enum": [
                    "clock_tree",
                    "board_clock",
                    "none"
                  ]
                },
                "software_timing": {
                  "enum": [
                    "board_time",
                    "instruction_proportional"
                  ]
                }
              }
            }
          ]
        },
        "model": {
          "type": "string"
        },
        "modelled": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "not_modelled": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "missing": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "coverage": {
          "oneOf": [
            {
              "type": "null"
            },
            {
              "type": "array",
              "prefixItems": [
                {
                  "type": "integer",
                  "minimum": 0
                },
                {
                  "type": "integer",
                  "minimum": 0
                }
              ],
              "minItems": 2,
              "maxItems": 2,
              "items": false
            }
          ]
        },
        "measured": {
          "type": "boolean"
        }
      }
    },
    "sbom": {
      "type": "object",
      "description": "The project's software bill of materials, made from its Cargo.lock: every package the lock pins, as CycloneDX 1.6 JSON.",
      "additionalProperties": false,
      "required": [
        "file",
        "format",
        "spec_version",
        "components",
        "licensed",
        "sha256",
        "cargo_lock_sha256"
      ],
      "properties": {
        "file": {
          "const": "sbom.cdx.json"
        },
        "format": {
          "const": "CycloneDX"
        },
        "spec_version": {
          "const": "1.6"
        },
        "components": {
          "type": "integer",
          "minimum": 0
        },
        "licensed": {
          "type": "integer",
          "minimum": 0
        },
        "sha256": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "cargo_lock_sha256": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        }
      }
    }
  }
}
