Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

First payment from a present-but-unregistered client is refused (client-not-registered) — extend the renewal presence-proof to first purchases

Open
#582 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
go

Research direction

Start in src/merchant/merchant.go at PurchaseSession, then read sessionIsRenewal, clientRegisteredForGate, and grantSessionAccess to understand the existing presence and rollback behavior. Check the related tests, if present, before changing the pre-Receive registration check. Done means a resolvable client can make a first purchase without NDS registration, unresolved clients remain rejected, and genuine access-grant failures still roll back.

Written by the indexing model from the issue text.

Description

Summary

A payment submitted by a client that is present and identifiable but not registered in NoDogSplash is refused before Receive with client-not-registered. The renewal path already treats "this MAC just submitted a token" as proof of presence and proceeds (the valve's bounded auth retry re-registers, grantSessionAccess rolls back on true failure) — but a first purchase from the same kind of client is hard-refused. Proposal: extend that same presence-proof to first purchases.

Observed

Lab rig, tollgate-wrt v0.6.0-alpha4 on OpenWrt 24.10.8. A wired LAN-side client (management host on br-lan) POSTs a valid token directly to the merchant:

$ curl -X POST --data "$TOKEN" http://192.168.103.51:2121/
{"kind":21023,...,"tags":[["level","error"],["code","client-not-registered"],
 ["p","14:5a:fc:49:c2:23"]],
 "content":"No captive-portal session found for this device. Reconnect to the TollGate Wi-Fi and try again.",...}

Note the MAC was resolved just-in-time from the socket (ARP table — "p" tag carries it), the mint is reachable, and the token is left unspent. The recovery instruction is wrong for this client class: it is wired, and no amount of reconnecting produces an NDS registration.

Mechanism

src/merchant/merchant.go, PurchaseSession pre-flight:

if !m.sessionIsRenewal(macAddress) && !m.clientRegisteredForGate(macAddress) {
    // refused: client-not-registered, before Receive (#403 L1)
}
  • clientRegisteredForGate probes ndsctl (3 attempts) and fails open on probe errors — only a clean "not registered" verdict refuses.
  • sessionIsRenewal (known MAC with active/expired local session) bypasses the check entirely, with an explicit comment: the client "is demonstrably present (it just submitted a token through the captive-portal) and the valve's bounded auth retry is what re-registers it", accepting the deliberate residual risk that Receive succeeded but the gate cannot open (rolled back by grantSessionAccess).

Why this bites beyond the lab

For a Wi-Fi customer loading the portal this is nearly unreachable (portal load = NDS pre-auth registration). The refusal hits:

  1. Wired/LAN-side clients — no NDS interception ever registers them; the error's advice is a dead end.
  2. Direct API/wallet payments that POST a token without rendering the portal page (automation, headless clients, the ?token= TIP-03 flow if the page load is skipped).
  3. Lapsed NDS state between portal load and payment submission (self-heals today only via reconnect).

Proposal

Treat "MAC resolved from the request socket + payment POST received" as the presence-proof for first purchases too — the same evidence the renewal path already accepts — and let the existing valve auth retry perform the just-in-time registration, with the existing grantSessionAccess rollback covering genuine registration failure:

  • Unresolvable/sentinel MACs stay rejected (already covered by the device-unresolved class — no change).
  • The pre-Receive order stays intact; only the registration precondition is relaxed from "NDS knows this MAC" to "this device is demonstrably present".
  • At minimum, fix the notice text for non-Wi-Fi clients ("Reconnect to the TollGate Wi-Fi" → guidance that matches the client class).

Reproduction

  1. Router with tollgate-wrt running, a reachable mint in accepted_mints.
  2. From a wired host on br-lan (so its MAC lands in the ARP table but never in NDS): curl -X POST --data "$CASHU_TOKEN" http://<router>:2121/
  3. Observe the kind-21023 client-not-registered event; wallet balance unchanged.

Concrete consumer: the physical rig's phone-payment E2E and host-side payment automation currently need a real Wi-Fi client solely to satisfy this pre-flight.

Dominant language
Go
Stars
12
Forks
14
Avg merge
1d 6h
Merged PRs (30d)
211

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from OpenTollGate/tollgate-module-basic-go

All issues in OpenTollGate/tollgate-module-basic-go

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.