Second review round asked for three things. Two adopted, one measured and declined.
ADOPTED
- Removing the Terminal plugin is recommended in writing as the right move (it is the
largest attack surface, and macros already provide command execution). Left installed
because it is the operator's plugin - removing a tool unilaterally is not the agent's
call. Documented how: rename to Terminal.disabled (readDirectory() skips *.disabled).
- Automatic password rotation and the deploy-key-read-only suggestion are recorded as
operator decisions with their trade-offs.
DECLINED, WITH EVIDENCE
- "php.ini should disable exec/shell_exec/passthru/system by default." Measured, this
would break the editor's core function, so it cannot be a default:
components/codegit/* -> Common::safe_execute 31 call sites (every git op)
components/macro/* -> Common::raw_execute 1 call site
common.php raw_execute -> function_exists("system") / function_exists("exec")
Every commit, push and fetch from the editor runs through exec/system. It stays a
deliberate exposure lever (S-7), not a default.
CORRECTED
- Review claimed the redacted patch file had a syntax error. Verified on the guest with
php83 -l: "No syntax errors detected". The placeholder is a plain string literal inside
a double-quoted PHP string. That finding was wrong, and is recorded as such rather than
"fixed" to satisfy a false positive.
Also fixed the section ordering in the doc.
atheos-blog-lxc
Provisioning for a browser-based code editor (Atheos) in an Alpine LXC, wired to Gitea, with the
armistace/blog repository cloned and ready to edit.
Built with the AI-DLC workflow — the full process trail (requirements, design, units, decisions,
audit log) lives in aidlc-docs/.
What this is
A small, single-purpose Proxmox container that puts an editor in your browser so you can write blog posts and commit them to Gitea — without VS Code, without a cloud IDE, and without a build toolchain.
| Guest | Proxmox LXC 136 on node scotty |
| OS | Alpine 3.23.2 (unprivileged, OpenRC) |
| URL | http://192.168.178.57/ — LAN only |
| Stack | nginx → php-fpm 8.3 (unix socket) → Atheos IDE |
| Sizes | 2 vCPU · 1 GB RAM · 20 GB rootfs · onboot=1 |
| Editor | Atheos — PHP, no database, real vim keybindings |
| Project | armistace/blog cloned to /var/www/atheos/workspace/blog |
| Git auth | per-repository deploy key (write-enabled) |
What it deliberately is NOT
- Not VS Code / code-server / Coder. Atheos is an independent, lightweight PHP editor.
- Not a build environment. The blog is a Pelican site, but building/publishing happens in your
existing pipeline. There is intentionally no Python, no pelican, no
makehere — the presence of Python would be a defect (verified by acceptance criterion AC-8). - Not internet-facing. No reverse proxy host, no DNS record, no port-forward is created.
Quick start
If you just want to use it:
- Open http://192.168.178.57/ and complete the Atheos first-run installer.
ssh root@192.168.178.57, then set your git identity — see RUNBOOK.md STEP 1. Git will not let you commit until you do, and that is deliberate: the agent does not create your identity.- Add the deploy key to
armistace/blogand switch the remote to SSH — RUNBOOK.md STEP 2 & 3.
👉 The full operational guide is RUNBOOK.md. Start at STEP 1.
Repo layout
.
├── README.md this file
├── RUNBOOK.md ← operational guide; START AT STEP 1
├── docs/
│ ├── security-notes.md credential model + hardening TODOs if ever exposed
│ ├── resiliency-notes.md what a non-PoC deployment would need
│ └── writer-branch-workflow.md how writing/publishing works from the editor
├── files/
│ ├── atheos.conf nginx vhost (install to /etc/nginx/http.d/atheos.conf)
│ ├── ssh-config ~atheos/.ssh/config (the gitea-blog alias)
│ └── macros.db.php installed copy of the Atheos writer macros
├── scripts/
│ ├── provision.sh rebuild the whole guest from scratch
│ └── update-atheos.sh update Atheos to latest upstream + re-pin
└── aidlc-docs/ AI-DLC process trail (requirements → design → units → audit)
Rebuilding from scratch
The guest holds nothing unique — the blog's source of truth is Gitea — so a rebuild is cheap:
# on scotty (192.168.178.69), as root
pct destroy 136
sh scripts/provision.sh
scripts/provision.sh is written to be re-runnable and reproduces the documented build exactly,
including the pinned Atheos commit and its verified tarball checksum.
Design decisions worth knowing
| # | Decision | Why |
|---|---|---|
| D1 | No git identity is configured by the agent. You set it (RUNBOOK STEP 1). | You own the armistace identity; setting it programmatically would impersonate you and blur attribution (requirement FR-11). |
| D2 | Atheos is pinned to a commit SHA, with update-atheos.sh to deliberately move it. |
Atheos has no releases; a moving branch is not reproducible. |
| D3 | nginx :80, web root /var/www/atheos, php-fpm over a unix socket. |
Smallest network surface — nothing extra listens on the LAN. |
| D6 | Per-repository deploy key, not a personal access token. | A Gitea PAT's scopes are route groups matched against your whole account, so a stolen token reaches every repo you can write. A deploy key reaches exactly one. |
Full rationale, including the alternatives that were rejected and the verification behind them, is in
aidlc-docs/design-artifacts/application-design.md
and docs/security-notes.md.
Security at a glance
- Writing happens on a branch, never on
master. The editor commits to a long-livedatheos-writerbranch and you merge via PR in Gitea — seedocs/writer-branch-workflow.md. ⚠️ This only holds if branch protection is enabled onarmistace/blog'smaster— without it the deploy key could force-push master directly. Confirm with thebranch_protectionsAPI call in that document. - Git auth: deploy key scoped to
armistace/blog, private key mode600, owned by the php-fpm user. - The SSH alias uses
IdentitiesOnly yes, so no other key is ever offered. - The web app runs as a dedicated unprivileged user (
atheos), which also owns the workspace. - ⚠️ Accepted risk: Atheos runs as a web app with shell-exec reach, so a compromise can use the
deploy key to write
blog. That is the intended floor (one repo, one branch) rather than the ceiling. Keep branch protection onblog'smaster. - If this is ever exposed to the wider web, work through
docs/security-notes.md§2 first.
Provenance
| Built | 2026-09-29 |
| AI-DLC stages executed | Workspace Detection, Requirements, Workflow Planning, Application Design, Units Generation, Infrastructure Design, Code Generation, Build & Test |
| Stages skipped (with rationale) | Reverse Engineering, User Stories, Functional Design, NFR Requirements, NFR Design — see aidlc-docs/plans/execution-plan.md |
| Atheos pin | f90cd1806dbe0e25673a77e27390e8b1a240c3f6 (build 611), tarball sha256 03ebcb1479b59f1898b5fa50808b181750b42211698f7f7b4042cf2514d78b20 |