{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://railiance.dev/schemas/reef.schema.json", "title": "Railiance reef declaration", "description": "Normative shape for declarations/reef.yaml in every reef-* repo. Authored by railiance-master under RMASTER-WP-0021-T04 from the live reef-railiance declaration and docs/reef-substrate-model.md. bound_rapps is a derived projection of rapp.bound_reefs, not a hand-maintained registry.", "type": "object", "additionalProperties": false, "required": [ "kind", "reef_id", "repo", "ownership_repo", "substrate_kind", "lifecycle_state", "criticality", "current_members" ], "properties": { "kind": { "const": "substrate-reef", "description": "Fixed discriminator. The live reef already uses this value." }, "reef_id": { "$ref": "#/$defs/reefSlug", "description": "Canonical identifier for the reef. Must equal the repo slug." }, "repo": { "$ref": "#/$defs/repoSlug", "description": "The reef-* repo holding this declaration." }, "ownership_repo": { "$ref": "#/$defs/repoSlug", "description": "The ownership-axis repo accountable for this substrate boundary. The live reef names railiance-infra." }, "substrate_kind": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "minLength": 3, "description": "What kind of substrate this reef is. Known values include server-group (reef-railiance) and object-storage (reef-storage). Kept as a slug rather than a closed enum. A provider-delegated kind (object-storage) does not host a rail: the provider operates the capability. See docs/reef-substrate-model.md." }, "lifecycle_state": { "enum": ["planned", "active", "retired"], "description": "Lifecycle of the reef as a substrate boundary. Distinct from rail readiness_state and from the per-binding admission states in docs/reef-production-readiness-contract.md (declared/installed/verified/production-approved/deprecated)." }, "criticality": { "enum": ["low", "medium", "high", "critical"], "description": "Operational criticality of the substrate. Same vocabulary as rapp.yaml. The live reef is high." }, "primary_rail": { "$ref": "#/$defs/railSlug", "description": "The default rail on this reef, when the reef hosts rails. Omit on a provider-delegated substrate (object-storage): there is no execution contract to host. If present, must also appear in hosted_rails." }, "hosted_rails": { "type": "array", "minItems": 0, "uniqueItems": true, "items": { "$ref": "#/$defs/railSlug" }, "description": "Rails this reef hosts or is prepared to host. Empty or omitted when the reef does not host a rail. Topology, not readiness. See ADR-0006." }, "bound_rapps": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/rappSlug" }, "description": "DERIVED. Projection of every rapp declaration whose bound_reefs lists this reef. Optional so a reef may omit the field and let the validator compute it. If present, the validator requires an exact match against that projection. reef-railiance currently hand-lists rapp-qonto only; that list is already stale (rapp-openbao and rapp-postgres are live on the same reef). Migration: either delete the field, or replace it with the derived set once those rapps name this reef." }, "current_members": { "type": "array", "minItems": 0, "uniqueItems": true, "items": { "type": "string", "minLength": 1 }, "description": "Named machines, buckets, or other units that currently compose this reef. Empty is allowed while a planned provider-delegated reef has no purchased members yet. Live compute example: Railiance01." }, "compatibility_notes": { "$ref": "#/$defs/notes", "description": "Human-readable caveats. Never load-bearing." }, "source_documents": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/sourceDocument" } }, "exposure": { "type": "object", "additionalProperties": false, "required": ["posture"], "description": "Host-port and public-DNS surface this reef publishes. Optional; omitted means private (ADR-0008). public is a substrate grant, not reef lifecycle_state. Provider-delegated reefs must not set public.", "properties": { "posture": { "enum": ["private", "operator", "public"], "description": "Default if exposure is omitted: private." }, "grants": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/exposureGrant" }, "description": "Substrate grants. Required by schema when posture is public." }, "tunnel": { "$ref": "#/$defs/exposureTunnel" } } } }, "allOf": [ { "description": "public reef exposure requires at least one substrate grant.", "if": { "required": ["exposure"], "properties": { "exposure": { "required": ["posture"], "properties": { "posture": { "const": "public" } } } } }, "then": { "properties": { "exposure": { "required": ["grants"] } } } } ], "$defs": { "repoSlug": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "minLength": 2 }, "railSlug": { "type": "string", "pattern": "^rail-[a-z0-9]+(-[a-z0-9]+)*$" }, "rappSlug": { "type": "string", "pattern": "^rapp-[a-z0-9]+(-[a-z0-9]+)*$" }, "reefSlug": { "type": "string", "pattern": "^reef-[a-z0-9]+(-[a-z0-9]+)*$" }, "notes": { "type": "array", "items": { "type": "string", "minLength": 1 }, "description": "Human-readable caveats. Never load-bearing: nothing may depend on parsing a note." }, "sourceDocument": { "type": "object", "additionalProperties": false, "required": ["repo", "path"], "properties": { "repo": { "$ref": "#/$defs/repoSlug" }, "path": { "type": "string", "minLength": 1 } } }, "exposureGrant": { "type": "object", "additionalProperties": false, "required": ["reason", "approved_on", "residual_risk_owner"], "description": "Accepted residual risk for a reef host port or public DNS name we publish. Must name a hostname or a port. Port 6443 is rejected by the validator.", "properties": { "hostname": { "type": "string", "minLength": 1 }, "port": { "type": "integer", "minimum": 1, "maximum": 65535 }, "reason": { "type": "string", "minLength": 1 }, "approved_on": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, "residual_risk_owner": { "type": "string", "minLength": 1 } }, "anyOf": [ { "required": ["hostname"] }, { "required": ["port"] } ] }, "exposureTunnel": { "type": "object", "additionalProperties": false, "required": ["name"], "description": "Named ops-bridge / SSH path to this reef. Does not change packet posture.", "properties": { "name": { "type": "string", "minLength": 1 }, "local_port": { "type": "integer", "minimum": 1, "maximum": 65535 } } } } }