guardian-framework 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +463 -0
- package/dist/cli.js +12958 -0
- package/dist/exports.js +12765 -0
- package/package.json +61 -0
- package/templates/languages/go-patterns.md +411 -0
- package/templates/languages/java-patterns.md +545 -0
- package/templates/languages/python-patterns.md +312 -0
- package/templates/languages/rust-patterns.md +232 -0
- package/templates/languages/typescript-patterns.md +313 -0
- package/templates/pi/INDEX.md +437 -0
- package/templates/pi/agent/AGENTS.md +166 -0
- package/templates/pi/agents/architecture-coordinator.md +40 -0
- package/templates/pi/agents/architecture-validator.md +36 -0
- package/templates/pi/agents/bootstrap-implementer.md +37 -0
- package/templates/pi/agents/issue-factory.md +31 -0
- package/templates/pi/agents/operations-validator.md +32 -0
- package/templates/pi/agents/security-validator.md +33 -0
- package/templates/pi/architecture/CHANGELOG.md +78 -0
- package/templates/pi/architecture/decisions/ADR-template.md +76 -0
- package/templates/pi/architecture/diagrams/system-overview.md +159 -0
- package/templates/pi/architecture/modules/module-template.md +152 -0
- package/templates/pi/context/checklists.md +91 -0
- package/templates/pi/context/domain-workflow.md +180 -0
- package/templates/pi/context/output-formats.md +135 -0
- package/templates/pi/context/patterns-base.md +47 -0
- package/templates/pi/context/patterns.md +38 -0
- package/templates/pi/context/project.md +88 -0
- package/templates/pi/domain/exploration.md +93 -0
- package/templates/pi/domain/ubiquitous-language.md +24 -0
- package/templates/pi/extensions/architect-lib/generators.ts +528 -0
- package/templates/pi/extensions/architect-lib/helpers.ts +344 -0
- package/templates/pi/extensions/architect-lib/types.ts +117 -0
- package/templates/pi/extensions/architect.ts +1425 -0
- package/templates/pi/extensions/ask-user-question.ts +579 -0
- package/templates/pi/extensions/bash-guard.ts +556 -0
- package/templates/pi/extensions/config-reload.ts +115 -0
- package/templates/pi/extensions/coordinator.ts +304 -0
- package/templates/pi/extensions/curator.ts +543 -0
- package/templates/pi/extensions/domain-explorer.ts +990 -0
- package/templates/pi/extensions/filechanges.ts +656 -0
- package/templates/pi/extensions/goal-loop.ts +717 -0
- package/templates/pi/extensions/hooks.ts +452 -0
- package/templates/pi/extensions/kanban.ts +547 -0
- package/templates/pi/extensions/pipeline.ts +1246 -0
- package/templates/pi/extensions/plan-mode.ts +209 -0
- package/templates/pi/extensions/project-scaffolder.ts +284 -0
- package/templates/pi/extensions/read-only-mode.ts +192 -0
- package/templates/pi/extensions/redaction.ts +128 -0
- package/templates/pi/extensions/session-persistence.ts +174 -0
- package/templates/pi/extensions/slash-commands.ts +229 -0
- package/templates/pi/extensions/snippets.ts +201 -0
- package/templates/pi/extensions/validation-runner.ts +100 -0
- package/templates/pi/github/agents/architecture-coordinator.agent.md +27 -0
- package/templates/pi/github/agents/architecture-validator.agent.md +20 -0
- package/templates/pi/github/agents/bootstrap-implementer.agent.md +20 -0
- package/templates/pi/github/agents/epic-planner.agent.md +70 -0
- package/templates/pi/github/agents/issue-factory.agent.md +20 -0
- package/templates/pi/github/agents/operations-validator.agent.md +20 -0
- package/templates/pi/github/agents/security-validator.agent.md +20 -0
- package/templates/pi/github/copilot/settings.json +16 -0
- package/templates/pi/github/copilot-instructions.md +155 -0
- package/templates/pi/github/instructions/architecture.instructions.md +71 -0
- package/templates/pi/github/instructions/validation.instructions.md +69 -0
- package/templates/pi/github/workflows/01-planning-workflow.md +75 -0
- package/templates/pi/github/workflows/02-issue-generation-workflow.md +69 -0
- package/templates/pi/github/workflows/03-implementation-workflow.md +80 -0
- package/templates/pi/github/workflows/04-validation-workflow.md +68 -0
- package/templates/pi/preflight_report.json +99 -0
- package/templates/pi/prompts/blueprint-update.md +262 -0
- package/templates/pi/prompts/blueprint-validate.md +218 -0
- package/templates/pi/prompts/bug-fix.md +50 -0
- package/templates/pi/prompts/ci-blueprint.md +131 -0
- package/templates/pi/prompts/context-refresh.md +258 -0
- package/templates/pi/prompts/epic-plan.md +356 -0
- package/templates/pi/prompts/epic-template.md +186 -0
- package/templates/pi/prompts/feature-development.md +131 -0
- package/templates/pi/prompts/git-issues.md +243 -0
- package/templates/pi/prompts/hotfix.md +71 -0
- package/templates/pi/prompts/issue-closeout.md +342 -0
- package/templates/pi/prompts/issue-draft.md +218 -0
- package/templates/pi/prompts/issue-implementation-series.md +173 -0
- package/templates/pi/prompts/issue-merge.md +372 -0
- package/templates/pi/prompts/issue-template-set.md +392 -0
- package/templates/pi/prompts/issue-template.md +207 -0
- package/templates/pi/prompts/pattern-extract.md +269 -0
- package/templates/pi/prompts/plan-to-issues.md +430 -0
- package/templates/pi/prompts/refactoring.md +82 -0
- package/templates/pi/prompts/scope-analyzer.md +254 -0
- package/templates/pi/prompts/sync-check.md +230 -0
- package/templates/pi/scripts/categorize-issues.sh +171 -0
- package/templates/pi/scripts/ci/check_architecture_conformance.sh +748 -0
- package/templates/pi/scripts/ci/check_planning_packet.py +228 -0
- package/templates/pi/scripts/ci/run_hardening_stages.sh +264 -0
- package/templates/pi/scripts/ci/run_preflight.sh +649 -0
- package/templates/pi/scripts/ci/run_stage.sh +193 -0
- package/templates/pi/scripts/ci/stage_docs_policy.sh +82 -0
- package/templates/pi/scripts/ci/stage_integration.sh +3 -0
- package/templates/pi/scripts/ci/stage_lint.sh +130 -0
- package/templates/pi/scripts/ci/stage_migration_verify.sh +3 -0
- package/templates/pi/scripts/ci/stage_package_build.sh +3 -0
- package/templates/pi/scripts/ci/stage_release_readiness.sh +3 -0
- package/templates/pi/scripts/ci/stage_remaining.sh +242 -0
- package/templates/pi/scripts/ci/stage_security.sh +3 -0
- package/templates/pi/scripts/ci/stage_static_analysis.sh +114 -0
- package/templates/pi/scripts/ci/stage_unit.sh +119 -0
- package/templates/pi/scripts/ci/validate_agent_output.py +181 -0
- package/templates/pi/scripts/ci/validate_agent_output.sh +243 -0
- package/templates/pi/scripts/create-feature-branch.sh +136 -0
- package/templates/pi/scripts/create-mr.sh +117 -0
- package/templates/pi/scripts/fetch-issues.sh +131 -0
- package/templates/pi/scripts/generate-architecture.sh +161 -0
- package/templates/pi/scripts/git/close-epic.sh +69 -0
- package/templates/pi/scripts/git/close-issue.sh +35 -0
- package/templates/pi/scripts/git/create-tracking-issue.sh +174 -0
- package/templates/pi/scripts/git/link-issue-to-epic.sh +51 -0
- package/templates/pi/scripts/git/update-tracking-issue.sh +66 -0
- package/templates/pi/scripts/languages/go/validate-architecture.sh +139 -0
- package/templates/pi/scripts/languages/go/validate-canonical.sh +129 -0
- package/templates/pi/scripts/languages/go/validate-ci.sh +132 -0
- package/templates/pi/scripts/languages/go/validate-integration.sh +156 -0
- package/templates/pi/scripts/languages/go/validate-operations.sh +146 -0
- package/templates/pi/scripts/languages/go/validate-security.sh +135 -0
- package/templates/pi/scripts/languages/go/validate-tests.sh +125 -0
- package/templates/pi/scripts/languages/java/validate-annotations.sh +185 -0
- package/templates/pi/scripts/languages/java/validate-architecture.sh +159 -0
- package/templates/pi/scripts/languages/java/validate-canonical.sh +114 -0
- package/templates/pi/scripts/languages/java/validate-ci.sh +269 -0
- package/templates/pi/scripts/languages/java/validate-integration.sh +149 -0
- package/templates/pi/scripts/languages/java/validate-operations.sh +142 -0
- package/templates/pi/scripts/languages/java/validate-security.sh +174 -0
- package/templates/pi/scripts/languages/java/validate-spring-architecture.sh +227 -0
- package/templates/pi/scripts/languages/java/validate-tests.sh +159 -0
- package/templates/pi/scripts/languages/python/validate-architecture.sh +99 -0
- package/templates/pi/scripts/languages/python/validate-canonical.sh +124 -0
- package/templates/pi/scripts/languages/python/validate-ci.sh +130 -0
- package/templates/pi/scripts/languages/python/validate-integration.sh +119 -0
- package/templates/pi/scripts/languages/python/validate-operations.sh +107 -0
- package/templates/pi/scripts/languages/python/validate-security.sh +68 -0
- package/templates/pi/scripts/languages/python/validate-tests.sh +102 -0
- package/templates/pi/scripts/languages/rust/validate-architecture.sh +188 -0
- package/templates/pi/scripts/languages/rust/validate-canonical.sh +146 -0
- package/templates/pi/scripts/languages/rust/validate-ci.sh +147 -0
- package/templates/pi/scripts/languages/rust/validate-integration.sh +149 -0
- package/templates/pi/scripts/languages/rust/validate-operations.sh +154 -0
- package/templates/pi/scripts/languages/rust/validate-security.sh +153 -0
- package/templates/pi/scripts/languages/rust/validate-tests.sh +150 -0
- package/templates/pi/scripts/languages/typescript/validate-architecture.sh +157 -0
- package/templates/pi/scripts/languages/typescript/validate-canonical.sh +135 -0
- package/templates/pi/scripts/languages/typescript/validate-ci.sh +244 -0
- package/templates/pi/scripts/languages/typescript/validate-integration.sh +166 -0
- package/templates/pi/scripts/languages/typescript/validate-operations.sh +162 -0
- package/templates/pi/scripts/languages/typescript/validate-security.sh +169 -0
- package/templates/pi/scripts/languages/typescript/validate-tests.sh +158 -0
- package/templates/pi/scripts/merge-mr.sh +95 -0
- package/templates/pi/scripts/mr-validation.sh +228 -0
- package/templates/pi/scripts/validate-architecture-readiness.sh +153 -0
- package/templates/pi/scripts/validate-architecture.sh +22 -0
- package/templates/pi/scripts/validate-canonical.sh +22 -0
- package/templates/pi/scripts/validate-ci.sh +37 -0
- package/templates/pi/scripts/validate-integration.sh +22 -0
- package/templates/pi/scripts/validate-operations.sh +22 -0
- package/templates/pi/scripts/validate-security.sh +22 -0
- package/templates/pi/scripts/validate-tests.sh +22 -0
- package/templates/pi/scripts/validate-ubiquitous-language.sh +291 -0
- package/templates/pi/scripts/validation-cache.sh +139 -0
- package/templates/pi/skills/agents/architecture-coordinator.md +178 -0
- package/templates/pi/skills/agents/architecture-generator.md +79 -0
- package/templates/pi/skills/agents/architecture-validator.md +74 -0
- package/templates/pi/skills/agents/ci-mr-validator.md +46 -0
- package/templates/pi/skills/agents/code-developer.md +76 -0
- package/templates/pi/skills/agents/commit.md +46 -0
- package/templates/pi/skills/agents/curator.md +71 -0
- package/templates/pi/skills/agents/debug.md +59 -0
- package/templates/pi/skills/agents/documentation-maintainer.md +36 -0
- package/templates/pi/skills/agents/goal-loop.md +125 -0
- package/templates/pi/skills/agents/hooks.md +122 -0
- package/templates/pi/skills/agents/integration-validator.md +35 -0
- package/templates/pi/skills/agents/issue-creator.md +75 -0
- package/templates/pi/skills/agents/issue-factory.md +143 -0
- package/templates/pi/skills/agents/kanban.md +85 -0
- package/templates/pi/skills/agents/land.md +59 -0
- package/templates/pi/skills/agents/operations-validator.md +43 -0
- package/templates/pi/skills/agents/pipeline.md +113 -0
- package/templates/pi/skills/agents/plan-mode.md +77 -0
- package/templates/pi/skills/agents/pull.md +40 -0
- package/templates/pi/skills/agents/push.md +41 -0
- package/templates/pi/skills/agents/security-validator.md +85 -0
- package/templates/pi/skills/agents/session-persistence.md +119 -0
- package/templates/pi/skills/agents/slash-commands.md +117 -0
- package/templates/pi/skills/agents/snippets.md +99 -0
- package/templates/pi/skills/agents/subagent-registry.md +78 -0
- package/templates/pi/skills/agents/test-validator.md +42 -0
- package/templates/pi/skills/validators/architecture-validator.md +43 -0
- package/templates/pi/skills/validators/ci-validator.md +27 -0
- package/templates/pi/skills/validators/context-compaction.md +73 -0
- package/templates/pi/skills/validators/integration-validator.md +38 -0
- package/templates/pi/skills/validators/model-registry.md +96 -0
- package/templates/pi/skills/validators/operations-validator.md +34 -0
- package/templates/pi/skills/validators/security-guards.md +72 -0
- package/templates/pi/skills/validators/security-validator.md +41 -0
- package/templates/pi/skills/validators/system-prompt-tiers.md +69 -0
- package/templates/pi/skills/validators/test-validator.md +33 -0
- package/templates/pi/types.ts +62 -0
- package/templates/pi/validators/README.md +93 -0
- package/templates/pi/validators/default.toml +209 -0
- package/templates/pi/validators/spring.toml +142 -0
- package/templates/pi/workpad.md +53 -0
- package/templates/project/java/Dockerfile +14 -0
- package/templates/project/java/README.md +40 -0
- package/templates/project/java/pom.xml +132 -0
- package/templates/project/typescript/Dockerfile +15 -0
- package/templates/project/typescript/README.md +29 -0
- package/templates/project/typescript/package.json +23 -0
- package/templates/project/typescript/tsconfig.json +21 -0
- package/templates/workflow.md +123 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# validate-security.sh — Java (Spring Boot Security)
|
|
4
|
+
# ============================================================================
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
PASS_COUNT=0; ERRORS=(); WARNINGS=()
|
|
8
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
9
|
+
pass() { echo -e "${GREEN}✅ PASS${NC} $1"; PASS_COUNT=$((PASS_COUNT + 1)); }
|
|
10
|
+
fail() { echo -e "${RED}❌ FAIL${NC} $1"; ERRORS+=("$1"); }
|
|
11
|
+
warn() { echo -e "${YELLOW}⚠️ WARN${NC} $1"; WARNINGS+=("$1"); }
|
|
12
|
+
|
|
13
|
+
echo "============================================"
|
|
14
|
+
echo " Security Validation (Java)"
|
|
15
|
+
echo "============================================"
|
|
16
|
+
echo ""
|
|
17
|
+
|
|
18
|
+
SRC_DIR="${1:-src/main/java}"
|
|
19
|
+
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
# @PreAuthorize Coverage
|
|
22
|
+
# ---------------------------------------------------------------------------
|
|
23
|
+
echo "--- @PreAuthorize Coverage ---"
|
|
24
|
+
if [ -d "$SRC_DIR" ]; then
|
|
25
|
+
CONTROLLER_FILES=$(find "$SRC_DIR" -name "*Controller.java" 2>/dev/null)
|
|
26
|
+
if [ -n "$CONTROLLER_FILES" ]; then
|
|
27
|
+
TOTAL_CONTROLLERS=$(echo "$CONTROLLER_FILES" | wc -l | tr -d ' ')
|
|
28
|
+
PROTECTED_COUNT=0
|
|
29
|
+
for f in $CONTROLLER_FILES; do
|
|
30
|
+
if grep -q "@PreAuthorize\|@Secured\|@RolesAllowed" "$f" 2>/dev/null; then
|
|
31
|
+
PROTECTED_COUNT=$((PROTECTED_COUNT + 1))
|
|
32
|
+
fi
|
|
33
|
+
done
|
|
34
|
+
if [ "$PROTECTED_COUNT" -eq "$TOTAL_CONTROLLERS" ]; then
|
|
35
|
+
pass "All $TOTAL_CONTROLLERS controllers have method-level security"
|
|
36
|
+
elif [ "$PROTECTED_COUNT" -gt 0 ]; then
|
|
37
|
+
warn "$PROTECTED_COUNT of $TOTAL_CONTROLLERS controllers have method-level security ($((TOTAL_CONTROLLERS - PROTECTED_COUNT)) unprotected)"
|
|
38
|
+
else
|
|
39
|
+
warn "No controllers have @PreAuthorize/@Secured annotations"
|
|
40
|
+
fi
|
|
41
|
+
else
|
|
42
|
+
pass "No controllers found, skipping @PreAuthorize check"
|
|
43
|
+
fi
|
|
44
|
+
else
|
|
45
|
+
warn "No source directory found"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# CSRF Configuration
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
echo ""
|
|
52
|
+
echo "--- CSRF Configuration ---"
|
|
53
|
+
SECURITY_CONFIG=$(find . -name "*SecurityConfig*" -o -name "*WebSecurityConfig*" -o -name "*SecurityConfiguration*" 2>/dev/null | head -5)
|
|
54
|
+
if [ -n "$SECURITY_CONFIG" ]; then
|
|
55
|
+
CSRF_DISABLED=0
|
|
56
|
+
for f in $SECURITY_CONFIG; do
|
|
57
|
+
if grep -qi "csrf.*disable\|\.csrf()" "$f" 2>/dev/null; then
|
|
58
|
+
CSRF_DISABLED=$((CSRF_DISABLED + 1))
|
|
59
|
+
fi
|
|
60
|
+
done
|
|
61
|
+
if [ "$CSRF_DISABLED" -gt 0 ]; then
|
|
62
|
+
warn "CSRF protection disabled in $CSRF_DISABLED config(s) — verify this is intentional (common for REST APIs)"
|
|
63
|
+
else
|
|
64
|
+
pass "CSRF protection not explicitly disabled (default enabled)"
|
|
65
|
+
fi
|
|
66
|
+
else
|
|
67
|
+
warn "No security configuration class found"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
# CORS Configuration
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
echo ""
|
|
74
|
+
echo "--- CORS Configuration ---"
|
|
75
|
+
if [ -n "$SECURITY_CONFIG" ]; then
|
|
76
|
+
CORS_CONFIGURED=0
|
|
77
|
+
for f in $SECURITY_CONFIG; do
|
|
78
|
+
if grep -qi "cors\|\.cors()" "$f" 2>/dev/null; then
|
|
79
|
+
CORS_CONFIGURED=$((CORS_CONFIGURED + 1))
|
|
80
|
+
fi
|
|
81
|
+
done
|
|
82
|
+
if [ "$CORS_CONFIGURED" -gt 0 ]; then
|
|
83
|
+
pass "CORS is explicitly configured in security config"
|
|
84
|
+
else
|
|
85
|
+
warn "CORS not explicitly configured (may use defaults)"
|
|
86
|
+
fi
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# ---------------------------------------------------------------------------
|
|
90
|
+
# Dependency Vulnerabilities (Maven/Gradle)
|
|
91
|
+
# ---------------------------------------------------------------------------
|
|
92
|
+
echo ""
|
|
93
|
+
echo "--- Dependency Vulnerabilities ---"
|
|
94
|
+
if [ -f "pom.xml" ]; then
|
|
95
|
+
if command -v mvn &>/dev/null; then
|
|
96
|
+
pass "Maven project — run 'mvn dependency-check:check' for full audit"
|
|
97
|
+
elif [ -f "mvnw" ]; then
|
|
98
|
+
pass "Maven Wrapper project — run './mvnw dependency-check:check' for full audit"
|
|
99
|
+
else
|
|
100
|
+
warn "Maven project but neither mvn nor mvnw found"
|
|
101
|
+
fi
|
|
102
|
+
elif [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then
|
|
103
|
+
if command -v gradle &>/dev/null; then
|
|
104
|
+
pass "Gradle project — run 'gradle dependencyCheck' for full audit"
|
|
105
|
+
elif [ -f "gradlew" ]; then
|
|
106
|
+
pass "Gradle Wrapper project — run './gradlew dependencyCheck' for full audit"
|
|
107
|
+
else
|
|
108
|
+
warn "Gradle project but neither gradle nor gradlew found"
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# ---------------------------------------------------------------------------
|
|
113
|
+
# Sensitive Configuration
|
|
114
|
+
# ---------------------------------------------------------------------------
|
|
115
|
+
echo ""
|
|
116
|
+
echo "--- Sensitive Configuration ---"
|
|
117
|
+
SECRETS_FOUND=0
|
|
118
|
+
for pattern in "password" "secret" "api.key" "token" "jwt.secret"; do
|
|
119
|
+
MATCHES=$(grep -rn "$pattern" application.yml application.yaml application.properties 2>/dev/null | grep -v "example\|placeholder\|#" || true)
|
|
120
|
+
if [ -n "$MATCHES" ]; then
|
|
121
|
+
SECRETS_FOUND=$((SECRETS_FOUND + 1))
|
|
122
|
+
fi
|
|
123
|
+
done
|
|
124
|
+
if [ "$SECRETS_FOUND" -gt 0 ]; then
|
|
125
|
+
warn "Sensitive configuration keys found (password/secret/token) — verify they use external secrets"
|
|
126
|
+
else
|
|
127
|
+
pass "No hardcoded secrets detected in configuration files"
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# ---------------------------------------------------------------------------
|
|
131
|
+
# @Query Injection
|
|
132
|
+
# ---------------------------------------------------------------------------
|
|
133
|
+
echo ""
|
|
134
|
+
echo "--- @Query Safety ---"
|
|
135
|
+
if [ -d "$SRC_DIR" ]; then
|
|
136
|
+
UNSAFE_QUERIES=0
|
|
137
|
+
for f in $(find "$SRC_DIR" -name "*.java" 2>/dev/null); do
|
|
138
|
+
if grep -qE "@Query\s*\(\s*\"SELECT" "$f" 2>/dev/null; then
|
|
139
|
+
if grep -qE "#\{\s*.*param\}|:\s*.*Param|@Param" "$f" 2>/dev/null; then
|
|
140
|
+
: # uses parameterized queries
|
|
141
|
+
else
|
|
142
|
+
warn "Potential unsafe query in $f (consider using @Param for parameterized queries)"
|
|
143
|
+
UNSAFE_QUERIES=$((UNSAFE_QUERIES + 1))
|
|
144
|
+
fi
|
|
145
|
+
fi
|
|
146
|
+
done
|
|
147
|
+
if [ "$UNSAFE_QUERIES" -eq 0 ]; then
|
|
148
|
+
pass "No obviously unsafe @Query patterns found"
|
|
149
|
+
fi
|
|
150
|
+
else
|
|
151
|
+
pass "No source directory found, skipping @Query check"
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
# ---------------------------------------------------------------------------
|
|
155
|
+
# Summary
|
|
156
|
+
# ---------------------------------------------------------------------------
|
|
157
|
+
echo ""
|
|
158
|
+
echo "============================================"
|
|
159
|
+
echo " Summary"
|
|
160
|
+
echo "============================================"
|
|
161
|
+
echo -e " Passed: ${GREEN}${PASS_COUNT}${NC}"
|
|
162
|
+
echo -e " Failed: ${RED}${#ERRORS[@]}${NC}"
|
|
163
|
+
echo ""
|
|
164
|
+
|
|
165
|
+
if [ ${#ERRORS[@]} -gt 0 ]; then
|
|
166
|
+
echo "FAILURES:"
|
|
167
|
+
for err in "${ERRORS[@]}"; do
|
|
168
|
+
echo " - $err"
|
|
169
|
+
done
|
|
170
|
+
exit 1
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
echo -e "${GREEN}Security validation passed.${NC}"
|
|
174
|
+
exit 0
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# validate-spring-architecture.sh — Spring Boot Package Ring Enforcement
|
|
4
|
+
# ============================================================================
|
|
5
|
+
#
|
|
6
|
+
# Package Ring Definitions (shared with validate-annotations.sh):
|
|
7
|
+
# domain/ → Zero external dependencies (no imports outside domain)
|
|
8
|
+
# application/ → Only depends on domain/
|
|
9
|
+
# infrastructure/ → Depends on application/ and domain/ only
|
|
10
|
+
# interfaces/ → Web layer, depends on application/ only
|
|
11
|
+
#
|
|
12
|
+
# Convention: com.{project}.{layer}.{component}
|
|
13
|
+
# Example: com.myapp.domain.model, com.myapp.application.usecase
|
|
14
|
+
#
|
|
15
|
+
# Architecture mode: reads archMode from guardian-manifest.json
|
|
16
|
+
# strict — domain/ must have zero external deps (default)
|
|
17
|
+
# simplified — domain/ may contain concrete providers (downgraded to warnings)
|
|
18
|
+
# ============================================================================
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
PASS_COUNT=0; ERRORS=(); WARNINGS=()
|
|
22
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
23
|
+
pass() { echo -e "${GREEN}✅ PASS${NC} $1"; PASS_COUNT=$((PASS_COUNT + 1)); }
|
|
24
|
+
fail() { echo -e "${RED}❌ FAIL${NC} $1"; ERRORS+=("$1"); }
|
|
25
|
+
warn() { echo -e "${YELLOW}⚠️ WARN${NC} $1"; WARNINGS+=("$1"); }
|
|
26
|
+
|
|
27
|
+
echo "============================================"
|
|
28
|
+
echo " Spring Architecture Ring Validation"
|
|
29
|
+
echo "============================================"
|
|
30
|
+
echo ""
|
|
31
|
+
|
|
32
|
+
ARCH_MODE="strict"
|
|
33
|
+
if [ -f "guardian-manifest.json" ]; then
|
|
34
|
+
ARCH_MODE=$(jq -r '.archMode // "strict"' guardian-manifest.json 2>/dev/null || echo "strict")
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
echo "Architecture mode: ${ARCH_MODE}"
|
|
38
|
+
echo ""
|
|
39
|
+
|
|
40
|
+
SRC_DIR="${1:-src/main/java}"
|
|
41
|
+
|
|
42
|
+
if [ ! -d "$SRC_DIR" ]; then
|
|
43
|
+
warn "No source directory found at $SRC_DIR"
|
|
44
|
+
echo ""
|
|
45
|
+
echo "============================================"
|
|
46
|
+
echo " Summary"
|
|
47
|
+
echo "============================================"
|
|
48
|
+
echo -e " Passed: ${GREEN}0${NC}"
|
|
49
|
+
echo -e " Failed: ${RED}0${NC}"
|
|
50
|
+
echo ""
|
|
51
|
+
exit 0
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# ============================================================================
|
|
55
|
+
# Step 1: Detect package rings
|
|
56
|
+
# ============================================================================
|
|
57
|
+
echo "--- Layer Discovery ---"
|
|
58
|
+
DOMAIN_DIR=$(find "$SRC_DIR" -type d -name "domain" 2>/dev/null | head -1)
|
|
59
|
+
APP_DIR=$(find "$SRC_DIR" -type d -name "application" 2>/dev/null | head -1)
|
|
60
|
+
INFRA_DIR=$(find "$SRC_DIR" -type d -name "infrastructure" 2>/dev/null | head -1)
|
|
61
|
+
WEB_DIR=$(find "$SRC_DIR" -type d \( -name "web" -o -name "interfaces" -o -name "controller" \) 2>/dev/null | head -1)
|
|
62
|
+
|
|
63
|
+
LAYER_COUNT=0
|
|
64
|
+
[ -n "$DOMAIN_DIR" ] && LAYER_COUNT=$((LAYER_COUNT + 1)) && echo " [✓] domain/"
|
|
65
|
+
[ -n "$APP_DIR" ] && LAYER_COUNT=$((LAYER_COUNT + 1)) && echo " [✓] application/"
|
|
66
|
+
[ -n "$INFRA_DIR" ] && LAYER_COUNT=$((LAYER_COUNT + 1)) && echo " [✓] infrastructure/"
|
|
67
|
+
[ -n "$WEB_DIR" ] && LAYER_COUNT=$((LAYER_COUNT + 1)) && echo " [✓] interfaces/web/"
|
|
68
|
+
|
|
69
|
+
if [ "$LAYER_COUNT" -ge 3 ]; then
|
|
70
|
+
pass "Clean Architecture layers detected ($LAYER_COUNT of 4)"
|
|
71
|
+
elif [ "$LAYER_COUNT" -ge 1 ]; then
|
|
72
|
+
pass "Partial layers detected ($LAYER_COUNT of 4)"
|
|
73
|
+
else
|
|
74
|
+
warn "No Clean Architecture layers detected"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# ============================================================================
|
|
78
|
+
# Step 2: Domain ring — must have zero external imports
|
|
79
|
+
# ============================================================================
|
|
80
|
+
echo ""
|
|
81
|
+
echo "--- Domain Ring: No External Dependencies ---"
|
|
82
|
+
if [ -n "$DOMAIN_DIR" ]; then
|
|
83
|
+
BAD_IMPORTS=0
|
|
84
|
+
for f in $(find "$DOMAIN_DIR" -name "*.java" 2>/dev/null); do
|
|
85
|
+
# Check for imports from outside domain
|
|
86
|
+
while IFS= read -r line; do
|
|
87
|
+
if echo "$line" | grep -qE "^(import\s+)([a-zA-Z0-9_.]+);$" 2>/dev/null; then
|
|
88
|
+
# Extract the package root (first 2-3 segments)
|
|
89
|
+
IMPORT_PKG=$(echo "$line" | sed 's/import \(.*\);/\1/' | cut -d'.' -f1-3 2>/dev/null)
|
|
90
|
+
FILE_PKG=$(grep "^package " "$f" 2>/dev/null | sed 's/package \(.*\);/\1/' | cut -d'.' -f1-3 2>/dev/null)
|
|
91
|
+
if [ -n "$IMPORT_PKG" ] && [ -n "$FILE_PKG" ] && [ "$IMPORT_PKG" != "$FILE_PKG" ]; then
|
|
92
|
+
# Check if import is from a different layer
|
|
93
|
+
IMPORT_LAYER=$(echo "$IMPORT_PKG" | rev | cut -d'.' -f1 | rev)
|
|
94
|
+
if [ "$IMPORT_LAYER" != "domain" ] && [ "$IMPORT_LAYER" != "model" ] && [ "$IMPORT_LAYER" != "validation" ]; then
|
|
95
|
+
# Skip Java/Spring standard library imports
|
|
96
|
+
if echo "$IMPORT_PKG" | grep -qE "^(java\.|javax\.|org\.springframework\.|org\.slf4j\.|com\.fasterxml\.)"; then
|
|
97
|
+
continue
|
|
98
|
+
fi
|
|
99
|
+
if [ "$ARCH_MODE" = "strict" ]; then
|
|
100
|
+
fail "Domain layer import from '$IMPORT_LAYER': ${f#./}"
|
|
101
|
+
else
|
|
102
|
+
warn "Domain layer import from '$IMPORT_LAYER': ${f#./} (allowed in simplified mode)"
|
|
103
|
+
fi
|
|
104
|
+
BAD_IMPORTS=$((BAD_IMPORTS + 1))
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
done < "$f"
|
|
109
|
+
done
|
|
110
|
+
if [ "$BAD_IMPORTS" -eq 0 ]; then
|
|
111
|
+
pass "Domain ring has no external dependencies (clean)"
|
|
112
|
+
fi
|
|
113
|
+
else
|
|
114
|
+
pass "No domain ring detected, skipping"
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
# ============================================================================
|
|
118
|
+
# Step 3: Application ring — only depends on domain
|
|
119
|
+
# ============================================================================
|
|
120
|
+
echo ""
|
|
121
|
+
echo "--- Application Ring: Only Depends on Domain ---"
|
|
122
|
+
if [ -n "$APP_DIR" ]; then
|
|
123
|
+
BAD_IMPORTS=0
|
|
124
|
+
for f in $(find "$APP_DIR" -name "*.java" 2>/dev/null); do
|
|
125
|
+
while IFS= read -r line; do
|
|
126
|
+
if echo "$line" | grep -qE "import\s+.*\.(infrastructure|web|interfaces|controller|repository)\." 2>/dev/null; then
|
|
127
|
+
# Skip Java/Spring standard imports
|
|
128
|
+
if echo "$line" | grep -qE "import\s+(java\.|javax\.|org\.springframework\.|org\.slf4j\.)"; then
|
|
129
|
+
continue
|
|
130
|
+
fi
|
|
131
|
+
fail "Application layer imports from non-domain layer: ${f#./}"
|
|
132
|
+
echo " $line"
|
|
133
|
+
BAD_IMPORTS=$((BAD_IMPORTS + 1))
|
|
134
|
+
fi
|
|
135
|
+
done < "$f"
|
|
136
|
+
done
|
|
137
|
+
if [ "$BAD_IMPORTS" -eq 0 ]; then
|
|
138
|
+
pass "Application ring only depends on domain (clean)"
|
|
139
|
+
fi
|
|
140
|
+
else
|
|
141
|
+
pass "No application ring detected, skipping"
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
# ============================================================================
|
|
145
|
+
# Step 4: Infrastructure ring — depends on domain + application only
|
|
146
|
+
# ============================================================================
|
|
147
|
+
echo ""
|
|
148
|
+
echo "--- Infrastructure Ring: Only Depends on Domain + Application ---"
|
|
149
|
+
if [ -n "$INFRA_DIR" ]; then
|
|
150
|
+
BAD_IMPORTS=0
|
|
151
|
+
for f in $(find "$INFRA_DIR" -name "*.java" 2>/dev/null); do
|
|
152
|
+
while IFS= read -r line; do
|
|
153
|
+
if echo "$line" | grep -qE "import\s+.*\.(web|interfaces|controller)\." 2>/dev/null; then
|
|
154
|
+
if echo "$line" | grep -qE "import\s+(java\.|javax\.|org\.springframework\.|org\.slf4j\.)"; then
|
|
155
|
+
continue
|
|
156
|
+
fi
|
|
157
|
+
fail "Infrastructure imports from web layer: ${f#./}"
|
|
158
|
+
echo " $line"
|
|
159
|
+
BAD_IMPORTS=$((BAD_IMPORTS + 1))
|
|
160
|
+
fi
|
|
161
|
+
done < "$f"
|
|
162
|
+
done
|
|
163
|
+
if [ "$BAD_IMPORTS" -eq 0 ]; then
|
|
164
|
+
pass "Infrastructure ring has no web layer imports (clean)"
|
|
165
|
+
fi
|
|
166
|
+
else
|
|
167
|
+
pass "No infrastructure ring detected, skipping"
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
# ============================================================================
|
|
171
|
+
# Step 5: Web/Interfaces ring — only depends on application
|
|
172
|
+
# ============================================================================
|
|
173
|
+
echo ""
|
|
174
|
+
echo "--- Web Ring: Only Depends on Application ---"
|
|
175
|
+
if [ -n "$WEB_DIR" ]; then
|
|
176
|
+
BAD_IMPORTS=0
|
|
177
|
+
for f in $(find "$WEB_DIR" -name "*.java" 2>/dev/null); do
|
|
178
|
+
while IFS= read -r line; do
|
|
179
|
+
if echo "$line" | grep -qE "import\s+.*\.(infrastructure|repository)\." 2>/dev/null; then
|
|
180
|
+
if echo "$line" | grep -qE "import\s+(java\.|javax\.|org\.springframework\.|org\.slf4j\.)"; then
|
|
181
|
+
continue
|
|
182
|
+
fi
|
|
183
|
+
fail "Web layer imports from infrastructure/repository: ${f#./}"
|
|
184
|
+
echo " $line"
|
|
185
|
+
BAD_IMPORTS=$((BAD_IMPORTS + 1))
|
|
186
|
+
fi
|
|
187
|
+
done < "$f"
|
|
188
|
+
done
|
|
189
|
+
if [ "$BAD_IMPORTS" -eq 0 ]; then
|
|
190
|
+
pass "Web ring has no infrastructure/repository imports (clean)"
|
|
191
|
+
fi
|
|
192
|
+
else
|
|
193
|
+
pass "No web ring detected, skipping"
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
# ============================================================================
|
|
197
|
+
# Step 6: Dependency direction summary
|
|
198
|
+
# ============================================================================
|
|
199
|
+
echo ""
|
|
200
|
+
echo "--- Dependency Direction Summary ---"
|
|
201
|
+
echo ""
|
|
202
|
+
echo " Domain/ → nothing outside domain"
|
|
203
|
+
echo " Application/ → domain/ only"
|
|
204
|
+
echo " Infrastructure/ → domain/ + application/"
|
|
205
|
+
echo " Web/ → application/ only"
|
|
206
|
+
echo ""
|
|
207
|
+
|
|
208
|
+
# ============================================================================
|
|
209
|
+
# Summary
|
|
210
|
+
# ============================================================================
|
|
211
|
+
echo "============================================"
|
|
212
|
+
echo " Summary"
|
|
213
|
+
echo "============================================"
|
|
214
|
+
echo -e " Passed: ${GREEN}${PASS_COUNT}${NC}"
|
|
215
|
+
echo -e " Failed: ${RED}${#ERRORS[@]}${NC}"
|
|
216
|
+
echo ""
|
|
217
|
+
|
|
218
|
+
if [ ${#ERRORS[@]} -gt 0 ]; then
|
|
219
|
+
echo "FAILURES:"
|
|
220
|
+
for err in "${ERRORS[@]}"; do
|
|
221
|
+
echo " - $err"
|
|
222
|
+
done
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
echo -e "${GREEN}Spring architecture validation passed.${NC}"
|
|
227
|
+
exit 0
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# validate-tests.sh — Java (Maven/Gradle)
|
|
4
|
+
# ============================================================================
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
PASS_COUNT=0; ERRORS=(); WARNINGS=()
|
|
8
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
9
|
+
pass() { echo -e "${GREEN}✅ PASS${NC} $1"; PASS_COUNT=$((PASS_COUNT + 1)); }
|
|
10
|
+
fail() { echo -e "${RED}❌ FAIL${NC} $1"; ERRORS+=("$1"); }
|
|
11
|
+
warn() { echo -e "${YELLOW}⚠️ WARN${NC} $1"; WARNINGS+=("$1"); }
|
|
12
|
+
|
|
13
|
+
echo "============================================"
|
|
14
|
+
echo " Test Validation (Java)"
|
|
15
|
+
echo "============================================"
|
|
16
|
+
echo ""
|
|
17
|
+
|
|
18
|
+
# Detect build tool
|
|
19
|
+
BUILD_TOOL=""
|
|
20
|
+
if [ -f "pom.xml" ]; then
|
|
21
|
+
BUILD_TOOL="maven"
|
|
22
|
+
elif [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then
|
|
23
|
+
BUILD_TOOL="gradle"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Unit Tests
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
echo "--- Unit Tests ---"
|
|
30
|
+
if [ -d "src/test" ] || [ -d "src/test/java" ]; then
|
|
31
|
+
if [ -z "$BUILD_TOOL" ]; then
|
|
32
|
+
warn "No build tool detected, skipping unit tests"
|
|
33
|
+
elif [ "$BUILD_TOOL" = "maven" ] && command -v mvn &>/dev/null; then
|
|
34
|
+
if mvn test -q -Dtest="*Test" 2>/dev/null; then
|
|
35
|
+
pass "Unit tests passed (mvn test)"
|
|
36
|
+
else
|
|
37
|
+
fail "Unit tests failed (mvn test)"
|
|
38
|
+
fi
|
|
39
|
+
elif [ "$BUILD_TOOL" = "gradle" ] && command -v gradle &>/dev/null; then
|
|
40
|
+
if gradle test --tests "*Test" -q 2>/dev/null; then
|
|
41
|
+
pass "Unit tests passed (gradle test)"
|
|
42
|
+
else
|
|
43
|
+
fail "Unit tests failed (gradle test)"
|
|
44
|
+
fi
|
|
45
|
+
elif [ "$BUILD_TOOL" = "maven" ] && [ -f "mvnw" ]; then
|
|
46
|
+
if ./mvnw test -q -Dtest="*Test" 2>/dev/null; then
|
|
47
|
+
pass "Unit tests passed (./mvnw test)"
|
|
48
|
+
else
|
|
49
|
+
fail "Unit tests failed (./mvnw test)"
|
|
50
|
+
fi
|
|
51
|
+
elif [ "$BUILD_TOOL" = "gradle" ] && [ -f "gradlew" ]; then
|
|
52
|
+
if ./gradlew test --tests "*Test" -q 2>/dev/null; then
|
|
53
|
+
pass "Unit tests passed (./gradlew test)"
|
|
54
|
+
else
|
|
55
|
+
fail "Unit tests failed (./gradlew test)"
|
|
56
|
+
fi
|
|
57
|
+
else
|
|
58
|
+
warn "No build tool executable available for unit tests"
|
|
59
|
+
fi
|
|
60
|
+
else
|
|
61
|
+
pass "No test directory (src/test) found, skipping tests"
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# ---------------------------------------------------------------------------
|
|
65
|
+
# Integration Tests
|
|
66
|
+
# ---------------------------------------------------------------------------
|
|
67
|
+
echo ""
|
|
68
|
+
echo "--- Integration Tests ---"
|
|
69
|
+
if [ -d "src/test" ]; then
|
|
70
|
+
if [ -z "$BUILD_TOOL" ]; then
|
|
71
|
+
pass "No build tool detected, skipping integration tests"
|
|
72
|
+
elif [ "$BUILD_TOOL" = "maven" ] && command -v mvn &>/dev/null; then
|
|
73
|
+
if mvn test -q -Dtest="*IT" 2>/dev/null; then
|
|
74
|
+
pass "Integration tests passed (mvn test -Dtest=*IT)"
|
|
75
|
+
else
|
|
76
|
+
fail "Integration tests failed"
|
|
77
|
+
fi
|
|
78
|
+
elif [ "$BUILD_TOOL" = "gradle" ] && command -v gradle &>/dev/null; then
|
|
79
|
+
if gradle test --tests "*IT" -q 2>/dev/null; then
|
|
80
|
+
pass "Integration tests passed (gradle test --tests *IT)"
|
|
81
|
+
else
|
|
82
|
+
fail "Integration tests failed"
|
|
83
|
+
fi
|
|
84
|
+
elif [ "$BUILD_TOOL" = "maven" ] && [ -f "mvnw" ]; then
|
|
85
|
+
if ./mvnw test -q -Dtest="*IT" 2>/dev/null; then
|
|
86
|
+
pass "Integration tests passed (./mvnw test)"
|
|
87
|
+
else
|
|
88
|
+
fail "Integration tests failed"
|
|
89
|
+
fi
|
|
90
|
+
elif [ "$BUILD_TOOL" = "gradle" ] && [ -f "gradlew" ]; then
|
|
91
|
+
if ./gradlew test --tests "*IT" -q 2>/dev/null; then
|
|
92
|
+
pass "Integration tests passed (./gradlew test)"
|
|
93
|
+
else
|
|
94
|
+
fail "Integration tests failed"
|
|
95
|
+
fi
|
|
96
|
+
else
|
|
97
|
+
warn "No build tool executable available for integration tests"
|
|
98
|
+
fi
|
|
99
|
+
else
|
|
100
|
+
pass "No src/test directory, skipping integration tests"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
# Coverage
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
echo ""
|
|
107
|
+
echo "--- Coverage ---"
|
|
108
|
+
if [ -n "$BUILD_TOOL" ]; then
|
|
109
|
+
if [ -f "pom.xml" ] && grep -q "jacoco" pom.xml 2>/dev/null; then
|
|
110
|
+
if command -v mvn &>/dev/null; then
|
|
111
|
+
COVERAGE_OUTPUT=$(mvn jacoco:report -q 2>&1 || true)
|
|
112
|
+
if [ -f "target/site/jacoco/index.html" ]; then
|
|
113
|
+
COVERAGE_PCT=$(grep -oP 'Total.*?([0-9]+)%' target/site/jacoco/index.html 2>/dev/null | grep -oP '[0-9]+' | head -1 || echo "")
|
|
114
|
+
if [ -n "$COVERAGE_PCT" ] && [ "$COVERAGE_PCT" -ge 80 ]; then
|
|
115
|
+
pass "Coverage: ${COVERAGE_PCT}% (≥ 80%)"
|
|
116
|
+
elif [ -n "$COVERAGE_PCT" ]; then
|
|
117
|
+
fail "Coverage: ${COVERAGE_PCT}% (< 80%)"
|
|
118
|
+
else
|
|
119
|
+
warn "Coverage report generated but percentage not detected"
|
|
120
|
+
fi
|
|
121
|
+
else
|
|
122
|
+
warn "JaCoCo report not found at target/site/jacoco/"
|
|
123
|
+
fi
|
|
124
|
+
fi
|
|
125
|
+
elif [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then
|
|
126
|
+
if grep -q "jacoco" build.gradle build.gradle.kts 2>/dev/null; then
|
|
127
|
+
if command -v gradle &>/dev/null; then
|
|
128
|
+
COVERAGE_OUTPUT=$(gradle jacocoTestReport -q 2>&1 || true)
|
|
129
|
+
pass "Coverage report generated (check build/reports/jacoco/)"
|
|
130
|
+
fi
|
|
131
|
+
fi
|
|
132
|
+
else
|
|
133
|
+
warn "JaCoCo not configured in build file, skipping coverage"
|
|
134
|
+
fi
|
|
135
|
+
else
|
|
136
|
+
warn "No build tool detected, skipping coverage"
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
# ---------------------------------------------------------------------------
|
|
140
|
+
# Summary
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
echo ""
|
|
143
|
+
echo "============================================"
|
|
144
|
+
echo " Summary"
|
|
145
|
+
echo "============================================"
|
|
146
|
+
echo -e " Passed: ${GREEN}${PASS_COUNT}${NC}"
|
|
147
|
+
echo -e " Failed: ${RED}${#ERRORS[@]}${NC}"
|
|
148
|
+
echo ""
|
|
149
|
+
|
|
150
|
+
if [ ${#ERRORS[@]} -gt 0 ]; then
|
|
151
|
+
echo "FAILURES:"
|
|
152
|
+
for err in "${ERRORS[@]}"; do
|
|
153
|
+
echo " - $err"
|
|
154
|
+
done
|
|
155
|
+
exit 1
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
echo -e "${GREEN}Test validation passed.${NC}"
|
|
159
|
+
exit 0
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# validate-architecture.sh — Python
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
# Activate Poetry venv if available
|
|
6
|
+
if [ -f "poetry.lock" ] && command -v poetry &>/dev/null; then
|
|
7
|
+
POETRY_ENV=$(poetry env info --path 2>/dev/null || true)
|
|
8
|
+
if [ -n "$POETRY_ENV" ] && [ -f "$POETRY_ENV/bin/activate" ]; then
|
|
9
|
+
source "$POETRY_ENV/bin/activate"
|
|
10
|
+
fi
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
SRC_DIR="${1:-src}"
|
|
14
|
+
PASS_COUNT=0; ERRORS=(); WARNINGS=()
|
|
15
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
16
|
+
pass() { echo -e "${GREEN}✅ PASS${NC} $1"; PASS_COUNT=$((PASS_COUNT + 1)); }
|
|
17
|
+
fail() { echo -e "${RED}❌ FAIL${NC} $1"; ERRORS+=("$1"); }
|
|
18
|
+
warn() { echo -e "${YELLOW}⚠️ WARN${NC} $1"; WARNINGS+=("$1"); }
|
|
19
|
+
|
|
20
|
+
echo "============================================"
|
|
21
|
+
echo " Architecture Validation (Python)"
|
|
22
|
+
echo "============================================"
|
|
23
|
+
|
|
24
|
+
# Layer structure
|
|
25
|
+
echo "--- Layer Structure ---"
|
|
26
|
+
if [ -d "$SRC_DIR" ]; then
|
|
27
|
+
HAS_DOMAIN=$(find "$SRC_DIR" -type d -name "domain" 2>/dev/null | head -1)
|
|
28
|
+
HAS_INFRA=$(find "$SRC_DIR" -type d -name "infrastructure" 2>/dev/null | head -1)
|
|
29
|
+
if [ -n "$HAS_DOMAIN" ] && [ -n "$HAS_INFRA" ]; then
|
|
30
|
+
pass "Domain and infrastructure layers present"
|
|
31
|
+
elif [ -n "$HAS_DOMAIN" ]; then
|
|
32
|
+
pass "Domain layer present (infrastructure added incrementally)"
|
|
33
|
+
else
|
|
34
|
+
pass "Source tree initialized"
|
|
35
|
+
fi
|
|
36
|
+
else
|
|
37
|
+
fail "Missing source directory: $SRC_DIR"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Canonical references
|
|
41
|
+
echo ""
|
|
42
|
+
echo "--- Canonical References ---"
|
|
43
|
+
if [ -d ".pi/architecture/modules" ]; then
|
|
44
|
+
MODULE_COUNT=$(find .pi/architecture/modules -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
|
|
45
|
+
pass "Canonical architecture documents found ($MODULE_COUNT modules)"
|
|
46
|
+
else
|
|
47
|
+
warn "No canonical architecture directory found"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Domain models
|
|
51
|
+
echo ""
|
|
52
|
+
echo "--- Domain Models ---"
|
|
53
|
+
DOMAIN_FILES=$(find "$SRC_DIR" -path "*/domain/*.py" 2>/dev/null | wc -l | tr -d ' ')
|
|
54
|
+
if [ "$DOMAIN_FILES" -gt 0 ]; then
|
|
55
|
+
pass "Domain model files found ($DOMAIN_FILES files)"
|
|
56
|
+
else
|
|
57
|
+
warn "No domain model files found yet"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Dependency direction
|
|
61
|
+
echo ""
|
|
62
|
+
echo "--- Dependency Direction ---"
|
|
63
|
+
DOMAIN_INFRA_IMPORTS=$(find "$SRC_DIR" -path "*/domain/*.py" -exec grep -l "from.*infrastructure" {} + 2>/dev/null | wc -l | tr -d ' ')
|
|
64
|
+
if [ "$DOMAIN_INFRA_IMPORTS" -eq 0 ]; then
|
|
65
|
+
pass "Domain layer has no infrastructure dependencies (clean architecture)"
|
|
66
|
+
else
|
|
67
|
+
warn "Domain imports from infrastructure ($DOMAIN_INFRA_IMPORTS references)"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Error handling
|
|
71
|
+
echo ""
|
|
72
|
+
echo "--- Error Handling ---"
|
|
73
|
+
ERROR_COUNT=$(grep -r "class.*Error" "$SRC_DIR" 2>/dev/null | wc -l | tr -d ' ')
|
|
74
|
+
if [ "$ERROR_COUNT" -gt 0 ]; then
|
|
75
|
+
pass "Custom exception classes defined ($ERROR_COUNT found)"
|
|
76
|
+
else
|
|
77
|
+
warn "Consider defining custom exception classes"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# Typed models
|
|
81
|
+
echo ""
|
|
82
|
+
echo "--- Typed Models ---"
|
|
83
|
+
MODEL_COUNT=$(grep -r "@dataclass" "$SRC_DIR" 2>/dev/null | wc -l | tr -d ' ')
|
|
84
|
+
if [ "$MODEL_COUNT" -gt 0 ]; then
|
|
85
|
+
pass "Typed dataclass models found ($MODEL_COUNT definitions)"
|
|
86
|
+
else
|
|
87
|
+
warn "No dataclass models found"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Summary
|
|
91
|
+
echo ""
|
|
92
|
+
echo "============================================"
|
|
93
|
+
echo " Passed: ${GREEN}${PASS_COUNT}${NC} Failed: ${RED}${#ERRORS[@]}${NC}"
|
|
94
|
+
if [ ${#ERRORS[@]} -gt 0 ]; then
|
|
95
|
+
for err in "${ERRORS[@]}"; do echo " - $err"; done
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
echo -e "${GREEN}Architecture validation passed.${NC}"
|
|
99
|
+
exit 0
|