diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b0c7f..3308152 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,47 @@ one of them changed. An entry says which artefact and which version, so `web 0.1 Every version published to a channel appears here. Nothing is written from memory afterwards: a build cannot be published without its entry. +## 2026-09-01 — Jarvis administers Kubernetes clusters `api 0.105.0` `web 0.128.0` + +**Register a cluster the way you register a server, and ask for the work in words.** A Kubernetes +cluster is now a kind of asset, under **Virtualization & containers**, reached either by pasting a +kubeconfig into the vault or by pointing Jarvis at the API server with a ServiceAccount token. Any +conformant cluster: k3s, RKE2, kubeadm, EKS, AKS, GKE. + +**What it can read.** Workloads (pods, deployments, statefulsets, daemonsets, replicasets, jobs, +cronjobs), nodes, namespaces, networking, storage, events, pod logs — including the previous +container's log, which on a CrashLoopBackOff is the only copy holding the error — live CPU and +memory where metrics-server is installed, and the Helm releases with their revision and status. The +output is shaped like `kubectl`, because that is what everyone reading the transcript already knows. + +**What it can do.** Scale, restart a rollout, delete a pod so its controller replaces it, cordon and +uncordon a node, drain one, suspend and resume a CronJob. Draining uses the eviction API, so a +PodDisruptionBudget refuses an eviction that would take a service below its floor instead of the +drain quietly ignoring it. + +**And, for what no fixed list covers:** read any API path (which is how custom resources — +cert-manager, Argo CD, CloudNativePG — are reached), apply a manifest with server-side apply, and +run a command inside a container. Those three are marked as tools whose operation the assistant +composes itself, so an access grant has to admit them deliberately rather than inheriting them from +a risk level. + +**Risk is judged per call, not per tool.** Scaling is an ordinary change; scaling to zero takes the +service down and asks first. An apply is an ordinary change; an apply carrying RBAC, an admission +webhook, a CRD or anything at all into `kube-system` asks first, and says which of those it found. +Deleting anything always asks. Applying a namespace with the deployment that goes in it does not — +an approval on every deploy is an approval nobody reads. + +**Two things it will not do.** No tool reads a Secret: the resource lists exclude them, and the Helm +tool reads the release index rather than decoding a release, which would carry the values a chart was +installed with. And a kubeconfig whose credential comes from running a program (`exec` / +`auth-provider` — the EKS and GKE default) is refused by name, with the ServiceAccount route named as +the answer, rather than failing later as an authentication error. + +**Testing a connection records what the cluster is** on the asset: version, distribution, node count, +total capacity and node addresses. + +Take both images. The schema gains one enum value and the migration is uneventful. + ## 2026-08-31 — The Tasks panel now looks like the rest of the workspace `web 0.127.0` **And its actions menu is reachable with a mouse again**, which is the part that was not merely diff --git a/README.md b/README.md index f50a416..ddb8893 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ is listed in full below. ## What it does -**Five connectors reach a managed system.** Each one is a set of tools the assistant may call, and +**Six connectors reach a managed system.** Each one is a set of tools the assistant may call, and what it may do with them is decided per call — see the next section. | Connector | Reaches | @@ -57,10 +57,12 @@ what it may do with them is decided per call — see the next section. | **Proxmox VE** | The cluster API. Read and power only — no create, clone, snapshot, backup or migrate. | | **MikroTik RouterOS** | The native binary API, or the RouterOS 7 REST API. One identical tool surface either way; the connection decides the transport. | | **Microsoft 365** | Graph, app-only, on any Microsoft cloud, authenticating with a client secret or a certificate. Named tools for identity, licences, groups, admin roles, Exchange Online, Intune and the audit logs, plus one that reaches every remaining Graph endpoint. | +| **Kubernetes** | Any conformant cluster through its API server — k3s, RKE2, kubeadm, EKS, AKS, GKE. Reached with a kubeconfig or a ServiceAccount token. Workloads, nodes, networking, storage, events, logs and usage to read; scale, rollout restart, cordon, drain and CronJob suspend to operate; and, for what no fixed list covers, an arbitrary API read, server-side apply of a manifest, and a command inside a container. | **An asset is the managed thing; a connection is a way of reaching it.** A Linux host commonly answers on OpenSSH *and* through an enrolled agent; a Proxmox node has a cluster API, a shell and an -agent. Each route carries its own address, its own credentials and its own health — so a vendor API +agent. A Kubernetes cluster is the control plane, and its nodes are separate assets if anybody wants a +shell on them. Each route carries its own address, its own credentials and its own health — so a vendor API that stops answering no longer makes a device unmanageable while its console is up. **And a terminal goes over a route you choose.** On a host reachable both ways, opening a shell asks @@ -359,7 +361,8 @@ it on machines that already took the update. binary that the api serves from `AGENT_RELEASE_DIR`, and a compose-only deployment has no way to produce one. `docker-compose.agent.yml` supplies it as a pullable image instead. Leaving it off is a supported state rather than a broken one: everything else works, the manifest and download endpoints -answer 503 saying no build is published, and the SSH, Proxmox, Microsoft 365 and MikroTik connectors +answer 503 saying no build is published, and the SSH, Proxmox, Kubernetes, Microsoft 365 and MikroTik +connectors all reach machines without it. Turn it on by adding one line to `.env`, so that every later `docker compose` command picks up both