docs: propose callback ingress and maintenance ADRs#277
Conversation
📝 WalkthroughWalkthroughThis PR adds two architectural decision records (ADRs) that define how callback ingress and maintenance-only runtime roles should operate as separate deployable surfaces within the awa system. ADR-027 specifies callback ingress extraction with signature verification and a dedicated CLI command. ADR-028 defines a maintenance-only runtime that executes internal loops independently. Both are indexed in the ADR README. ChangesArchitectural Decisions
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ADR-029 (#284) provides the durable lifecycle-effect mechanism ADR-027 explicitly punted on and ADR-028 implicitly relied on. Update both ADRs and the index to reference it: - ADR-027: replace the "needs a future durable mechanism" passage with a reference to ADR-029; observation hooks stay in-process, durable side effects flow through transactional follow-up jobs from the callback receiver's resolution transaction. - ADR-028: note that rescues close the rescue/timeout event gap by emitting follow-up Awa jobs in the rescue transaction, no handler registry required in the maintenance process. - ADR index: cross-reference ADR-029 from the 027/028 rows.
- Fix wrong claim that cancellation produces no hooks today: `Cancelled` is a hook event in ADR-015; the ADR now states cancellation has both a hook and an enqueue counterpart. - Use the `on_*_enqueue` family naming consistently in the boundary section (was mixing a stray generic `on_event_enqueue`). - Acknowledge that `WaitingForCallback` is a new event introduced by the ADR-015 amendment in PR #276; on `main` prior to that PR neither the hook variant nor the `on_waiting_for_callback_enqueue` counterpart exists. - Point the index row at the PR that proposes ADR-027/028 (#277) rather than the ADR file paths, which only exist on that branch until it lands.
- Fix wrong claim that cancellation produces no hooks today: `Cancelled` is a hook event in ADR-015; the ADR now states cancellation has both a hook and an enqueue counterpart. - Use the `on_*_enqueue` family naming consistently in the boundary section (was mixing a stray generic `on_event_enqueue`). - Acknowledge that `WaitingForCallback` is a new event introduced by the ADR-015 amendment in PR #276; on `main` prior to that PR neither the hook variant nor the `on_waiting_for_callback_enqueue` counterpart exists. - Point the index row at the PR that proposes ADR-027/028 (#277) rather than the ADR file paths, which only exist on that branch until it lands.
…cycle effects (#284) * docs: propose ADR-029 — transactional follow-up jobs for durable lifecycle effects Codify ADR-015's prose advice ("enqueue another job") as a first-class API. In-process hooks (ADR-015) remain for observation; durable side effects are delivered by enqueuing a follow-up Awa job in the same transaction as the triggering state commit, inheriting Awa's at-least-once delivery, retries, DLQ, and admin visibility. Resolves the durable-callback-notification punt in ADR-027 (callback ingress enqueues follow-ups in the resolving transaction) and closes the rescue/timeout event gap implied by ADR-028 (maintenance can enqueue follow-ups in the rescue transaction). Composes with ADR-013's guarded finalization: rolled-back outcomes do not emit follow-ups. Considers and rejects: NOTIFY as the substrate (at-most-once, drops to disconnected listeners), a dedicated awa.events outbox (duplicates Awa's own durable queue engine), and WAL CDC (heavy infra, contrary to ADR-001). * docs(adr-029): address review feedback - Fix wrong claim that cancellation produces no hooks today: `Cancelled` is a hook event in ADR-015; the ADR now states cancellation has both a hook and an enqueue counterpart. - Use the `on_*_enqueue` family naming consistently in the boundary section (was mixing a stray generic `on_event_enqueue`). - Acknowledge that `WaitingForCallback` is a new event introduced by the ADR-015 amendment in PR #276; on `main` prior to that PR neither the hook variant nor the `on_waiting_for_callback_enqueue` counterpart exists. - Point the index row at the PR that proposes ADR-027/028 (#277) rather than the ADR file paths, which only exist on that branch until it lands.
… (#293) * feat(callbacks): callback-only receiver router and CLI subcommand Adds `awa_ui::callback_router(pool, CallbackReceiverConfig)` — an axum router that mounts only the three callback ingress routes (`complete`, `fail`, `heartbeat`). It deliberately omits everything in `awa serve` that doesn't belong on a publicly-reachable surface: - no static UI assets - no admin REST routes (jobs, queues, DLQ, runtime, stats) - no permissive CORS - writable DB required at build time (read-only pools fail fast instead of surfacing as runtime 503s on every request) `CallbackAuth` is an explicit enum (`Signed([u8; 32])` vs `Unsigned`) so the security choice cannot be made by forgetting a setter. `Unsigned` is intentionally awkward to type — choose it only when the receiver lives on a trusted network (mTLS at the load balancer, IP allow-list, private VPC). CLI surface: `awa callbacks serve` with its own tuned pool, the same host/port/pool flags as `awa serve`, plus `--callback-hmac-secret`, `--path-prefix`, and `--allow-unsigned`. Mutually-exclusive validation fails fast with a useful message. Tests cover: - valid + invalid signature on every route - admin and static paths returning 404 on the receiver - `--allow-unsigned` accepting unauthenticated requests - custom `path_prefix` routing (and default 404ing under that config) docs/http-callbacks.md gains a "Deploying callback ingress separately" section explaining when to use the receiver vs `awa serve` and showing the CLI invocation. Closes #279. Refs #277 (design), ADR-027. * feat(callbacks): user-owned callback receiver helpers and docs Adds the minimum surface needed for hosting Awa's callback ingress routes inside a user-owned API layer (FastAPI, axum, Flask, etc.) without copying the signing algorithm. Rust side: the `awa::callback_contract` module already exposes `sign`, `verify`, `callback_url`, and the protocol constants. The new `docs/callback-receivers.md` shows the canonical custom-axum pattern that composes those helpers with `awa::admin::*_external`. Python side: - New PyO3 wrappers in `awa-python/src/callback_contract.rs` export the same three Rust functions plus the constants. They take and return the same types so signatures produced from Python are bit-for-bit identical to what the worker emits. - New `awa.callback_contract` Python module re-exports them with ergonomic names (`sign`, `verify`, `build_callback_url`, `SIGNATURE_HEADER`, `DEFAULT_HEARTBEAT_TIMEOUT_SECS`, `DEFAULT_PATH_PREFIX`). - `awa.__init__` exposes it as `awa.callback_contract`. - `awa/_awa.pyi` typestubs describe the new surface. - New `tests/test_callback_contract.py` (11 tests) pins the contract: roundtrip, wrong-secret/id/hex rejection, secret-length validation, URL normalization, constant parity, AND a known BLAKE3 test vector asserted from both Python and Rust so the bindings cannot drift. Docs: - `docs/callback-receivers.md` is the new home for the user-owned API pattern, covering custom axum and FastAPI receivers end-to-end and pointing back at the `callback_path_prefix` worker knob from #280. - `docs/http-callbacks.md` links to it for the third deployable option (alongside `awa serve` and `awa callbacks serve`). Closes #281. Refs #277 (design draft), ADR-027.
Summary
awa serve/ admin UIBoth ADRs depended on a story for "how do durable lifecycle effects flow when the resolving / rescuing process has no handler registry?" That story is now ADR-029, proposed separately in #284, and the latest revision of this PR wires ADR-027 and ADR-028 to reference it explicitly (callback ingress and maintenance rescue both emit follow-up jobs in the same transaction as their state commit).
Related design
Follow-up issues
Validation