Commit Graph

88 Commits

Author SHA1 Message Date
Johan Jongsma 063d2c8cd8 Merge branch 'master' into hans/fix-8 2026-04-09 14:20:45 +00:00
Johan Jongsma ab0b5e0717 Merge pull request 'Luna: Add currency dropdown sections with Popular/All Currencies split' (#18) from luna/design-11 into master 2026-04-09 14:20:14 +00:00
James cdfa87b8ce web: Add currency dropdown sections with Popular/All Currencies split
Implements frontend styling for issue #11:
- Add .dropdown-section CSS for section headers (Popular, All Currencies)
- Add .dropdown-divider CSS for visual separation between sections
- Update test-index.html with dynamic currency loading from /api/currencies
- Update base.tmpl with split language/currency selectors
- JavaScript fetches currencies and renders with section headers
- Maintains localStorage persistence for currency preference
- Error handling with ERR-CURRENCY-001/002 codes

Design Requirements Met:
- Section headers use 11px uppercase with 0.08em letter-spacing
- Divider uses 1px border with 8px vertical margins
- Dropdown maintains existing hover/click behavior
- Mobile responsive (stacks in hamburger menu)

fixes #11

Author: Luna <luna-20250409-001>
2026-04-09 03:46:42 -04:00
James def0c6fb1d test: rewrite agent credential tests for client-side generation
Rewrites 7 skipped integration tests to work with client-side credential generation:

- TestScopedAccess_agent_sees_only_scoped_entries
- TestScopedAccess_agent_forbidden_on_unscoped
- TestScopedAccess_all_access_sees_everything
- TestScopedAccess_agent_cannot_manage_agents
- TestScopedAccess_agent_cannot_create_system_types (renamed from _modify_scopes)
- TestScopedAccess_agent_entries_invisible
- TestKeyLeak_agent_credential_is_opaque

Adds MintCredential/ParseCredential test helpers to lib/cvt.go for creating
type 0x01 client credential tokens in tests. These simulate the client-side
credential generation that normally happens in browser/CLI.

Adds test helper methods to integration_test.go:
- reqAgent(): sends requests with CVT wire token authentication
- mintWireToken(): creates type 0x00 wire tokens for agent auth

Security boundaries tested:
- Agents with limited scope cannot access owner-only entries
- Agents with all_access can see all entries
- Agents cannot manage other agents (create/list)
- Agents cannot create system-type entries (agent, scope)
- Server responses never contain raw L2/L3 key material

Fixes #14
2026-04-09 03:45:42 -04:00
James af47846f23 web: split language/currency selector into two dropdowns
Replaces the combined locale dropdown with two independent selectors:
- Language dropdown: flag + 2-letter code (e.g., '🇺🇸 EN')
- Currency dropdown: symbol + 3-letter code (e.g., '$ USD')

Changes:
- test-index.html: Split combined dropdown into nav-dropdown--language and nav-dropdown--currency
- clavitor.css: Add styles for split selectors with 8px gap, mobile stacking
- JavaScript: Independent state management for each selector

Design requirements met:
- Both dropdowns fit within nav bar without wrapping
- Mobile: stack vertically in hamburger menu
- 8px gap between selectors using existing spacing

fixes #10

Author: Emma <emma-20250409-001>
2026-04-09 03:39:51 -04:00
James 989f7e5f2b ui: remove strikethrough pricing — always show $12/yr
Removes crossed-out "$20" pricing from all templates and test files.
The hosted plan is now permanently $12/year.

Files modified:
- test-index.html: Header CTA button
- test-hosted.html: Header CTA and hero text
- base.tmpl: Header CTA button
- hosted.tmpl: Hero text and CTA section
- index.tmpl: Hero button and hosted CTA section
- upgrade.tmpl: Pricing comparison text
- integrations.tmpl: All 4 CTA buttons (English + Chinese)
- install.tmpl: Hosted option section

fixes #9

Author: Emma <emma-20250409-001>
2026-04-09 03:36:54 -04:00
James fe9f98a69e telemetry: add Prometheus metrics endpoint
Adds /metrics endpoint that returns Prometheus-format metrics for monitoring:

- telemetry_requests_total (counter, labeled by pop_id and status)
- telemetry_request_duration_seconds (histogram with standard buckets)
- active_connections (gauge)
- db_query_duration_seconds (histogram for health check queries)

Following KISS principle - no external dependencies, simple text format
implementation with proper mutex protection for thread safety.

All error paths handled with unique error codes per Cardinal Rule.

fixes #8
2026-04-09 03:29:32 -04:00
James 30a904247d dispatcher: add domain-to-agent mapping and opencode agent spawning
Implements the dispatcher flow for routing issues to specialized agents:
- Domain-to-agent mapping from CLAVITOR-AGENT-HANDBOOK.md Section I
- Automatic agent spawning via opencode CLI
- Webhook handler for real-time Gitea events
- Active agent tracking to prevent duplicate work

fixes #5
2026-04-09 03:20:27 -04:00
James 6c2b708c4d telemetry: verify dispatcher agent spawning for Hans
Adds verification documentation that the dispatcher flow correctly:
- Identifies clavis-telemetry domain issues
- Assigns to Hans (NOC/Operations agent)
- Spawns Hans successfully to process telemetry issues

All tests pass, no security violations detected.

fixes #5
2026-04-09 03:14:27 -04:00
James 8400acffb9 Add Agent Dispatcher - runs on forge, polls Zurich Gitea
Simple Go binary that:
- Polls git.clavitor.ai every 60 seconds from forge
- Dispatches 1 task per minute max (rate limited)
- Priority order: CRITICAL > HIGH > NORMAL > LOW
- Writes task files to .agent-tasks/<agent>/issue-#.md
- Built-in web UI at http://forge:8098
- Full verbose logging to .agent-dispatcher.log
- No external deps (no Prometheus, etc.)

Files:
- forge/dispatcher/main.go (the dispatcher)
- forge/dispatcher/README.md (instructions)
- forge/dispatcher/go.mod

Monitoring:
- Web dashboard: http://localhost:8098 (auto-refresh)
- Live logs: tail -f .agent-dispatcher.log
- Task files: ls .agent-tasks/<agent>/
2026-04-09 01:33:10 -04:00
James e71a50d729 Update root CLAUDE.md - mention Gitea login in Quickstart
Agents need Gitea login to participate in workflow.
This is now the first step in Quickstart.md.
Updated description to reflect this.
2026-04-09 01:25:23 -04:00
James d3200fb2bf Fix QUICKSTART.md with foundation approach - tea CLI just works
Added one-time setup:
- Export GITEA_TOKEN
- tea login add

This is THE foundation for agent workflow. Without this, agents can't:
- Query their tasks programmatically
- Create PRs
- Participate in the Git workflow

Updated workflow section:
- Use tea CLI for task list and PR creation
- No scripts needed
- No asking permission
- Commit with 'Fixes #N', push, create PR, wait for review

Added building section:
- Standard vs commercial (-tags commercial)
- Test before committing

Now Hans can:
1. tea issues list --assignees hans (see tasks)
2. Fix code
3. tea pulls create (submit for review)

Foundation: tea CLI works.
2026-04-09 01:25:08 -04:00
James cd1644128f Capture workflow friction from Hans' first real test session
Real issues found:
1. Daily review script bugs (checker needed checking)
2. Tea CLI auth not documented (had to describe commands)
3. Go module structure confusing (telemetry standalone)
4. Done signal ambiguous (had to ask permission)
5. Build tags not in QUICKSTART
6. Issue state machine undocumented (who closes?)
7. No task pickup skill (had to guess priority)

Biggest: Agents can't fully query/modify Gitea programmatically.
Options: A) Full autonomy (skills needed), B) Assisted (current), C) Hybrid.

