Commit Graph

1453 Commits

Author SHA1 Message Date
Chris Coutinho 65c3f099fa feat(astrolabe): implement app password provisioning for multi-user background sync
Adds complete app password provisioning workflow for multi-user BasicAuth
deployments, allowing users to independently enable background sync by
generating and storing Nextcloud app passwords.

**New Components:**

Backend (PHP):
- CredentialsController: Validates and stores app passwords
  * Validates app password format and authenticity via OCS API
  * Stores encrypted passwords in oc_preferences
  * Provides status and credential management endpoints
- AstrolabeAdminSettings: Admin configuration page for MCP server URL
- AstrolabeAdminSettingsListener: Event listener for admin section
- Updated McpTokenStorage: Added background sync credential methods

Frontend:
- personalSettings.js: Form handling for app password entry
  * AJAX submission with error handling
  * Shows success/error notifications
  * Triggers page reload after successful save
- settings.css: Styling for settings pages
- Updated personal.php template: Two-option UI
  * Option 1: OAuth refresh token (future, not yet available)
  * Option 2: App password (works today, recommended)
  * Shows "Active" badge when provisioned
  * Displays credential type and provisioned timestamp

Routes:
- POST /api/v1/background-sync/credentials - Store app password
- GET /api/v1/background-sync/status - Get provisioning status
- DELETE /api/v1/background-sync/credentials - Revoke credentials
- GET /api/v1/background-sync/credentials/{userId} - Admin only

**Testing:**
- test_astrolabe_settings_buttons.py: Integration test for UI buttons

**Workflow:**
1. User generates app password in Nextcloud Security settings
2. User navigates to Astrolabe personal settings
3. User enters app password in "Option 2: App Password" form
4. Backend validates password via OCS API call
5. Password stored encrypted in oc_preferences
6. Page reloads showing "Active" badge with credential details
7. MCP server can now use stored password for background operations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 19:39:13 +01:00
Chris Coutinho b293258210 test(astrolabe): fix app password extraction in multi-user background sync test
Fixes the Playwright-based integration test that verifies multi-user app
password provisioning for background sync in Astrolabe.

**Root Cause:**
The test was failing to extract the generated app password from Nextcloud's
"New app password" dialog due to overly specific CSS selectors that didn't
match the actual DOM structure.

**Changes:**
- Enhanced network response logging to capture HTTP status codes
- Simplified app password extraction logic:
  * Wait for dialog heading using text selector
  * Iterate through ALL text inputs on page
  * Find password by pattern: contains dashes and length > 20
  * Validate extracted password against expected format
- Added format validation with regex before returning password
- Added detailed debug logging for each extraction step
- Improved error messages with screenshot paths

**Testing:**
Test now successfully completes for both alice and bob test users:
- Logs in to Nextcloud
- Generates app password in Security settings
- Extracts password from dialog
- Navigates to Astrolabe settings
- Enters and saves app password
- Verifies "Active" badge appears
- Confirms credentials stored in database

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 19:32:06 +01:00
Chris Coutinho 1a5bb10cd0 feat(config): consolidate configuration with smart dependency resolution (ADR-021)
Simplifies configuration by consolidating overlapping settings and adding
automatic dependency resolution. This makes semantic search configuration
significantly easier for users while maintaining 100% backward compatibility.

## Key Changes

### Variable Renaming (Backward Compatible)
- `VECTOR_SYNC_ENABLED` → `ENABLE_SEMANTIC_SEARCH` (old name still works)
- `ENABLE_OFFLINE_ACCESS` → `ENABLE_BACKGROUND_OPERATIONS` (old name still works)
- Deprecation warnings logged when old names used
- Old names will be removed in v1.0.0

### Smart Dependency Resolution
- `ENABLE_SEMANTIC_SEARCH` automatically enables background operations in multi-user modes
- No need to set both `ENABLE_OFFLINE_ACCESS` and `VECTOR_SYNC_ENABLED` anymore
- Single-user mode doesn't auto-enable background ops (not needed)

### Explicit Mode Selection (Optional)
- New `MCP_DEPLOYMENT_MODE` environment variable
- Valid values: single_user_basic, multi_user_basic, oauth_single_audience,
  oauth_token_exchange, smithery
