All notable changes to Arkyc are documented here. The format is based on Keep a Changelog, and the project aims to follow Semantic Versioning.
Phase 20 — Hardening & Release. Production-readiness pass focused on the API.
- Rate limiting on sensitive surfaces (auth login / 2FA / register / forgot /
email-verify, the API-key session routes, and outbound webhook test deliveries)
via the Express driver's IP-keyed limiter. Returns
429; inert under test. - Session-expiry sweep (
sessionService.sweepExpired) that expires past-TTL, non-terminal sessions the lazy per-request refresh never reaches, firingverification.expiredwebhooks + realtime. Two drivers viaSESSION_SWEEP_DRIVER:schedule(framework scheduler, default) orqueue(self-reschedulingSessionSweepJob, no cron — start withark session:sweep --loop);offdisables. - Per-tenant data retention: media-only cleanup that deletes captured images,
selfie, liveness video, and proof-of-address image once a session is older than
the organization's
retention_days, keeping the session row + decision. Driven by the scheduler (daily) or the queue sweep; also runnable viaark retention:purge. - Webhook signing secrets encrypted at rest (framework
Encryption, AES-GCM keyed byAPP_KEY), decrypted only at sign time; legacy plaintext rows pass through until the re-encrypt migration runs. - Per-project origin allowlist enforced on client-token requests (opt-in: an
empty
allowed_originsnever blocks). Disallowed browser origins get403origin_not_allowed. - Observability seams: a vendor-neutral
reportError(structured logging + pluggable external reporter) wired into the global error path and maintenance jobs, plus a no-op metrics sink to swap for a backend. - Hot-path indexes on
verification_sessions(expires_atfor the sweep;(organization_id, status)for the review queue).
- Webhook secrets are no longer stored in plaintext.
- Audited retry limits (webhook 5, OCR 3, biometric 5, liveness attempts 3) and
signed-asset-URL TTLs (clamped to a bounded
[min, max]); all confirmed finite.
- New settings:
SESSION_SWEEP_DRIVER,SESSION_SWEEP_INTERVAL.APP_KEYnow also derives the at-rest encryption key — set a strong, stable value; rotating it makes existing ciphertext unreadable.