Commit Graph

1949 Commits

Author SHA1 Message Date
Chris Coutinho 0a53aa5fcd ci: enable Playwright browser tests in GitHub Actions
The GITHUB_ACTIONS skip was added before Playwright automation existed,
when tests required manual browser interaction. Now that Playwright
handles the OAuth flow programmatically, the skip is unnecessary —
GitHub Actions fully supports Playwright with localhost networking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:09:14 +01:00
Chris Coutinho abd43f8028 ci: disable NC 33 matrix until upstream apps support it
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:57:21 +01:00
Chris Coutinho e7157ab256 fix: skip keycloak hook when profile inactive and update stale PRM test
Add DNS pre-check (getent hosts keycloak) to the post-installation hook
so it exits instantly when the keycloak profile is not active, instead of
retrying for ~2.5 minutes. Also update test_prm_endpoint to assert the
AS proxy URL (localhost:8001) per ADR-023, replacing the stale Nextcloud
URL (localhost:8080).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:50:15 +01:00
Chris Coutinho 5947fff13f chore: revert 2026-03-02 11:28:56 +01:00
Chris Coutinho a9e5c687b8 ci: Ignore oauth and multi-user-basic in integration testing matrix to reduce github ci usage 2026-03-02 11:27:37 +01:00
Chris Coutinho 9d1a84af5a feat(auth): implement OAuth AS proxy to fix audience mismatch (ADR-023)
MCP clients like Claude Code were unable to use tools because tokens
obtained directly from Nextcloud had the wrong audience claim. The MCP
server now acts as its own OAuth Authorization Server, proxying auth
to Nextcloud with its own client_id so tokens have the correct audience.

New endpoints: /.well-known/oauth-authorization-server, /oauth/token,
/oauth/register. Modified /oauth/authorize from pass-through to
intermediary pattern. PRM now points authorization_servers to the MCP
server instead of Nextcloud.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:25:54 +01:00
Chris Coutinho d09ebf20cc feat(ci): add Nextcloud version matrix (NC 31, 32, 33)
- Add cross-product matrix (3 versions x 4 auth modes = 12 CI jobs)
- Parameterize Nextcloud image in docker-compose.yml via NEXTCLOUD_IMAGE env var
- Pin NC 31.0.8, 32.0.6, 33.0.0 with SHA digests in workflow
- Add Renovate customManagers to auto-update NC images in workflow
- Fix Astrolabe install hook to prefer volume mount over app store
- Bump Astrolabe submodule to support NC 33 (max-version 31→33)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:13:38 +01:00
Chris Coutinho 0d14c75eb1 fix: address remaining PR #589 review findings
- Consolidate MCP session + login flow cleanup into _mcp_session_with_login_flow() helper,
  replacing 4 duplicated AsyncExitStack sites in app.py
- Fix get_shared_storage() race condition by using module-level anyio.Lock() init
  (reverts regression from ba59763)
- Collapse cosmetic if/else branching in scope_authorization.py
- Consolidate dual password storage paths into single store_app_password_with_scopes() call
- Mark unused request param as _ in list_supported_scopes
- Make ALL_SUPPORTED_SCOPES an immutable tuple; use list() instead of .copy()
- Add hasattr(ctx, "elicit") guard in elicitation.py, narrow except to NotImplementedError
- Add YAML comment explaining --oauth flag for mcp-login-flow service

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 09:59:56 +01:00
Chris Coutinho ba597634bd fix: address PR #589 review findings
- Fix anyio.Lock() created at module import time; use lazy init in
  get_shared_storage() to avoid instantiation before event loop exists
- Stop get_login_flow_session from silently swallowing DB exceptions;
  re-raise and handle in caller with proper error response
- Update ProvisionAccessResponse and UpdateScopesResponse status field
  docs to include all actual values (declined, cancelled, unchanged)
- Narrow except clause in present_login_url to (AttributeError,
  NotImplementedError) instead of bare Exception
- Add KeyError handling in LoginFlowV2Client.initiate() and poll() for
  clear errors on malformed Nextcloud responses
- Simplify redundant env-var bypass branches in scope_authorization.py
- Extract _maybe_login_flow_cleanup() context manager to replace 4
  inline cleanup loop registrations in app.py; move sleep to end of
  loop body so cleanup runs once at startup
- Replace fragile string replacement in _rewrite_login_flow_url with
  proper urllib.parse URL handling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 09:10:57 +01:00
Chris Coutinho 1a6ce0fa7d fix: address PR review issues for Login Flow v2
- Fix circular dependency in scope_authorization: auth tools requiring
  only identity scopes (openid/profile/email) now bypass the login flow
  provisioning check, so unprovisioned users can call provisioning tools