- Removes ambiguity about which deployment mode is active
- Falls back to auto-detection if not set (existing behavior)

### Configuration Templates
- Reorganized `env.sample` by deployment mode with clear sections
- Added mode-specific quick-start templates:
  - `env.sample.single-user` - Simplest configuration
  - `env.sample.oauth-multi-user` - Recommended multi-user
  - `env.sample.oauth-advanced` - Token exchange mode

## Implementation Details

### Files Modified
- `nextcloud_mcp_server/config.py` - Smart dependency resolution helpers
- `nextcloud_mcp_server/config_validators.py` - Simplified validation, explicit mode
- `tests/unit/test_config_validators.py` - 19 new tests (60 total, all passing)
- `env.sample` - Reorganized by deployment mode
- `docs/configuration.md` - Complete rewrite with consolidated approach
- `docs/troubleshooting.md` - New consolidation troubleshooting section
- `README.md` - Updated variable references

### New Files
- `docs/ADR-021-configuration-consolidation.md` - Architecture decision record
- `docs/configuration-migration-v2.md` - Comprehensive migration guide
- `env.sample.single-user` - Single-user quick-start template
- `env.sample.oauth-multi-user` - OAuth multi-user quick-start template
- `env.sample.oauth-advanced` - Token exchange quick-start template

## User Impact

### Before (Confusing)
```bash
ENABLE_OFFLINE_ACCESS=true      # Why both?
VECTOR_SYNC_ENABLED=true        # What's the relationship?
```

### After (Simplified)
```bash
MCP_DEPLOYMENT_MODE=oauth_single_audience  # Explicit (optional)
ENABLE_SEMANTIC_SEARCH=true                # Auto-enables background ops!
```

### Benefits
- 📉 2 fewer variables to understand for semantic search
- 📋 Clear intent ("I want semantic search")
- 🎯 Explicit mode declaration available
- 🔄 100% backward compatible
-  All 265 unit tests passing

## Testing
- All 60 config validation tests passing
- 10 new tests for configuration consolidation
- 9 new tests for explicit mode selection
- Full unit test suite: 265 tests passing
- Backward compatibility verified

## Migration
Users can migrate at their own pace. Old variable names continue working
with deprecation warnings. See docs/configuration-migration-v2.md for
detailed migration instructions.

Related: ADR-021

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 20:36:36 +01:00
github-actions[bot] 34273ec01e bump: version 0.4.4 → 0.5.0 astrolabe-v0.5.0 2025-12-20 20:42:30 +00:00
github-actions[bot] fd7f33943d bump: version 0.56.2 → 0.57.0 v0.57.0 2025-12-20 20:42:29 +00:00
Chris Coutinho ecaa1f8f01 Merge pull request #443 from cbcoutinho/feature/multi-user-deployment
refactor(config): centralize configuration validation and add dynamic Astrolabe testing
2025-12-20 21:42:10 +01:00
Chris Coutinho 981f102b27 fix(config): address reviewer feedback
- Restore CI test filter (-m unit -m smoke) for faster CI runs
- Replace local path reference with ADR-020 reference in config_validators.py
- Add comprehensive BasicAuthMiddleware unit tests (10 tests covering all edge cases)

Addresses critical CI issue and improves test coverage for multi-user BasicAuth mode.
2025-12-20 21:16:17 +01:00
Chris Coutinho 94febf1602 ci(test): build Astrolabe app before running tests
Add build step for Astrolabe app in CI workflow to compile frontend
assets before docker-compose starts.

Changes:
- Install Node.js 20 for Astrolabe build
- Run composer install --no-dev for Astrolabe PHP dependencies
- Run npm ci and npm run build to compile frontend assets

This ensures the Astrolabe app is properly built in CI, similar to
the existing OIDC app build process.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 21:11:28 +01:00
Chris Coutinho 286a3eb20f feat(auth): add multi-user BasicAuth pass-through mode
Implement multi-user BasicAuth pass-through mode (ADR-020) where each
request includes BasicAuth credentials that are forwarded to Nextcloud
APIs without persistent storage.

Changes:
- Add _get_client_from_basic_auth() in context.py to extract credentials
  from Authorization header (set by BasicAuthMiddleware)
- Add AstrolabeClient for app password provisioning via Astrolabe API
- Update oauth_sync.py with dual credential support (app passwords first,
  then refresh tokens as fallback)
