Add explicit property type declarations to IdpTokenRefresher,
CredentialsController, OAuthController, and McpServerClient classes.
This improves type safety and allows Psalm to properly infer types,
eliminating MissingPropertyType and many MixedMethodCall errors.
Also adds IClient import where needed and validates getSystemValue
returns to ensure string types before use.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GitHub workflows should be defined only in the root .github directory,
not in the subproject directory.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Delete stored token when refresh callback fails or returns null
- Delete stored token when expired with no refresh callback available
- Fix test namespaces (Service → OCA\Astrolabe\Tests\Unit\Service)
- Update tests to verify token deletion on refresh failure
Prevents repeated refresh attempts with stale tokens that will never
succeed, improving error handling and reducing unnecessary API calls.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace NcCheckboxRadioSwitch :checked with :model-value
- Replace NcCheckboxRadioSwitch @update:checked with @update:model-value
- Replace NcButton type="primary|secondary|tertiary" with variant prop
- Bump @nextcloud/vue minimum version to ^9.3.3
These changes address deprecated APIs removed in @nextcloud/vue v9.0.0:
- :checked/:update:checked was replaced by v-model/modelValue pattern
- type prop for button variants was replaced by variant prop
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix PHP CS Fixer issues (single quotes, indentation)
- Add typed property declarations to ApiController
- Add Psalm baseline to suppress 517 pre-existing errors
- Fix workflow name references (astroglobe → astrolabe)
The CI workflow was previously watching a non-existent path and never
ran. After fixing the path trigger, these pre-existing code quality
issues were discovered. The Psalm baseline allows CI to pass while
tracking technical debt for incremental resolution.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The IdpTokenRefresher was incorrectly using overwrite.cli.url (the
external URL like http://localhost:8080) for internal token refresh
requests. This URL is not accessible from inside Docker containers
since port 8080 is only mapped on the host machine.
Changed getNextcloudBaseUrl() to:
- Always use http://localhost (internal port 80) by default
- Added optional astrolabe_internal_url config for custom setups
- Removed overwrite.cli.url usage (intended for external URLs only)
This fixes 401 errors in Astrolabe semantic search when OAuth tokens
need to be refreshed in containerized deployments.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add unit tests for /api/v1/status endpoint focusing on OIDC config:
- Test hybrid mode (multi_user_basic + enable_offline_access) returns OIDC
- Test pure multi_user_basic mode without offline_access omits OIDC
- Test OAuth mode returns OIDC config
- Test single-user BasicAuth mode omits OIDC config
- Test partial OIDC config (only discovery_url or only issuer)
Also updates docs/authentication.md with Astrolabe hybrid mode setup:
- Two-step credential setup (OAuth + app password)
- Technical details for each credential type
- Request direction table explaining why two credentials needed
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use :input-label prop for NcSelect field labels instead of :label
(the :label prop sets the option label property key, not the visible label)
- Fix CSS loading in admin.php and personal.php templates to use
astrolabe-main (the bundled CSS file)
- Update minimum Nextcloud version to 31 (required for Vue 3)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
In hybrid mode (multi_user_basic + offline_access), users need BOTH:
- OAuth token for Astrolabe→MCP API calls
- App password for MCP→Nextcloud background sync
Changes:
- Personal.php: Pass correct oauthUrl pointing to Astrolabe's OAuth
controller instead of MCP server's browser OAuth. Check both OAuth
token AND app password status in hybrid mode.
- personal.php template: Show two-step workflow UI requiring both
credentials before showing "Active" status. Each step shows
completion badges.
- IdpTokenRefresher.php: Use http://localhost for internal token
refresh requests (consistent with OAuthController). External URLs
like localhost:8080 don't work from inside the container.
Fixes 401 errors when searching in Astrolabe with hybrid deployment.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The /api/v1/status endpoint now returns OIDC configuration (discovery_url,
issuer) when running in hybrid mode (multi_user_basic + offline_access),
not just in pure OAuth mode.
This allows Astrolabe to discover the IdP and complete the OAuth flow
for obtaining tokens to call MCP server management APIs.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change limit initialization from string '20' to number 20 in App.vue
- Update AdminSettings.vue NcTextField to use v-model instead of legacy
:value/@update:value bindings
- Update AdminSettings.vue NcSelect components to use :model-value with
computed getters and @update:model-value for proper object-to-id
conversion (same pattern as App.vue)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The astrolabe app was using Vue 2 style bindings that don't work with
@nextcloud/vue 9.x and Vue 3:
- NcTextField: Changed from :value/@update:value to v-model
- NcSelect: Changed from v-model (with computed prop) to
:model-value/@update:model-value
The legacy :value and @update:value props were being ignored because
@nextcloud/vue 9.x components use modelValue/update:modelValue internally.
This caused the search button to remain disabled and the algorithm
dropdown to be unresponsive.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>