rail-kubernetes/workplans/RAIL-K8S-WP-0003-private-by-default-networking.md
codex 004f1c4dc1 Enforce private-by-default rail exposure
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a02669-87ee-7a31-b111-edc95a16e0fa
2026-08-22 12:34:25 +02:00

76 lines
2.3 KiB
Markdown

---
id: RAIL-K8S-WP-0003
type: workplan
title: "Private-by-default networking until an exposure grant exists"
domain: financials
repo: rail-kubernetes
status: finished
owner: codex
topic_slug: railiance
created: "2026-08-15"
updated: "2026-08-22"
related:
- RMASTER-WP-0023
- ADR-0008
- ADR-0006
---
# RAIL-K8S-WP-0003 — private-by-default networking
Intake from `RMASTER-WP-0023-T05`. Until this rail owns live networking,
`railiance-cluster` may implement the same controls and back-link here.
## Goal
Enforce ADR-0008 on the Kubernetes rail: ClusterIP is the paved Service;
default-deny NetworkPolicy; no public Ingress unless the rapp has
`exposure.posture: public`, a grant, `binding_admission:
production-approved`, and the reef has granted a public surface.
Do not define what production-safe means (ADR-0006). Do not open `6443`.
## T01 — Pave ClusterIP and default-deny
```task
id: RAIL-K8S-WP-0003-T01
status: done
priority: high
```
Templates and overlays emit ClusterIP and default-deny NetworkPolicy.
Document the operator/tunnel path for debug. Missing `exposure` means
`private`.
**Done when:** a new rapp on this rail has no public listener unless a
grant exists.
**Outcome (2026-08-22):** generated overlays now render an explicit
`ClusterIP` Service, a default-deny ingress `NetworkPolicy`, and no Ingress by
default. The scaffold regression test renders the generated chart and asserts
all three properties.
## T02 — Gate public Ingress on the grant
```task
id: RAIL-K8S-WP-0003-T02
status: done
priority: high
```
A public Ingress class is emitted only when the declaration carries a
valid grant. An Ingress object is not itself a grant.
**Done when:** an ungranted rapp cannot obtain a public Ingress from the
paved path.
**Outcome (2026-08-22):** Stage 2 renders the chart before server dry-run or
apply and validates any Ingress/IngressRoute against both the rapp and reef
declarations. Private is the fail-closed default; a public surface requires a
matching grant and `production-approved` binding admission. Regression tests
cover missing, mismatched, and valid grants.
## Completion evidence
- `python3 -m unittest discover -s tests -v`: 6 tests passed.
- Generated overlay `tests/stage2-template.sh`: passed, including Helm render.
- `bash -n tools/create_railiance_overlay_repo.sh`: passed.