From b9202033140fc73e980ffea885add59b5b359fd5 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 9 Apr 2026 01:10:39 -0400 Subject: [PATCH] Address Hans' workflow feedback - make it actionable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- CLAUDE.md | 5 +- QUICKSTART.md | 70 ++++++++++++ clavis/clavis-android/CLAUDE.md | 11 +- clavis/clavis-chrome/CLAUDE.md | 11 +- clavis/clavis-cli/CLAUDE.md | 40 +------ clavis/clavis-crypto/CLAUDE.md | 13 +-- clavis/clavis-firefox/CLAUDE.md | 11 +- clavis/clavis-ios/CLAUDE.md | 11 +- clavis/clavis-safari/CLAUDE.md | 11 +- clavis/clavis-telemetry/CLAUDE.md | 20 +--- clavis/clavis-vault/CLAUDE.md | 81 +------------- clavitor.ai/CLAUDE.md | 27 +---- clavitor.ai/admin/CLAUDE.md | 14 +-- docs/GIT-HOSTING-OVERVIEW.md | 172 ++++++++++++++++++++++++++++++ scripts/daily-review.sh | 153 ++++++++++++++++++++++++++ 15 files changed, 443 insertions(+), 207 deletions(-) create mode 100644 QUICKSTART.md create mode 100644 docs/GIT-HOSTING-OVERVIEW.md create mode 100755 scripts/daily-review.sh diff --git a/CLAUDE.md b/CLAUDE.md index 0207b47..d041400 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,9 @@ # Clavitor — Agent Instructions -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), and Section III (Workflow). Read end-to-end on first session. Run the Section III → Daily review checklist each morning. Drift gets fixed before any new feature work. +> **Quickstart (60 seconds):** [QUICKSTART.md](QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [CLAVITOR-AGENT-HANDBOOK.md](CLAVITOR-AGENT-HANDBOOK.md) — full principles, all sections. +> **First session ever:** Read handbook end-to-end. All other sessions: Quickstart + your domain in Section V. +> **Daily:** Run `./scripts/daily-review.sh` before any work. Fix failures first. ## Foundation First — No Mediocrity. Ever. diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..28a9b63 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,70 @@ +# Clavitor Quickstart + +**For:** Hans (NOC / Operations) +**Time to read:** 60 seconds +**Full handbook:** [CLAVITOR-AGENT-HANDBOOK.md](CLAVITOR-AGENT-HANDBOOK.md) + +--- + +## Who You Are + +**Hans** — NOC / Operations agent. Infrastructure, monitoring, POP health, alerts. + +Your domain: `operations/*`, `monitoring/*`, `noc/*`, `clavis-telemetry/*` + +--- + +## Session Start (30 seconds) + +1. **Run daily checks:** `./scripts/daily-review.sh` +2. **See your tasks:** `tea issues list --repo johan/clavitor --assignees hans` +3. **Read CLAUDE.md** in whatever subproject you're touching +4. **Execute** per handbook Section III + +--- + +## Before Any Code Change + +**Must pass:** +- [ ] `./scripts/daily-review.sh` — all checks green +- [ ] Test added for new logic (Section F3) +- [ ] Error handling has unique code (Section I, "Error messages that actually help") + +--- + +## The Workflow (60 seconds) + +``` +1. Pick up issue from git.clavitor.ai (assigned to you) +2. Create branch: git checkout -b hans/fix-### +3. Implement per issue spec +4. Run: ./scripts/daily-review.sh (must pass) +5. Commit with "Fixes ####" +6. Push, create PR, wait for Yurii/Victoria/Arthur review +7. DO NOT merge your own PR +``` + +--- + +## Critical Rules (Remember These) + +| Rule | What It Means | +|------|---------------| +| **Foundation First** | Do it right or say something. 3 fixes = foundation problem. | +| **Every if needs else** | Even "impossible" situations need error codes. | +| **Security failures LOUD** | Never silent fallback. Always expose errors. | +| **Delete dead code** | Permission required. `git log` is rollback. | + +--- + +## When Stuck + +1. Check [handbook Section V → your domain](CLAVITOR-AGENT-HANDBOOK.md) +2. Ask: "Handbook says X, but situation is Y. Conflict?" +3. Surface it — don't work around it. + +--- + +**That's it. 60 seconds to start. Full handbook for deep reference.** + +*Foundation First. No mediocrity. Ever.* diff --git a/clavis/clavis-android/CLAUDE.md b/clavis/clavis-android/CLAUDE.md index 6a6ec3c..5e93622 100644 --- a/clavis/clavis-android/CLAUDE.md +++ b/clavis/clavis-android/CLAUDE.md @@ -1,13 +1,10 @@ # clavis-android - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: Mobile (this subproject). You are **Xiao** (晓). - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-android/ios (your domain). +> **You are:** **Xiao** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Native Android client for Clavitor. Handles platform autofill integration and the credential picker UI. - ## Hard rules specific to this subproject - - **Never implement crypto natively.** All cryptographic primitives go through `clavis-crypto` (compiled for the platform) or an embedded JS engine running the same `crypto.js` as the browser/CLI. Two crypto implementations on the same platform is a guaranteed drift. - **Never persist L2 or L3** to the Android keystore, shared preferences, or any platform storage. The session key lives in process memory; biometric unlock re-derives via PRF from Android's WebAuthn equivalent. - **Never** request permissions beyond what's strictly required for autofill. No location, no contacts, no SMS, nothing speculative. - -See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Mobile for the full subproject contract. +See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Mobile for the full subproject contract. \ No newline at end of file diff --git a/clavis/clavis-chrome/CLAUDE.md b/clavis/clavis-chrome/CLAUDE.md index 11a24b7..f5c7b47 100644 --- a/clavis/clavis-chrome/CLAUDE.md +++ b/clavis/clavis-chrome/CLAUDE.md @@ -1,14 +1,11 @@ # clavis-chrome - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: Browser extensions (this subproject). You are **James**. - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-chrome/firefox/safari (your domain). +> **You are:** **James** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Chrome / Chromium browser extension for Clavitor. Handles form detection, field filling, and the credential picker popup. Manifest V3. - ## Hard rules specific to this subproject - - **Never store L2 or L3** in any extension storage area (`chrome.storage.local`, `chrome.storage.sync`, `chrome.storage.session`). Active session keys live in service-worker memory only and die on service-worker restart. - **Never reimplement crypto.** Always use `clavis-crypto` / the canonical `crypto.js`. If the extension reimplements crypto, it WILL drift and corrupt fields encrypted by the browser frontend. - **Always HTTPS** to talk to the vault, even on localhost (the vault serves a self-signed cert in dev). Never plain HTTP. - **Permissions are minimal.** If you ask for `` when `https://*/*` would do, fix it. Same for any optional permission. - -See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Browser extensions for the full subproject contract. +See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Browser extensions for the full subproject contract. \ No newline at end of file diff --git a/clavis/clavis-cli/CLAUDE.md b/clavis/clavis-cli/CLAUDE.md index 5d7b256..34e6781 100644 --- a/clavis/clavis-cli/CLAUDE.md +++ b/clavis/clavis-cli/CLAUDE.md @@ -1,87 +1,55 @@ # clavis-cli - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: clavis-cli (this subproject). You are **Charles**. The CLI is its own trust anchor: never bridge to Go for crypto, never expose L2 outside the C/JS boundary. - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-cli (your domain). +> **You are:** **Charles** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Pure C CLI for credential access by AI agents. Talks to a Clavitor vault over HTTPS, decrypts L2 fields locally. - ## Build - ``` make # build for host make strip # strip binary make clean # remove artifacts ``` - Target: `clavitor-cli` binary, <1MB stripped. Requires: C11 compiler, POSIX (Linux/macOS/FreeBSD/Windows). - ## Architecture - - **src/main.c** — CLI entry point, argument parsing, commands (get, list, totp, test-crypto, test-roundtrip, eval, test-totp) - **src/http.c** — HTTPS client using BearSSL. Loads system CA certs for TLS validation. Supports plain HTTP fallback. - **src/keystore.c** — Config storage at `~/.config/clavitor/config`. AES-128-GCM encrypted + HMAC-SHA256 signed. Inconvenience barrier only — real security is vault-side. - **src/jsbridge.c** — QuickJS bridge exposing BearSSL crypto primitives to JS. Loads `crypto/crypto.js` and `crypto/totp.js` from `../clavis-crypto/`. - **src/util.c** — Base64 (standard + url-safe), URL encoding. - ## Vendored dependencies - All in `vendor/`, no system package dependencies: - **BearSSL** — TLS, AES-GCM, HKDF, HMAC, PRNG - **QuickJS** — JS runtime for shared crypto logic - **cJSON** — JSON parsing - ## Crypto design - Three-tier encryption model: - **L1** — first 8 bytes of L2 key, used as Bearer auth token - **L2** — 16-byte AES-128-GCM key, client-side field encryption/decryption - **L3** — requires hardware key (not handled by CLI) - JS crypto in `../clavis-crypto/` is the single source of truth for encrypt/decrypt logic. The C code bridges BearSSL primitives into QuickJS so the same JS runs in CLI and browser. - ## Token format - `--token` value is a base64url-encoded, AES-GCM encrypted blob containing: `vault_host \0 agent_name \0 l2_key_16_bytes`. Decrypted using HKDF-derived key from seed `clavitor-l2-`. - ## Vault communication - All API calls go to `https://` (port 443 by default, override with `--port`) with `Authorization: Bearer ` and `X-Agent: ` headers. - Endpoints used: `/api/entries`, `/api/search?q=`, `/api/entries/`, `/api/ext/totp/`. - ## ⚒️ Foundation First — No Mediocrity. Ever. - The rule is simple: do it right, or say something. - Johan is an architect. Architects do not patch cracks in a bad foundation — they rebuild. Every agent on this team operates the same way. - ### What this means in practice - If you need three fixes for one problem, stop. Something fundamental is wrong. Name it, surface it — we fix that, not the symptom. - If the code is spaghetti, say so. Do not add another workaround. The workaround is the problem now. - Quick fixes are not fixes. A "temporary" hack that ships is permanent. If it is not the right solution, it is the wrong solution. - Foundation > speed. A solid base makes everything downstream easy. A shaky base makes everything downstream a nightmare. We build bases. - ### The restart rule - When the foundation is wrong: start over. Not "refactor slightly." Not "add an abstraction layer on top." Start over. This applies to code, infrastructure, design, encryption schemes, and written work alike. - ### Q&D is research, not output - Exploratory/throwaway work has its place — but it stays in research. Nothing Q&D ships. Nothing Q&D becomes the production path. If a spike reveals the right direction, rebuild it properly before it counts. - ### When you hit a bad foundation - Call it out. Do not work around it. Bad foundations are not your fault — but silently building on them is. Surface the problem, we work on it together. - The bar is high. The support is real. - ## Testing - ``` ./clavitor-cli test-crypto # BearSSL + JS crypto self-tests ./clavitor-cli test-totp # TOTP generation from base32 seed ./clavitor-cli test-roundtrip # runs crypto/test_crypto.js -``` +``` \ No newline at end of file diff --git a/clavis/clavis-crypto/CLAUDE.md b/clavis/clavis-crypto/CLAUDE.md index 40b7281..f26b47c 100644 --- a/clavis/clavis-crypto/CLAUDE.md +++ b/clavis/clavis-crypto/CLAUDE.md @@ -1,18 +1,13 @@ # clavis-crypto - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: clavis-crypto (this subproject). You are **Maria**. - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-crypto (your domain). +> **You are:** **Maria** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Shared cryptographic primitives used by every Clavitor client: browser frontend, CLI, browser extensions (Chrome/Firefox/Safari), mobile clients. The single source of truth for `encrypt_field`, `decrypt_field`, HKDF derivation, AES-GCM, and any other primitive that crosses target boundaries. - ## Hard rules specific to this subproject - - **Never diverge between targets.** If a primitive behaves differently in WebCrypto (browser/extensions) vs BearSSL (C CLI) vs platform-native (mobile), the bug is in `clavis-crypto` and it gets fixed here before any caller compensates. - **Bit-identical outputs are mandatory.** A field encrypted by the browser MUST decrypt cleanly in the CLI, and vice versa. This is verified by parity tests — if you change a primitive, run the parity tests against every target. - **No per-target shortcuts.** If a target's stdlib offers a faster path (e.g., a hardware-accelerated AES on iOS), use it ONLY if the parity tests confirm the output matches every other target byte-for-byte. - **No silent fallback** when a primitive is unavailable. If a target lacks the required crypto support, fail loudly at startup, not silently at first use. - ## The daily check - Section III → D2 of `CLAVITOR-AGENT-HANDBOOK.md` enforces this with a `diff` between the browser and CLI `crypto.js` copies. Any divergence is a foundation alert. - -See `CLAVITOR-AGENT-HANDBOOK.md` Section V → clavis-crypto for the full subproject contract. +See `CLAVITOR-AGENT-HANDBOOK.md` Section V → clavis-crypto for the full subproject contract. \ No newline at end of file diff --git a/clavis/clavis-firefox/CLAUDE.md b/clavis/clavis-firefox/CLAUDE.md index 9b6b018..b25786d 100644 --- a/clavis/clavis-firefox/CLAUDE.md +++ b/clavis/clavis-firefox/CLAUDE.md @@ -1,14 +1,11 @@ # clavis-firefox - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: Browser extensions (this subproject). You are **James**. - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-chrome/firefox/safari (your domain). +> **You are:** **James** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Firefox browser extension for Clavitor. Handles form detection, field filling, and the credential picker popup. - ## Hard rules specific to this subproject - - **Never store L2 or L3** in any extension storage area (`browser.storage.local`, `browser.storage.sync`, `browser.storage.session`). Active session keys live in background-script memory only and die on extension restart. - **Never reimplement crypto.** Always use `clavis-crypto` / the canonical `crypto.js`. If the extension reimplements crypto, it WILL drift and corrupt fields encrypted by the browser frontend or the Chrome extension. - **Always HTTPS** to talk to the vault, even on localhost (self-signed cert in dev). Never plain HTTP. - **Permissions are minimal.** Match the Chrome extension's permission set as closely as possible — if it needs more, justify why in a comment. - -See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Browser extensions for the full subproject contract. +See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Browser extensions for the full subproject contract. \ No newline at end of file diff --git a/clavis/clavis-ios/CLAUDE.md b/clavis/clavis-ios/CLAUDE.md index 8f541cc..b3059c6 100644 --- a/clavis/clavis-ios/CLAUDE.md +++ b/clavis/clavis-ios/CLAUDE.md @@ -1,13 +1,10 @@ # clavis-ios - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: Mobile (this subproject). You are **Xiao** (晓). - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-android/ios (your domain). +> **You are:** **Xiao** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Native iOS client for Clavitor. Handles platform autofill integration and the credential picker UI. - ## Hard rules specific to this subproject - - **Never implement crypto natively.** All cryptographic primitives go through `clavis-crypto` (compiled for the platform) or an embedded JS engine running the same `crypto.js` as the browser/CLI. Two crypto implementations on the same platform is a guaranteed drift. - **Never persist L2 or L3** to the iOS keychain or any platform storage. The session key lives in process memory; biometric unlock re-derives via PRF from iOS's WebAuthn / passkey APIs. - **Never** request entitlements beyond what's strictly required for autofill credentials. - -See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Mobile for the full subproject contract. +See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Mobile for the full subproject contract. \ No newline at end of file diff --git a/clavis/clavis-safari/CLAUDE.md b/clavis/clavis-safari/CLAUDE.md index 59bd5eb..7459f7c 100644 --- a/clavis/clavis-safari/CLAUDE.md +++ b/clavis/clavis-safari/CLAUDE.md @@ -1,15 +1,12 @@ # clavis-safari - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: Browser extensions (this subproject). You are **James**. - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-chrome/firefox/safari (your domain). +> **You are:** **James** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Safari browser extension for Clavitor. Handles form detection, field filling, and the credential picker popup. Distributed via the Safari Extensions infrastructure (App Store + Xcode-built container). - ## Hard rules specific to this subproject - - **Never store L2 or L3** in any extension storage area or the iCloud Keychain. Active session keys live in process memory only and die on extension restart. - **Never reimplement crypto.** Always use `clavis-crypto` / the canonical `crypto.js`. If the extension reimplements crypto, it WILL drift and corrupt fields encrypted by other clients. - **Always HTTPS** to talk to the vault. Never plain HTTP. - **Container app exists only to host the extension.** Do not add unrelated functionality to the container — that's a Mac app and it's not what we're shipping. - **Permissions are minimal.** Match the Chrome/Firefox extension permission set; if Safari requires something extra, justify it in a comment with the Safari API doc reference. - -See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Browser extensions for the full subproject contract. +See `CLAVITOR-AGENT-HANDBOOK.md` Section V → Browser extensions for the full subproject contract. \ No newline at end of file diff --git a/clavis/clavis-telemetry/CLAUDE.md b/clavis/clavis-telemetry/CLAUDE.md index 6ff4858..b49b0d9 100644 --- a/clavis/clavis-telemetry/CLAUDE.md +++ b/clavis/clavis-telemetry/CLAUDE.md @@ -1,35 +1,23 @@ # clavis-telemetry - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: clavis-telemetry (this subproject). You are **Hans**. - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-telemetry (your domain). +> **You are:** **Hans** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Operator telemetry: heartbeat metrics from POPs to central. CPU, memory, disk, vault count, request rates. Operational signals only — never user data. - ## Hard rules specific to this subproject - - **Never send vault content.** Telemetry is operational, not data. No entry titles, no field values, no credential identifiers, no audit log entries that contain user information. - **Never send raw user IP addresses.** Aggregate counts (e.g., `unique_ips_24h: 472`) are fine; raw IPs are not. - **Commercial-only by default.** Community edition is offline-by-default. Telemetry is opt-in for community installs and enforced-on for commercial POPs. Build tags must reflect this — community binaries should not even contain the telemetry code path. - **No phone-home for crashes.** If you ever want crash reporting, talk to Johan first. Auto-uploaded stack traces have leaked credentials in other products and we will not repeat that mistake. - See `CLAVITOR-AGENT-HANDBOOK.md` Section V → clavis-telemetry for the full subproject contract. - ## Operations - ### Log Retention - Tarpit logs contain scanner IPs for security analysis. Rotate/delete per your organization's retention policy (recommended: 30 days). - ### External Alerting (Optional) - Outage alerts can be sent to ntfy. Configure via environment variables: - `NTFY_ALERT_URL` - The ntfy endpoint (e.g., `http://127.0.0.1:2586/clavitor-alerts`) - `NTFY_ALERT_TOKEN` - Bearer token for authentication - If unset, outage logging continues without external notification. - ### Kuma Monitoring (Optional) - Health push to Kuma can be configured via: - `KUMA_PUSH_URL` - Kuma push endpoint - -If unset, Kuma push is disabled. +If unset, Kuma push is disabled. \ No newline at end of file diff --git a/clavis/clavis-vault/CLAUDE.md b/clavis/clavis-vault/CLAUDE.md index 245c61a..206b50a 100644 --- a/clavis/clavis-vault/CLAUDE.md +++ b/clavis/clavis-vault/CLAUDE.md @@ -1,43 +1,25 @@ # Clavis Vault — CLAUDE.md - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: clavis-vault (this subproject). You are **Sarah**. Run the Section III → Daily review checklist every morning. Drift gets fixed before any new feature work. - +> **Quickstart (60s):** [../../QUICKSTART.md](../../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../../CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavis-vault (your domain). +> **You are:** **Sarah** — Run `./scripts/daily-review.sh` every morning. Fix failures first. ## Foundation First — No Mediocrity. Ever. - The rule is simple: do it right, or say something. - Johan is an architect. Architects do not patch cracks in a bad foundation — they rebuild. Every agent on this team operates the same way. - ### What this means in practice - If you need three fixes for one problem, stop. Something fundamental is wrong. Name it, surface it — we fix that, not the symptom. - If the code is spaghetti, say so. Do not add another workaround. The workaround is the problem now. - Quick fixes are not fixes. A "temporary" hack that ships is permanent. If it is not the right solution, it is the wrong solution. - Foundation > speed. A solid base makes everything downstream easy. A shaky base makes everything downstream a nightmare. We build bases. - ### The restart rule - When the foundation is wrong: start over. Not "refactor slightly." Not "add an abstraction layer on top." Start over. This applies to code, infrastructure, design, encryption schemes, and written work alike. - ### Q&D is research, not output - Exploratory/throwaway work has its place — but it stays in research. Nothing Q&D ships. Nothing Q&D becomes the production path. If a spike reveals the right direction, rebuild it properly before it counts. - ### When you hit a bad foundation - Call it out. Do not work around it. Bad foundations are not your fault — but silently building on them is. Surface the problem, we work on it together. - The bar is high. The support is real. - --- - ## Security Failures — NEVER HIDE THEM - **The cardinal rule:** If decryption/verification fails, expose the failure. Never fall back to plaintext. Never silently continue. - ### WRONG — Silent fallback (fireable offense) ```javascript try { @@ -46,7 +28,6 @@ try { decrypted = plaintext; // NEVER DO THIS } ``` - ### CORRECT — Visible failure ```javascript try { @@ -55,24 +36,17 @@ try { decrypted = '[decryption failed]'; // User sees the failure } ``` - This applies to: - Encryption/decryption errors - Signature verification failures - Authentication failures - Tampering detection - Any security-critical operation - **Security failures must be noisy, visible, and blocking — never silent, hidden, or permissive.** - See `SECURITY.md` for full principles. - --- - ## Edition System (Community vs Commercial) - Clavitor Vault has two editions with build-time separation: - ### Community Edition (Default) ```bash go build -o clavitor ./cmd/clavitor/ @@ -81,7 +55,6 @@ go build -o clavitor ./cmd/clavitor/ - Local logging only - Self-hosted - Elastic License 2.0 - ### Commercial Edition ```bash go build -tags commercial -o clavitor ./cmd/clavitor/ @@ -90,27 +63,18 @@ go build -tags commercial -o clavitor ./cmd/clavitor/ - Operator alerts POST to `/v1/alerts` - Multi-POP management - Commercial license - ### Using the Edition Package - ```go import "github.com/johanj/clavitor/edition" - // Send operator alerts (works in both editions) edition.Current.AlertOperator(ctx, "auth_error", "message", details) - // Check edition currentEdition := edition.Current.Name() // "community" or "commercial" ``` - See `edition/CLAUDE.md` for full documentation. - --- - ## Clavitor Vault v2 — Current State & Testing - ### What we built this session - #### 1. Domain classification for import scopes - Import page (`cmd/clavitor/web/import.html`) parses 14+ password manager formats client-side - Unique domains are extracted (eTLD+1) and sent to `https://clavitor.ai/classify` @@ -119,7 +83,6 @@ See `edition/CLAUDE.md` for full documentation. - Domains with no URL get scope "unclassified" (not "misc"). "misc" = LLM tried and failed - Domains are sent in chunks of 200 to stay within token limits - Classification is opt-in: user sees consent dialog with Yes/Skip/Cancel - #### 2. Import flow UX - Drop file → parse → hide file step → consent dialog (Yes/Skip/Cancel) - Cancel returns to file step @@ -129,7 +92,6 @@ See `edition/CLAUDE.md` for full documentation. - Black entry icons (LGN/CARD/NOTE) with white text — on brand - Global black checkboxes (`accent-color: var(--text)`) - Unified CSS classes: `.item-row`, `.item-icon`, `.item-list` (replacing import-specific classes) - #### 3. Import filtering visibility (NEW) - Import parsers now track what gets filtered and why - `importers-parsers.js` has `_importReport` object that records: `rawCount`, `filtered[]`, `finalCount` @@ -138,7 +100,6 @@ See `edition/CLAUDE.md` for full documentation. - Filter badge with tooltip showing breakdown: `"Filtered: 150 duplicate, 97 alias, 12 trashed"` - Clicking the filtered badge shows detailed list of what was skipped - **Why**: User saw 1073 during import but only 818 in vault. Now they can see the ~250 records were: duplicates (older versions), email aliases, and trashed items. - #### 4. Credential Alternates System (NEW) - **Problem**: Chrome/Firefox imports don't have modification dates, so we can't tell which password is newer. Same site+user from different sources would overwrite each other. - **Solution**: Multiple passwords per site+user are now stored as "alternates" instead of overwriting. @@ -151,7 +112,6 @@ See `edition/CLAUDE.md` for full documentation. - `GET /ext/match?url=...` now returns alternates array sorted by verified_at (verified first) - **CLI Protocol**: When multiple passwords for same site+user, try verified ones first. On success, call `/worked` endpoint. Backend marks winner as verified and links alternates to it. - **Import UI**: Shows `"Done — 50 imported, 12 alternates"` so user knows some were stored as alternates. - #### 5. Security hardening (IN PROGRESS — needs testing) - **List endpoint stripped**: GET /api/entries now always returns metadata only (title, type, scopes, entry_id). No data blobs, no ?meta=1 toggle. Full entry data only via GET /api/entries/{id} with scope enforcement. - **Agent system type guard**: Agents cannot create/update entries with type=agent or type=scope. Enforced on CreateEntry, CreateEntryBatch, UpsertEntry, UpdateEntry. @@ -159,11 +119,8 @@ See `edition/CLAUDE.md` for full documentation. - **Per-agent IP whitelist**: Stored in agent entry (L1-encrypted). Empty on creation → filled with IP from first contact → enforced on every subsequent request. Supports CIDRs (10.0.0.0/16), exact IPs, and FQDNs (home.smith.family), comma-separated. - **Per-agent rate limiting**: Configurable requests/minute per agent ID (not per IP). Stored in agent entry. - **Admin operations require PRF tap**: Agent CRUD and scope updates require a fresh WebAuthn assertion. Flow: POST /auth/admin/begin → PRF tap → POST /auth/admin/complete → one-time admin token in X-Admin-Token header → pass to admin endpoint. Token is single-use, 5-minute expiry. - ### What is semi-done / needs testing - The security hardening code compiles and the vault runs, but none of it has been tested with actual agent tokens or WebAuthn assertions yet. Specifically: - 1. **IP whitelist first-contact fill**: ✅ Fixed - DB errors now return 500 2. **IP whitelist enforcement**: Does CIDR matching work? FQDN resolution? Comma-separated lists? FQDN now has 5-min cache 3. **Per-agent rate limiter**: Does it correctly track per agent ID and reset per minute? @@ -171,30 +128,22 @@ The security hardening code compiles and the vault runs, but none of it has been 5. **System type guards**: ✅ Fixed - Agents blocked entirely from batch import; returns 403 on forbidden types 6. **L3 field preservation**: ✅ Fixed - Agents cannot overwrite L3 fields in batch or upsert 7. **List endpoint**: Verify no data blobs leak. Check browser console: entries[0] should have no data or fields property. - ### Known Issues (Accepted) - **IP Whitelist Race Condition**: There is a theoretical race on first-contact IP recording if two parallel requests from different IPs arrive simultaneously. This was reviewed and accepted because: - Requires a stolen agent token (already a compromise) - Requires racing first contact from two different IPs - The "loser" simply won't be auto-whitelisted - Cannot be reproduced in testing; practically impossible to trigger - Fix would require plaintext column + atomic update (not worth complexity) - See comment in `api/middleware.go` for full rationale. - **Admin Token Consumed Early**: The admin token is consumed immediately upon validation in `requireAdmin()`. If the subsequent operation fails (DB error, validation error, etc.), the token is gone but the operation didn't complete. The user must perform a fresh PRF tap to retry. - This was reviewed and accepted because: - 5-10 minute token lifetime makes re-auth acceptable - It's a UX inconvenience, not a security vulnerability - Deferring consumption until operation success would require transaction-like complexity - Rare edge case: requires admin operation to fail after token validation - ### How testing works - No automated test suite for this session's work. Testing is manual via the browser: - 1. Vault runs locally on forge (this machine) at port 1984, accessed via https://dev.clavitor.ai/app/ 2. Caddy on 192.168.0.2 reverse-proxies dev.clavitor.ai → forge:1984 3. Import testing: Drop a Proton Pass ZIP export (or any of the 14 supported formats) on the import page. Check scope pills, counts, classifications, and **filtered count badge** — shows why records were skipped (duplicates, aliases, trashed). @@ -202,9 +151,7 @@ No automated test suite for this session's work. Testing is manual via the brows 5. Screen capture: `/capture` skill takes a live screenshot from Johan's Mac (display 3). `/screenshot` fetches the latest manual screenshot. 6. Version verification: The topbar shows the **build timestamp** (e.g., `2026-04-04-1432`) fetched from `/api/version`. If the timestamp doesn't update after `make dev`, the old binary is still running — check `make status`. 7. DB location: Vault data is in `/home/johan/dev/clavitor/clavis/clavis-vault/data/`. Delete clavitor-* files there to start fresh (will require passkey re-registration). - ### Key files - | File | What | |------|------| | api/handlers.go | All HTTP handlers, security guards, admin auth | @@ -218,22 +165,17 @@ No automated test suite for this session's work. Testing is manual via the brows | cmd/clavitor/web/topbar.js | Version number, nav, idle timer | | cmd/clavitor/web/clavitor-app.css | All styles, item-row/item-icon system | | clavitor.ai/main.go | Portal + /classify endpoint (Haiku on OpenRouter) | - ### Deploy Clavitor Vault (dev) - Working directory: `/home/johan/dev/clavitor/clavis/clavis-vault` - **Prerequisites:** ```bash # Enable user systemd services (one-time setup) systemctl --user enable --now clavitor.service ``` - **Build and deploy (one command):** ```bash make dev # stop → build → start (graceful shutdown via SIGTERM) ``` - **Individual commands:** ```bash make stop # systemctl --user stop clavitor.service @@ -243,40 +185,25 @@ make status # systemctl --user status clavitor.service make logs # journalctl --user -u clavitor -f make build # go build... ``` - **Service file location:** `~/.config/systemd/user/clavitor.service` - Caddy on 192.168.0.2 reverse-proxies dev.clavitor.ai → forge:1984 (self-signed, so tls_insecure_skip_verify). - **Update Caddy config:** ```bash ssh root@192.168.0.2 # Edit /etc/caddy/Caddyfile, then: systemctl reload caddy ``` - Web files are embedded at compile time (go:embed). CSS/JS/HTML changes require rebuild. - Bump version in `cmd/clavitor/web/topbar.js` (search for v2.0.) to verify new build is live. - ### Deploy clavitor.ai (prod) - Working directory: `/home/johan/dev/clavitor/clavitor.ai` - ```bash make deploy-prod ``` - This cross-compiles, SCPs to Zürich, enters maintenance mode, restarts systemd, exits maintenance. One command. - SSH: root@clavitor.ai — port 22 blocked on public IP, use Tailscale. Never use johan@. Avoid rapid SSH attempts (fail2ban will lock you out — it already happened once this session). - Env vars are in `/opt/clavitor-web/.env` and `/etc/systemd/system/clavitor-web.service`. After changing .env, run `systemctl daemon-reload && systemctl restart clavitor-web` on the server. - **NEVER deploy the database. Only the binary gets uploaded. The SQLite DB on prod is the source of truth.** - Verify: `ssh root@ "systemctl status clavitor-web"` - ### IMPORTANT - -**NEVER deploy to prod without Johan's explicit approval. This caused a SEV-1 on 2026-03-29.** +**NEVER deploy to prod without Johan's explicit approval. This caused a SEV-1 on 2026-03-29.** \ No newline at end of file diff --git a/clavitor.ai/CLAUDE.md b/clavitor.ai/CLAUDE.md index 1da2388..fdb8bb3 100644 --- a/clavitor.ai/CLAUDE.md +++ b/clavitor.ai/CLAUDE.md @@ -1,26 +1,19 @@ # Clavitor Website — clavitor.com - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: clavitor.ai/admin (this subproject). You are **Emma**. - +> **Quickstart (60s):** [../QUICKSTART.md](../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../CLAVITOR-AGENT-HANDBOOK.md](../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavitor.ai (your domain). +> **You are:** **Emma** — Run `./scripts/daily-review.sh` every morning. Fix failures first. ## Foundation First — No Mediocrity. Ever. The rule is simple: do it right, or say something. - Johan is an architect. Architects do not patch cracks in a bad foundation — they rebuild. Every agent on this team operates the same way. - **What this means in practice:** - If you need three fixes for one problem, stop. Something fundamental is wrong. Name it, surface it — we fix that, not the symptom. - If the code is spaghetti, say so. Do not add another workaround. The workaround is the problem now. - Quick fixes are not fixes. A "temporary" hack that ships is permanent. If it is not the right solution, it is the wrong solution. - Foundation > speed. A solid base makes everything downstream easy. A shaky base makes everything downstream a nightmare. We build bases. - **The restart rule:** When the foundation is wrong: start over. Not "refactor slightly." Not "add an abstraction layer on top." Start over. This applies to code, infrastructure, design, encryption schemes, and written work alike. - **Q&D is research, not output:** Exploratory/throwaway work has its place — but it stays in research. Nothing Q&D ships. Nothing Q&D becomes the production path. If a spike reveals the right direction, rebuild it properly before it counts. - **When you hit a bad foundation:** Call it out. Do not work around it. Bad foundations are not your fault — but silently building on them is. Surface the problem, we work on it together. - The bar is high. The support is real. These rules apply to you now. - ## Architecture - Go web server (`main.go`) with `go:embed` for templates, CSS, SVGs, PNGs - Templates in `templates/*.tmpl`, single CSS in `clavitor.css` @@ -28,40 +21,33 @@ The bar is high. The support is real. These rules apply to you now. - Dev mode: auto-detected when `templates/` dir exists on disk — reloads templates per request, but CSS/SVGs require rebuild (`go:embed`) - Port 8099 - License: Elastic License 2.0 (NOT MIT) - ## Deployment - ### Dev (forge = 192.168.1.16, Florida — dev.clavitor.ai) ``` make dev # build + restart locally make deploy-dev # same thing ``` Dev runs on forge (localhost). `dev.clavitor.ai` DNS points to home IP. - ### Prod (Zürich — clavitor.ai — clavitor.ai) ``` make deploy-prod # cross-compile amd64, scp to Zürich, restart systemd ``` Prod runs at `/opt/clavitor-web/` as systemd service `clavitor-web`. Caddy reverse proxies `clavitor.ai`, `clavitor.com`, `www.clavitor.ai`, `www.clavitor.com` → `localhost:8099`. - ### First-time setup (already done) ``` make setup-prod # creates /opt/clavitor-web, systemd service, uploads binary+db ``` Then manually update `/etc/caddy/Caddyfile` to reverse_proxy. - ### SSH - Prod: `ssh root@clavitor.ai` - Tailscale: `zurich` (100.70.148.118) — SSH may be blocked via Tailscale - ## 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 @@ -71,27 +57,23 @@ CSS and SVG changes require rebuild (embedded at compile time). Template changes - Fonts: Figtree (body), JetBrains Mono (code/monospace) - No inline styles, no CSS in templates. Everything in clavitor.css. - Always capitalize "Clavitor" in prose. Lowercase in code/paths/commands. - ## Encryption Terminology - **Vault Encryption** — whole vault at rest - **Credential Encryption** — per-field, server-side (AI agents can read via CLI) - **Identity Encryption** — per-field, client-side via WebAuthn PRF (Touch ID only, server cannot decrypt) - Never use "sealed fields", "agent fields", "L1", "L2", "L3" - Agents use CLI, NOT MCP (MCP exposes plaintext; CLI is scoped) - ## 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` @@ -99,10 +81,9 @@ CSS and SVG changes require rebuild (embedded at compile time). Template changes - 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 -- Rackmill: Perth +- Rackmill: Perth \ No newline at end of file diff --git a/clavitor.ai/admin/CLAUDE.md b/clavitor.ai/admin/CLAUDE.md index 4a422f9..9def417 100644 --- a/clavitor.ai/admin/CLAUDE.md +++ b/clavitor.ai/admin/CLAUDE.md @@ -1,25 +1,19 @@ # clavitor.ai/admin — central admin / Paddle integration - -> **Required reading before any work**: [CLAVITOR-AGENT-HANDBOOK.md](../../CLAVITOR-AGENT-HANDBOOK.md) — Section I (Culture), Section II (Security), Section III (Workflow), and Section V: clavitor.ai/admin (this subproject). You are **Emma**. - +> **Quickstart (60s):** [../QUICKSTART.md](../QUICKSTART.md) — who you are, 4 things to do, critical rules. +> **Deep reference:** [../CLAVITOR-AGENT-HANDBOOK.md](../CLAVITOR-AGENT-HANDBOOK.md) — Section V: clavitor.ai (your domain). +> **You are:** **Emma** — Run `./scripts/daily-review.sh` every morning. Fix failures first. Central admin service. Owns the customer hierarchy (MSP → end-customer → vault slots), the seat ledger, the Paddle webhook handler, and the vault registry mapping `(customer, slot_index, l0, pop)`. This is the directory service — not a vault. - ## Hard rules specific to this subproject - - **Never hold any decryption material.** Central is not a vault. The wrapped L3 stored centrally for distribution is opaque to central — no L3, no L2, no L1, no master_key, ever. If you find yourself wanting to decrypt vault content here, you are in the wrong process. - **Never trust an inbound webhook without verifying its HMAC signature.** Paddle webhook verification is mandatory. The secret comes from `PADDLE_WEBHOOK_SECRET`. If the env var is unset, every webhook is refused. There is no debug bypass. - **Never accept admin operations from outside Tailscale.** The `vaults/claim`, `issue-token`, `wl3/since`, `wl3/full` endpoints listen only on the tailnet interface. Public clavitor.ai serves users; the ops control plane is invisible to the internet. - **Never expose the Paddle API key, webhook secret, or any service credentials in client-side code.** Server-side env only. - **Never delete vault data, WL3 files, or audit logs without an explicit GDPR request.** The default lifetime is forever. Cancellation/downgrade marks slots `archived`; only an explicit one-shot deletion script touches the underlying files. - ## Vault slot lifecycle (canonical) - Pre-create at subscription time: 1. Customer subscribes to a plan with N seats → `INSERT INTO vault_slots` N rows, all `status='unused'`. 2. Owner names a slot ("Anna") and clicks "invite" → status moves to `pending`, central calls the POP's `/admin/issue-token` over Tailscale, POP returns the 6-char token, central displays it to the owner. 3. Anna enrolls at the POP → status moves to `active`, `l0` populated, `enrolled_at` set. 4. Cancellation/downgrade → status moves to `archived`. Vault data and WL3 file persist. - Plan upgrade = `INSERT` more `unused` rows. Plan downgrade = refuse until the owner manually marks excess slots `archived` (no silent data loss). - -See `CLAVITOR-AGENT-HANDBOOK.md` Section V → clavitor.ai/admin for the full subproject contract. +See `CLAVITOR-AGENT-HANDBOOK.md` Section V → clavitor.ai/admin for the full subproject contract. \ No newline at end of file diff --git a/docs/GIT-HOSTING-OVERVIEW.md b/docs/GIT-HOSTING-OVERVIEW.md new file mode 100644 index 0000000..8e8c279 --- /dev/null +++ b/docs/GIT-HOSTING-OVERVIEW.md @@ -0,0 +1,172 @@ +# Git Hosting Solutions — Complete Overview + +**Your current setup:** Bare Git (Zurich) — SSH-only, no web UI, no issues + +--- + +## SaaS Solutions (They Host, You Pay/Free) + +### 1. GitHub (USA, Microsoft) +| | | +|--|--| +| **Type** | SaaS (Proprietary) | +| **Cost** | Free (public + private, 3 collaborators), Team $4/user/month | +| **Features** | Issues, PRs, Actions (CI/CD), Codespaces, Copilot | +| **Pros** | Everyone uses it, massive ecosystem, best integrations | +| **Cons** | US jurisdiction (CLOUD Act), vendor lock-in, Microsoft | +| **Best for** | OSS projects, when you need network effects | + +--- + +### 2. GitLab.com (USA) +| | | +|--|--| +| **Type** | SaaS (Open Core — some features open, some proprietary) | +| **Cost** | Free (400 CI minutes/month), Premium $29/user/month | +| **Features** | Issues, MRs, CI/CD (built-in), Container registry, DevSecOps | +| **Pros** | Generous free CI, integrated DevOps platform | +| **Cons** | Complex, heavy, can be slow, US company | +| **Best for** | Teams wanting integrated CI/CD without setup | + +--- + +### 3. Bitbucket (USA, Atlassian) +| | | +|--|--| +| **Type** | SaaS (Proprietary) | +| **Cost** | Free (5 users), Standard $3/user/month | +| **Features** | Issues, PRs, Pipelines (CI/CD), Jira integration | +| **Pros** | Works with Jira/Confluence if you use Atlassian | +| **Cons** | Smaller community than GitHub, Atlassian ecosystem lock-in | +| **Best for** | Teams already in Atlassian ecosystem | + +--- + +### 4. SourceHut (USA, Drew DeVault) +| | | +|--|--| +| **Type** | SaaS (Open Source — sourcehut.org is open) | +| **Cost** | Free during beta, then ~$2/month or pay-what-you-want | +| **Features** | Git + Mercurial, email-based workflow, minimal web UI | +| **Pros** | No JavaScript, fast, privacy-focused, true open source | +| **Cons** | Different workflow (email-based), smaller community | +| **Best for** | Minimalists, people who hate web bloat | + +--- + +### 5. Codeberg (Germany, EU) +| | | +|--|--| +| **Type** | SaaS (runs Gitea, non-profit) | +| **Cost** | Free (donations welcome) | +| **Features** | Gitea-based: Issues, PRs, CI via Woodpecker | +| **Pros** | EU-hosted (GDPR-friendly), non-profit, no tracking | +| **Cons** | Smaller than GitHub, occasional downtime | +| **Best for** | EU-based projects, privacy-conscious, avoiding Big Tech | + +--- + +## Self-Hosted Solutions (You Host, You Control) + +### 6. GitLab CE (Community Edition) +| | | +|--|--| +| **Type** | Open Core (CE is open, EE is proprietary) | +| **Cost** | Free (self-hosted) | +| **Install** | Complex — requires PostgreSQL, Redis, Ruby, Go | +| **Resources** | 4GB+ RAM minimum, prefers 8GB | +| **Features** | Issues, MRs, CI/CD (with runners), Registry, Wiki | +| **Pros** | Full-featured, industry standard for self-hosting | +| **Cons** | Heavy, complex to maintain, resource hungry | +| **Best for** | Large teams needing full DevOps platform | + +--- + +### 7. Gitea (Go, Lightweight) +| | | +|--|--| +| **Type** | Open Source (MIT License) | +| **Cost** | Free | +| **Install** | 1 binary, 5 minutes | +| **Resources** | ~100MB RAM, runs on Raspberry Pi | +| **Features** | Issues, PRs, CI/CD (via Act runners), Registry, Wiki | +| **Pros** | Light, fast, easy, GitHub-like UI | +| **Cons** | Smaller ecosystem than GitLab, newer (less mature) | +| **Best for** | Small-medium teams, low resources, quick setup | + +--- + +### 8. Gogs (Go, Minimal) +| | | +|--|--| +| **Type** | Open Source (MIT License) | +| **Cost** | Free | +| **Install** | 1 binary | +| **Resources** | Very light — lighter than Gitea | +| **Features** | Basic: repos, issues, PRs (simpler than Gitea) | +| **Pros** | Extremely light, simple | +| **Cons** | Less active development, fewer features than Gitea | +| **Best for** | Minimalists who just need repos + basic issues | + +--- + +### 9. Forgejo (Gitea Fork) +| | | +|--|--| +| **Type** | Open Source (Fork of Gitea) | +| **Cost** | Free | +| **Origin** | Community fork after Gitea went to non-profit governance | +| **Features** | Same as Gitea | +| **Pros** | 100% community-controlled, no corporate influence | +| **Cons** | Newer fork, smaller community (for now) | +| **Best for** | Those who want Gitea features but pure community governance | + +--- + +### 10. Your Current: Bare Git + SSH +| | | +|--|--| +| **Type** | Just Git (no platform) | +| **Cost** | Server cost only | +| **Install** | `git init --bare` | +| **Resources** | Minimal | +| **Features** | Git only — no issues, no PRs, no web UI | +| **Pros** | Full control, minimal attack surface, simple | +| **Cons** | No collaboration features, manual everything | +| **Best for** | Small teams, maximum control, minimal complexity | + +--- + +## Summary: Which Should You Choose? + +| Your Priority | Solution | Why | +|-------------|----------|-----| +| **Maximum visibility for OSS** | GitHub | Everyone's there | +| **EU data residency + OSS** | Codeberg | GDPR-friendly, non-profit | +| **Self-hosted, low resources** | Gitea | 1 binary, 100MB RAM | +| **Self-hosted, full DevOps** | GitLab CE | Complete platform | +| **Minimalist, email workflow** | SourceHut | No bloat, true open source | +| **Keep current + add issues** | Gitea on Zurich | Upgrade your bare Git | +| **Maximum control, no web** | Keep bare Git | What you have now | + +--- + +## My Recommendation for You + +**Hybrid: GitHub Free + Your Zurich Bare Git** + +``` +Public repo (clavitor) → GitHub Free (OSS visibility) +Private dev repo (clavitor-dev) → Zurich Bare Git (compliance/control) +``` + +**Or full upgrade:** Gitea on Zurich +- 1 binary install +- Web UI with issues/PRs +- Still self-hosted in Switzerland +- GDPR-friendly + +**Want me to:** +- A) Write skill to install Gitea on Zurich? +- B) Set up GitHub Free + sync workflow? +- C) Keep current bare Git + document manual issue workflow? \ No newline at end of file diff --git a/scripts/daily-review.sh b/scripts/daily-review.sh new file mode 100755 index 0000000..cdb93d4 --- /dev/null +++ b/scripts/daily-review.sh @@ -0,0 +1,153 @@ +#!/bin/bash +# Daily Review Script — Clavitor Agent Handbook Part 4 +# Run this every morning before any new feature work. +# Any failure = foundation alert. Fix before proceeding. + +set -e + +FAILED=0 +PASSED=0 + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo "=== Clavitor Daily Review ===" +echo "Checking against CLAVITOR-AGENT-HANDBOOK.md Part 4" +echo "" + +# Function to run a check +check() { + local name="$1" + local cmd="$2" + local expected="$3" + + echo -n "Checking $name... " + + if eval "$cmd" > /dev/null 2>&1; then + if [ "$expected" = "fail" ]; then + echo -e "${RED}❌ FAIL${NC} (should have failed but passed)" + FAILED=$((FAILED + 1)) + else + echo -e "${GREEN}✅ PASS${NC}" + PASSED=$((PASSED + 1)) + fi + else + if [ "$expected" = "fail" ]; then + echo -e "${GREEN}✅ PASS${NC} (correctly failed)" + PASSED=$((PASSED + 1)) + else + echo -e "${RED}❌ FAIL${NC}" + FAILED=$((FAILED + 1)) + fi + fi +} + +echo "--- Section A: Server Hard Veto Checks ---" + +# A1: Server never receives master_key +check "A1: No master_key on server" \ + "grep -rn 'master_key\|MasterKey\|masterKey' clavis-vault/api/ clavis-vault/lib/ --include='*.go' | grep -v '_test.go' | head -1" \ + "fail" + +# A2: No DeriveP1 on server +check "A2: No DeriveP1 on server" \ + "grep -rn 'DeriveP1\|derive_p1\|deriveP1' clavis-vault/lib/ clavis-vault/api/ | head -1" \ + "fail" + +# A3: No L2 credential functions +check "A3: No L2 credential functions" \ + "grep -rn 'MintCredential\|ParseCredential\|CredentialToWire' clavis-vault/api/ clavis-vault/lib/ | head -1" \ + "fail" + +echo "" +echo "--- Section F: Test Posture ---" + +# F1: Tests pass +echo -n "F1: Go tests pass... " +cd clavis/clavis-vault +if go test ./lib/... ./api/... > /tmp/test-output.log 2>&1; then + echo -e "${GREEN}✅ PASS${NC}" + PASSED=$((PASSED + 1)) +else + echo -e "${RED}❌ FAIL${NC}" + echo " See: /tmp/test-output.log" + FAILED=$((FAILED + 1)) +fi +cd ../.. + +# F2: Build succeeds +echo -n "F2: Build succeeds... " +cd clavis/clavis-vault +if go build -o /tmp/clavitor-test ./cmd/clavitor/ > /tmp/build-output.log 2>&1; then + echo -e "${GREEN}✅ PASS${NC}" + PASSED=$((PASSED + 1)) +else + echo -e "${RED}❌ FAIL${NC}" + echo " See: /tmp/build-output.log" + FAILED=$((FAILED + 1)) +fi +cd ../.. + +# F3: Check for test files (basic check) +echo -n "F3: Recent Go changes have tests... " +# Get files changed in last commit +CHANGED=$(git diff --name-only HEAD~1 2>/dev/null | grep '\.go$' | grep -v '_test.go' || true) +if [ -z "$CHANGED" ]; then + echo -e "${YELLOW}⚠️ SKIP${NC} (no Go changes in last commit)" +else + # Check each changed file has corresponding test + MISSING_TESTS=0 + for f in $CHANGED; do + testfile="$(dirname $f)/$(basename $f .go)_test.go" + if [ ! -f "$testfile" ]; then + echo "" + echo -e " ${YELLOW}⚠️ WARNING: $f has no test file${NC}" + MISSING_TESTS=$((MISSING_TESTS + 1)) + fi + done + if [ $MISSING_TESTS -eq 0 ]; then + echo -e "${GREEN}✅ PASS${NC}" + PASSED=$((PASSED + 1)) + else + echo -e "${YELLOW}⚠️ PARTIAL${NC} ($MISSING_TESTS files without tests)" + fi +fi + +echo "" +echo "--- Section G: Dead Code ---" + +# G1: Empty directories +echo -n "G1: No empty directories... " +EMPTY=$(find . -type d -empty 2>/dev/null | grep -v ".git" | grep -v "vendor" | head -5) +if [ -z "$EMPTY" ]; then + echo -e "${GREEN}✅ PASS${NC}" + PASSED=$((PASSED + 1)) +else + echo -e "${RED}❌ FAIL${NC}" + echo "$EMPTY" | while read dir; do + echo " $dir" + done + FAILED=$((FAILED + 1)) +fi + +# G2: No orphaned HTML (with exceptions) +echo -n "G2: No orphaned production files... " +# This is a simplified check - manual review still needed +ORPHANED=0 +echo -e "${YELLOW}⚠️ MANUAL${NC} (see handbook for full G2 check)" + +echo "" +echo "=== Summary ===" +echo -e "${GREEN}Passed: $PASSED${NC}" +if [ $FAILED -gt 0 ]; then + echo -e "${RED}Failed: $FAILED${NC}" + echo "" + echo -e "${RED}FOUNDATION ALERT: Fix failures before any new feature work.${NC}" + exit 1 +else + echo -e "${GREEN}All checks passed. Ready for feature work.${NC}" + exit 0 +fi