scrollcase-consumer 0.3.0

Verify, prepare, and run caller-supplied local Scrollcase boxes.
Documentation
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://scrollcase.dev/schema/v2/release-manifest.schema.json",
  "title": "Box release manifest",
  "description": "The immutable description of one built box: what it is, which target it runs on, where its archive lives, and how it was produced. Published as the payload of a signed document and never edited after signing; a correction ships as a new version.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schemaVersion",
    "kind",
    "boxId",
    "modelId",
    "runtimeId",
    "version",
    "target",
    "compatibility",
    "archive",
    "pythonEntryPoint",
    "modelCacheSubdir",
    "selfTest",
    "provenance"
  ],
  "properties": {
    "schemaVersion": {
      "const": 2
    },
    "kind": {
      "$ref": "#/$defs/kind",
      "description": "Wire discriminator, \"<namespace>.release\". The namespace belongs to the publishing project \u2014 a project with boxes already in the field must keep emitting the one its clients recognise \u2014 and defaults to scrollcase.box for a new one."
    },
    "boxId": {
      "$ref": "#/$defs/identifier"
    },
    "modelId": {
      "$ref": "#/$defs/identifier"
    },
    "runtimeId": {
      "$ref": "#/$defs/identifier"
    },
    "version": {
      "type": "string",
      "minLength": 1
    },
    "target": {
      "$ref": "https://scrollcase.dev/schema/v2/target.schema.json"
    },
    "compatibility": {
      "type": "object",
      "additionalProperties": true,
      "description": "What the host must satisfy before this box may be installed. The builder copies these constraints through verbatim and never interprets them, so a project may add its own alongside the ones defined here. A consumer that cannot evaluate a constraint must refuse the box rather than assume it passes.",
      "properties": {
        "minHostAppVersion": {
          "type": "string",
          "minLength": 1,
          "description": "Lowest version of the installing application this box supports."
        },
        "maxHostAppVersionExclusive": {
          "type": "string",
          "minLength": 1
        },
        "minMacosVersion": {
          "type": "string",
          "minLength": 1
        },
        "minRamGb": {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Installed memory in decimal gigabytes (1 GB = 1,000,000,000 bytes)."
        },
        "minNvidiaDriverVersion": {
          "type": "string",
          "minLength": 1
        },
        "hostEnvironments": {
          "type": "array",
          "minItems": 1,
          "items": {
            "enum": [
              "native",
              "windows-wsl2"
            ]
          },
          "description": "Host environments this payload was validated on."
        }
      }
    },
    "archive": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "format",
        "url",
        "sha256",
        "sizeBytes"
      ],
      "properties": {
        "format": {
          "const": "zip"
        },
        "url": {
          "type": "string",
          "minLength": 1
        },
        "sha256": {
          "$ref": "#/$defs/sha256"
        },
        "sizeBytes": {
          "type": "integer",
          "exclusiveMinimum": 0
        }
      }
    },
    "installedSizeBytes": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "description": "Sum of extracted payload file sizes before activation metadata is written, so a consumer can check free space before downloading."
    },
    "payloadDigest": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "format",
        "sha256"
      ],
      "description": "SHA-256 of the canonical entry list carried at payload-digest.v1 inside the payload, letting a consumer re-identify an extracted installation once the archive is gone. Optional: boxes built before it exists carry no such commitment.",
      "properties": {
        "format": {
          "const": "sha256-path-list-v1"
        },
        "sha256": {
          "$ref": "#/$defs/sha256"
        }
      }
    },
    "pythonEntryPoint": {
      "type": "string",
      "minLength": 1,
      "description": "Interpreter path relative to the extracted box root, for example venv/bin/python. Fixed per target by the adapter."
    },
    "modelCacheSubdir": {
      "type": "string",
      "minLength": 1,
      "description": "Directory relative to the extracted box root holding model assets."
    },
    "environment": {
      "type": "object",
      "description": "Signed environment variables applied whenever Scrollcase runs the box interpreter. These values override both the inherited host environment and caller-supplied values.",
      "propertyNames": {
        "minLength": 1,
        "pattern": "^[^=\\u0000]+$"
      },
      "additionalProperties": {
        "type": "string",
        "pattern": "^[^\\u0000]*$"
      }
    },
    "selfTest": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "pythonImports",
        "timeoutSeconds"
      ],
      "description": "The import check a consumer can repeat after extraction with the box's own interpreter. The builder also ran the scroll's Python-code and file assertions, which are builder-only checks.",
      "properties": {
        "pythonImports": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "minLength": 1
          }
        },
        "timeoutSeconds": {
          "type": "integer",
          "exclusiveMinimum": 0
        }
      }
    },
    "execution": {
      "$ref": "https://scrollcase.dev/schema/v2/execution.schema.json"
    },
    "provenance": {
      "$ref": "#/$defs/provenance"
    },
    "weights": {
      "const": "on-demand",
      "description": "Present only when the assets were deliberately left out of the archive. Absent means the box is self-contained: everything it needs is inside it."
    },
    "assets": {
      "type": "array",
      "minItems": 1,
      "description": "Assets the consumer must fetch and place under the box root before first use. Present only with on-demand weights. The declared hash is what makes fetching them safe.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "url",
          "relativePath",
          "sizeBytes",
          "sha256"
        ],
        "properties": {
          "url": {
            "type": "string",
            "minLength": 1
          },
          "relativePath": {
            "type": "string",
            "minLength": 1
          },
          "sizeBytes": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "sha256": {
            "$ref": "#/$defs/sha256"
          }
        }
      }
    }
  },
  "$defs": {
    "identifier": {
      "type": "string",
      "pattern": "^[a-z0-9]+(?:[-.][a-z0-9]+)*$"
    },
    "kind": {
      "type": "string",
      "pattern": "^[a-z0-9]+(?:[.-][a-z0-9]+)*\\.release$"
    },
    "sha256": {
      "type": "string",
      "pattern": "^[a-f0-9]{64}$"
    },
    "provenance": {
      "type": "object",
      "additionalProperties": false,
      "description": "How this box was produced. Every field is recorded by the builder from observed state, never accepted from caller input, so the record cannot be dressed up after the fact.",
      "required": [
        "scrollId",
        "scrollVersion",
        "builderRevision",
        "sourceTreeDirty",
        "sourceRevision",
        "pythonVersion",
        "dependencyLockSha256",
        "builtAt",
        "pixiVersion"
      ],
      "properties": {
        "scrollId": {
          "type": "string",
          "minLength": 1
        },
        "scrollVersion": {
          "type": "string",
          "minLength": 1
        },
        "builderRevision": {
          "type": "string",
          "pattern": "^[a-f0-9]{40}$",
          "description": "Exact commit of the builder source that produced the box."
        },
        "sourceTreeDirty": {
          "type": "boolean",
          "description": "Whether the builder's working tree carried uncommitted changes. True means the build is not reproducible from the recorded revision alone."
        },
        "sourceRevision": {
          "type": "string",
          "minLength": 1,
          "description": "Upstream revision of the packaged model source, as declared by the scroll."
        },
        "pythonVersion": {
          "type": "string",
          "minLength": 1
        },
        "pixiVersion": {
          "type": "string",
          "minLength": 1
        },
        "dependencyLockSha256": {
          "$ref": "#/$defs/sha256",
          "description": "Hash of the pixi.lock the environment was solved from."
        },
        "builtAt": {
          "type": "string",
          "minLength": 1
        }
      }
    }
  },
  "dependentRequired": {
    "assets": [
      "weights"
    ],
    "weights": [
      "assets"
    ]
  }
}