Schema: backup-manifest

{
  "$defs": {
    "FileEntry": {
      "additionalProperties": false,
      "description": "One per-file backup entry. The path is a portable relative POSIX path, sha256 is a lowercase SHA-256 digest, bytes is the regular file size, and mode is POSIX permission bits.",
      "properties": {
        "bytes": {
          "description": "Byte count of the regular file.",
          "minimum": 0,
          "type": "integer"
        },
        "mode": {
          "description": "POSIX permission bits, for example 420 for 0644.",
          "maximum": 511,
          "minimum": 0,
          "type": "integer"
        },
        "path": {
          "description": "Portable relative POSIX path of the backed-up entry. Pattern enforcement for portable relative POSIX is performed at runtime.",
          "minLength": 1,
          "type": "string"
        },
        "sha256": {
          "description": "Lowercase SHA-256 hex digest of the regular file content.",
          "pattern": "^[a-f0-9]{64}$",
          "type": "string"
        }
      },
      "required": [
        "path",
        "sha256",
        "bytes",
        "mode"
      ],
      "type": "object"
    }
  },
  "$id": "https://australis.systems/schemas/htmx-ui-template-scaffold/backup-manifest.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "description": "Canonical Draft 2020-12 envelope for the backup manifest emitted by the package's destructive-path machinery. See package ARCHITECTURE.md 'Replace, Backup, Restore, Purge, And Recovery' and root docs/architecture/software-design-and-resilience.md \u00a7\u00a74.1 (determinism) and \u00a7\u00a75 (resilience). The manifest records the operation that produced the backup, the source root, the partial path during staging, the manifest digest, the per-file entries (with portable relative POSIX paths, lowercase SHA-256 digests, byte counts, POSIX octal mode strings), the directory list, the creation timestamp, and the final marker (always exactly 'COMPLETE' once verified). schema_version is major-version-pinned: only '1.0.0' documents are accepted.",
  "properties": {
    "created_at_utc": {
      "description": "RFC 3339 timestamp (UTC) when the manifest was written.",
      "format": "date-time",
      "type": "string"
    },
    "directories": {
      "description": "Portable relative POSIX directory paths present in the backup.",
      "items": {
        "minLength": 1,
        "type": "string"
      },
      "type": "array",
      "uniqueItems": true
    },
    "files": {
      "description": "Per-file backup entries, ordered. Each entry is a FileEntry.",
      "items": {
        "$ref": "#/$defs/FileEntry"
      },
      "type": "array"
    },
    "manifest_digest": {
      "description": "Lowercase SHA-256 hex digest of the canonical manifest body (64 hex characters).",
      "pattern": "^[a-f0-9]{64}$",
      "type": "string"
    },
    "operation": {
      "const": "backup_create"
    },
    "operation_id": {
      "description": "Unique identifier of the destructive operation that required this backup. The restore command uses this binding to refuse mismatched backups.",
      "minLength": 1,
      "type": "string"
    },
    "schema_version": {
      "description": "Major-version-locked envelope version. Documents with any value other than '1.0.0' MUST fail validation, which enforces the major-version-1 contract.",
      "enum": [
        "1.0.0"
      ],
      "type": "string"
    },
    "source_root": {
      "description": "Absolute path of the original source root that was backed up.",
      "minLength": 1,
      "type": "string"
    },
    "status": {
      "const": "COMPLETE"
    }
  },
  "required": [
    "schema_version",
    "operation",
    "operation_id",
    "source_root",
    "created_at_utc",
    "files",
    "directories",
    "status",
    "manifest_digest"
  ],
  "title": "Backup Manifest",
  "type": "object"
}