docs: correct facts and the Docker firewall claims #27

Merged
claudiomaradonna merged 6 commits from docs/audit-round into main 2026-10-08 08:44:30 +02:00
Collaborator

Why

A documentation audit, with every finding checked against the code, found wrong facts, duplicated text and breaks of the documentation rules across README, CONTRIBUTING, docs/ and the role READMEs. The most serious was a security claim: the ai-stack and warden READMEs, the migration doc and group_vars/ai_mainframes.yml said the castrum nftables table restricts who reaches the ports Docker publishes for LocalAI, LocalAGI and LocalRecall. It does not.

What changed

  • docs/ARCHITECTURE.md#firewall now explains why: with Docker's default publishing, a packet for a published port is rewritten to the container's address before the input hook sees it, and a containerized host's table has no forward chain. The bind address therefore decides who reaches a published port. Every other mention links there. warden's own port stays restricted, because warden listens on the host.
  • docs/MIGRATION-AI-STACK.md: the operator chooses whether to publish LocalRecall during the harvest, and the rollback removes the host from ai_mainframes first. The LocalAI copy steps now live only here, and the storage layout only in the ai-stack README.
  • Top-level docs: wrong facts corrected. The ownership table gains the migration doc. One-off steps that their commits' bodies already carry are removed.
  • Role READMEs: the Example Playbook and License sections are removed (the examples broke the one-tenant rule, and the licence said GPLv3). Facts now match the roles' defaults, repeated firewall text is replaced by links, and history and site-specific wording are gone.
  • No behaviour change: no task, template, handler or variable value differs, and the YAML edits are comments only. Fixing the bypass is out of scope.

Verification

  • make check after every commit: passed.
  • Every changed YAML file parses to the same value as on main, and ansible-inventory --list is identical for every tenant before and after.
  • Every relative link and anchor in the tracked docs resolves.
  • Not run: make test and make verify (no podman in the agent sandbox); no molecule scenario is affected.

Risks and follow-ups

  • The Docker bypass on ai_mainframes hosts needs its own fix.
  • group_vars/brick_servers.yml applies one cluster's rpcbind setting and brick port range to every tenant.
  • Template comments in ai-stack's compose.yml.j2 and env.j2 and hardening-basic's 99-protect-links.conf still carry stale wording; changing them re-renders files on hosts.
## Why A documentation audit, with every finding checked against the code, found wrong facts, duplicated text and breaks of the documentation rules across README, CONTRIBUTING, `docs/` and the role READMEs. The most serious was a security claim: the ai-stack and warden READMEs, the migration doc and `group_vars/ai_mainframes.yml` said the castrum nftables table restricts who reaches the ports Docker publishes for LocalAI, LocalAGI and LocalRecall. It does not. ## What changed - `docs/ARCHITECTURE.md#firewall` now explains why: with Docker's default publishing, a packet for a published port is rewritten to the container's address before the input hook sees it, and a containerized host's table has no forward chain. The bind address therefore decides who reaches a published port. Every other mention links there. warden's own port stays restricted, because warden listens on the host. - `docs/MIGRATION-AI-STACK.md`: the operator chooses whether to publish LocalRecall during the harvest, and the rollback removes the host from `ai_mainframes` first. The LocalAI copy steps now live only here, and the storage layout only in the ai-stack README. - Top-level docs: wrong facts corrected. The ownership table gains the migration doc. One-off steps that their commits' bodies already carry are removed. - Role READMEs: the Example Playbook and License sections are removed (the examples broke the one-tenant rule, and the licence said GPLv3). Facts now match the roles' defaults, repeated firewall text is replaced by links, and history and site-specific wording are gone. - No behaviour change: no task, template, handler or variable value differs, and the YAML edits are comments only. Fixing the bypass is out of scope. ## Verification - `make check` after every commit: passed. - Every changed YAML file parses to the same value as on main, and `ansible-inventory --list` is identical for every tenant before and after. - Every relative link and anchor in the tracked docs resolves. - Not run: `make test` and `make verify` (no podman in the agent sandbox); no molecule scenario is affected. ## Risks and follow-ups - The Docker bypass on `ai_mainframes` hosts needs its own fix. - `group_vars/brick_servers.yml` applies one cluster's rpcbind setting and brick port range to every tenant. - Template comments in ai-stack's `compose.yml.j2` and `env.j2` and hardening-basic's `99-protect-links.conf` still carry stale wording; changing them re-renders files on hosts.
The ai-stack and warden READMEs, the migration-facing group file and the
port-file comments said the castrum table decides who reaches the ports
Docker publishes for LocalAI, LocalAGI and LocalRecall. It does not:
Docker's default publishing DNATs the packet before the input hook and
forwards it to the container, and a containerized host's table carries
no forward chain, so those rules never match. The bind address decides.

