Security
Security's home page. The controls below already exist but were documented control-by-control. This page is the index, the trust-boundary view, the PII / PDPD map, and the list of open hardening items. It is the Security entry point in the by-role guide.
Trust boundaries
- Edge: TLS at the gateway; per-service JWKS-verified ES256 tokens - identity is the issuer, all other services verify.
- Tenant isolation: every request carries
x-merchant-id; Casbin scopes authorization to that merchant's domain. - Secrets: a SealedSecret controller decrypts into K8s Secrets at runtime; app config via
APP_ENV_*. - E-invoice integrity: provider credentials are AES-256-GCM encrypted; invoices are Ed25519 / PKCS#7 signed.
Controls - where each one lives
| Area | Control | Reference |
|---|---|---|
| Authentication | JWKS ES256 sign-in, sign-up, password change | identity/authentication |
| Authorization | Casbin RBAC, per-merchant domains, priority roles | identity/casbin-authorization |
| Secrets | SealedSecret + env config | infrastructure/configuration |
| Network | Network policy / Cilium, ingress | infrastructure/networking |
| Hardening | Pod / cluster hardening | infrastructure/security-hardening |
| Crypto | Per-merchant credential encryption, invoice signing | invoice/domain-model |
| Webhook integrity | X-Webhook-Signature HMAC-SHA256 | VNPAY IPN Contract |
Personal data (PII) & Decree 13/2023 (PDPD)
BANA processes personal data, so the Personal Data Protection Decree (Nghị định 13/2023/NĐ-CP) applies. Inventory (protections marked confirm are not yet verified against code):
| Data | Where | Protection | PDPD obligation |
|---|---|---|---|
| Customer name · phone · email | identity / customer | confirm | consent · retention · erasure |
| Employee profile | identity / employee | access-controlled | consent · least access |
| User login (username + credential) | identity | credential scheme - see authentication | strong policy (see issues) |
| Buyer tax code (MST) | invoice / tax | stored | lawful basis: tax |
| Device fingerprint | device / signal | confirm | consent · privacy risk (flagged) |
| Payment provider credentials | payment | AES-256-GCM encrypted | data minimisation |
Largest gap: there is no consent / retention / erasure design, no data-subject-request flow, and no field-level data-classification policy. Owned by Security + Legal.
Audit logging
Security-relevant events that should be auditable: sign-in / sign-out, grant / revoke, role change, credential decrypt, invoice signing & issuance, device deactivate.
State: inconsistent across docs (one page claims 10-year retention, another defers audit to Phase 3). An authoritative audit-log design - event list, schema, retention, tamper-evidence - is not yet written. Action item.
Open hardening items
| Item | Where | Action |
|---|---|---|
| Password minimum length is 4 | authentication (4-80) | raise to ≥ 8-12 + complexity / breached-password check |
| Sign-up grants OWNER by default | authentication | gate OWNER (invite / approval); default to a least-privilege role |
Internal /webhooks/payment is unauthenticated | VNPAY IPN Contract → known issues | verify X-Webhook-Signature (constant-time) + add a replay window |
| Checksum / signature compares are not constant-time | mq-pay verify helpers | use crypto.timingSafeEqual |
| Secret examples in docs | infrastructure/configuration | keep secret values as <placeholders>, never real strings |
These fixes live in application / infrastructure code, not the docs - tracked here so Security has one list.