- Commit message format (imperative mood, 50 char subject, area prefixes)
- Commit early/often philosophy
- When to amend vs. new commit
- Push guidelines (never force main, destructive operations need approval)
- Repository hygiene (what to commit, .gitignore maintenance)
- Signed commits noted for future
1. Fixed 'Scoped' agent creation:
- Scope selector now appears when 'Scoped' is selected
- Loads available scopes from entries
- Shows checkboxes for each scope
- Select All/None button
- Validates at least one scope selected
2. Fixed token display:
- Uses result.credential (was result.token)
- Uses result.scopes (was result.scope)
3. Added agent widget to main screen:
- Shows active agent count
- Click to open agent management
- Only appears when agents exist
4. Removed Admin option from create/edit (agents can't manage agents)
HandleUpdateAgent allows updating:
- IP whitelist (ip_whitelist array)
- Rate limit per minute (rate_limit_minute)
Does NOT allow updating (security):
- Admin status (intentionally omitted)
- All_access flag
- Scopes
Requires admin token (PRF tap) since it's a sensitive operation.
This enables the Edit Agent GUI in agents.html to save changes.
- Added Edit modal for existing agents
- Can modify IP whitelist (comma-separated, supports CIDR/FQDN)
- Can modify rate limits (per minute and per hour)
- Shows current values in modal
- Cancel/Save workflow with toast notifications
- Click outside modal to close
The agents.html page now has full CRUD for agent settings:
- Create with WL/RL
- Edit WL/RL
- Lock/Unlock/Revoke
Replaces wasteful 30s polling with event-driven design:
- No polling - worker sleeps until woken by SignalReplication()
- Replication triggers immediately on write operations
- Perfect for low-change vaults (could be days without writes)
Changes:
- edition/replication.go: Event-driven worker with channel signaling
- edition/edition.go: Add SignalReplication var
- edition/community.go: No-op SignalReplication stub
- edition/commercial.go: Wire up signalReplication
Architecture:
1. Write handler marks entry dirty (replication_dirty = 1)
2. Calls edition.SignalReplication() (non-blocking)
3. Worker wakes, batches ALL dirty entries
4. POSTs to backup POP
5. Clears dirty flags on success
6. Worker sleeps until next signal
Retry logic:
- Exponential backoff: 1s, 5s, 25s, 125s...
- Max 5 retries, then operator alert
- Dirty entries persist in DB until replicated
Resource efficiency:
- CPU: Only wakes on actual writes (not 2,880x/day polling)
- Network: Only sends when data changes
- For 10 writes/day: ~288x fewer wakeups than polling
Documentation:
- SPEC-replication-async.md: Full event-driven design spec
Replication is a COMMERCIAL-ONLY feature:
- Community Edition: No replication functionality (privacy-first, single-node)
- Commercial Edition: Real-time sync to backup POPs (Calgary/Zurich)
Changes:
- edition/replication.go: Commercial-only replication implementation stub
- edition/edition.go: Add ReplicationConfig and StartReplication stub
- edition/commercial.go: Wire up replication, use globalConfig
- edition/community.go: No-op StartReplication stub
- edition/CLAUDE.md: Document replication as commercial-only
- cmd/clavitor/main.go: Add replication flags (replication-*)
- replication-primary, replication-backup, replication-token
- Warning if used in Community Edition
Security:
- Replication requires inter-POP auth token
- 30-second poll interval, batch up to 100 entries
- Automatic retry with backoff
Note: Full implementation TBD - this is the infrastructure scaffolding.
The actual replicationBatch() logic needs to be implemented for production.
Complete vault rewrite with correct foundation:
- CVT encrypted envelope tokens (type 0x00 wire, type 0x01 client credential)
- Agents and scopes stored as L1-encrypted entries (no separate tables)
- Scope-based access control with AgentCanAccess() set intersection
- Owner-only admin enforcement (agents cannot manage agents/scopes)
- 14 password manager importers (Proton, Bitwarden, 1Password, LastPass,
Dashlane, KeePass, KeePassXC, NordPass, Keeper, RoboForm, Enpass,
Safari/iCloud, Chrome, Firefox)
- FIELD_SPEC single source of truth for field kind and tier
- L2/L3 client-side encryption on import (PRF required)
- Domain classification service on clavitor.ai/classify
- Scope auto-assignment during import (13 categories)
- Light theme default (Figtree font, matching clavitor.ai branding)
- Unified page shell across all screens (topbar on every page)
- Batch import with progress indicator
- ZIP extraction for Proton Pass exports
- Proton dedup by title+user+url
- 55 tests passing (26 API + 29 lib)
- Key leak detection tests (L1/L2/L3 never in responses)
- CLI updated for CVT token format
- Old code archived in _old/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- POPs map on /hosted now generated from clavitor.db (28 POPs, 8 live)
- Added /glass (looking glass with client-side latency)
- Added /noc?pin=250365 (NOC dashboard with telemetry)
- Added POST /telemetry endpoint for POP agent heartbeats
- Encryption terminology: Vault/Credential/Identity (no more sealed/agent/L1-L3)
- License: MIT → Elastic License 2.0
- Capitalize Clavitor in all prose
- MCP references → CLI (agents use CLI, not MCP)
- GitHub links disabled (project not public yet)
- New favicon (black square logo) + apple-touch-icon
- Darker worldmap land/borders
- Added CLAUDE.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Security fix: Changed from 0.0.0.0 (all interfaces) to 127.0.0.1 (localhost only)
Files modified:
- design-system/server.go
- design-system/server-temp.go
Before: http.ListenAndServe(0.0.0.0:8888, ...) - exposed on LAN/WAN
After: http.ListenAndServe(127.0.0.1:8888, ...) - localhost only
Note: server-temp.go has 60-minute auto-shutdown. Dev server was not running
at time of fix (likely auto-shut or manually killed).