forked from bchanot/claude
chore(seo-data): install/make/doctor wiring + gitleaks allowlist for token store
This commit is contained in:
@@ -4,3 +4,12 @@
|
||||
# Used by: lib/toggle-external.sh enable|disable magic
|
||||
# Get a key at: https://21st.dev/magic (dashboard → API keys)
|
||||
MAGIC_API_KEY=your_21st_dev_magic_api_key_here
|
||||
|
||||
# ── Google SEO data layer (lib/seo-data) — used by /seo FULL ──
|
||||
# OAuth Desktop client: GCP console → APIs & Services → Credentials → OAuth client (Desktop).
|
||||
# Scope requested at consent: webmasters.readonly. One-time setup: make seo-connect
|
||||
GOOGLE_OAUTH_CLIENT_ID=<your-client-id.apps.googleusercontent.com>
|
||||
GOOGLE_OAUTH_CLIENT_SECRET=<your-client-secret>
|
||||
# CrUX + PageSpeed API key (GCP console → Credentials → API key, restricted to those APIs).
|
||||
# Get it: https://developer.chrome.com/docs/crux/api
|
||||
CRUX_API_KEY=<your-crux-api-key>
|
||||
|
||||
@@ -113,6 +113,11 @@ install-*.log
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# seo-data engine local artifacts (live under ~/.claude, never committed)
|
||||
.venv-seo-data/
|
||||
seo-data/tokens.json
|
||||
__pycache__/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
@@ -34,4 +34,7 @@ paths = [
|
||||
# for stray COPIES of secrets outside this file; flagging the vault
|
||||
# itself on every run is pure noise, not signal.
|
||||
'''(^|/)\.env$''',
|
||||
# seo-data OAuth token store — legitimate local secret (like ~/.claude/.env),
|
||||
# 0600, outside git. Allowlisted so `make scan-secrets` doesn't flag the vault.
|
||||
'''(^|/)\.claude/seo-data/tokens\.json$''',
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.PHONY: help install plugin link doctor update new-skill profile profile-list profile-current profile-reset onboard test scan-secrets
|
||||
.PHONY: help install plugin link doctor update new-skill profile profile-list profile-current profile-reset onboard test scan-secrets seo-connect
|
||||
|
||||
help: ## Show available commands
|
||||
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*## "}; {printf " make %-14s %s\n", $$1, $$2}'
|
||||
@@ -22,8 +22,14 @@ onboard: link ## Onboard an existing project (run from the project directory)
|
||||
@echo "Open Claude Code in your project directory and run: /onboard"
|
||||
@echo "Or with hints: /onboard Python FastAPI monorepo"
|
||||
|
||||
seo-connect: ## Connect a Google account for /seo FULL (creates venv, OAuth consent)
|
||||
@python3 -m venv "$$HOME/.claude/.venv-seo-data"
|
||||
@"$$HOME/.claude/.venv-seo-data/bin/pip" install -q -r lib/seo-data/requirements.txt
|
||||
@bash -c 'read -r -p "Label for this account (e.g. client-a): " label; \
|
||||
"$$HOME/.claude/.venv-seo-data/bin/python3" lib/seo-data/connect.py --label "$$label"'
|
||||
|
||||
test: ## Run deterministic tests (lib/tests/*.test.sh + lib/gitflow-test.sh + lib/tests/run-*.sh)
|
||||
@fail=0; for t in lib/tests/*.test.sh lib/gitflow-test.sh lib/tests/run-*.sh; do \
|
||||
@fail=0; for t in lib/tests/*.test.sh lib/seo-data/*.test.sh lib/gitflow-test.sh lib/tests/run-*.sh; do \
|
||||
echo "== $$t"; \
|
||||
case "$$(basename "$$t")" in \
|
||||
run-release-candidate.sh) RC_WORK=$$(mktemp -d) RC_TAG=1 bash "$$t" || fail=1 ;; \
|
||||
|
||||
@@ -400,6 +400,21 @@ fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ── seo-data (GSC/CrUX data layer) — non-fatal ──
|
||||
ENVF="$HOME/.claude/.env"
|
||||
if grep -qE '^[[:space:]]*(export[[:space:]]+)?CRUX_API_KEY=.' "$ENVF" 2>/dev/null; then
|
||||
pass "seo-data: CRUX_API_KEY present"
|
||||
else
|
||||
warn "seo-data: CRUX_API_KEY absent in ~/.claude/.env — /seo FULL falls back to lab PageSpeed"
|
||||
fi
|
||||
STORE="$HOME/.claude/seo-data/tokens.json"
|
||||
if [ -f "$STORE" ]; then
|
||||
N=$(python3 "$REPO/lib/seo-data/tokenstore.py" list --file "$STORE" 2>/dev/null | grep -o '"label"' | wc -l)
|
||||
pass "seo-data: $N Google account(s) connected"
|
||||
else
|
||||
warn "seo-data: no Google account connected (run: make seo-connect) — GSC data disabled"
|
||||
fi
|
||||
|
||||
# ────────────────────────────────────────────────────────────
|
||||
# Summary
|
||||
# ────────────────────────────────────────────────────────────
|
||||
|
||||
+10
@@ -106,6 +106,16 @@ echo ""
|
||||
echo "── Setting up symlinks..."
|
||||
bash "$REPO/link.sh"
|
||||
|
||||
# ── 5b. Optional: connect a Google account for /seo FULL ──
|
||||
echo ""
|
||||
if [ -f "$HOME/.claude/seo-data/tokens.json" ]; then
|
||||
ok "seo-data: a Google account is already connected"
|
||||
else
|
||||
info "SEO data layer (GSC + CrUX) is optional. To enable real Search Console"
|
||||
info "data in /seo FULL: add GOOGLE_OAUTH_* + CRUX_API_KEY to ~/.claude/.env,"
|
||||
info "then run: make seo-connect"
|
||||
fi
|
||||
|
||||
# ── 6. Install plugins ──
|
||||
echo ""
|
||||
echo "── Installing plugins..."
|
||||
|
||||
@@ -106,6 +106,17 @@ has "connect.persist wrote prop" "$L3" 'sc-domain:x.com'
|
||||
hasnt "connect.persist redacts" "$L3" 'RT_X'
|
||||
rm -rf "$TMP3"
|
||||
|
||||
echo "── wiring locks ──"
|
||||
tf() { if grep -qF -- "$3" "$2" 2>/dev/null; then ok "$1"; else no "$1" "missing: $3"; fi; }
|
||||
tf "env.example client id" "$REPO/.env.example" "GOOGLE_OAUTH_CLIENT_ID="
|
||||
tf "env.example crux key" "$REPO/.env.example" "CRUX_API_KEY="
|
||||
tf "makefile seo-connect" "$REPO/Makefile" "seo-connect:"
|
||||
tf "makefile discovers test" "$REPO/Makefile" "lib/seo-data/*.test.sh"
|
||||
tf "install prompts connect" "$REPO/install.sh" "make seo-connect"
|
||||
tf "doctor checks seo-data" "$REPO/doctor.sh" "seo-data"
|
||||
tf "gitleaks allowlist store" "$REPO/.gitleaks.toml" "seo-data/tokens"
|
||||
tf "gitignore venv" "$REPO/.gitignore" ".venv-seo-data"
|
||||
|
||||
echo ""
|
||||
echo "seo-data engine: $PASS pass, $FAIL fail"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
|
||||
Reference in New Issue
Block a user