clawd/memory/2026-03-01.md

14 KiB

03:09 AM — vault1984 session (continued)

vault1984 project — major progress tonight

  • Domain: vault1984.com registered in Openprovider, DNS via Cloudflare (zone: 1c7614cd4ee5eabdc03905609024f93a), A record → 47.197.93.62 (forge home IP), TTL 60
  • Caddy: vault1984.com, www.vault1984.com block added, reverse_proxy → 192.168.1.16:1984. HTTPS live via ZeroSSL.
  • GitHub: Private repo created at https://github.com/johanjongsma/vault1984 under johanjongsma account (not johan-jongsma which is Kaseya-linked). GH token: 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 (stored for repo ops).
  • Systemd service: vault1984.service running on forge, auto-restart, EnvironmentFile=/home/johan/dev/vault1984/.env
  • VAULT_KEY: d153af4a1b9e58023d0ec465f2674fc29d52ea0b9ef9a0f0cbbaaee63f0117fb (persistent)
  • DB: /home/johan/dev/vault1984/vault1984.db

vault1984 — what's built

  • Go binary, single SQLite, port 1984
  • Marketing website at /, app UI at /app/
  • L1/L2 encryption, MCP endpoint, scoped tokens, TOTP, import (format-detection only — LLM never sees credential values)
  • LLM config: LLM_API_KEY, LLM_BASE_URL, LLM_MODEL (any OpenAI-compatible provider)
  • 11 integration tests passing (TestHealth, TestCreateLogin, TestReadLogin_RoundTrip, TestURLMatch, TestTOTP_AgentGeneratesCode, TestMCP_ListCredentials, TestMCP_GetCredential_Inou, TestMCP_GetTOTP, TestScopedToken_HidesOtherEntries, TestPasswordGenerator, TestAuditLog)

