> ## Documentation Index
> Fetch the complete documentation index at: https://developers.safarapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Attestations

> Technical and organisational measures snapshot, refreshed quarterly

<Info>
  This page is a **self-attestation**, refreshed quarterly. Independent third-party certification (ISO 27001 and SOC 2 Type I) is in preparation, target **Q4 2026**.
</Info>

The full attestations bundle (`SAFARAPI-ATTEST-v1.0`) is referenced by Annex 3 of the [DPA](/trust/dpa) and incorporated by reference into the Main Agreement.

## At a glance

| Area             | Posture                                                                                |
| ---------------- | -------------------------------------------------------------------------------------- |
| **API auth**     | Bearer (Argon2id-hashed secrets) + HMAC SHA256 on writes, anti-replay timestamp window |
| **Console auth** | Keycloak OIDC + MFA mandatory for admin and finance roles                              |
| **Transit**      | TLS 1.3 only, HSTS preload, Let's Encrypt auto-renewal                                 |
| **At rest**      | AES-256 across R2, B2, LUKS full-disk on K3s nodes                                     |
| **Audit log**    | 7 years WORM (Cloudflare R2 Object Lock) — Bank Al-Maghrib aligned                     |
| **Backups**      | Dual pipeline (PITR 5 min RPO + daily `pg_dump` 24 h RPO), restore drilled             |
| **Pen test**     | Annual — next scheduled Q3 2026, summary under NDA                                     |
| **Patch SLO**    | Critical CVE 24 h, High 7 d, Medium 30 d                                               |
| **PCI scope**    | None — Safariat never touches card data                                                |

## Identity and access

### API authentication

* **Token format**: `sk_<env>_<8-char-prefix>_<random-secret>`, where `<env>` is `live` or `test`.
* **Secret hashing**: Argon2id (m=64 MiB, t=3, p=1). Secrets are **not recoverable** — only the 8-character prefix is stored in clear for support.
* **Write signing**: every POST/PUT/DELETE/PATCH must include `X-Timestamp` (Unix epoch seconds) and `X-Signature` (HMAC SHA256 of `<timestamp>\n<METHOD>\n<path?query>\n<body>` keyed with the secret).
* **Anti-replay**: timestamp window ±5 minutes, server-side `Clock`-aware.
* **Environment isolation**: a `sk_test_*` key cannot access production data and vice-versa — enforced at the authentication filter.
* **Rate limiting**: per-API-key Bucket4j, default 600 req/min, configurable per partner; 429 with `Retry-After`.
* **IP allowlist**: optional per partner; enforced at the same authentication filter.

### Scopes (least privilege)

`catalog:read` · `quote:create` · `booking:read` · `booking:write` · `booking:cancel` · `settlement:read` · `webhook:manage`

### Console

* Keycloak realm `safarapi-partners`, **mandatory MFA** for `PARTNER_ADMIN` and `FINANCE`.
* Federated identity (SAML / OIDC bridge to your IdP) available on request.

## Cryptography

| Where              | Algorithm                                                         | Key custody                                |
| ------------------ | ----------------------------------------------------------------- | ------------------------------------------ |
| In transit         | TLS 1.3, HSTS preload                                             | Let's Encrypt via cert-manager             |
| R2 object storage  | AES-256-GCM                                                       | Cloudflare-managed                         |
| B2 backups         | AES-256-CTR + optional client-side AES-256 for `pg_dump` archives | Provider-managed                           |
| K3s node disks     | LUKS full-disk encryption                                         | Host-managed                               |
| Kubernetes Secrets | Bitnami Sealed Secrets (RSA-OAEP + AES-256-GCM)                   | Public key in Git, private key in K3s only |
| Admin secrets      | 1Password Business (AES-256, E2EE)                                | 2FA mandatory                              |

### Pseudonymisation

The customer reference you send us is stored as `SHA-256(<partner_id>:<customer_ref>)` — scoped per partner, **non-reversible**. We cannot correlate the same end-customer across two different Partners.

## Data residency

| Asset                             | Region                                                          | Provider                  |
| --------------------------------- | --------------------------------------------------------------- | ------------------------- |
| Primary PostgreSQL                | Germany                                                         | Contabo (EU bare-metal)   |
| Object storage (public + private) | EU                                                              | Cloudflare R2             |
| Physical PITR backups             | EU (`eu-central-003`)                                           | Backblaze B2              |
| Logical backups (daily `pg_dump`) | US (`us-east-005`), AES-256 client-side encrypted before upload | Backblaze B2              |
| Identity provider                 | Germany                                                         | Self-hosted Keycloak      |
| Audit log WORM                    | EU                                                              | Cloudflare R2 Object Lock |

No Personal Data of EU Data Subjects is processed outside the EU **except** the daily logical-backup tier, which is encrypted client-side with the key held exclusively by Safariat in the EU.

