Positions & terminals — the concepts
The Positions & shared terminals page is the admin workflow (click here, enable that). This page explains the model behind it — what the building blocks are, how they connect, and how it feels in daily use. Protocol details live under Integrate → Position terminals.
The four building blocks
Two of them live in Modgud, two in the real world:
The position is the star of the model: a business role staffed by changing people. It receives rights through the ordinary groups & roles machinery, but it never signs in — it gets activated (more on that below). For downstream systems, the gate acts — never Anna or Ben.
Everything is a link
The whole system is three links between those blocks. Each has its own moment, its own flow — and answers a different question.
| Link | Question it answers | When & how |
|---|---|---|
| ① Person ↔ Position | Who may staff this post? | A simple list on the position ("authorized users"). Grant, suspend, revoke — takes effect immediately. |
| ② Terminal ↔ Position | Where may this post be staffed? | An authorization assignment. One terminal may carry several positions, selected for each shift. |
| ③ Device ↔ Terminal | Which hardware actually stands there? | At installation, exactly once. DPoP pins a device key, client-secret identifies its holder, while none deliberately leaves this link unproven. |
Mnemonic
Link ① says who, ② says where, ③ says with what. The daily unlock is not a fourth link — it is the moment all three are checked at once.
The realm security floor decides how strong links ① and ③ must be. A weaker position policy cannot silently undercut that floor.
For engineers: ① is the grant, ② is the terminal slot with its auto-created OAuth client, ③ is the enrollment (device key binding). The client appears in the OAuth grid as inventory only — everything is managed in the position.
A position is not a group
The most tempting confusion — and the most important distinction in the model:
The one-liner
A group distributes rights. A position acts.
- Group "porters" with Anna as member: rights flow to the person. Anna acts, under her own name, with the group's rights. The group itself never appears at runtime — no tokens, no sessions. It is a distribution mechanism.
- Position "gate" with Anna authorized: rights never flow to Anna! The grant gives her no right of the gate — only the ability to switch the gate on. Then the gate acts, with its rights. Anna's own permissions are irrelevant during the shift.
The authorized-users list looks like membership but is a key cabinet: "these people may start the engine", not "these people are the engine". And the two concepts stack instead of competing — the position receives its own rights through groups, like any other principal.
Same person, two devices, two actors
This is why the terminal is hardened more than the PC next to it: it is the vessel for the post's rights, which can exceed those of any single person in front of it. Security scales with the position's rights, not the person's. The inverse exists too — a kiosk position can deliberately hold fewer rights than the human in front of it.
A position never authenticates — it gets activated
A position has no login credential of its own (that is the difference to a service account, which identifies itself, from anywhere). Every position token starts with an allowed activation proof — a person proving themselves or a position-owned hardware token — at an enrolled terminal. The chain is strict:
Position → terminal assignment → enrolled device → allowed activation proof → sessionNo slot → no device → no unlock → never a token. A position without terminals is valid, but dormant: configuration waiting for hardware.
A shift at the gate
- 06:02 — Anna taps. Modgud checks all three links at once: is this the real device (③)? may the gate run here (②)? may Anna staff the gate (①)? → unlocked. From now on the terminal acts as the gate.
- Handover: Ben taps → Anna's shift ends automatically, his begins. Exactly one shift runs per terminal at any time.
- Locking: at the device, or remotely by an admin (force-lock, effective immediately — terminal tokens are revoked on the spot).
- Time limits: every shift ends at the configured ceiling at the latest (default 16 h, absolute maximum 24 h), even if nobody locks.
- Cascades: deactivating Anna, revoking her grant, disabling the slot or the position — each ends the affected running shift automatically.
What the audit attests — and what it doesn't
The staffing audit attests the unlock, not each action:
06:02 gate / left terminal unlocked by Anna
07:15 alarm #4711 acknowledged by "the gate"
14:01 handover: Anna's shift ended, unlocked by Ben
17:40 force-lock by admin — terminal lockedWho actually clicked the alarm at 07:15 is not recorded — if Anna was on a break and a colleague clicked, the log still shows Anna's shift. That is not a gap; it is the nature of every shared device. What the model guarantees: only authorized people can unlock, and who unlocked is cleanly recorded. Accountability is session-level, not action-level. For a critical action, the consumer can request a fresh step-up proof. Modgud then returns a separate access token valid for at most 60 seconds; it may be bound to an action and consumer nonce and is intended to be consumed once by jti.
Which principal for which job?
| If … | … then |
|---|---|
| a person acts and must appear in the business data (receipt, ticket, signature) | ordinary user login — also on a shared device, with fast switching |
| a post acts that has to be activated (gate, control room, reception) | position + terminals — this model |
| a machine acts, with no human activation at all (sealed appliance, server job) | service account |
The test question in one sentence: "Who owns what the system does — the person, the post, or the machine?" One concept per answer, and no fourth is needed. (A group is none of the three — it distributes rights, it never acts.)
Policy choices and guard rails
How people and devices prove themselves is a per-position policy. Multiple activation classes can be enabled together; DPoP + personal passkey remains the recommended default.
- Activation proof: personal passkey, personal password, personal e-mail OTP, or a position-owned activation token. The token is a logical, individually revocable object with an RP-bound WebAuthn credential; the audit names the token rather than a person.
team-secretis reserved for a future feature and is deliberately unavailable today. - Device binding: DPoP key, client secret, or none. Client-secret and none still run the complete admin-approved Device Flow;
noneonly removes a cryptographic device identity and is appropriate only where the physical and network controls justify it. - Realm guard rails: the realm declares required proof and binding capabilities. Tightening a floor first previews affected positions and, when confirmed, immediately ends sessions that no longer comply.
- Multi-position terminals: one device may serve several positions ("reception" by day, "night gate" after hours). New assignments are fixed before enrollment; adding one later requires a replacement slot and fresh approval. Exactly one active shift still exists per terminal.