clavitor/clavis/clavis-vault/edition/CLAUDE.md

6.2 KiB

Clavitor Edition System

Required reading before any work: CLAVITOR-AGENT-HANDBOOK.md — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: clavis-vault (this subproject). You are Sarah. Commercial-only code MUST be behind build tags so community builds cannot accidentally activate it.

This directory implements build-time differentiation between Community (OSS) and Commercial (hosted) editions of Clavitor Vault.

Architecture

edition/
├── edition.go       # Interface definition (build-agnostic)
├── community.go     # Community Edition (default, !commercial build tag)
└── commercial.go    # Commercial Edition (commercial build tag)

Build Instructions

Community Edition (Default)

# Self-hosted, no telemetry, Elastic 2
go build -o clavitor ./cmd/clavitor/

Commercial Edition

# Managed by clavitor.ai, telemetry enabled, SCIM/SIEM support
go build -tags commercial -o clavitor ./cmd/clavitor/

Key Differences

Feature Community Commercial
Telemetry Manual opt-in via CLI flags Enabled by default, centralized
Operator Alerts Local logs only POSTs to /v1/alerts endpoint
Replication Not available Real-time sync to backup POPs (Calgary/Zurich)
Tarpit Not available (simple 404) 30s connection drain (anti-scanner)
Central Management None Multi-POP dashboard at clavitor.ai
SCIM/SIEM No Yes
License Elastic License 2.0 Commercial license

Commercial-Only Features

The following features are only available in Commercial Edition and do not exist in Community code:

1. Real-Time Replication to Backup POPs

Build constraint: //go:build commercial

Background replicator that:

  • Polls EntryListUnreplicated() every 30 seconds
  • POSTs encrypted entry blobs to backup POP (Calgary or Zurich)
  • Automatic retry with exponential backoff (max 5 retries)
  • Batching for efficiency (up to 100 entries per request)
  • Conflict resolution: last-write-wins by timestamp
  • Automatic failover: primary → backup POP switching

Community behavior: No replication code. ReplicatedAt field exists in DB schema (for future compatibility) but is never populated or read.

2. Multi-POP Failover

Commercial POPs register with the control plane. If primary POP fails, DNS routes to backup within 60 seconds.

3. Centralized Audit Log Aggregation

All operator alerts across all POPs feed into central dashboard at clavitor.ai.

4. Tarpit (Anti-Scanner Defense)

Build constraint: //go:build commercial

Commercial edition includes a "tarpit" handler for 404/405 responses that:

  • Holds unrecognized requests for 30 seconds
  • Drips one byte per second to keep connection alive
  • Wastes scanner/bot resources (automated tools timeout waiting)
  • Capped at 1000 concurrent connections (drops excess immediately)
  • Interruptible on shutdown — checks edition.ShutdownContext each second

Community behavior: Simple 404/405 responses. Fast, user-friendly, immediate shutdown.

Why this is commercial-only:

  • Self-hosted users (community) don't need anti-scanner defense
  • Tarpit complicates shutdown (needs context cancellation)
  • Enterprise (commercial) faces more automated attacks

Usage in Code

Sending Operator Alerts

// Always use edition.Current.AlertOperator() instead of log.Printf
edition.Current.AlertOperator(ctx, "auth_error", "message", map[string]any{
    "key": "value",
})

Community behavior: Logs to stderr with OPERATOR ALERT [type]: message prefix.

Commercial behavior: Logs locally + POSTs JSON to {TelemetryHost}/v1/alerts.

Checking Edition

if edition.Current.Name() == "commercial" {
    // Commercial-only features
}

if edition.Current.IsTelemetryEnabled() {
    // Telemetry is active (commercial always, community if configured)
}

Commercial Configuration

Only valid for commercial builds. Community builds log a warning if called.

edition.SetCommercialConfig(&edition.CommercialConfig{
    TelemetryHost:  "https://hq.clavitor.com",
    TelemetryToken: "bearer-token",
    TelemetryFreq:  300, // 5 minutes
    POPRegion:      "us-east-1",
})

// Start periodic telemetry reporting
ctx := context.Background()
edition.StartTelemetry(ctx)

Environment Variables (Commercial)

Variable Purpose
TELEMETRY_HOST Base URL for telemetry (e.g., https://hq.clavitor.com)
TELEMETRY_TOKEN Bearer token for authentication
TELEMETRY_FREQ Seconds between POSTs (default: 300)
POP_REGION POP identifier for dashboards

Alert Endpoint (Commercial)

Commercial builds POST to:

POST {TelemetryHost}/v1/alerts
Authorization: Bearer {TelemetryToken}
Content-Type: application/json

Payload:

{
  "edition": "commercial",
  "type": "auth_system_error",
  "message": "Agent lookup failed",
  "details": {"error": "..."},
  "hostname": "pop-us-east-1-03",
  "pop_region": "us-east-1",
  "timestamp": "2026-04-02T00:11:45Z"
}

Handling 404/Method Not Allowed

The router uses edition-specific handlers for unmatched routes:

notFoundHandler := edition.Current.NotFoundHandler()
r.NotFound(notFoundHandler)
r.MethodNotAllowed(notFoundHandler)

Community: Returns simple 404. Fast shutdown, no resource waste.

Commercial: Tarpit handler holds connections for 30s (anti-scanner), but exits immediately on edition.ShutdownContext cancellation.

Important Notes for Opus

  1. Never remove the build tags — they're essential for the dual-license model.
  2. Always use edition.Current — don't branch on build tags in application code.
  3. Community is default — if someone builds without tags, they get OSS edition.
  4. Commercial config is optional — commercial builds work without telemetry (just logs).
  5. Telemetry is separate — the old lib/telemetry.go still exists for community opt-in.

Testing

# Test community
go test ./edition/...

# Test commercial
go test -tags commercial ./edition/...

# Build both
go build ./cmd/clavitor/ && go build -tags commercial ./cmd/clavitor/