## Resilience

* **Kubernetes** (K3s) — 3 control-plane + at least 1 worker node.
* **PostgreSQL CNPG** — primary + 1 hot standby with auto-failover.
* **Rolling deployments** with readiness/liveness probes on `/actuator/health`.
* **ArgoCD self-heal** — declarative GitOps, drift auto-reverted.
* **Backup tier 1**: Barman + WAL streaming to B2 EU. RPO ≤ 5 min. Restore drill passed 2026-04-17.
* **Backup tier 2**: daily `pg_dump` to B2 US-East (independent account, smaller blast radius). RPO 24h.
* **RTO**: 4 hours target, validated.

## Logging and audit

Every API request lands in `partner_api_audit_log` (PostgreSQL native monthly partitioning, 12-month rolling, ShedLock job auto-creates new partitions) with:

`request_id` · `partner_id` · `api_key_id` · `method` · `path` · `query_params` · `request_body_hash` (SHA-256 — body itself is **not** stored) · `status` · `latency_ms` · `client_ip` · `user_agent` · `idempotency_key` · `error_code` · `created_at`

Retention: **90 days** hot (database), **7 years** cold archive (Cloudflare R2 Object Lock, retention mode `compliance` — irrevocable).

Application logs go to Fluent Bit → Elasticsearch (90-day hot retention) with Kibana saved searches restored automatically on cluster recovery via ArgoCD PostSync hook.

## Software supply chain

* Container images pinned to **specific patch versions** (`keycloak:26.0.8`, not `:26.0` or `:latest`). Moving tags are forbidden — see post-mortem of the 2026-04-17 incident.
* Renovate Bot weekly dependency PRs.
* Trivy scan on every image build — fails the pipeline on Critical CVEs.
* GitOps deploy via ArgoCD — no human writes to the cluster outside emergency procedures (logged).

### Patch SLO

| Severity                | SLO         |
| ----------------------- | ----------- |
| Critical (CVSS ≥ 9.0)   | 24 hours    |
| High (CVSS 7.0 — 8.9)   | 7 days      |
| Medium (CVSS 4.0 — 6.9) | 30 days     |
| Low                     | Best effort |

## Data minimisation

| Booking type                            | Required Personal Data                                      | Notes                        |
| --------------------------------------- | ----------------------------------------------------------- | ---------------------------- |
| Domestic experience                     | First name, last name, email, phone                         | Minimum required for voucher |
| Domestic multi-day trip                 | Same + optional birth date (when accommodation requires it) | —                            |
| International flight (Omra/Haj/charter) | Same + passport number                                      | IATA reservation requirement |

We **never** request: payment card data, biometrics, health data, religious / political / sexual-orientation data, trade union membership.

## Compliance matrix

| Framework                       | Status           | Notes                                              |
| ------------------------------- | ---------------- | -------------------------------------------------- |
| GDPR (EU 2016/679)              | Applicable       | DPA signed per partner                             |
| Loi 09-08 (Maroc)               | Applicable       | CNDP declaration on request                        |
| Bank Al-Maghrib externalisation | Aligned          | 7-year audit log + sub-processor approval workflow |
| PCI DSS                         | Not in scope     | No card data handled                               |
| ISO 27001                       | Targeted Q4 2026 | External auditor engagement in progress            |
| SOC 2 Type I                    | Targeted Q4 2026 | External auditor engagement in progress            |
| eIDAS                           | Not applicable   | No qualified signature primitives offered          |

## Incident response

1. **Detect** — external probes + Prometheus alerts + security log alerts.
2. **Acknowledge** — within MTTA (1h Critical, 4h High, 1bd Normal).
3. **Triage** — scope, affected partners, root cause hypothesis.
4. **Mitigate** — rollback, scale, isolate, patch.
5. **Communicate** — status page every 30 min during the incident; direct email to affected partners.
6. **Resolve** — confirm via probes and metrics.
7. **Post-mortem** — published within 5 business days for Critical / High incidents.

### Vulnerability disclosure

* Report to `security@safarapi.com` (PGP key on the security page).
* We acknowledge within **24 hours**.
* Researcher acknowledgement in the public Hall of Fame (with consent).

## Obtaining the attestations bundle

The full attestations bundle is provided as a PDF on request — email
`security@safarapi.com`. On production approval, the current bundle is included
automatically in your compliance pack and refreshed annually.

## Contact

* Security: `security@safarapi.com`
* Privacy / DPA: `dpo@safarapi.com`
* Operations / SLA: `ops@safarapi.com`
* Billing: `billing@safarapi.com`

## Related documents

* [Data Processing Agreement](/trust/dpa)
* [Service Level Agreement](/trust/sla)
* [Security overview](/security/overview)
