From 22fed471f4a0a5842a0dfbe5691d331b4aa21ef4 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Mar 2026 02:03:15 -0400 Subject: [PATCH] Rebrand: dynamic POPs from DB, NOC dashboard, looking glass, terminology overhaul MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- clavitor.com/CLAUDE.md | 59 ++++++++++ clavitor.com/apple-touch-icon.png | Bin 0 -> 408 bytes clavitor.com/clavitor-logo.svg | 4 + clavitor.com/clavitor.db | Bin 45056 -> 65536 bytes clavitor.com/favicon.svg | 7 +- clavitor.com/main.go | 135 ++++++++++++++++++++- clavitor.com/templates/base.tmpl | 5 +- clavitor.com/templates/footer.tmpl | 4 +- clavitor.com/templates/index-v2.tmpl | 4 +- clavitor.com/templates/index.tmpl | 55 ++++----- clavitor.com/templates/install.tmpl | 40 +++---- clavitor.com/templates/noc.tmpl | 155 +++++++++++++++++++++++++ clavitor.com/templates/pricing.tmpl | 4 +- clavitor.com/templates/privacy.tmpl | 4 +- clavitor.com/templates/sources.tmpl | 4 +- clavitor.com/templates/styleguide.tmpl | 2 +- clavitor.com/templates/terms.tmpl | 4 +- 17 files changed, 414 insertions(+), 72 deletions(-) create mode 100644 clavitor.com/CLAUDE.md create mode 100644 clavitor.com/apple-touch-icon.png create mode 100644 clavitor.com/clavitor-logo.svg create mode 100644 clavitor.com/templates/noc.tmpl diff --git a/clavitor.com/CLAUDE.md b/clavitor.com/CLAUDE.md new file mode 100644 index 0000000..96bd6bb --- /dev/null +++ b/clavitor.com/CLAUDE.md @@ -0,0 +1,59 @@ +# Clavitor Website — clavitor.com + +## Architecture +- Go web server (`main.go`) with `go:embed` for templates, CSS, SVGs, PNGs +- Templates in `templates/*.tmpl`, single CSS in `clavitor.css` +- SQLite DB: `clavitor.db` (pops, telemetry, uptime, incidents, accounts, vaults, sessions) +- Dev mode: auto-detected when `templates/` dir exists on disk — reloads templates per request, but CSS/SVGs require rebuild (`go:embed`) +- Port 8099 + +## Build & Run +``` +CGO_ENABLED=1 go build -o clavitor-web . +./clavitor-web +``` +CSS and SVG changes require rebuild (embedded at compile time). Template changes reload in dev mode. + +## Brand & Design +- Light mode only. Single source of truth: `clavitor.css` +- Logo: the black square (`#0A0A0A`). favicon.svg = black square +- Colors: black `#0A0A0A` (brand), red `#DC2626` (accent), light red `#F5B7B7` (planned/secondary), grayscale +- No purple. No green (except inherited SVG diagrams). Red is the only accent. +- Square shapes for permanent UI elements. Circles only for transient animations (pulses, "You" dot) +- Fonts: Figtree (body), JetBrains Mono (code/monospace) +- No inline styles, no CSS in templates. Everything in clavitor.css. + +## Encryption Terminology +- **Vault Encryption** — whole vault at rest +- **Credential Encryption** — per-field, server-side (AI agents can read via MCP) +- **Identity Encryption** — per-field, client-side via WebAuthn PRF (Touch ID only, server cannot decrypt) +- Never use "sealed fields", "agent fields", "L1", "L2", "L3" + +## POPs (Points of Presence) +- Stored in `pops` table in clavitor.db — the single source of truth +- Map on /hosted is generated dynamically from DB via JavaScript +- Zürich = HQ, black dot, larger (11×11). Live POPs = red. Planned = light red. +- "You" visitor dot = circle (not square — "you" is not clavitor) + +## Key URLs +- `/hosted` — hosted product page with dynamic world map +- `/glass` — looking glass (latency from user's browser) +- `/noc?pin=250365` — NOC dashboard (telemetry, read-only, hardcoded PIN) +- `/telemetry` — POST endpoint for POP agent heartbeats (no auth) +- `/ping` — server-side TCP ping (for diagnostics) + +## Vault Binary +- Source: `~/dev/clavitor/clovis/clovis-vault/` +- Build for ARM64: `cd ~/dev/clavitor/clovis/clovis-vault && GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o clavitor-linux-arm64 ./cmd/clavitor` +- All POPs are ARM64 (AWS t4g.micro) +- Vault runs on port 1984 with TLS +- Has `/ping` endpoint (11 bytes, no DB, CORS via middleware) for looking glass +- Has `/health` endpoint (heavier, queries DB) + +## Providers +- AWS: most POPs (free tier t4g.micro) +- LightNode: Santiago, Bogotá, Manila, Dhaka +- ishosting: Istanbul, Almaty +- HostAfrica: Lagos, Nairobi +- Voyager NZ → switched to AWS for Auckland +- Rackmill: Perth diff --git a/clavitor.com/apple-touch-icon.png b/clavitor.com/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e8860ec29c6cde688e685daa4bc6de75f6f43cf2 GIT binary patch literal 408 zcmeAS@N?(olHy`uVBq!ia0vp^TR@nD1xQXma&9M(Qb_g)@?~JCQe$9fXklRZ1r%y{ z!N5>zz`*b-fq}tl1_Oh5!JJ)zHb4ocByV>Y28LC=%0@sQdx@v7EBh;ENmgzykpQOs zK%tMGE{-7;x87b*WgFv$RUc)Jn^vE?ZMpA% z#Bsao1MwWPf>uf;E-yMR2rg81a&PGy6avgZ?+^lO9 + Clavitor + + diff --git a/clavitor.com/clavitor.db b/clavitor.com/clavitor.db index ff3b82297063092b1d9e2ff3954e982c51cfc15c..0b4d3e548e80d76f39503ce700f15f90d0f650c9 100644 GIT binary patch delta 3222 zcma)7YiJu+79PcpB}~ zj2s-&I!f9sT{ciLEY!}crO+P>-9EBx7s^6^6uKr3&XG;_-QPnKF*H0u;|LGxcekV?ou&w zFZn6{C*tqkPw-!OzV+U8xw;>8{?_C0eAIDsm->F~8^?uf{iM?$i8!tcI>;9#SrKGW zQuJK4A_85~+W+^YvzgR`Q$EiA1S4}v4=vR;(_pOm)A2=V!7I7(TRa>Cgy;?mA>iB(bU4sd~j6L)q*aUq|wlb78(yJFR3phj$a|<~Br4qC~ASnkk#Lv{SS(z{fTqRY{QK6)R!Wa7)pDJZlT}ill0C zS=k)Pxa{fOW7D!!)^r7w5T8cHb0BSRS1X8yoF)ln1yT8E&M2GSN;OxJQ~@g9@OgUI zf{pC#^O965tE)M^tb<~%l;7E*eW9vB3XuJd8HlpB-1PqfLi|X^?3~OS4+HFcp;!iD zjxGg_f4TQ2(JVi z!A!&|Ego`*uPfb7e_x;DCzJOV+#8PB@nA(QufRE_S`us&4K__sRJ5&|vI3`tBA^Cq zKMWfWy0e|0Z?Iq2YaguD;$EkJV8C(hgxNBdo~&oA8Uw85 z$oMJl;X`GpNT5UggQBhLQ`r-CvEPdgKzAefppy+4KfHc)P1ev@ zla-6-2EAseVe@Qy2`qyn(^K(3p!LV8GwWz=fJ#IwSM{X`Qz-&Pk;JKy1^7Qi{e!fjiAcPq5XvhdLI%zl$S2aE*Sn+1wo1gDNqMObsKHn@?1 zrbqY&KSN)-pQ^m|Wh+04i5TQ3+2qIdZ!A-eXntI-HA7= z`6v&y!6qP^@rK}#FodOc8X1ZL$$TD2g21qJo|@g~ zHM=YAWTt=DFVxxE%eHpPjJNp$M@Id-s~8X{lnB}`E@I`jHQ$m&cQ zwh{UyT5|!__FN>M5fcecgld*}HU>`mERjMXqFjb)-E;QzoX4uP&F*KnCsDhcbZ_GPu{$Q`#y~7wf%Mf=;>zT F{{gfVbm9O2 delta 664 zcmYk4&1=(O9LJy3YVzcHe#x>nwywyib1kvHAOSr%H&oWt)QJ<6;Y}1#)T?iZ6coXO zVEJ{%wM$no9ux%EyBAl)zrcfs=}Ek3@nlc>B#(OuW zu03jfubWSj{kNWg`G@FqK+LrH5xyAT`3k°0Ih(m~f6x=V3D&*~3%Q8i=R%Hv{p zSZgYZ)9o|s(P8*OvRa3j%jPB1HhRW=!__+Q66V0SANDr0%}xy-nZyh6jTb%w`$cA+F=`wKrdenT+He$Z0Mn zg5z*WP}niSeY;2YnNxrlfg{eQp*bj8})Hn*+9n z*KrT#8yWB{N#^6w^Q{T)4@oRi@O`U*cUmLhnT+Jto16LUj{0mP&&Abn3Os#trvvQ??ok;(9#yX_6yoY- zO=8mWQ~OBt6ZrLdnS0w9$;WL4{u3qcZQVSfzbGf1PBJnkP+8PoIsvD)$UaiJwsefo kBp50FACEU04qgdUxG&V0!boW?=E3t))M~l&*Hp6q0P~%X0RR91 diff --git a/clavitor.com/favicon.svg b/clavitor.com/favicon.svg index 92d2303..ecb96fe 100644 --- a/clavitor.com/favicon.svg +++ b/clavitor.com/favicon.svg @@ -1,5 +1,4 @@ - - - v - 84 + + Clavitor + diff --git a/clavitor.com/main.go b/clavitor.com/main.go index 5649ebb..c2b1b2f 100644 --- a/clavitor.com/main.go +++ b/clavitor.com/main.go @@ -3,6 +3,7 @@ package main import ( "database/sql" "embed" + "encoding/json" "fmt" "html/template" "io" @@ -20,7 +21,7 @@ import ( //go:embed templates/*.tmpl var tmplFS embed.FS -//go:embed *.svg *.css +//go:embed *.svg *.css *.png var static embed.FS var templates *template.Template @@ -115,7 +116,7 @@ func main() { loadTemplates() var err error - db, err = sql.Open("sqlite3", "clavitor.db?mode=ro") + db, err = sql.Open("sqlite3", "clavitor.db") if err != nil { log.Fatalf("failed to open clavitor.db: %v", err) } @@ -170,6 +171,136 @@ func main() { http.HandleFunc("/styleguide", func(w http.ResponseWriter, r *http.Request) { render(w, PageData{Page: "styleguide", Title: "clavitor — Styleguide"}) }) + // NOC telemetry ingest — agents POST here + http.HandleFunc("/telemetry", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "POST" { + w.WriteHeader(405) + return + } + var t struct { + NodeID string `json:"node_id"` + Version string `json:"version"` + Hostname string `json:"hostname"` + UptimeSeconds int64 `json:"uptime_seconds"` + CPUPercent float64 `json:"cpu_percent"` + MemTotalMB int64 `json:"memory_total_mb"` + MemUsedMB int64 `json:"memory_used_mb"` + DiskTotalMB int64 `json:"disk_total_mb"` + DiskUsedMB int64 `json:"disk_used_mb"` + Load1m float64 `json:"load_1m"` + VaultCount int `json:"vault_count"` + VaultSizeMB float64 `json:"vault_size_mb"` + VaultEntries int `json:"vault_entries"` + Mode string `json:"mode"` + } + if err := json.NewDecoder(r.Body).Decode(&t); err != nil || t.NodeID == "" { + http.Error(w, `{"error":"bad payload"}`, 400) + return + } + db.Exec(`INSERT INTO telemetry (node_id, version, hostname, uptime_seconds, cpu_percent, memory_total_mb, memory_used_mb, disk_total_mb, disk_used_mb, load_1m, vault_count, vault_size_mb, vault_entries, mode) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, + t.NodeID, t.Version, t.Hostname, t.UptimeSeconds, t.CPUPercent, t.MemTotalMB, t.MemUsedMB, t.DiskTotalMB, t.DiskUsedMB, t.Load1m, t.VaultCount, t.VaultSizeMB, t.VaultEntries, t.Mode) + // Update daily uptime + today := time.Now().Format("2006-01-02") + db.Exec(`INSERT OR REPLACE INTO uptime (node_id, date, status) VALUES (?, ?, 'operational')`, t.NodeID, today) + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(`{"ok":true}`)) + }) + + // NOC API — latest telemetry per node + nocPin := func(r *http.Request) bool { return r.URL.Query().Get("pin") == "250365" } + + http.HandleFunc("/noc/api/telemetry", func(w http.ResponseWriter, r *http.Request) { + if !nocPin(r) { http.NotFound(w, r); return } + rows, err := db.Query(`SELECT t.node_id, t.received_at, t.version, t.hostname, t.uptime_seconds, t.cpu_percent, t.memory_total_mb, t.memory_used_mb, t.disk_total_mb, t.disk_used_mb, t.load_1m, t.vault_count, t.vault_size_mb, t.vault_entries, t.mode FROM telemetry t INNER JOIN (SELECT node_id, MAX(id) as max_id FROM telemetry GROUP BY node_id) latest ON t.id = latest.max_id`) + if err != nil { + http.Error(w, `{"error":"query failed"}`, 500) + return + } + defer rows.Close() + type Tel struct { + NodeID string `json:"node_id"` + ReceivedAt int64 `json:"received_at"` + Version string `json:"version"` + Hostname string `json:"hostname"` + UptimeSec int64 `json:"uptime_seconds"` + CPU float64 `json:"cpu_percent"` + MemTotal int64 `json:"memory_total_mb"` + MemUsed int64 `json:"memory_used_mb"` + DiskTotal int64 `json:"disk_total_mb"` + DiskUsed int64 `json:"disk_used_mb"` + Load1m float64 `json:"load_1m"` + VaultCount int `json:"vault_count"` + VaultSizeMB float64 `json:"vault_size_mb"` + VaultEntries int `json:"vault_entries"` + Mode string `json:"mode"` + } + var list []Tel + for rows.Next() { + var t Tel + rows.Scan(&t.NodeID, &t.ReceivedAt, &t.Version, &t.Hostname, &t.UptimeSec, &t.CPU, &t.MemTotal, &t.MemUsed, &t.DiskTotal, &t.DiskUsed, &t.Load1m, &t.VaultCount, &t.VaultSizeMB, &t.VaultEntries, &t.Mode) + list = append(list, t) + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]any{"telemetry": list}) + }) + + http.HandleFunc("/noc/api/nodes", func(w http.ResponseWriter, r *http.Request) { + if !nocPin(r) { http.NotFound(w, r); return } + pops := loadPops() + type N struct { + ID string `json:"ID"` + Status string `json:"Status"` + } + var nodes []N + for _, p := range pops { + nodes = append(nodes, N{ID: p.City, Status: p.Status}) + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]any{"nodes": nodes}) + }) + + http.HandleFunc("/noc/api/telemetry/history", func(w http.ResponseWriter, r *http.Request) { + if !nocPin(r) { http.NotFound(w, r); return } + node := r.URL.Query().Get("node") + limit := r.URL.Query().Get("limit") + if limit == "" { limit = "60" } + rows, err := db.Query(`SELECT received_at, cpu_percent, memory_used_mb, memory_total_mb FROM telemetry WHERE node_id = ? ORDER BY id DESC LIMIT ?`, node, limit) + if err != nil { + http.Error(w, `{"error":"query failed"}`, 500) + return + } + defer rows.Close() + type H struct { + TS int64 `json:"ts"` + CPU float64 `json:"cpu"` + MemUsed int64 `json:"mem_used_mb"` + MemTotal int64 `json:"mem_total_mb"` + } + var hist []H + for rows.Next() { + var h H + rows.Scan(&h.TS, &h.CPU, &h.MemUsed, &h.MemTotal) + hist = append(hist, h) + } + // Reverse so oldest first + for i, j := 0, len(hist)-1; i < j; i, j = i+1, j-1 { + hist[i], hist[j] = hist[j], hist[i] + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]any{"history": hist}) + }) + + // NOC dashboard — hardcoded PIN, read-only, not a security boundary + http.HandleFunc("/noc", func(w http.ResponseWriter, r *http.Request) { + if r.URL.Query().Get("pin") != "250365" { + http.NotFound(w, r) + return + } + data := PageData{Page: "noc", Title: "NOC — clavitor"} + data.Pops = loadPops() + render(w, data) + }) + http.HandleFunc("/glass", func(w http.ResponseWriter, r *http.Request) { data := PageData{Page: "glass", Title: "Looking Glass — clavitor"} data.Pops = loadPops() diff --git a/clavitor.com/templates/base.tmpl b/clavitor.com/templates/base.tmpl index d65f83f..085ce95 100644 --- a/clavitor.com/templates/base.tmpl +++ b/clavitor.com/templates/base.tmpl @@ -6,6 +6,7 @@ {{.Title}} {{if .Desc}}{{end}} + @@ -18,7 +19,7 @@ diff --git a/clavitor.com/templates/index.tmpl b/clavitor.com/templates/index.tmpl index 1247065..2b7cac0 100644 --- a/clavitor.com/templates/index.tmpl +++ b/clavitor.com/templates/index.tmpl @@ -135,7 +135,7 @@
Credential Encryption

