Metadata-Version: 2.4
Name: authweave-webhooks
Version: 7.3.1
Summary: Asymmetric Standard Webhooks toolkit for AuthWeave integrations
Project-URL: homepage, https://github.com/ZYLVEXT/litestar-auth
Project-URL: documentation, https://zylvext.github.io/litestar-auth/
Project-URL: source, https://github.com/ZYLVEXT/litestar-auth
Project-URL: tracker, https://github.com/ZYLVEXT/litestar-auth/issues
Author-email: Vladislav Shepilov <shepilov.v@protonmail.com>
Maintainer-email: Vladislav Shepilov <shepilov.v@protonmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: authentication,ed25519,security,standard-webhooks,webhooks
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries
Requires-Python: <3.15.0,>=3.12.0
Requires-Dist: authweave-core==7.3.1
Requires-Dist: cryptography<51.0,>=50.0.0
Provides-Extra: httpx
Requires-Dist: httpx<1.0,>=0.28.1; extra == 'httpx'
Provides-Extra: litestar
Requires-Dist: litestar<3.0,>=2.24.0; extra == 'litestar'
Provides-Extra: redis
Requires-Dist: redis<9.0,>=8.1.0; extra == 'redis'
Description-Content-Type: text/markdown

# authweave-webhooks

Asymmetric Standard Webhooks toolkit for AuthWeave integrations
(`authweave-standard-webhooks-v1a` Ed25519 profile).

This package does **not** depend on `litestar-auth` and is not authentication
middleware. It verifies or produces webhook deliveries before JSON parsing.

```bash
uv add 'authweave-webhooks[redis]'
```

```python
from authweave_webhooks import (
    Ed25519PublicKey,
    PublicKeyDocument,
    StandardWebhooksVerifier,
    StaticPublicKeyResolver,
)
from authweave_webhooks.redis_store import RedisReplayStore

resolver = StaticPublicKeyResolver(
    PublicKeyDocument(
        version="1",
        environment="sandbox",
        owner="merchant-1",
        endpoint="https://merchant.example/hooks/payments",
        not_before=0,
        retire_after=None,
        keys=(Ed25519PublicKey(public_key),),
    )
)
verifier = StandardWebhooksVerifier(
    resolver,
    replay_store=RedisReplayStore(redis),
    expected_environment="sandbox",
    expected_owner="merchant-1",
    expected_endpoint="https://merchant.example/hooks/payments",
    time_source=lambda: 1_700_000_000,
)
verified = await verifier.verify(headers=headers, body=raw_body)
```

The replay store is mandatory. After a signature succeeds, `verify()` atomically
claims the `webhook-id` in a namespace derived from environment, owner, endpoint,
and id. The library derives a TTL that covers the complete inclusive timestamp
acceptance window; replay-store outage or capacity pressure fails verification
closed. A repeated valid delivery is returned with `verified.replay_detected=True`;
the flag is telemetry, not business idempotency.

After **every** successful verification, atomically insert the complete raw body
and verified metadata into a durable inbox with a unique key over environment,
owner, endpoint, and `webhook_id`. Never overwrite an existing row, and acknowledge
the HTTP delivery only after that transaction commits. A retry can then restore an
inbox row missing after a crash, while a committed row absorbs concurrent or later
retries. Use a shared replay store such as Redis in multi-worker deployments.

Pass an optional core `SecurityObserver` to the verifier or HTTP sender to emit
bounded verification/replay/delivery telemetry. Retry and queue consumers may
pass `TraceCorrelation` values through `links=`; trace context is correlation
only and is never accepted as identity.

`HttpxWebhookSender` requires a non-empty exact endpoint allowlist, disables
redirects, and streams at most 65,536 response bytes. The application must also
place its HTTP client behind the controlled egress proxy/subnet described in the
merchant sender threat model; DNS safety is not inferred from HTTPS syntax.

```python
from authweave_webhooks.sender import HttpxWebhookSender

sender = HttpxWebhookSender(
    httpx_client,
    allowed_endpoints={"https://merchant.example/hooks/payments"},
)
result = await sender.send(endpoint=merchant_endpoint, delivery=delivery)
```

## Extras

- `[redis]` — shared `RedisReplayStore` for fail-closed verification
- `[httpx]` — one-shot HTTPS sender without auto-retry
- `[litestar]` — raw-body verification helper

Private keys stay inside `AsyncMessageSigner` implementations. The library never
accepts private key bytes on verifier APIs and keeps secrets out of `repr` /
error messages.

See `docs/roadmap.md`, `docs/merchant/webhooks.md`, the sender threat model, and
ADR 0002 for key-tenancy and egress rules. Language-neutral vectors plus Python
and dependency-free Node.js verifiers live in `docs/vectors/webhooks/v1a/`.