- Fix no-op detection in nc_auth_update_scopes: NULL scopes (legacy "all")
  now correctly map to ALL_SUPPORTED_SCOPES instead of empty set
- Fix get_app_password_with_scopes swallowing exceptions: re-raise instead
  of returning None, matching sibling methods
- Add missing audit logging to update_app_password_scopes,
  delete_login_flow_session, and delete_expired_login_flow_sessions
- Pin setup-uv to v7.3.1 in CI unit-test job (was v7.3.0)
- Add FastMCP type annotation to register_auth_tools parameter
- Log warning when user accepts elicitation without checking acknowledged box

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:02:30 +01:00
Chris Coutinho 3df0b06cd1 Merge remote-tracking branch 'origin/master' into feat/docker-compose-profiles-login-flow 2026-03-01 18:52:50 +01:00
Chris Coutinho 0b8afec494 feat(helm): add login-flow auth mode to Helm chart (ADR-022)
Add Login Flow v2 as a fourth auth mode alongside basic, multi-user-basic,
and oauth. This enables multi-user deployments using Nextcloud's native
Login Flow v2 without requiring OAuth patches to user_oidc.

- Add loginFlow section to values.yaml with token encryption config
- Add login-flow env vars, args, volume mounts to deployment.yaml
- Add login-flow secret and oauth-storage PVC templates
- Add loginFlowSecretName helper, update dataStorageEnabled
- Add multi-user-basic and login-flow sections to NOTES.txt
- Add version footer and ArtifactHub changelog annotations
- Update README with 4 auth modes and docker-compose profiles

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:25:23 +01:00
Chris Coutinho bd69e68dd5 ci: enable Playwright install for multi-user-basic CI job
Astrolabe tests moved to multi_user_basic markers use Playwright browser
automation, so the CI matrix entry needs needs-playwright: true.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:01:54 +01:00
Chris Coutinho 148573e28b Merge remote-tracking branch 'origin/master' into feat/docker-compose-profiles-login-flow 2026-03-01 17:26:05 +01:00
github-actions[bot] 5d81d60262 bump: version 0.57.89 → 0.57.90 nextcloud-mcp-server-0.57.90 2026-03-01 16:26:00 +00:00
Chris Coutinho b86e798ba8 Merge pull request #592 from cbcoutinho/renovate/anthropics-claude-code-action-1.x
chore(deps): update anthropics/claude-code-action action to v1.0.64
2026-03-01 17:25:47 +01:00
Chris Coutinho a7d623733b Merge pull request #591 from cbcoutinho/renovate/docker.io-library-python-3.12-slim-trixie
chore(deps): update docker.io/library/python:3.12-slim-trixie docker digest to f3fa41d
2026-03-01 17:25:35 +01:00
github-actions[bot] 3311b20ef6 bump: version 0.57.88 → 0.57.89 nextcloud-mcp-server-0.57.89 2026-03-01 16:24:44 +00:00
Chris Coutinho 28c7f1cdbd Merge pull request #594 from cbcoutinho/renovate/ghcr.io-astral-sh-uv-0.x
chore(deps): update ghcr.io/astral-sh/uv docker tag to v0.10.7
2026-03-01 17:24:30 +01:00
github-actions[bot] 2713f74be6 bump: version 0.57.87 → 0.57.88 nextcloud-mcp-server-0.57.88 2026-03-01 16:23:38 +00:00
Chris Coutinho e3c5a87b22 Merge pull request #590 from cbcoutinho/renovate/docker.io-library-nextcloud-32.0.6
chore(deps): update docker.io/library/nextcloud:32.0.6 docker digest to 5c4e09f
2026-03-01 17:23:22 +01:00
Chris Coutinho 53cf223a56 Merge pull request #595 from cbcoutinho/renovate/ollama-1.x
chore(deps): update helm release ollama to v1.46.0
2026-03-01 17:23:11 +01:00
Chris Coutinho 6bfde0de1f Merge pull request #596 from cbcoutinho/renovate/major-github-artifact-actions
chore(deps): update actions/upload-artifact action to v7
2026-03-01 17:22:58 +01:00
github-actions[bot] 8cf3264914 bump: version 0.57.86 → 0.57.87 nextcloud-mcp-server-0.57.87 2026-03-01 16:05:13 +00:00
Chris Coutinho ed2f400ed8 Merge pull request #593 from cbcoutinho/renovate/astral-sh-setup-uv-7.x
chore(deps): update astral-sh/setup-uv action to v7.3.1
2026-03-01 17:04:56 +01:00
renovate-bot-cbcoutinho[bot] 6ba598afd1 chore(deps): update actions/upload-artifact action to v7 2026-03-01 16:03:54 +00:00
renovate-bot-cbcoutinho[bot] d0bfecea97 chore(deps): update helm release ollama to v1.46.0 2026-03-01 16:03:49 +00:00
renovate-bot-cbcoutinho[bot] bf0a4ac5d3 chore(deps): update ghcr.io/astral-sh/uv docker tag to v0.10.7 2026-03-01 16:03:28 +00:00
renovate-bot-cbcoutinho[bot] 3da6feba41 chore(deps): update astral-sh/setup-uv action to v7.3.1 2026-03-01 16:03:20 +00:00
renovate-bot-cbcoutinho[bot] 1224090469 chore(deps): update anthropics/claude-code-action action to v1.0.64 2026-03-01 16:03:13 +00:00
renovate-bot-cbcoutinho[bot] aa624401c3 chore(deps): update docker.io/library/python:3.12-slim-trixie docker digest to f3fa41d 2026-03-01 16:03:08 +00:00
renovate-bot-cbcoutinho[bot] 61e867397c chore(deps): update docker.io/library/nextcloud:32.0.6 docker digest to 5c4e09f 2026-03-01 16:03:02 +00:00
Chris Coutinho db1e0606ad fix: address PR #589 review feedback (round 2)
Consolidate three independent RefreshTokenStorage lazy singletons into a
single lock-protected get_shared_storage() function, eliminating race
conditions on concurrent first-access. Remove blanket try/except in
_get_stored_scopes so storage errors propagate as proper MCP errors
instead of silently triggering "please provision" messages. Handle
declined/cancelled elicitation results in Login Flow tools by cleaning up
sessions and returning clear status. Add update_app_password_scopes() to
avoid unnecessary decrypt/re-encrypt when only scopes change. Add
unprovisioned-user early exit and no-op detection to nc_auth_update_scopes.
Remove four dead config fields and misleading NEXTCLOUD_PASSWORD deprecation
warning. Add periodic login flow session cleanup task. Generate separate
Fernet keys per service. Add board cleanup in deck integration test. Gate
CI unit tests on linting and skip Astrolabe build for single-user profile.
Fix test markers from oauth to multi_user_basic for astrolabe integration
tests. Update login_flow.py docstrings to document outbound HTTP calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:35:31 +01:00
Chris Coutinho 33cf0fee9b fix(ci): remove dev OIDC mount to fix HTTP 500 in single-user/multi-user-basic
The dev OIDC app was mounted for all profiles but composer install only
ran for Playwright profiles, causing a missing vendor/autoload.php fatal
error that broke all /apps/* and /ocs/* routes. The hook script already
has app store fallback logic, so removing the dev mount is sufficient.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:28:01 +01:00
Chris Coutinho b2fd4da9fe fix(ci): fix health check timeout and per-profile MCP server URL routing
The Nextcloud health check expected HTTP 401 from serverinfo, but NC 32
returns 200 — causing 5-minute timeouts. Switch to /status.php with
"installed":true check (matches Docker healthcheck). Also route the
correct MCP_SERVER_URL per CI matrix profile into the app container so
Astrolabe connects to the right service, and make the init script
gracefully skip when the var is unset.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:30:07 +01:00
Chris Coutinho 16cd2e27cb fix(ci): fix PHP gating, add multi-user-basic matrix entry, upload debug artifacts
PHP setup was gated behind needs-playwright but Astrolabe build needs
composer unconditionally. Add multi-user-basic CI matrix entry with
proper marker filtering. Upload Playwright screenshots and service logs
as artifacts on failure for easier debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 11:02:39 +01:00
Chris Coutinho e28af5453b fix: address PR #589 review feedback for Login Flow v2
- Fix data loss in nc_auth_update_scopes: remove premature
  delete_app_password call; old password stays valid until upsert
  replaces it on successful re-provisioning
- Replace assert with proper error return in nc_auth_check_status
- Add lazy singleton for RefreshTokenStorage in auth_tools,
  scope_authorization, and context to avoid per-call re-initialization
- Centralize _is_login_flow_mode() to get_settings().enable_login_flow
  and remove duplicate definitions and per-call os.getenv reads
- Add dev-only comment to TOKEN_ENCRYPTION_KEY in docker-compose.yml
- Gate OIDC build steps in CI behind matrix.needs-playwright
- Add diagnostic step reporting Playwright skip count in CI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 10:08:55 +01:00
Chris Coutinho 87ec3c4f5b chore: update third_party submodule pointers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 09:17:29 +01:00
Chris Coutinho 989749530c fix(ci): fix integration test collection and skip Playwright in CI
- Add @pytest.mark.oauth to OAuth-dependent tests in
  test_scope_authorization.py so they're excluded from single-user job
- Add module-level pytestmark to test_introspection_authorization.py
- Fix single-user marker expression to also exclude oauth smoke tests
- Add --ignore paths for multi-user, qdrant, and RAG evaluation tests
- Uncomment GITHUB_ACTIONS skip in oauth_callback_server fixture
- Add GITHUB_ACTIONS skip to login_flow_oauth_token fixture
- Mount third_party/oidc volume in docker-compose.yml app service
- Add OIDC diagnostic step in CI for playwright jobs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 09:17:03 +01:00
Chris Coutinho 2d46959d01 fix(test): fix 17 pre-existing unit test failures and add astrolabe CI build
Unit test fixes:
- test_userinfo_routes: patch nextcloud_httpx_client instead of httpx.AsyncClient
- test_instrument_tool: patch trace_operation in metrics module (where imported)
- test_management_app_password_endpoints: patch nextcloud_httpx_client and
  get_settings at correct import locations
- test_management_status_endpoint: patch detect_auth_mode and get_settings at
  correct import locations (api.management, not config/config_validators)
- test_token_exchange: fix TokenBrokerService constructor args (client_id/
  client_secret instead of encryption_key)

CI:
- Add Node.js setup and astrolabe build step (composer + npm ci + npm run build)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:53:06 +01:00
Chris Coutinho 59fdcd123a fix(ci): keep third_party mount, always build submodules in CI
The third_party volume mount is required for astrolabe/notes/oidc
development. Always checkout submodules and build the OIDC app in
all CI matrix jobs since the app container needs it.

Remove the docker-compose.oidc.yml override (no longer needed).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:51:36 +01:00
Chris Coutinho b79c54cc6a fix(ci): revert accidental third_party mount, use compose override for OIDC
The third_party:/opt/apps volume was accidentally uncommented in
docker-compose.yml. Without submodules checked out, this empty mount
breaks the Notes app installation hook in CI.

Fix: keep the mount commented in docker-compose.yml and add a separate
docker-compose.oidc.yml override that's only used for OIDC-requiring
profiles (oauth, login-flow) in CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:48:07 +01:00
Chris Coutinho fe3fbe95a1 fix(ci): don't block integration matrix on unit-test failures
Unit tests have pre-existing failures unrelated to deployment mode
testing. Run integration matrix after linting only so the matrix
can expand and test each profile independently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:39:45 +01:00
Chris Coutinho 8fe7d81e57 ci: use matrix strategy for deployment mode integration tests
Replace the single integration-test job with a matrix that tests each
deployment mode independently using Docker Compose profiles:

- single-user: smoke + integration tests (port 8000)
- oauth: OAuth flow tests with Playwright (port 8001)
- login-flow: Login Flow v2 tests with Playwright (port 8004)

Unit tests run separately without Docker. OIDC app build and Playwright
install are conditional based on the mode. Service logs are captured on
failure for debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:35:47 +01:00
Chris Coutinho 8b5c2395b5 feat: add Docker Compose profiles and Login Flow v2 service
Add selective service startup via Docker Compose profiles so each MCP
deployment mode runs independently. Also add the new mcp-login-flow
service (port 8004) for Login Flow v2 authentication (ADR-022).

Profile assignments:
- single-user: mcp (port 8000)
- multi-user-basic: mcp-multi-user-basic (port 8003)
- oauth: mcp-oauth (port 8001)
- keycloak: keycloak + mcp-keycloak (port 8002)
- login-flow: mcp-login-flow (port 8004)

Infrastructure services (db, redis, app, recipes) always start.

Integration tests cover the full Login Flow v2 provisioning flow:
OAuth → browser login → app password → Nextcloud API access for
notes, calendar, contacts, files, deck, and cookbook operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:33:54 +01:00
github-actions[bot] 5796e2ba54 bump: version 0.57.85 → 0.57.86 nextcloud-mcp-server-0.57.86 2026-02-26 15:42:35 +00:00
github-actions[bot] 37141ea79f bump: version 0.64.3 → 0.64.4 v0.64.4 2026-02-26 15:42:35 +00:00
Chris Coutinho 68126f6fe3 Merge pull request #555 from cbcoutinho/renovate/icalendar-7.x
fix(deps): update dependency icalendar to v7
2026-02-26 16:42:12 +01:00
github-actions[bot] 78b934ffa6 bump: version 0.57.84 → 0.57.85 nextcloud-mcp-server-0.57.85 2026-02-25 12:43:46 +00:00
Chris Coutinho 01a9ad5278 Merge pull request #588 from cbcoutinho/renovate/anthropics-claude-code-action-1.x
chore(deps): update anthropics/claude-code-action action to v1.0.60
2026-02-25 13:43:30 +01:00