← Reports

Auth Portal & Cloud File Search

Technical Report — 8 April 2026 | Prepared by Luci

1. Auth Portal — How It Works

Overview

The Auth Portal is a Flask web app running on Luci (Hetzner) at http://100.118.207.3:8788, accessible via Tailscale. It manages OAuth tokens for four cloud services so Elmar can re-authenticate from his phone or laptop without terminal access.

1.1 Services & Auth Flows

ServiceAuth FlowToken FileStatus
M365 (Safair) Device Code Flow ~/.graph-api-token.json Active
Google Workspace OAuth2 Authorization Code ~/.config/gws/credentials.json Active
Personal OneDrive Device Code Flow ~/.graph-api-token-personal.json Needs Auth
Dropbox OAuth2 Code (no redirect) ~/.dropbox-api-token.json Just Authenticated

1.2 Auth Flow Details

M365 & Personal OneDrive — Device Code Flow
  1. Portal calls /oauth2/v2.0/devicecode to get a user code + verification URL
  2. User sees the code in the portal UI and clicks the link to microsoft.com/devicelogin
  3. Background thread polls /oauth2/v2.0/token every 5s until user completes sign-in
  4. On success, saves access_token + refresh_token + expires_on to the token JSON file
  5. Auto-refresh: when the token expires, graph_api.py or the auth portal calls the refresh endpoint automatically

M365 Safair uses tenant-specific authority (/common as of today). Personal OneDrive uses /consumers authority with Files.ReadWrite.All scope only.

Google Workspace — Authorization Code Flow
  1. Portal generates a consent URL with all required scopes (Gmail, Calendar, Drive, etc.)
  2. User clicks the link, signs into Google, grants consent
  3. Google redirects to http://localhost:1 with an auth code in the URL
  4. User copies the full redirect URL back to the portal
  5. Portal extracts the code, exchanges it for tokens via oauth2.googleapis.com/token
  6. Saves tokens to ~/.config/gws/credentials.json
Dropbox — OAuth2 Code Flow (No Redirect)
  1. Portal generates an auth URL pointing to dropbox.com/oauth2/authorize with token_access_type=offline
  2. No redirect URI — Dropbox shows the auth code directly on screen
  3. User copies the code and pastes it into the portal
  4. Portal exchanges the code for tokens via api.dropboxapi.com/oauth2/token using Basic auth (app key:secret)
  5. Saves access_token + refresh_token to ~/.dropbox-api-token.json
  6. Auto-refresh via _dbx_refresh_token() when access token expires

1.3 Health Monitoring

The portal exposes GET /api/status which returns health for all four services. Each service's health check:

A scheduled health check (oauth_health_check.py) runs periodically and writes status to ~/workspace/data/oauth-health-status.json.

1.4 Architecture Diagram