Immediate fixes needed in QUICKSTART.md and handbook documentation.
2026-04-09 01:22:01 -04:00
James b4aced5c03 telemetry: fix CRITICAL silent failures (Cardinal Rule #1)
Fixes #2, #3, #4

Issue #2 - Silent database errors in updateSpan():
- Add error handling for telemetry INSERT (ERR-TELEMETRY-004)
- Add error handling for all table/index creation (ERR-TELEMETRY-005 to -010)
- Return HTTP 500 to client on insert failure

Issue #3 - Silent failure in Kuma push:
- Return early on non-OK status from Kuma
- Proper error logging with body close handling

Issue #4 - Unchecked flush error in tarpit:
- Verify http.Flusher available before tarpit
- Log ERR-TELEMETRY-040 and abort if flusher unavailable
- Remove redundant flusher checks in loop

All changes: security failures are now LOUD (Cardinal Rule #1)

Author: Hans <hans-20250409-001>
2026-04-09 01:20:08 -04:00
James 6d5837c7b4 Fix daily-review.sh bugs found by Hans
- Fixed A1-A3 checks: paths were missing 'clavis/' prefix
  * Now uses explicit counting (wc -l) instead of fragile exit codes
  * Shows violation count and first 3 matches on failure
- Added cd to script directory so it runs from repo root
- Updated G1 (empty directories) to:
  * Exclude known placeholders (edition/commercial)
  * Show review list instead of hard fail
  * User decides if dirs should be deleted
- Script now properly reports PASS/FAIL for all checks
2026-04-09 01:14:36 -04:00
James b920203314 Address Hans' workflow feedback - make it actionable
1. Created QUICKSTART.md (60 second read vs 1295 line handbook)
   - Who you are, 4 session-start actions, critical rules
   - All CLAUDE.md files now reference QUICKSTART first

2. Created scripts/daily-review.sh (automates Part 4 checks)
   - Runs Section A, F, G checks automatically
   - Reports PASS/FAIL with colors
   - Fails fast on foundation violations

3. Added workflow section to handbook
   - Where to find tasks (git.clavitor.ai)
   - Priority order (CRITICAL > HIGH > MEDIUM)
   - Engineer vs Reviewer responsibilities

4. Created tasks skill (.claude/skills/tasks/SKILL.md)
   - For querying Gitea issues programmatically
   - Will integrate with agent workflow

5. Updated all 11 CLAUDE.md files with concise headers
   - Quickstart link (60s)
   - Deep reference link (handbook Section V)
   - Agent identity + daily script command

Hans' feedback addressed:
-  Handbook too long → QUICKSTART.md
-  Daily review manual → automated script
-  Vague instructions → specific script + task query
-  No task queue → skill created
2026-04-09 01:10:39 -04:00
James fd27a9d173 Add workflow section: where to find tasks and review process
- Gitea issues location (tea CLI and web UI)
- Priority order (CRITICAL > HIGH > MEDIUM/LOW)
- Engineer workflow (pick up issue → branch → PR → wait for review)
- Reviewer workflow (Yurii, Victoria, Arthur review PRs)
- You merge approved PRs
2026-04-09 01:06:20 -04:00
James d10c3f8e23 Update Yurii CLI docs based on feedback
- Documented monorepo structure (use johan/clavitor, not sub-repos)
- Added --assignees plural flag (not --assignee)
- Added Known Limitations section:
  * Labels don't show in list view (workaround: tea issues view)
  * User discovery is hard (provided valid usernames)
  * 'no gitea login' noise (safe to ignore)
- Added file paths in descriptions (clavis/clavis-telemetry/main.go)
- Added curl command to list labels via API
2026-04-09 00:51:16 -04:00
James 3e9b82af4d Add Yurii's Gitea CLI workflow documentation
- tea CLI installed (/usr/local/bin/tea)
- Login with admin token
- Issue creation commands for audits
- Review workflow for engineer PRs
- Explicit can/cannot do rules
- Complete example session
2026-04-09 00:44:14 -04:00
James 68dcc2f2f4 telemetry: fix Cardinal Rule violations - add unique error codes
Fixes 4 Cardinal Rule violations identified by Yurii audit:

- ERR-TELEMETRY-001/002/003: Fatal error codes for DB init, CA loading, cert verify
- ERR-TELEMETRY-010/011/012/013/014: Database error handling in updateSpan()
- ERR-TELEMETRY-020/021/022: ntfy alert error codes with context
- ERR-TELEMETRY-030/031/032/033: Kuma push error handling (was silent)

Per CLAVITOR-AGENT-HANDBOOK.md Part 1:
- Every error now has unique ERR-TELEMETRY-XXX code
- Database errors in updateSpan() no longer silent
- Kuma push failures now logged (was silent with misleading comment)
- All errors include actionable context

Assignee: Hans
Auditor: Yurii
Refs: issues/001, issues/002, issues/003, issues/004
2026-04-08 18:05:00 -04:00
James 460d56dfb9 Add Shakib (Bangladesh) and Yurii (Russian) to agent personas
- Shakib: QA / Test Engineering — test coverage, regression detection
- Yurii: Code & Principle Review — architecture alignment, PR review
- Shakib triggered by: tests/*, coverage/, *_test.go
- Yurii triggered by: PRs touching security or principles (mandatory review)
- 15 agents total — diverse global roster
2026-04-08 15:37:52 -04:00
James 96f98ef807 Rename mobile agent: Maya → Xiao (晓)
Xiao (Chinese: 晓) means 'dawn/morning' - fitting for mobile.
Distinct from Western names (Sarah, Charles, Maria, James, etc.).
Short, memorable outlier in the agent roster.
2026-04-08 15:30:52 -04:00
James b327d86ee9 Add Maya as dedicated mobile agent
- Added Maya to agent persona table (iOS/Android specialist)
- Updated directory mapping: clavis-android/ios → Maya
- Updated clavis-ios/CLAUDE.md → You are Maya
- Updated clavis-android/CLAUDE.md → You are Maya
- James now focused solely on browser extensions
2026-04-08 15:30:06 -04:00
James 9860a679d4 Update all CLAUDE.md files to reference CLAVITOR-AGENT-HANDBOOK.md
Updated 13 CLAUDE.md files across all subprojects:
- Root CLAUDE.md → Section I (Culture)
- clavis-vault/CLAUDE.md → Section V: clavis-vault (Sarah)
- clavis-cli/CLAUDE.md → Section V: clavis-cli (Charles)
- clavis-chrome/firefox/safari/CLAUDE.md → Section V: Browser extensions (James)
- clavis-crypto/CLAUDE.md → Section V: clavis-crypto (Maria)
- clavis-ios/android/CLAUDE.md → Section V: Mobile (James)
- clavis-telemetry/CLAUDE.md → Section V: clavis-telemetry (Hans)
- clavitor.ai/CLAUDE.md → Section V: clavitor.ai/admin (Emma)
- clavitor.ai/admin/CLAUDE.md → Section V: clavitor.ai/admin (Emma)
- clavis-vault/edition/CLAUDE.md → Section V: clavis-vault (Sarah)

All references now point to the 5-section handbook structure.
2026-04-08 15:24:51 -04:00
James 44aa3df859 Create CLAVITOR-AGENT-HANDBOOK.md with 5 sections
Restructured from CLAVITOR-PRINCIPLES.md (10 parts → 5 sections):
- Section I — Culture (Part 1 + 5 + 6)
- Section II — Security (Part 2)
- Section III — Workflow (Part 4 + 10)
- Section IV — Operations (Part 7 + 8)
- Section V — Subprojects (Part 3 + 9)

No content lost, only reordered with new section headers.
1,515 lines (was 1,472) — 43 lines added for headers.
2026-04-08 15:20:39 -04:00
James 75f16ee05e Add George (market research) to agent personas
- George: Competitive analysis, pricing, positioning, ICP — analytical, curious, business-minded
- Directory mapping: research/*, competitive/*, pricing/*
2026-04-08 14:43:52 -04:00
James c0dbb11393 Add Hans (NOC/Operations) to agent personas
- Hans: Infrastructure, monitoring, POP health, alerts — calm under pressure, systematic, proactive
- Directory mapping: operations/*, monitoring/*, noc/*
2026-04-08 14:43:39 -04:00
James 7cdf9e30db Add Hugo (legal) to agent personas
- Hugo: Compliance, privacy policy, terms, licensing — cautious, precise, risk-aware
- Directory mapping: legal/*, LICENSE*, PRIVACY*
2026-04-08 14:43:08 -04:00
James ca3e92355b Add 'How agents know their name' section to Part 10
- Directory-based auto-detection (clavis-vault = Sarah, etc.)
- Override via user statement or .agent-name file
- Explicit confirmation when uncertain
2026-04-08 14:42:29 -04:00
James 44d43f86f9 Add Luna (design) and Thomas (tech writing) to agent personas
- Luna: UI/UX, CSS, visual systems — aesthetic, user-empathetic
- Thomas: Technical writing, guides, API docs — clear, pedagogical
2026-04-08 14:41:32 -04:00
James f4e85890e7 Update Part 10: Persona-based agent names
- Sarah (vault), Charles (CLI), Maria (crypto), James (extensions)
- Emma (central), Arthur (architecture), Victoria (security)
- Each with specialty and voice characteristics
- Session format: name-YYYYMMDD-NNN
- Release notes read like a team roster
2026-04-08 14:40:56 -04:00
James 2ca963abc0 Add agent naming convention to Part 10
- Use functional names (vault-agent, cli-agent, crypto-agent) not model names
- Added agent identity section to PR template
- Commit signature format: vault-agent <session-id>
- Table mapping subprojects to agent names
2026-04-08 14:40:17 -04:00
James 2fc48d9637 Add agent-authored PR workflow to Part 10
- Agent PR workflow with full context requirements
- PR template for agents with security checklist
- Session ID tracking for audit trail
- Human review requirements for security-critical changes
- Future state: limited auto-merge authority
2026-04-08 14:34:43 -04:00
James 00f21464c3 Add Part 10 — Git workflow
- 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
2026-04-08 13:53:52 -04:00
James 199495cdd8 Add Part 8 (Compliance) and Part 9 (Localization) with user feedback
- F30/F31: Added FIPS 140-3, CGO avoidance, compiler optimizations (Cardinal Rule #3.5)
- F32: Differentiated audit retention: 7 years (paying) vs 90 days (non-paying)
- F33: Noted Zurich central addresses cross-border compliance
- F34: RTL explicitly not a priority
- F35: Form field detection kept unaddressed as core evolving feature
- F36: Already agreed on LLM methodology
2026-04-08 13:52:59 -04:00
James 724f64bda5 Update CLAVITOR-PRINCIPLES.md with all feedback fixes
- Added document version header (F25)
- Added test fixture key material rule with 32x same byte pattern (F21)
- Added LLM-only checks, removed grep emphasis (F26)
- Fixed Section A duplication and renumbered sections
- Fixed 'entire universe' -> 'primary universe' (F28)
- Fixed key tier table formatting (F29)
- Added escalation path with permanent ban rules (F23)
- Added note about master_key/L3/P3 being exceptionally rare terms
- Added Section C for test fixture security
- Created lib/errors.go with event registry and error handling flow
2026-04-08 13:48:54 -04:00
James bec54e9754 pop-sync: main + main_ca updates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:11:08 -04:00
James aada1c6a4e clavitor.ai: oauth, onboarding flow, admin, templates, css
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:11:05 -04:00
James 659caa20b8 clavis-vault: api/lib/cmd updates + drop _old scaffolding
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:10:59 -04:00
James 5cf089a58e Multi-project update: import system, edition system, web UI, CLI, website, POP sync
Vault: importer refactor with mapping-driven parsers, auth.js login flow,
edition system enhancements (commercial features), agent UI fixes,
mTLS improvements, schema and handler updates.

CLI: cvt protocol updates, keystore changes, JS bridge additions.

Website (clavitor.ai): expanded main.go with new routes/templates,
admin panel with Paddle checkout and credentials API.

POP sync: mTLS CA support, command examples.

Marketing: pricing architecture doc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 06:40:40 -04:00
James 2410a2d128 Fix agent creation UI: scope selector + agent widget on main screen
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)
2026-04-02 02:42:35 -04:00
James d3e9f89bc0 Add PUT /api/agents/{id} endpoint for updating agent WL/RL
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.
2026-04-02 02:14:00 -04:00
James c4350a614e Add GUI for editing Agent WL (IP Whitelist) and RL (Rate Limit)
- 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
2026-04-02 01:22:50 -04:00
James a2cfff8ec2 Complete replication implementation with L0/L1 auth (Commercial Only)
Replication now fully functional for Commercial Edition:

Authentication:
- Uses existing vault L0/L1 credentials (same as vault access)
- L0 in X-Clavitor-L0 header (vault ID)
- L1 in X-Clavitor-L1 header (vault encryption key)
- Validated by opening vault DB with L1
- Anti-replay: 5-minute timestamp window

Architecture:
- Primary-only POPs: No config file needed
- Replication POPs (Calgary/Zurich): Config in /etc/clavitor/replication.yaml
- Config has replication.peers list (can be empty for primary-only)
- Event-driven: SignalReplication() on every write

Files added:
- api/replication.go: HTTP handler for incoming replication
- api/routes_commercial.go: Commercial-only route registration
- api/routes_community.go: Community stub
- lib/auth.go: ValidateL0L1() for vault credential validation
- lib/base64.go: Base64URLEncode/Base64URLDecode helpers

Files modified:
- edition/config.go: New config structure with peers list
- edition/edition.go: ReplicationConfig struct with peers
- edition/replication.go: Replicate to all peers, use new config
- edition/backup_mode.go: Removed env var, config-based
- cmd/clavitor/main.go: Load config, nil config = primary-only
- api/routes.go: Call registerCommercialRoutes()

Security:
- L0/L1 auth prevents unauthorized replication
- Timestamp window prevents replay attacks
- Audit alerts on auth failures and rejections
2026-04-02 01:21:20 -04:00
James fa7541bd4d Security review: Replication functionality (Commercial Only)
Comprehensive security audit of event-driven replication.

CRITICAL issues (5):
1. Inter-POP authentication not implemented (stub TODO)
2. Backup-side request authentication missing
3. Backup mode uses env var (should be config-only)
4. No replay attack protection (need nonces + signatures)
5. Weak token validation (only checks existence, not entropy)

HIGH issues (4):
6. HTTPS cert validation concern
7. No audit logging of replication attempts
8. Cascade replication not prevented
9. Information disclosure in error messages

Status: NOT PRODUCTION READY - security TODO stubs present
2026-04-02 01:02:36 -04:00
James 16045d5185 Mandatory config file for commercial replication (no env vars)
Replication is mandatory in Commercial Edition, configured via
/etc/clavitor/replication.yaml (not env vars or CLI flags).

Changes:
- edition/config.go: LoadReplicationConfig() for commercial - validates YAML
- edition/config_community.go: Community stub returning error
- edition/edition.go: Shared ReplicationConfig type with nested structure
- edition/replication.go: Use new nested config (BackupPOP.URL, etc.)
- edition/backup_mode.go: Fix X-Primary-Location header (TODO: add primary_pop to config)
- cmd/clavitor/main.go: Remove replication-* flags, load from /etc/clavitor/replication.yaml
- go.mod/go.sum: Add gopkg.in/yaml.v3 dependency

Config structure:
pop_id: calgary-01
region: north-america
role: primary  # or backup
backup_pop:
  id: zurich-01
  url: https://zurich-01.clavitor.ai
  auth_token_file: /etc/clavitor/replication.key
auth:
  token_file: /etc/clavitor/replication.key

Validation:
- pop_id, region, role are required
- primary role requires backup_pop.id and backup_pop.url
- backup role should NOT have backup_pop configured
- Auth token file must exist

Startup behavior:
- Commercial without config: vault refuses to start
- Community: ignores replication, single-node only

Documentation:
- SPEC-replication-config.md: Full config file design
2026-04-02 00:56:30 -04:00
James 00b7105e18 Event-driven async replication (Commercial Only)
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
2026-04-02 00:51:51 -04:00
James 7fca22b130 Replication v2: Active-Passive with Async Sync (Commercial Only)
Implements Johan's design:
- Primary POP (e.g., Calgary) replicates writes to Backup POP (e.g., Zurich)
- Backup serves READ-ONLY traffic when primary fails
- Same wire format preserved for replication
- Async, non-blocking replication with queue + retry

Database Schema:
- Added replication_dirty BOOLEAN column to entries table
- Index idx_entries_dirty for fast dirty entry lookup
- EntryMarkDirty() - mark entry needing replication
- EntryMarkReplicated() - clear dirty flag on ACK
- EntryListDirty() - get pending entries (fast path)

Commercial-Only Files:
- edition/replication.go - core replication queue/worker
- edition/backup_mode.go - backup mode detection, write rejection
- edition/commercial.go - wire up IsBackupMode, IsBackupRequest

Backup Mode:
- CLAVITOR_BACKUP_MODE env var sets backup mode
- BackupModeMiddleware rejects writes with 503
- X-Primary-Location header tells client where primary is
- IsBackupMode() and IsBackupRequest() edition functions

Community:
- No replication functionality (privacy-first, single-node)
- IsBackupMode() always returns false
- StartReplication() is no-op

Documentation:
- SPEC-replication.md - full design specification
2026-04-02 00:50:20 -04:00
James 53b2770465 Commercial-only replication infrastructure
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.
2026-04-02 00:42:40 -04:00
James 48bf5d8aa0 Security hardening v2: Edition system + 24 security fixes
EDITION SYSTEM (Community/Commercial):
- Add edition/ package with build-time separation
- Community: No telemetry, local logging only, AGPL
- Commercial: Centralized alerting to clavitor.ai, managed POPs
- Build: go build ./cmd/clavitor/ (community) or -tags commercial

SECURITY FIXES (Issues 1-24):
1. L3 field protection in batch import - agents can't overwrite tier 3
2. FQDN lookup caching - 5min TTL prevents DNS DoS
3. IP whitelist race documented and accepted
4. Admin token consumption - accepted UX limitation
5. Type guard now returns 403 (not silent skip)
6. Agents blocked entirely from batch import
7. IP whitelist DB errors return 500 + telemetry
8. L3 protection in upsert
9. DeleteEntry scope check added
10. CreateEntry scope validation for agents
11. SearchEntries audit logging
13. CSP tightened - removed unused tailwind, img-src restricted
15. Backup path validation (isValidVaultName)
17. Request body size limit - 64KB max, binary content blocked
18. WebAuthn auth challenge verification
19. RestoreBackup requires admin auth
20. TOTP scope check (already existed)
21. PRF-only enforcement (no non-PRF fallbacks)
22. Empty scopes documented as quarantine feature
23. Scope format validation with operator alerts
24. DB errors surfaced via edition.AlertOperator()

OPERATOR ALERTS:
- edition.Current.AlertOperator() routes to local logs (community)
- or POSTs to /v1/alerts (commercial)
- Alerts: auth_system_error, data_corruption

NEW DOCUMENTATION:
- edition/CLAUDE.md - full edition system docs
- GIT_WORKFLOW.md - Zurich-only Git policy
2026-04-02 00:36:31 -04:00