- Simplify oauth_tools.py provisioning logic
- Add integration tests for app password provisioning and multi-user BasicAuth

Features:
- Stateless multi-user mode: credentials passed per-request
- Optional background sync via app passwords (stored in Astrolabe)
- Falls back to refresh tokens if app password not available
- Test coverage for provisioning flow and pass-through mode

Related: ADR-019 (Multi-user BasicAuth), ADR-020 (Deployment Modes)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 20:55:31 +01:00
Chris Coutinho 19b209f412 test: Enable all tests 2025-12-20 20:53:02 +01:00
Chris Coutinho cd7ba5685a feat(astrolabe): add dynamic MCP server configuration for testing
Replace static post-installation configuration with dynamic test-time
configuration to support testing multiple MCP server deployments.

Changes:
- Remove static MCP server URL and OAuth client setup from post-installation
- Add configure_astrolabe_for_mcp_server fixture (session-scoped)
- Fixture dynamically configures:
  * Nextcloud system config (mcp_server_url, mcp_server_public_url)
  * OAuth client creation via occ oidc:create
  * Client credential storage (astrolabe_client_id, astrolabe_client_secret)
- Update existing OAuth tests to use dynamic configuration
- Add test_astrolabe_multi_server_integration.py with parametrized tests

Benefits:
- Test Astrolabe with mcp-oauth, mcp-keycloak, mcp-multi-user-basic
- Each test configures for its specific MCP server
- No static configuration conflicts between deployments
- Cleaner post-installation (37 lines, down from 85)

Test Results:
- test_astrolabe_configuration_for_different_servers: PASSED (mcp-oauth, mcp-keycloak)
- test_astrolabe_reconfiguration: PASSED

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 20:49:53 +01:00
Chris Coutinho 4507359760 refactor(config): centralize configuration validation and simplify startup
Implement centralized configuration validation (ADR-020) to simplify
deployment mode detection and improve error messages.

Changes:
- Create ADR-020 documenting 5 deployment modes with required/optional config
- Add config_validators.py with validate_configuration() and mode detection
- Simplify app.py startup with single validation point at get_app()
- Remove duplicate is_oauth_mode() function (43 lines)
- Fix DeploymentMode mapping (only SELF_HOSTED and SMITHERY_STATELESS exist)
- Add comprehensive unit tests (41 tests covering all modes and edge cases)
- Add enable_multi_user_basic_auth to Settings and BasicAuthMiddleware

Docker Compose:
- Remove conflicting ENABLE_MULTI_USER_BASIC_AUTH from mcp-oauth service
- Add dedicated mcp-multi-user-basic service on port 8003

Test Results:
- 237/237 integration tests PASSED
- All deployment modes verified: single-user BasicAuth, multi-user BasicAuth,
  OAuth single-audience, OAuth token exchange (Keycloak), Smithery stateless

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 20:49:28 +01:00
Chris Coutinho 8682fa4f88 ci: Handle NO_COMMITS_TO_BUMP gracefully in bump scripts
When commitizen finds no eligible commits to bump, it exits with
code 1 and outputs [NO_COMMITS_TO_BUMP]. This was causing the
GitHub Actions workflow to fail even though this is an expected
scenario.

Updated all three bump scripts (bump-mcp.sh, bump-helm.sh,
bump-astrolabe.sh) to:
- Detect the [NO_COMMITS_TO_BUMP] message
- Exit with code 0 (success) instead of code 1
- Output an informational message instead of an error

