Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
154 lines
3.7 KiB
Bash
Executable File
154 lines
3.7 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# DSS - Environment Variable Analysis
|
|
# Checks environment configuration (names only, no values)
|
|
#
|
|
|
|
set -e
|
|
|
|
PROJECT_PATH="${1:-.}"
|
|
|
|
# Common env vars that should be set
|
|
REQUIRED_VARS=(
|
|
"NODE_ENV"
|
|
"PORT"
|
|
)
|
|
|
|
# Optional but recommended
|
|
RECOMMENDED_VARS=(
|
|
"LOG_LEVEL"
|
|
"DATABASE_URL"
|
|
"API_URL"
|
|
)
|
|
|
|
# Sensitive vars that should NOT be in code
|
|
SENSITIVE_PATTERNS=(
|
|
"API_KEY"
|
|
"SECRET"
|
|
"PASSWORD"
|
|
"TOKEN"
|
|
"PRIVATE"
|
|
"AWS_"
|
|
"FIGMA_TOKEN"
|
|
)
|
|
|
|
# Find env files
|
|
find_env_files() {
|
|
local files=()
|
|
|
|
for pattern in ".env" ".env.local" ".env.development" ".env.production" ".env.example"; do
|
|
if [[ -f "$PROJECT_PATH/$pattern" ]]; then
|
|
local var_count=$(grep -cE "^[A-Z_]+=" "$PROJECT_PATH/$pattern" 2>/dev/null || echo 0)
|
|
local has_values="false"
|
|
|
|
# Check if file has actual values (not just placeholders)
|
|
if grep -qE "^[A-Z_]+=.+" "$PROJECT_PATH/$pattern" 2>/dev/null; then
|
|
if ! grep -qE "^[A-Z_]+=(your_|<|placeholder)" "$PROJECT_PATH/$pattern" 2>/dev/null; then
|
|
has_values="true"
|
|
fi
|
|
fi
|
|
|
|
files+=("{\"file\":\"$pattern\",\"variables\":$var_count,\"has_real_values\":$has_values}")
|
|
fi
|
|
done
|
|
|
|
echo "${files[@]}"
|
|
}
|
|
|
|
# Get var names from env files (not values)
|
|
get_env_var_names() {
|
|
local vars=()
|
|
|
|
for file in "$PROJECT_PATH/.env"* 2>/dev/null; do
|
|
if [[ -f "$file" ]]; then
|
|
while IFS= read -r varname; do
|
|
if [[ -n "$varname" && ! " ${vars[*]} " =~ " $varname " ]]; then
|
|
vars+=("\"$varname\"")
|
|
fi
|
|
done < <(grep -oE "^[A-Z_][A-Z0-9_]*" "$file" 2>/dev/null)
|
|
fi
|
|
done
|
|
|
|
echo "${vars[@]}"
|
|
}
|
|
|
|
# Check for hardcoded sensitive vars in code
|
|
check_hardcoded_secrets() {
|
|
local findings=()
|
|
|
|
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
|
|
local found=$(grep -rEl "${pattern}.*=.*['\"][^'\"]+['\"]" "$PROJECT_PATH" \
|
|
--include="*.js" --include="*.ts" --include="*.py" \
|
|
! -path "*/node_modules/*" ! -path "*/.git/*" \
|
|
2>/dev/null | head -5)
|
|
|
|
if [[ -n "$found" ]]; then
|
|
while IFS= read -r file; do
|
|
if [[ -n "$file" ]]; then
|
|
findings+=("{\"file\":\"${file#$PROJECT_PATH/}\",\"pattern\":\"$pattern\"}")
|
|
fi
|
|
done <<< "$found"
|
|
fi
|
|
done
|
|
|
|
echo "${findings[@]}"
|
|
}
|
|
|
|
# Check current environment
|
|
check_current_env() {
|
|
local status=()
|
|
|
|
for var in "${REQUIRED_VARS[@]}"; do
|
|
if [[ -n "${!var}" ]]; then
|
|
status+=("{\"var\":\"$var\",\"status\":\"set\"}")
|
|
else
|
|
status+=("{\"var\":\"$var\",\"status\":\"missing\"}")
|
|
fi
|
|
done
|
|
|
|
for var in "${RECOMMENDED_VARS[@]}"; do
|
|
if [[ -n "${!var}" ]]; then
|
|
status+=("{\"var\":\"$var\",\"status\":\"set\",\"required\":false}")
|
|
fi
|
|
done
|
|
|
|
echo "${status[@]}"
|
|
}
|
|
|
|
# Build output
|
|
env_files=$(find_env_files)
|
|
var_names=$(get_env_var_names)
|
|
hardcoded=$(check_hardcoded_secrets)
|
|
current_env=$(check_current_env)
|
|
|
|
files_json=$(IFS=,; echo "${env_files[*]}")
|
|
names_json=$(IFS=,; echo "${var_names[*]}")
|
|
hardcoded_json=$(IFS=,; echo "${hardcoded[*]}")
|
|
current_json=$(IFS=,; echo "${current_env[*]}")
|
|
|
|
# Calculate readiness score
|
|
total_files=${#env_files[@]}
|
|
hardcoded_count=${#hardcoded[@]}
|
|
readiness="ready"
|
|
[[ $total_files -eq 0 ]] && readiness="missing_config"
|
|
[[ $hardcoded_count -gt 0 ]] && readiness="has_hardcoded_secrets"
|
|
|
|
cat <<EOF
|
|
{
|
|
"scan_type": "environment",
|
|
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
"project_path": "$PROJECT_PATH",
|
|
"readiness": "$readiness",
|
|
"env_files": [${files_json:-}],
|
|
"variables_defined": [${names_json:-}],
|
|
"current_environment": [${current_json:-}],
|
|
"hardcoded_secrets": [${hardcoded_json:-}],
|
|
"recommendations": [
|
|
"Use .env.example for template (no real values)",
|
|
"Add .env* to .gitignore",
|
|
"Use environment variables for all secrets",
|
|
"Consider using a secrets manager for production"
|
|
]
|
|
}
|
|
EOF
|