core
Security & PDPA
Security standards — encryption at rest, HMAC webhooks, key management, data-subject rights under PDPA
⏱ PDPA
SlipBolt handles financial data, so security is designed in from the credential layer all the way to PDPA-compliant deletion
Authentication
| Credential | Used for | Details |
|---|---|---|
| JWT (HS256) | Dashboard / LIFF | 15-minute access token + 7-day refresh (rotated) · cookie httpOnly + Secure + SameSite=Lax + path /api |
| API key | Server-to-server | sk_live_… / sk_test_… · stored as an argon2 hash (shown in full once) · revoke/rotate yourself |
- Refresh tokens are stored as a sha256 hash (
Session.tokenHash) — a leaked DB dump cannot be replayed - Refresh-reuse detection — an old token used again → the whole chain is revoked immediately
- New-device detection — a login from a new device → email alert
Encryption
- In transit: TLS 1.2+ on every endpoint
- At rest: LINE channel secret/token encrypted with AES-256-GCM (key
ENCRYPTION_KEY· 32-byte hex) — decrypted only when calling the LINE API, plaintext is never cached in Redis - User passwords: argon2id
Webhook integrity
- Inbound (LINE): the HMAC-SHA256 of the raw body is checked on every request before it is accepted
- Outbound (yours): every delivery is signed
X-Slipbolt-Signature: t=<ts>,v1=<hmac>— verify it every time with the endpoint's webhook secret (see Webhooks)
Rate limit & abuse
- Global throttle 120 req/min · login 5 req/min
- API keys have a per-key rate limit of 120 req/min (same on every plan · not tied to price)
- a combined ceiling of 240 req/min on
POST /api/v1/verify— see Authentication
- a combined ceiling of 240 req/min on
- Input to
POST /api/v1/verify: raw bytes ·multipart/form-data· JSONimage(base64) /url/qr— the whole request is capped at 5 MB ·urlmust be publichttps://(the real IP is checked after DNS resolution — internal/cloud-metadata addresses are refused) and redirects are not followed
Audit log
Every security event (login/logout · password · session · link/unlink · API key · plan · admin action) is stored in audit_logs, append-only · users can see their own at Settings → Audit Log · pruned automatically after 90 days
System logs redact sensitive values automatically (password, *token*, *secret*, Authorization)
PDPA — data-subject rights
| Right | Where |
|---|---|
| Access / Portability | GET /auth/me/export → all your data as JSON (no secrets) · Settings → Security |
| Erasure | DELETE /auth/me → soft-delete + cancel subscription + revoke every session · hard-deleted by cron after 24 hours |
| Slip privacy | Slip images are discarded right after verification (never persisted) · only text is kept (ref/amount/date/name) |
| Retention | Transaction data is anonymised automatically after pdpaRetentionMonths (default 12 months) when the shop enables auto-delete |
Every piece of data is isolated per shop (shopId) — nothing leaks across tenants
Reporting a vulnerability
Found a security issue? Please contact the team before disclosing it publicly — we will respond and fix it promptly
