Commit Graph
2069 Commits
Author SHA1 Message Date
Chris CoutinhoandClaude Opus 4.6 2508f36ebf fix: address PR review round 2 — expiry checks, race guards, poll tests
- Log warning if /app mount not found when sharing poll task group
- Add docstring explaining unconditional task group creation
- Check session expires_at in provision_status to catch stale sessions
- Guard _poll_and_store status writes against cleanup-while-polling race
- Use "error" status (not "expired") when app_password is missing
- Remove hardcoded "Astrolabe Background Sync" user_agent string
- Fix async mock pattern (new_callable=AsyncMock) in test
- Add autouse fixture to clear _provision_sessions between tests
- Add _poll_and_store unit tests: completed, expired, error, cleanup
- Document all status values in provision_status docstring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 09:29:14 +02:00
Chris CoutinhoandClaude Opus 4.6 777a09c806 fix: address PR review — XSS escape, asyncio→anyio, URL rewrite dedup
- Escape HTML in _render_error to prevent XSS from exception messages
- Replace asyncio.create_task/sleep with anyio task group and sleep,
  tying poll task lifetime to the app lifespan for proper cleanup
- Extract rewrite_url_origin() utility to fix duplicated URL rewriting
  logic and replace urlparse._replace with stable urlunparse API
- Add warning log for insecure HTTP redirect URIs
- Add unit tests for validation, XSS escaping, route handlers, and
  URL rewriting (16 new tests in test_provision_routes.py)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 08:51:41 +02:00
