Prevent concurrent version bumps and spurious releases in the release
pipeline:
- Add a workflow-level concurrency group (cancel-in-progress: false) so
only one bump-version run executes at a time. Concurrent runs have
previously raced to bump the version and push tags, causing release
failures. Subsequent pushes now queue instead of cancelling an
in-flight bump/release.
- Make commitizen the single source of truth for whether a release is
warranted. The previous grep heuristic counted commits matching
feat|fix|docs|refactor|perf|test|build|ci|chore, but commitizen only
bumps for feat/fix/breaking changes. A CI- or docs-only push therefore
set bumped=true and fired release+docker against the old, already
released tag. Now we compare the latest tag before/after running
bump-mcp.sh and only set bumped=true (and emit the new tag) when it
actually changes, so release/docker exit early on non-release pushes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Split the Docker image build into a per-platform matrix and merge job,
producing a single multi-arch manifest (linux/amd64 + linux/arm64) without
QEMU emulation. The arm64 build runs on the native ubuntu-24.04-arm runner.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Blocking:
- AS proxy callback now calls verify_id_token before caching the proxy
code so a tampered IdP response can't smuggle identity claims.
Important:
- Browser OAuth flow generates and verifies an OIDC nonce; new alembic
migration 006 adds the nonce column to oauth_sessions.
- _origin_matches_self logs a warning when CSRF check is bypassed.
- oauth_tools.py uses get_shared_storage instead of fresh handles.
Nits:
- New token_utils.get_oidc_discovery shares the 5-minute cache with
verify_id_token; oauth_login (integrated) and _revoke_refresh_token_at_idp
now use it instead of issuing fresh discovery fetches.
- Drop typing.Optional from oauth_tools.py in favour of X | None.
CI:
- test.yml generates an ephemeral Fernet TOKEN_ENCRYPTION_KEY per run
with openssl, removing the dependency on a missing repo secret.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses the two remaining 🟡 findings from the PR #758 follow-up review:
1. extract_user_id_from_token previously fell back to "default_user" when
the verified access token had no sub claim. In a multi-tenant deployment
a malformed IdP token could have bucketed every request under a single
sentinel user, risking cross-tenant data exposure. The function now
raises McpError on that branch; the BasicAuth no-token sentinel path is
preserved.
2. oauth_callback_nextcloud (Flow 2) read the PKCE code_verifier from
oauth_sessions but never deleted the row, leaving the verifier valid for
the full 10-minute TTL. The row is now deleted eagerly inside the same
branch, mirroring oauth_login_callback in browser_oauth_routes.
Also wires TOKEN_ENCRYPTION_KEY through the docker-compose step in the CI
test workflow so the integration matrix can boot — every job had been
failing fast on the ${TOKEN_ENCRYPTION_KEY:?...} interpolation guard added
in PR #758 finding 5.
Tests pin both fixes (test_token_utils_user_id.py,
test_oauth_callback_session_cleanup.py).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps the claude-code-action pin to v1.0.97 and turns on
`track_progress` + `use_sticky_comment` so reviews update a single
tracking comment per PR instead of appending a fresh comment on every
push. Mirrors the pattern in astrolabe-cloud-website.
The prompt now directs Claude to deliver the review by editing the
tracking comment via `mcp__github_comment__update_claude_comment`, and
`Bash(gh pr comment:*)` is dropped from the allowed-tools list since
that path is no longer used. Permissions widen from read to write on
pull-requests + issues so the action can edit its own comment.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>