61 lines
3.7 KiB
Markdown
Executable File
61 lines
3.7 KiB
Markdown
Executable File
# M5 engineering — private staging deployment contract
|
||
|
||
Updated: 2026-11-02. This is the first bounded M5 engineering slice. It defines
|
||
and offline-tests a private Kubernetes staging workload in `ansible-role-luanti`;
|
||
it is not a live cluster deployment, closed alpha, or production authorization.
|
||
The game payload remains 0.5.0-m4 / Luanti 5.18.0 / save schema 1.
|
||
|
||
## Staging contract implemented
|
||
|
||
- One `Recreate` Deployment, one retained standalone world PVC, ConfigMap with
|
||
explicit staging settings, UDP-only `ClusterIP` service and ingress
|
||
NetworkPolicy restricted to explicit IPv4 client CIDRs.
|
||
- Deployment image must be an immutable `@sha256:<64 lowercase hex>` reference.
|
||
This repository does **not** build or publish the Luanti server image. The
|
||
operator-provided image must contain Luanti 5.18.0, the verified game under
|
||
`/opt/luanti/games/last_hearth`, and the documented non-root/volume/entrypoint
|
||
contract. A digest is pinning/integrity metadata, not publisher authentication.
|
||
- Production mode, mutable image tags, missing coordinates, empty/wildcard client
|
||
access, malformed CIDRs and invalid names fail validation before Kubernetes API
|
||
access. PvP, creative mode and announcements are disabled; Luanti mod security is
|
||
enabled; default player privileges are limited. The pod runs non-root with a
|
||
read-only root filesystem, dropped capabilities, no service-account token, and
|
||
bounded CPU/memory.
|
||
- No public Ingress, `NodePort`, or `LoadBalancer` is rendered; apply operations
|
||
use `state: present` without pruning/deletion. The cluster CNI must enforce
|
||
NetworkPolicy, and the VPN/routed client source addresses must be confirmed by
|
||
the operator.
|
||
- Admin bootstrap is a controlled staging procedure: initially allow only the
|
||
operator's VPN address, initialize the native account with a unique staging-only
|
||
password, verify privileges and a second ordinary account, then deliberately
|
||
widen the allowlist for invited testers. Never reuse platform passwords or put
|
||
passwords/secrets in role variables, ConfigMaps, or this repository.
|
||
- PVC encryption, backup custody/retention, stopping remote writers and offline
|
||
restore remain operator duties. This role does not create backups or prove
|
||
storage encryption.
|
||
|
||
## Offline checks
|
||
|
||
The role test script renders Kubernetes YAML locally, validates required resource
|
||
shape and safety invariants, and checks pinning, policy, storage, privilege and
|
||
exposure. Negative cases prove production mode, mutable image references, empty or
|
||
public client CIDRs and invalid coordinates are rejected. The portable test target
|
||
has no kubeconfig and must not contact a cluster. If Ansible CLI is available, the
|
||
script additionally runs role syntax, Ansible rendering and negative task tests.
|
||
**Local result:** direct Jinja render and all resource-shape/security invariants
|
||
passed, along with seven fail-closed configuration cases. The Docker daemon was
|
||
unavailable, and Ansible CLI cannot run under the configured Windows Python
|
||
console in this environment, so full Ansible task syntax/render validation remains
|
||
unverified. No Kubernetes API was contacted.
|
||
|
||
## Remaining M5 work
|
||
|
||
No server image/artifact has been built or scanned, no staging cluster has been
|
||
configured or contacted, and no invited client has joined. Still required:
|
||
artifact build/signing/provenance, cluster-specific access and encrypted storage
|
||
review, moderator/reporting policy, client and server telemetry, restart/outage/
|
||
disconnect tests, sustained multiplayer and concurrent workstation/storage tests,
|
||
and a witnessed backup-break-restore drill with measured recovery objectives.
|
||
Earlier M1–M4 human acceptance gates remain open. No production rollout or M5
|
||
exit-gate pass is claimed.
|