Skip to content

Demonstration Mode Guide ​

Common

Demonstration Mode is an application-wide write-admission policy for shared demonstration deployments. It is provided by the first-party a-demo suite and uses a global Vona Guard to prevent ordinary visitors from changing demo data.

It is disabled by default. When enabled, it protects selected HTTP write methods while leaving the rest of the application's authentication and authorization policies in force.

What Demonstration Mode does—and does not do ​

Demonstration Mode is a safety rail for demo data. It is not a replacement for:

  • Passport authentication
  • RBAC or domain-specific authorization
  • validation and business rules
  • WAF, reverse-proxy, or network controls
  • database and other data-access safeguards

Approval by this Guard only lets the request continue to the normal request pipeline; it does not grant the caller any additional permission.

The policy applies to HTTP requests only. It does not protect side-effecting GET handlers, background jobs, scheduled work, queues, CLI execution, or other non-HTTP code. Model state-changing HTTP APIs with the protected write methods and retain their ordinary authorization rules.

Enable Demonstration Mode ​

Configure the backend environment and restart Vona:

dotenv
DEMONSTRATION_ENABLED=true
DEMONSTRATION_USERNAME_WHITELIST=admin,demo-editor

DEMONSTRATION_ENABLED enables the Guard only when its value is the exact lowercase string true. An unset value, an empty value, TRUE, True, and 1 all leave Demonstration Mode disabled.

Use Runtime and Flavors to select the active environment files and understand precedence. In a local backend setup, an uncommitted vona/env/.env.local is a typical place for local overrides. Deployment-injected environment values may also take precedence. For the broader configuration model, see the Config Guide.

Environment values are evaluated while the backend initializes. Restart Vona after changing either Demonstration Mode variable.

Configure exempt writers ​

DEMONSTRATION_USERNAME_WHITELIST is a comma-separated list of usernames that may perform protected writes:

dotenv
DEMONSTRATION_USERNAME_WHITELIST=admin, demo-editor, content-manager

The list is normalized as follows:

  • surrounding whitespace is removed from each entry
  • empty entries are discarded
  • repeated entries are deduplicated
  • usernames match entries exactly and case-sensitively

Whitelist membership is necessary but not sufficient. A protected write is admitted only when the current user is all of the following:

  • authenticated
  • account-active
  • non-anonymous
  • present in the username whitelist

If the whitelist is absent or empty while Demonstration Mode is enabled, no user qualifies for protected writes.

Request behavior ​

The Guard protects these HTTP methods:

  • POST
  • PATCH
  • DELETE
  • PUT

Other methods pass through this Guard unchanged. Apart from the built-in authentication routes and the conditional logout policy, a protected request is allowed only for an eligible whitelisted user. All other protected requests are rejected with:

FieldValue
HTTP status403 Forbidden
Application error codedemo-demonstration:1001
MeaningThe operation is forbidden in demonstration mode.

The Guard depends on Passport-resolved account state, so it makes this decision only after the current account information is available. Passing the Demonstration Mode check does not bypass later Passport, RBAC, or business-policy checks.

Exempt authentication routes ​

Demonstration Mode deliberately does not apply to the standard authentication and OAuth routes below. This keeps sign-in, registration, account association and migration, OAuth callbacks, and token flows available while the write policy is active.

text
/home/user/passport/register
/home/user/passport/login
/home/user/passport/login/:module/:providerName/:clientName?
/home/user/passport/associate/:module/:providerName/:clientName?
/home/user/passport/migrate/:module/:providerName/:clientName?
/home/user/passport/refreshAuthToken
/home/user/passport/createPassportJwtFromOauthCode
/home/user/passport/createTempAuthToken
/auth/passport/callback

These are route templates used by the built-in authentication flows. They are not a general mechanism for bypassing Demonstration Mode on arbitrary URLs.

Logout policy ​

Logout is deliberately absent from the unconditional authentication-route exemptions. While Demonstration Mode is enabled, its behavior depends on the validated effective bean.passport.authTokenMode:

  • auth (default): POST /home/user/passport/logout remains a protected write. Only authenticated, active, non-anonymous whitelisted users may continue; other users receive 403 with demo-demonstration:1001. This prevents ordinary visitors sharing a demo account and authentication record from revoking other visitors' logins.
  • session: the Guard lets POST /home/user/passport/logout continue regardless of whitelist membership because logout revokes only the requesting login session. Normal Passport authentication, account-state checks, and other authorization policies still apply. This is not an authentication bypass.

To enable independent logins in a shared demo deployment:

dotenv
AUTH_TOKEN_MODE=session

The supported values are auth and session; the default is auth. The equivalent typed project-config setting is modules['a-user'].authToken.mode.

Session mode creates a fresh identity for each login in the existing auth-token token field, and token refresh preserves that identity. Tabs sharing a credential share one session: logging out from one signs out the others. This is per login, not per tab.

Session mode requires stateful tokens and does not support the refresh strategy reissue. Password changes, password resets, and initial password setup retain their broader security invalidation behavior. Switching auth-token modes requires coordinated workers and a new login; do not mix modes across workers or expect existing credentials to migrate automatically. See Auth-token mode for typed configuration and deployment guidance.

The conditional allowance applies only to POST on the exact built-in route template /home/user/passport/logout. It does not exempt other write methods or business routes. When Demonstration Mode is disabled, this Guard does not restrict logout, but the configured auth-token mode still determines revocation behavior.

Deploy with the a-demo suite ​

The demo-demonstration module is included in the current project's a-demo suite; no separate package installation is required.

If an operator intentionally excludes the whole suite:

dotenv
PROJECT_DISABLED_SUITES=a-demo

then demo-demonstration and its Guard are not loaded, regardless of DEMONSTRATION_ENABLED or the whitelist. This is expected when a deployment does not include demo capabilities.

For ordinary policy changes, use DEMONSTRATION_ENABLED rather than disabling the suite. Reserve PROJECT_DISABLED_SUITES=a-demo for deployments that intentionally exclude all a-demo functionality.

Troubleshooting ​

SymptomCheck
The policy appears inactiveConfirm DEMONSTRATION_ENABLED=true uses exact lowercase spelling, then restart Vona and check active environment-file and deployment-variable precedence.
An intended demo editor receives 403Confirm that the user is authenticated, active, non-anonymous, and that their username exactly matches a whitelist entry, including case.
A request is unexpectedly allowedConfirm whether it uses a method other than POST, PATCH, DELETE, or PUT, or whether it belongs to an exempt built-in authentication route.
The policy never loadsConfirm that a-demo is not listed in PROJECT_DISABLED_SUITES.
A non-HTTP mutation still runsDemonstration Mode only guards applicable HTTP requests; add the appropriate authorization and execution controls to the relevant job, queue, CLI, or service path.

Released under the MIT License.