diff --git a/lib/git-crypt.sh b/lib/git-crypt.sh new file mode 100644 index 0000000..3877c0c --- /dev/null +++ b/lib/git-crypt.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +# ============================================================================= +# lib/git-crypt.sh +# git-crypt lifecycle management (init, export, verify). +# ============================================================================= + +gcrypt_init() { + git-crypt init + success "git-crypt initialized in $(pwd)" +} + +gcrypt_export_key() { + local genome_name="$1" + local key_path="${KEYS_DIR}/${genome_name}.key" + + mkdir -p "${KEYS_DIR}" + git-crypt export-key "$key_path" + success "Symmetric key exported to: $key_path" + warn "Action required: Store this key in Vaultwarden and remove it from local disk." +} + +gcrypt_verify() { + local genome_name="$1" + local key_path="${KEYS_DIR}/${genome_name}.key" + + info "Verifying git-crypt status for ${genome_name}..." + git-crypt lock + + # Checking if the private marker is still encrypted (binary check) + if file "raw/private/.gitkeep" 2>/dev/null | grep -q "data"; then + success "Encryption verified: private/ directory is protected." + else + warn "Encryption check inconclusive. Please run 'git-crypt status' manually." + fi + + [[ -f "$key_path" ]] && git-crypt unlock "$key_path" +} + +gcrypt_print_key_instructions() { + local genome_name="$1" + local v_url="${VAULTWARDEN_URL:-https://your-vaultwarden.com}" + + echo -e "\n ── ${BOLD}Key Management: ${genome_name}${NC} ──\n" + echo " 1. Encode the key to base64:" + echo " base64 < ${KEYS_DIR}/${genome_name}.key" + echo "" + echo " 2. Save to Vaultwarden (${v_url}):" + echo " Name: \"${genome_name} key\"" + echo " Note: " + echo "" + echo " 3. For AI Server / Runtime Injection:" + echo " export BW_SESSION=\$(bw unlock --raw)" + echo " git-crypt unlock <(bw get notes \"${genome_name} key\" --session \"\$BW_SESSION\" | base64 -d)" +} + +gcrypt_print_runtime_model() { + echo "" + echo " RUNTIME SECURITY MODEL:" + echo " ─────────────────────────────────────────────────────────────" + echo " On Forgejo (remote):" + echo " raw/private/ and wiki/private/ are opaque AES-256-CTR blobs." + echo " Collaborators without the key see binary in private/," + echo " plaintext everywhere else. Git handles this gracefully." + echo "" + echo " On your laptop:" + echo " Once unlocked, files are transparently decrypted by the git" + echo " smudge filter. Obsidian reads them as normal Markdown." + echo "" + echo " On the AI VM:" + echo " Same as laptop when unlocked. Use runtime injection (step 5" + echo " above) so the key is never written to disk." + echo "" + echo " Limitation:" + echo " Encryption does NOT protect against a full server compromise" + echo " where an attacker has root access to a machine where the repo" + echo " is already unlocked. Runtime injection mitigates this." + echo " ─────────────────────────────────────────────────────────────" + echo "" +}