Files
observatory/docs/PWA.md
T
gamertan 92a66db3df docs: publish Preview 19 dogfood evidence
Export the reviewed allowlisted snapshot from private source commit 05928cebd01b586cf9e9d4b8c8537a7605a6068c. This records the exact candidate, bounded capacity result, stateful migration scratch requirement, authenticated batch identity proof, and immediate live acceptance evidence.

AI-Assisted: OpenAI Codex
Signed-off-by: Cole Speelman <crspeelman@gmail.com>
2026-08-18 21:47:08 -04:00

4.2 KiB

Progressive web application boundary

Observatory's PWA support adds availability without turning browser storage into an implicit telemetry replica.

The deterministic service worker precaches only:

  • the public offline explanation;
  • content-addressed CSS and JavaScript; and
  • the content-addressed application icon.

It does not automatically cache authenticated navigation responses. On the incident page, an authorized user may explicitly save a separate read-only snapshot. The worker validates both same-origin URLs, requires one matching organization selector, fetches with the current session, verifies a successful HTML response, and stores that response under the ordinary inbox URL.

The saved page contains the organization name plus current incident titles, states, severities, and times. It excludes incident identifiers, response forms, CSRF tokens, saved-query text, telemetry values, actor identifiers, and project, environment, and service identifiers. The page is not an authority for response actions; reconnection is required.

Signing out sends a private-cache deletion request before submitting the ordinary sign-out form. An expired server session cannot notify a disconnected browser, so operators should treat saved incident snapshots like any other explicitly downloaded sensitive material on that device.

The Badging API receives only the current open-incident count when supported.

Optional Web Push

Web Push follows RFC 8291 message encryption and RFC 8292 VAPID authentication. It is disabled unless the server configuration names a VAPID private-key file, contact subject, bounded queue, and request timeout. Create a new private key without exposing it in command arguments or output:

observatory admin web-push generate-key \
  --output-file /etc/gamertan-observatory/web-push.json

The output is created exclusively as a mode-0600 regular file. The installed systemd unit copies that root-owned source into its private credential directory as web-push.json, and the non-root server configuration references only that runtime copy. Do not place the key value in configuration, process arguments, deployment manifests, or source control:

"web_push": {
  "private_key_file": "/run/credentials/gamertan-observatory.service/web-push.json",
  "subject": "mailto:security@sandwichhime.com",
  "queue_capacity": 64,
  "request_timeout": "10s"
}

The source key remains /etc/gamertan-observatory/web-push.json, owned by root with mode 0600. LoadCredential= makes the service-specific runtime copy readable without granting the static service account access to /etc or weakening the original file. A differently named service must update both the unit and the credential-directory path explicitly; Observatory does not search for secrets.

An authorized incident reader must press the browser control before Observatory requests notification permission or creates a subscription. One browser endpoint is owned by one user and may be mapped to several of that user's organizations. Removing one organization keeps the browser subscribed until its final mapping is removed. Authorization is checked again for every delivery; revoked access retires only that organization's mapping. Endpoints are accepted only as bounded HTTPS push-service URLs and delivery uses a redirect-free client that rejects DNS results containing non-public IP addresses.

Only a transition into firing enqueues a notification. The bounded queue is best effort and never blocks alert evaluation or incident persistence. The encrypted payload is always exactly:

Gamertan Observatory needs your attention.

The service worker ignores incoming payload content and renders that same fixed sentence. It includes no organization, host, service, severity, rule, incident identifier, count, or telemetry text. Activating it opens /app/, where the user must have a valid authenticated session before seeing details. Browser-vendor push relays remain an explicit metadata boundary: they can observe delivery timing, endpoint identity, and the fixed payload size even though they cannot read its encrypted content.