Appearance
Build a paid Wi-Fi application
This walkthrough turns a Linux Wi-Fi gateway into a customer application that can sell or allocate time-bounded access. It proves the paid_wifi reference workflow: reserve value, create an access session, request gateway activation, wait for the session, revoke access, and commit only after the workflow succeeds.
You finish with:
- a Wi-Fi Gateway Device Class bound as
gateway - customer-visible
access_sessionrecords grant_accessandrevoke_accessproduct commands- a durable
purchase_accessprocess - a failure path that releases the reservation when activation fails
- one published customer instance tested through success and compensation
This is a Product Logic proof, not a captive portal, RADIUS server, payment processor, or production network policy. Those systems remain part of your product.
Before you start
You need:
- Product Applications beta access on Standard+
- a Customer Portal and a downstream test customer
- a Linux gateway in a Wi-Fi Gateway Device Class
- a device-side integration capable of granting and revoking one client
- a test client identifier that is safe to use
- a staging resource account or payment sandbox
Do not use a production payment credential or a real customer MAC address in screenshots or examples.
Part 1: Define the gateway contract
Create or select Wi-Fi Gateway under Engineering > Device classes. The representative gateway must belong to this class.
Define two bounded operations in the device contract:
| Product operation | Expected device responsibility |
|---|---|
| Grant access | Validate the client and expiry, update the local network policy idempotently, and report success or failure |
| Revoke access | Remove only the intended entitlement and report success or failure |
The production bridge must use a stable correlation or entitlement identifier. Repeated delivery must not create duplicate rules, and a late grant must not restore an entitlement after revocation.

Use a Device Class action with structured object input (client_id, expires_at) so the Product command can pass those fields through Prelude Agent to the gateway handler. Repeated delivery must not create duplicate rules, and a late grant must not restore an entitlement after revocation.
Part 2: Create the application and binding
- Open Developer > Product Applications.
- Create Paid Wi-Fi with key
paid_wifi. - Open Build > Hardware.
- Connect the Wi-Fi Gateway class with role alias
gateway. - Confirm the staging gateway appears as an eligible device for that role.
Use the role alias in every later command. Do not store a Device Class hash or one gateway's device ID in the application definition.
Part 3: Define access-session records
In Build > Models, add:
| Field | Value |
|---|---|
| Model key | access_session |
| Label | Access Session |
| Lifecycle | Operational |
| Customer create | Enabled only for the intended purchase surface |
| Customer update | Enabled only where state transitions are constrained |
| Customer delete | Disabled |
Add these minimum fields:
| Field key | Type | Meaning |
|---|---|---|
client_id | String | Stable client identifier understood by the gateway |
state | String | Pending, active, expired, failed, or another explicit application state |
For production, also model the plan, requested duration, entitlement ID, customer-visible price, currency, start and expiry timestamps, gateway reference, and external payment reference. Do not overload client_id as the financial or idempotency identity.
Part 4: Define gateway commands
In Behaviour > Commands, create:
| Command | Binding | Timeout | Input used by the proof |
|---|---|---|---|
grant_access | gateway | 30 seconds | client and expiry |
revoke_access | gateway | 30 seconds | client |
Command acceptance is not proof that network policy changed. The process must wait for a terminal success, failure, rejection, or expiry report from the qualified device bridge.
Part 5: Build the purchase process
Add a process named Purchase Access with key purchase_access.
Build this flow:
text
reserve payment or quota
-> create pending access_session
-> invoke grant_access and wait
-> wait for session duration
-> invoke revoke_access and wait
-> commit reservation
-> completeSend grant failures, rejections, and expiries to:
text
release reservation
-> fail with activation_failedThe normative reference uses:
- account key
payments - unit
AUD - a bounded test limit
reservation_idas the remembered reservationsession_idas the created record- success states
succeededoracknowledged - failure states
failed,rejected, andexpired
Keep commerce outside the process unless it is represented by a qualified integration. A resource reservation can prove hold, commit, and release semantics, but it does not collect money.
Part 6: Expose the customer entry point
In Access:
- add an Access Sessions list or detail page
- expose a deliberate purchase operation that starts
purchase_access - allow only the customer roles that may buy or allocate access
- keep raw command invocation unavailable to ordinary viewers
- add an HTTPS payment integration only when its retry and idempotency design has been reviewed
The customer should see a plain outcome: activating, active until a specific time, expired, or activation failed with no charge committed. Do not show internal process step names as the primary experience.
Part 7: Publish and run the happy path
- Open Release and validate the draft.
- Publish version 1.
- Attach it to the staging Customer Portal.
- Provision the Cafe Wi-Fi customer instance.
- Create the bounded
paymentstest resource account. - In Sandbox, start
purchase_accesswith:- a test amount
- test client ID
- staging gateway device ID
- short session duration
- expiry
- Confirm the process waits on
grant_access. - Report the grant command as succeeded from the test bridge.
- Tick the due timer.
- Confirm
revoke_accessis requested. - Report revocation as succeeded.
- Confirm the process completes and the reservation is committed once.
Verify the access rule exists during the session and is absent afterwards. Cloud process completion alone is not enough.

Part 8: Prove compensation
Start another purchase with a unique idempotency and correlation identity. Report grant_access as failed or rejected.
Confirm:
- the process fails with
activation_failed - the reservation changes to released
- committed value remains zero
- the client does not have network access
- retrying with the same idempotency identity does not double reserve
- another customer cannot see the session or process activity
Also test a lost command acknowledgement. Treat an ambiguous outcome as an investigation state; do not silently charge or grant again.

Production handover gate
- [ ] Grant and revoke are idempotent on the gateway.
- [ ] A late grant cannot restore expired or revoked access.
- [ ] Session duration uses a trusted clock and explicit expiry.
- [ ] Activation failure releases the reservation.
- [ ] Duplicate callbacks and process starts do not double charge or double grant.
- [ ] Ambiguous command outcomes enter review instead of silently succeeding.
- [ ] Captive portal, RADIUS, firewall, and payment responsibilities are documented.
- [ ] Customer viewers cannot invoke purchase or raw gateway commands.
- [ ] Another customer cannot see sessions, devices, executions, or activity.
- [ ] Logs and screenshots contain no payment secrets or customer identifiers.