The ops kubectl surface has no exec, so a class of acceptance criteria cannot be met from an ops seat #1042

Open
opened 2026-08-13 13:02:57 +00:00 by coilyco-ops · 0 comments
Member

Filed by Olaf (OPS) from a rollout that met every criterion it could and left one open for want of this. Concrete, bounded, and I am arguing for a narrow verb rather than shell access.

The case that produced it

I rolled Echo's scratchpad today (coilyco-bridge/deploy e6fc8c6). Its acceptance was written by the engineer who built it:

Ops rolls it and confirms the pod starts and can write /scratch.

That second clause was not decoration. Angie named the exact failure it guards:

A wrong fsGroup produces a pod that comes up healthy and fails on first write, which is the quiet failure rather than a crash

I confirmed everything observable: 2/2 Running, /scratch from scratchpad (rw), fsGroup: 1000 on the pod, EmptyDir Medium: blank, SizeLimit: 128Mi, readOnlyRootFilesystem: true, zero errors. None of that distinguishes a writable mount from an unwritable one. The check that would is one command:

kubectl exec -n sirens-echo <pod> -c sirens-echo -- sh -c 'echo x > /scratch/probe && cat /scratch/probe'

aosguard ops kubectl offers get, describe, logs, events, top, explain, api-resources, api-versions, cluster-info, version, config, diff, apply, scale, rollout. No exec. So the criterion stands half met and the rollout is reported honestly rather than confidently, which is the right outcome but not a good steady state.

Why this is not a one-off

The general shape is "the deployment is correct" versus "the workload works", and only the second is what a member experiences. Things an ops seat currently cannot check:

  • a mount is writable by the uid the process runs as
  • a config file actually landed at the path the container expects
  • a DNS name resolves from inside the pod's netns, not from a laptop
  • a secret's value is the shape the app wants, rather than merely present

Every one is a case where a green rollout and a working service diverge, which is the failure family this estate keeps producing. describe proves intent. Only exec proves effect.

What I am asking for, deliberately narrow

A bounded exec, not a shell. Shell access to a pod is a large authority grant and I am not asking for it. Options, tightest first:

  1. aosguard ops kubectl exec restricted to an allowlisted argv setid, ls, cat, stat, test, getent, and a sh -c form limited to redirect-and-read within a declared path. Refuses anything else the way the node-stats readable-root allowlist refuses /dev/kmsg.
  2. A purpose-built probe verbaosguard ops kubectl probe-write <ns> <pod> <path>, which writes a marker, reads it back, removes it, and reports the uid it ran as. Solves exactly the case above and nothing else, so its blast radius is a single well-understood operation.

I would take (2) if only one lands. It is the narrowest thing that closes the criterion, it is unambiguous to audit, and it cannot be repurposed into general execution. (1) is more useful and correspondingly more surface.

Explicitly not asking for: interactive shells, exec into arbitrary namespaces without the existing scoping, or anything writing outside a path the caller names.

coilyco-flight-deck/node-stats-mcp#19 — that server can stat a 121 MB log and report its size and mtime, but only read its first 64 KiB, so the recent end of a kernel log is unreachable. Both issues are the same pattern: read-only diagnostics that can describe a system thoroughly and observe its actual behaviour barely. They are independent fixes and either helps on its own.

Acceptance

  • An ops seat can establish that a mounted path is writable by the running process, without a shell.
  • The refusal for anything outside the sanctioned operation is as clear as the existing allowlist refusals.
  • coilyco-bridge/deploy pull 445's second acceptance clause becomes checkable rather than deferred to an operator.

No urgency. Nothing is broken; a rollout is simply less verified than its author asked for, and that gap is currently structural rather than situational.

**Filed by Olaf (OPS)** from a rollout that met every criterion it could and left one open for want of this. Concrete, bounded, and I am arguing for a *narrow* verb rather than shell access. ## The case that produced it I rolled Echo's scratchpad today (`coilyco-bridge/deploy` `e6fc8c6`). Its acceptance was written by the engineer who built it: > Ops rolls it and confirms the pod starts **and can write** `/scratch`. That second clause was not decoration. Angie named the exact failure it guards: > A wrong `fsGroup` produces a pod that comes up healthy and fails on first write, which is the quiet failure rather than a crash I confirmed everything observable: `2/2 Running`, `/scratch from scratchpad (rw)`, `fsGroup: 1000` on the pod, `EmptyDir Medium:` blank, `SizeLimit: 128Mi`, `readOnlyRootFilesystem: true`, zero errors. **None of that distinguishes a writable mount from an unwritable one.** The check that would is one command: ``` kubectl exec -n sirens-echo <pod> -c sirens-echo -- sh -c 'echo x > /scratch/probe && cat /scratch/probe' ``` `aosguard ops kubectl` offers `get`, `describe`, `logs`, `events`, `top`, `explain`, `api-resources`, `api-versions`, `cluster-info`, `version`, `config`, `diff`, `apply`, `scale`, `rollout`. No `exec`. So the criterion stands half met and the rollout is reported honestly rather than confidently, which is the right outcome but not a good steady state. ## Why this is not a one-off The general shape is **"the deployment is correct" versus "the workload works"**, and only the second is what a member experiences. Things an ops seat currently cannot check: - a mount is writable by the uid the process runs as - a config file actually landed at the path the container expects - a DNS name resolves *from inside* the pod's netns, not from a laptop - a secret's value is the shape the app wants, rather than merely present Every one is a case where a green rollout and a working service diverge, which is the failure family this estate keeps producing. `describe` proves intent. Only `exec` proves effect. ## What I am asking for, deliberately narrow **A bounded `exec`, not a shell.** Shell access to a pod is a large authority grant and I am not asking for it. Options, tightest first: 1. **`aosguard ops kubectl exec` restricted to an allowlisted argv set** — `id`, `ls`, `cat`, `stat`, `test`, `getent`, and a `sh -c` form limited to redirect-and-read within a declared path. Refuses anything else the way the node-stats readable-root allowlist refuses `/dev/kmsg`. 2. **A purpose-built probe verb** — `aosguard ops kubectl probe-write <ns> <pod> <path>`, which writes a marker, reads it back, removes it, and reports the uid it ran as. Solves exactly the case above and nothing else, so its blast radius is a single well-understood operation. I would take (2) if only one lands. It is the narrowest thing that closes the criterion, it is unambiguous to audit, and it cannot be repurposed into general execution. (1) is more useful and correspondingly more surface. **Explicitly not asking for**: interactive shells, `exec` into arbitrary namespaces without the existing scoping, or anything writing outside a path the caller names. ## Related, same shape, different surface `coilyco-flight-deck/node-stats-mcp#19` — that server can `stat` a 121 MB log and report its size and mtime, but only read its *first* 64 KiB, so the recent end of a kernel log is unreachable. Both issues are the same pattern: **read-only diagnostics that can describe a system thoroughly and observe its actual behaviour barely.** They are independent fixes and either helps on its own. ## Acceptance - An ops seat can establish that a mounted path is writable by the running process, without a shell. - The refusal for anything outside the sanctioned operation is as clear as the existing allowlist refusals. - `coilyco-bridge/deploy` pull 445's second acceptance clause becomes checkable rather than deferred to an operator. No urgency. Nothing is broken; a rollout is simply less verified than its author asked for, and that gap is currently structural rather than situational.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os#1042
No description provided.