{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schema.ontai.dev/v1alpha1/seam-core/InfrastructureTalosCluster.json",
  "title": "InfrastructureTalosCluster",
  "description": "Root declaration CRD for a Talos cluster under Seam governance. Owned by seam-core; platform operator reconciles instances of this type. Declares whether the cluster is bootstrapped from scratch (mode=bootstrap) or imported from existing infrastructure (mode=import). On mode=import the role field is mandatory. platform-schema.md §4. Decision H.",
  "x-ont-layer": "seam-core",
  "x-ont-stability": "alpha",
  "x-ont-namespace": "seam-system",
  "x-ont-depends-on": [],
  "type": "object",
  "required": ["spec"],
  "properties": {
    "spec": {
      "type": "object",
      "description": "InfrastructureTalosCluster specification. Immutable after admission except for status fields.",
      "required": ["mode"],
      "properties": {
        "mode": {
          "type": "string",
          "enum": ["bootstrap", "import"],
          "description": "Declares whether this cluster provisions a new cluster (bootstrap) or records an existing cluster managed outside Seam (import). Immutable after creation."
        },
        "role": {
          "type": "string",
          "enum": ["management", "tenant"],
          "description": "Declares the role of this cluster in the Seam topology. Mandatory on mode=import; absent on mode=bootstrap."
        },
        "talosVersion": {
          "type": "string",
          "description": "Talos OS version for this cluster. Used by the Conductor to select a compatible conductor image per INV-012."
        },
        "clusterEndpoint": {
          "type": "string",
          "description": "Cluster VIP or primary API endpoint IP. Required on mode=import. Optional on mode=bootstrap (derived from bootstrap Job output). Renamed from endpoint."
        },
        "nodeAddresses": {
          "type": "array",
          "description": "List of node IPs belonging to this cluster. Used by DSNSReconciler to populate A records in the seam DNS zone. platform-schema.md §5.",
          "items": {
            "type": "string"
          }
        },
        "infrastructureProvider": {
          "type": "string",
          "enum": ["native", "capi", "screen"],
          "default": "native",
          "description": "Infrastructure provider backing this cluster. native: standard path (direct bootstrap or CAPI). capi: explicit CAPI alias. screen: reserved for future Screen operator (INV-021); sets ScreenProviderNotImplemented and halts."
        },
        "capi": {
          "type": "object",
          "description": "CAPI integration settings. When absent the cluster uses the direct bootstrap path.",
          "required": ["enabled"],
          "properties": {
            "enabled": {
              "type": "boolean",
              "description": "When true the cluster is managed via Cluster API. When false or absent the direct bootstrap path is used."
            },
            "talosVersion": {
              "type": "string",
              "description": "Talos version for TalosConfigTemplate and CABPT machineconfig generation. Required when enabled=true."
            },
            "kubernetesVersion": {
              "type": "string",
              "description": "Kubernetes version for TalosControlPlane. Required when enabled=true."
            },
            "controlPlane": {
              "type": "object",
              "description": "Control plane configuration. Required when enabled=true.",
              "properties": {
                "replicas": {
                  "type": "integer",
                  "description": "Desired number of control plane nodes."
                }
              },
              "additionalProperties": false
            },
            "workers": {
              "type": "array",
              "description": "List of worker node pools. Each pool maps to a MachineDeployment + SeamInfrastructureMachineTemplate.",
              "items": {
                "type": "object",
                "required": ["name"],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Pool identifier. Used as the MachineDeployment name suffix."
                  },
                  "replicas": {
                    "type": "integer",
                    "description": "Desired number of worker nodes in this pool."
                  },
                  "seamInfrastructureMachineNames": {
                    "type": "array",
                    "description": "SeamInfrastructureMachine CR names pre-provisioned for this pool.",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "additionalProperties": false
              }
            },
            "ciliumPackRef": {
              "type": "object",
              "description": "Reference to the cluster-specific Cilium ClusterPack. Applied as the first pack after the CAPI cluster reaches Running state. Required when enabled=true. platform-schema.md §2.3.",
              "required": ["name", "version"],
              "properties": {
                "name": {
                  "type": "string",
                  "description": "ClusterPack CR name for the Cilium pack."
                },
                "version": {
                  "type": "string",
                  "description": "ClusterPack version string."
                }
              },
              "additionalProperties": false
            }
          },
          "additionalProperties": false
        },
        "kubeconfigSecretRef": {
          "type": "string",
          "description": "Name of the Secret containing the kubeconfig for this cluster. Required on mode=import. Not used when CAPI manages the lifecycle."
        },
        "talosconfigSecretRef": {
          "type": "string",
          "description": "Name of the Secret containing the talosconfig for this cluster."
        },
        "lineage": {
          "type": "object",
          "description": "Sealed causal chain record. Authored once at object creation and immutable thereafter. seam-core-schema.md §5, CLAUDE.md Decision 1.",
          "additionalProperties": true
        },
        "pkiRotationThresholdDays": {
          "type": "integer",
          "default": 30,
          "minimum": 1,
          "description": "Days before cert expiry to auto-trigger PKI rotation. When pkiExpiryDate is within this many days of the current time, the TalosCluster reconciler creates a PKIRotation CR automatically. Default 30. platform-schema.md §13."
        },
        "hardeningProfileRef": {
          "type": "object",
          "description": "Reference to a HardeningProfile CR to apply at bootstrap. ONT-native path: the platform reconciler creates a NodeMaintenance (operation=hardening-apply, label ontai.dev/hardening-trigger=bootstrap) in seam-tenant-{cluster} after the cluster reaches Ready. CAPI path: MachineConfigPatches and SysctlParams are merged into TalosConfigTemplate at provisioning time. platform-schema.md §11.",
          "required": ["name"],
          "properties": {
            "name": {
              "type": "string",
              "description": "HardeningProfile CR name."
            },
            "namespace": {
              "type": "string",
              "description": "HardeningProfile CR namespace. Defaults to the TalosCluster namespace (seam-system) when absent."
            }
          },
          "additionalProperties": false
        }
      },
      "additionalProperties": false,
      "x-kubernetes-validations": [
        {
          "rule": "self.mode != 'import' || (has(self.role) && (self.role == 'management' || self.role == 'tenant'))",
          "message": "role must be present and one of management or tenant when mode is import"
        }
      ]
    },
    "status": {
      "type": "object",
      "description": "Runtime status. Written exclusively by the TalosClusterReconciler.",
      "properties": {
        "observedGeneration": {
          "type": "integer",
          "description": "Generation of the spec most recently reconciled."
        },
        "origin": {
          "type": "string",
          "enum": ["bootstrapped", "imported"],
          "description": "Records how the cluster came to exist. bootstrapped: created via the bootstrap path. imported: adopted via the import path."
        },
        "capiClusterRef": {
          "type": "object",
          "description": "Reference to the owned CAPI Cluster object in the tenant namespace. Only set for CAPI-managed clusters (capi.enabled=true).",
          "required": ["name"],
          "properties": {
            "name": {
              "type": "string",
              "description": "CAPI Cluster CR name."
            },
            "namespace": {
              "type": "string",
              "description": "CAPI Cluster namespace."
            }
          },
          "additionalProperties": false
        },
        "conditions": {
          "type": "array",
          "description": "Standard Kubernetes condition list. Condition types: Ready, Bootstrapping, Bootstrapped, Importing, Degraded, CiliumPending, ControlPlaneUnreachable, PartialWorkerAvailability, ConductorReady, ScreenProviderNotImplemented, PhaseFailed, KubeconfigUnavailable, HardeningApplied.",
          "items": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "pkiExpiryDate": {
          "type": "string",
          "format": "date-time",
          "description": "Earliest certificate expiry found across talosconfig and kubeconfig Secrets. Set by the TalosCluster reconciler after reading the stored Secrets. Used to detect approaching PKI expiry. platform-schema.md §13."
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": true
}
