Skip to content
Written with Claude

Changelog v3.16.3 (2026-06-03)

Version 3.16.3 (2026-06-03)

Full Changelog

Patch release that lets static-content parsing template environment-variable values into served files, alongside the existing per-user claim templating. This is aimed at Single-Page Apps deployed to Kubernetes: the SPA bundle is built once, and app-wide values (BUILD_LABEL, feature-flag toggles, analytics IDs) are injected from pod env vars at boot without rebuilding the bundle per environment.

What changed

AvailableEnvVars under StaticFiles:ParseContentOptions

A new optional config key lists environment variable names whose values are templated into static content using the same {NAME} tag syntax the claim path already uses:

jsonc
jsonc
"StaticFiles": {
  "Enabled": true,
  "ParseContentOptions": {
    "Enabled": true,
    "FilePaths": [ "/index.html" ],
    "AvailableClaims": [ "user_id", "user_name" ],
    "AvailableEnvVars": {
      "BUILD_LABEL": "local",
      "DEMO_FLAG": "false",
      "TRACKING_ID": ""
    }
  }
}
html
html
<script>
  window.__appConfig = {
    userId: {user_id},          // claim → 123 or null
    buildLabel: {BUILD_LABEL},  // env   → "demo" (or "local" default)
    demoMode: {DEMO_FLAG} === "true"
  };
</script>

Behaviour details:

  • Two forms. AvailableEnvVars accepts an array of names (["BUILD_LABEL"]; a missing variable resolves to the empty string) or an object of name→default pairs ({"DEMO_FLAG":"false"}; the default is used when the variable is absent). AvailableClaims gains the same object form, so an absent claim can resolve to a configured default instead of NULL.
  • Resolved once at startup. Env values are read at parser construction. A K8s pod restart re-reads them; changing a value in a running process is not picked up.
  • JSON-escaped, like claims. Each value is substituted as a complete, escaped JSON literal, so templates use a bare {NAME} token (no surrounding quotes) and an accidental quote/backslash in a value cannot break the JS string.
  • Claims win on collision. If a name exists both as a user claim and an env var, the per-request claim value takes precedence.

Security note

Anything listed in AvailableEnvVars is templated into static content served to any client — treat it as a public allowlist. Never list a secret (database password, API key, signing token). Resolution is an explicit per-name lookup; the whole environment is never exposed. This is distinct from the server-side Config:ParseEnvironmentVariables mechanism, which substitutes {ENV} tokens into appsettings.json values that never leave the server.

This is fully backward compatible: the new key is optional, and configs that omit it behave exactly as before.

Comments