# Service operations Build with `make install test build`. `make test-integration` launches real Chromium inside the pinned upstream image; it needs Docker, not a host browser. Publish the tested image through the existing Forgejo OCI credential lane and read its digest back. `make render IMAGE_REFERENCE=forgejo.coulomb.social/coulomb/rapp-playwright@sha256:…` rejects floating tags. Never record a placeholder as a published digest. The initial package uses a single replica, Recreate updates, 100m CPU/256Mi requests, 1 CPU/1Gi limits, and a 2Gi local-path PVC. Artifacts expire after one hour; they are transient evidence, not a backup service. Consumers download what they need to retain. Recreate avoids a surge on the capacity-constrained single-node cluster and preserves the RWO volume. Before activation, confirm the node identity and current resource headroom, platform lifecycle ownership/admission, publication/pull access, and private consumer connectivity. Run `make server-dry-run IMAGE_REFERENCE=…`, inspect `kubectl diff -f .rendered/workload.yaml` on railiance01, then deploy the reviewed manifest with `make deploy IMAGE_REFERENCE=…`. No existing workload or policy needs relaxation. Platform confirmation is tracked in WP-0004-T01. For the first installation, after admission, run `make bootstrap-namespace IMAGE_REFERENCE=…` before the full server dry run. Kubernetes does not persist a dry-run Namespace, so namespace-scoped objects cannot be server-validated until the namespace exists. This bootstrap dry-runs and diffs only the reviewed Namespace before creating it. The full deployment also diffs before applying. The `playwright-consumer` Role grants only pod discovery and port-forward. Bind an approved existing user/group through the identity/platform owner. This repo does not mint credentials or silently bind all authenticated users. Callers with existing authorized Kubernetes access can use the documented port-forward. The pod has no service-account token and no cluster permissions. Readiness performs the authenticated-protocol preflight over pod loopback. It requires a successful browser launch; liveness checks the process only. The pod uses non-root UID/GID 1000, read-only root, dropped capabilities and RuntimeDefault seccomp. Tini reaps orphaned browser processes. Chromium's OS sandbox is disabled for this trusted-target pilot; it is not approved for hostile websites or mutually untrusted tenants. The HTTP/CONNECT origin gate, private-address checks, blocked workers/WebSockets, per-run process/context and resource limits cover the documented application-level boundary, not browser-kernel exploits. ## Verify and recover After establishing the consumer tunnel, `make verify-live TRIAL_OUT=.local/live-N` must produce four PNGs, focus/keyboard assertions and a receipt. Check the live container image and imageID against the published digest, PVC binding, deny-all ingress and ready replica. Exercise wrong run token, deliberate UI failure, unreachable target, cancellation and service restart; a passing health endpoint alone is insufficient. After restart, accepted nonterminal runs become `interrupted`; completed runs remain retrievable until expiry. A client disconnect does not cancel an accepted job, so all runs have enforced deadlines. Supervisor cancellation closes the browser; after two seconds it kills the recorded worker/browser process groups. Service shutdown drains/cancels bounded work. Corrupt receipts cause startup to fail closed; restore or quarantine the affected transient run directory through the owner, without exposing capability hashes or screenshots in logs. Rollback: retain the previous immutable image reference and rendered revision, review its schema compatibility, then run `make rollback IMAGE_REFERENCE=…`. Verify the replacement's imageID and repeat the trial. For the first release, test recovery by reapplying the same verified digest; do not call that proof of cross-version rollback. Once a second release exists, exercise an actual digest change and return to the reviewed release. No automated rollback migrates or deletes the PVC. V1 receipts are JSON; future incompatible formats require an explicit migration/rollback decision. Upgrade Playwright and its base image together, update the lockfile, repeat the unit/browser/client tests and consumer pilot, then publish a new immutable image. The Python client checks protocol v1 and does not install Playwright. ## Published release Release [0.1.0](../releases/0.1.0.json) is published and pull-verified. Use its immutable reference for rendering; registry publication is no longer blocked. The cluster-owned ingress now allows a bounded 600-second HTTPS request body; see [cause, rollout and verification](evidence/2026-10-13-publication.md). For subsequent publications, fetch the remote index with `docker buildx imagetools inspect --raw ` and hash the exact returned bytes. Require the expected digest, then pull that immutable reference with `sudo k3s crictl pull ` on railiance01 and verify its recorded repo digest. A successful upload alone does not establish node pull access.