8db4425d98
gates / gates (push) Successful in 2m38s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
94 lines
4.5 KiB
Python
94 lines
4.5 KiB
Python
"""r717live.py — R-717 live proof on scratch 9202 (test controller 0.301.0, drill catalog with wishlist's after_setup).
|
|
|
|
1 wishlist installed fresh; the household's first account (the fixture, through the setup gate);
|
|
2 the household opens the app (POST /apps/<slug>/setup-gate/open) → after_setup's close command runs;
|
|
the DB value read (enableSignup=false) + the controller's own lines;
|
|
3 a STRANGER straight at the app (the container's address — past the address block, the strictest case):
|
|
sign-up refused; the user count before/after;
|
|
4 the household's 15-minute window (POST /apps/<slug>/signup-window) → the open command; DB = true; a family member
|
|
signs up straight at the app → success; the user count +1;
|
|
5 after the window ends (polled; ~15 min): the close command ran again; DB = false; a stranger refused; count unchanged.
|
|
Evidence: ../E/live.txt."""
|
|
import json, os, secrets, sys, time
|
|
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
|
import box_walk as w
|
|
import upgrade_fixtures_box as fixtures
|
|
|
|
APP, SUB = "wishlist", "wishlist"
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
log = open(os.path.join(HERE, "..", "E", "live.txt"), "a", buffering=1)
|
|
|
|
|
|
def say(*a):
|
|
w.say(*a); log.write(" ".join(map(str, a)) + "\n")
|
|
|
|
|
|
DBJS = r'''const {DatabaseSync}=require('node:sqlite');const db=new DatabaseSync('/usr/src/app/data/prod.db',{readOnly:true});
|
|
const v=db.prepare("select value from system_config where key='enableSignup' and groupId='global'").get();
|
|
const n=db.prepare("select count(*) as n from user").get();console.log('DB enableSignup='+(v?v.value:'<no row: default open>')+' users='+n.n);'''
|
|
|
|
|
|
def db():
|
|
return w.guest("docker exec -i wishlist node - <<'JS'\n" + DBJS + "\nJS\n").strip().splitlines()[-1:]
|
|
|
|
|
|
def stranger(tag):
|
|
"""A sign-up straight at the app's own address inside the box — past the box's address block."""
|
|
u = f"{tag}{secrets.token_hex(3)}"
|
|
body = f"name={tag}&username={u}&email={u}%40example.invalid&password=Drill-{secrets.token_hex(8)}&tokenId="
|
|
out = w.guest(f"""ip=$(docker inspect -f '{{{{range .NetworkSettings.Networks}}}}{{{{.IPAddress}}}} {{{{end}}}}' wishlist | awk '{{print $1}}')
|
|
curl -s -m 30 -H 'Host: {SUB}.{w.DOMAIN}' -H 'Origin: https://{SUB}.{w.DOMAIN}' -H 'x-sveltekit-action: true' \\
|
|
-H 'Content-Type: application/x-www-form-urlencoded' -w '\\nHTTP %{{http_code}}' --data '{body}' http://$ip:3000/signup""")
|
|
return " ".join(out.split())[-220:]
|
|
|
|
|
|
def ctl_lines(since):
|
|
return w.guest(f"docker logs --since {since} felhom-controller 2>&1 | grep -v DEBUG | grep -i -E 'after_setup|native|signup|sign-up|window' | cut -c1-300")
|
|
|
|
|
|
w.login()
|
|
if w.stack(APP).get("deployed"):
|
|
say("wishlist installed from the earlier probe — removing it first (scratch box)")
|
|
w.remove(APP)
|
|
w.sync_rescan()
|
|
time.sleep(5)
|
|
w.sync_rescan()
|
|
say("9202 controller:", w.guest("docker inspect -f '{{.Config.Image}}' felhom-controller").strip())
|
|
if not w.deploy(APP, SUB):
|
|
sys.exit(say("RESULT install failed") or 1)
|
|
fx = fixtures.FIXTURES[APP]
|
|
tok = fx.seed(w, SUB, say)
|
|
say("[1] the household's first account:", tok is not None, "| DB:", db())
|
|
t0 = w.guest("date -u +%Y-%m-%dT%H:%M:%SZ").strip()
|
|
code, d = w.ctl("POST", f"/apps/{APP}/setup-gate/open", {})
|
|
say("[2] the household opens the app (setup done) ->", code, str(d)[:160])
|
|
time.sleep(25)
|
|
say("[2] DB after the close command:", db())
|
|
log.write(ctl_lines(t0) + "\n")
|
|
say("[3] stranger, straight at the app:", stranger("stranger"))
|
|
say("[3] DB:", db())
|
|
t1 = w.guest("date -u +%Y-%m-%dT%H:%M:%SZ").strip()
|
|
code, d = w.ctl("POST", f"/apps/{APP}/signup-window", {})
|
|
say("[4] the household opens the 15-minute window ->", code, str(d)[:160])
|
|
time.sleep(25)
|
|
say("[4] DB inside the window:", db())
|
|
say("[4] a family member, straight at the app:", stranger("family"))
|
|
say("[4] DB:", db())
|
|
log.write(ctl_lines(t1) + "\n")
|
|
t2 = time.time()
|
|
while time.time() - t2 < 1500:
|
|
time.sleep(30)
|
|
v = db()
|
|
if v and "enableSignup=false" in v[0]:
|
|
say(f"[5] the switch reads CLOSED again {round(time.time() - t2)} s after the check began: {v}")
|
|
break
|
|
else:
|
|
say("[5] the switch did NOT close within 25 minutes:", db())
|
|
say("[5] stranger after the window, straight at the app:", stranger("late"))
|
|
say("[5] DB:", db())
|
|
log.write(ctl_lines(t1) + "\n")
|
|
st = w.stack(APP)
|
|
say("[5] app page record:", json.dumps({k: (st.get("app_config") or {}).get(k) for k in ("after_setup", "setup_gate")})[:600])
|
|
if not os.environ.get("KEEP"):
|
|
say("remove ->", w.remove(APP))
|