{
  "name": "Threat Strata",
  "version": "1.0.0",
  "description": "Agent contract for validating and submitting an encrypted threat model.",
  "schema": {
    "url": "/threat-model.schema.json",
    "format": "threat-model-studio",
    "version": "1.0.0",
    "sha256": "5a09d110110e41c03e5dfc4eb6c247b95f3681b2c1a89b36a9f38ca06de28118"
  },
  "script": {
    "url": "/submit.mjs",
    "sha256": "c6fd783d6188287a8302ab26d904a65af5b06f0d645cd83ebc9834212147be7f",
    "sizeBytes": 21786,
    "source": "https://github.com/synlace/threatstrata/blob/main/scripts/submit.mjs",
    "verification": [
      "sha256sum submit.mjs"
    ]
  },
  "submit": {
    "endpoint": "/api/models",
    "method": "POST",
    "contentType": "application/json",
    "maxBytes": 1048576
  },
  "crypto": {
    "alg": "AES-256-GCM",
    "aad": "threat-model-link-v1",
    "keyBytes": 32,
    "ivBytes": 12,
    "keyEncoding": "base64url",
    "link": "/m/{id}#{key}"
  },
  "instructions": [
    "Read this manifest. Fetch the schema at schema.url.",
    "Build a threat model with format threat-model-studio and schemaVersion 1.0.0.",
    "Omit node and boundary positions. The viewer computes a readable automatic layout.",
    "Choose a runner. Prefer Node 20 or newer because it needs no extra package.",
    "Use Python 3.9 or newer only when Node is unavailable. Python submission needs the cryptography package. Ask the user before installing cryptography.",
    "Download the chosen runner.url and compare its SHA-256 with runner.sha256.",
    "Download the schema. Keep it next to the runner or pass it with --schema.",
    "Node: run node submit.mjs validate model.json --schema threat-model.schema.json. Python: run python3 submit.py validate model.json --schema threat-model.schema.json.",
    "Fix every error and warning, then validate again.",
    "Node: run node submit.mjs submit model.json --manifest <this manifest URL>. Python: run python3 submit.py submit model.json --manifest <this manifest URL>.",
    "Return the url field to the user. The link contains the decryption key."
  ],
  "privacy": "The server stores account identity, an authentication verifier, and ciphertext. It never receives passwords, workspace keys, or plaintext projects, models, or model links. Encryption and decryption happen on the client. Anyone with a model link can read the model.",
  "preferredRunner": "node",
  "runners": [
    {
      "id": "node",
      "label": "Node.js",
      "runtime": "node",
      "minVersion": "20",
      "url": "/submit.mjs",
      "sha256": "c6fd783d6188287a8302ab26d904a65af5b06f0d645cd83ebc9834212147be7f",
      "sizeBytes": 21786,
      "command": "node submit.mjs",
      "source": "https://github.com/synlace/threatstrata/blob/main/scripts/submit.mjs",
      "verification": [
        "sha256sum submit.mjs"
      ]
    },
    {
      "id": "python",
      "label": "Python",
      "runtime": "python3",
      "minVersion": "3.9",
      "url": "/submit.py",
      "sha256": "8ac6cbabf943af669d6c1cc99b5eb92202416355f2cb2c8d7bd3b5f3d82fed7e",
      "sizeBytes": 21871,
      "command": "python3 submit.py",
      "source": "https://github.com/synlace/threatstrata/blob/main/scripts/submit.py",
      "dependencies": [
        "cryptography"
      ],
      "dependencyCheck": "python3 -c \"import cryptography\"",
      "dependencyInstall": "Ask the user before running: python3 -m pip install cryptography",
      "verification": [
        "sha256sum submit.py"
      ]
    }
  ]
}