vault1984 — landing page work

  • Real world map: Natural Earth 110m topojson, pre-projected to SVG, antimeridian artifacts fixed, no grid lines
  • Datacenter locations: Virginia, Zürich (gold #D4AF37, HQ), Beijing, Sydney
  • Visitor geolocation: /geo endpoint (ip-api.com, detects private IPs, falls back to browser geolocation API)
  • Red pulsing dot + 5th card for visitor location
  • Zürich: gold dot, gold label, larger pulse rings, subtle gold border on card
  • Copy fixes: "Your EA" → "Your assistant can book your flights. Not read your diary.", TOTP explained inline, L1/L2 explainer rewritten for clarity, Bitwarden removed from editorial copy (kept in complaint quotes), "your government" rejected — kept "or anybody else"
  • vault1984 styled everywhere (green 1984)

SMTP — noreply@inou.com

  • Dedicated Stalwart account created on Zurich: username noreply, password InouNoreply2026!
  • Port 465 (implicit TLS) — port 587 only offers OAuth2, not PLAIN/LOGIN
  • SMTP creds for inou app: host=mail.inou.com, port=465, user=noreply, pass=InouNoreply2026!, from=noreply@inou.com

Caddy (192.168.0.2) — important corrections

  • SSH: ssh root@192.168.0.2 (direct LAN). Do NOT use Tailscale (requires re-auth).
  • Log dir ownership fix: chown caddy:caddy /var/log/caddy after every reboot (known issue)
  • Caddy updated to 2.11.1, Tailscale 1.94.2 during tonight's update
  • Git backup: git@zurich.inou.com:caddy-config.git — Caddyfile committed, auto-commits via daily-updates.sh
  • Added to daily-updates.sh: apt upgrade + Caddyfile git push

Cloudflare API

  • Token: dSVz7JZtyK023q7kh4MMNmIggK1dahWdnBxVnP3O
  • Account ID: 86e646c0224dc44dcffb08c981ff9200
  • vault1984.com zone ID: 1c7614cd4ee5eabdc03905609024f93a

Spacebot feedback on vault1984

Opus-level analysis: concept "ahead of everyone else", architecture "genuinely clever". Red flags cited: no GitHub (fixed), no audit (acknowledged gap), L2 recovery not documented (gap remains), L1 server-readable on hosted copy is misleading (needs callout in copy). "Bookmark it, check back in 6 months."

Kaseya / password space

Confirmed: Kaseya had Passly (via ID Agent) — no longer offered as of early 2025. Clear market.

04:28 AM — vault1984 session cont. (pre-compaction)

vault1984 landing page — current state

What's working on the landing page

  • Real world map (Natural Earth 110m SVG, pre-projected, no CDN)
  • 4 DC dots: Virginia (green), Zürich (gold #D4AF37), Beijing (green), Sydney (green)
  • Visitor geo: /geo endpoint → ip-api.com, private IP → browser geolocation API fallback
  • Reverse geocode for browser geo: /geo?lat=X&lon=Y (Go handler, ip-api.com)
  • Visitor red dot on map + 5th card in grid (St. Pete working)
  • 5-col grid, one row, solid bg colors (no gradients): green #0d1f10, gold #1a1600, red #1f0a0a
  • Self-hosted Tailwind CSS (16KB), Google Fonts (CDN), favicon.svg
  • Zero CDN except Google Fonts
  • No console errors

What was in progress when we stopped

  • Fix /geo to accept lat/lon query params for reverse geocode (Go handler update needed)
  • "You" card still showing no city/country (bigdatacloud → switched to /geo?lat=X&lon=Y proxy)
  • Nav "Hosted" link: was missing from hosted.html, just added
  • Map and cards alignment: in same container width
  • Last commit not yet built/pushed — changes pending in both hosted.html and index.html

Pending build/push

cd /home/johan/dev/vault1984
# 1. Update /geo handler to accept lat/lon params for reverse geocode
# 2. go build -o vault1984 ./cmd/vault1984/
# 3. sudo systemctl restart vault1984
# 4. git add -A && git commit -m "..." && git push

/geo handler needs update

  • Add lat/lon query param support to GeoLookup handler
  • If lat/lon provided → use ip-api.com reverse geocode (or nominatim)
  • If no lat/lon → use IP-based geo (existing behavior)

vault1984 website structure

  • / → index.html (marketing, slim hosted CTA)
  • /hosted → hosted.html (map + pricing + datacenter cards)
  • /app/ → embedded app UI (vault)
  • /install.html, /pricing.html, /privacy.html, /terms.html → static pages
  • /geo → Go handler (ip-api.com lookup by IP or lat/lon)
  • /api/* → vault REST API (auth required)
  • /mcp → MCP endpoint (scoped token auth)

Tailwind rebuild needed when adding new classes

cd /home/johan/dev/vault1984/cmd/vault1984/website
/tmp/tailwindcss --config /tmp/tw.config.js --input /tmp/tw.css \
  --content "./*.html" --output tailwind.min.css --minify

tw.config.js custom colors: accent=#22C55E, navy=#0A1628, navy-light=#111f38

Cloudflare vault1984.com

  • Zone ID: 1c7614cd4ee5eabdc03905609024f93a
  • A record: @ → 47.197.93.62 (forge home IP), TTL 60
  • NS: aryanna + sage.ns.cloudflare.com
  • Token: dSVz7JZtyK023q7kh4MMNmIggK1dahWdnBxVnP3O

noreply@inou.com SMTP

  • Host: mail.inou.com, Port: 465 (implicit TLS — 587 is OAuth2 only)
  • User: noreply, Pass: InouNoreply2026!

05:20 ET — vault1984 /hosted page polish session

Changes made (commits 6ad6fca, c3695cd, and ongoing)

  • Geo detection fixed: /geo?lat=X&lon=Y now reverse-geocodes via Nominatim OSM (free, no key). LAN visitors get real city/country via browser geolocation.
  • Nav: vault1984 left-aligned (w-full px-8, no max-w-7xl centering on nav bar). Hosted link → gold #D4AF37 with pulsing dot animation.
  • Zürich card bg: #1a1600#3d2e00 (visibly amber/golden)
  • "You" card: city / country / region on separate lines (was jammed as "Saint Petersburg, United States")
  • Flexbox cards: already fixed (5 cards in one row via flex:1 min-width:0)
  • Sources page: /sources live at vault1984.com/sources — all complaint quotes with verbatim text + URLs (1Password forum, Bitwarden GitHub/Community, LastPass HN)
  • Viewport fix (spawned Opus): Two root problems at 1200px viewport — nav items crowded + cards cut off below fold. Opus tasked to: shrink nav (text-2xl, gap-4, drop '— $12/yr'), remove security model box (~200px saved), cap SVG map at max-height:380px. Target section height ~639px, fits in 1136px (1200 - 64px nav).

Key file locations

  • /home/johan/dev/vault1984/cmd/vault1984/website/hosted.html — main hosted page
  • /home/johan/dev/vault1984/cmd/vault1984/website/sources.html — new sources page
  • /home/johan/dev/vault1984/api/routes.go — added /sources route
  • /home/johan/dev/vault1984/api/handlers.go — GeoLookup with Nominatim lat/lon path

Running state

  • Binary: /home/johan/dev/vault1984/vault1984
  • Live: http://localhost:1984 and https://vault1984.com
  • Opus agent session: clear-summit (pid 2981583) — fixing viewport

Johan feedback patterns this session

  • "the viewport is getting worse" → screenshots showed wrong Chrome tab; actual issue was 200+px of wasted margins + unconstrained SVG map height
  • Wants evidence before "done" — always take screenshot after changes
  • Card layout: each DC gets name + flag + subtitle + live dot, "You" card gets city/country/region split

06:33 ET — vault1984 architecture decisions

Project split (done)

  • vault1984 (GitHub + Zurich, MIT OSS) → pure app binary, / serves vault UI
  • vault1984-web (Zurich only, proprietary) → marketing site + auth + Stripe
  • Website files removed from vault1984 binary entirely
  • vault1984-web at git@zurich.inou.com:vault1984-web.git

Three files for self-hosted install

vault1984       # binary (always recoverable, OSS)
vault1984.db    # data (back up — encrypted blobs, safe anywhere)
.env            # VAULT_KEY (never back up digitally — write on paper)
  • DB can be backed up anywhere (blobs are already AES-256-GCM encrypted)
  • .env is the single irreplaceable secret
  • SQLite encryption (SQLCipher) rejected — redundant, fields already encrypted
  • File permissions (chmod 600) = only mitigation for filesystem exposure
  • Self-hosters own the machine → not the threat model; external attackers are

Auth architecture decisions

  • L1 encryption: VAULT_KEY from .env (server secret, not user password)
  • L2 encryption: WebAuthn PRF client-side (AI never sees it)
  • User auth: WebAuthn (Touch ID, Face ID, YubiKey) — no master password
  • Multiple devices: each registers separately, any one unlocks vault
  • Recovery: 12-word BIP39 mnemonic, shown ONCE at setup, give to trusted person (mom)
  • Recovery flow: mom reads words over phone → email OTP to you → both required → new device registered
  • Mandatory 2 credentials: rejected for L1 (too much friction); L2 only unlocks with ≥2
  • VAULT_KEY is machine secret, completely separate from user WebAuthn credentials

WebAuthn setup wizard (spawned Opus agent: dawn-lagoon)

3-step wizard:

  1. "Register this device" → WebAuthn navigator.credentials.create()
  2. "Your recovery phrase" → show 12 BIP39 words, confirm 3 random ones
  3. "You're in" → vault ready Returning users: WebAuthn prompt immediately on page load Recovery: paste 12 words → allowed to register new device

Routing fix

  • / now serves the vault app (was serving marketing website)
  • /app removed

Self-hoster threat model

  • External attackers breaching their server → encrypted blobs protect users
  • Self-hoster themselves → not the threat model (their machine, their data)

vault1984 — pre-release rules

  • No migrations until v1.0 release — schema is source of truth, no ALTER TABLE needed
  • No existing DBs to worry about — dev only, wipe and recreate freely
  • checksum INTEGER column reserved in entries table (nullable, not yet implemented)
  • Implement checksum before release, not before

06:42 ET — vault1984 session wrap-up (full state for resume)

Agent running: dawn-lagoon (Opus)

Implementing WebAuthn setup wizard. Check status with process(action=poll, sessionId=dawn-lagoon) before resuming.

Current binary state

  • Running on forge at http://192.168.1.16:1984/
  • / serves the vault app UI
  • Marketing website fully removed from binary → lives in ~/dev/vault1984-web/
  • VAULT_KEY loaded from .vault_key file (ephemeral workaround — not yet wired to .env properly)

Architecture decided (DO NOT RE-DEBATE)

  • L1 key: VAULT_KEY in .env — machine secret, not user password
  • User auth: WebAuthn only (Touch ID, Face ID, YubiKey) — no master password
  • Recovery: 12-word BIP39 mnemonic, shown once at setup, give to trusted person
  • Recovery flow: trusted person reads words → email OTP to user → both required → register new device
  • Self-hoster threat model: external attackers only; self-hoster owns the machine
  • No SQLite encryption — fields already AES-256-GCM encrypted, redundant
  • No migrations until v1.0 — no existing DBs, clean slate
  • checksum INTEGER reserved in entries table (nullable, implement before release)
  • Backup story: vault1984.db (safe anywhere, blobs encrypted) + .env (never digitally)

Two projects

Project Location Git Visibility
vault1984 ~/dev/vault1984/ GitHub + Zurich MIT OSS
vault1984-web ~/dev/vault1984-web/ Zurich only Proprietary

vault1984-web

  • Pure static HTML for now (all the old website files)
  • Will grow to include: login, registration, Stripe billing, multi-tenant hosted
  • Active content = needs a Go backend eventually (same pattern as vault1984)
  • vault1984.com → Cloudflare → points here eventually

Next steps when resuming vault1984

  1. Check dawn-lagoon agent output (WebAuthn wizard)
  2. Wire VAULT_KEY to proper .env file (not .vault_key)
  3. Systemd service on forge
  4. Caddy proxy (vault.jongsma.me or similar)
  5. Import Johan's credentials (12,623 entries from browsers + Proton)
  6. Scoped MCP tokens UI
  7. Binary releases (GitHub Actions)

GitHub token

  • james-vault: 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
  • Has delete_repo scope (added today)

Key files

  • lib/dbcore.go — schema + DB operations
  • lib/types.go — Entry struct (has Checksum *int64 field reserved)
  • api/routes.go — routing (websiteFS removed, webFS only, / serves app)
  • cmd/vault1984/main.go — entrypoint (webFS only embed)
  • cmd/vault1984/web/index.html — app UI (setup wizard being rewritten by Opus)