Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
3.6 KiB
Phase 2 — Plan Mode Doc
Goal: produce a written, user-approved plan (RULE 0.5) that enumerates every apt change to the VM before any packet leaves the workstation. Verify criterion: user clicked "approve" on the plan; plan artefact exists at
<run-dir>/plan.md.
2.a — Synthesise the plan
Write <run-dir>/plan.md (where <run-dir> is ./.keisei/vm-provision/<timestamp>/) with
EXACTLY these sections — no more, no less:
# VM-Provision Plan — <timestamp>
## Intent
<INTENT one-line>
## Target
- Provider: <PROVIDER>
- Region: <REGION>
- Plan: <PLAN> (<arch>)
- VM name: kei-<env>-<role> # derived, ASK if ambiguous
## Access
- Admin user: <ADMIN_USER> # default keiadmin
- SSH port: <SSH_PORT> # default 22
- SSH pubkey: <path> # read from ~/.ssh/id_*.pub
## Ports to allow (ufw + provider cloud firewall)
<APP_PORTS — list>
## TLS
- Host: <TLS_HOST or none>
- Method: <HTTP-01 | DNS-01 | none>
## Hardening steps (harden-base.sh)
- apt update + upgrade
- install: ufw fail2ban unattended-upgrades needrestart auditd audispd-plugins
- write /etc/ssh/sshd_config.d/99-kei.conf
- ufw default-deny-in + rate-limit ssh + allow APP_PORTS
- fail2ban sshd jail
- auditd baseline ruleset (/etc/audit/rules.d/99-kei.rules)
- unattended-upgrades (AUTO reboot = FALSE)
## Verification (hard gate before handoff)
- ssh-check → exit 0
- firewall-diff (intent YAML vs live ufw) → exit 0
## Rollback
- `_primitives/provision-<provider>.sh destroy <VM_NAME>` — 1-command destroy.
- TF state: <path or "none — CLI-driven">
## Cost estimate
<Plan price per month from PROVIDER pricing page; CITE>
Cite the source for every price/region/plan detail. Numbers NOT cited = NO-GO per RULE 0.4.
2.b — Build the firewall-intent.yaml
Write <run-dir>/firewall-intent.yaml:
default:
incoming: deny
outgoing: allow
routed: deny
rules:
- port: <SSH_PORT>
proto: tcp
action: limit
from: any
comment: "ssh (rate-limited)"
# one entry per APP_PORTS:
- port: 443
proto: tcp
action: allow
from: any
This file is the source of truth the Phase 5 firewall-diff will
compare against live ufw status numbered output. Drift = Phase 5 fail.
2.c — AskUserQuestion (customise ports, TLS, admin name)
One AskUserQuestion call with up to 4 questions:
-
Admin user? (stored as
ADMIN_USER)keiadmin(default)- Custom (user types — only free-text in Phase 2)
-
SSH port? (stored as
SSH_PORT)22(default; simpler)2222(obscurity; not security, but reduces log noise)- Custom
-
Application ports to open? (multi-select, stored as
APP_PORTS)443/tcp— HTTPS (most apps)80/tcp— HTTP (only if ACME HTTP-01 or redirect)none— tunneled via Tailscale / private net only
-
TLS? (stored as
TLS_HOST+ method)- Caddy HTTP-01 (need 80/tcp + 443/tcp + DNS pointing to VM)
- Caddy DNS-01 (no port 80 needed; need DNS provider API token)
- None (app provides its own TLS or is behind a proxy)
2.d — Present the plan for approval
Render plan.md in chat. Ask ONE final AskUserQuestion:
Proceed with this plan?
- Approve → Phase 3.
- Iterate → loop back to 2.c with the user's change request.
- Abort → emit plan-only artefact and exit (
HANDOFF_TO=none).
2.e — Verify criterion
plan.mdwritten to<run-dir>/plan.md.firewall-intent.yamlwritten to<run-dir>/firewall-intent.yaml.- User clicked "Approve".
Emit:
Phase 2 done: plan @ <run-dir>/plan.md. <len(APP_PORTS)> ports, TLS=<method>.
Proceed to Phase 3.