S
supero.docs
Documentation/Reference apps/Inside Relay, an open-source healthcare staffing marketplace app

Inside Relay, an open-source healthcare staffing marketplace app

Relay is an open-source healthcare staffing marketplace app with shifts, credential checks, timesheets and payouts. On GitHub, live at relay.supero.live.

  • apps
  • mobility
  • healthcare-staffing
  • approvals
  • marketplace

Overview

A working healthcare staffing marketplace app with its source on GitHub, where an admin approves credentials, a facility approves hours, and both approvals are the same borrowed state machine.
Per-diem staffing, where clinicians pick up single shifts, has two sign-offs. Somebody checks a nurse's licence before she works an ICU shift. The hospital agrees she worked the twelve hours before she is paid for them. That is two approvals by two different people.
In Relay, whose source is the apps/mobility/relay folder on GitHub, they run on the same code. Verification and Timesheet, two of the nine schemas (table definitions) in schemas.py, both declare "extends": "approval:base_approval", which borrows the platform's approval lifecycle, and each has a child step schema extending approval:base_approval_step. Among the 19 apps in the repo, Relay is the only one in which two schemas extend the same service base.

Telling the service which approval you mean

Two schemas on one service means each call has to say which one it is about, and a helper called approvalOp in ui/app.js does that. Every approval call names its schemas through extending_schema and step_extending_schema: verification for a credential, timesheet for hours.
The whole approval surface is three operations, to submit, to approve a step and to reject one. The admin's credential queue calls approve_step on a verification. The facility's timesheet page calls approve_step on a timesheet.
Different screens. One mechanism.

One shift through the healthcare staffing marketplace, posting to payout

Shift extends booking:base_booking and is the only public schema, so the board of open shifts loads before anyone signs in. A facility posts a shift with a role and an hourly rate, and it sits at requested. A clinician claims it. That runs the booking service's book operation and stamps her username on the row. She checks in, then out. Checking out completes the booking, creates a Timesheet with hours and rate copied from the shift, adds its approval step and submits it, all inside one promise chain in a function named checkOut.
Credentials take a parallel route through a different service. Credential extends attachment:base_attachment and has a file attribute of type File; no other app in the repo extends attachment. The clinician uploads a licence, the record moves from pending_upload to uploaded, and a Verification is created and submitted for the admin. On approval the credential_verified workflow emails her. The queue also has a triage button that asks services.ai to list three things worth checking on that kind of credential, and shows a fixed sentence if the call fails.
Pay is modelled as a payment. Payout extends payment:base_payment, and the seeded payouts sit at pending or captured. The shift_settlement workflow in setup.py gives its first step a compensate block that calls refund_payment, and an admin panel can run it against a claimed or completed shift or run a drill copy, shift_settlement_failtest, whose second step is written to fail, so the reversal is the only thing left for the engine to do.

Records with two rightful readers

A timesheet belongs to the clinician who worked the shift. It also belongs to the facility that must approve it. An owner filter matches one field, so setup.py leaves shifts, timesheets and contracts shared across the tenant and locks individual fields instead:
python
        PolicyRule(entity="shift", can_read=True, can_create=True, can_update=True,
                   readonly_fields=["workflow_status", "processed_at"]),
        PolicyRule(entity="timesheet", can_read=True, can_create=True, can_update=True,
                   readonly_fields=["workflow_status", "processed_at"]),
        PolicyRule(entity="timesheet_step", can_read=True, can_create=True, can_update=True),
        PolicyRule(entity="contract", can_read=True, can_create=True, can_update=True,
                   readonly_fields=["billing_amount", "plan_name", "shifts_per_period"]),
A tenant_user can create and edit a timesheet but cannot write workflow_status or processed_at. On a shift, the last step of the settlement workflow is the one declared to write them.
Private records go the other way. Credentials and their verifications, payouts and profiles: each of those rules carries filter_field="owner_username", policy-based row scoping, and a clinician reads only her own. The policy file knows two roles. An admin is tenant_admin and everyone else is tenant_user. The app still shows three personas, because a persona field on each Profile row says whether a tenant_user is a clinician or a facility, and the shell picks the interface from that. The sign-up tab creates a clinician profile with credentialed set to false.

The live board, then your own

The login page at relay.supero.live has a button for each persona. Anonymous requests to its public endpoint returned the shift list for shift and 403 for timesheet and credential on 2 October 2026.
The seed in setup.py posts 11 shifts for one facility and creates three clinicians holding five credentials between them. It also writes three timesheets and leaves one of them pending, so the facility login has something to approve straight away. The hosted board held 16 shifts when I looked, five more than the seed.
bash
git clone https://github.com/supero-platform/supero-apps
cd supero-apps/apps/mobility/relay
cp .env.example .env    # set SUPERO_DOMAIN and SUPERO_PASSWORD
./run.sh
No Supero account is required: the first run claims the domain name from your .env and has the marketplace up in about two minutes. The code in the relay folder is MIT. The hosted platform underneath is not open source.
Nursing is one two-sided market with a credential check in the middle. If yours is tutors or locum vets, the schema file you would write begins at https://www.supero.dev.