Audit policy · Zoza Auth

Every challenge logged. Every admin action logged. Customer banks read it all.

Zoza Auth is an authentication oracle: when we say "approved", a bank transfers money. The single most important safety property we can offer is: the bank can verify every event we've ever signed off on, on its own account. This page documents exactly what's logged, who reads it, and how long we keep it.

The two log surfaces

Auth maintains two complementary logs:

Both logs pull from the same source events — one is customer-scoped, the other is platform-scoped. A breach or tamper on one cannot hide from the other.

Events we log

actionwhenvisible toretention
device_registeredUser enrols a new device with bank XBank X90 days
device_revokedBank X revokes a user's device (theft, replacement)Bank X90 days
challenge_issuedBank X calls POST /v1/challengesBank X90 days
challenge_approvedUser's device signs + verify succeedsBank X90 days
challenge_deniedUser taps Deny, or verify fails (wrong key, mismatch)Bank X90 days
challenge_expiredTTL elapsed without a responseBank X90 days
application_submitProspective customer submits POST /v1/applicationsZoza opsIndefinite (abuse signal)
application_approve / application_rejectZoza admin reviewsZoza opsIndefinite

Each row stores: app_id, user_id, device_id, challenge_id, action, success, error, created_at. Plaintext payloads, proofs, private keys, and biometric data are never logged.

How customer banks read their log

Authenticated to the API with your bearer API key:

# Fetch the latest 100 audit events for your app
curl https://auth-api.zoza.world/v1/apps/{app_id}/audit   -H "Authorization: Bearer $ZOZA_AUTH_API_KEY"

# Example response
{
  "app_id": "app_...",
  "count": 100,
  "audits": [
    {
      "id": "aud_...",
      "action": "challenge_approved",
      "user_id": "user_rahul",
      "device_id": "iphone_15_pro",
      "challenge_id": "ch_...",
      "success": true,
      "created_at": "2026-04-17T14:22:18Z"
    },
    ...
  ]
}

We recommend banks pull their log every 5 minutes into their own SIEM (Splunk / Chronicle / ELK). If an attacker compromises our API, the bank's local copy remains tamper-evident.

Who else can read it?

Zoza operators: yes, for platform operation (debugging, abuse triage, rate-limit tuning). Every operator read is itself logged in activity_logs on zoza-admin — a read of the audit log creates an audit log entry. Meta-logging, so to speak.

Law enforcement: only under a DPDP-compliant legal request addressed to the customer bank, not to Zoza directly. We are a data-processor, not a data-fiduciary. In the rare case of compelled disclosure targeting Zoza (e.g. if the bank itself is under investigation), the warrant canary at /about/auth-canary reflects that.

The public: no — unlike Shield, Auth's audit log is customer-scoped (private). What's public is the existence of the log, the field schema, the retention period, and this policy.

Tamper resistance

The auth_audit table is append-only at the application layer. Direct database DELETE or UPDATE is possible with Postgres superuser — in that scenario, the customer bank's own scraped copy (see above) is the ground truth. On the roadmap: ed25519-signed hash-chain, same pattern as Shield's audit log. ETA ~20 dev days.

In the meantime, every admin action in zoza-admin leaves a second row in activity_logs with a separate write path — a tamper on one without the other is detectable.

What we never log