Merge remote-tracking branch 'gitea-ai/main' into gsd/phase-13-aiui-functional-conversational-node-control-and-content-surf

This commit is contained in:
archipelago
2026-08-08 10:10:33 -04:00
3 changed files with 167 additions and 1 deletions
+25
View File
@@ -55,6 +55,31 @@ Two details in that check are deliberate and should not be "tightened":
this node does not hold surfaces as a **failed rotation** with the wallet
intact.
## Nothing else may touch LND mid-rotation
Between "stop LND" and "start LND" the rotation owns a stopped container whose
credential material is being deleted. Two background actors would step in there
unasked: the **health monitor** restarts any container it finds stopped, and the
**reconciler** starts one whose unit is enabled. Either brings LND back up
mid-deletion — and LND re-mints `macaroons.db` on unlock, so the deletion loop
would race a live process writing that file, or "succeed" against material that
had already been regenerated. The operator would be told they had rotated while
the old root key was still in service.
The rotation therefore holds `app_ops::op_lock("lnd")` for its whole duration.
That is the lock both actors already consult (`lifecycle_op_in_flight`, reached
in the health monitor via `lifecycle_op_covers_container`), and it also
serialises against the `package.start`/`stop`/`restart` workers, so an operator
hitting "Restart" on Lightning mid-rotation queues rather than interleaving. A
rotation requested while one of those is running fails fast with a short
explanation instead of waiting silently.
Deliberately **not** the `user-stopped` marker that `recreate_wallet_destructively`
uses for its own window: that marker is a file on disk, so a rotation that died
between marking and clearing would leave Lightning suppressed *permanently*
fixable only by finding and editing JSON on the node. The lock guard releases
when it drops, on every path including a panic.
## The BTCPay coupling — the part that bites
**BTCPay Server keeps its own inline copy of the admin macaroon**, and it cannot