# Redis Lab Strict Kubeconfig Renderer Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use > `superpowers:subagent-driven-development` to implement this plan task-by-task. Steps use checkbox > (`- [ ]`) syntax for tracking. **Goal:** Complete parent Task 11.1A by replacing mutation-by-mutation kubeconfig filtering with a pinned-K3s, strict block-grammar validator/renderer and passing an independent safety review. **Architecture:** Freeze the already-reviewed lifecycle/ownership state machine as Task 11.1A-1. Move kubeconfig validation/rendering into one tracked AWK program, Task 11.1A-2. The program accepts only the exact single-cluster/context/user block grammar emitted by the pinned K3s slice, transforms only lab identity fields, and rejects every non-allowlisted structure before any lab `kubectl` command. **Tech Stack:** Bash 5 strict mode, POSIX-compatible AWK features already used by the repository, the fake-command shell contract, Gradle 9, Java 21. ## Global Constraints - Do not create a VM, run real Multipass/k3s/kubectl, inspect host inventory, or access the network. - Do not modify Task 11.1A-1 ownership, state, signal, lock, cleanup or fingerprint behavior. - Do not add `yq`, PyYAML, Ruby, Java YAML runtime, or another downloadable parser dependency. - The only accepted source grammar is the pinned K3s admin kubeconfig block-style shape defined in deep design ยง37.13.4.1. - `preferences: {}` is the only permitted flow collection. - Validation failure removes the destination, emits only `redis-lab: lab kubeconfig invalid`, and occurs before lab `kubectl`. - Preserve prior `CREATED|RECONCILE` state and delete only exact marker-proven current-run VMs. - Tests must show RED against the current implementation before production changes. - Human-only Git policy applies: do not stage, commit, amend or push. --- ### Task 1: Extract a strict generated-kubeconfig renderer **Files:** - Create: `infra/redis-lab/lib/render-kubeconfig.awk` - Modify: `infra/redis-lab/bin/redis-lab` - Modify: `infra/redis-lab/test/redis-lab-contract.sh` **Interfaces:** - Consumes: `awk -v address= -v target=ca-redis-lab -f `. - Produces: rendered kubeconfig on stdout and exit `0`, or no accepted output and non-zero exit. - Integration: `render_lab_kubeconfig ` performs atomic temporary render, mode `0600`, destination replacement only after renderer success. - [x] **Step 1: Add realistic positive and sibling-flow RED fixtures** Change the fake `valid` kubeconfig to this complete credential-data shape, using canary values rather than real certificate material: ```yaml apiVersion: v1 clusters: - cluster: certificate-authority-data: preserve-default-ca-canary server: https://127.0.0.1:6443 name: default contexts: - context: cluster: default namespace: team-default user: default name: default current-context: default kind: Config preferences: {} users: - name: default user: client-certificate-data: preserve-default-client-cert-canary client-key-data: preserve-default-client-key-canary ``` Add separate public `up` variants containing, after their canonical item: ```yaml cluster : {server: https://foreign.invalid:6443} ``` and: ```yaml context : {cluster: foreign, user: foreign} ``` Each variant must assert failure, zero lab `kubectl`, three exact marker-proven deletes, removed rendered kubeconfig, and no forbidden fake invocation. - [x] **Step 2: Run the direct contract and verify RED** Run: ```bash bash -n infra/redis-lab/bin/redis-lab infra/redis-lab/test/redis-lab-contract.sh bash infra/redis-lab/test/redis-lab-contract.sh ``` Expected: syntax succeeds and the first new sibling-flow case fails because the current renderer unexpectedly accepts it. - [x] **Step 3: Implement the strict AWK state machine** `render-kubeconfig.awk` must use an explicit `state` transition for every accepted line. It must not print from a catch-all rule. The accepted transition sequence is: ```text apiVersion -> clusters -> cluster-item -> ca-data -> server -> cluster-name -> contexts -> context-item -> context-cluster -> optional-namespace -> context-user -> context-name -> current-context -> kind -> preferences -> users -> user-name -> user-body -> client-cert -> client-key -> EOF ``` Exact identity transitions print these replacements: ```awk print " server: https://" address ":6443" print " name: " target print " cluster: " target print " user: " target print "current-context: " target print "- name: " target ``` CA/client credential and namespace transitions print `$0` unchanged. Any unmatched line sets `invalid=1`; `END` exits non-zero unless the final state is `client-key`, every required transition occurred once, the input had no tab/CR/YAML marker, and no trailing line exists. - [x] **Step 4: Integrate the renderer fail-closed** Add: ```bash KUBECONFIG_RENDERER="${REPOSITORY_ROOT}/infra/redis-lab/lib/render-kubeconfig.awk" ``` `validate_static_contract` must require a readable regular non-symlink renderer at that exact canonical path. Replace the inline AWK body with: ```bash local render_next="${destination_file}.next" rm -f -- "${render_next}" if ! awk -v address="${server_address}" -v target="${CONTEXT_NAME}" \ -f "${KUBECONFIG_RENDERER}" "${source_file}" >"${render_next}"; then rm -f -- "${render_next}" "${destination_file}" fail 'lab kubeconfig invalid' return 1 fi chmod 0600 -- "${render_next}" mv -f -- "${render_next}" "${destination_file}" ``` Add the `.next` destination to symlink-child validation. Propagate `rm`, `chmod` and `mv` failures with the same sanitized error and without retaining a partially accepted destination. - [x] **Step 5: Run focused GREEN** Run the direct contract again. Expected: `redis-lab-contract: PASS`, exit `0`. ### Task 2: Complete the mutation matrix and parent acceptance **Files:** - Modify: `infra/redis-lab/test/redis-lab-contract.sh` - Modify: `infra/redis-lab/README.md` - Modify: `docs/superpowers/plans/2026-07-29-redis-production-capability-completion.md` - Modify: `.superpowers/sdd/2026-07-29-redis-production-capability-completion/progress.md` - Create: `.superpowers/sdd/2026-07-29-redis-production-capability-completion/task-11-1a-2-brief.md` - Create: `.superpowers/sdd/2026-07-29-redis-production-capability-completion/task-11-1a-2-report.md` **Interfaces:** - Consumes: Task 1 strict renderer and existing lifecycle fake runtime. - Produces: parent Task 11.1A review package with no open Critical/Important finding. - [x] **Step 1: Add one mutation per grammar boundary** Add table-driven fixture variants for missing, duplicate, reordered and unknown keys; whitespace before colon; quoted/tagged/explicit keys; anchor/alias/merge; unexpected `{}`/`[]`; tab, CRLF, `---`/`...`, and trailing content. Every case must assert failure before lab `kubectl`, exact current-run cleanup and removed render output. - [x] **Step 2: Prove scalar preservation and exact transformation** The positive case must assert: ```text server: https://192.0.2.10:6443 name/current-context: ca-redis-lab namespace: team-default preserve-default-ca-canary preserve-default-client-cert-canary preserve-default-client-key-canary ``` It must also assert that no `name: default`, `cluster: default`, `user: default`, `current-context: default` or loopback server remains. - [x] **Step 3: Re-run the full fake-only verification** Run: ```bash bash -n infra/redis-lab/bin/redis-lab infra/redis-lab/test/redis-lab-contract.sh bash infra/redis-lab/test/redis-lab-contract.sh cd src ./gradlew :adapter:outbound:cache-redis:redisLabContractTest --console=plain ./gradlew :adapter:outbound:cache-redis:test --console=plain ./gradlew :adapter:outbound:cache-redis:check --dry-run --console=plain ``` Expected: direct `PASS`; both Gradle executions `BUILD SUCCESSFUL`; dry-run includes `redisLabContractTest`. - [x] **Step 4: Run an independent scoped review** Reviewer acceptance: - strict renderer has no catch-all pass-through; - the valid pinned fixture reaches EOF exactly once; - every non-allowlisted structural line fails; - destination publication is atomic/fail-closed; - Task 11.1A-1 lifecycle code is unchanged except the renderer call and static path checks; - Critical `0`, Important `0`, both spec and quality PASS. - [x] **Step 5: Close the parent task** Only after Step 4 passes, replace the ledger `BLOCKED` state with an additive resolution line: ```text Task 11.1A-2: complete (human-only commit policy; strict renderer review clean) Task 11.1A: complete (11.1A-1 lifecycle + 11.1A-2 renderer; fake-only evidence) ``` Do not claim live readiness, R2 or VM/k3s qualification.