Bound a panel credential to its own widgets, and let one screen be re-paired
Three things a paired wall panel needed.
The scope check now walks the panel's widgets instead of allowing the
`/messages/` prefix wholesale: a screen may publish what its own controls and
querying charts point at, read the history of what its tiles draw, and nothing
else — the catalogue of every message in the installation included. The same
walk that already bounds its socket, so both surfaces agree.
Pending pairing codes moved out of the per-process dictionary into Redis, keyed
per code with the code's own TTL and indexed in a zset so the fifty-code cap
means the same thing to every worker. Without a Redis there is one process by
definition, and the dictionary stays.
And a per-panel nonce in the token, bumped by `POST /panels/{id}/unpair`: that
refuses the screen hanging there without touching the panel, its dashboards or
their arrangement. A save cannot write the nonce back, so a stale client cannot
undo a revocation. Only for a credential this installation signed — one the
portal minted carries no nonce and is revoked at the hub.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tULRZJUkZsw7rMJ3h4xvu
This commit is contained in:
@@ -174,7 +174,7 @@ def decode_worker_token(token: str) -> dict[str, Any]:
|
||||
|
||||
|
||||
def create_panel_token(
|
||||
panel: str, user_id: uuid.UUID | str, expires_delta: timedelta
|
||||
panel: str, user_id: uuid.UUID | str, expires_delta: timedelta, nonce: int = 0
|
||||
) -> str:
|
||||
"""The credential a paired wall panel holds.
|
||||
|
||||
@@ -185,6 +185,11 @@ def create_panel_token(
|
||||
``fluksio.api.deps`` lets it reach only that panel's dashboards and the message
|
||||
endpoints its widgets need.
|
||||
|
||||
``pnc`` is the panel's nonce at the moment of pairing, and the filter
|
||||
refuses a credential naming any other. Bumping the panel's nonce is
|
||||
therefore how one screen is re-paired without deleting the panel out from
|
||||
under its dashboards.
|
||||
|
||||
Long-lived on purpose: a wall tablet is set up once and left running, and
|
||||
it has no keyboard to log in again with.
|
||||
"""
|
||||
@@ -193,6 +198,7 @@ def create_panel_token(
|
||||
"sub": str(user_id),
|
||||
"aud": PANEL_AUDIENCE,
|
||||
"panel": panel,
|
||||
"pnc": nonce,
|
||||
"iat": now,
|
||||
"exp": now + expires_delta,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user