Grimmory and MeTube published behind the family gate (controller >= 0.287.0, decisions 63/64), with complete records
gates / gates (push) Successful in 3s
gates / gates (push) Successful in 3s
- family_gate / family_gate_except / min_controller format (README, REUSE); gate family-gate + decoys - templates/grimmory (v3.5.0, exceptions OPDS/Kobo/KOReader/Komga) + onboarding/grimmory.md - templates/metube (2026.09.29, no exceptions; ladder .28 -> .29) + onboarding/metube.md; fixture MeTube - volume-persistence gate: routed port read from the label NAME (R-801, red-proofed); APP_EXERCISE (R-788) - box_walk: family_cookie; no cached "not gated" while an app has no router 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:
+28
-1
@@ -130,6 +130,14 @@ def gate_cookie(sub):
|
||||
sess = open(f"{SC}/sess{os.getpid()}.txt").read().strip()
|
||||
r = sh(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", "Accept: text/html", "-H", f"Host: {sub}.{DOMAIN}", f"{BASE}/"])
|
||||
loc = _loc(r.stdout)
|
||||
st = re.match(r"HTTP/\S+ (\d+)", r.stdout or "")
|
||||
if not loc and (not st or st.group(1) in ("404", "502", "503", "504")):
|
||||
# the app is not routed at this moment (a restart, an update's stop): NOT the same as "not gated" — a cached ""
|
||||
# here sent every later call past nothing and read the gate's 401 as the app's (2026-10-02, grim-step)
|
||||
say(f" gate: {sub} not routed right now ({st.group(1) if st else 'no answer'}) — not cached, asked again next call")
|
||||
return ""
|
||||
if "/__family/start" in loc: # v0.287.0: the FAMILY gate — the household's dashboard session vouches, as for
|
||||
return family_cookie(sub, loc, sess) # the setup gate (decisions 63/64)
|
||||
if "/__gate/start" not in loc:
|
||||
GATE[sub] = ""
|
||||
return "" # not gated (open, or no gate for this app)
|
||||
@@ -148,6 +156,25 @@ def gate_cookie(sub):
|
||||
return GATE[sub]
|
||||
|
||||
|
||||
def family_cookie(sub, loc, sess):
|
||||
"""Pass the FAMILY gate (controller >= 0.287.0) as the household: /__family/start on the dashboard host with the
|
||||
dashboard session → the app host's /__felhom_gate/fcb → `felhom_famgate`. Never printed."""
|
||||
import urllib.parse
|
||||
u = urllib.parse.urlsplit(loc)
|
||||
r = sh(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", "Accept: text/html", "-H", f"Host: {u.hostname}", "-H", f"Cookie: {sess}",
|
||||
f"{BASE}{u.path}?{u.query}"])
|
||||
u = urllib.parse.urlsplit(_loc(r.stdout))
|
||||
if "/__felhom_gate/fcb" not in u.path:
|
||||
say(f" family gate: the dashboard did not hand back a callback for {sub}")
|
||||
GATE[sub] = ""
|
||||
return ""
|
||||
r = sh(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", "Accept: text/html", "-H", f"Host: {u.hostname}", f"{BASE}{u.path}?{u.query}"])
|
||||
m = re.search(r"(?im)^set-cookie:\s*(felhom_famgate=[^;\r\n]+)", r.stdout or "")
|
||||
GATE[sub] = m.group(1) if m else ""
|
||||
say(f" family gate: {sub} is family-gated — passed as the household (cookie {'set' if GATE[sub] else 'NOT set'})")
|
||||
return GATE[sub]
|
||||
|
||||
|
||||
def app_curl(sub, path, *extra, method=None, data=None, timeout=45, _retry=True):
|
||||
"""A call to the APP's own front door on 9202 — the household's route, not ours. Carries the setup
|
||||
gate's cookie when the app is gated, merged into a fixture's own Cookie header (never a second one)."""
|
||||
@@ -172,7 +199,7 @@ def app_curl(sub, path, *extra, method=None, data=None, timeout=45, _retry=True)
|
||||
r = sh(args, timeout=timeout + 30, inp=data)
|
||||
body, _, tail = (r.stdout or "").rpartition("\n")
|
||||
code, _, redir = tail.strip().partition(" ")
|
||||
if _retry and "/__gate/start" in redir:
|
||||
if _retry and ("/__gate/start" in redir or "/__family/start" in redir):
|
||||
GATE.pop(sub, None) # the gate cookie expired or was never taken — log in as the household again
|
||||
return app_curl(sub, path, *raw, method=method, data=data, timeout=timeout, _retry=False)
|
||||
return r.returncode, code.strip(), body
|
||||
|
||||
Reference in New Issue
Block a user