--- id: MAS-WP-0007 type: workplan title: "Operate MAS as a switchable facility" domain: communication repo: mail-address-semantics status: finished owner: claude topic_slug: coulomb-social created: "2026-10-18" updated: "2026-11-01" origin: residual origin_ref: MAS-WP-0003 state_hub_workstream_id: "03751989-8ed1-5a3f-bcc3-71aef8b375a6" --- # Operate MAS as a switchable facility Residual of MAS-WP-0003. Namespace `mas` is the MAS facility for `mas.coulomb.social`, with replies through Scaleway TEM capped at 300. It stays. The 2026-10-19 retirement backlog is withdrawn. **Founder decision (2026-11-01, `4d38ed47-8ab1-419e-839c-92921f7eeef1`): keep it, and make it switchable.** Do not delete the namespace, revoke the TEM key, remove DNS, or tear down the OpenBao role. Operate the existing facility so mail and the statute can be turned off and back on without discarding evidence, credentials, or the public address. The 2026-10-19 redeploy record stays part of this workplan: - 2026-10-19: redeployed `mas-mx` and `mas-statute` with image `mas-live:v0.2-a95f848`, side-loaded into k3s containerd. The previous image was `v0.2-a45f1a1`. The evidence (`events.jsonl`, 36 events, and `tickets.sqlite3`) was backed up before the rollout and is intact on the PVC. Checked: `mas discover` valid; the profile's relay control; TEM relay with null-sender discard; OpenDKIM/OpenDMARC running; the ticket service runs with `--max-sent 300 --require-dmarc-pass`; empty queue; relaying to the public IP refused with 554 (`x@other`, `x!y@other`, `a@mas...@other`). - 2026-10-19: redeployed with image `mas-live:v0.2-480e69a`: MAS-WP-0012's one outbound path, and v0.2 final. The evidence was backed up first. The legacy outbox was imported once into `tickets-outbox.sqlite3`: 9 rows, 4 sent, so 4 of 300 count toward the cap. The ticket service runs with `--max-sent 300 --require-dmarc-pass --email-held-duration-max 7d --emails-held-storage-max 100MB`. Checked: statute valid, 36 evidence events intact, TEM relay with null-sender discard, empty queue, relaying refused with 554. The migration was first tested in the image against a copy of the live volume. ## What the facility is Durable parts stay when the facility is off. The power switch must not delete or edit them: - namespace `mas` - PVC `mas-evidence` (`events.jsonl`, `tickets.sqlite3`, the outbox DB) - Services `mas-smtp` (LoadBalancer) and `mas-statute` - Ingress `mas-statute` and its TLS secret - ExternalSecret `mas-relay`, its SecretStore, and ServiceAccount - OpenBao role `external-secrets-mas-tem-relay`, policy `workload-kv-read-mas-tem-relay`, and KV path `platform/suppliers/scaleway/mas-tem-relay` - DNS for `mas.coulomb.social`, the TEM domain, and the TEM API key Switchable parts are the two Deployments, `mas-mx` and `mas-statute`. Off means both `replicas: 0`. The LoadBalancer keeps its address and has no ready pods, so port 25 takes no mail, and the statute ingress has no backend. On means both `replicas: 1` and ready, on the same PVC and image. Known limits, unchanged by this workplan: one replica, a side-loaded image, snakeoil SMTP TLS, and the 300-reply cap. A later decision can raise any of those. This workplan does not roll a new image and does not turn the live facility off. ## Retire the teardown ```task id: MAS-WP-0007-T01 status: cancel priority: medium state_hub_task_id: "e0a65837-1769-5129-b258-fbaeb3047f62" ``` Cancelled 2026-11-01. The founder withdrew retirement. Do not export for teardown, delete namespace `mas`, ask ops-mason to remove the OpenBao role, revoke the Scaleway TEM key, remove DNS, or delete the side-loaded images. ## Record the facility contract ```task id: MAS-WP-0007-T02 status: done priority: high state_hub_task_id: "18d8898e-52c9-572d-aa7c-014fb1f7751e" ``` Update the current-direction docs so they describe a kept, switchable facility. `SCOPE.md` and INTENT.md phase-2 criterion 5 stop saying the live environment is retired. `deploy/railiance/` states the durable and switchable parts and the limits above. The release-unit note stops calling this something other than the operated facility. Historical workplans and `history/` stay as they were. Done 2026-11-01. `SCOPE.md`, INTENT.md criterion 5, `deploy/railiance/README.md`, the manifest header, and `registry/release-units/mas.yaml` describe the switchable facility. The 300-reply cap, side-loaded image, and snakeoil SMTP TLS are recorded as limits. ## Add the power switch ```task id: MAS-WP-0007-T03 status: done priority: high state_hub_task_id: "78a11c89-7cda-5ff7-bd0a-b7958b6c9fe7" ``` Add an operator command, `on`, `off`, and `status`, that scales only `deploy/mas-mx` and `deploy/mas-statute`. It records the desired power on namespace `mas` as annotation `mas.coulomb.social/power`. The supported apply path reads that annotation and renders `replicas: 0` when the facility is off, so a later apply does not turn it back on. Missing annotation means on, which matches the manifest and the live facility. The command must not delete the namespace, volume, secrets, services, or ingress. On the cluster, record `power=on` to match the running facility. Do not scale it to 0 and do not roll a new image. Done 2026-11-01. `deploy/railiance/power.sh` and `apply.sh`, with `facility.py` doing the render. Live: `power.sh on` with the railiance01 admin kubeconfig annotated namespace `mas` as `power=on`, scaled both Deployments to 1, and both were already ready. Pod start times stayed `mas-mx` 2026-10-21T22:18:00Z and `mas-statute` 2026-10-19T11:36:30Z. `power.sh status` shows `power=on`, both Deployments 1/1, and endpoints for `mas-smtp` and `mas-statute`. No new image. ## Test the switch offline ```task id: MAS-WP-0007-T04 status: done priority: high state_hub_task_id: "3f458be1-a8c8-5b05-96e8-851294e36d60" ``` Test the render without a cluster. Power `off` sets both Deployment replicas to 0 and leaves the Service, PVC, Ingress, and ExternalSecret in place. Power `on` leaves `replicas: 1`. The image placeholder is replaced. The operator command has no delete of those durable objects. Done 2026-11-01. `tests/test_facility_power.py`: 4 passed.