auth · observability · health

Infrastructure that tells the truth about itself.

Dependency gauges are sampled at scrape time, never cached. Health endpoints distinguish "slower" from "wrong". Path labels use route templates so cardinality stays bounded.

Auth
HMAC-256
peppered key hashes
Log format
JSON
1 object per line
Correlation
X-Request-ID
echoed on every response
DB targets
PG / SQLite
no code change

Security model

Passwords

Bcrypt with per-password salt. Failed logins lock the account after 5 attempts for 15 minutes.

API keys

High-entropy tokens stored only as peppered HMAC-SHA256 hashes and shown exactly once. A database leak alone cannot derive a usable key.

Roles

owner > admin > viewer, enforced by a single dependency at the route boundary rather than scattered checks.

Audit

Every privileged action records who did what, when, and from where — alongside the account correlation id.

Privacy

Visitor IPs are salted and hashed at ingest. Raw addresses are never persisted.

Secrets

Configuration loads from the environment. Peppers, postback secrets and database URLs never live in code.

Degradation policy

OK

All dependencies reachable — HTTP 200.

DEGRADED

Redis or workers down. The app still serves; background processing pauses — HTTP 200.

UNAVAILABLE

Database down. The only hard dependency, so no trusted data can be served — HTTP 503.

Exported metrics

  • profitos_http_requests_total{method,path,status}
  • profitos_http_request_duration_seconds{method,path}
  • profitos_celery_tasks_total{task,state}
  • profitos_queue_depth
  • profitos_workers_online
  • profitos_redis_up · profitos_db_up
  • profitos_connector_records_total{status}
  • profitos_connector_syncs_total{status}

Structured access log

{"ts":"2026-08-06T17:22:41.118Z","level":"INFO","logger":"profitos.access",
 "message":"POST /postback 200","request_id":"9c4f1ab7e0d3","account_id":42,
 "method":"POST","path":"/postback","status_code":200,"latency_ms":11.4}