From 2b50bf5d53954373a5d987146770327ac1c5979a Mon Sep 17 00:00:00 2001 From: Sam Valladares Date: Sun, 21 Jun 2026 18:19:01 -0500 Subject: [PATCH] ci: guard against private cloud service code in public repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vestige Cloud is split: the public client (a thin HTTP sync backend that only moves encrypted bytes) belongs here, but the hosted service — billing, sync-key->namespace mapping, per-user isolation, Lemon Squeezy webhooks, transactional email — must live only in the private repo. Add scripts/check-no-private-cloud.sh, which git-greps tracked files for distinctive private-service signatures (service crate identity, module headers, billing/provider internals, server-side sync-key mapping SQL). The patterns are chosen so the legitimate public client — including its VESTIGE_CLOUD_* client env vars — does not match. Wired into CI via guard-no-private-cloud.yml on push/PR. Verified both directions: passes on the clean repo, fails (naming the markers) when real private webhook.rs/keys.rs are introduced. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/guard-no-private-cloud.yml | 25 ++++++ scripts/check-no-private-cloud.sh | 83 ++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 .github/workflows/guard-no-private-cloud.yml create mode 100755 scripts/check-no-private-cloud.sh diff --git a/.github/workflows/guard-no-private-cloud.yml b/.github/workflows/guard-no-private-cloud.yml new file mode 100644 index 0000000..515e959 --- /dev/null +++ b/.github/workflows/guard-no-private-cloud.yml @@ -0,0 +1,25 @@ +name: Guard — No Private Cloud Code + +# Fails if private Vestige Cloud *service* code (billing, sync-key/namespace +# mapping, Lemon Squeezy webhooks, transactional email) ever lands in this +# public repo. The public cloud *client* is allowed and does not trip this. +on: + push: + branches: [main, feat/cloud-sync-mvp] + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + guard: + name: No private cloud service code + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Scan for private cloud service markers + run: ./scripts/check-no-private-cloud.sh diff --git a/scripts/check-no-private-cloud.sh b/scripts/check-no-private-cloud.sh new file mode 100755 index 0000000..d666dc5 --- /dev/null +++ b/scripts/check-no-private-cloud.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# check-no-private-cloud.sh — Fail if private Vestige Cloud *service* code leaks +# into this public repository. +# +# Vestige Cloud is split: +# - PUBLIC client (this repo): a thin HTTP sync backend that only moves +# encrypted bytes and presents an opaque bearer token. +# Legitimate. Reads VESTIGE_CLOUD_ENDPOINT / _SYNC_KEY / +# _ENCRYPTION_KEY env vars on the client side. +# - PRIVATE service (separate repo, no public remote): the hosted blob +# service that owns sync-key -> namespace mapping, per-user +# isolation, Lemon Squeezy billing webhooks, and +# transactional email. This MUST NEVER be committed here. +# +# This guard scans only tracked files (git grep) for distinctive *service* +# signatures — module headers, billing/provider internals, and server-side +# auth/namespace mapping — chosen so the legitimate public client does NOT +# match. It deliberately does NOT match the VESTIGE_CLOUD_* client env-var +# prefix, which the public client uses legitimately. +set -u + +cd "$(git rev-parse --show-toplevel)" || { + echo "check-no-private-cloud: not inside a git repository" >&2 + exit 2 +} + +# Distinctive private-service signatures. Each is a fixed string (grep -F via +# -e with --fixed-strings) that appears in the private vestige-cloud service +# and must never appear in this public repo. Keep these specific. +PATTERNS=( + # Service crate identity / entrypoint + 'name = "vestige-cloud"' + 'Vestige Cloud — hosted managed-sync blob service' + # Service module headers + 'Sync-key store and authentication' + 'Blob storage for the managed-sync service' + 'Lemon Squeezy webhook handling' + 'Transactional email delivery via Resend' + # Billing / provider internals (server-only) + 'LEMONSQUEEZY_WEBHOOK_SECRET' + 'lemonsqueezy' + # Server-side sync-key -> namespace mapping (the authoritative mapping that + # by design lives ONLY in the hosted service, never the client) + 'sync_keys SET key_hash' +) + +# Files this guard itself lives in / references the patterns must be excluded, +# or it would always flag itself. Exclude this script and any allowlist doc. +EXCLUDES=( + ':(exclude)scripts/check-no-private-cloud.sh' + ':(exclude).github/workflows/guard-no-private-cloud.yml' +) + +violations=0 +report="" + +for pat in "${PATTERNS[@]}"; do + # -I skip binary, -n line numbers, -F fixed string, -i case-insensitive. + if hits=$(git grep -Ini -F -e "$pat" -- "${EXCLUDES[@]}" 2>/dev/null); then + if [ -n "$hits" ]; then + violations=$((violations + 1)) + report+=$'\n'" ✗ private-service marker found: \"$pat\""$'\n' + report+="$(printf '%s\n' "$hits" | sed 's/^/ /')"$'\n' + fi + fi +done + +if [ "$violations" -ne 0 ]; then + echo "════════════════════════════════════════════════════════════════════" + echo " PRIVATE CLOUD SERVICE CODE DETECTED IN PUBLIC REPO" + echo "════════════════════════════════════════════════════════════════════" + echo "$report" + echo "════════════════════════════════════════════════════════════════════" + echo " The hosted Vestige Cloud service (billing, namespace mapping," + echo " per-user isolation) must live ONLY in the private repo, never here." + echo " Remove the file(s) above from this repo. If a match is a false" + echo " positive, refine the pattern in scripts/check-no-private-cloud.sh." + echo "════════════════════════════════════════════════════════════════════" + exit 1 +fi + +echo "check-no-private-cloud: OK — no private Vestige Cloud service code in public repo" +exit 0