diff --git a/src/content/docs/changelog/index.mdx b/src/content/docs/changelog/index.mdx index 9dee55a2..233ea7f8 100644 --- a/src/content/docs/changelog/index.mdx +++ b/src/content/docs/changelog/index.mdx @@ -13,6 +13,7 @@ Notable changes to the kit, newest first. ## 2026-11-03 +- **Frontend containers: the inactivity timeout is configurable from the environment (fix).** Both apps read `inactivityIdleMs` and `inactivityWarningMs` from `/config.json`, but the container's `config.json.template` never carried them, so an operator could not change the auto sign-out time without rebuilding the image. The template now renders them from `FSH_INACTIVITY_IDLE_MS` and `FSH_INACTIVITY_WARNING_MS`. Unset or empty keeps the built-in timings (admin 10 minutes, dashboard 20, each with a 60-second warning), so existing deployments behave as before; a value that is not a positive integer stops the container at start with a clear error rather than rendering invalid JSON. `deploy/docker` exposes them as `FSH_ADMIN_INACTIVITY_IDLE_MS`, `FSH_DASHBOARD_INACTIVITY_IDLE_MS` and `FSH_INACTIVITY_WARNING_MS` in `.env`. The Terraform static-site `runtime_config` and the Aspire dev setup are unchanged. See [Frontend development](/docs/frontend/development/#the-container-pattern) and [#1442](https://github.com/fullstackhero/dotnet-starter-kit/pull/1442). - **Dashboard: the overview welcomes the tenant by its name (fix).** The first-run card on a tenant with no subscription read "Welcome to" followed by the tenant identifier (for example `qpb2edshbj`), and the header caption showed the same identifier, because both came from the token's `tenant` claim. Both now use the tenant name from `GET /api/v1/tenants/me/status`, which the overview already loads for its "Valid for" card, and fall back to the identifier while that call is loading or has failed. No backend change. See [Tenant dashboard](/docs/frontend/dashboard/#page-inventory) and [#1437](https://github.com/fullstackhero/dotnet-starter-kit/pull/1437). - **Both apps: non-ASCII claims in the access token now render correctly (fix).** `decodeJwt` decoded the token payload with a bare `atob`, which returns one character per byte, while the payload is UTF-8. A display name like "Comitê de Ética" therefore showed as "Comitê de Ética" in the user menu and the overview greeting, even though the token and the database were correct. The payload bytes are now decoded as UTF-8 in both the dashboard and the admin console. No configuration change. See PR [#1439](https://github.com/fullstackhero/dotnet-starter-kit/pull/1439). diff --git a/src/content/docs/frontend/architecture.mdx b/src/content/docs/frontend/architecture.mdx index 3709eeab..c488f2b4 100644 --- a/src/content/docs/frontend/architecture.mdx +++ b/src/content/docs/frontend/architecture.mdx @@ -1,6 +1,6 @@ --- title: Frontend architecture -lastUpdated: 2026-06-11 +lastUpdated: 2026-10-14 description: Shared patterns across the admin + dashboard apps - folder layout, API client, route guards, realtime context, error handling, ProblemDetails parsing. sidebar: label: Architecture @@ -261,7 +261,7 @@ In dev, Vite serves `public/config.json`; in production, the Nginx container ren ### Inactivity auto sign-out -Both apps auto-sign-out idle sessions: admin after 10 minutes, dashboard after 20, each with a 60-second warning countdown - all four numbers configurable per deploy in `config.json`. The last-activity timestamp is shared across tabs via the `fsh.lastActivity` localStorage key so activity in any tab keeps the whole session alive. +Both apps auto-sign-out idle sessions: admin after 10 minutes, dashboard after 20, each with a 60-second warning countdown - all four numbers configurable per deploy in `config.json`. In the container images set `FSH_INACTIVITY_IDLE_MS` and `FSH_INACTIVITY_WARNING_MS` (milliseconds); see [development](/docs/frontend/development/#the-container-pattern). The last-activity timestamp is shared across tabs via the `fsh.lastActivity` localStorage key so activity in any tab keeps the whole session alive. ## What both apps don't do diff --git a/src/content/docs/frontend/development.mdx b/src/content/docs/frontend/development.mdx index c2741bb2..bfec88ae 100644 --- a/src/content/docs/frontend/development.mdx +++ b/src/content/docs/frontend/development.mdx @@ -1,6 +1,6 @@ --- title: Local development -lastUpdated: 2026-09-26 +lastUpdated: 2026-10-14 description: Running the React frontends with Vite HMR, building for production, deploying to static hosts or behind Nginx, runtime config via /config.json. sidebar: label: Local development @@ -113,6 +113,9 @@ The dashboard's variant swaps `dashboardUrl` for a `demoMode` flag (login-page d # clients/{app}/docker/docker-entrypoint.sh : "${FSH_API_URL:?FSH_API_URL is required (e.g. https://api.example.com)}" : "${FSH_DEFAULT_TENANT:=root}" +: "${FSH_INACTIVITY_IDLE_MS:=600000}" # admin; the dashboard defaults to 1200000 +: "${FSH_INACTIVITY_WARNING_MS:=60000}" +# ...exits with an error unless both inactivity values are positive integers envsubst < /etc/fsh/config.json.template \ > /usr/share/nginx/html/config.json @@ -127,6 +130,8 @@ The template lives at `/etc/fsh/config.json.template`, outside the web root, so { "apiBase": "${FSH_API_URL}", "defaultTenant": "${FSH_DEFAULT_TENANT}", + "inactivityIdleMs": ${FSH_INACTIVITY_IDLE_MS}, + "inactivityWarningMs": ${FSH_INACTIVITY_WARNING_MS}, "dashboardUrl": "${FSH_DASHBOARD_URL}" } ``` @@ -139,6 +144,16 @@ docker run -e FSH_API_URL=https://api.example.com -e FSH_DASHBOARD_URL=https://a The same image runs everywhere; only env vars differ. +| Variable | Apps | Default | Maps to | +|---|---|---|---| +| `FSH_API_URL` | both | required | `apiBase` | +| `FSH_DASHBOARD_URL` | admin | required | `dashboardUrl` | +| `FSH_DEFAULT_TENANT` | both | `root` | `defaultTenant` | +| `FSH_INACTIVITY_IDLE_MS` | both | admin `600000` (10 min), dashboard `1200000` (20 min) | `inactivityIdleMs` | +| `FSH_INACTIVITY_WARNING_MS` | both | `60000` (60 s) | `inactivityWarningMs` | + +The two inactivity values are bare JSON numbers in the template, so the entrypoint validates them: unset or empty keeps the default, and anything that is not a positive integer (`abc`, `0`, `-5`, `1.5`) stops the container at start with an error instead of serving a broken `config.json`. The entrypoint defaults mirror the ones in each app's `src/env.ts`; change both together. The Docker Compose deployment reads `FSH_ADMIN_INACTIVITY_IDLE_MS`, `FSH_DASHBOARD_INACTIVITY_IDLE_MS` and `FSH_INACTIVITY_WARNING_MS` from `.env`, because the two apps default to different idle times. + ### Reading runtime config in code ```ts