This allows the bump-version workflow to complete successfully
when no version bumps are needed, matching the workflow's existing
logic that handles empty BUMPED_COMPONENTS.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 13:17:50 +01:00
Chris Coutinho 53b84200d4 ci: Gracefully exit on no commit bump 2025-12-20 13:11:11 +01:00
Chris Coutinho f5e5965864 Merge pull request #421 from cbcoutinho/renovate/nextcloud-openapi-extractor-1.x
chore(deps): update dependency nextcloud/openapi-extractor to v1.8.7
2025-12-20 13:01:09 +01:00
Chris Coutinho 989c3d7541 Merge pull request #420 from cbcoutinho/renovate/icewind1991-nextcloud-version-matrix-digest
chore(deps): update icewind1991/nextcloud-version-matrix digest to c2bf575
2025-12-20 13:00:39 +01:00
Chris Coutinho 4bda647271 Merge pull request #422 from cbcoutinho/renovate/peter-evans-create-pull-request-7.x
chore(deps): update peter-evans/create-pull-request action to v7.0.11
2025-12-20 13:00:02 +01:00
Chris Coutinho 32f3380205 Merge pull request #419 from cbcoutinho/renovate/pin-dependencies
chore(deps): pin dependencies
2025-12-20 12:59:55 +01:00
renovate-bot-cbcoutinho[bot] 0d6b8a935d chore(deps): update peter-evans/create-pull-request action to v7.0.11 2025-12-20 11:12:56 +00:00
renovate-bot-cbcoutinho[bot] eece9ebadc chore(deps): update dependency nextcloud/openapi-extractor to v1.8.7 2025-12-20 11:12:49 +00:00
renovate-bot-cbcoutinho[bot] c390378278 chore(deps): update icewind1991/nextcloud-version-matrix digest to c2bf575 2025-12-20 11:12:35 +00:00
renovate-bot-cbcoutinho[bot] bd424a1ab7 chore(deps): pin dependencies 2025-12-20 11:12:17 +00:00
github-actions[bot] f8734b3edd bump: version 0.56.1 → 0.56.2 v0.56.2 2025-12-20 00:13:59 +00:00
Chris Coutinho 0ea7145df1 Merge pull request #407 from cbcoutinho/renovate/docker-setup-buildx-action-digest
chore(deps): update docker/setup-buildx-action digest to 8d2750c
2025-12-20 01:13:40 +01:00
github-actions[bot] f7a3d2d8f5 bump: version 0.4.3 → 0.4.4 astrolabe-v0.4.4 2025-12-20 00:04:37 +00:00
Chris Coutinho 18298177f7 fix(astrolabe): screenshots in info.xml 2025-12-20 01:04:20 +01:00
github-actions[bot] d9fa81082a bump: version 0.4.2 → 0.4.3 astrolabe-v0.4.3 2025-12-19 23:58:57 +00:00
Chris Coutinho 651b73545d fix(astrolabe): screenshots in info.xml 2025-12-20 00:58:40 +01:00
github-actions[bot] 46505210cd bump: version 0.4.1 → 0.4.2 astrolabe-v0.4.2 2025-12-19 23:52:44 +00:00
github-actions[bot] abf051afdb bump: version 0.56.0 → 0.56.1 v0.56.1 2025-12-19 23:52:44 +00:00
Chris Coutinho d4d1a332fb fix(astrolabe): Update screenshots 2025-12-20 00:52:21 +01:00
Chris Coutinho a3ed321e14 fix(ci): skip existing Helm chart releases to prevent duplicate release errors
The chart-releaser workflow was failing when the Helm chart version hadn't
changed but the MCP server version was bumped. Added skip_existing: true to
gracefully handle this scenario.
2025-12-19 22:41:04 +01:00
Chris Coutinho 2bb738ed3f bump: version 0.4.0 → 0.4.1 astrolabe-v0.4.1 2025-12-19 22:31:29 +01:00
Chris Coutinho 10c8b62818 bump: version 0.3.2 → 0.4.0 2025-12-19 22:30:46 +01:00
github-actions[bot] 87abadbbfc bump: version 0.55.1 → 0.56.0 v0.56.0 2025-12-19 21:29:13 +00:00
Chris Coutinho defc55a5dc feat(ci): add --increment flag to bump scripts for manual version control
Allows forcing specific version bumps (PATCH|MINOR|MAJOR) instead of
relying solely on commitizen's automatic detection based on conventional
commits.

Usage:
  ./scripts/bump-mcp.sh --increment MINOR
  ./scripts/bump-helm.sh --increment PATCH
  ./scripts/bump-astrolabe.sh --increment MAJOR
