Callback security¶
The callback receiver exposes state-changing endpoints for externally executed attempts:
POST {prefix}/:callback_id/complete
POST {prefix}/:callback_id/fail
POST {prefix}/:callback_id/heartbeat
The default prefix is /api/callbacks. These routes can complete, fail, or extend an attempt, so they require an authentication boundary.
Signed callbacks¶
Awa supports a 32-byte BLAKE3 keyed hash over the callback ID. Despite the historical hmac option name, this is BLAKE3 keyed hashing, not RFC HMAC.
- Configure the receiver with
--callback-hmac-secretorAWA_CALLBACK_HMAC_SECRETusing 64 hexadecimal characters. - Configure
HttpWorkerConfig.hmac_secretwith the same 32-byte key. - The dispatcher sends
X-Awa-Signature; the external worker forwards it when calling the receiver. - The receiver verifies the signature before accepting a callback mutation.
If no secret is configured, signature verification is disabled. Use that only when a trusted network or authenticating proxy already protects the receiver.
Custom receivers¶
Use awa::callback_contract in Rust or awa.callback_contract in Python rather than reimplementing signature verification. Both language surfaces call the same Rust implementation and share a pinned test vector. The callback receiver guide includes axum and FastAPI examples.
Operational checklist¶
- Terminate TLS before any externally reachable receiver.
- Use a different secret in each environment and rotate it like any shared credential.
- Do not log callback signatures or secret material.
- Expose only the callback routes, not the admin router.
- Grant the receiver only the database/runtime authority its deployment model requires; never give it migrator credentials.