Elmar (phone/laptop) │ ▼ Tailscale (100.118.207.3:8788) ┌─────────────────────────────────┐ │ Auth Portal (Flask) │ │ │ │ Cards: M365 │ GWS │ OneDrive │ │ │ │ Dropbox │ │ │ │ /api/status → health checks │ │ /auth/* → OAuth flows │ │ /api/m365/* → device code flow │ └──────────┬───────────────────────┘ │ Tokens saved to disk: ~/.graph-api-token.json (M365 Safair) ~/.graph-api-token-personal.json (Personal OneDrive) ~/.config/gws/credentials.json (Google) ~/.dropbox-api-token.json (Dropbox) │ ▼ Used by: graph_api.py, search_all.py, gws CLI, Dropbox API

2. Cloud File Search — What We Have

2.1 Search Tools on Luci (Server)

search_all.py — Unified Cloud Search

Searches all four cloud drives in parallel via their respective APIs:

DriveAPI UsedCapabilities
M365 Work OneDrive MS Search API (/search/query) Full-text content search, ranked results, content snippets
Personal OneDrive Graph API (/me/drive/search) Filename + content search
Google Drive Drive API v3 (fullText contains) Full-text content search inside docs, PDFs, etc.
Dropbox Dropbox API (/2/files/search_v2) Filename + content search with match highlights
python ~/workspace/scripts/search_all.py "fleet plan"
python ~/workspace/scripts/search_all.py "FICA" --drive onedrive_work
python ~/workspace/scripts/search_all.py "budget" --top 10 --json

2.2 Search Tools on Local Machine (Lucienne)

file-search skill — Local File Catalog + Gety.ai

Three search modes available locally:

ModeWhat It SearchesHow
Gety.ai (MCP) Inside file content (semantic + full-text) mcp__gety__Search — searches PDFs, DOCX, PPTX, images via OCR
Catalog (CLI) Filenames + paths across all drives search_files.py — 121K+ files indexed, keyword + LanceDB semantic
Google Drive API Inside Google Drive files --gdrive-content flag on catalog search

2.3 Capability Comparison

Luci (Server)
  • Has API-based cloud search (all 4 drives)
  • Has Auth portal for token management
  • Has Parallel multi-drive search
  • Missing Gety.ai (local-only MCP)
  • Missing Local file catalog (121K files)
  • Missing LanceDB semantic search
  • Missing Direct filesystem access to files
Lucienne (Local Mac)
  • Has Gety.ai semantic/content search
  • Has File catalog (121K+ files)
  • Has LanceDB vector search
  • Has Direct filesystem access
  • Has Google Drive API search
  • Partial M365 search (via m365 CLI, not search_all.py)
  • Missing Dropbox API search
  • Missing Personal OneDrive API search
  • Missing Unified multi-drive API search

3. What We Did Today (MC-393)

Changes Made
  1. Added Dropbox OAuth to auth_portal.py — New card in the portal UI, OAuth2 code flow without redirect URI (Dropbox shows code directly on screen), token refresh support, health check integration
  2. Added Personal OneDrive to auth_portal.py — Device code flow using /consumers authority, separate token file (~/.graph-api-token-personal.json), auto-refresh support
  3. Created search_all.py — Unified cloud file search that queries all four drives in parallel via their APIs and merges/deduplicates results
  4. Fixed Dropbox OAuth redirect issue — Removed redirect_uri=http://localhost:1 parameter (wasn't registered in the Dropbox app), switched to no-redirect flow
  5. Authenticated Dropbox — Successfully authenticated with Elmar's Dropbox account
Still Pending

4. Improvement Opportunities

4.1 The Gap: Luci Has APIs, Lucienne Has RAG

Core insight: On Elmar's local Mac, Gety.ai provides semantic/RAG search inside documents. Luci can't run Gety (it's a desktop app with MCP). But Luci now has all four cloud APIs authenticated. The local machine has Gety + file catalog but lacks the unified API search and Dropbox/Personal OneDrive API access.

4.2 Recommended Improvements

#ImprovementWhereImpact
1 Deploy search_all.py on local machine — give Lucienne the same unified cloud API search that Luci has Local Mac High
2 Add search_all.py to file-search skill — integrate as a 4th search mode alongside Gety, Catalog, and GDrive content search Skill High
3 Add Dropbox & Personal OneDrive tokens on local — copy auth_portal.py or just the token files so Lucienne can search these drives too Local Mac Medium
4 PKA Dashboard integration — add a "Cloud Search" widget to the PKA dashboard that calls search_all.py and displays results Dashboard Medium
5 Search as MCP tool on Luci — expose search_all.py as an MCP tool so any Claude instance can call it remotely, not just Luci Luci MCP Future
6 Content extraction — after finding a file via API search, add ability to download + extract content (currently search_all.py only returns metadata/snippets) Both Future

4.3 Gety.ai vs API Search — When to Use What

ScenarioBest ToolWhy
"Find a PDF that mentions FICA on page 3" Gety.ai (local only) Semantic search inside document content, OCR for scanned docs
"Find my budget spreadsheet" File Catalog (local) or search_all.py Filename search — fast, broad coverage
"Find documents about Heron project in Dropbox" search_all.py (Luci or local) Dropbox API does content search server-side
"Search across everything — OneDrive, GDrive, Dropbox" search_all.py + Gety in parallel API search covers cloud-only files; Gety covers local+OCR

5. Files Reference

FileLocation (Luci)Purpose
auth_portal.py~/workspace/scripts/auth_portal.pyOAuth token management web UI (port 8788)
search_all.py~/workspace/scripts/search_all.pyUnified cloud file search CLI
graph_api.py~/workspace/scripts/graph_api.pyMS Graph API client (email, calendar, OneDrive)
file-search skill~/.claude/skills/file-search/SKILL.mdLocal file search (Gety + catalog + GDrive)
google-drive skill~/.claude/skills/google-drive/SKILL.mdGoogle Drive API client (drive.py)
m365 skill~/.claude/skills/m365/SKILL.mdMS365 integration (email, calendar, OneDrive)

Report generated by Luci | MC-393 | 8 April 2026