AI-readable

-

Encrypted at rest, decryptable by the vault server. Your AI agent reads these via MCP.

+

Encrypted at rest, decryptable by the vault server. Your AI agent accesses these via the CLI.

  • API keys & tokens
  • SSH keys
  • @@ -179,12 +179,12 @@

    AI-powered 2FA

    -

    Store TOTP secrets as Credential fields. Your AI generates time-based codes on demand via MCP — no more switching to your phone.

    +

    Store TOTP secrets as Credential fields. Your AI generates time-based codes on demand via the CLI — no more switching to your phone.

    -

    Scoped MCP tokens

    -

    Create separate MCP tokens per agent. Each token sees only its designated entries. Compromise one, the rest stay clean.

    +

    Scoped agent tokens

    +

    Create separate tokens per agent. Each token sees only its designated entries. Compromise one, the rest stay clean.

    @@ -201,26 +201,22 @@
    - +

    10 agents.
    Each gets exactly what it needs.

    -

    Create scoped MCP tokens per agent. One compromised agent exposes one scope — not your entire vault.

    +

    Create scoped CLI tokens per agent. One compromised agent exposes one scope — not your entire vault.

    +

    Why not MCP? Because MCP gives the agent access to the vault — search, list, browse. That's too much. Clavitor's CLI gives the agent exactly the credentials it's scoped to. Nothing more. No browsing, no discovery, no surprise access.

    -

    ~/.claude/mcp.json

    -
    {
    -  "mcpServers": {
    -    "vault-dev": {
    -      "url": "http://localhost:1984/mcp",
    -      "headers": { "Authorization": "Bearer mcp_dev_a3f8..." }
    -    },
    -    "vault-social": {
    -      "url": "http://localhost:1984/mcp",
    -      "headers": { "Authorization": "Bearer mcp_social_7b2e..." }
    -    }
    -  }
    -}
    +

    Agent workflow

    +
    # Agent fetches credential — encrypted, never plaintext
    +$ clavitor get github.token --agent dev --format env
    +GITHUB_TOKEN=ghp_a3f8...
    +
    +# Scoped: dev agent can't see social credentials
    +$ clavitor get twitter.oauth --agent dev
    +Error: access denied (scope: dev)
    @@ -289,9 +285,9 @@

    Four ways in. Each one designed for a different context. All pointing at the same encrypted store.

    -

    MCP

    +

    CLI

    For AI agents

    -

    Claude, GPT, or any MCP-compatible agent can search credentials, fetch API keys, and generate 2FA codes — scoped to exactly what you allow.

    +

    Agents call the CLI to fetch credentials — scoped per agent. Each agent sees only what it's been granted. No vault browsing, no discovery.

    Extension

    @@ -415,15 +411,14 @@
    # Running on http://localhost:1984
    -

    MCP config for Claude Code / Cursor / Codex

    -
    {
    -  "mcpServers": {
    -    "clavitor": {
    -      "url": "http://localhost:1984/mcp",
    -      "headers": { "Authorization": "Bearer mcp_your_token_here" }
    -    }
    -  }
    -}
    +

    Agent access — scoped, encrypted

    +
    # Create a scoped token for your deploy agent
    +$ clavitor token create --scope deploy --name "CI pipeline"
    +Token: ctk_deploy_9f2a...
    +
    +# Agent fetches only what it's scoped to
    +$ clavitor get vercel.token --agent deploy
    +VERCEL_TOKEN=tV3r...

    Full install guide →

    diff --git a/clavitor.com/templates/install.tmpl b/clavitor.com/templates/install.tmpl index f0e3383..e1f311c 100644 --- a/clavitor.com/templates/install.tmpl +++ b/clavitor.com/templates/install.tmpl @@ -2,8 +2,8 @@ {{define "install"}}
    -

    Open source · MIT

    -

    Self-host clavitor

    +

    Open source · Elastic License 2.0

    +

    Self-host Clavitor

    One binary. No Docker. No Postgres. No Redis. Runs anywhere Go runs. You'll need a server with a public IP, DNS, and TLS if you want access from outside your network.

    @@ -19,9 +19,9 @@
    $ curl -fsSL clavitor.com/install.sh | sh

    Or download directly:

    @@ -47,7 +47,7 @@

    A SQLite database is created automatically in ~/.clavitor/.

    $ clavitor
    -
    clavitor running on http://localhost:1984
    +
    Clavitor running on http://localhost:1984
    Database: ~/.clavitor/vault.db
    @@ -56,20 +56,16 @@
    4
    -

    Configure MCP

    -

    Point your AI assistant at the vault. Works with Claude Code, Cursor, Codex, or any MCP-compatible client.

    -

    ~/.claude/mcp.json

    -
    {
    -  "mcpServers": {
    -    "clavitor": {
    -      "url": "http://localhost:1984/mcp",
    -      "headers": {
    -        "Authorization": "Bearer YOUR_MCP_TOKEN"
    -      }
    -    }
    -  }
    -}
    -

    Generate an MCP token from the web UI at http://localhost:1984 after first run.

    +

    Configure agent access

    +

    Create a scoped token for each AI agent. Agents use the CLI to fetch credentials — encrypted in transit, never exposed in plaintext.

    +
    +
    # Create a scoped agent token
    +
    $ clavitor token create --scope dev --name "Claude Code"
    +
    Token: ctk_dev_a3f8...
    +
    # Agent fetches credentials via CLI
    +
    $ clavitor get github.token --agent dev
    +
    +

    Manage tokens from the web UI at http://localhost:1984 after first run.

    @@ -90,7 +86,7 @@

    Run as a service

    -

    For always-on availability, run clavitor as a systemd service.

    +

    For always-on availability, run Clavitor as a systemd service.

    /etc/systemd/system/clavitor.service

    [Unit]
     Description=clavitor
    @@ -109,7 +105,7 @@ WantedBy=multi-user.target
    $ sudo systemctl enable --now clavitor

    Expose to the internet

    -

    Put clavitor behind Caddy for TLS and remote access.

    +

    Put Clavitor behind Caddy for TLS and remote access.

    Caddyfile

    vault.yourdomain.com {
         reverse_proxy localhost:1984
    diff --git a/clavitor.com/templates/noc.tmpl b/clavitor.com/templates/noc.tmpl
    new file mode 100644
    index 0000000..5ddd52f
    --- /dev/null
    +++ b/clavitor.com/templates/noc.tmpl
    @@ -0,0 +1,155 @@
    +{{define "noc"}}
    +
    +

    Network Operations

    +

    Clavitor NOC

    +

    Real-time telemetry from {{len .Pops}} points of presence.

    +
    + +
    + +
    +
    +
    Nodes reporting
    +
    Avg CPU
    +
    Avg Mem
    +
    Total Vaults
    +
    + +
    +

    Loading...

    +
    +{{end}} + +{{define "noc-script"}} + +{{end}} diff --git a/clavitor.com/templates/pricing.tmpl b/clavitor.com/templates/pricing.tmpl index 248c951..78167ce 100644 --- a/clavitor.com/templates/pricing.tmpl +++ b/clavitor.com/templates/pricing.tmpl @@ -13,10 +13,10 @@

    Self-hosted

    Free
    -

    Forever. MIT license. No strings.

    +

    Forever. Elastic License 2.0. No strings.

    Self-host guide →

    What you get

    -
    • Three-tier encryption (Vault, Credential, Identity)
    • WebAuthn PRF (Identity biometric encryption)
    • MCP server for AI agents
    • Scoped MCP tokens (multi-agent)
    • TOTP generation via MCP
    • Browser extension (Chrome, Firefox)
    • Import from Bitwarden / 1Password
    • LLM-powered field classification
    • Unlimited entries
    • Full source code (MIT)
    +
    • Three-tier encryption (Vault, Credential, Identity)
    • WebAuthn PRF (Identity biometric encryption)
    • CLI for AI agents (encrypted delivery)
    • Scoped agent tokens (multi-agent)
    • TOTP generation via CLI
    • Browser extension (Chrome, Firefox)
    • Import from Bitwarden / 1Password
    • LLM-powered field classification
    • Unlimited entries
    • Full source code (ELv2)

What this policy covers

-

This privacy policy applies to the hosted clavitor service at clavitor.com. If you self-host clavitor, your data never touches our servers and this policy doesn't apply to you — your privacy is entirely in your own hands.

+

This privacy policy applies to the hosted Clavitor service at clavitor.com. If you self-host Clavitor, your data never touches our servers and this policy doesn't apply to you — your privacy is entirely in your own hands.

Data we store

-

When you use hosted clavitor, we store:

+

When you use hosted Clavitor, we store:

  • Account information: email address and authentication credentials
  • Credential fields: encrypted at rest with AES-256-GCM using your vault key
  • diff --git a/clavitor.com/templates/sources.tmpl b/clavitor.com/templates/sources.tmpl index b2ad2ef..b638135 100644 --- a/clavitor.com/templates/sources.tmpl +++ b/clavitor.com/templates/sources.tmpl @@ -11,7 +11,7 @@
    -

    "I tried giving Claude access to 1Password and it immediately wanted to read my credit card details. That's not what I wanted. clavitor is the only thing that solves this properly."

    +

    "I tried giving Claude access to 1Password and it immediately wanted to read my credit card details. That's not what I wanted. Clavitor is the only thing that solves this properly."

    @devrel_mike · X · 2024

    @@ -26,7 +26,7 @@
    -

    "clavitor LLM field mapping matches by intent. Entries are indexed by URL — the right credential for the right site, every time."

    +

    "Clavitor LLM field mapping matches by intent. Entries are indexed by URL — the right credential for the right site, every time."

    @jolaneti11 · X · 2024

    diff --git a/clavitor.com/templates/styleguide.tmpl b/clavitor.com/templates/styleguide.tmpl index 8c81c3c..ea6dfca 100644 --- a/clavitor.com/templates/styleguide.tmpl +++ b/clavitor.com/templates/styleguide.tmpl @@ -13,7 +13,7 @@

    Design System

    -

    clavitor Styleguide

    +

    Clavitor Styleguide

    Single source of truth. One stylesheet: clavitor.css. No inline styles in HTML.

    diff --git a/clavitor.com/templates/terms.tmpl b/clavitor.com/templates/terms.tmpl index 7a3067d..9210a83 100644 --- a/clavitor.com/templates/terms.tmpl +++ b/clavitor.com/templates/terms.tmpl @@ -11,10 +11,10 @@

    1. Acceptance

    -

    By using clavitor (the "Service"), you agree to these terms. If you don't agree, don't use the Service.

    +

    By using Clavitor (the "Service"), you agree to these terms. If you don't agree, don't use the Service.

    2. Description

    -

    clavitor is a password manager with three-tier encryption: Vault Encryption (at rest), Credential Encryption (per-field, server-side), and Identity Encryption (per-field, client-side). The hosted service stores encrypted vault data on your behalf. The self-hosted version (MIT licensed) runs entirely on your own infrastructure.

    +

    Clavitor is a password manager with three-tier encryption: Vault Encryption (at rest), Credential Encryption (per-field, server-side), and Identity Encryption (per-field, client-side). The hosted service stores encrypted vault data on your behalf. The self-hosted version (Elastic License 2.0) runs entirely on your own infrastructure.

    3. Accounts

    You are responsible for maintaining the security of your account credentials and authenticator device. We cannot recover Identity fields if you lose access to your WebAuthn authenticator — the mathematical design prevents it.