feat(astrolabe): replace PDF.js with server-side PyMuPDF rendering#501
Conversation
Plotly.js v3 removed string format for title attributes (plotly/plotly.js#7212). All titles must now use object format: { text: "..." } Changes: - Main layout title: string → { text: "..." } - Scene axis titles (xaxis, yaxis, zaxis): string → { text: "..." } - Colorbar title: string → { text: "..." } Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add dbquery.py for MariaDB and sqlitequery.py for SQLite databases in MCP service containers. Both scripts wrap docker compose exec to simplify database inspection during development. - dbquery.py: Query Nextcloud MariaDB with vertical/JSON output - sqlitequery.py: Query MCP service SQLite DBs with service aliases (mcp, oauth, keycloak, basic) and column/JSON output modes - Document both scripts in CLAUDE.md Database Inspection section Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace Close button click with Escape key in app password dialog (h2 element was intercepting pointer events) - Make test_users_setup fixture idempotent by checking user existence before creation and only tracking created users for cleanup - Fix search results detection by removing wait for .app-content-wrapper CSS class that doesn't exist in Astrolabe's Vue app - Add progress logging during results polling - Increase polling timeout to 30 seconds for search results Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename OAuthController.php to OauthController.php for consistency - Fix Personal.php to check specifically for app password presence using getBackgroundSyncPassword() instead of hasBackgroundSyncAccess() for hybrid auth mode Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace generic "Network error" with specific error messages: - Show backend error message when available from HTTP response - Display "Authorization required. Please complete Step 1 in Settings → Astrolabe." for 401 Unauthorized errors - Show "Search service unavailable" for 503 errors - Keep generic network error only for actual connection failures This helps users understand when they need to complete OAuth authorization vs when there's an actual network problem. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When viewing PDF chunks in semantic search, the PDF viewer failed with "can't access private field" errors. This was caused by: 1. CSP blocks web workers (worker-src 'none'), forcing fake worker mode 2. Vite transforms ES private fields in the bundle, but the worker file is untransformed, causing incompatible private field implementations 3. Vue's ref() wraps PDFDocumentProxy in a Proxy, which can't access ES private fields Fixed by: - Loading pdfjs-dist externally via script tag (avoids Vite transform) - Creating pdfjs-loader.mjs that imports pdf.mjs and sets window.pdfjsLib - Using Util::addScript() for CSP-compliant script loading with nonces - Using shallowRef() instead of ref() for pdfDoc to avoid Proxy wrapper - Setting workerSrc at runtime using OC.linkTo() for correct app path Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update psalm-baseline.xml to match renamed OauthController.php (lowercase 'a') - Move AlertCircle import to top of PDFViewer.vue to satisfy ESLint import/first rule Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…PDF rendering Replace the client-side PDF.js viewer with server-side rendering using PyMuPDF. This avoids CSP worker restrictions and ES private field access issues that affected Chromium browsers. Changes: - Add /api/v1/pdf-preview endpoint to MCP server (management.py) - Add pdf-preview route and controller action in Astrolabe PHP backend - Refactor PDFViewer.vue to display server-rendered PNG images - Remove pdfjs-dist dependency and client-side PDF loading code - Use @nextcloud/axios for CSRF token handling in PDFViewer The server downloads the PDF via WebDAV, renders the requested page with PyMuPDF at the specified scale, and returns a base64-encoded PNG image. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix Psalm static analysis errors: - Add return type annotations to refresh callback closures - Use strict null comparisons instead of truthy/falsy checks - Cast response body to string for json_decode - Add type annotation for decoded JSON data - Update psalm-baseline.xml to remove fixed issues Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive unit tests for the /api/v1/pdf-preview endpoint: - Parameter validation (file_path, page, scale) - OAuth token authentication - PDF rendering with PyMuPDF - Error handling (file not found, invalid page, corrupted PDF) - Edge cases (URL-encoded paths, boundary values, missing config) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add allowed_bots configuration for renovate-bot-cbcoutinho to enable Claude Code review on dependency update PRs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review for PR #501: Server-side PDF Rendering with PyMuPDFSummaryThis PR successfully replaces client-side PDF.js rendering with server-side PyMuPDF rendering to address CSP worker restrictions and ES private field access issues in Chromium browsers. The implementation is well-structured and follows the project's architectural patterns. ✅ StrengthsArchitecture & Design
Code Quality
Implementation Details
🔍 Issues & Concerns1. Resource Management - Memory Safety
|
…viz preview endpoints
Split the monolithic management.py (1988 lines) into 4 focused modules: - management.py: Server status, user sessions, shared helpers (~520 lines) - passwords.py: App password provisioning for BasicAuth mode (~300 lines) - webhooks.py: Webhook registration management (~290 lines) - visualization.py: Search and PDF preview endpoints (~810 lines) Backward compatibility maintained via __init__.py re-exports. Updated test imports to use new module paths. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review - PR #501: Replace PDF.js with Server-Side PyMuPDF RenderingThis is a well-executed architectural change that solves real browser compatibility issues. The implementation is solid, but I have some suggestions for improvement. ✅ Strengths1. Excellent Problem-Solution Alignment
2. Comprehensive Testing
3. Good Code Organization
4. Security Considerations
🔧 Issues & Recommendations1. Security: Path Traversal Validation is Insufficient
|
| Category | Rating | Comments |
|---|---|---|
| Architecture | ⭐⭐⭐⭐⭐ | Excellent separation of concerns, solves real problems |
| Security | ⭐⭐⭐ | Path traversal check is weak, no rate limiting |
| Testing | ⭐⭐⭐⭐ | Comprehensive unit tests, missing integration tests |
| Code Quality | ⭐⭐⭐⭐ | Clean code, good type annotations, follows conventions |
| Performance | ⭐⭐⭐ | No caching, no rate limiting, excessive logging |
✅ Approval Recommendation
Approve with minor changes. The core implementation is solid and solves a real problem. The security and performance issues should be addressed before merge:
Critical (must fix):
- Strengthen path traversal validation (Issue Test on PRs to master #1)
- Add rate limiting (Issue Clean up ci #2)
Recommended (should fix):
3. Improve error handling in PHP controller (Issue #3)
4. Reduce logging verbosity (Issue #6)
Nice to have:
5. Add page rendering cache (Issue #5)
6. Add integration tests (Issue #7)
7. Update documentation (Issue #9)
Great work overall! The shift to server-side rendering is the right architectural choice, and the implementation demonstrates good engineering practices. 🚀
Summary
Replace client-side PDF.js with server-side PyMuPDF rendering for the Astrolabe PDF chunk viewer. This addresses CSP worker restrictions and ES private field access issues that affected Chromium browsers.
Changes
Backend (Python MCP Server)
/api/v1/pdf-previewendpoint that renders PDF pages to PNG using PyMuPDFBackend (PHP Astrolabe App)
pdfPreviewcontroller action with OAuth token handlinggetPdfPreviewservice method to call MCP server/api/pdf-previewFrontend (Vue)
PDFViewer.vueto display server-rendered PNG images@nextcloud/axiosfor CSRF token handlingpdfjs-distdependency entirelyTests
Why server-side rendering?
PDF.js has issues in Nextcloud's environment:
Server-side rendering with PyMuPDF:
Testing
Supersedes #441 (original plotly.js update branch)
This PR was generated with the help of AI, and reviewed by a Human