docs: publish archive control design set

This commit is contained in:
2026-07-23 13:39:09 +00:00
parent 6ca94a546e
commit 7e295cff3a
12 changed files with 1960 additions and 7 deletions
+177
View File
@@ -0,0 +1,177 @@
# Telegram UX
Archive Control adds a separate handler/module to the existing bot. Existing
commands and conversations retain their current behavior.
## Authorization and shared state
The handler accepts private-chat users through the existing `@username`
allowlist for compatibility. A configured numeric Telegram user ID may pin an
entry; when pinned, both the ID and current allowlist rule must match. This
mitigates username reassignment while permitting a staged migration.
Jobs, placements, events, queues, and routes are shared administrative state and
store no initiating-user identity. UI session state records only what is needed
to resume the conversation/view and expires after 24 hours by default.
## Entry point and navigation
The existing “Archive/Unarchive Resources” entry opens one message:
```text
What do you want to do?
[ Archive ] [ Unarchive ]
[ Evict Cache ] [ Job Status ]
```
All subsequent pages edit this message. `Cancel` closes the active selection
flow. `Back` returns one level while retaining validated filters/selections.
Callback payloads contain opaque session/action IDs, not resource names or
paths, and are validated against persisted session revision and expiry.
## Archive and unarchive flow
### 1. Select source resource
Control queries relevant online nodes on demand. It groups identical resource
and selection replicas into one display choice while showing distinct
selections separately. The list is stable-sorted and paged:
```text
Which cached resource do you want to archive? (page 1/3)
filters: `documentary`, `2025`
1. `10.0 GB` Resource A — cache-1
2. `840 MB` Resource B — cache-2
[ 1 ] [ 2 ]
[ Prev ] [ Next ]
[ Remove filters ] [ Cancel ]
```
Size is selected-complete logical content, not total torrent size. New messages
add literal, case-insensitive filters and narrow the current results; Remove
filters resets the chain. If no item remains, the message explains whether no
source is online, no selected-complete data exists, or filters eliminated all
results.
### 2. Select source replica and target
If multiple identical-selection replicas exist, control may choose a healthy
source automatically using deterministic availability/route/free-space rules;
otherwise it lists the source replicas. One eligible target is selected
automatically; multiple targets are paged. Offline targets are not offered.
A resource already on a target is still eligible when the requested selection
has an unverified delta. The UI says that it will extend an existing placement.
### 3. Confirm or choose one entry
Before showing confirmation, control obtains fresh full trees from source and
target and calculates the transfer delta.
```text
Archive Resource A from cache-1 to archive-2?
Requested: 7 files, 10.0 GB
Already verified there: 2 files, 3.1 GB
Will transfer: 5 files, 6.9 GB
[ Confirm ]
[ Choose one entry… ] [ Cancel ]
```
Choose one entry opens a paged/filterable tree. Only source-selected-complete
files/directories are enabled. Selecting a directory expands it to descendant
file indices, returns to a freshly recomputed confirmation, and clearly states
the chosen subtree. The protocol supports multiple entries from v1, but the
initial UI exposes one.
Confirmation uses a persisted, single-use nonce bound to session revision,
operation, resource, source, target, selection, fingerprints, and placement
generation. Double taps or stale callbacks cannot create a second job.
## Evict Cache flow
The first page lists current cache placements. Selecting one triggers fresh
queries to the cache and relevant online archive nodes. Each row/confirmation
shows coverage:
- enabled when the union of verified archives covers every selected cache file;
- disabled with missing file count/size and unavailable archive explanation
otherwise.
There is no override button. Confirmation creates a durable three-step
eviction job; it never clears an archive placement or a transfer history row.
## Job Status
Status pages show live and retained jobs with operation, resource, endpoints,
state, current-step and overall percentages, bytes/s where meaningful, and
failure reason.
Routine edits are coalesced to one per five seconds by default. Step changes,
stall transitions, failures, commit, cleanup-required, and terminal states edit
immediately subject to Telegram rate-limit backoff.
State symbols:
| Symbol | Meaning |
| --- | --- |
| 🟡 | queued/not started |
| 🔵 | active, waiting, or stalled |
| 🟠 | committed but cleanup required |
| 🟢 | succeeded |
| 🔴 | failed or cancelled |
Transfer jobs display five numbered steps: Source Stage/HardLink, Syncthing,
Target Merge/Copy, QB Verification, and Staging Cleanup. Route setup and
preflight are named, unnumbered pre-steps. Eviction displays Verify Archive
Coverage, QB Remove Entry, and Safe File Unlink.
A stalled job keeps its last overall percentage:
```text
🔵 Archive: Resource A — cache-1 → archive-2
[2/5 Syncthing: 63.42%, overall 32.68%, stalled, last progress 38m ago]
Waiting indefinitely; retry occurs when progress/service connectivity returns.
```
Failure messages include stable phase and clear reason, while hiding secrets
and host-only paths.
## Clear and remove behavior
`Clear Finished` hides only green successful jobs and leaves a 30-day default
tombstone. Orange Cleanup Required is not clearable as finished.
`Remove One` first replaces buttons with current-page job numbers and Cancel.
A successful green row hides immediately. A queued job confirmation deletes
only its queue record/reservation. An active, failed-with-residue, or cancelling
job requires a second confirmation and begins/continues compensation; its row
remains until safe cleanup is known. A committed job can only retry staging
cleanup. No history action deletes a cache placement; that is exclusively Evict
Cache.
## Restart and rate-limit behavior
Sessions, pages, filters, chosen entries, confirmation bindings, and live status
views are persisted. On bot restart, active status messages resume updates when
the stored chat/message remains editable; otherwise users can reopen Job Status
without losing job state. “message is not modified” is treated as success.
Telegram retry-after values pause/coalesce edits without affecting orchestration.
## Interactive test entry
An opt-in `Archive Control (Test)` entry reuses this same handler with an
independent callback namespace and SQLite database. Its scripted backend
provides comprehensive, empty, and slow-route scenarios without contacting
control/client daemons, qBittorrent, or Syncthing. The production entry,
callback namespace, database, jobs, placements, and other bot features are
unchanged.
The test entry exposes administrator-only `/actest` controls to reset a
scenario, move a synthetic job through displayed states, fail the next selected
backend call, complete a slow route, inspect recent trace events, or export the
complete JSONL trace. The trace contains callback and filter inputs, session
state transitions, exact message/keyboard renders, backend results/errors, and
job transitions, so a UI report can be reproduced without live storage nodes.