Pair a wall panel through the portal

A screen somewhere this installation is not reachable from asks the portal for
a code instead, and the portal mints its credential — because a token signed
here is one such a device could never present.

Where it was minted changes nothing about what it may do. The panel gate moved
off the branch that decodes a local panel token and onto whatever claims name
a panel, so the portal's and this installation's are bounded by the same check
against the same panel's dashboards. A token of that scope naming no panel is
refused rather than left holding the account it borrows.

The connector marks what arrives on its socket, since that is the only thing
that makes it true, and the approval screen now names what is holding a code —
approving adopts whatever answers, so it is worth a look first.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017F9RnYCJgASuBTcAjxmnsp
This commit is contained in:
2026-08-20 23:42:58 +02:00
co-authored by Claude Opus 5
parent bf531309e9
commit 4c8339e643
17 changed files with 695 additions and 175 deletions
+23 -3
View File
@@ -2075,9 +2075,29 @@ export const PanelsPublicSchema = {
The address is the server's own, because the browser's origin is not a
reliable answer to it: an admin working through the portal is on the
portal's origin, and a screen cannot be sent there — the portal serves a
page only to someone holding a portal session, and the credential it hands
that page is the portal's rather than the panel's.`
portal's origin, and this one is for a screen on this network.
An installation enrolled with a portal has a second address, built by the
dialog from what \`\`/cloud/status\`\` reports rather than from here — a panel
is not the thing that knows whether remote access is on.`
} as const;
export const PendingDeviceSchema = {
properties: {
device: {
type: 'string',
title: 'Device'
},
remote: {
type: 'boolean',
title: 'Remote',
default: false
}
},
type: 'object',
required: ['device'],
title: 'PendingDevice',
description: 'Who is asking, as far as the request itself says.'
} as const;
export const PlacementSchema = {