Skip to content

M16.8 Public status pages on a custom domain #71

Closed as not planned
Closed as not planned

Description

@productdevbook

Part of #63. Needs M16.7 (and through it M16.4).

yuva-api

  • status_pages: slug (default address /status/{slug}/), name, logo, light and dark accent colours, theme, languages, time zone, visibility (public, password, members at the default address only), groups of components (services, dependencies, checks with public names; unlisted ones stay private), manual overrides, auto_publish, the inbox and e-mail channel for subscriber mail.
  • 90-day uptime per component from monitor_state_changes, response time for check-backed components from monitor_check_days; incidents and maintenance from M16.7 with their published updates.
  • Rendering: html/template with the server's en, tr, de catalogs, no JavaScript, a nonce'd inline stylesheet, light and dark, text for every state; a snapshot per page rebuilt on change and every 60 s; Cache-Control: public, max-age=30 with ETag; no cookie except the password unlock, no script, no address logged.
  • /status.json (CORS *), /feed.rss, /feed.atom, /badge.svg, /embed (the only framable path), /subscribe.
  • Subscribers: a mailing list of the page's inbox made with the page (M13 double opt-in, consent events, unsubscribe, suppression); a plain POST form with a sealed form token and honeypot; notices as broadcasts of kind status from a fixed template through broadcast_send (approval gate and daily cap kept); members choose per update whether it notifies. No public webhook subscriptions; workspace webhooks get monitor.incident.
  • Custom domains (status_page_domains, 5 per page): CNAME to YUVA_STATUS_CNAME (or matching A/AAAA at an apex) plus a TXT token at _yuva-status.<hostname>; status_domains job (5 minutes while pending for 7 days, hourly once verified, unserved after 72 h without the records); a verified host serves only its page's paths.
  • TLS: YUVA_STATUS_TLS=proxy (default) with GET /status-domains/check?domain= for Caddy's on-demand ask; YUVA_STATUS_TLS=acme with a TLS listener on YUVA_STATUS_TLS_ADDR serving verified hosts by SNI only, status_cert jobs through golang.org/x/crypto/acme and HTTP-01 from acme_challenges on the main listener, ECDSA keys sealed in tls_certificates, renewal at two-thirds of the lifetime, backoff under the CA's failure limits, acme_accounts; tested against Pebble in CI.

yuva-panel

  • Status page editor with a live preview: branding, components and groups, domain setup with the CNAME and TXT records to add and their verification and certificate state, incident and maintenance editor with a timeline and the notify switch, subscriber list. en and tr.

yuva-docs

  • Status pages, custom domains (CNAME, TXT, apex records, both TLS modes for self-hosting), incident updates and subscribers; en, tr, de.

Done when

A workspace connects status.<test domain> with a CNAME and TXT record and the page loads over HTTPS with a certificate the server obtained (Pebble in CI), and through a proxy whose ask call the server answers; a second workspace cannot claim the same hostname; stopping a sample service's dependency turns its component degraded, opens an incident on the page and e-mails a confirmed subscriber once; resolving it updates the page, the feeds, the badge and the JSON endpoint; the page works with JavaScript off and passes an accessibility check in en, tr and de.

Activity

  1. productdevbook commented on Oct 14, 2026

    @productdevbook
    OwnerAuthor

    Closed for now: the API monitoring work moved off main into #72 and is not on the roadmap until that PR is reviewed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions