{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://prometheusroot.github.io/omarchy-plugin-check/spec/v1/store.schema.json",
  "title": "Store snapshot v1 (store.json)",
  "description": "One compact, signed file the CLI and the store app load at start (ADR-0013, ADR-0014). Signed detached: store.json.sig = `ssh-keygen -Y sign -n omarchy-plugin-check-snapshot`. Clients reject a bad signature, an expired snapshot and a version lower than the last one they accepted.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schemaVersion",
    "kind",
    "version",
    "generatedAt",
    "expires",
    "dev",
    "catalog",
    "imageBase",
    "apiBase",
    "providers",
    "ranking",
    "shelves",
    "categories",
    "plugins"
  ],
  "properties": {
    "schemaVersion": {
      "const": 1
    },
    "kind": {
      "const": "omarchy-plugin-check/store"
    },
    "version": {
      "type": "integer",
      "minimum": 1,
      "description": "Strictly increasing (unix seconds of generation)."
    },
    "generatedAt": {
      "$ref": "common.schema.json#/$defs/dateTime"
    },
    "expires": {
      "$ref": "common.schema.json#/$defs/dateTime"
    },
    "dev": {
      "type": "boolean",
      "description": "true = signed with a DEV key and/or contains unsigned-dev provider rows. Never true for a published snapshot."
    },
    "catalog": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "generatedAt",
        "plugins",
        "retired",
        "builtin"
      ],
      "properties": {
        "generatedAt": {
          "oneOf": [
            {
              "$ref": "common.schema.json#/$defs/dateTime"
            },
            {
              "type": "null"
            }
          ]
        },
        "plugins": {
          "type": "integer"
        },
        "retired": {
          "type": "integer"
        },
        "builtin": {
          "type": "integer"
        }
      }
    },
    "imageBase": {
      "type": "string",
      "description": "Prefix for img.thumb / img.full values that are not absolute https URLs."
    },
    "apiBase": {
      "type": "string",
      "description": "Base for `report` paths (api/v1/)."
    },
    "providers": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "tier",
          "verification",
          "rows"
        ],
        "properties": {
          "id": {
            "$ref": "common.schema.json#/$defs/providerId"
          },
          "name": {
            "type": "string"
          },
          "tier": {
            "$ref": "common.schema.json#/$defs/tier"
          },
          "verification": {
            "$ref": "common.schema.json#/$defs/verification"
          },
          "rows": {
            "type": "integer",
            "minimum": 0
          }
        }
      }
    },
    "ranking": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "version",
        "factors",
        "gates",
        "statsGeneratedAt"
      ],
      "properties": {
        "version": {
          "type": "string"
        },
        "factors": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "label",
              "weight"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "label": {
                "type": "string"
              },
              "weight": {
                "type": "number",
                "minimum": 0
              }
            }
          }
        },
        "gates": {
          "type": "object",
          "additionalProperties": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "statsGeneratedAt": {
          "oneOf": [
            {
              "$ref": "common.schema.json#/$defs/dateTime"
            },
            {
              "type": "null"
            }
          ]
        }
      }
    },
    "shelves": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "top",
        "trending",
        "new",
        "updated",
        "safePicks",
        "byCategory"
      ],
      "properties": {
        "top": {
          "$ref": "#/$defs/ids"
        },
        "trending": {
          "$ref": "#/$defs/ids"
        },
        "new": {
          "$ref": "#/$defs/ids"
        },
        "updated": {
          "$ref": "#/$defs/ids"
        },
        "safePicks": {
          "$ref": "#/$defs/ids"
        },
        "byCategory": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/$defs/ids"
          }
        }
      }
    },
    "categories": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "count"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          }
        }
      }
    },
    "plugins": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/plugin"
      }
    }
  },
  "$defs": {
    "ids": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "$ref": "common.schema.json#/$defs/pluginId"
      }
    },
    "plugin": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "name",
        "verdict"
      ],
      "properties": {
        "id": {
          "$ref": "common.schema.json#/$defs/pluginId"
        },
        "name": {
          "type": "string",
          "maxLength": 200
        },
        "author": {
          "type": "string",
          "maxLength": 200
        },
        "desc": {
          "type": "string",
          "maxLength": 1000
        },
        "cat": {
          "type": "string",
          "maxLength": 64
        },
        "kind": {
          "type": "string",
          "maxLength": 64
        },
        "tags": {
          "type": "array",
          "maxItems": 20,
          "items": {
            "type": "string",
            "maxLength": 64
          }
        },
        "repo": {
          "type": "string"
        },
        "formerRepos": {
          "type": "array",
          "maxItems": 20,
          "uniqueItems": true,
          "items": {
            "$ref": "common.schema.json#/$defs/repoUrl"
          },
          "description": "Previous repository URLs of this listing (marketplace registry repositoryMigrations + repositoryIdentity.previousRepositories, lower-cased). A checkout whose origin is one of them is this plugin, moved; a name that is another listing's current repository is never listed here (ADR-0034)."
        },
        "path": {
          "type": "string",
          "maxLength": 512,
          "description": "Plugin directory in the repo when not the root."
        },
        "install": {
          "type": "string",
          "maxLength": 300,
          "description": "Only when not the default command; \"\" = not installable."
        },
        "license": {
          "type": "string",
          "maxLength": 64
        },
        "version": {
          "type": "string",
          "maxLength": 64
        },
        "state": {
          "enum": [
            "retired",
            "builtin"
          ],
          "description": "Absent = listed."
        },
        "verif": {
          "type": "string",
          "maxLength": 32,
          "description": "Marketplace verificationStatus, verbatim."
        },
        "listed": {
          "type": "string",
          "description": "Marketplace listedAt, to the second."
        },
        "updated": {
          "type": "string"
        },
        "img": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "thumb": {
              "type": "string",
              "description": "imageBase-relative name, or an absolute https URL"
            },
            "full": {
              "type": "string"
            },
            "w": {
              "type": "integer"
            },
            "h": {
              "type": "integer"
            }
          }
        },
        "gallery": {
          "type": "array",
          "maxItems": 8,
          "items": {
            "type": "string",
            "pattern": "^https://"
          }
        },
        "gh": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "stars",
            "vel30",
            "lastCommit",
            "c90",
            "contrib",
            "bus",
            "rel180",
            "lastRelease",
            "issues",
            "respH",
            "archived",
            "branch"
          ],
          "properties": {
            "stars": {
              "type": "integer",
              "minimum": 0
            },
            "vel30": {
              "type": "integer",
              "minimum": 0,
              "description": "Stars gained in the last 30 days (estimated above 100, see docs/RANKING.md)."
            },
            "lastCommit": {
              "type": [
                "string",
                "null"
              ]
            },
            "c90": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "contrib": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "description": "Distinct authors in the last 100 default-branch commits."
            },
            "bus": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "description": "Fewest authors covering half of those commits."
            },
            "rel180": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "lastRelease": {
              "type": [
                "string",
                "null"
              ]
            },
            "issues": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "respH": {
              "type": [
                "number",
                "null"
              ],
              "minimum": 0,
              "description": "Median hours to first non-author comment, last 20 issues."
            },
            "archived": {
              "type": "boolean"
            },
            "branch": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        },
        "mkt": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "views",
            "copies",
            "hearts"
          ],
          "properties": {
            "views": {
              "type": "integer"
            },
            "copies": {
              "type": "integer"
            },
            "hearts": {
              "type": "integer"
            }
          }
        },
        "rank": {
          "type": "integer",
          "minimum": 1
        },
        "score": {
          "type": "number",
          "minimum": 0
        },
        "fac": {
          "type": "array",
          "items": {
            "type": "number"
          },
          "description": "Weighted factor contributions, same order as ranking.factors."
        },
        "verdict": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "combined",
            "basis",
            "providers"
          ],
          "properties": {
            "combined": {
              "$ref": "common.schema.json#/$defs/verdict"
            },
            "basis": {
              "enum": [
                "trusted",
                "untrusted",
                "none"
              ]
            },
            "contested": {
              "const": true,
              "description": "Present only when contested."
            },
            "commit": {
              "$ref": "common.schema.json#/$defs/sha1",
              "description": "Present only for a trusted basis whose rows all reviewed this commit (the CLI compares it with the installed HEAD)."
            },
            "tree": {
              "$ref": "common.schema.json#/$defs/sha1",
              "description": "The git tree of `commit`, from the trusted statements' subject gitTree; present only with `commit` and when those rows agree. Clients accept a checkout whose HEAD^{tree} equals it as the reviewed content (ADR-0034)."
            },
            "providers": {
              "type": "object",
              "additionalProperties": {
                "$ref": "common.schema.json#/$defs/verdict"
              }
            },
            "criteria": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "checked",
                "failed"
              ],
              "description": "The deciding trusted row's criteria (absent without a trusted row).",
              "properties": {
                "checked": {
                  "type": "array",
                  "uniqueItems": true,
                  "items": {
                    "$ref": "common.schema.json#/$defs/criterion"
                  }
                },
                "failed": {
                  "type": "array",
                  "uniqueItems": true,
                  "items": {
                    "$ref": "common.schema.json#/$defs/criterion"
                  }
                }
              }
            },
            "risk": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100,
              "description": "The deciding trusted row's risk score from its optional report extension (0 = no risk signal)."
            }
          }
        },
        "report": {
          "const": true,
          "description": "An aggregated view exists at apiBase + 'plugins/<id>.json' (every plugin of a snapshot has one, ADR-0032)."
        },
        "ini": {
          "type": "string",
          "maxLength": 4,
          "description": "Marketplace initials for the tile (else derived from the name)."
        },
        "accent": {
          "type": "string",
          "maxLength": 32,
          "description": "Marketplace accent name (cyan, amber, ...); else derived from the id."
        }
      },
      "description": "Compact row: an absent key means null / empty list; `state` absent = listed; `install` absent = `omarchy plugin add <repo>.git --enable`, \"\" = not installable via omarchy plugin add."
    }
  }
}
