{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://geregeapp.mn/schemas/omas/1.0/gerege-miniapp.schema.json",
  "title": "Gerege mini app manifest (OMAS 1.0, Gerege implementation)",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "omas_version",
    "slug",
    "client_id",
    "version",
    "name",
    "category",
    "developer",
    "entry",
    "origins",
    "icons",
    "accent_color",
    "scopes",
    "bridge",
    "channels",
    "legal",
    "verification"
  ],
  "properties": {
    "omas_version": {
      "const": "1.0"
    },
    "slug": {
      "type": "string",
      "pattern": "^[a-z0-9-]{2,32}$"
    },
    "client_id": {
      "type": "string",
      "pattern": "^mapp_(test_)?[A-Za-z0-9]{8,40}$"
    },
    "version": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+([-+][0-9A-Za-z.-]+)?$"
    },
    "name": {
      "$ref": "#/$defs/i18n24"
    },
    "subtitle": {
      "$ref": "#/$defs/i18n40"
    },
    "category": {
      "enum": [
        "travel",
        "shopping",
        "finance",
        "games",
        "services",
        "food",
        "transport",
        "utilities"
      ]
    },
    "developer": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "name",
        "email"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 80
        },
        "email": {
          "type": "string",
          "format": "email"
        },
        "url": {
          "$ref": "#/$defs/https"
        }
      }
    },
    "entry": {
      "$ref": "#/$defs/https"
    },
    "origins": {
      "type": "array",
      "minItems": 1,
      "maxItems": 3,
      "uniqueItems": true,
      "items": {
        "type": "string",
        "pattern": "^https://[a-z0-9.-]+(:[0-9]{2,5})?$"
      }
    },
    "icons": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "src",
          "size"
        ],
        "properties": {
          "src": {
            "$ref": "#/$defs/https"
          },
          "size": {
            "enum": [
              128,
              256,
              512,
              1024
            ]
          }
        }
      },
      "contains": {
        "properties": {
          "size": {
            "const": 512
          }
        }
      }
    },
    "accent_color": {
      "type": "string",
      "pattern": "^#[0-9A-Fa-f]{6}$"
    },
    "scopes": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "enum": [
          "profile.basic",
          "profile.phone",
          "profile.email",
          "payments"
        ]
      },
      "contains": {
        "const": "profile.basic"
      }
    },
    "bridge": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "min_version",
        "methods"
      ],
      "properties": {
        "min_version": {
          "type": "integer",
          "minimum": 1
        },
        "methods": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "enum": [
              "ready",
              "getContext",
              "getLaunchCode",
              "requestPayment",
              "openExternal",
              "share",
              "copy",
              "haptic",
              "setTitle",
              "close",
              "openMiniApp"
            ]
          }
        }
      }
    },
    "external_urls": {
      "type": "array",
      "maxItems": 20,
      "uniqueItems": true,
      "items": {
        "$ref": "#/$defs/https"
      }
    },
    "requires_verified": {
      "type": "boolean"
    },
    "min_age": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 13,
      "maximum": 21
    },
    "channels": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "enum": [
          "ios",
          "android",
          "web"
        ]
      }
    },
    "webhook_url": {
      "$ref": "#/$defs/https"
    },
    "legal": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "privacy_url",
        "terms_url",
        "support_url"
      ],
      "properties": {
        "privacy_url": {
          "$ref": "#/$defs/https"
        },
        "terms_url": {
          "$ref": "#/$defs/https"
        },
        "support_url": {
          "$ref": "#/$defs/https"
        }
      }
    },
    "verification": {
      "type": "string",
      "pattern": "^omas-verify=[A-Za-z0-9_-]{16,128}$"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "scopes": {
            "contains": {
              "const": "payments"
            }
          }
        }
      },
      "then": {
        "required": [
          "webhook_url"
        ]
      }
    }
  ],
  "$defs": {
    "https": {
      "type": "string",
      "pattern": "^https://",
      "maxLength": 2048
    },
    "i18n24": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "mn"
      ],
      "properties": {
        "mn": {
          "type": "string",
          "minLength": 1,
          "maxLength": 24
        },
        "en": {
          "type": "string",
          "maxLength": 24
        }
      }
    },
    "i18n40": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "mn"
      ],
      "properties": {
        "mn": {
          "type": "string",
          "maxLength": 40
        },
        "en": {
          "type": "string",
          "maxLength": 40
        }
      }
    }
  },
  "$comment": "OMAS 1.0 manifest schema with the Gerege deviations, each of which widens: channels also accepts \"android\"; in non-production deployments http://localhost is accepted wherever https:// is (not expressed here). The authoritative check is modules/miniapp/manifest.go."
}
