Catalog PyPI
PACKAGE EXPLORERView in registry

aac-invoke-auth

PyPI

AAC sidecar-to-agent invoke-push authentication (AAC1-HMAC-SHA256) — signing and verification core, with FastAPI mounting surfaces.

aacagentauthorizationfastapihmacmiddlewaresidecar
Versions collected1
Direct dependencies3From release 0.1.2
Last observed20 Oct, 16:50 UTC

README

Version 0.1.2 documentation

aac-invoke-auth

Authenticate /invoke pushes from your paired AAC sidecar.

When your agent runs behind an AAC sidecar, the sidecar verifies the cross-organizational authority chain and then POSTs the verified context to your agent's /invoke endpoint. The X-AAC-* headers on that push are your agent's entire view of the verified chain — so your agent must be able to tell a genuine sidecar push from a forged one. This package is that check: the sidecar HMAC-signs every push with a pairing secret shared with exactly one agent, and your agent verifies the signature before trusting anything.

The verification core is standard-library only (hmac, hashlib) and framework-agnostic. FastAPI mounting surfaces ship behind an extra:

pip install aac-invoke-auth[fastapi]

Quick start (FastAPI)

Generate the pairing secret once and share the file with your sidecar (the sidecar's sidecar.agent_invoke_auth.secret_file points at the same file; one secret per sidecar–agent pair, never shared across pairs):

openssl rand -hex 32 > /etc/aac/invoke-auth/invoke-auth.secret

Point your agent at it and mount the middleware:

export AAC_INVOKE_AUTH_SECRET_FILE=/etc/aac/invoke-auth/invoke-auth.secret
from fastapi import FastAPI
from aac_invoke_auth.fastapi import InvokeAuthGuard, InvokeAuthMiddleware

app = FastAPI()
app.add_middleware(
    InvokeAuthMiddleware,
    guard=InvokeAuthGuard.from_env(),
    protected_paths=("/invoke",),   # required, exact-match
)

That's the whole integration. Unsigned, tampered, replayed-stale, or wrong-secret pushes get a 401 with a generic detail and never reach your business logic; your handlers read request.json() unchanged.

Prefer route-scoped protection? The guard is also a plain FastAPI dependency:

from fastapi import Depends

guard = InvokeAuthGuard.from_env()

@app.post("/invoke", dependencies=[Depends(guard)])
async def invoke(request: Request): ...

Both surfaces call the same verifier — pick whichever fits your app.

Fail-fast startup, by design

InvokeAuthGuard.from_env() refuses to start when AAC_INVOKE_AUTH_SECRET_FILE is unset. A missing secret is a security downgrade; it should fail your deployment loudly at boot, not degrade into a log line nobody reads.

The single escape hatch — for extraordinary cases only, such as tenant test/pilot environments or debugging a suspected signing mismatch — is setting

export AAC_INVOKE_AUTH_ALLOW_UNAUTHENTICATED=true

explicitly (only the exact value true; a typo still fails the boot). An opted-out agent accepts every push unverified and logs a prominent warning at startup so the posture is visible in your logs. Never run this in production: the sidecar side has a symmetric dev_mode interlock, and both exist to make "unauthenticated" impossible to reach by accident.

Testing your agent

aac_invoke_auth.testing ships with the package:

from aac_invoke_auth.testing import signing_test_client

client = signing_test_client(app)          # wraps FastAPI's TestClient
response = client.post("/invoke", headers=aac_headers, json=payload)

post() calls to protected paths are signed exactly the way the paired sidecar signs them (secret read from AAC_INVOKE_AUTH_SECRET_FILE); everything else passes through. So your test suite exercises the real production verification path instead of opting out of it.

Wire format

AAC1-HMAC-SHA256 over method, path, timestamp, a SHA-256 body digest, and every X-AAC-* header (derived by rule, so header insertion/removal after signing fails verification). Freshness window ±30s. The canonicalization is frozen behind the algorithm name: a change that alters any signature is a wire-format break and ships under a new algorithm prefix, never as an update to AAC1-HMAC-SHA256.

Ports of this middleware for other stacks (Express, Spring, Go net/http) follow the same model; the core stays standard-library-only in every language precisely to keep those ports mechanical.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.214 Sept 20263

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

NOT_FOUND
cascadeauth/aac-prototype

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 16:50 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:d2a3955cbf586cb47d7a76c100bc8da33cae613600ce95961c0aed5ba5430f10