R-717: after_setup open_command — the family window reopens an app's DB-held sign-up switch
The command form ran only when the lock was SET, so a database switch closed by
`command` stayed closed through the household's 15-minute window. New twin
fields `open_command` + `open_success` (same service/user/args_env and the same
argv-safe expansion and success-marker rules as `command`/`success`).
- liftNativeLock (the window, via OpenSignupWindow → goNativeLock(false)): marks
the gate record native_lock "opening" BEFORE anything opens, lifts the env,
runs open_command; only full success records "lifted". A failed open closes
the switch again at once and records after_setup {ok: false, step: open}; the
app page shows its own line (app_info.signup_native_open_failed).
- The close: reconcileSignupBlocks (every 20 s and at controller start) runs
`command` for any non-"applied" state once no window runs. A failed close
after a window is logged ERROR ("may still be OPEN past the household's
window") and retried every nativeLockOpenRetry (2 min) instead of 30.
- After a successful app update, verifyAndConclude → markNativeLockForReapply
sets native_lock "" so the loop closes the switch again.
- A template with `command` but no `open_command` keeps today's window (env
only) and logs once per app that its own switch cannot be reopened.
Tests: internal/stacks/after_setup_r717_test.go (7), web render + parity case.
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:
@@ -783,7 +783,11 @@ func (s *Server) appDetailHandler(w http.ResponseWriter, r *http.Request, slug s
|
||||
data["CloseSignupOffered"] = s.stackMgr.CloseSignupOffered(found.Name)
|
||||
}
|
||||
data["SignupNative"] = found.Meta.AfterSetup != nil && len(found.Meta.AfterSetup.Env) > 0
|
||||
data["SignupNativeFailed"] = found.AppConfig != nil && found.AppConfig.AfterSetup != nil && !found.AppConfig.AfterSetup.OK
|
||||
nativeFailed := found.AppConfig != nil && found.AppConfig.AfterSetup != nil && !found.AppConfig.AfterSetup.OK
|
||||
// R-717: a failed OPEN (the household's window; the switch was closed again) says so in its own words.
|
||||
nativeOpenFailed := nativeFailed && found.AppConfig.AfterSetup.Step == "open"
|
||||
data["SignupNativeFailed"] = nativeFailed && !nativeOpenFailed
|
||||
data["SignupNativeOpenFailed"] = nativeOpenFailed
|
||||
// v0.281.0 (decision 47): the sign-up card — closed, or open for the household's 15 minutes.
|
||||
if s.stackMgr != nil {
|
||||
blocked, until := s.stackMgr.SignupBlocked(found.Name)
|
||||
|
||||
Reference in New Issue
Block a user