Demo Script
Step-by-step presenter guide for the Healthcare vertical. Switch verticals below to see the matching credentials and flows.
Credentials
| Name | Role | Login email | Password |
|---|---|---|---|
| Jane Patient | owner | owner@atko.email | Demo123! |
| Chris Carer | delegate | delegate@atko.email No standing access — earned via delegation / approval flows. | Demo123! |
| Dr. Morgan | admin | approver@atko.email | Demo123! |
| Sam Nurse | member | member@atko.email | Demo123! |
| Unrelated User | none | outsider@atko.email | Demo123! |
Demo Flows
FGA baseline: who sees what
Verify that Auth0 FGA controls resource visibility — owner and member see resources, outsider is denied.
- 1
Log in as Jane Patient (`owner@atko.email` / `Demo123!`)
→ Look for: Dashboard shows patient records with an **FGA-filtered** badge. Inspector → FGA Authorization panel shows `listObjects` returned the record ids, each with `can_view = ALLOWED`.
- 2
Open the Inspector sidebar → **FGA Authorization** section
→ Look for: The `listObjects` call shows `current_time` was auto-injected. Each resource row has a green ALLOWED badge.
- 3
Log out → log in as **Unrelated User** (`outsider@atko.email` / `Demo123!`)
→ Look for: Dashboard shows empty state: "No patient records you are authorised to view." FGA panel shows empty `listObjects` result — `outsider` has no tuples.
Delegation lifecycle: grant → accept → revoke
The account owner grants scoped time-bounded access to a carer, who accepts — then the owner revokes and access is removed immediately.
- 1
Log in as Jane Patient (`owner@atko.email` / `Demo123!`) → **Delegations** (`/delegations`)
→ Look for: An amber banner prompts MFA step-up. Click **Step up with MFA** and complete the challenge. Select **SMS** to receive the code via the demo OTP inbox, or **Email** for the atko.email inbox. For SMS: open the **OTP Inbox** (`/otp`) tab first — the code appears there automatically within a few seconds. For Email: check the shared atko.email inbox.
- 2
In the Grant Access form: enter `delegate@atko.email`, select delegation type **Carer**, choose a target patient record from the dropdown, select relevant scopes (e.g. `appointments:read`, `records:read`), set expiry 30 days → Submit
→ Look for: Success message. The delegation appears under **Delegations you've granted** with status Pending.
- 3
Log out → log in as Chris Carer (`delegate@atko.email` / `Demo123!`) → **Delegations**
→ Look for: A pending invitation card is shown under **Pending invitations for you** with the consent summary, scopes, and expiry date.
- 4
Click **Accept**
→ Look for: Card moves to **Access granted to you** with status Active. Inspector → Delegations panel shows the FGA object, relation `delegate`, `valid_until`, and scopes.
- 5
Go to Dashboard (`/`)
→ Look for: Dashboard shows ONLY the delegated patient record — not other records on the account. FGA-filtered badge present. This is scoped delegation: Chris Carer can see the granted record but nothing else.
- 6
Log out → log in as Jane Patient → Delegations → click **Revoke** (complete MFA step-up if prompted)
→ Look for: Delegation status changes to Revoked. The FGA conditional tuple has been removed.
- 7
Log out → log in as Chris Carer → Dashboard
→ Look for: Empty state. Access denied immediately — no tuple means `can_view` returns false.
- 8
Check **Audit Trail** (`/audit`)
→ Look for: Events: `delegation:create` → `delegation:accept` → `delegation:revoke`, each with correct actor, subject, and correlation ID.
On-behalf-of: acting as the represented patient
An active carer switches context to act on behalf of the patient, receiving an OBO token (sub=patient, act.sub=carer) visible in the inspector sidebar.
- 1
Log in as Chris Carer (`delegate@atko.email`) → Dashboard
→ Look for: Context switcher at the top shows **Available delegated contexts** with an entry for Jane Patient's patient record.
- 2
Click **'Act on behalf of Jane Patient'**
→ Look for: A non-dismissible amber/indigo banner appears: "Acting on behalf of [Jane's sub] · [FGA object] · delegation [id] · expires [time]".
- 3
View the delegated dashboard
→ Look for: Heading reads "Viewing on behalf of…". The delegated patient record is shown with the delegation scopes listed.
- 4
Open Inspector sidebar → **On-Behalf-Of Token** section
→ Look for: Decoded JWT shows `sub` = Jane Patient's Auth0 sub, `act.sub` = Chris Carer's Auth0 sub, `scope` = the granted scopes, `delegation_id`, and a 15-minute expiry. Note reads: "Custom-issued JWT following RFC 8693 claims convention — not a native Auth0 token exchange."
- 5
Click **Stop** in the delegated-mode banner
→ Look for: Banner clears. Dashboard returns to "Acting as myself". OBO cookies cleared — context switcher shows no active context.
Approval request: ask → inbox → approve
A nurse with no standing access requests it; the patient approves from their inbox — creating an active delegation on the spot.
- 1
Log in as Sam Nurse (`member@atko.email` / `Demo123!`) → **Requests** (`/requests`)
→ Look for: Mode badge shows **Simulation (in-app inbox)** (default) or **Live CIBA (Guardian push)** if configured. My Requests table is empty.
- 2
In **Request access**: select a target patient record from the dropdown, enter the reason "Need to view appointment schedule to coordinate care", select scopes (e.g. `appointments:read`) → Submit
→ Look for: Success: "Approval request created — pending in the approver inbox." My Requests shows the request with status **Pending**.
- 3
Log out → log in as Jane Patient (`owner@atko.email`) → **Requests**
→ Look for: **Approver inbox** shows the pending card with requester email (`member@atko.email`), target record, scopes, and reason. Inspector → Approval Requests panel also shows it.
- 4
Click **Approve**
→ Look for: Card leaves the inbox. Success: "Approved — access granted to the requester."
- 5
Log out → log in as Sam Nurse → Dashboard
→ Look for: The previously requested patient record now appears with FGA-filtered badge. Inspector → Delegations panel shows the new active delegation created by the approval.
- 6
Check **Audit Trail** (`/audit`)
→ Look for: Events: `request:create` → `request:approve`, with `delegationId` referencing the delegation that was auto-created.
Run npm run demo:reset between demo runs to clear delegations, requests, and audit events.