Conformance updates.
This commit is contained in:
+49
-2
@@ -4,9 +4,9 @@ Specification for a Mechanical Compiler instance.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Revision | 5.2 (2026-08-17) |
|
||||
| Revision | 5.3 (2026-08-18) |
|
||||
| Supersedes | Revisions 1 through 4 |
|
||||
| Basis | Revision 4, reconciled against the proven staging build, then work orders 002 and 003 |
|
||||
| Basis | Revision 4, reconciled against the proven staging build, work orders 002 and 003, and container standardisation |
|
||||
| Scope | **Host-agnostic.** Applies to any instance. |
|
||||
| Instance state | `STAGING-STATE.md`, and later `PRODUCTION-STATE.md` |
|
||||
| Failure evidence | `FAILURES.md` |
|
||||
@@ -769,6 +769,44 @@ wrong form reported a pass against containers that were not running.
|
||||
|
||||
---
|
||||
|
||||
## 14a. Conformance
|
||||
|
||||
**REQ** — An instance carries an executable **baseline check**: read-only,
|
||||
runnable at any time, exiting non-zero when any container diverges from the
|
||||
standard.
|
||||
|
||||
**REQ** — **A property not checked by it is not part of the standard.** This is
|
||||
what makes conformance terminate. Without it, divergence is discovered one
|
||||
property at a time whenever something behaves oddly, and the process never
|
||||
finishes because nothing states what "the same" means. A property that must be
|
||||
uniform belongs in the check, not in an operator's memory.
|
||||
|
||||
**REQ (F-031)** — The check must examine **the thing being standardised**. An
|
||||
assertion derived from a related observation is not a check. Postfix
|
||||
configuration on the host says what the host does; it says nothing about the
|
||||
containers, and a standard asserted that way was wrong on two of three.
|
||||
|
||||
**REQ** — Each failure names the failure-log entry that established the
|
||||
requirement, so the reason survives the person who found it.
|
||||
|
||||
**REQ (F-032)** — Host-level requirements belong to the host, not to whichever
|
||||
project discovered them first. Where several projects share a host, the check
|
||||
is host-level and covers every container regardless of owner. Two projects on
|
||||
this host independently rediscovered the same two defects before this was done.
|
||||
|
||||
### Mail
|
||||
|
||||
**REQ** — **Containers do not originate mail.** Only the host does, and only its
|
||||
own operational alerts. A container with a mail agent installed but SMTP egress
|
||||
blocked is worse than either alone: it queues indefinitely and delivers nothing,
|
||||
while appearing configured.
|
||||
|
||||
Application mail — participant notification and similar — is a separate design
|
||||
problem with its own delivery and inbound requirements. It is not solved by
|
||||
leaving a partially configured agent in a container.
|
||||
|
||||
---
|
||||
|
||||
## 15. Acceptance gates
|
||||
|
||||
**REQ** — Five independent gates. Revision 4 ran them as one list, which meant
|
||||
@@ -812,6 +850,15 @@ active. Reference toolchain image reproduces `ddd0f154…`. Scaffolding removed.
|
||||
|
||||
Undefined pending a strategy decision.
|
||||
|
||||
**REQ** — **Conformance is a precondition, not a companion.** Backup work does
|
||||
not begin until the baseline check (§14a) exits zero, and the check forms part
|
||||
of restore verification.
|
||||
|
||||
A backup of an unverified configuration does not preserve a system; it
|
||||
preserves a state of confusion, and a restore returns that state faithfully.
|
||||
This was not hypothetical: a backup taken before 2026-08-18 would have restored
|
||||
two containers that queue mail forever (F-031).
|
||||
|
||||
### Gate 5 — Production automation
|
||||
|
||||
Idempotent scripts derived from a proven manual procedure. Firewall posture
|
||||
|
||||
+99
-1
@@ -6,7 +6,7 @@ Compiler environment.
|
||||
| | |
|
||||
|---|---|
|
||||
| Scope | All instances. Staging entries are marked `srv-b`. |
|
||||
| Updated | 2026-08-17, after work order 003 |
|
||||
| Updated | 2026-08-18, after repository seeding and container standardisation |
|
||||
| Method | `PROCESS.md` section 7 |
|
||||
| Rule | Append only. Never edit an entry except to add a `Resolution` line. |
|
||||
| Numbering | Sequential, never reused. See §0 on the renumbering. |
|
||||
@@ -634,6 +634,100 @@ device class.
|
||||
|
||||
---
|
||||
|
||||
### F-029 — pip cache written into the repository working tree
|
||||
CT 100. Repository seeding.
|
||||
|
||||
**Observed:** `git add -A` staged 465 files where 28 were expected. The extra
|
||||
437 were `.cache/` — pip's download cache.
|
||||
**Cause:** **Proven.** The service user's home is the install directory, so
|
||||
`$HOME/.cache` **is** `/var/www/mechcomp/.cache`. `make deps` wrote there.
|
||||
**Correction:** `.cache/`, `.local/`, `.ssh/`, `.gitconfig` and `.lesshst`
|
||||
added to `.gitignore`; the cache unstaged before committing.
|
||||
**Consequence:** Setting the service user's home to `install_dir` is correct
|
||||
and matches YunoHost convention, but it means **any tool writing to `$HOME`
|
||||
writes into the working tree**. `.gitignore` must anticipate that from the
|
||||
first commit.
|
||||
|
||||
Method note: reading the staged list by eye showed nothing wrong. Counting it
|
||||
and grouping by top-level directory found the problem immediately. **Verify by
|
||||
counting, not by scanning** — a long correct-looking list is exactly where an
|
||||
extra 437 files hide.
|
||||
|
||||
---
|
||||
|
||||
### F-030 — a network command in a work order could hang indefinitely
|
||||
`srv-b`. Repository seeding.
|
||||
|
||||
**Observed:** An SSH authentication test was issued with neither
|
||||
`ConnectTimeout` nor `BatchMode`. Gitea's SSH is on port 42022, so the attempt
|
||||
on 22 hung and the operator had to interrupt it.
|
||||
**Cause:** **Proven.** Missing timeout options, and an incorrect assumption
|
||||
about the port.
|
||||
**Correction:** Re-issued with `-o ConnectTimeout=10 -o BatchMode=yes -p 42022`,
|
||||
after a `timeout`-wrapped reachability probe that could not hang.
|
||||
**Consequence:** **Every network command in a work order carries an explicit
|
||||
timeout.** A command that can hang strands the session, and the operator cannot
|
||||
tell a hang from slow progress. Reachability is probed with `timeout` before any
|
||||
client is invoked.
|
||||
|
||||
Also recorded, having been got wrong twice: Gitea **deploy tokens** are
|
||||
account-level under user Settings, not repository settings. Repository-scoped
|
||||
credentials are **deploy keys**. SSH here is on **42022**, so remotes need
|
||||
`ssh://git@host:42022/owner/repo.git` — the `git@host:path` shorthand cannot
|
||||
carry a port.
|
||||
|
||||
---
|
||||
|
||||
### F-031 — a standard was asserted from a check that never examined the thing
|
||||
CT 100, CT 101, CT 102. Container standardisation.
|
||||
|
||||
**Observed:** The architect stated that CT 100 and CT 101 had no mail agent, and
|
||||
standardised CT 102 by purging Postfix to match. The first run of
|
||||
`ct-baseline.sh` reported a mail agent installed on **both** CT 100 and CT 101.
|
||||
CT 102 — the container just "corrected" — was the only one conforming.
|
||||
|
||||
**Cause:** **Proven.** The earlier assertion came from inspecting Postfix
|
||||
configuration and `/etc/aliases` **on `srv-b`**, during work order 002. That
|
||||
established what the host does. It said nothing about the containers, and the
|
||||
containers were never examined.
|
||||
|
||||
**Correction:** Postfix purged from CT 100 and CT 101. Queues were checked first
|
||||
and both were empty, so nothing was lost. Re-run: 62 passed, 0 failed.
|
||||
|
||||
**Consequence:** **A standard asserted from a proxy observation is not a
|
||||
standard.** The check must examine the thing being standardised. This is the
|
||||
same class as F-027 — a result that cannot distinguish the case it claims to
|
||||
test — but reached through inference rather than through shell semantics.
|
||||
|
||||
It is also the justification for `ct-baseline.sh` existing. Divergence had been
|
||||
discovered by asking, one property at a time, whenever something behaved oddly.
|
||||
That does not terminate: every check finds a new difference because nothing
|
||||
states what "the same" means. The script is that statement, and it disagreed
|
||||
with the architect on its first run.
|
||||
|
||||
---
|
||||
|
||||
### F-032 — the same host defects were discovered independently by two projects
|
||||
`srv-b`. Cross-project.
|
||||
|
||||
**Observed:** Kane Fabric's `INFRASTRUCTURE_BASELINE.md`, written independently,
|
||||
records `nesting=1,keyctl=1` against `226/NAMESPACE` systemd failures, and that
|
||||
minimal Debian CTs lack a generated `en_US.UTF-8`. These are F-003 and F-004,
|
||||
found again on the same host, in different words, at a different time.
|
||||
**Cause:** **Proven.** Both are properties of the Proxmox/Debian 12 host, not of
|
||||
either application. Neither project's documentation was visible to the other.
|
||||
**Correction:** None required — both projects reached the correct conclusion.
|
||||
**Consequence:** **Host-level requirements belong to the host, not to whichever
|
||||
project discovered them first.** `ct-baseline.sh` encodes them once and checks
|
||||
every container on `srv-b` regardless of owner, so the third project does not
|
||||
have to discover them a third time.
|
||||
|
||||
Note that `keyctl=1` is required **only where Docker runs**. CT 101 was proven
|
||||
to work with `nesting=1` alone (F-003). Kane Fabric's baseline currently
|
||||
specifies both; if CT 102 runs no containers, `keyctl` can be dropped.
|
||||
|
||||
---
|
||||
|
||||
## Open, not closed
|
||||
|
||||
| # | Status |
|
||||
@@ -649,5 +743,9 @@ device class.
|
||||
| F-026 | **Corrected** 2026-08-17. Reboot persistence proven. |
|
||||
| F-027 | **Corrected** 2026-08-17. Applies retroactively to F-018's proofs. |
|
||||
| F-028 | **Corrected** 2026-08-17. |
|
||||
| F-029 | **Corrected** 2026-08-18. |
|
||||
| F-030 | **Corrected** 2026-08-18. |
|
||||
| F-031 | **Corrected** 2026-08-18. Root cause of `ct-baseline.sh`. |
|
||||
| F-032 | **Closed** 2026-08-18. No correction required; encoded in `ct-baseline.sh`. |
|
||||
|
||||
Everything else is closed with a proven cause and a proven correction.
|
||||
|
||||
@@ -356,6 +356,28 @@ needs a directory to exist, create it in the same group.
|
||||
|
||||
---
|
||||
|
||||
## 9a. The baseline check
|
||||
|
||||
`ct-baseline.sh` is the executable definition of the container standard on this
|
||||
host. Read-only, runnable at any time, exits non-zero on divergence.
|
||||
|
||||
Run it:
|
||||
|
||||
- before starting work on a container;
|
||||
- after any change to a container or to host firewall rules;
|
||||
- after any host reboot;
|
||||
- before considering backup work (see `ENVIRONMENT.md` §15 gate 4).
|
||||
|
||||
**A property not checked by it is not part of the standard.** If something
|
||||
should be uniform across containers, add it to the script. If it should not,
|
||||
leave it out and stop worrying about the difference. That is the whole point:
|
||||
it converts an endless comparison into a pass or a fail.
|
||||
|
||||
It covers containers belonging to more than one project, and encodes host
|
||||
requirements neither project owns alone. Treat it as host property.
|
||||
|
||||
---
|
||||
|
||||
## 10. Current mode
|
||||
|
||||
**Infrastructure: complete and accepted.** Host, containers, network isolation,
|
||||
@@ -366,6 +388,12 @@ bastion access, TLS, reverse proxy, mail alerting, disk monitoring. See
|
||||
more than an afternoon; the documents are in Gitea. This changes when
|
||||
`artifacts/` stops being empty.
|
||||
|
||||
**Repository seeded** at `c7e32d8`: reference implementation, frozen oracle,
|
||||
pinned toolchain, test harness. Dependencies installed in CT 100, oracle
|
||||
verified in-container, `3 passed, 236 skipped`.
|
||||
|
||||
**Container baseline established.** All three containers on `srv-b` conform.
|
||||
|
||||
**Development: starting.** First work item is the Shapely port —
|
||||
`pytest -n auto` green against the 123 frozen cases.
|
||||
|
||||
|
||||
+35
-1
@@ -4,7 +4,7 @@ What the Mechanical Compiler is for, and the order in which it gets built.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Updated | 2026-08-17 |
|
||||
| Updated | 2026-08-18 |
|
||||
| Companions | `PROCESS.md`, `ENVIRONMENT.md`, `STAGING-STATE.md`, `FAILURES.md` |
|
||||
|
||||
---
|
||||
@@ -133,6 +133,11 @@ a new call into the same machinery, not a new machine.
|
||||
monitored, four test alerts received, serial numbers recorded, reboot-proven.
|
||||
- **Container SMTP egress blocked, 2026-08-17.** The project-local half of F-025
|
||||
is corrected; the estate question about `wg-pk` client trust remains open.
|
||||
- **Repository seeded, 2026-08-18.** Reference implementation, frozen oracle,
|
||||
pinned toolchain and test harness at `c7e32d8`. Dependencies installed, oracle
|
||||
verified in-container, `3 passed, 236 skipped`.
|
||||
- **Container baseline established, 2026-08-18.** All three containers on
|
||||
`srv-b` conform, asserted by an executable check rather than by inspection.
|
||||
|
||||
### Next — the port
|
||||
|
||||
@@ -172,6 +177,24 @@ getting their own generators.
|
||||
|
||||
---
|
||||
|
||||
## 4a. Parallel project
|
||||
|
||||
**Kane Fabric** — a separate project on the same host, and the platform on
|
||||
which SASE, HOA Diagnostics, the Mechanical Compiler and other SASE-consuming
|
||||
projects are implemented.
|
||||
|
||||
It is recorded here so its existence is known, not because it creates work.
|
||||
Kane Fabric owns geographic state; the Mechanical Compiler owns member
|
||||
geometry, qualification and workflow state. Both sets of documents describe a
|
||||
future interface between them; **neither defines it, and that is deliberate.**
|
||||
Part I §6 holds that use cases precede interface proliferation, and no use case
|
||||
crosses the boundary yet.
|
||||
|
||||
The contract becomes real work when a compiled member first needs to be sited
|
||||
somewhere. It will be cheaper to define then, against a concrete artifact.
|
||||
|
||||
---
|
||||
|
||||
## 5. Staging to production
|
||||
|
||||
`srv-b` is standalone and will remain so. Promotion is export/restore, not
|
||||
@@ -264,3 +287,14 @@ on whether it makes distributed manufacturing capacity legible.
|
||||
have observed the positive case.
|
||||
12. **A component surviving its own restart is not proven to survive the
|
||||
host's.** Different machinery; assert against the one that matters (F-026).
|
||||
13. **A standard must be executable.** If conformance cannot be asserted by
|
||||
running something, it is not a standard but a recollection, and it will
|
||||
drift. A property not checked is not part of the standard (F-031).
|
||||
14. **Check the thing, not something related to it.** An assertion inferred
|
||||
from an adjacent observation is not evidence, however reasonable the
|
||||
inference (F-031).
|
||||
15. **Verify by counting, not by scanning.** A long, correct-looking list is
|
||||
exactly where an unexpected 437 files hide (F-029).
|
||||
16. **Conformance precedes backup.** Backing up an unverified configuration
|
||||
preserves the confusion along with the data, and a restore returns it
|
||||
faithfully.
|
||||
|
||||
+108
-11
@@ -4,7 +4,7 @@ Live state of the Mechanical Compiler staging instance on `srv-b`.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Updated | 2026-08-17, after work order 003 (monitoring, SMTP egress) |
|
||||
| Updated | 2026-08-18, after repository seeding and container standardisation |
|
||||
| Instance | Staging / development |
|
||||
| Specification | `ENVIRONMENT.md` revision 5 |
|
||||
| Failure log | `FAILURES.md` |
|
||||
@@ -329,7 +329,10 @@ work. None is a defect.
|
||||
the four members, so drive age is a known quantity rather than an
|
||||
assumption. `smartctl -d cciss,N -A /dev/sda`. Read-only, one command.
|
||||
- [ ] **Backup infrastructure, entirely.** Postponed 2026-08-16 because the
|
||||
strategy may change: `vzdump` job, archive sizing, retention, free-space
|
||||
strategy may change, and reaffirmed 2026-08-18 on stronger grounds: a
|
||||
backup of an unverified configuration restores the confusion along with
|
||||
the data. **Entry condition: `ct-baseline.sh` exits 0.** Scope when
|
||||
resumed: `vzdump` job, archive sizing, retention, free-space
|
||||
guard, host-side pull, `mechcomp-backup`, backup alerting, gold media,
|
||||
3+ TB redundancy.
|
||||
|
||||
@@ -348,6 +351,91 @@ hold the only instance with no monitoring, no alerting and no backup.
|
||||
|
||||
---
|
||||
|
||||
## 3b. Container baseline
|
||||
|
||||
**`ct-baseline.sh` is the definition of "standard configuration" on this host.**
|
||||
It changes nothing, runs any time, and exits 0 only when every container
|
||||
conforms.
|
||||
|
||||
```
|
||||
last run 2026-08-18
|
||||
result 62 passed, 0 failed, 3 informational
|
||||
scope srv-b, CT 100, CT 101, CT 102
|
||||
```
|
||||
|
||||
**A property not checked by that script is not part of the standard.** That is
|
||||
what makes it terminate. Divergence used to be discovered by asking, one
|
||||
property at a time, whenever something behaved oddly — which never finishes,
|
||||
because nothing stated what "the same" meant. If a property should be uniform,
|
||||
it belongs in the script rather than in someone's memory.
|
||||
|
||||
What it asserts, per container: `onboot`, unprivileged, `nesting=1`, a single
|
||||
interface on the service bridge, systemd `running` with zero failed units, one
|
||||
interface stanza, Debian 12, timezone, **generated** locale, `curl`,
|
||||
`ca-certificates`, `openssh-server`, sshd active, admin account with
|
||||
`authorized_keys` at `0600`, **no mail agent**, SMTP egress blocked, LAN
|
||||
gateway unreachable. Host-level: systemd health, both firewall rules, `smartd`
|
||||
device count, bastion key.
|
||||
|
||||
Each failure cites the failure entry that established the requirement, so the
|
||||
reason survives the person.
|
||||
|
||||
### The mail standard
|
||||
|
||||
**Containers do not send mail.** Only `srv-b` does, and only its own alerts,
|
||||
through `[10.110.0.1]:25`. A container with a mail agent installed but SMTP
|
||||
egress blocked is the worst case: it queues forever and delivers nothing.
|
||||
|
||||
CT 100 and CT 101 were in exactly that state until 2026-08-18 (F-031).
|
||||
|
||||
### Ownership
|
||||
|
||||
The script checks containers belonging to two projects and encodes host
|
||||
requirements neither owns alone (F-032). It is **host-level**, not Mechanical
|
||||
Compiler property. Suggested home: `/usr/local/sbin/ct-baseline.sh` on `srv-b`,
|
||||
with the canonical copy outside this repository.
|
||||
|
||||
### Relationship to backup
|
||||
|
||||
**Conformance is a precondition for backup, not a companion to it.** A backup
|
||||
taken before 2026-08-18 would have preserved two containers that queue mail
|
||||
forever, and a restore would have faithfully returned them to that state.
|
||||
|
||||
Backing up an unverified configuration does not preserve a system; it preserves
|
||||
a state of confusion. The entry condition for backup work is `ct-baseline.sh`
|
||||
exiting 0 — and it becomes part of restore verification.
|
||||
|
||||
---
|
||||
|
||||
## 3a. Parallel project on this host
|
||||
|
||||
**Kane Fabric** is a separate project sharing `srv-b`. It is where SASE, HOA
|
||||
Diagnostics, the Mechanical Compiler and other SASE-consuming projects are
|
||||
implemented.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Repository | `github.com/git64bit/Kane-Fabric` |
|
||||
| Container | CT 102 `kane-fabric` |
|
||||
| Address | `10.20.0.12/24` on `vmbr1`, gateway `10.20.0.1` |
|
||||
| Ownership | Separate project. Not Mechanical Compiler infrastructure. |
|
||||
| Baseline | Conforms as of 2026-08-18, verified by `ct-baseline.sh` |
|
||||
|
||||
Recorded here for two operational reasons only.
|
||||
|
||||
**It shares the service network.** CT 102 sits on `vmbr1` alongside CT 100 and
|
||||
CT 101, so host-level rules scoped to `10.20.0.0/24` apply to it. In particular
|
||||
it **inherits the SMTP egress block** (F-025) — if Kane Fabric ever needs to
|
||||
send mail, that will present as a Postfix failure with a non-obvious cause.
|
||||
|
||||
**Host resources are shared, not pooled.** Neither project consumes or
|
||||
repurposes the other's containers. Any integration is through an explicit
|
||||
contract, not through co-location on `srv-b`.
|
||||
|
||||
No interface between the two projects exists today, and none is assumed.
|
||||
|
||||
---
|
||||
|
||||
## 4. Access model
|
||||
|
||||
Confirmed: no workstation access from the home LAN is required.
|
||||
@@ -374,25 +462,31 @@ entire address space.
|
||||
Repository state:
|
||||
|
||||
```
|
||||
HEAD e85c4f4e5bab9a4f032230c99aa6784ace4c80e2
|
||||
top level .git LICENSE README.md venv
|
||||
git status ?? venv/
|
||||
absent requirements-base.txt, requirements-cad.txt, service units
|
||||
HEAD c7e32d8e0772d89d1117bab7ff08d61e5b2a497e
|
||||
top level .gitignore LICENSE Makefile README.md docs/ fixtures/ legacy/
|
||||
pyproject.toml requirements-*.txt src/ tests/ tools/ venv/
|
||||
remote ssh://git@gitea.barternetwork.us:42022/TheRON/mechanical-compiler.git
|
||||
deploy key srv-b-ct100, read/write
|
||||
venv Python 3.11.2, shapely 2.1.2, cadquery 2.8.0, mechcomp editable
|
||||
tests 3 passed, 236 skipped
|
||||
oracle ddd0f154... verified in-container
|
||||
absent the Shapely port itself
|
||||
```
|
||||
|
||||
None of the following can be honestly completed, and none may be fabricated by
|
||||
provisioning:
|
||||
|
||||
- [ ] Dependency install from committed manifests
|
||||
- [x] ~~Dependency install from committed manifests~~ — done 2026-08-18
|
||||
- [ ] `mechcomp.service`, `mechcomp-worker.service`
|
||||
- [ ] Reference toolchain image `mechcomp/reference-toolchain:8.0.0`
|
||||
- [ ] Fixture reproduction against `ddd0f154...`
|
||||
- [ ] Application-runtime acceptance
|
||||
- [ ] Replacing the placeholder with the real service
|
||||
|
||||
**Architect decision:** `venv/` belongs in `.gitignore` — it is a legitimate
|
||||
artifact inside `install_dir` per YunoHost convention, it simply should not be
|
||||
tracked. Applied with the first application commit.
|
||||
**Applied 2026-08-18:** `venv/` is in `.gitignore`, along with `.cache/`,
|
||||
`.local/`, `.ssh/`, `.gitconfig` and `.lesshst` — the service user's home is
|
||||
`install_dir`, so anything writing to `$HOME` writes into the working tree
|
||||
(F-029).
|
||||
|
||||
The Shapely port gates all of the above.
|
||||
|
||||
@@ -425,4 +519,7 @@ All three need CIVICVS.
|
||||
| Why did delivery fail downstream? | `mx1` relay trust. Proven and corrected (F-023). |
|
||||
| Where does Postfix log on this host? | journald. No `rsyslog`, no `/var/log/mail.log` (F-024). |
|
||||
| Should container SMTP egress be blocked? | Yes. Implemented and reboot-proven (F-025 project-local half). |
|
||||
| Do the containers autostart? | Yes, `onboot: 1` on both, proven by host reboot (F-026). |
|
||||
| Do the containers autostart? | Yes, `onboot: 1` on all three, proven by host reboot (F-026). |
|
||||
| How do files reach a container? | Upload to `/root/incoming` on `srv-b`, then `pct push` / `pct exec`. See `PROCESS.md`. |
|
||||
| How does CT 100 push to Gitea? | Deploy key `srv-b-ct100`, SSH on port **42022**, read/write. |
|
||||
| Do containers send mail? | **No.** Only `srv-b` does. See section 3b. |
|
||||
|
||||
Reference in New Issue
Block a user