R-773: a removed app restored from its backup gets its sign-up lock back (record opened_by restore + block, before anything starts)
gates / gates (push) Successful in 29s
gates / gates (push) Successful in 29s
An installed app the household never closed keeps what it had (decision 49). Red-proof RP-D2. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -229,6 +229,31 @@ func (m *Manager) CloseSignupNow(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// restoreSignupLock is R-773's half of PersistUnitRedeployConfig: for an app whose template locks sign-up, the lock
|
||||
// record (opened_by "restore", never a closed gate) and — best effort — its block file. nil, nil when the template has
|
||||
// no lock. A block that cannot be written now is logged and left to the loop (the record says it is wanted); hosts that
|
||||
// cannot be read refuse the restore before anything starts (fail closed, as the gate's own install does).
|
||||
// The app's own switch (`after_setup`) is the loop's: NativeLock is "" so it runs once the app is up.
|
||||
func (m *Manager) restoreSignupLock(name, composePath string, env map[string]string, meta *Metadata) (*SetupGateRecord, error) {
|
||||
block := strings.TrimSpace(meta.SignupBlock)
|
||||
if block == "" && meta.AfterSetup == nil {
|
||||
return nil, nil
|
||||
}
|
||||
rs, err := gateRoutersFromCompose(composePath, env)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: the app's addresses could not be read: %w", name, err)
|
||||
}
|
||||
hosts := gateHosts(rs)
|
||||
if block != "" {
|
||||
if err := m.writeSignupBlock(name, hosts, block); err != nil {
|
||||
m.logger.Printf("[ERROR] [stacks] %s: the restore's sign-up block could not be written: %v — the loop retries; sign-up is OPEN until it is", name, err)
|
||||
}
|
||||
}
|
||||
now := m.now().UTC().Format(time.RFC3339)
|
||||
m.logger.Printf("[INFO] [stacks] %s: restored after a removal — sign-up closed again as after its setup (hosts %v)", name, hosts)
|
||||
return &SetupGateRecord{State: SetupGateOpen, Since: now, Hosts: hosts, OpenedAt: now, OpenedBy: SetupGateByRestore}, nil
|
||||
}
|
||||
|
||||
// goNativeLock runs applyNativeLock in the background, one at a time per app (a press, the window and the loop
|
||||
// can meet). The seam afterSetupSync makes it synchronous for tests.
|
||||
func (m *Manager) goNativeLock(name string, lock bool, why string) {
|
||||
|
||||
Reference in New Issue
Block a user