Near-miss, 2026-07-25. A bin/arcodange sandbox checkpoint refresh was issued while the current kube-context was do-nyc3-kissmetrics-prod-k8s-cluster — a client production cluster. sandbox-lifecycle.sh never checked the context: it patched the ArgoCD Application, scaled erp-sandbox to zero and copied a prod secret, all against the client's cluster.
Nothing was damaged — that cluster has no application CRD and no erp/erp-sandbox namespaces, so every call failed silently under || true. That is luck, not a control. The same script on a cluster that happened to have an erp-sandbox namespace would have scaled it to zero and run DROP OWNED ... CASCADE against it.
Fix:
ERP_KUBE_CONTEXT (default default) pins the target; all 20 kubectl calls now route through K(), so nothing inherits the ambient context.
assert_arcodange_cluster() proves the target by positive fingerprint — the erp, erp-sandbox and argocd namespaces and the erp-sandbox ArgoCD Application. A client cluster cannot match all four by accident. Wired into all three entry points, before any mutation.
Verified live: refuses the client context (with the reason and the remedy), refuses an unknown context, passes on the homelab and completes sync-documents normally.
This is the kube-side twin of the Playwright host guard shipped in #75 — same failure mode (ambient environment pointing at something that is not the sandbox), same remedy (explicit target, proven before acting).
**Near-miss, 2026-07-25.** A `bin/arcodange sandbox checkpoint refresh` was issued while the current kube-context was **`do-nyc3-kissmetrics-prod-k8s-cluster` — a client production cluster**. `sandbox-lifecycle.sh` never checked the context: it patched the ArgoCD Application, scaled `erp-sandbox` to zero and copied a prod secret, all against the client's cluster.
Nothing was damaged — that cluster has no `application` CRD and no `erp`/`erp-sandbox` namespaces, so every call failed silently under `|| true`. **That is luck, not a control.** The same script on a cluster that happened to have an `erp-sandbox` namespace would have scaled it to zero and run `DROP OWNED ... CASCADE` against it.
Fix:
- `ERP_KUBE_CONTEXT` (default `default`) pins the target; all 20 `kubectl` calls now route through `K()`, so nothing inherits the ambient context.
- `assert_arcodange_cluster()` proves the target by **positive fingerprint** — the `erp`, `erp-sandbox` and `argocd` namespaces **and** the `erp-sandbox` ArgoCD Application. A client cluster cannot match all four by accident. Wired into all three entry points, before any mutation.
Verified live: refuses the client context (with the reason and the remedy), refuses an unknown context, passes on the homelab and completes `sync-documents` normally.
This is the kube-side twin of the Playwright host guard shipped in #75 — same failure mode (ambient environment pointing at something that is not the sandbox), same remedy (explicit target, proven before acting).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
sandbox-lifecycle.sh scales deployments to zero, patches the ArgoCD Application
and runs DROP OWNED ... CASCADE. Every one of those ran against whatever
kube-context happened to be current.
This workstation also carries a CLIENT production cluster. On 2026-07-25 a
`checkpoint refresh` was issued while the current context was
do-nyc3-kissmetrics-prod-k8s-cluster: the script patched the ArgoCD Application,
scaled `erp-sandbox` to zero and copied a prod secret — all against the client's
cluster. Nothing was damaged only because that cluster has no `application` CRD
and no erp/erp-sandbox namespaces, so each call failed silently under `|| true`.
That is luck, not a control.
- ERP_KUBE_CONTEXT (default: "default") pins the target; every kubectl call now
goes through K(), so nothing inherits the ambient context.
- assert_arcodange_cluster() proves the target by positive fingerprint — the
erp, erp-sandbox and argocd namespaces AND the erp-sandbox ArgoCD Application.
A client cluster cannot match all four by accident. Wired into all three
entry points, before any mutation.
Verified: refuses the client context, refuses an unknown context, passes on the
homelab and completes normally.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Near-miss, 2026-07-25. A
bin/arcodange sandbox checkpoint refreshwas issued while the current kube-context wasdo-nyc3-kissmetrics-prod-k8s-cluster— a client production cluster.sandbox-lifecycle.shnever checked the context: it patched the ArgoCD Application, scalederp-sandboxto zero and copied a prod secret, all against the client's cluster.Nothing was damaged — that cluster has no
applicationCRD and noerp/erp-sandboxnamespaces, so every call failed silently under|| true. That is luck, not a control. The same script on a cluster that happened to have anerp-sandboxnamespace would have scaled it to zero and runDROP OWNED ... CASCADEagainst it.Fix:
ERP_KUBE_CONTEXT(defaultdefault) pins the target; all 20kubectlcalls now route throughK(), so nothing inherits the ambient context.assert_arcodange_cluster()proves the target by positive fingerprint — theerp,erp-sandboxandargocdnamespaces and theerp-sandboxArgoCD Application. A client cluster cannot match all four by accident. Wired into all three entry points, before any mutation.Verified live: refuses the client context (with the reason and the remedy), refuses an unknown context, passes on the homelab and completes
sync-documentsnormally.This is the kube-side twin of the Playwright host guard shipped in #75 — same failure mode (ambient environment pointing at something that is not the sandbox), same remedy (explicit target, proven before acting).
🤖 Generated with Claude Code
https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh