Merge in a checklist-style "provisioning script safety" section, adapted
from wshobson/agents' bash-defensive-patterns skill (fetched directly
from GitHub, MIT licensed) rather than trusted from its catalog summary.
Covers: shell-choice caution (#!/bin/bash isn't guaranteed on FreeBSD;
bash is a package at /usr/local/bin/bash, not base), a contextual
error-handling philosophy instead of a blanket `set -Eeuo pipefail`,
trap-based cleanup/logging for scripts interrupted mid-jail-creation
(without auto-rollback, which can worsen the known destroy/create IP
churn issue), jail-name/IP input validation before destructive `bastille`
commands, and FreeBSD `mktemp`/`sed -i`/`date` syntax differences from
GNU. Deliberately dropped the upstream's interactive `rm -rI` cleanup
pattern (wrong for unattended SSH automation) and did not import
retry/locking/ShellCheck-gate advice that wasn't actually present in the
real upstream files. Cross-references remote-shell-quoting-safety instead
of duplicating its nested-shell-quoting content.
Also documents the /usr/local/bastille vs /www/bastille bastille_prefix
split already present across this fleet's hosts (gringo/staging vs
granja), which the new script-safety guidance assumes readers already
know not to hardcode.
Full worked patterns and code examples live in the new
references/script-safety.md; SKILL.md keeps the load-bearing summary.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- server-fleet-map: add gringo row
- bastille-jail-provisioning: elevate default-deny-outbound to the standard
for every new jail; reference gringo's live pf.conf
- modded-app-update-pattern: new skill, fork/rebase pattern for locally
patched apps; uses tailnetatlas on gringo as the concrete example
- dependency-vuln-scanning: new skill, npm audit / pip-audit / osv-scanner
cadence for deployments and monthly thereafter
Real incident on the staging host: nat on $ext_if from <subnet> to any ->
($ext_if) silently failed to rewrite the source IP when that IP was
already aliased on the same interface, breaking all outbound jail traffic
with no error anywhere - just clean timeouts. Fixed by using an explicit
target IP instead of the interface macro. Cost real debugging time to
trace from "WordPress admin hangs after a PHP upgrade" back to this.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two real gotchas from today's goddy->gringo Laravel migration: every jail
on an NPM-fronted host needs a dedicated listen port (8000+last-octet),
not just the shared port 80, or NPM cutover silently can't reach it even
though every direct/Host-header test passes. Separately, zsh ties a
variable literally named `path` to $PATH itself - overwriting it broke
every subsequent command in a config-editing script with no clear error.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New skill wordpress-plugin-staging-verification: use the persistent
staging-1 jail (real-world plugin set left active) instead of a
disposable clean-room jail, full verification checklist, and the
cosmetic-proc_open-error-vs-real-fatal distinction.
Extended bastille-jail-provisioning: bastille0-loopback-missing gotcha
(pass the interface explicitly), IP-alias-can-silently-fail-after-
recreate gotcha, host-reverse-proxy-vs-jail-IP curl mixup, Valkey as
part of the stock stack (correct FreeBSD package name, ACL auth
requirement).
Extended wordpress-plugin-conventions: drop-in source files
(object-cache.php/advanced-cache.php logic) must be excluded from any
glob-based plugin autoloader, or they redeclare WP core's own
wp_cache_*() functions and fatal -- real bug found and fixed live during
iWP Cache's first staging activation attempt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
WordPress plugin rebrand/conventions/remote-CLI patterns, Gitea release
workflow, bastille jail provisioning, remote shell quoting safety, server
fleet map, delegate brief writing, and verification discipline -- all
derived from real incidents this session, plus two skills adapted (MIT
license, attributed) from obra/superpowers and andrej-karpathy-skills.