mirror of
https://github.com/kuhyx/steam-backlog-enforcer.git
synced 2026-11-14 16:10:49 +01:00
kuhy 2026-11-11, multi-day research without re-setup. W1: once a window was used in a lock, the block's purge spares ~/.local/share/Steam (Librarian's install and local saves) for the rest of the lock; ~/steam, ~/.steam and the rest still go. The package stays removed, hosts/iptables are re-applied, and since the kept install could otherwise be launched without the package, every Steam game is killed on sight. A record that cannot be read also keeps the folder (an irreversible delete never rests on unknown state); the block itself stays fully applied. W2: the 48 h cap is gone; --until is bounded by the lock's end. An open window may be extended ONCE, to the lock end at most, never shortened, never reopened after it ended. The extension is a separate extended_until field beside until, so a daemon still on the previous code reads the original window instead of rejecting the record as corrupt (which would have purged the folder). Failure modes unchanged: missing/corrupt record = no window, and a corrupt one refuses a new window or extension. Checked: 3325 tests at 100% coverage; pylint 10/10 in parts; vmbox: extension accepted once, refused beyond the lock end, earlier or equal, second time and non-root; extended end honoured past the original end; at close the Steam dir and a save survive, ~/steam and ~/.steam go, a game started after close is killed; extension to exactly the lock end accepted. Not verified on the host. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzxdWWzuCEg1m87jpKyRrw
66 lines
2.7 KiB
Python
66 lines
2.7 KiB
Python
"""Which commands stay usable under each lock.
|
|
|
|
A leaf module (no imports) so the CLI dispatcher in ``main._shared`` and the
|
|
root daemon's control socket consult ONE table: a lock the daemon enforced
|
|
differently from the CLI would be a way around it for anyone who can reach
|
|
the socket. ``main._shared`` cannot be imported by the daemon directly --
|
|
``main`` imports the enforce loop, which starts the control socket.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
# Commands that remain usable while the manual pick lock is active.
|
|
# Principle: only what is needed to release the lock (done/check) or
|
|
# that cannot change the game assignment (status, enforce, setup, serve).
|
|
_MANUAL_LOCK_EXEMPT_COMMANDS = frozenset(
|
|
{
|
|
"done",
|
|
"check",
|
|
"status",
|
|
"enforce",
|
|
"setup",
|
|
"serve",
|
|
"abandon-pick",
|
|
# Allowed so a second game can be locked in alongside the first; the
|
|
# cap inside cmd_pick_manual is what stops this being a way out.
|
|
"pick-manual",
|
|
# The daily gaming budget is orthogonal to which game is assigned, and
|
|
# gaming-unblock is a recovery hatch for a stuck bind mount - locking
|
|
# it behind a manual pick would leave Steam masked with no way back.
|
|
"gaming-status",
|
|
"gaming-unblock",
|
|
"gaming-reset",
|
|
# Reconciles the block's domain list; cannot shorten or end a lock.
|
|
"total-block-refresh",
|
|
# Records the one bounded research window (see _research_window); the
|
|
# lock itself and its end date stay untouched.
|
|
"total-block-research",
|
|
}
|
|
)
|
|
|
|
# Commands that remain usable while a total gaming block is active. Far
|
|
# stricter than _MANUAL_LOCK_EXEMPT_COMMANDS: no done/pick/reset/
|
|
# add-exception - nothing here shortens or ends a total block. The one bounded
|
|
# opening is total-block-research: root-only, a single window per lock that
|
|
# only Librarian may use (up to the lock's end, extendable once), recorded in a
|
|
# root-only state directory; the daemon re-applies the full block when it
|
|
# expires. The lock and its end date are never touched.
|
|
#
|
|
# gaming-unblock is included because a playtime bind mount makes the total
|
|
# block's own `pacman -R steam` fail EBUSY - it must stay reachable exactly
|
|
# when the two collide. gaming-reset is NOT included: it shortens enforcement.
|
|
# serve changes nothing itself (every job it starts is lock-checked on its own)
|
|
# and refusing it took the web UI down for the whole block, crash-looping its
|
|
# systemd unit, the first time anything restarted it.
|
|
_TOTAL_BLOCK_EXEMPT_COMMANDS = frozenset(
|
|
{
|
|
"status",
|
|
"enforce",
|
|
"gaming-status",
|
|
"gaming-unblock",
|
|
"serve",
|
|
"total-block-refresh",
|
|
"total-block-research",
|
|
}
|
|
)
|