Controls mapping
This maps Nazeel's features to the control frameworks a Saudi buyer is audited against. It is a mapping, not a certification: Nazeel is not certified against any of these, and no product can be "compliant" on a customer's behalf. What a product can do is implement controls and produce evidence, and what follows is exactly which ones, where in the code, and how you demonstrate them to your own auditor.
Every row was checked against this repository rather than written from memory. Where Nazeel does part of a control and the customer does the rest, the row says so — a mapping that claims more than it does is worse than none, because your auditor will find the gap and then distrust the rest of the table.
Frameworks covered: NCA Essential Cybersecurity Controls (ECC-1:2018), SAMA Cyber Security Framework (v1.0), ISO/IEC 27001:2022 Annex A, and the Personal Data Protection Law (PDPL) as it bears on data residency.
How to use this
Your auditor will ask for evidence, not for claims. Each row's Evidence column names something you can produce from a running installation — an export, a screen, a file. Produce it once during preparation and keep it with your control documentation; the audit log export is signed, so it can be handed over and verified without access to the cluster.
Identity and access
| Control | NCA ECC | SAMA CSF | ISO 27001 | What Nazeel does | Evidence |
|---|---|---|---|---|---|
| Identity federation | 2-2-3 | 3.3.5 | A.5.16 | Authentication is delegated to your identity provider over OIDC (authorization code with PKCE) or SAML 2.0. Nazeel holds no passwords for federated users | Settings → Security shows the configured provider; GET /api/v1/auth/providers |
| Multi-factor authentication | 2-2-3 | 3.3.5 | A.5.17 | TOTP for local accounts, enforceable for all of them by policy. Federated users get whatever your IdP enforces | Settings → Security → MFA policy; the audit log records enrolment and reset |
| Password storage | 2-2-3 | 3.3.5 | A.5.17 | Argon2id (api/internal/localauth). Passwords are never logged and never in a backup in plaintext |
Source review; a backup contains only the hash |
| Role-based access | 2-2-3 | 3.3.5 | A.5.15 | Three roles — Developer, Team lead, Admin — enforced in the API, never only in the UI. The admission webhook enforces the same rules against kubectl |
Admin → Users; GET /api/v1/rbac/matrix prints the full matrix |
| Privileged session recording | 2-2-4 | 3.3.6 | A.8.15 | Every web terminal session is recorded as asciicast and replayable. Terminal-on means recorded; it cannot be turned off per session | Admin → Terminal sessions; download any recording |
| Privileged session limits | 2-2-4 | 3.3.6 | A.8.15 | Idle timeout (15m default) and maximum duration (4h default) per team, with the reason recorded on each closed session | Admin → Quotas; the sessions list shows why each ended |
| Session revocation | 2-2-3 | 3.3.5 | A.5.18 | Roles are re-read from the store on every request, so a revoked role takes effect immediately rather than at token expiry | Remove a role and observe the next request refused |
| Brute-force protection | 2-2-3 | 3.3.5 | A.8.5 | Ten failed passwords locks one account; sixty failures exhausts one client address across all unauthenticated endpoints. Counters survive a restart | Audit entries for lockouts; the security whitepaper |
Logging and monitoring
| Control | NCA ECC | SAMA CSF | ISO 27001 | What Nazeel does | Evidence |
|---|---|---|---|---|---|
| Audit trail | 2-12-1 | 3.3.13 | A.8.15 | Every action of every user is an entry chained by SHA-256 to the previous one. The database refuses UPDATE and DELETE on the table | Admin → Audit → Verify walks the chain |
| Tamper evidence | 2-12-1 | 3.3.13 | A.8.15 | Any alteration breaks the chain and Verify reports where. Exports are signed with the installation's ed25519 key |
Export an evidence package; verify it with the published public key |
| Log retention | 2-12-3 | 3.3.13 | A.8.15 | Entries are never deleted. Old ranges can be archived into signed evidence packages that stay accounted for; consecutive archives join with no gap | Admin → Audit; GET /api/v1/audit/archives |
| Write-once storage | 2-12-3 | 3.3.13 | A.8.15 | Archives can be written to your own object storage. With object lock enabled on the bucket, nobody — including a Nazeel administrator — can alter or delete them until retention expires | Settings → Evidence storage reports whether the bucket has object lock |
| SIEM integration | 2-12-2 | 3.3.13 | A.8.16 | Live forwarding to your SIEM over syslog (RFC 5424, TCP or UDP) or HTTP JSON | Settings → SIEM; entries appear in your collector |
| Monitoring | 2-12-2 | 3.3.13 | A.8.16 | Prometheus metrics for request and error rates, latency, environments by phase, licence expiry, data-volume free space and a stalled audit head, with example alert rules | /metrics; the Monitoring section of the admin guide |
Data protection and residency
| Control | NCA ECC | SAMA CSF | ISO 27001 / PDPL | What Nazeel does | Evidence |
|---|---|---|---|---|---|
| Data residency | 1-1-1, 4-1-2 | 3.3.14 | PDPL Art. 29 | Nazeel runs entirely inside your cluster. It makes no outbound calls: no telemetry, no update check, no licence phone-home. It talks only to endpoints your administrator configured — the cluster API, your git server, your registry, your IdP, your SMTP relay, your SIEM, and optionally an AI endpoint and object storage you name | NetworkPolicy egress allow-list (charts/nazeel/templates/networkpolicy.yaml); make netpol-check |
| Licence verification offline | — | — | — | The licence is an ed25519-signed file verified locally against a key compiled into the binary. It works in a sealed room | ADR 0004; an air-gapped install |
| Encryption in transit | 2-7-1 | 3.3.9 | A.8.24 | HSTS on every response when TLS is configured; the admission webhook and the bundled registry serve TLS from certificates the operator issues and renews | curl -I against the dashboard; the registry's certificate |
| Encryption at rest (backups) | 2-7-1 | 3.3.9 | A.8.24 | Database backups and audit archives are encrypted with AES-256-GCM before they are written anywhere. The key lives in a Kubernetes Secret, deliberately not inside the backup | A backup file begins NAZEELENC; nazeel-api verify-backup |
| Encryption at rest (volume) | 2-7-1 | 3.3.9 | A.8.24 | Yours. Nazeel writes to a PersistentVolume; encrypting it is your storage class's job | Your StorageClass configuration |
| Secrets handling | 2-7-2 | 3.3.9 | A.8.24 | Credentials live in Kubernetes Secrets, never in the database. The API never returns a stored credential; the support bundle redacts them, verified by a test that plants known values | GET /api/v1/settings/* returns secretConfigured, never the secret |
Development and change
| Control | NCA ECC | SAMA CSF | ISO 27001 | What Nazeel does | Evidence |
|---|---|---|---|---|---|
| Environment separation | 2-6-1 | 3.3.8 | A.8.31 | Each developer environment is its own namespace with its own quota and limits. Nothing a preview does can reach another team's namespace | kubectl get ns; the NetworkPolicy per environment |
| Test data | 2-6-2 | 3.3.8 | A.8.33 | Yours. Nazeel copies the deployment definition, not the data: persistent volume claims become empty directories in an environment, with a warning. What a shared baseline's database contains is your decision | The warning on environment creation; the whitepaper's Known gaps |
| Secure build | 2-6-3 | 3.3.8 | A.8.28 | Builds run as unprivileged Jobs in their own namespace with no service account token and egress limited to an allow-list. No Docker daemon and no host socket anywhere | ADR 0007; charts/nazeel/templates/build-namespace.yaml |
| Vulnerability scanning | 2-10-1 | 3.3.11 | A.8.8 | Optional scanning of every built image, per team, in warn or block mode, using your scanner and your offline vulnerability database. Available in every edition that can build | Admin → Quotas → Scan built images; the Builds tab records the result |
| Change approval | 2-6-1 | 3.3.8 | A.8.32 | Every change goes through the API with its RBAC and the admission webhook, and is audited. The AI assist proposes and a person approves; the audit entry records both names | Audit log entries for any change; ADR 0008 |
| Backup and recovery | 2-9-1 | 3.3.10 | A.8.13 | Scheduled encrypted backups, a documented restore procedure, and a documented disaster-recovery runbook — both exercised by drills that are run before every release | The disaster-recovery runbook; make e2e-restore, make e2e-dr |
What Nazeel does not do
Stated plainly, because a mapping without this section is not believed:
- It does not classify your data. PDPL obligations about what personal data you hold and why are yours; Nazeel holds user identities and the audit trail of what they did.
- It does not encrypt the data volume. That is your storage class.
- It does not manage your identity provider. Password policy, account lifecycle and joiner-mover-leaver processes are in your IdP, not here.
- It does not sign preview images. They are built from a branch, used by one environment and deleted with it. The release pipeline signs what ships.
- It is not certified against any framework. No third party has assessed it. This table tells your assessor where to look.
Keeping this honest
If you find a row that overstates what Nazeel does, it is a bug — report it the way you would report any other. Each row was verified against the code at the time of writing, and the verification is worth repeating at each release rather than assumed to hold.