docs: migrate Authentik (SSO keystone) to edge2 CT 105

- Authentik -> edge2 CT 105 (Postgres pg_dump/restore; SECRET_KEY carried verbatim; zero-downtime until ~2s cutover)
- Multi-block Caddy cutover: auth.echo6.co + notes.echo6.co outpost/forward_auth -> 100.64.0.36:9000
- runbook: add reboot tailscale-before-docker gotcha; clarify dnsmasq must NOT be repointed (points at Caddy host)
- source left stopped + intact on Contabo as cold rollback

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Johnson 2026-06-18 05:49:07 +00:00
commit 44f0257376
140 changed files with 4013 additions and 24 deletions

100
vault/docs/navi/cc-rules.md Normal file
View file

@ -0,0 +1,100 @@
# Navi: Claude Code Rules
## Repository & SSH
**All Navi SSH goes to:** `recon-vm` (VM 1130, 192.168.1.130)
**Never SSH to cortex for Navi work.** Previous attempt to deploy from cortex wrecked production by deploying from a stale clone.
**Work directory:** `/home/zvx/projects/repos/navi` on VM 1130
**Never touch:** `/home/zvx/projects/navi-work` on cortex (stale clone, do not use)
## Git / Repository Rules
**GitHub (zvx-echo6) is the source of truth for all repos.**
### Remote Convention
- **origin** = GitHub (github.com/zvx-echo6/{repo})
- **forge** = Forgejo backup (forge.echo6.co/matt/{repo})
### Creating New Repos
1. Create on GitHub first (public unless told otherwise)
2. Create matching repo on Forgejo
3. Configure Forgejo repo as pull mirror from GitHub (8h interval)
4. Local clone: origin = GitHub, forge = Forgejo
### Exceptions
- **echo6-docs** is the sole exception — Forgejo only, no GitHub copy
### Rules
- Never force-push to origin without explicit approval
- Never use `git add -A` — stage files explicitly
## Critical Constraints
- **Never re-export namedTheme** through any intermediary module — import directly from protomaps-themes-base in MapView.jsx
- **Never use `git add -A`** — stage files explicitly
- **Never deploy without smoke tests** — run full checklist (see deployment.md)
- **Never start preview servers** — deploy to production and test there
## Build & Deploy
```bash
ssh recon-vm
cd /home/zvx/projects/repos/navi
npm run build && rsync -av --delete dist/ /mnt/nav/frontend/
```
## Git Workflow
- Feature branches: name descriptively (theme-*, fix-*, feat-*)
- Always merge to master before deploying
- Check for unmerged commits: `git log branch..master --oneline`
## Code Patterns
### queryRenderedFeatures for Optional Layers
Guard with map.getLayer() — USFS/BLM hit layers may not exist:
```javascript
const layers = [USFS_TRAILS_HIT, USFS_ROADS_HIT].filter(id => map.getLayer(id))
const features = layers.length > 0
? map.queryRenderedFeatures(e.point, { layers })
: []
```
### buildStyle Theme Colors
```javascript
const theme = getTheme(themeName)
const colors = theme.colors || namedTheme(themeName) // direct import
```
### PlaceCard useEffect Changes
Investigation-before-implementation — fragile race conditions between:
- Boundary fetch from Wikidata/OSM
- selectedPlace state updates
- AbortController cleanup
## Architecture Notes
- **Boundary highlight** is NOT an overlay toggle — it's a dynamic click-response layer
- **Route polyline** uses GeoJSON source.setData() — silent failure if namedTheme is re-exported
- **Measure tool** also uses GeoJSON — same failure mode
## Smoke Test Checklist
After every deploy:
- [ ] Route between two addresses — polyline renders
- [ ] Click city label — boundary outline appears
- [ ] Theme switching (all 4 themes)
- [ ] Overlay toggles (hillshade, contours, public lands)
- [ ] Console: no "bt is not defined" or "f is not defined"

View file

@ -0,0 +1,55 @@
# Navi Deployment
## Source Repository
**Location:** VM 1130 (`192.168.1.130`) at `/home/zvx/projects/repos/navi`
> **WARNING:** Never deploy from `/home/zvx/projects/navi-work` on cortex — that clone is stale.
## Build & Deploy
```bash
# SSH to VM 1130
ssh recon-vm
# Always backup first
cp -r /mnt/nav/frontend /mnt/nav/frontend.bak.$(date +%Y%m%d-%H%M%S)
# Build and deploy
cd /home/zvx/projects/repos/navi
npm run build && rsync -av --delete dist/ /mnt/nav/frontend/
```
## Infrastructure
- **Nginx** on VM 1130 serves `/mnt/nav/frontend/` on port 8440
- `index.html`: no-cache (always fresh)
- Hashed assets (`*.js`, `*.css`): cache forever
- **Caddy** on CT 101 routes `navi.echo6.co` → VM 1130:8440
## Pre-Deploy Checklist
1. Merge feature branch to master before deploying
2. Check for unmerged upstream commits:
```bash
git log your-branch..master --oneline
```
3. Create backup (see above)
## Post-Deploy Smoke Tests
Run after **every** deploy:
- [ ] Route between two addresses — polyline renders
- [ ] Click city label — boundary outline appears
- [ ] Theme switching works (dark, light, clean, cyberpunk)
- [ ] Toggle overlays (hillshade, contours, public lands)
- [ ] Console: no `bt is not defined` or `f is not defined` errors
## Rollback
```bash
# If deploy fails, restore backup
rm -rf /mnt/nav/frontend
mv /mnt/nav/frontend.bak.YYYYMMDD-HHMMSS /mnt/nav/frontend
```