Chris CoutinhoandClaude Opus 4.6 c21776948d fix: use app password auth for background sync in Login Flow mode
Login Flow v2 is a deployment-wide mode where all users authenticate
with app passwords (not OAuth refresh tokens). Set use_basic_auth=True
when enable_login_flow is true so the background sync user manager
queries the app_passwords table and scanners use app password
authentication for Nextcloud API calls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 00:55:31 +02:00
Chris CoutinhoandClaude Opus 4.6 474cfe5e98 fix: discover Login Flow v2 users in OAuth mode user manager
When enable_login_flow is true, also check the app_passwords table
for provisioned users. Previously, OAuth mode only queried the
refresh_tokens table, missing users who were provisioned via
Login Flow v2 (which stores app passwords, not refresh tokens).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 00:48:02 +02:00
Chris CoutinhoandClaude Opus 4.6 eefede8c47 fix: rewrite Login Flow v2 poll endpoint URL to use configured host
Nextcloud returns poll/login URLs using its internal hostname (e.g.
http://localhost/login/v2/poll) which is unreachable from the MCP
server container in Docker networks. Rewrite the poll endpoint's
origin to use the configured NEXTCLOUD_HOST so server-side polling
works correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:21:41 +02:00
Chris CoutinhoandClaude Opus 4.6 c2f23a566c fix: handle internal hostname without port in Login Flow v2 URL rewriting
Nextcloud may omit default ports in the login_url (e.g. http://app
instead of http://app:80). Extract just scheme+hostname from
NEXTCLOUD_HOST for the URL replacement check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:11:42 +02:00
Chris CoutinhoandClaude Opus 4.6 1a51f5bbf5 refactor: use redirect-based Login Flow v2 provision instead of popup
Replace the popup-based approach with a direct redirect to Nextcloud's
login page. This is more compatible with Playwright E2E tests and
simpler for users. The background polling task still runs server-side
to store the app password when the user grants access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:17:54 +02:00
Chris CoutinhoandClaude Opus 4.6 081ecbe401 feat: add web-based Login Flow v2 provisioning endpoint
Add /app/provision and /app/provision/status endpoints for browser-based
Login Flow v2 app password provisioning. Used by Astrolabe's "Enable
Semantic Search" to chain OAuth (bearer token) + Login Flow v2 (app
password) in a single user interaction.

The provision page initiates Login Flow v2, opens Nextcloud's login URL
in a popup, polls for completion via background task, and redirects back
to the caller's redirect_uri on success.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 21:56:16 +02:00
github-actions[bot] 2c5b4430b7 bump: version 0.58.17 → 0.58.18 2026-03-29 19:00:37 +00:00
github-actions[bot] 3e78510295 bump: version 0.66.2 → 0.67.0 2026-03-29 19:00:36 +00:00
Chris CoutinhoandGitHub d29408bacc Merge pull request #665 from cbcoutinho/feat/claude-funnel-config
feat: add Tailscale Funnel config for Claude AI connector testing
2026-03-29 21:00:16 +02:00
Chris CoutinhoandClaude Opus 4.6 b8dc1d7f52 feat: add Tailscale Funnel config for Claude AI connector testing
Add docker compose services (tailscale-mcp + nginx-claude-filter) behind
a claude-funnel profile that expose the login-flow MCP server via
Tailscale Funnel with IP-based access control:

- /mcp endpoint restricted to Claude AI outbound IPs (160.79.104.0/21)
- /oauth/*, /.well-known/*, /app paths open to all IPs (user login flow)
- All other paths return 404

Also add favicon.png served at /favicon.ico for connector directory
discovery (Google favicon service).

Usage:
  docker compose --profile login-flow --profile claude-funnel up -d

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 21:00:00 +02:00
github-actions[bot] 592fb8f5e2 bump: version 0.58.16 → 0.58.17 2026-03-29 18:58:13 +00:00
github-actions[bot] 39138ec117 bump: version 0.66.1 → 0.66.2 2026-03-29 18:58:12 +00:00
Chris CoutinhoandGitHub 8a501375bb Merge pull request #664 from cbcoutinho/fix/login-flow-oauth-compat
fix: resolve OAuth compatibility issues for login-flow deployment
2026-03-29 20:57:52 +02:00
Chris CoutinhoandClaude Opus 4.6 25788eecc7 fix: allow HTTPS redirect URIs for non-localhost OAuth clients
Relax redirect_uri validation to accept HTTPS for remote hosts (e.g.,
cloud-hosted MCP clients like Claude AI) while keeping HTTP allowed
for localhost per RFC 8252 loopback exception.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 19:03:25 +02:00
Chris CoutinhoandClaude Opus 4.6 f151eb10b3 fix: move Astrolabe OAuth hook to before-starting for reliable OIDC client creation
Move 26-configure-astrolabe-oauth.sh from post-installation (runs once
on first boot) to before-starting (runs on every start). This ensures
the Astrolabe OIDC client is created as soon as MCP_SERVER_URL is
available, even if it wasn't set during initial installation.

Also copy 25-configure-mcp-server-url.sh to before-starting so the
mcp_server_url config stays current across container recreations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 18:39:49 +02:00
Chris CoutinhoandClaude Opus 4.6 fe8799a133 fix: resolve OAuth compatibility issues for login-flow deployment
- Drop OIDC fork: comment out third_party/oidc mount, use upstream
  v1.16.3 from app store (fixes consent redirect race, PR #631)
- Support client_secret_basic auth: add _extract_basic_auth() helper
  so TS MCP SDK can authenticate at token endpoint (RFC 6749 §2.3.1)
- Multi-issuer JWT validation: accept tokens with internal Docker
  issuer (http://app:80) or public URL (NEXTCLOUD_PUBLIC_ISSUER_URL)
  since AS proxy obtains tokens server-to-server
- Introspection fallback: try token introspection when JWT verification
  fails, supporting both JWT and opaque token types
- Register all tool scopes in DCR: add semantic:read, collectives:read,
  collectives:write to OIDC client allowed_scopes so tokens include
  them and semantic search tools are visible to authenticated clients
- Auto-create Astrolabe OAuth client: new app-hook creates OIDC client
  and stores credentials in config.php so the "Authorize via OAuth"
  button works without manual setup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:05:26 +02:00
github-actions[bot] 3cf4c777ed bump: version 0.58.15 → 0.58.16 2026-03-28 14:59:22 +00:00
Chris CoutinhoandGitHub 78d3da6611 Merge pull request #662 from cbcoutinho/renovate/nextcloud-33-33.x
chore(deps): update nextcloud-33 docker tag to v33.0.1
2026-03-28 15:59:05 +01:00
renovate-bot-cbcoutinho[bot]andGitHub 4354ee7270 chore(deps): update nextcloud-33 docker tag to v33.0.1 2026-03-28 11:20:49 +00:00
github-actions[bot] bd81477295 bump: version 0.58.14 → 0.58.15 2026-03-28 09:53:31 +00:00
github-actions[bot] 1948360b83 bump: version 0.66.0 → 0.66.1 2026-03-28 09:53:31 +00:00
Chris CoutinhoandGitHub 89791a558b Merge pull request #657 from cbcoutinho/fix/renovate-nextcloud-version-pinning
fix: pin Renovate Nextcloud updates to matching major version
2026-03-28 10:53:11 +01:00
Chris CoutinhoandGitHub fd303dde36 Merge pull request #651 from cbcoutinho/renovate/docker.io-qdrant-qdrant-1.x
chore(deps): update docker.io/qdrant/qdrant docker tag to v1.17.1
2026-03-28 10:52:57 +01:00
github-actions[bot] 407203d020 bump: version 0.58.13 → 0.58.14 2026-03-28 09:52:52 +00:00
Chris CoutinhoandGitHub 8729b1dd1f Merge pull request #652 from cbcoutinho/renovate/qdrant-1.x
chore(deps): update helm release qdrant to v1.17.1
2026-03-28 10:52:37 +01:00
github-actions[bot] d5b9b2ed04 bump: version 0.58.12 → 0.58.13 2026-03-28 09:52:11 +00:00
Chris CoutinhoandGitHub a4d1e5f6a6 Merge pull request #654 from cbcoutinho/renovate/anthropics-claude-code-action-1.x
chore(deps): update anthropics/claude-code-action action to v1.0.81
2026-03-28 10:51:54 +01:00
Chris CoutinhoandClaude Opus 4.6 1482d2d43d fix: pin Renovate Nextcloud updates to matching major version
The custom regex manager matched all nextcloud_image entries with the
same depName, causing Renovate to bump all matrix entries (NC 31, 32, 33)
to the latest version instead of only the targeted major.

Fix by capturing nextcloud_version to create version-specific dep names
(nextcloud-31, nextcloud-32, nextcloud-33) with allowedVersions rules
constraining each to its own major. Also pins docker-compose.yml to 32.x
and removes redundant inline # renovate: comments that could cause
duplicate matching.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:48:55 +01:00
github-actions[bot] 19fab2a381 bump: version 0.58.11 → 0.58.12 2026-03-28 08:41:12 +00:00
github-actions[bot] 35abc4eaae bump: version 0.65.4 → 0.66.0 2026-03-28 08:41:11 +00:00
Chris CoutinhoandGitHub c56249dcc4 Merge pull request #647 from cbcoutinho/feature/collectives-support
feat: add Nextcloud Collectives app support
2026-03-28 09:40:50 +01:00
Chris CoutinhoandClaude Opus 4.6 52470ea713 fix: address PR review feedback (round 9)
- Fix emoji clearing bug: use _UNSET sentinel in update_collective so
  emoji=None sends {"emoji": null} instead of raising ValueError
- Move collectives_get_trashed_collectives to Read Tools section
- Remove redundant is_trash field from ListTrashedPagesResponse
- Add page lifecycle note to collectives_trash_page docstring
- Add unit test for clearing collective emoji via update_collective
- Add integration test for clearing collective emoji via MCP tool

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 09:19:53 +01:00
renovate-bot-cbcoutinho[bot]andGitHub 162bb5b7e4 chore(deps): update anthropics/claude-code-action action to v1.0.81 2026-03-27 23:20:33 +00:00
renovate-bot-cbcoutinho[bot]andGitHub 57c3bdcaba chore(deps): update helm release qdrant to v1.17.1 2026-03-27 15:36:33 +00:00
github-actions[bot] ecb0b8331a bump: version 0.58.10 → 0.58.11 2026-03-27 14:18:07 +00:00
github-actions[bot] 83e430dd66 bump: version 0.65.3 → 0.65.4 2026-03-27 14:18:07 +00:00
Chris CoutinhoandGitHub d6632e13b2 Merge pull request #649 from cbcoutinho/fix/pin-starlette-below-1.0
fix: pin starlette<1.0 to prevent startup crash
2026-03-27 15:17:44 +01:00
github-actions[bot] ff770d7d1b bump: version 0.58.9 → 0.58.10 2026-03-27 14:17:35 +00:00
Chris CoutinhoandGitHub d85ff8d2b3 Merge pull request #650 from cbcoutinho/renovate/anthropics-claude-code-action-1.x
chore(deps): update anthropics/claude-code-action action to v1.0.80
2026-03-27 15:17:15 +01:00
Chris CoutinhoandClaude Opus 4.6 cb16060b1b fix: address PR review feedback (round 8)
- Fix inconsistent error code in set_collective_emoji (400 → -32603)
- Allow clearing emoji via set_collective_emoji(emoji=None)
- Remove destructiveHint from trash operations (soft deletes are recoverable)
- Change delete_collective to idempotentHint=False (requires trash precondition)
- Add restore_collective and get_trashed_collectives tools
- Add unit tests for ValueError guard, clear-emoji path, and new tools
- Add integration test for full trash/restore/delete lifecycle
- Verify move_page returns new title in response message

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:26:26 +01:00
renovate-bot-cbcoutinho[bot]andGitHub 129a5b9125 chore(deps): update docker.io/qdrant/qdrant docker tag to v1.17.1 2026-03-26 23:19:50 +00:00
renovate-bot-cbcoutinho[bot]andGitHub 84fafa6a6b chore(deps): update anthropics/claude-code-action action to v1.0.80 2026-03-26 23:19:45 +00:00
Chris CoutinhoandClaude Opus 4.6 7224a2ebe3 fix: address PR review feedback (round 7) and fix CI
- Rename collectives_update_collective to collectives_set_collective_emoji
  (more precise since only emoji is settable)
- Use standard JSON-RPC error code -32603 (INTERNAL_ERROR) instead of -1
- Handle UnicodeDecodeError when reading page content via WebDAV
- Replace brittle 'Welcome' content assertion with length check

Fixes CI: test_update_operations_not_idempotent no longer matches the
renamed tool, which is correctly idempotent (no ETag involved).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 23:18:42 +01:00
Chris CoutinhoandClaude Opus 4.6 b6d01fc0bd fix: pin starlette<1.0 to prevent startup crash (#648)
Starlette 1.0.0 removed the @app.middleware() decorator, which breaks
nextcloud-mcp-server on fresh installs. Pin starlette<1.0 until we
address the full set of breaking changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 19:30:57 +01:00
Chris CoutinhoandClaude Opus 4.6 85119bde91 fix: address PR review feedback (round 6)
- Fix assign_tag sending Content-Type header with no body
- Mark collectives_update_collective as idempotent (no ETag involved)
- Raise OCSError when 'data' key missing instead of silent fallback
- Tighten color validator to 3 or 6 hex chars only
- Add comment explaining null emoji semantics in set_page_emoji

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 14:38:11 +01:00
Chris CoutinhoandClaude Opus 4.6 aa46c6147b fix: address PR review feedback (round 5)
- Validate OCS envelope in trash_collective, delete_collective, trash_page
- Guard _unwrap_ocs against non-OCS responses with informative OCSError
- Remove _get_ocs_headers() indirection, use class constants directly
- Split headers: _OCS_HEADERS (GET) vs _OCS_HEADERS_JSON (with body)
- Fix docstring claiming emoji param is required when it is optional
- Rename misleading test, add test for non-OCS envelope handling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:49:28 +01:00
Chris CoutinhoandClaude Opus 4.6 95edd9ba8e fix: add trash/delete collective tools and address review feedback (round 4)
Add collectives_trash_collective and collectives_delete_collective MCP
tools with proper destructiveHint annotations. Refactor integration test
fixture to use MCP tools for cleanup instead of direct httpx/OCS calls.
Optimize _get_ocs_headers() to class-level constant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:36:40 +01:00
github-actions[bot] 2be63a85e5 bump: version 0.58.8 → 0.58.9 2026-03-26 06:17:24 +00:00