# /lib/upgrade/keep.d/shater-core — what sysupgrade and LuCI "Backup" must carry
# out of /etc/shater.
#
# HOW THIS FILE IS READ. /sbin/sysupgrade (base-files, list_static_conffiles):
#
#	find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' \
#		/etc/sysupgrade.conf /lib/upgrade/keep.d/* 2>/dev/null) \
#		\( -type f -o -type l \) $filter 2>/dev/null
#
# so blank lines and lines starting with '#' are stripped, and every other line is
# a path handed to `find`: a directory is recursed, a path that does not exist is
# silently skipped (hence a trailing '/' for the two directories, and no need to
# guard for a fresh install that has neither). The result is tarred and, on a real
# sysupgrade, HELD IN RAM across the flash — which is why this is a per-file
# decision and not simply "/etc/shater/".
#
# WHY IT EXISTS. Everything the product knows besides /etc/config/shater lives in
# /etc/shater, and nothing shipped a keep.d entry for it. A "keep settings"
# sysupgrade, or a LuCI backup restored onto a new router, therefore produced a
# box whose config looked complete and whose node inventory was EMPTY — silently.
#
# /etc/config/shater is NOT listed here: it is declared in
# Package/shater-core/conffiles, and sysupgrade backs CHANGED conffiles up on its
# own (list_changed_conffiles). Listing it again would work, but it would claim
# ownership of a mechanism that already covers it.

# THE NODE INVENTORY. Subscription-fetched nodes deliberately live OUTSIDE UCI
# (shater/model/subcache.go) — one JSON file per subscription. Without them the
# restored box has groups and rules that reference nodes which do not exist, so no
# tunnel comes up, and the only repair is `sub update`, which needs the internet
# the tunnel was supposed to be providing. Indented JSON: a few hundred KiB even
# for a several-hundred-node subscription.
/etc/shater/subs/

# THE BOOT-ARMOR ARM TOKEN. Its PRESENCE is what lets /etc/init.d/shater-armor
# (START=21) load the fail-closed plane before fw4's `lan -> wan ACCEPT` is the
# only rule on the box. Without it the first boot after a restore forwards LAN to
# WAN in the clear until the daemon has built an engine. One small nft script.
/etc/shater/boot.nft

# COMPILED LIST ARTIFACTS (.srs). Losing these fails SILENTLY in the worst
# direction: a missing LOCAL rule-set is left out of the generated config and the
# engine starts perfectly happily with the filtering simply gone
# (shater/generate/ruleset.go, compiledListRuleSet). "It will re-download itself"
# is NOT true for them either — a compiled url list is rebuilt only by the next
# generate, and nothing schedules one (see the note in /etc/init.d/shater-cron
# about `ruleset update`). Cheap to keep: compiled .srs is 3-6% of the source
# text (~80 KiB for a 150k-domain list), under a 4 MiB soft cap.
/etc/shater/lists/

# ALERT DE-DUPLICATION STATE. A few hundred bytes mapping subscription -> when its
# expiry warning last fired. Without it every subscription already announced
# announces itself again on the restored box — the exact re-alert storm the file
# was created to prevent (shater/alert/expiry.go).
/etc/shater/alert-state.json

# DELIBERATELY NOT KEPT. Each of these is history or cache, and the backup is
# built in RAM:
#
#   /etc/shater/stats.db     Traffic/query HISTORY, not configuration. Bounded
#                            only by globals.stats_disk_limit_mb, whose default is
#                            64 MB and whose 0 means UNLIMITED — one file able to
#                            outweigh everything else here by two orders of
#                            magnitude, and the only entry whose loss costs the
#                            operator nothing but a chart.
#   /etc/shater/cache.db     sing-box's own cache (8 MiB cap, deleted above it).
#                            Rebuilt on demand by design, and a stale rule-set
#                            cache carried onto a different box is worse than no
#                            cache at all.
#   /etc/shater/shaterd.log  A log (capped by globals.log_max_kb). A restored box
#                            wants its own log, and this one carries the DNS query
#                            history of the box it came from — which is not
#                            something to move into an archive a person then puts
#                            somewhere else.
#
# ON SECRECY, since this archive routinely ends up in cloud storage: subs/*.json
# carries every node's credentials (UUID/password/keys). That is not a NEW
# exposure — /etc/config/shater already carries the subscription URLs and every
# manual node's credentials, and it is already in the backup as a conffile — but a
# shater backup is a secret-bearing file and should be treated as one.
