Skip to content

feat(service-auth-py): Python S2S auth client + verifier + middleware - #876

Merged
izzywdev merged 3 commits into
masterfrom
feat/service-auth-py-client
Aug 31, 2026
Merged

feat(service-auth-py): Python S2S auth client + verifier + middleware#876
izzywdev merged 3 commits into
masterfrom
feat/service-auth-py-client

Conversation

@izzywdev

Copy link
Copy Markdown
Owner

Summary

  • Adds fuzefront-service-auth (packages/service-auth-py), the Python peer of the merged TypeScript packages/service-auth (Add @fuzefront/service-auth: runtime S2S auth (client + fail-closed verifier + middleware) #873) and @fuzefront/security-client.
  • ServiceAuthClient: caller-side M2M token acquisition against POST /api/v1/security/tokens, in-memory caching, refresh-before-expiry with a safety margin, thread-safe single-flight refresh, invalidate().
  • MachineTokenVerifier.verify_machine_token(): callee-side verification against POST /api/v1/security/tokens/introspect. Fails closed on every ambiguity (connection error, timeout, malformed body, missing/non-bool active) and — critically — branches on the active boolean in the response BODY, never on HTTP status, because that endpoint always answers HTTP 200 per the real server route (backend/security/src/routes/security.ts).
  • FastAPI dependency (middleware/fastapi.py) and Flask decorator (middleware/flask.py), both emitting the same {"error", "code"} JSON body shape as the TS sibling's Express middleware, sharing its ServiceAuthErrorCode vocabulary.
  • Bounded, positive-only LRU cache for verified identities, capped at the token's own exp; failures are never cached.
  • Pluggable authorize hook seam (authz.py) for per-caller authorization once /authz/* is wired in by callers.
  • .github/workflows/service-auth-py-publish.yml, mirroring identity-py-publish.yml / config-client-py-publish.yml (GitHub Release asset — GitHub Packages has no PyPI-style registry and this is a private family package).

Why this repo/location

Python client packages that peer a TS runtime already live under packages/*-py in this repo (identity-py, config-client-py, selection-list-client-py), all distributed as GitHub Release assets. packages/service-auth-py is the natural sibling of packages/service-auth (#873), so backend/UI/tests all read as one product rather than splitting the S2S story across repos. FuzeKeys was considered and ruled out — it's a separate identity/vault product, not this cross-service concern.

Test plan

  • pytest -q40 passed (mocked HTTP layer, no real network calls)
  • Includes the regression test the package exists for: an introspection response with HTTP 200 and active: false is rejected — in the verifier, the FastAPI dependency, and the Flask decorator
  • Concurrent single-flight refresh (20 threads, 1 HTTP call), refresh-before-expiry, fail-closed on connection error / malformed body / non-200
  • Publish to GitHub Release — not run in this PR (tag-triggered); package is merge-ready, not yet published

🤖 Generated with Claude Code

fuzeone-bot and others added 3 commits August 31, 2026 21:50
…ware [skip ci]

WIP: builds fuzefront-service-auth (packages/service-auth-py), the Python
peer of packages/service-auth, against the frozen packages/security/openapi.yaml
tokens contract. Local pytest run pending (dependency install contended by
concurrent worktree agents on this machine) -- pushing now per no-stall policy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session-Id: fe3aa738-cb24-4315-a29b-29834ddea892
Align error codes/status, MachineIdentity.scopes, and invalidate() with the
merged TypeScript sibling (FuzeFront PR #873) so both languages' resource
servers emit the same {error, code} JSON body and share one error-code
vocabulary (MISCONFIGURED/TOKEN_REQUEST_FAILED/MALFORMED_RESPONSE/NO_TOKEN/
INTROSPECTION_UNAVAILABLE/TOKEN_INACTIVE/FORBIDDEN/UNKNOWN).

Verified: pytest -q -> 40 passed (includes the fail-open regression test:
an introspection response with HTTP 200 and active:false is rejected, in
the verifier, the FastAPI dependency, and the Flask decorator).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session-Id: fe3aa738-cb24-4315-a29b-29834ddea892
@github-actions
github-actions Bot enabled auto-merge (squash) August 31, 2026 19:04
@izzywdev
izzywdev merged commit 30ac560 into master Aug 31, 2026
43 of 44 checks passed
@izzywdev
izzywdev deleted the feat/service-auth-py-client branch August 31, 2026 19:04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

- uses: actions/setup-python@v7
headers={"Content-Type": "application/json", "Accept": "application/json"},
)
try:
with urllib.request.urlopen(request, timeout=timeout) as response:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants