{ "lexicon": 1, "id": "com.publicdomainrelay.temp.cluster.getKubeconfig", "defs": { "main": { "type": "procedure", "description": "Return a kubeconfig for the named cluster of the calling account. Creates on read: if the account has no cluster of this name, this call creates the account workspace, its home, the Cluster record (spec.running=false) and the mounted child, then returns a kubeconfig. Idempotent - a second call finds everything and returns the same thing. Requires a service-auth JWT from the CALLER's own PDS; the account is the VERIFIED token's iss and is never read from this input. A cluster whose spec.running is false answers ClusterNotRunning; call createCluster or controlPlaneUp first. This call does not wake the control plane. The kubeconfig carries a client key and a short-lived x509 client certificate issued by the cluster's own OpenBao PKI. The key is made by OpenBao and returned only in this response; nothing stores it. ttlSeconds sets the certificate lifetime.", "input": { "encoding": "application/json", "schema": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string", "description": "The cluster label, unique within the calling account. RFC-1123 label, <=63 characters." }, "ttlSeconds": { "type": "integer", "minimum": 60, "maximum": 86400, "description": "Lifetime of the client certificate in seconds. Absent is 28800 (8 h). Below 60 or above 86400 is InvalidRequest: refused, never clamped. Never together with noExpiry." }, "noExpiry": { "type": "boolean", "default": false, "description": "Issue a certificate with no expiry (NotAfter 9999-12-31T23:59:59Z truncated to the cluster CA). It ends only by revocation (revokeIdentity), deleteCluster, or the CA expiring. Never together with ttlSeconds." } } } }, "output": { "encoding": "application/json", "schema": { "type": "object", "required": ["kubeconfig", "instance"], "properties": { "kubeconfig": { "type": "string", "description": "The whole kubeconfig, as YAML text. users[0].user holds client-certificate-data and client-key-data; there is no exec block and no token. The certificate's CN is the caller DID and its O is socialweb.computer:cluster-owners. Keep the file mode 0600; never commit it." }, "instance": { "type": "string", "description": "status.instance: the opaque per-materialisation generation id of the cluster this kubeconfig points at. Retain it - a cached kubeconfig whose instance no longer matches must not be reused, and a new instance exists after every delete-then-recreate; controlPlaneDown and controlPlaneUp and a gateway restart keep the instance, because the cluster keeps its CA and state." } } } }, "errors": [ { "name": "InvalidRequest", "description": "Name absent, or not a legal RFC-1123 label within 63 characters." }, { "name": "Unauthorized", "description": "Missing or invalid service-auth token. Also returned when the token's aud is not this service or its lxm is not this method." }, { "name": "IdentityRevoked", "description": "The caller's identity carries a deny record for this account. The deny is written before any deletion, so it refuses while the revocation is still propagating." }, { "name": "ClusterNotFound", "description": "This account has no cluster of that name. Deliberately indistinguishable from a name that belongs to another account." }, { "name": "ClusterNotRunning", "description": "The cluster exists but spec.running is false. Call createCluster or controlPlaneUp, then call this again." }, { "name": "ClusterInitializing", "description": "The control plane or its vault is coming up. Retry after the Retry-After header." } ] } } }