Multi-tenant isolation
ERPly Pro runs as a multi-tenant SaaS with strict isolation by tenantId at every layer.
Isolation layers
- Cognito — one User Pool per environment (sandbox/staging/prod). Each user carries the
tenant_idclaim. - Lambda authorizer — validates the JWT, extracts
tenant_id, and compares it against theX-Tenant-Idheader. Any mismatch →403. - DynamoDB — every table uses
PK = tenant#<tenantId>as a prefix, and the clients (TenantBoundDynamoClient) inject the filter automatically. - Secrets Manager — PFX files and passphrases are stored under
erplypro/<env>/tenants/<tenantId>/p12. The Lambda's IAM policy only allows the patternerplypro/<env>/tenants/${aws:PrincipalTag/tenantId}/*via session tags. - Logs — Powertools
LoggerinjectstenantIdandcorrelationIdinto every line for audit.
Controlled bypass
Administrative components (archival cron, global metrics) use TenantBypassDeniedError as a guard: the only way to pass tenant_id=None is via an explicit flag (reason="archive-sweep"), which is recorded in the logs.
More detail in US-EP-04 (DynamoDB + Secrets) and US-EP-03 (Cognito + authorizer).