{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://rctp.dev/schemas/ucp-profile.schema.json",
  "title": "UCP profile (RCTP subset)",
  "description": "The RCTP-relevant subset of a UCP profile served at /.well-known/ucp (binding 1, 3.1, 10). Open where UCP is open: UCP profiles and capability entries carry fields RCTP does not define, so the top level, ucp and capability entries allow other members. The RCTP configs (dev.rctp.operator, dev.rctp.listing, dev.rctp.deal, and RCTP scopes in dev.ucp.common.identity_linking) are closed. keys[] holds public keys only; each kid is its RFC 7638 thumbprint (B-1).",
  "type": "object",
  "properties": {
    "ucp": {
      "type": "object",
      "properties": {
        "version": {
          "type": "string",
          "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
          "description": "UCP release, such as 2026-08-25"
        },
        "capabilities": {
          "type": "object",
          "propertyNames": {
            "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
          },
          "additionalProperties": {
            "type": "array",
            "items": {
              "$ref": "#/$defs/CapabilityEntry"
            },
            "minItems": 1
          },
          "properties": {
            "dev.rctp.operator": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "properties": {
                  "version": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 32
                  },
                  "spec": {
                    "type": "string",
                    "format": "uri"
                  },
                  "schema": {
                    "type": "string",
                    "format": "uri"
                  },
                  "config": {
                    "$ref": "#/$defs/OperatorConfig"
                  }
                },
                "required": [
                  "version",
                  "config"
                ]
              }
            },
            "dev.rctp.listing": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "properties": {
                  "version": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 32
                  },
                  "spec": {
                    "type": "string",
                    "format": "uri"
                  },
                  "schema": {
                    "type": "string",
                    "format": "uri"
                  },
                  "config": {
                    "$ref": "#/$defs/ListingConfig"
                  }
                },
                "required": [
                  "version",
                  "config"
                ]
              }
            },
            "dev.rctp.deal": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "properties": {
                  "version": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 32
                  },
                  "spec": {
                    "type": "string",
                    "format": "uri"
                  },
                  "schema": {
                    "type": "string",
                    "format": "uri"
                  },
                  "config": {
                    "$ref": "#/$defs/DealConfig"
                  }
                },
                "required": [
                  "version"
                ]
              }
            },
            "dev.ucp.common.identity_linking": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "required": [
                  "version"
                ],
                "properties": {
                  "version": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 32
                  },
                  "config": {
                    "type": "object",
                    "properties": {
                      "scopes": {
                        "type": "object",
                        "description": "UCP scope policies; RCTP scopes carry default_tier and allowed_tiers (D-32)",
                        "patternProperties": {
                          "^dev\\.rctp\\.(listing|deal):[a-z][a-z0-9_]*$": {
                            "$ref": "#/$defs/ScopePolicy"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "required": [
        "version",
        "capabilities"
      ]
    },
    "keys": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/ProfileKey"
      },
      "minItems": 1
    }
  },
  "required": [
    "ucp",
    "keys"
  ],
  "$defs": {
    "CapabilityEntry": {
      "type": "object",
      "properties": {
        "version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 32
        },
        "spec": {
          "type": "string",
          "format": "uri"
        },
        "schema": {
          "type": "string",
          "format": "uri"
        },
        "config": {
          "type": "object"
        }
      },
      "required": [
        "version"
      ],
      "description": "One version of a capability. Open: UCP may add members."
    },
    "ProfileKey": {
      "type": "object",
      "properties": {
        "kty": {
          "const": "EC"
        },
        "crv": {
          "const": "P-256"
        },
        "x": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_-]{43}$"
        },
        "y": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_-]{43}$"
        },
        "kid": {
          "$ref": "common.schema.json#/$defs/Thumbprint"
        },
        "use": {
          "const": "sig"
        },
        "alg": {
          "const": "ES256"
        }
      },
      "additionalProperties": false,
      "required": [
        "kty",
        "crv",
        "x",
        "y",
        "kid"
      ],
      "description": "A public ES256 signing key. kid is its RFC 7638 thumbprint (B-1). Private members are not allowed."
    },
    "OperatorConfig": {
      "type": "object",
      "properties": {
        "legal_entity": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "jurisdiction": {
          "$ref": "common.schema.json#/$defs/CountryCode"
        },
        "incident_contact": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://[^\\s]+$",
          "description": "An https URL of the operator's incident desk; never a person (INV-9)"
        },
        "incident_sla_hours": {
          "type": "integer",
          "minimum": 1,
          "maximum": 720
        },
        "certifications": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "scheme": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "level": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "assessed_at": {
                "type": "string",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
                "description": "Calendar date, YYYY-MM-DD"
              },
              "expires_at": {
                "type": "string",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
                "description": "Calendar date, YYYY-MM-DD"
              }
            },
            "additionalProperties": false,
            "required": [
              "scheme",
              "assessed_at"
            ]
          }
        },
        "data_residency": {
          "type": "array",
          "items": {
            "$ref": "common.schema.json#/$defs/CountryCode"
          },
          "uniqueItems": true
        },
        "key_custody": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        }
      },
      "additionalProperties": false,
      "required": [
        "legal_entity",
        "jurisdiction",
        "incident_contact",
        "incident_sla_hours"
      ],
      "description": "config of dev.rctp.operator: who answers for an operator's agents (Draft 0.4 4.1(2))"
    },
    "ListingConfig": {
      "type": "object",
      "properties": {
        "term_sets": {
          "type": "array",
          "items": {
            "$ref": "common.schema.json#/$defs/TermSetId"
          },
          "minItems": 1,
          "uniqueItems": true
        }
      },
      "additionalProperties": false,
      "required": [
        "term_sets"
      ],
      "description": "config of dev.rctp.listing: the term sets the enforcement point enforces (Draft 0.4 6.2)"
    },
    "DealConfig": {
      "type": "object",
      "properties": {
        "webhook_url": {
          "type": "string",
          "format": "uri",
          "pattern": "^https://[^\\s]+$",
          "description": "Operators: where the gateway sends webhooks (binding 9)"
        },
        "offer_expiry": {
          "type": "object",
          "properties": {
            "default_seconds": {
              "type": "integer",
              "minimum": 1
            },
            "max_seconds": {
              "type": "integer",
              "minimum": 1
            }
          },
          "additionalProperties": false,
          "required": [
            "default_seconds",
            "max_seconds"
          ]
        },
        "offer_budget": {
          "type": "object",
          "properties": {
            "per_agent": {
              "type": "integer",
              "minimum": 1
            },
            "per_operator": {
              "type": "integer",
              "minimum": 1
            },
            "window_hours": {
              "type": "number",
              "exclusiveMinimum": 0
            }
          },
          "additionalProperties": false,
          "required": [
            "per_agent",
            "per_operator",
            "window_hours"
          ]
        }
      },
      "additionalProperties": false,
      "description": "config of dev.rctp.deal: offer expiry and budget for an enforcement point (Draft 0.4 7.3, 8.5); webhook_url for an operator"
    },
    "ScopePolicy": {
      "type": "object",
      "properties": {
        "default_tier": {
          "$ref": "common.schema.json#/$defs/GrantTier"
        },
        "allowed_tiers": {
          "type": "array",
          "items": {
            "$ref": "common.schema.json#/$defs/GrantTier"
          },
          "minItems": 1,
          "uniqueItems": true
        },
        "description": {
          "type": "string",
          "maxLength": 500
        }
      },
      "additionalProperties": false,
      "required": [
        "default_tier",
        "allowed_tiers"
      ],
      "description": "Policy of one RCTP scope (Draft 0.4 5.2(2), 8.4)"
    }
  }
}
