Development docs
Development docsMay include features newer than the installer.

Local accounts and project access

SparkStudio has separate engineering and operator sessions backed by one gateway account store. Engineering opens Projects, Designer and delegated gateway administration according to its capabilities. Operator URLs remain /runtime/<project-id> and load only the published application. Signing in to one audience does not sign in to the other. Project URLs contain no credentials or access tokens.

First administrator

On a new or upgraded data directory without accounts, the gateway requires setup. Open its local engineering page on the gateway computer, then enter the one-time code from <data-directory>/security/setup-code.txt and choose an administrator username and password. There is no default username/password and no HTTP endpoint exposing the setup code. Setup requires a loopback connection even when HTTPS is configured. Successful setup removes the code; it cannot be used to create another administrator. Existing project, connection and database files are preserved.

For the Docker release, create the initial administrator with docker compose exec gateway sparkstudio-admin setup. The command prompts for credentials without displaying the password, reads the protected setup code inside the data volume and calls the existing API through the container's unexposed loopback listener. It cannot reset existing accounts. A browser connection through a published Docker port has a bridge peer and cannot complete local-only bootstrap, even when the browser runs on the Docker host. Docker's public HTTP landing port redirects read requests to a fixed configured HTTPS origin; HTTP account and write requests remain rejected.

Passwords contain 12–256 characters and are stored using the framework's salted, versioned PBKDF2 password hasher. The security/ directory is restricted to the gateway Windows identity, local Administrators and SYSTEM; Unix directories/files use owner-only permissions. Back up the whole gateway data directory with its identity and data-protection files. A missing or invalid identity store requires administrator recovery; removing security files is not an ordinary password-reset workflow.

Your account

In Designer, click your name at the bottom of the expanded workspace sidebar to open Account settings. Theme selection (Light, Dark, Primary or System) applies immediately in that browser. To change your password, save any project, query or script edits first, then enter your current password and the new password twice. Successful changes sign that account out on all devices and from both engineering and operator sessions. Sign in again with the new password. The sign-out icon beside your name ends the current session; the collapsed sidebar retains this icon.

Self-service changes require the current password, a valid session and its CSRF token. Incorrect current passwords use the existing account/address attempt limits; invalid passwords leave credentials and sessions unchanged. The endpoint accepts only current and new passwords, never a target account or role. It rechecks the session inside the credential update lock and records an audit outcome without credential contents. If the other application is signed in as another person, that person's session is preserved. Password fields are held only in the open form and cleared after attempts or dismissal.

Permissions

Permission Scope
Gateway administrator Accounts, project lifecycle/import, shared connections/tag configuration, security settings, audit and manual Python execution; all project permissions
Design Read/edit/export a named project's drafts, resources and queries; preview read queries
Publish Publish a named project's reviewed application revision; requires Design. Changed executable code also requires gateway administrator approval
View Read a named project's published application and captured read queries
Operate Submit published Python actions in that project; requires View

Design does not imply View or Operate, and operator access does not imply Design. Only administrators create, rename, duplicate, archive or restore projects. A designer can save a draft without publishing it. Draft update-query execution and manual Python execution require administrator access. A non-administrator publisher can publish layout/data changes, but cannot activate changed executable Python or browser code, including by rollback. A gateway administrator must review and publish executable changes. Approved actions run with the gateway account; this approval boundary is not a script sandbox.

The application API declares permission metadata for both project-specific and legacy default-project routes. Legacy /api/project, /api/runtime, query, script and asset aliases always authorize the actual default project; a project header cannot retarget them. Unknown APIs fail closed. The catalog includes only projects accessible to the selected audience. Runtime image reads are limited to assets referenced in the current publication.

Viewer pages retain navigation, popups, filtering and table paging while disabling editable inputs, input events and Python action buttons. The server independently rejects viewer action calls. Input values, passwords and browser-supplied role claims cannot identify the audit actor.

Open Gateway Settings → Security. Users & access and Operator settings are tabs: the first manages accounts and grants, while the second manages the public operator URL and each project's readable tag paths. In Project tag access, search the project list and select a project to edit its multiline Tag-path prefixes field. Enter one exact path or folder prefix per line. Switching projects or Security tabs preserves unsaved operator settings. Save operator settings applies the URL and all project scopes together; Cancel changes discards the draft and retrieves the latest saved settings. Accounts and Audit update automatically while visible; updates pause while an account dialog is open. Operator settings are never replaced by background polling. A failed load shows a contextual Retry action.

Security settings declare readable tag paths separately for each project. An exact path grants that tag; a prefix ending in / grants descendants. * explicitly grants every gateway tag. Empty scopes grant no tag data to non-administrator operators. HTTP reads and event streams enforce the same scope; denied explicit reads return 403. Administrators and engineering designers retain engineering tag browsing. Published query/action code is trusted and can access its authored data sources; tag-read scopes are not an operating-system or Python sandbox.

Designer Operator application in the workspace sidebar opens the published project in another tab. Copy that tab's address to share a stable project link. Use the gateway's reachable HTTPS address for remote operators; a localhost link only works on the computer opening it. Publishing updates the application at the existing link; it does not create an anonymous access grant. The Designer header no longer contains separate runtime/link buttons.

