Security architecture
The controls below describe how identity is established, how multi-tenant data is kept isolated, where signing keys live, and how security-relevant actions are recorded.
Authentication
sigill.ai accepts two credential types on protected endpoints: short-lived bearer tokens issued by the login flow, and per-tenant API keys held salted-hashed in the database. Federated identity (Google, Microsoft Entra ID) is delegated to ZITADEL via OIDC. A valid token establishes identity only — it never establishes authorisation.
Tenant isolation
sigill.ai is multi-tenant. Tenant-scoped records are protected by application-level authorisation and ORM-level tenant filters. Protected handlers resolve tenant membership and role from the database on each request, rather than trusting role claims embedded in the token. Organisation lifecycle status is enforced the same way: a suspended organisation is rejected on every request — existing sessions and API keys included, with the API keys revoked at suspension — not merely at the next login. Three independent layers enforce isolation:
- Application-level authorisation. Every tenant-scoped request passes through a central authorisation helper that compares the caller's claimed tenant against the request target, loads the caller's row from the database, and checks the database-resolved role against the minimum required for the action.
- ORM-level tenant filter. Tenant-scoped records are filtered by the current tenant at the data-access layer. Even if a query omits an explicit tenant predicate, the filter adds it.
- DTO-level capability boundary. Billing state, entitlements, and security-posture flags are not bindable from user-facing request bodies. The only path that may mutate them is the billing webhook handler with verified signature.
Key management
Signing keys are held in AWS KMS. Private-key material is non-extractable: it never appears in memory or on disk outside the KMS HSM boundary. The application's IAM permissions on a given key are limited to Sign, GetPublicKey, and DescribeKey.
| Key | Algorithm | Custody | Rotation |
|---|---|---|---|
| Platform document-seal key | RSA-4096, SIGN_VERIFY | AWS KMS — eu-north-1 | Manual; certificate reissued before notAfter |
| Tenant Bring-Your-Own-Certificate (BYOC) keys | RSA-4096, SIGN_VERIFY | AWS KMS, one key per tenant certificate | On tenant request — 7-day grace window on revoke |
| Bearer-token signing secret | HMAC-SHA-256 | AWS Secrets Manager | Manual (see posture for token-lifetime follow-up) |
| Database master credential | RDS-managed credential | AWS Secrets Manager | Managed by AWS RDS rotation |
| API keys (per tenant) | Random 256-bit, stored salted-hashed | Application database | Rotatable by tenant owner; two slots so rotation is zero-downtime |
BYOC certificates are addressed by tenant-scoped identifier, never by a client-supplied KMS ARN — meaning a request body cannot select another tenant's key. Certificate provisioning generates a CSR signed by the new KMS key; the customer submits the CSR to a CA of their choosing and uploads the resulting chain, which sigill.ai validates against the public key of the KMS key before activating.
Audit logging
Security-relevant actions — logins, role changes, plan changes, stamp and seal operations, settings changes, key rotations, MFA changes — are written to a tenant-scoped audit log inside the same database transaction as the action itself. A successful operation with a failed audit write is treated as a failure, because an unrecorded signing event defeats the product.
| Plan | Audit retention |
|---|---|
| Free | 7 days |
| Starter | 30 days |
| Business | 90 days |
| Scale | 1 year |
| Enterprise | Custom (per contract) |
By default only the tenant owner can read the audit log. Tenant owners may grant their members read access via a tenant setting; the change is itself audited.