StrataDocs

Security overview

How Strata protects organizational data — the page IT and security teams will scrutinize before approving rollout.

This page is the executive summary. For specifics, see Data handling and privacy and Legal and policies.

Authentication

Strata uses Microsoft SSO as the only sign-in path for end users. There are no passwords stored in Strata's database, no local accounts, and no per-tenant password reset flow to break.

  • Sign-in happens through a Microsoft OAuth popup. The popup hands an authorization code back to the Strata app, which exchanges it server-side for tokens.
  • The permissions Strata requests are scoped to what each connected extension needs, and there are two consent surfaces. The Microsoft extensions — Outlook, OneDrive, SharePoint, Teams — consent through Microsoft Graph (e.g. Mail.Read only after the user connects Outlook). Jira and Confluence are not Microsoft services and consent separately through a single Atlassian OAuth screen that covers both products — Jira scopes such as read:jira-work and write:jira-work, Confluence scopes such as read:confluence-content.all and write:confluence-content, plus offline_access. The screen is assembled from what that member is actually allowed, so a Jira-only organization is never asked for Confluence permissions and a member who may not write is asked for read scopes only; the full scope list is on the Atlassian extensions page. The administrative scopes manage:jira-project, manage:jira-configuration, manage:jira-webhook, manage:servicedesk-customer, and manage:confluence-* are deliberately never requested, in any configuration — Strata cannot administer your Atlassian site.
  • A Strata session cookie (strata_session) is set after successful auth. It is HttpOnly, Secure (HTTPS), and SameSite=None (so the cookie is still sent inside the Outlook task pane's cross-origin iframe; CSRF protection is preserved by the separate X-CSRF-Token header requirement).
  • The same session token is persisted in the platform database's sessions table so it survives server restarts. Session validation checks memory first, then the database — both layers respect revocation.

Disabling a user in the Users page hard-revokes every session for that user immediately. SCIM-driven deactivation does the same within seconds of the IdP firing the event.

Per-organization tenant isolation

Every record in Strata's database is scoped to an org_id. Cross-tenant access is blocked at three layers:

  1. Application — admin mutations all flow through _assertUserInOrg, _assertConnInOrg, _assertInviteInOrg IDOR guards before touching the database. Custom roles, sessions, audit logs, agents, conversations — everything is org-scoped.
  2. Auth gates — the admin middleware (requireAdmin) checks the session's orgId and rejects requests with no org. SCIM bearer tokens carry their orgId and the handlers reject any cross-org target with HTTP 403.
  3. AI engine routing — every organization runs on its own Azure AI Foundry, and routing uses AsyncLocalStorage to bind every AI request to the correct tenant's Foundry. There is no shared engine and no fallback for your data — a request about it can only go to your own Foundry. The in-product help assistant is separate and Kronisys-hosted; it receives your support question and that conversation, not your business data.

UUID comparison in the org-isolation paths is case-insensitive because SQL Server returns uppercase UUIDs while client-supplied IDs are lowercase — a regression Strata caught and fixed during a self-demote scenario.

AI model governance

The set of AI models a user can reach is itself an access control. Strata runs a central, Kronisys-curated Model Catalog; each organization enables the subset it wants from that catalog. The models served span OpenAI, Anthropic, xAI, DeepSeek, Mistral AI, Cohere, and Microsoft, and every one of them runs through Microsoft Azure AI Foundry — Strata never calls a model provider directly.

The effective models any single user can use are the intersection of three layers:

  1. Organization — the models the org has enabled in the catalog (allowed_models).
  2. Role — each role can be scoped to a narrower set than the org's.
  3. Per-user — an admin can restrict an individual user below their role's set in Admin → Users → (manage user) → Extensions & Data → AI models. Inherit means "all org-allowed models."

This intersection is enforced on every surface that can invoke a model — chat, agents, the Teams bot, voice mode, and the programmatic /v1 API. Disabling a model in the catalog removes it everywhere at once; an agent or API key pinned to a now-disabled model stops working rather than silently falling back.

Note

There is no separate "lock" toggle. allowed_models is always authoritative — what an organization has enabled is exactly what its members can use.

Encryption

Strata uses AES-256-GCM for any sensitive value stored at rest:

ValueEncryption
Personal database connection passwords (db_connections.db_password_encrypted)AES-256-GCM, key from DB_ENCRYPTION_KEY, stored as iv:tag:ciphertext hex string.
Organization database connection passwords (org_db_connections.db_password)AES-256-GCM, same algorithm, stored as iv (12B) + tag (16B) + ciphertext binary.
Bring-your-own Foundry API keys (organizations.foundry_key)AES-256-GCM, same key, never displayed back to the admin.
Identity PII — user, session, and invite emails and namesAES-256-GCM field-level encryption, so the database itself stores only ciphertext. Equality lookups (sign-in, admin search, invite matching) run against an HMAC-SHA256 blind index rather than plaintext. Values are decrypted only in application memory on read.
SCIM bearer tokens (scim_tokens.token_hash)SHA-256 hash only — token plaintext shown once at issuance.

The encryption key (DB_ENCRYPTION_KEY) is an environment variable on the App Service, never stored in the database or in source.

Data in transit:

  • All HTTPS traffic served by Azure App Service with TLS 1.2+.
  • Outbound SQL Server connections use the mssql driver with encrypt: true and TLS certificate validation. The "Trust server certificate" toggle on org-managed connections is the only escape hatch and is documented as for self-signed certs in trusted private networks only.
  • Outbound Microsoft Graph, Atlassian Cloud, and Azure AI Foundry calls use HTTPS.

Session and request controls

The application enforces:

  • CSRF double-submit cookie pattern. Every mutating request must carry an X-CSRF-Token header matching the strata_csrf cookie. Constant-time compare. Narrow exemptions for OAuth callbacks (no CSRF header possible), the Teams bot webhook (Microsoft → us), SCIM (bearer-auth, no cookies), and per-agent webhook triggers (HMAC-signed body).
  • Helmet-managed Content Security Policy. default-src 'self', frame ancestors 'none' to block clickjacking. The Outlook task pane has a relaxed CSP scoped to /outlook/* so the Outlook clients can iframe the panel.
  • Permissions-Policy that disables camera, geolocation, payment, USB, motion sensors, and locks microphone and autoplay to same-origin.
  • Same-origin-allow-popups COOP so the Microsoft OAuth popup keeps its opener relationship — required for the popup-to-parent postMessage to work without breaking sign-in.
  • API rate limiter at 1000 requests per 15-minute window per IP across all /api/* routes (with /api/auth and /api/schema exempt for their own internal limits).
  • Per-admin bulk rate limit of 20 bulk requests per 5 minutes to prevent UUID enumeration via bulk action endpoints.

The audit log as a security control

Every admin-triggered change is recorded in the audit_log table with the actor's user ID, email, IP, action, target, and a JSON details payload. See Audit log for the full action vocabulary.

For SCIM-driven actions, the actor is recorded as scim:<token-label> so an investigator can correlate IdP-side events to Strata changes.

Audit log retention is configurable per org (30 to 3650 days, default 365) and swept nightly.

Session revocation

Admins with canRevokeSessions can:

  • Terminate individual sessions from the Sessions page.
  • Force a single user out of every device from the user-manage modal in Users.
  • Wipe every session in the organization at once via POST /api/admin/org/revoke-all-sessions (requires canManageUsers) — useful for suspected breach response.

Revocation is reflected in the next validateSession call. There is no observable lag.

Org-wide kill switch

Two big red buttons sit under Organization settingsBranding & Policy:

  • Suspend organization — every member is blocked from chat, DB, file, and email endpoints (403 "Organization suspended"). Admins can still reach /admin to lift, and /api/auth so they can sign back in. This requires the Suspend organization permission (owner-reserved) and a step-up confirmation: the admin must type the organization's display name before suspend or unsuspend takes effect. Useful for billing disputes, incident response, or planned maintenance windows.
  • Request organization deletion — the start of the deletion workflow. Two-signal design (customer request + Kronisys approval) with a 30-day grace window. See Organization deletion.

A platform-wide kill switch also exists via the STRATA_MAINTENANCE=1 environment variable. When set, every route returns 503 except /api/health and static assets. This is operator-controlled, not admin-controlled.

Hosting and infrastructure

Strata is deployed on:

  • Azure App Service (Linux container, Node 20 LTS) — the application server.
  • Azure SQL Database (platform database) — users, sessions, conversations, settings, audit log, artifacts.
  • Azure Communication Services — system emails (transactional).
  • Azure Blob Storage — file artifacts, admin export ZIPs, cold-stored message archives.
  • Azure AI Foundry — every model in the Model Catalog routes through Foundry, running in your organization's own Azure AI Foundry — see Bring your own Azure AI Foundry.
  • Azure Redis Cache — agent run locks and inter-instance coordination.

All Azure resources are in a single Azure region per deployment. Region selection is part of your contract with Kronisys.

What we do NOT do

To be explicit about what Strata is not:

  • Strata does not train AI models on your data. AI requests pass through Foundry as inference-only calls.
  • Strata does not sell or share organizational data with third parties.
  • Strata does not expose a public anonymous tier — every user must sign in with Microsoft SSO.
  • Strata does not persist OAuth refresh tokens for extensions in plaintext. Tokens live in extension_tokens, encrypted at the row level.

One thing Strata does do, stated plainly: its connectors are no longer all Microsoft. Connecting Jira or Confluence sends the content the AI works with — issues, comments, and service requests on the Jira side, page bodies and page comments on the Confluence side — to Atlassian Cloud, read from there and written there when your organization has enabled writes, directly rather than through Microsoft Graph. Atlassian pins that data to the region your Atlassian site was created in; Strata's platform database and your organization's Azure AI Foundry are separate infrastructure in their own regions. An organization that needs every connector to stay inside the Microsoft boundary should leave both the Jira and Confluence availability switches off on the Atlassian extension page (Settings → Extensions → Atlassian → Manage) — unchecking only one still leaves the other sending content to Atlassian Cloud.

What can go wrong

FailureWhat it means
All users get 403 "Organization suspended"The org is suspended. Check Organization settings → Branding & Policy.
All users get 503 across all orgsThe platform STRATA_MAINTENANCE flag is set. Operator action; contact support@kronisys.com.
Sign-in popup auto-closes without effectCOOP misconfiguration — should not happen in current builds. Refresh and retry. If persistent, contact support.
CSRF token missing or invalid. Refresh the page and try again.The strata_csrf cookie was deleted, expired, or the X-CSRF-Token header did not match. Refresh the page.
Too many requests. Please wait a few minutes before trying again. (429 on /api/*)The global IP-based rate limiter caught a burst. Throttle the caller.
All AI failing after a Foundry changeVerify your Foundry endpoint and key. There is no fallback to Strata's platform engine. See Bring your own Azure AI Foundry.

See Data handling and privacy for what data is collected and where it lives, and Legal and policies for the binding documents.

Related