mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
* docs: restructure documentation into focused, navigable pages (#docs-reorg) Break the 4096-line documentation.mdx monolith into 13 focused pages organized by feature area. Reorganize Mintlify navigation from 5 generic groups into 7 feature-based groups. Move Orbital Surveillance from Infrastructure to Map Layers where it belongs. - Extract: signal-intelligence, features, overview, hotspots, CII, geographic-convergence, strategic-risk, infrastructure-cascade, military-tracking, maritime-intelligence, natural-disasters, contributing, getting-started - Append to: architecture.mdx (9 sections), ai-intelligence.mdx (3 sections) - Fix legacy .md links in map-engine.mdx, maps-and-geocoding.mdx - Slim documentation.mdx to an 80-line index/hub page - Eliminate duplicate content that caused repeated headings * fix(docs): remove duplicate H1 headings from all Mintlify pages Mintlify auto-renders the frontmatter `title` as an H1, so having `# Title` in the body creates a doubled heading on every page. Remove the redundant H1 (and repeated description lines) from all 31 .mdx files.
143 lines
5.6 KiB
Plaintext
143 lines
5.6 KiB
Plaintext
---
|
|
title: "API Key Gating & Registration — Deployment Guide"
|
|
description: "Desktop cloud fallback is gated on a WORLDMONITOR_API_KEY. Without a valid key, the desktop app operates local-only (sidecar). A registration form collects emails via Convex DB for future key distribution."
|
|
---
|
|
## Overview
|
|
|
|
Desktop cloud fallback is gated on a `WORLDMONITOR_API_KEY`. Without a valid key, the desktop app operates local-only (sidecar). A registration form collects emails via Convex DB for future key distribution.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Desktop App Cloud (Vercel)
|
|
┌──────────────────┐ ┌──────────────────────┐
|
|
│ fetch('/api/...')│ │ api/[domain]/v1/[rpc]│
|
|
│ │ │ │ │ │
|
|
│ ┌──────▼───────┐ │ │ ┌──────▼───────┐ │
|
|
│ │ sidecar try │ │ │ │ validateApiKey│ │
|
|
│ │ (local-first)│ │ │ │ (origin-aware)│ │
|
|
│ └──────┬───────┘ │ │ └──────┬───────┘ │
|
|
│ fail │ │ │ 401 if invalid │
|
|
│ ┌──────▼───────┐ │ fallback │ │
|
|
│ │ WM key check │─┼──────────────►│ ┌──────────────┐ │
|
|
│ │ (gate) │ │ +header │ │ route handler │ │
|
|
│ └──────────────┘ │ │ └──────────────┘ │
|
|
└──────────────────┘ └──────────────────────┘
|
|
```
|
|
|
|
## Required Environment Variables
|
|
|
|
### Vercel
|
|
|
|
| Variable | Description | Example |
|
|
|----------|-------------|---------|
|
|
| `WORLDMONITOR_VALID_KEYS` | Comma-separated list of valid API keys | `wm_abc123def456,wm_xyz789` |
|
|
| `CONVEX_URL` | Convex deployment URL (from `npx convex deploy`) | `https://xyz-123.convex.cloud` |
|
|
|
|
### Generating API keys
|
|
|
|
Keys must be at least 16 characters (validated client-side). Recommended format:
|
|
|
|
```bash
|
|
# Generate a key
|
|
openssl rand -hex 24 | sed 's/^/wm_/'
|
|
# Example output: wm_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6
|
|
```
|
|
|
|
Add to `WORLDMONITOR_VALID_KEYS` in Vercel dashboard (comma-separated, no spaces).
|
|
|
|
## Convex Setup
|
|
|
|
### First-time deployment
|
|
|
|
```bash
|
|
# 1. Install (already in package.json)
|
|
npm install
|
|
|
|
# 2. Login to Convex
|
|
npx convex login
|
|
|
|
# 3. Initialize project (creates .env.local with CONVEX_URL)
|
|
npx convex init
|
|
|
|
# 4. Deploy schema and functions
|
|
npx convex deploy
|
|
|
|
# 5. Copy the deployment URL to Vercel env vars
|
|
# The URL is printed by `npx convex deploy` and saved in .env.local
|
|
```
|
|
|
|
### Verify Convex deployment
|
|
|
|
```bash
|
|
# Typecheck Convex functions
|
|
npx convex dev --typecheck
|
|
|
|
# Open Convex dashboard to see registrations
|
|
npx convex dashboard
|
|
```
|
|
|
|
### Schema
|
|
|
|
The `registrations` table stores:
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `email` | string | Original email (for display) |
|
|
| `normalizedEmail` | string | Lowercased email (for dedup) |
|
|
| `registeredAt` | number | Unix timestamp |
|
|
| `source` | string? | Where the registration came from |
|
|
| `appVersion` | string? | Desktop app version |
|
|
|
|
Indexed by `normalizedEmail` for duplicate detection.
|
|
|
|
## Security Model
|
|
|
|
### Client-side (desktop app)
|
|
|
|
- `installRuntimeFetchPatch()` checks `WORLDMONITOR_API_KEY` before allowing cloud fallback
|
|
- Key must be present AND valid (min 16 chars)
|
|
- `secretsReady` promise ensures secrets are loaded before first fetch (2s timeout)
|
|
- Fail-closed: any error in key check blocks cloud fallback
|
|
|
|
### Server-side (Vercel edge)
|
|
|
|
- `api/_api-key.js` validates `X-WorldMonitor-Key` header on sebuf routes
|
|
- **Origin-aware**: desktop origins (`tauri.localhost`, `tauri://`, `asset://`) require a key
|
|
- Web origins (`worldmonitor.app`) pass through without a key
|
|
- Non-desktop origin with key header: key is still validated
|
|
- Invalid key returns `401 { error: "Invalid API key" }`
|
|
|
|
### CORS
|
|
|
|
`X-WorldMonitor-Key` is allowed in both `server/cors.ts` and `api/_cors.js`.
|
|
|
|
## Verification Checklist
|
|
|
|
After deployment:
|
|
|
|
- [ ] Set `WORLDMONITOR_VALID_KEYS` in Vercel
|
|
- [ ] Set `CONVEX_URL` in Vercel
|
|
- [ ] Run `npx convex deploy` to push schema
|
|
- [ ] Desktop without key: cloud fallback blocked (console shows `cloud fallback blocked`)
|
|
- [ ] Desktop with invalid key: sebuf requests get `401`
|
|
- [ ] Desktop with valid key: cloud fallback works as before
|
|
- [ ] Web access: no key required, works normally
|
|
- [ ] Registration form: submit email, check Convex dashboard
|
|
- [ ] Duplicate email: shows "already registered"
|
|
- [ ] Existing settings tabs (LLMs, API Keys, Debug) unchanged
|
|
|
|
## Files Reference
|
|
|
|
| File | Role |
|
|
|------|------|
|
|
| `src/services/runtime.ts` | Client-side key gate + header attachment |
|
|
| `src/services/runtime-config.ts` | `WORLDMONITOR_API_KEY` type, validation, `secretsReady` |
|
|
| `api/_api-key.js` | Server-side key validation (origin-aware) |
|
|
| `api/[domain]/v1/[rpc].ts` | Sebuf gateway — calls `validateApiKey` |
|
|
| `api/register-interest.js` | Registration endpoint → Convex |
|
|
| `server/cors.ts` / `api/_cors.js` | CORS headers with `X-WorldMonitor-Key` |
|
|
| `src/components/WorldMonitorTab.ts` | Settings UI for key + registration |
|
|
| `convex/schema.ts` | Convex DB schema |
|
|
| `convex/registerInterest.ts` | Convex mutation |
|