{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:cede:schema:package:v0",
  "title": "CEDE submission pack, v0",
  "description": "The artifact of the Package verb (SPEC.md section 3.7): a submission pack assembled from analytical runs that already happened, as draft exhibits a person can take into their own placement process and execute elsewhere. SPEC.md section 3.7 and section 4 (P4) are normative for the semantics; this file encodes them as constraints, and where the two disagree SPEC.md wins and this file has a bug. Three constraints carry the perimeter directly: the pack's status is the constant 'draft', the pack and EVERY document inside it carry an identical watermark constant naming the document a draft produced by analytics software, and the disclosure sentence is a constant. No member of this schema records a signature, an acceptance, a counterparty's assent or an execution of any kind, and no revision of this file may add one without a spec amendment: the pack is a set of documents about risk, never a step in a transaction.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema_version",
    "id",
    "created_at",
    "verb",
    "run_id",
    "status",
    "watermark",
    "subject",
    "assembled_from",
    "documents",
    "limitations",
    "disclosure",
    "links"
  ],
  "properties": {
    "schema_version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
      "description": "Version of this schema the payload conforms to."
    },
    "id": {
      "type": "string",
      "minLength": 1,
      "description": "Server-assigned identity of this pack, and the address it is served at."
    },
    "created_at": {
      "$ref": "#/$defs/timestamp"
    },
    "verb": {
      "const": "package",
      "description": "Which of the seven verbs (SPEC.md section 3) produced this."
    },
    "run_id": {
      "type": "string",
      "minLength": 1,
      "description": "Identity of this assembly run. Content-addressed in v0: the same object packaged twice from the same runs yields the same id, because assembling a pack reads recorded runs and computes nothing."
    },
    "status": {
      "const": "draft",
      "description": "SPEC.md section 4 P4 in the schema itself: a pack is a draft and has no other state. A constant, because a status field that could hold anything else is the first half of an acceptance mechanism."
    },
    "watermark": {
      "$ref": "#/$defs/watermark"
    },
    "subject": {
      "$ref": "#/$defs/subject"
    },
    "assembled_from": {
      "type": "array",
      "minItems": 1,
      "description": "The runs this pack was assembled from, exactly as the object's own provenance.model_runs records them. Package computes nothing: every exhibit below is a document some earlier run produced, and this array is how a reader checks that against the object it came from.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "run_id",
          "verb",
          "model",
          "model_version"
        ],
        "description": "One recorded run. Labelled with the model and version that produced it (SPEC.md section 4, P9), like every other result.",
        "properties": {
          "run_id": {
            "type": "string",
            "minLength": 1
          },
          "verb": {
            "type": "string",
            "minLength": 1
          },
          "model": {
            "type": "string",
            "minLength": 1
          },
          "model_version": {
            "type": "string",
            "minLength": 1
          },
          "completed_at": {
            "$ref": "#/$defs/timestamp"
          }
        }
      }
    },
    "documents": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "exposure_summary",
        "pricing_exhibit",
        "draft_slip"
      ],
      "description": "The documents of the pack, keyed by what they are rather than ordered in a list, so a consumer addresses an exhibit by name and a pack with no backtest behind it is a missing key rather than a silently shorter array. A pricing exhibit is mandatory: SPEC.md section 3.7 takes an object with pricing in provenance as its input, and a pack without one would be a submission about nothing. The draft slip is mandatory for the same reason read the other way: SPEC.md section 3.7 names it as part of what Package produces, so a pack without one is an incomplete pack rather than a pack of a different kind, and the API refuses an object that cannot fill it rather than assembling a slip with blank sections.",
      "properties": {
        "exposure_summary": {
          "$ref": "#/$defs/exposure_summary"
        },
        "pricing_exhibit": {
          "$ref": "#/$defs/pricing_exhibit"
        },
        "backtest_exhibit": {
          "$ref": "#/$defs/backtest_exhibit"
        },
        "draft_slip": {
          "$ref": "#/$defs/draft_slip"
        }
      }
    },
    "limitations": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "string",
        "minLength": 1
      },
      "description": "What this pack is not, as members of the document rather than prose around it. Required and non-empty: a set of exhibits read without its limitations is a set of numbers nobody can weigh."
    },
    "disclosure": {
      "const": "This submission pack is a set of draft exhibits assembled by analytics software from runs that already happened. It is execution ready in exactly one sense: a person can take these documents into their own placement process and execute them elsewhere. Cede is not a party to anything in it, is not a risk carrier or an intermediary, records no assent to it from anyone, and holds no signature, acceptance or execution mechanism of any kind.",
      "description": "SPEC.md section 3.7 and section 4 (P4, P6), pinned as a constant for the same reason the technical price disclosure is: free text can be reworded into an implication of transactability one careless edit at a time, and a constant cannot."
    },
    "links": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "self",
        "object"
      ],
      "description": "Where this pack is served, and the object it was assembled from.",
      "properties": {
        "self": {
          "type": "string",
          "minLength": 1
        },
        "object": {
          "type": "string",
          "minLength": 1
        }
      }
    }
  },
  "$defs": {
    "timestamp": {
      "type": "string",
      "format": "date-time",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$"
    },
    "watermark": {
      "const": "DRAFT — produced by analytics software. This document carries no acceptance, no signature and no capacity, and nothing in Cede executes it.",
      "description": "SPEC.md section 4 P4: every document a pack contains is watermarked as a draft produced by analytics software. A constant rather than free text, and carried on the pack AND on each document inside it, because a document lifted out of the pack and read on its own must still say what it is. tests/contract/test_package_contract.py asserts it on the artifact and on every exhibit."
    },
    "exposure_amount": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "amount"
      ],
      "description": "An insured value exactly as the object carries it (risk-object.v0 exposure_amount): currency-tagged when the source file stated one anywhere, untagged when it did not. Untagged is admissible here for the same reason it is admissible there — adr/ADR-0029 — and a pack that dropped an untagged value would be silently reporting less exposure than the object holds.",
      "properties": {
        "amount": {
          "type": "number",
          "minimum": 0
        },
        "currency": {
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        }
      }
    },
    "subject": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "object_id",
        "schema_version",
        "status"
      ],
      "description": "What was packaged: the canonical risk object, by the identity it is served at.",
      "properties": {
        "object_id": {
          "type": "string",
          "minLength": 1
        },
        "schema_version": {
          "type": "string",
          "minLength": 1,
          "description": "schema_version of the risk object that was packaged."
        },
        "status": {
          "type": "string",
          "minLength": 1,
          "description": "The object's own status at the moment of assembly — a state of the object, never a state of a transaction (SPEC.md section 2)."
        },
        "peril": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "exposure_summary": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "title",
        "watermark",
        "exposure"
      ],
      "description": "The first document of the pack: what is at risk, summarised from the object's own exposure block. A summary and never a re-derivation — the numbers here are the object's numbers.",
      "properties": {
        "kind": {
          "const": "exposure_summary"
        },
        "title": {
          "type": "string",
          "minLength": 1
        },
        "watermark": {
          "$ref": "#/$defs/watermark"
        },
        "exposure": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "location_count",
            "source_fidelity"
          ],
          "properties": {
            "kind": {
              "type": "string",
              "minLength": 1,
              "description": "The exposure kind the object carries: a location schedule, an SOV, an index, and so on."
            },
            "currency": {
              "type": "string",
              "pattern": "^[A-Z]{3}$"
            },
            "location_count": {
              "type": "integer",
              "minimum": 0,
              "description": "How many locations the object carries. Zero is a real answer for an index exposure and is stated rather than omitted."
            },
            "values": {
              "type": "object",
              "additionalProperties": false,
              "description": "Insured values by coverage part, as the object carries them.",
              "properties": {
                "building": {
                  "$ref": "#/$defs/exposure_amount"
                },
                "contents": {
                  "$ref": "#/$defs/exposure_amount"
                },
                "business_interruption": {
                  "$ref": "#/$defs/exposure_amount"
                },
                "other": {
                  "$ref": "#/$defs/exposure_amount"
                }
              }
            },
            "source_fidelity": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "unmapped_columns",
                "guessed_units",
                "ambiguous_rows",
                "inferred_mappings"
              ],
              "description": "Ingest's honesty channel (SPEC.md section 3.1), carried into the pack as counts. All four are mandatory so that 'nothing was guessed' is stated as a zero rather than inferred from a missing key: a submission pack that quietly dropped what could not be normalised would be the one place that record matters most.",
              "properties": {
                "unmapped_columns": {
                  "type": "integer",
                  "minimum": 0
                },
                "guessed_units": {
                  "type": "integer",
                  "minimum": 0
                },
                "ambiguous_rows": {
                  "type": "integer",
                  "minimum": 0
                },
                "inferred_mappings": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            }
          }
        },
        "peril": {
          "type": "object",
          "description": "The object's peril block, as it stands."
        },
        "period": {
          "type": "object",
          "description": "The object's cover period, as it stands."
        },
        "financial_structure": {
          "type": "object",
          "description": "The object's financial structure, as it stands — limit, attachment, and the technical premium a price run wrote onto it, with its pointer to the assumption set."
        }
      }
    },
    "pricing_exhibit": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "title",
        "watermark",
        "price"
      ],
      "description": "The pricing document of the pack: the price response of the run the object's provenance names, embedded whole rather than summarised. Embedded because SPEC.md section 3.3 makes a technical price meaningless apart from the assumption set travelling with it, and a pack that carried the premium without the assumptions would be the exact footnote-shaped failure that rule exists to stop.",
      "properties": {
        "kind": {
          "const": "pricing_exhibit"
        },
        "title": {
          "type": "string",
          "minLength": 1
        },
        "watermark": {
          "$ref": "#/$defs/watermark"
        },
        "price": {
          "type": "object",
          "description": "A price response document, carrying its complete assumption set. Validated in full against urn:cede:schema:price-response:v0 by the contract oracle; restated loosely here so that the two schemas cannot drift into disagreeing about the same bytes."
        }
      }
    },
    "draft_slip": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "title",
        "watermark",
        "slip"
      ],
      "description": "The draft slip SPEC.md section 3.7 names: the terms of the object laid out the way a person reads them, on one document. Populated from the risk object and from nothing else — Package computes nothing here either, so every line is a restatement of what the object records, and the object remains the record where the two disagree. Watermarked like every other document in the pack (section 4, P4), and carrying its own statements of what it is not, because a slip is the document in a pack that most looks like paper and is the one most likely to be read alone.",
      "properties": {
        "kind": {
          "const": "draft_slip"
        },
        "title": {
          "type": "string",
          "minLength": 1
        },
        "watermark": {
          "$ref": "#/$defs/watermark"
        },
        "slip": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "parties",
            "period",
            "jurisdiction",
            "financial_structure",
            "trigger",
            "technical_premium",
            "statements"
          ],
          "description": "The slip's own sections, all mandatory. Mandatory rather than optional because the alternative is a slip that renders a blank governing law or an empty party list and reads as a document somebody forgot to finish: an object missing any of these is refused at POST /objects/{id}/package with the missing blocks named (error code unpackageable_object), which is a refusal a caller can act on. No member here records a signature, an acceptance, a counterparty's assent or an execution, and none may ever be added: the slip is a draft about risk, never a step in a transaction.",
          "properties": {
            "parties": {
              "type": "array",
              "minItems": 1,
              "description": "The parties as the object's counterparties array records them, reproduced rather than resolved. SPEC.md section 2: descriptive only — recording a party on an object creates no obligation and no relationship through Cede, and Cede verifies no identifier as KYC.",
              "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "role",
                  "name"
                ],
                "properties": {
                  "role": {
                    "type": "string",
                    "minLength": 1
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1
                  },
                  "identifiers": {
                    "type": "object",
                    "description": "LEI or similar where the object carries one. Never verified by Cede."
                  }
                }
              }
            },
            "period": {
              "type": "object",
              "description": "The cover period being modelled, as the object records it: inception, expiry and the zone day boundaries are evaluated in."
            },
            "jurisdiction": {
              "type": "object",
              "description": "Governing law and territorial scope, as the object records them. Informational: Cede gives no legal advice and executes nothing (SPEC.md section 2)."
            },
            "financial_structure": {
              "type": "object",
              "description": "Limit, attachment, layers where Structure produced any, and reinstatements where the object carries them. The premium is deliberately NOT here: it is restated below under technical_premium with its disclosure, because a premium sitting next to the limit in a terms block reads like a term somebody set rather than the output of a run."
            },
            "trigger": {
              "type": "object",
              "description": "The parametric index definition or the wording reference, whichever branch the object populates (SPEC.md section 2, trigger or wording). Reproduced whole: an index restated without its measurement, window, thresholds and payout function is not a trigger anybody can read."
            },
            "technical_premium": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "basis",
                "amount",
                "currency",
                "assumptions_ref",
                "disclosure"
              ],
              "description": "The technical premium the price run wrote onto the object, restated on the slip as analytical output. basis is the constant 'technical' and assumptions_ref is mandatory for exactly the reason SPEC.md section 4 P3 gives: a premium on a slip, without the label and without the pointer to the assumption set that produced it, is the one number in this pack a reader is most likely to mistake for a price somebody stands ready to transact at.",
              "properties": {
                "basis": {
                  "const": "technical"
                },
                "amount": {
                  "type": "number",
                  "minimum": 0
                },
                "currency": {
                  "type": "string",
                  "pattern": "^[A-Z]{3}$"
                },
                "assumptions_ref": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Pointer to the complete assumption set that produced this amount — the pricing exhibit in this same pack carries it in full."
                },
                "price_run_ref": {
                  "type": "string",
                  "minLength": 1,
                  "description": "The price run this pack was assembled from, named on the slip so a reader matches the number to the exhibit without doing it by eye."
                },
                "disclosure": {
                  "const": "Technical premium: analytical output of the price run named here, under the assumption set that run recorded and no other. It is an actuarial estimate, not a price at which any party stands ready to transact, and nobody has agreed to it.",
                  "description": "Pinned as a constant for the same reason the pack's own disclosure is: free text can be reworded into an implication of transactability one careless edit at a time, and a constant cannot."
                }
              }
            },
            "statements": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "string",
                "minLength": 1
              },
              "description": "What this slip is, and is not, carried inside the document rather than in prose around it — an exhibit is the thing a person lifts out and sends on alone, and copy that lived only on the docs page would not travel with it."
            }
          }
        }
      }
    },
    "backtest_exhibit": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "title",
        "watermark",
        "backtest"
      ],
      "description": "The backtest document of the pack, present exactly when a backtest run of a structure cut from this object is recorded in its provenance. Absent otherwise: a pack never runs a verb to fill a gap, because a number produced at assembly time is a number nobody asked for and nobody reviewed.",
      "properties": {
        "kind": {
          "const": "backtest_exhibit"
        },
        "title": {
          "type": "string",
          "minLength": 1
        },
        "watermark": {
          "$ref": "#/$defs/watermark"
        },
        "backtest": {
          "type": "object",
          "description": "A backtest artifact, carrying its window, data coverage and the disclosure that history is not a projection. Validated in full against urn:cede:schema:backtest-response:v0 by the contract oracle; restated loosely here for the same reason price is."
        }
      }
    }
  }
}
