Skip to content

Session-Based Action Authorization

Actions dispatched by the control plane are implicitly authorized: they arrive in the executions block of the node's authenticated state pull, so the control plane has already decided the node may run them. Actions triggered locally via plexd actions run in an SSH session require explicit authorization through a session-scoped JWT.

Authorization Flow

User                Platform / CP              plexd (Target Node)
 |                       |                            |
 |-- Request SSH ------->|                            |
 |   session             |-- Check RBAC               |
 |                       |   (user x node x actions)  |
 |                       |                            |
 |                       |-- Issue session JWT        |
 |                       |   { sub, node_id,          |
 |                       |     actions, exp }         |
 |                       |                            |
 |                       |-- Session in the state --->|
 |                       |   pull's sessions block    |-- Start SSH session
 |<======== SSH session (tunneled through mesh) =====>|-- Inject PLEXD_SESSION_TOKEN
 |                       |                            |
 |-- plexd actions run -------------------------------->|
 |   diagnostics.collect |                            |-- Read token from env
 |                       |                            |-- Validate JWT (local)
 |                       |                            |-- Check action scope
 |                       |                            |-- Execute
 |<-- Result ----------------------------------------------|
 |                       |<-- Callback (result + -----|
 |                       |    session context)        |

Session JWT Structure

json
{
  "iss": "plexsphere",
  "sub": "user_abc123",
  "email": "admin@example.com",
  "node_id": "n_xyz789",
  "session_id": "sess_a1b2c3",
  "actions": [
    "diagnostics.*",
    "health.check",
    "hooks/backup"
  ],
  "iat": 1705312200,
  "exp": 1705341000
}

The JWT is signed with the control plane's Ed25519 key. plexd receives the corresponding public key during registration and uses it for local validation - no roundtrip required.

Action Scope Patterns

PatternMatches
*All actions and hooks
diagnostics.*All actions in the diagnostics namespace
hooks/*All hooks (script and CRD)
hooks/backupOnly the backup hook
health.checkExactly one action

Authorization Tiers

TriggerAuthenticationAuthorization
Pull (control plane)NSK-authenticated state pullPre-authorized by the control plane: an entry in the executions block is the authorization, and the dispatch decision is the control plane's alone
SSH via access proxyPLEXD_SESSION_TOKEN (JWT)Local JWT validation + action scope check
Direct SSH (no token)No token presentDenied (or control-plane roundtrip if online)
Local root access--local flag, root or plexd user onlyNo scope limit, emergency use

Trigger attribution — who asked for a control-plane execution — lives in the control plane's audit trail, not on the node: the pull entry carries no requester identity.

Token Revocation

Revocation is not pushed to the node as a command. When a session ends (disconnect, admin termination, timeout), the control plane drops its entry from the sessions block of the node's state pull, and the next reconcile observes the absence: that absence is the teardown signal. plexd closes the session and, for a session whose listener it provisioned, reports a session_ended activity row with terminated_by: plexd_close — the node cannot tell a revocation from a control plane that failed to serve the block, so it does not claim an operator action. There is no revocation callback to answer and no terminal status to report — see Secure Access Tunneling for the dispatcher that performs the teardown.

The session_revoked SSE event only shortens the window. Its payload is never parsed; it triggers a reconcile so the drain is observed now rather than on the next scheduled cycle, and a node that misses the event converges on its own cadence.

The session JWT itself is not revoked on the node. plexd keeps no local revocation set: local validation covers the signature and exp, so a token already handed out stays usable for its remaining lifetime. Keeping session tokens short-lived is what bounds that window.

Local Transport via Unix Socket

The plexd actions run CLI does not execute actions directly. It connects to the plexd daemon via a Unix socket (/var/run/plexd.sock), ensuring locally triggered actions go through the same path as control-plane-dispatched ones: token validation, integrity checks, sandbox, resource limits, and audit.

plexd actions run diagnostics.collect --param include_network=true
       |
       |-- Unix socket (/var/run/plexd.sock) --> plexd daemon
                                                    |-- Validate session JWT
                                                    |-- Check action scope
                                                    |-- Verify hook integrity
                                                    |-- Apply sandbox + limits
                                                    |-- Execute
                                                    +-- Report to control plane