115
vault/docs/navi/themes.md Normal file
View file

@ -0,0 +1,115 @@
# Navi Theme System
## Architecture
**Registry:** `src/themes/registry.js`
Central source for theme metadata, overlay config, UI CSS vars, and satellite adjustments.
## Critical: namedTheme Import
> **NEVER re-export namedTheme through registry.js or any other module.**
namedTheme must be imported **directly** from protomaps-themes-base in MapView.jsx:
```javascript
// CORRECT
import { layers, namedTheme } from 'protomaps-themes-base'
import { getTheme, getThemeSprite, getOverlayConfig } from '../themes/registry'
function buildStyle(themeName) {
const theme = getTheme(themeName)
const colors = theme.colors || namedTheme(themeName) // direct import for built-ins
return {
// ...
layers: layers('protomaps', colors, { lang: 'en' }),
}
}
```
**Why:** Vite's bundling of namedTheme through a re-export breaks MapLibre's Web Worker, causing silent GeoJSON rendering failure (routes, boundaries, measure tool all invisible, "f is not defined" error in worker).
## Theme Config Shape
```javascript
{
id: 'dark', // unique identifier
name: 'Dark', // display name
dark: true, // affects overlay styling, sprite fallback
swatch: ['#1c1917', '#7a9a6b', '#b8a88a'], // theme picker preview
fontImports: [], // Google Font URLs (empty = system fonts)
colors: null, // null = built-in, object = custom theme colors
satellite: null, // raster adjustments when satellite active
overlay: { ... }, // per-layer styling for overlays
ui: { ... }, // 32 CSS custom properties
}
```
## UI CSS Variables
Applied by applyThemeUI() via document.documentElement.style.setProperty():
- Backgrounds: --bg-base, --bg-raised, --bg-overlay, --bg-input, --bg-inset, --bg-muted
- Text: --text-primary, --text-secondary, --text-tertiary, --text-inverse
- Borders: --border, --border-subtle
- Accent: --accent, --accent-hover, --accent-muted
- Pins: --pin-origin, --pin-destination, --pin-intermediate, --pin-stroke
- Status: --status-success, --status-warning, --status-danger, --success, --warning, --warning-muted
- Fonts: --font-sans, --font-mono, --font-heading
- Shadows: --shadow, --shadow-lg
## Overlay Config
Read via getOverlayConfig(themeId, layerKey) with spread-defaults fallback:
- hillshade: exaggeration, illuminationDirection, shadowColor, highlightColor
- contours: colors, opacities, widths for minor/intermediate/index lines + labels
- publicLands: fill/outline colors per agency (NPS, USFS, BLM, etc.)
- usfsTrails: road/trail colors by use type (motorized, bicycle, hiker)
- blmTrails: route colors by vehicle class (4WD, ATV, non-mechanized)
## Satellite Raster Adjustments
Neutral defaults (no adjustment):
```javascript
satellite: {
opacity: 1.0,
brightnessMin: 0.0,
brightnessMax: 1.0,
contrast: 0.0, // MapLibre uses -1 to 1 range
saturation: 0.0, // MapLibre uses -1 to 1 range
hueRotate: 0,
}
```
## Font Support
fontImports array of Google Font URLs, managed on theme switch:
```javascript
fontImports: [
'https://fonts.googleapis.com/css2?family=Orbitron&display=swap',
'https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap',
]
```
Injected as <link data-theme-font> tags, removed on theme switch.
## Theme Picker
ThemePicker.jsx — swatch popover in header, reads themeList() for [{id, name, dark, swatch}].
## Current Themes
| ID | Name | Type | Description |
|----|------|------|-------------|
| light | Light | built-in | Default light theme |
| dark | Dark | built-in | Default dark theme |
| clean | Clean | custom | Google Maps-inspired, utilitarian |
| cyberpunk | Cyberpunk | custom | Neon palette, Orbitron + Share Tech Mono fonts |
## Adding a New Theme
1. Create src/themes/{name}.js with full theme config
2. Import and register in registry.js themes object
3. Theme auto-appears in picker via themeList()