STAGING-STATE recorded mechcomp.service as delivered at deploy/mechcomp.service on 11 SEP. The unit was real; the directory was not. It existed only on CT 100, so the repository claimed to hold something it did not, and the only way to answer a question about the service was to read the container. The nginx vhost had never been committed at all. Both imported verbatim as they ran on 12 SEP, with their host checksums proven equal at import. A first commit of a configuration file records reality, not intentions -- every later improvement is then a diff against a known-good starting point rather than a rewrite nobody can check. mechcomp.env is deliberately absent. It is the one file that is supposed to differ between instances, it is root:mechcomp 0640 because a deployment's bindings belong to the deployment, and a committed copy would create a second source of truth for exactly the wrong file. ENVIRONMENT.md documents the keys. Certificates and keys likewise. IDENTITY-CONTRACT.md is the boundary between this application and the membership system, and the only document here written to be read by someone who does not work on this repository. Two systems that must agree on an interface need it written once, somewhere both can point at. The compiler does not authenticate anyone; it is told. CT 101 decides, against the membership system, and sets X-Kane-Auth-Email and X-Kane-Auth-Method. They map onto Author.email and Author.method, which already exist and are tested. The parser's refusal to recover `verified` from text was built for this: a record read back is always self-declared, because a file cannot attest to its own verification. The decision belongs at CT 101 and never at wg-pk. The hub carries twenty peers and is estate infrastructure this project does not own, so authorisation there would make every future adjustment an escalation and would teach a shared transport about one project's membership roll. CT 101 already shares the service bridge with CT 100 and CT 102. One gated prefix, /m/. nginx gets one location block, written once. Gating a new endpoint afterwards is choosing a URL in Python -- no proxy change, no escalation. That cheapness makes the placement of the line reversible rather than structural. Today it sits at export: the catalogue and composer are open, and what requires membership is producing an artifact whose design record names an author. Section 6 is the part most likely to erode and is written hardest. The compiler must never learn what a building is, what a membership level is, or that group names exist -- including as a configuration value, which is how the leak arrives by the side door. The test is that the membership system can rename every level and replace its storage without a line of this repository being read. Section 9 deletes the ACL from the roadmap rather than deferring it. The compiler will not have a user table, a login form or a session. Recorded openly rather than assumed: the service is world-reachable and unauthenticated, /m/ is not yet gated, and STL export will therefore ship open. Same posture the whole service already has. The earlier justification -- "acceptable for a development name" -- was wrong and is corrected separately: dev.mechcomp.kane-il.us is production, dev abbreviates Mechanical Compiler Developers, and the name is on printed material. The inbound header strip depends on none of this and should land on its own. It costs one directive and removes a forgery that becomes possible the moment the headers mean anything.
67 lines
3.0 KiB
Markdown
67 lines
3.0 KiB
Markdown
# deploy/
|
|
|
|
The configuration that makes this application a running service, under version
|
|
control.
|
|
|
|
## Why this directory exists
|
|
|
|
`STAGING-STATE.md` recorded `mechcomp.service` as delivered at
|
|
`deploy/mechcomp.service` on 2026-09-11. The unit was real; the directory was
|
|
not. The file existed only on CT 100, so the repository claimed to hold
|
|
something it did not, and the only way to answer a question about the service
|
|
was to read the container.
|
|
|
|
That is the failure mode this directory closes. The repository is the single
|
|
source of truth. Where these files and the hosts disagree, the disagreement is
|
|
a finding — and the direction of travel is from here outward, not from the host
|
|
back.
|
|
|
|
## What is here
|
|
|
|
| File | Lives on | Installed at |
|
|
|---|---|---|
|
|
| `mechcomp.service` | CT 100 | `/etc/systemd/system/mechcomp.service` |
|
|
| `nginx/mechanical-compiler.conf` | CT 101 | `/etc/nginx/sites-available/mechanical-compiler`, symlinked from `sites-enabled/` |
|
|
|
|
Both are imported **verbatim** as they ran on 2026-09-12. The first commit of a
|
|
configuration file records reality, not intentions; any improvement is a later
|
|
diff that can be read against a known-good starting point.
|
|
|
|
## What is deliberately not here
|
|
|
|
**`/etc/mechcomp/mechcomp.env`.** It is the deployment's own answers —
|
|
`MECHCOMP_BIND`, `MECHCOMP_PORT`, `MECHCOMP_BASE_URL` — and it is
|
|
`root:mechcomp 0640` because a deployment's bindings belong to the deployment.
|
|
A committed copy would be a second source of truth for the one file that is
|
|
supposed to differ between instances. `ENVIRONMENT.md` documents the keys; the
|
|
values stay on the host.
|
|
|
|
**Certificates and keys.** `/etc/ssl/mechcomp/` on CT 101 holds a leaf signed by
|
|
the local staging CA. Keys are never committed.
|
|
|
|
## Two facts about the nginx vhost worth knowing before editing it
|
|
|
|
**CT 101 does not know the public name.** Its `server_name` is
|
|
`mechanical-compiler.dev.infra`, a hosts-file name resolvable on `srv-b`, CT 100
|
|
and CT 101 only, and its certificate is signed by the local staging CA. Public
|
|
TLS terminates at `wg-pk`, which proxies inward over the WireGuard tunnel to a
|
|
DNAT on `srv-b`. `dev.mechcomp.kane-il.us` appears nowhere in this file and does
|
|
not need to.
|
|
|
|
**Both server blocks are `default_server`.** CT 101 answers whatever `Host`
|
|
arrives, which is why the public name works without being named. That is
|
|
acceptable because `10.20.0.0/24` is a portless service bridge with LAN traffic
|
|
dropped, so the only thing that can reach port 443 is the tunnel — but it means
|
|
`server_name` is documentation here rather than a filter, and adding a second
|
|
site to CT 101 will require that to change.
|
|
|
|
## Applying a change
|
|
|
|
Infrastructure mode (`PROCESS.md` §2). One command group, read-only first, a
|
|
rollback copy of the file before editing, `nginx -t` before `reload`, and the
|
|
change proven from outside the container rather than from within it.
|
|
|
|
A change to either file lands in the repository first and is copied outward.
|
|
Editing on the host and back-porting reintroduces exactly the drift this
|
|
directory was created to end.
|