Security architecture

How eworks.cloud protects workspaces, data and models, layer by layer.

Overview: defense in depth

No single control is trusted on its own. Every request crosses at least five independent layers, and each layer fails closed.

LayerPrimary controlFails closed by
EdgeWAF, DDoS mitigation, TLS 1.3 terminationDropping the connection
IdentitySSO federation + MFARejecting the session
AuthorizationRBAC + ABAC + tenant isolationReturning an empty result set
DataAES-256 at rest, field-level encryptionRefusing to decrypt
ObservabilityAppend-only audit trail, anomaly detectionAlerting and rate-limiting

Design rules the platform holds itself to:

  • Deny by default. A new table, endpoint or tool is unreachable until an explicit policy grants access.
  • Least privilege. Service credentials are scoped to a single capability and a single environment.
  • No implicit trust between tenants. Tenant identity is derived from the verified token, never from a request parameter.
  • Everything privileged is logged. If an action can change access, data or configuration, it produces an audit event.

Authentication

SSO federation

Workspaces can federate with any SAML 2.0 or OIDC identity provider — Entra ID, Okta, Google Workspace, Keycloak, JumpCloud. Domain-verified workspaces can force federated login and disable password sign-in entirely.

  • Assertions are validated for signature, audience, issuer, and clock skew (±120 s).
  • NameID / sub is the stable external identity; email changes do not create a new account.
  • Just-in-time provisioning creates the member on first login with the default workspace role.
  • SCIM 2.0 keeps membership and deprovisioning in sync.

Multi-factor authentication

FactorNotes
Passkey (WebAuthn)Phishing-resistant, recommended default
YubiKey / U2F security keyHardware-backed, supports FIPS keys
TOTPRFC 6238, 30-second window, one-step drift tolerance
Recovery codes10 single-use codes, shown once, hashed at rest

SMS is intentionally not offered. Admins can require MFA for all members, or only for privileged roles.

Session management

  • Access tokens are short-lived JWTs (15 minutes) signed with rotating RS256 keys.
  • Refresh tokens are rotating and single-use; reuse of a consumed refresh token revokes the whole session family.
  • Idle timeout 8 hours, absolute timeout 30 days, both configurable per workspace.
  • Admins can revoke any individual session or all sessions for a member from e.identity.

Verify a token against the published JWKS:

bash
curl -s https://id.eworks.cloud/.well-known/jwks.json | jq '.keys[].kid'
python
from jwt import PyJWKClient
import jwt

jwks = PyJWKClient("https://id.eworks.cloud/.well-known/jwks.json")
key = jwks.get_signing_key_from_jwt(token).key

claims = jwt.decode(
    token,
    key,
    algorithms=["RS256"],
    audience="eworks-api",
    issuer="https://id.eworks.cloud",
)
print(claims["sub"], claims["workspace_id"], claims["role"])

Authorization

Role-based access control

RoleRead dataWrite dataManage membersBilling & security settings
AdminYesYesYesYes
MemberYesYesNoNo
ViewerYesNoNoNo

Roles are stored in a dedicated user_roles table, never on the profile record, and are always evaluated server-side. A client-supplied role claim is ignored.

Attribute-based access control

On top of roles, policies evaluate attributes carried by the request:

  • workspace_id — hard tenant boundary.
  • department — department tags on documents, agents and chat sessions restrict visibility to matching members.
  • classificationpublic, internal, confidential, restricted. Restricted records require an explicit grant plus MFA within the last hour.
  • environment — sandbox credentials can never read production records.

Tenant isolation

Every tenant-scoped table enforces row-level security keyed on the workspace claim of the verified token. Object storage paths are prefixed with the workspace ID and signed URLs expire in 15 minutes. Vector indexes are partitioned per workspace so retrieval can never cross a tenant boundary.

Data encryption

StateControl
At restAES-256-GCM on all database volumes, object storage and backups, with managed KMS keys and automatic annual rotation
In transitTLS 1.3 externally; mutual TLS between internal services
Field levelEnvelope encryption for API credentials, connector secrets, and any field tagged restricted
BackupsEncrypted with a separate key, restore requires two-person approval

Field-level ciphertext is never returned by the API — only a masked reference such as sk_live_••••4f2a — and the plaintext is decrypted at point of use inside the service that needs it.

Network security

  • Application, database and worker subnets are separated inside a private network; databases have no public route.
  • Security groups allow only the specific ports each tier needs; egress is restricted to an allowlist of model and connector endpoints.
  • A managed WAF applies OWASP core rules, bot filtering and per-path request limits at the edge.
  • Volumetric DDoS mitigation is always on at the edge, with automatic challenge escalation.
  • Administrative interfaces support IP allowlisting per workspace.

API security

  • Bearer tokens. OAuth 2.0 JWT access tokens with scoped claims; the Authorization: Bearer header is the only accepted credential for user-context calls.
  • Rate limiting. Per token, per workspace and per IP. Defaults: 600 requests/minute per token, 60 model completions/minute per workspace. Exceeding returns 429 with Retry-After.
  • Request signing. Webhooks and server-to-server integrations are signed with HMAC-SHA256 over the raw body plus a timestamp; requests older than 5 minutes are rejected.
  • API key rotation. Keys are issued with an expiry (90 days by default), support overlapping dual-key rotation, and are revocable instantly.

Verify a webhook signature:

python
import hmac, hashlib, time

def verify(body: bytes, header: str, secret: str) -> bool:
    ts, sig = header.split(",", 1)
    ts = ts.removeprefix("t=")
    sig = sig.removeprefix("v1=")
    if abs(time.time() - int(ts)) > 300:
        return False
    expected = hmac.new(secret.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

Logging and monitoring

  • Application, access and security logs stream to CloudWatch log groups with a 400-day hot window; audit events are additionally written to the immutable 7-year store.
  • Anomaly detection watches authentication failures, unusual geographies, bulk exports, privilege changes and abnormal token spend.
  • Alerting thresholds:
SignalThresholdAction
Failed authentications, single account> 5 in 10 minutesLock account, page on-call
Failed authentications, workspace-wide> 50 in 10 minutesSecurity incident opened
Bulk data access> 1,000 records in 5 minutesAlert workspace admins
Privilege escalationAny role change to AdminImmediate notification to all admins
Impossible travelTwo logins > 800 km/h apartSession challenge + alert
Note: alerting thresholds are workspace-configurable in e.dash. Lowering them does not reduce what is logged — logging is always complete.

Next