The PVS is a private-network appliance with a self-signed certificate. The browser is untrusted with respect to PVS secrets. The local HelioSlate API binds to loopback only and validates same-origin mutation requests.
The production PVS layer has no general request method. Callers can choose only typed read queries:
- exact variable names;
- substring match;
- tag;
- existing cache identifier;
- a read query paired with a cache identifier.
The only network method is GET and the only paths are /auth and /vars.
Selector names are closed over name, match, tag, cache, and fmt.
Values are validated as data, never concatenated into a URL. Redirects are
disabled. Private IPs are required. Any appearance of set or mutation syntax
is rejected before I/O.
First-use certificate inspection performs a dedicated TLS handshake with verification disabled solely to obtain the leaf DER certificate. HelioSlate shows its SHA-256 fingerprint and does not authenticate until the user approves it. The exact DER certificate and fingerprint are stored locally. Every authenticated connection checks the live fingerprint before sending a credential and uses an SSL context anchored to the approved certificate. Fingerprint changes fail closed.
The credential is the last five characters of the PVS serial. It is stored by
keyring under HelioSlate.PVS and a username scoped to the configured PVS
address. Session cookies exist only in the in-memory HTTP client and are
discarded at logout or process exit. Structured logs and diagnostics pass
through recursive redaction.
On firmware that exposes /sys/info/serialnum as limited unauthenticated
Varserver data, HelioSlate requests it only after the owner approves the PVS
certificate. The full serial remains inside the backend call long enough to
derive the suffix and is neither returned by the setup API nor persisted.
Automatic and manually entered credentials are authenticated through the pinned
certificate before Windows Credential Manager stores them.
Production binds the mutable API to 127.0.0.1 on a dynamic port. Host mode
additionally exposes a fixed private-network HTTPS listener using a stable,
locally generated certificate. The private key is encrypted at rest with a
random password stored in Windows Credential Manager. The listener requires
TLS 1.2 or newer and rejects source addresses outside private IP ranges.
New dashboards first inspect the host certificate and require the user to compare its complete SHA-256 fingerprint. A single-use six-digit code then creates a pending request. It never issues a credential by itself. Approval and denial routes remain loopback-only; until approval, the joining computer has no snapshot, event, history, or tariff access.
Paired tokens authorize only snapshot, event, history, tariff, and node-status reads. Diagnostics, PVS setup, credentials, collection controls, and all other mutations remain loopback-only. Pairing codes expire after ten minutes, are single-use, and lock after eight failed attempts. Client tokens are 256-bit random values, hashed at rest on the host, stored by Windows Credential Manager on the client, immediately revocable, and expire after 180 days.
Loopback mutation requests validate that browser origins are themselves loopback origins, preventing a hostile DNS-rebinding host header from becoming an allowed origin. API responses are non-cacheable and include restrictive content, framing, referrer, permissions, opener, and resource policies.
The LAN interface is not a public internet endpoint and must never be forwarded through a router.
Optional remote access uses a second loopback-only portal on port 8766.
Tailscale Serve terminates private HTTPS and forwards authenticated identity
headers. HelioSlate trusts those headers only when the request arrived on the
dedicated portal; direct LAN and local-UI requests cannot use them to authorize
a remote identity.
The first authenticated visit creates a pending membership record. Middleware checks membership before calling telemetry handlers, so pending, denied, or revoked accounts receive only an authorization error and no solar payload. Approved remote accounts are restricted to the same read allowlist as paired dashboards. Every mutation and every owner/diagnostic endpoint remains local.
Owner binding, invitations, approvals, denials, and revocations are recorded in a separate WAL-mode SQLite database. Revocation takes effect on the next request because there is no independently valid HelioSlate browser token. Repeated remote requests are rate-limited. The owner must separately revoke the Tailscale machine share to remove the outer network grant.
The generated *.ts.net HTTPS certificate name is recorded in public
Certificate Transparency logs, but traffic and the service remain private to
authorized Tailscale identities.
The optional invitation website has a separate FastAPI application bound only
to 127.0.0.1:8767. Tailscale Funnel publishes that application on HTTPS port
8443. It is intentionally a different application and port from the private
dashboard portal: no HelioSlate solar, history, household, owner, diagnostic,
or mutation API route exists in the helper application.
The helper serves static HTML, CSS, and JavaScript with a restrictive Content
Security Policy. Invitation details are encoded after # in the invitation
URL. URL fragments are decoded in the recipient's browser and are not sent to
the public helper or Tailscale Funnel. Anyone can reach the helper's generic
instructions, but that alone grants neither Tailscale reachability nor
HelioSlate authorization.
Funnel uses the host's *.ts.net DNS name, so that certificate name is public
and the hostname must not contain sensitive information. Disabling the
household website removes only the port 8443 Funnel configuration; the
private port 443 Serve configuration remains separate.
Manual invitation delivery stores no Tailscale API credential: the owner creates a single-use machine share in Tailscale and pastes its link into HelioSlate. Optional automatic delivery uses a user-owned, expiring Tailscale API access token because Tailscale rejects machine-share creation from scoped trust-credential OAuth tokens. The token is stored in Windows Credential Manager. API and OAuth error messages never include credentials or arbitrary upstream response bodies.