mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 08:41:13 -07:00
forgetest: /fuse-identity is two-factor; the auth test asserts both refusals
forgectrl reveals the fuse identity only to the token AND the physical button held, so the token alone must answer 403 with the button message. The test now asserts the no-token refusal and the token-without-button refusal and never fetches the identity itself (a 200 would have carried the fuse password into the result log). BRINGUP: the bench campaign on the flashed dev image, 7 of 24 passed so far.
This commit is contained in:
@@ -1443,6 +1443,25 @@ The coverage currency rule is in `CLAUDE.md`
|
||||
"Working rules". Bench validation and the bench-tab ports are Next work
|
||||
item 15.
|
||||
|
||||
**Bench campaign opened 2026-08-15 on the flashed dev image
|
||||
`20260815194415` (manifest identity `2d69a61e…`, equal to the release
|
||||
build's).** The tool came up on `:8090` with all 24 tests required.
|
||||
Passed so far, driven through the API with the operator present:
|
||||
`image.health` (kernel options, module + 16 MiB ring, forgectrl holding
|
||||
`/dev/glowforge`, K80 controllers before K90 forgectrl, 0600 token and
|
||||
settings, 2.6 GiB free on /data), `kernel.latch-locked-idle` (interlock
|
||||
`0x2d`, FIRE 0, LASER_ON 0/0, faults 0), `forgectrl.auth`,
|
||||
`forgectrl.settings-bounds`, `forgectrl.panel-serves`,
|
||||
`logs.tree-tail-export` (sanitized bundle carries no panel token),
|
||||
`update.slots-and-signature` - 7 of 24. One finding, on the tool side:
|
||||
`forgectrl.auth` first failed because it expected `/fuse-identity` to
|
||||
answer 200 to the token alone; the endpoint is two-factor (token AND the
|
||||
physical button held) by design, so the test now asserts both refusals
|
||||
and never fetches the identity (a 200 would have put the fuse password
|
||||
in the result log). That FAIL closed the first campaign, as the rules
|
||||
say; the second campaign holds the passes. Next: the takeover drills,
|
||||
motion, cooling, camera, cloud, then the live tests from the page.
|
||||
|
||||
## Hardware facts bank (measured)
|
||||
|
||||
- **DRV8825 stepper drivers wedge on 40 V rail glitches** (factory board;
|
||||
|
||||
@@ -28,7 +28,8 @@ def lan_ip():
|
||||
covers=_COVERS_AUTH,
|
||||
description="Every state-changing endpoint refuses an unauthenticated write; a non-literal "
|
||||
"Host, a non-literal Origin and a cross-site Sec-Fetch-Site are refused; the "
|
||||
"cooling report channel refuses a non-loopback peer; the fuse view is token-gated; "
|
||||
"cooling report channel refuses a non-loopback peer; the fuse view is two-factor "
|
||||
"(token and the physical button) and refused without either; "
|
||||
"the flash and factory-restore chain is refused unauthenticated.")
|
||||
def auth(ctx):
|
||||
fc = ctx.forgectrl
|
||||
@@ -74,14 +75,22 @@ def auth(ctx):
|
||||
st, body = fc.get("/status", headers={"Sec-Fetch-Site": "same-origin", "Origin": "http://127.0.0.1:8080"})
|
||||
ctx.check(st == 200, "same-origin literal Origin refused (%s)", st)
|
||||
|
||||
# the token opens the fuse view; without it, refused
|
||||
# the fuse view is two-factor: the token AND the physical button held.
|
||||
# Without the token: authentication refused; with the token and nobody
|
||||
# at the button: refused with the button message. The identity itself is
|
||||
# never fetched (it would land in this log).
|
||||
st, body = fc.get("/fuse-identity", auth=False)
|
||||
ev["fuse_noauth"] = st
|
||||
ctx.check(st == 403, "GET /fuse-identity without token -> %s", st)
|
||||
ctx.log("GET /fuse-identity (no token) -> %s %s", st, body if isinstance(body, dict) else "")
|
||||
ctx.check(st == 403 and isinstance(body, dict) and body.get("error") == "authentication required",
|
||||
"GET /fuse-identity without token -> %s %r", st, body)
|
||||
st, body = fc.get("/fuse-identity")
|
||||
ev["fuse_auth"] = st
|
||||
ctx.log("GET /fuse-identity with token -> %s", st)
|
||||
ctx.check(st == 200, "GET /fuse-identity with the token -> %s", st)
|
||||
ev["fuse_token_no_button"] = st
|
||||
ctx.log("GET /fuse-identity (token, button not held) -> %s %s", st, body if isinstance(body, dict) else "")
|
||||
msg = body.get("error", "") if isinstance(body, dict) else str(body)
|
||||
ctx.check(st == 403 and "button" in msg,
|
||||
"GET /fuse-identity with the token but no button -> %s %r (expected the two-factor refusal)",
|
||||
st, body)
|
||||
|
||||
# the cooling report channel: loopback only, even with a token
|
||||
ip = lan_ip()
|
||||
|
||||
Reference in New Issue
Block a user