Close the last four headers, and say what the destructive tools refuse to do

This commit is contained in:
Gmer4Lfe
2026-08-25 16:51:14 -04:00
parent c6254f2342
commit f4adc31215
5 changed files with 153 additions and 8 deletions
+55
View File
@@ -28,6 +28,42 @@
# pointing at a directory the data is not in is worse than not having started. # pointing at a directory the data is not in is worse than not having started.
# #
# ============================================================================================== # ==============================================================================================
# OPERATIONAL MODEL
# ==============================================================================================
#
# Two halves, in order: move the files, then rewrite the conf keys that point at them. Doing it
# the other way round would leave every path variable naming a location nothing had reached yet,
# and any script that ran in between would create the old layout again underneath the new one.
#
# Idempotent. A path already under DATA_DIR is left alone, so a re-run after a partial migration
# finishes the job rather than moving things twice or failing on what is already done.
#
# One-time by intent, not by a marker file. There is no "already migrated" flag — the check is
# whether each individual path is already where it belongs, which is also what makes an
# interrupted run safe to repeat.
#
# ==============================================================================================
# DESIGN PRINCIPLES
# ==============================================================================================
#
# Existing keys are rewritten, which is why conf_upgrade cannot do this.
# conf_upgrade adds keys the template has and the installation does not, and never rewrites a
# value the operator already holds — correct for it, and exactly why it is the wrong tool here.
# STATE_DIR, BANDWIDTH_LOG, AI_INDEX_DB and two dozen more are existing keys whose values must
# change, or they would go on naming the old layout forever while the new directory variables
# sat beside them unused.
#
# Move, never copy-and-hope.
# The data being relocated is the only copy — statistics, histories, the AI index, arr caches.
# Everything is moved and the source is gone afterwards, so there is no second location that
# might still be written to by something that missed the change.
#
# The conf rewrite is the last thing, and the riskiest thing.
# Until it happens the installation still works from the old layout. That ordering means an
# abort partway through leaves a system that runs, rather than one whose paths point at
# nothing.
#
# ==============================================================================================
# OPERATIONAL SAFEGUARDS # OPERATIONAL SAFEGUARDS
# ============================================================================================== # ==============================================================================================
# #
@@ -49,6 +85,25 @@
# check costs nothing and the failure is silent otherwise. # check costs nothing and the failure is silent otherwise.
# #
# ============================================================================================== # ==============================================================================================
# CONFIGURATION
# ==============================================================================================
#
# This script reads conf to find the old locations and rewrites conf to record the new ones. It
# is the one script here whose purpose is to change these values rather than obey them.
#
# Read to locate what moves
# STATE_DIR, BANDWIDTH_LOG, AI_INDEX_DB, AI_MEMORY_FILE, AI_TOKEN_DB, ARR_CLEANUP_STATS,
# ARR_SYNC_BLOCKLIST, CORRUPTION_SCAN_STATE_FILE, LIDARR_CACHE_FILE, ZFS_REPORT_LOG and the
# rest of the per-script path keys — roughly two dozen in total.
#
# Written as the new roots
# DATA_DIR and the directories beneath it: DB_DIR, STATE_DIR, AI_DATA_DIR,
# CACHE_BACKUP_DIR, ARR_CACHE_BACKUP_DIR, CONF_CACHE_BACKUP_DIR, LOG_ARCHIVE_DIR.
#
# Every rewritten value is expressed as ${DB_DIR}/… rather than an absolute path, so a later
# storage-mode migration moves them again by changing one variable.
#
# ==============================================================================================
# RUNTIME MODES # RUNTIME MODES
# ============================================================================================== # ==============================================================================================
# #
+37 -1
View File
@@ -42,7 +42,43 @@
# my-Foo.xml routinely holds a container called something else. Matching on the filename # my-Foo.xml routinely holds a container called something else. Matching on the filename
# silently pushes the wrong template, or nothing at all. # silently pushes the wrong template, or nothing at all.
# #
# USAGE # OPERATIONAL SAFEGUARDS
# Only in NORMAL state. FALLBACK_STATE_FILE is read before anything is pushed or removed, and
# any other state refuses the action. A push during a live failover would deploy a second copy
# of a container the partner is currently running on our behalf; a remove would delete the one
# doing the covering.
#
# --status is exempt from that gate, because it only reports. Refusing to answer "what is
# deployed over there" during a failover would withhold the information precisely when it is
# most wanted.
#
# Every deploy is verified stopped, and a container that will not stay stopped is an error
# rather than a warning — see DESIGN PRINCIPLES. A second live instance against the same data
# is the failure this whole script exists inside.
#
# Push and remove are explicit modes with no default. Running the script with no flag does
# nothing; neither action can be reached by accident, and neither is a side effect of editing
# the tier list.
#
# --dry-run works in every mode and touches nothing on either host — no container is built,
# started, stopped or removed, and no template is written or deleted.
#
# Remove deletes the container's appdata on the partner as well. That is deliberate and is the
# most destructive thing here; the NORMAL-state gate above is what keeps it away from a
# partner that is mid-handback.
#
# CONFIGURATION
# master.conf
# FALLBACK_<HOST>_TIER1..N the covered container names — what --push deploys and --status
# reports on. This script reads that list; it never edits it.
#
# host*.conf
# FALLBACK_STATE_FILE overrides where fallback.sh's state is read from. Defaults to
# STATE_DIR/fallback_state.db. A missing file reads as NORMAL,
# which is the correct default on a host where fallback has never
# run.
#
# RUNTIME MODES
# coverage_deploy.sh --push deploy every covered container onto the partner (stopped) # coverage_deploy.sh --push deploy every covered container onto the partner (stopped)
# coverage_deploy.sh --remove stop, remove, and delete the pushed template on the partner # coverage_deploy.sh --remove stop, remove, and delete the pushed template on the partner
# coverage_deploy.sh --status report, per covered container, whether it exists there # coverage_deploy.sh --status report, per covered container, whether it exists there
+36
View File
@@ -20,6 +20,42 @@
# decision to notify is the exit code rather than this script parsing the text it just printed. # decision to notify is the exit code rather than this script parsing the text it just printed.
# #
# ============================================================================================== # ==============================================================================================
# DESIGN PRINCIPLES
# ==============================================================================================
#
# Silence is the normal output.
# A report that always says something is a report nobody reads. A perfect week prints nothing
# and notifies nothing, so anything that does appear in the Sunday report is worth the glance.
#
# The exit code is the decision, not the text.
# uptime_probe.php --report exits 1 when it has something to say and 0 when it does not. This
# script never parses the output it just printed to work out whether to notify — a report whose
# wording changed would otherwise silently stop notifying.
#
# It reads; it never probes.
# The measurements are already taken, once a minute, by Tools/uptime_probe.sh. Re-probing at
# report time would describe Sunday morning rather than the week being reported on.
#
# ==============================================================================================
# OPERATIONAL SAFEGUARDS
# ==============================================================================================
#
# Read-only. Reads the stored history and prints; records nothing, and cannot alter the data it
# is reporting on.
#
# UPTIME_PROBE_ENABLED gates the whole run — with the probe off there is no history worth
# reporting, and this says nothing rather than reporting an empty week as a perfect one.
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
#
# uptime_report.sh the weekly read. Silent when every domain was 100%.
#
# Called from COFFEE_REPORT_SCRIPTS; takes no arguments and has no other mode. For live figures
# or a per-domain table, use Tools/uptime_probe.sh --status.
#
# ==============================================================================================
# CONFIGURATION # CONFIGURATION
# ============================================================================================== # ==============================================================================================
# #
+6 -6
View File
@@ -5,6 +5,12 @@
// to reach it. Generated so the assistant can answer "how do I change X" with a path through // to reach it. Generated so the assistant can answer "how do I change X" with a path through
// the pages instead of an instruction to open master.conf. // the pages instead of an instruction to open master.conf.
// //
// OPERATIONAL MODEL
// Reads the section registries and the conf files, resolves each setting to the page and card
// that renders it, and writes the whole map in one pass. Nothing is merged with what is
// already there — the output is derived entirely from the registries, so a stale entry cannot
// survive a rebuild.
//
// DESIGN PRINCIPLES // DESIGN PRINCIPLES
// The assistant cannot see the UI any other way. // The assistant cannot see the UI any other way.
// The retrieval index reads git-tracked files. PHP body markup is not indexed and would be // The retrieval index reads git-tracked files. PHP body markup is not indexed and would be
@@ -26,12 +32,6 @@
// with no route through the UI is a real finding, and this map is the only thing that // with no route through the UI is a real finding, and this map is the only thing that
// would ever notice. // would ever notice.
// //
// OPERATIONAL MODEL
// Reads the section registries and the conf files, resolves each setting to the page and card
// that renders it, and writes the whole map in one pass. Nothing is merged with what is
// already there — the output is derived entirely from the registries, so a stale entry cannot
// survive a rebuild.
//
// OPERATIONAL SAFEGUARDS // OPERATIONAL SAFEGUARDS
// Writes exactly one file, pages/readme/ui-map.md, and nothing else. No conf is modified, no // Writes exactly one file, pages/readme/ui-map.md, and nothing else. No conf is modified, no
// page is touched, and the registries it reads are only read. // page is touched, and the registries it reads are only read.
+19 -1
View File
@@ -23,6 +23,7 @@
# rsync would then stop nothing before copying a live database. They are excluded by name and # rsync would then stop nothing before copying a live database. They are excluded by name and
# must stay excluded. # must stay excluded.
# #
# OPERATIONAL SAFEGUARDS
# A docker that cannot be read is not a docker with nothing in it. # A docker that cannot be read is not a docker with nothing in it.
# If `docker ps -a` fails, times out, or returns nothing on a host that is meant to run # If `docker ps -a` fails, times out, or returns nothing on a host that is meant to run
# containers, EVERY name looks missing and one run would strike the entire configuration. # containers, EVERY name looks missing and one run would strike the entire configuration.
@@ -34,7 +35,24 @@
# verified by sourcing the result in a subshell and confirming the key still parses as an # verified by sourcing the result in a subshell and confirming the key still parses as an
# array with exactly one fewer element. # array with exactly one fewer element.
# #
# USAGE # Each removal is its own verified rewrite.
# Several names can reach the limit in one run, and each is removed and re-verified
# independently rather than batched into a single edit. A rewrite that fails verification
# therefore costs that one entry, not every entry the run intended to prune.
#
# --dry-run records no strike. A dry run that advanced the counter would eventually prune
# through repetition alone, which is the opposite of what it is for.
#
# CONFIGURATION
# master.conf
# CONF_PRUNE_STRIKE_LIMIT consecutive runs a name must be missing before it is removed.
# Seeing the container again resets its strike to zero immediately,
# so a rebuild costs one strike at most.
#
# The keys this may prune are an explicit allow list in the script, deliberately not a conf
# value — see DESIGN PRINCIPLES for why a pattern is the wrong shape here.
#
# RUNTIME MODES
# conf_container_prune.sh strike, and prune anything at the limit # conf_container_prune.sh strike, and prune anything at the limit
# conf_container_prune.sh --dry-run report what would be struck and pruned, write nothing # conf_container_prune.sh --dry-run report what would be struck and pruned, write nothing
# conf_container_prune.sh --status show current strikes and stop # conf_container_prune.sh --status show current strikes and stop