Bare /runtime/<project-id> links default to Application only: the authored screen and popups without the SparkStudio header, screen menu, parameter selectors, theme/account controls or footer. The screen fits the available browser viewport while preserving its aspect ratio. Use authored navigation buttons to move between screens in this view. Connection-loss, action-result and publication notices remain available as overlays when needed.

Append ?view=controls to restore the surrounding interface, including the configured screen menu, context selectors, theme, Switch user and Sign out. The setting belongs to the link; it does not edit or republish the project. Only one exact view=controls parameter opts in; absent, unknown or duplicated values use Application only. Legacy /runtime redirects preserve this query choice. Sign-in and all View/Operate permissions apply identically in both presentations.

Sessions and request protection

Sessions use separate HttpOnly, SameSite=Strict cookies for engineering and operators. HTTPS cookies are Secure. In the default supported configuration, plain HTTP account/API access is allowed only when the actual peer is loopback and remote clients require HTTPS. Authorization uses the captured TCP peer and direct TLS connection feature, not a forwarded scheme or address. Forwarded/original-address headers also disqualify loopback setup and HTTP-account access. TLS termination at a reverse proxy and IIS forwarding are not supported security deployments; use direct gateway HTTPS. Gateway Settings → Deployment reports the observed listener mode.

Cookie names are host scoped: using different ports does not isolate them. The Docker Compose example sets SPARKSTUDIO_COOKIE_NAMESPACE=SparkStudioDocker, so a Windows gateway and a container opened through localhost keep separate engineering/operator cookies. The setting accepts 1–48 ASCII letters, digits, underscores or hyphens. Use a distinct stable namespace for each additional gateway sharing the browser hostname; changing it requires signing in again. Omitting it preserves the existing Windows cookie names. It changes no account, audience, permission, CSRF or TLS behavior.

HSTS is also host wide across ports. With the explicit container redirect enabled, TLS responses for localhost and loopback IP hosts omit HSTS so a parallel Windows HTTP gateway on that hostname is not forced onto an unsupported HTTPS port. Public DNS and non-loopback IP hosts retain the existing HSTS header; non-container deployment behavior is unchanged. Direct HTTPS, Secure cookies and the fixed HTTPS landing redirect remain required for container browser access.

Sessions expire after eight hours without sliding renewal and require sign-in after a gateway restart. Each session has a random CSRF token held only in browser memory and sent on API mutations, including POST query reads. Origin checks and JSON requirements also protect account endpoints. Login failures are throttled by source address and account/source pair; another address cannot globally lock out an account. Account edits, permission changes, disabling and password resets revoke that account's sessions. Logout revokes the selected audience's server session. Active tag streams check revocation, expiry, project availability and current scopes while running; the browser also polls its session and clears protected content on loss of access.

The frontend discards form and query state when its identity or effective permissions change. Multiple tabs share their audience cookie and receive sign-out notifications. Shared-station operators should use Switch user or Sign out. Project JavaScript and Python remain trusted authored code. Hosting engineering and operator applications on distinct origins, external identity providers, MFA, fine-grained per-action permissions and hardened multi-tenant isolation remain future work.

Audit and limits

Security records account administration, sign-in/out, permission denials, project changes/publication and operator action outcomes using the authenticated account identity. Records omit request bodies, passwords, CSRF values and form contents. Audit files remain local in security/; the UI shows recent entries. Rotation keeps a current file and one previous file, each approximately 5 MiB. This is a bounded local audit trail, not tamper-evident archival or an external compliance log. Scheduled/startup/shutdown/tag-triggered gateway scripts do not acquire an interactive operator identity. Explicit gateway message requests retain their authenticated request checks. Execution diagnostics are recorded separately from the security audit; see gateway events.

The public installer, container lifecycle, real SQL Server and factory-network acceptance remain separate release gates. Project archives and .sparkproj packages do not contain users, password hashes, session cookies, security settings or the gateway audit log.

Verification commands

Use a fresh disposable data directory on loopback port 5091. node tools/test-security.mjs exercises actual account setup and authenticated requests; its generated test credentials stay in ignored .data/test-evidence/security-test-accounts.json. Existing integration suites can use the real-session preload:

$env:SPARKSTUDIO_TEST_AUTH_FILE = Join-Path $PWD '.data/test-evidence/security-test-accounts.json'
node --import ./tools/test-auth-session.mjs tools/test-input-controls.mjs http://127.0.0.1:5091

The preload is restricted to isolated loopback ports 5091 and 5093, authenticates normally and sends the matching audience cookie and CSRF token. It adds no authentication bypass to the gateway. Never use fixture credentials for a deployed gateway. Example-loader and legacy unauthenticated CLI calls now need authenticated requests; opening Designer and importing a package remains the interactive path.

Delegated operations and equipment commands

Non-administrators may receive separate Diagnostics, Configuration, Backups, Audit and Sessions capabilities. These enable only their corresponding gateway operations; account administration, project lifecycle and recovery activation remain administrator-only. See access boundaries for the operation matrix and workshop.

Project Commands is explicit and implies Operate/View; existing Operate grants do not acquire Commands. Published equipment commands also require readable target and readback tags, fresh confirmation, current publication and current account authority before dispatch. See equipment commands. Ordinary Python actions remain trusted published code and retain the separate memory-tag API; this permission is not an operating-system script sandbox.