2025-12-19 22:28:43 +01:00
github-actions[bot] 6a68e45e7c bump: version 0.3.1 → 0.3.2 astrolabe-v0.3.2 astrolabe-v0.3.3 2025-12-19 21:12:28 +00:00
Chris Coutinho a2fa4b2832 fix(astrolabe): add contents:write permission to appstore workflow
The workflow was failing to create GitHub releases with 'Not Found' error
because it lacked the required permissions. Added contents:write permission
to allow creating releases and uploading artifacts.
2025-12-19 22:12:06 +01:00
github-actions[bot] 9cfadbfc04 bump: version 0.3.0 → 0.3.1 astrolabe-v0.3.1 2025-12-19 21:04:50 +00:00
Chris Coutinho 6fed78196e fix(astrolabe): update commitizen pattern to properly update info.xml version
The pattern 'version' was too broad and matched multiple lines:
- <?xml version="1.0"?>
- <version>0.2.1</version>
- min-version="30" max-version="32"

Changed to '<version>' to specifically match only the version tag.

Also fixed version mismatch: info.xml now correctly shows 0.3.0 to match
the version in .cz.toml and package.json.
2025-12-19 22:04:26 +01:00
github-actions[bot] db430dd2c9 bump: version 0.2.0 → 0.3.0 2025-12-19 20:55:59 +00:00
Chris Coutinho 3618aed39e fix(astrolabe): prevent workflow failure when only helm/astrolabe commits exist
When filtering commits with grep -v, if all commits are filtered out,
grep returns exit code 1 which causes the pipeline to fail with set -e.

Wrap grep commands in { ... || true; } to ensure they don't fail the
pipeline when they filter out all results.

This fixes the workflow failure when a fix(astrolabe): commit is pushed
without any MCP server changes.
2025-12-19 21:55:36 +01:00
Chris Coutinho 4c083c7314 fix(astrolabe): info.xml 2025-12-19 21:48:27 +01:00
github-actions[bot] 3202640cf7 bump: version 0.55.0 → 0.55.1 v0.55.1 2025-12-19 20:45:55 +00:00
Chris Coutinho c9bbe71869 fix(ci): push all tags explicitly in bump workflow
The --follow-tags flag only pushes annotated tags by default.
Commitizen creates lightweight tags, so we need to explicitly push
all tags with --tags to ensure version tags are pushed to trigger
release workflows.
2025-12-19 21:45:06 +01:00
github-actions[bot] 00edb273cd bump: version 0.54.0 → 0.55.0 v0.55.0 2025-12-19 20:35:20 +00:00
Chris Coutinho 608b3282dd fix(ci): make MCP server default bump target for all non-scoped commits
BREAKING CHANGE: MCP server now bumps for ANY conventional commit except
those explicitly scoped to helm or astrolabe.

Previous behavior:
- MCP bumped only for unscoped or scope=mcp commits
- fix(ci): commits were ignored → no version bump

New behavior:
- MCP bumps for ALL commits except scope=helm or scope=astrolabe
- fix(ci): commits now trigger MCP version bump ✓
- feat(api): commits now trigger MCP version bump ✓
- Any custom scope triggers MCP version bump ✓

This treats the MCP server as the default/primary component in the
monorepo, with Helm chart and Astrolabe as opt-in specialized components.

Changes:
1. Updated bump-version.yml workflow logic to exclude helm/astrolabe
   instead of only including mcp/unscoped
2. Updated pyproject.toml commitizen patterns to use negative lookahead:
   (?!\((?:helm|astrolabe)\))
3. Fixed docker-build-publish.yml to only trigger on v* tags (MCP only)
4. Fixed appstore-build-publish.yml action version (v1.0.4)
5. Updated test script to use grep -P for PCRE support
6. Added test cases for ci, api, and custom scopes

All 19 scope filtering tests now pass.
2025-12-19 21:34:49 +01:00
Chris Coutinho 2888bd5693 fix(ci): restrict docker build to MCP server tags only
Docker images should only be built for MCP server releases (v* tags),
not for Helm chart (nextcloud-mcp-server-*) or Astrolabe (astrolabe-v*)
releases.

Changed trigger from all tags to v* pattern only.
2025-12-19 20:48:55 +01:00
Chris Coutinho 90d95da48d fix(ci): correct appstore-push-action version to v1.0.4
The latest available version is v1.0.4, not v1.0.6. This was causing
the Astrolabe app store deployment workflow to fail.
2025-12-19 20:48:28 +01:00
Chris Coutinho 31fb52761e bump: version 0.53.0 → 0.54.0 nextcloud-mcp-server-0.54.0 2025-12-19 20:46:11 +01:00