ARCHITECTURE.md#firewall now owns that fact; ai-stack, warden,
ADVANCED_USAGE's group table, group_vars/ai_mainframes.yml and the
ai-stack and warden port-file and defaults comments state their own
consequence and link to it. warden's own port stays restricted: warden
listens on the host. Comments only in the YAML files: each parses to the
same value as on main, and ansible-inventory lists every tenant
identically before and after.

The bypass itself is left for a separate change.
The LocalAI storage copy (install -d, docker cp, one host's backend
digest) lived in both the ai-stack README and MIGRATION-AI-STACK.md.
The README now keeps the layout, its modes and the DS4 cache, and links
to the migration for the stopped-container copy; the migration links
back for the layout and the cache, and checks backend digests generally
instead of one host's.

The migration doc also stated wrong facts: LocalRecall does publish a
port by default, and leaving ai_mainframes drops the ai-stack chain at
the next firewall-apply run while the containers keep running. Its
references to an untracked sub-project, "this change", "this estate"
and LocalAI v4.9 are gone, and so are the README's prose copies of its
own variable bullets. ai_stack_ports now says it does not follow the
publish ports.

The compose and env templates keep their "pre-v4.9" and "sub-project"
comments: they render onto hosts.
ARCHITECTURE: only a service role waits to be switched on; scripts/
holds the Windows bootstrap alone and tests/molecule/ joins the map;
the firewall paragraph and fact-cache note lose their iptables-era
wording; the OS section names scan-share's own dispatch; per-host flags
are more than warden's; ai-stack publishes its ports rather than opening
them.

ADVANCED_USAGE: flags set per host point at the catalogue; changing a
service's ports defers to each role README and the firewall rules; the
Windows play names scan-share. CONTRIBUTING: docker-engine also has no
scenario, and os-updates and sysadmin-tools have none; every new role
gets a catalogue row; the ownership table gains the migration doc; the
agents section points at AGENTS.md without restating it.

The root host_vars and core.hooksPath one-off steps leave the standing
docs: their commits' bodies (4447250, 2a06ab0) already carry them, and
the root_host_vars gate names any file left behind. Counts and history
told as reasons for a rule go too.
Every role README loses its "Example Playbook" and "License" sections:
the examples ran `-i inventory/example.yml`, against the one-tenant
rule, and repeated what ADVANCED_USAGE owns; the licence said GPLv3
where the root README and meta say GPL-3.0-or-later.

Facts now match the roles: docker-engine installs python3-requests,
auditd states its defaults and that it does not reload auditd, warden's
cross-reference points at a paragraph that exists, sysadmin-tools hides
no account by default, windows-hardening-basic needs only
ansible.windows, and hardening-basic gives its sshd and mmap defaults,
a profile table and the derived modprobe list. ai-stack and warden say
that switching them off leaves the stack or the service running.

The port-only roles keep one paragraph each on the firewall and link to
ARCHITECTURE#firewall and firewall-apply's peer addresses instead of
restating fail-closed and convergence; firewall-apply links to the rule
format instead of copying it. swarm's site-specific rp_filter section
becomes one fact in hardening-basic. History, item counts and the
playbook warning ADVANCED_USAGE owns leave the READMEs; the opening
sentences read as the catalogue does.
The migration now has the operator choose LocalRecall's publish in the
harvest, since it defaults to 8082 and then answers whoever reaches the
bind address; the verify bullet says each case in its own sentence.
Step 2 notes each backend's digest so step 3 has a value to check, a
stack castrum converged before the LocalAI mounts gets its one-line
order, and the rollback leaves ai_mainframes as its first step instead
of only describing it.

The ai-stack README says why its 0700 paths are private and keeps the
TTFT check the split dropped; ADVANCED_USAGE's ai_mainframes row no
longer misparses; ARCHITECTURE limits "restricts nothing" to the
published port, since warden's rule still covers 9090. hardening-basic
gives rp_filter its own heading, which swarm links to, and states the
forwarding defaults; gluster and swarm link to the firewall rules
instead of restating them; collection counts, a CONTRIBUTING clause
restating AGENTS.md and a site claim about Italian PCs go.
The review found the same false firewall implication outside the files
the branch had touched: traefik-routes said its verify GET proves the
stack host's firewall admits the proxy, and edge_routers' row and group
file called membership the source list an AI mainframe admits. Both now
say what the GET proves and link the Docker bypass.

Site wording and history leave neighbouring comments and READMEs:
"on this estate", "the canary had", "See the design spec.", "today's
behaviour", "the approved design"/"v1", and the BitLocker note's history.
The ai-stack molecule converge comment now matches verify.yml, which
asserts LocalRecall's publish. Comments only in YAML: every changed file
parses to the same value as on main, and ansible-inventory lists every
tenant identically.

group_vars/brick_servers.yml still describes one cluster in the shared
layer; moving its values is a behaviour change left to the owner.
claudiomaradonna deleted branch docs/audit-round 2026-10-08 08:44:35 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
claudiomaradonna/castrum!27
No description provided.