Skip to content

[Maintainer] Upgrade to v0.12.0 #47

@github-actions

Description

@github-actions

[Maintainer] Upgrade to v0.12.0

Current version: 0.10.0
Target version: 0.12.0

⚠️ This is a breaking release. Manual review is recommended.

Upgrade Notes

Highlights

New opt-in OAuth2 client_credentials client for service-to-service auth, plus a matching integration in the fleet-registry emitter. Caretaker can now attach a bearer JWT to outbound heartbeats alongside (or instead of) the existing HMAC signature path.

OAuth2 client (src/caretaker/auth/oauth_client.py)

  • OAuth2ClientCredentials posts to the token endpoint using client_secret_basic, caches the returned JWT in-process with a 30-second skew against the server-reported expires_in, and coalesces concurrent callers through an asyncio.Lock so a burst of requests triggers a single refresh.
  • build_client_from_env() reads OAUTH2_CLIENT_ID / OAUTH2_CLIENT_SECRET / OAUTH2_TOKEN_URL (and optional OAUTH2_SCOPE) and returns None when any required var is unset — callers fall through to their unauthenticated path so existing installs stay byte-identical.
  • Failures surface as OAuth2TokenError; the module never retries silently.

Fleet emitter integration

  • FleetRegistryConfig.oauth2 → new OAuth2ClientConfig block (off by default). When enabled, emit_heartbeat decorates the heartbeat POST with Authorization: Bearer <jwt>.
  • Module-level client cache keyed on (client_id, client_secret, token_url, scope_env, scope, timeout) keeps the JWT cache warm across heartbeats and invalidates automatically on rotation.
  • Fail-open contract preserved: an auth-server outage logs a WARNING and the heartbeat still goes out (unauthenticated) rather than breaking the run loop.

Configuration

fleet_registry:
  enabled: true
  endpoint: https://fleet.example/api/fleet/heartbeat
  oauth2:
    enabled: true
    client_id_env: OAUTH2_CLIENT_ID
    client_secret_env: OAUTH2_CLIENT_SECRET
    token_url_env: OAUTH2_TOKEN_URL
    scope_env: OAUTH2_SCOPE
    default_scope: ""
    timeout_seconds: 10.0

Consumer rollout

Five caretaker-topic consumer repos were provisioned against the shared roauth2.cat-herding.net authorization server (client_credentials, scope read write):

  • audio_engineer, python_dsa, kubernetes-apply-vscode, flashcards, Example-React-AI-Chat-App

Each carries per-repo OAUTH2_CLIENT_ID / OAUTH2_CLIENT_SECRET secrets plus OAUTH2_TOKEN_URL / OAUTH2_ISSUER_URL variables. The caretaker side remains opt-in; flip fleet_registry.oauth2.enabled to start using them.

Compatibility

  • No breaking changes. Default behaviour unchanged — OAuth2 only engages when both the config block and the env vars are populated.
  • min_compatible: 0.10.0.

Tests

12 new unit tests for OAuth2ClientCredentials (cache hit/miss, concurrent coalescing, expiry clamping, transport errors, authorization header shape) plus 2 new emitter tests covering the bearer-header wiring and fail-open behaviour on token-fetch failure.

🤖 Generated with Claude Code

📋 Full Changelog

@copilot Please apply this upgrade.
See .github/agents/maintainer-upgrade.md for instructions.

FROM: 0.10.0
TO: 0.12.0
BREAKING: True

Steps:

  1. Update version pins in pyproject.toml / requirements.txt
  2. Update any workflow references
  3. Run tests to verify compatibility
  4. Update the version in config if applicable

Acceptance criteria:

  • Version updated to target
  • All tests pass
  • No regressions

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions