From 04e83f64a9eec4a7b9bddabf7b7debdaa7f61299 Mon Sep 17 00:00:00 2001 From: John Coffey Date: Sat, 22 Aug 2026 16:13:10 -0700 Subject: [PATCH] Prefill the demo's login and say on its home page that it's a simulation Two demo-only affordances, both off by default everywhere else. The login form starts with the demo's read-only account already in both fields, so a visitor doesn't need credentials handed to them out of band. It's a build-time opt-in: the web image is built with VITE_DEMO_USERNAME/VITE_DEMO_PASSWORD, and the page prefills only when it has both, so a deployment that sets neither -- every deployment except the demo -- gets the ordinary empty form, and a half-configured one can't leave a password next to an empty username box. This does bake a password into a static bundle, which is fine for exactly this case and nothing else: a Viewer-role account on a deployment whose database is wiped and reseeded nightly. api.ts says so next to the export, so nobody later points these at an account that can do something. The home page then explains what a visitor is actually looking at -- synthetic data from a simulated fleet, a nightly reset that discards anything they change, and the features that are deliberately limited (read-only account, alerts that notify a placeholder webhook, no time-series charts). Gated on the same signal as the prefill rather than a second flag that could drift out of sync with it. Also carries the landing page's light/dark logo swap, which touches the same file. --- web/Dockerfile | 8 ++ web/src/lib/api.ts | 22 +++++ web/src/lib/components/DemoNotice.svelte | 113 +++++++++++++++++++++++ web/src/routes/+page.svelte | 14 ++- web/src/routes/login/+page.svelte | 33 ++++++- 5 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 web/src/lib/components/DemoNotice.svelte diff --git a/web/Dockerfile b/web/Dockerfile index 3bf0ab1..780b6e9 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -28,10 +28,18 @@ ARG VITE_ENTERPRISE_AUTH_BASE_URL # actually turned local auth on server-side too (LOCAL_AUTH_ENABLED). # See api.ts's requestFrom/alertingRequest doc comment. ARG VITE_LOCAL_AUTH_ENABLED=false +# Both unset by default: the login page only prefills when it has both, +# so every deployment that doesn't opt in gets an ordinary empty form. +# See web/src/lib/api.ts's demoUsername on why a public demo can bake a +# password in and nothing else should. +ARG VITE_DEMO_USERNAME +ARG VITE_DEMO_PASSWORD ENV VITE_API_BASE_URL=${VITE_API_BASE_URL} ENV VITE_ALERTING_API_BASE_URL=${VITE_ALERTING_API_BASE_URL} ENV VITE_ENTERPRISE_AUTH_BASE_URL=${VITE_ENTERPRISE_AUTH_BASE_URL} ENV VITE_LOCAL_AUTH_ENABLED=${VITE_LOCAL_AUTH_ENABLED} +ENV VITE_DEMO_USERNAME=${VITE_DEMO_USERNAME} +ENV VITE_DEMO_PASSWORD=${VITE_DEMO_PASSWORD} RUN npm run build # Not distroless: serving a static SPA needs *some* HTTP server, and diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index ab511c1..4f892be 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -26,6 +26,28 @@ export const enterpriseAuthBase = import.meta.env.VITE_ENTERPRISE_AUTH_BASE_URL // which never sets either of these. export const localAuthEnabled = import.meta.env.VITE_LOCAL_AUTH_ENABLED === 'true'; +// Public-demo convenience: with both set at build time, the login page +// starts with these credentials already in the fields, so a visitor to a +// public demo can sign in without being handed a password out of band. +// Two separate vars, neither with a default, and the login page requires +// BOTH before prefilling anything -- a deployment that sets neither (every +// deployment except the demo) gets exactly today's empty form, and a +// half-configured one can't leave a password sitting next to an empty +// username box. +// +// This bakes a password into a static bundle, which is only acceptable +// for what it's for: a throwaway read-only Viewer account on a deployment +// whose entire database is wiped and reseeded nightly. Never point these +// at an account that can do anything worth doing. +export const demoUsername = import.meta.env.VITE_DEMO_USERNAME as string | undefined; +export const demoPassword = import.meta.env.VITE_DEMO_PASSWORD as string | undefined; + +// A deployment that prints its own login credentials on its login screen +// is, by definition, the public demo -- so the same two build args also +// gate the demo notice on the landing page, rather than a third flag +// that could drift out of sync with them. +export const isPublicDemo = Boolean(demoUsername && demoPassword); + export type Language = '' | 'sql' | 'spl'; // warnings (Phase 7) is populated by the shared costguard package's diff --git a/web/src/lib/components/DemoNotice.svelte b/web/src/lib/components/DemoNotice.svelte new file mode 100644 index 0000000..c115884 --- /dev/null +++ b/web/src/lib/components/DemoNotice.svelte @@ -0,0 +1,113 @@ + + + + + diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index 3829e79..9e96e60 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -7,6 +7,8 @@ import logoLight from '$lib/assets/logo-stacked-light.svg'; import { isLight } from '$lib/theme.svelte'; import { Button } from '$lib/components/ui'; + import DemoNotice from '$lib/components/DemoNotice.svelte'; + import { isPublicDemo } from '$lib/api'; const shortcuts: { href: string; label: string; hint: string }[] = [ { href: '/search', label: 'Search', hint: 'Query logs with filters, free-text, or raw SQL' }, @@ -16,13 +18,20 @@ ]; -
+ +

One query bar for filter/stats queries and free-text search across every host and service you're shipping logs from.

+ {#if isPublicDemo} + + {/if} +
{#each shortcuts as s (s.href)}