@aporthq/aport-agent-guardrails 1.0.8
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 +217 -0
- package/README.md +481 -0
- package/bin/agent-guardrails +133 -0
- package/bin/aport-create-passport.sh +444 -0
- package/bin/aport-cursor-hook.sh +90 -0
- package/bin/aport-guardrail-api.sh +108 -0
- package/bin/aport-guardrail-bash.sh +394 -0
- package/bin/aport-guardrail-v2.sh +5 -0
- package/bin/aport-guardrail.sh +5 -0
- package/bin/aport-resolve-paths.sh +71 -0
- package/bin/aport-status.sh +276 -0
- package/bin/frameworks/crewai.sh +49 -0
- package/bin/frameworks/cursor.sh +95 -0
- package/bin/frameworks/langchain.sh +48 -0
- package/bin/frameworks/n8n.sh +36 -0
- package/bin/frameworks/openclaw.sh +19 -0
- package/bin/lib/allowlist.sh +18 -0
- package/bin/lib/common.sh +28 -0
- package/bin/lib/config.sh +46 -0
- package/bin/lib/constants.sh +232 -0
- package/bin/lib/detect.sh +65 -0
- package/bin/lib/error.sh +269 -0
- package/bin/lib/passport.sh +19 -0
- package/bin/lib/templates/.gitkeep +1 -0
- package/bin/lib/templates/config.yaml +6 -0
- package/bin/lib/validation.sh +206 -0
- package/bin/openclaw +660 -0
- package/docs/ADDING_A_FRAMEWORK.md +87 -0
- package/docs/AGENTS.md.example +40 -0
- package/docs/CODE_REVIEW.md +192 -0
- package/docs/DEPLOYMENT_READINESS.md +81 -0
- package/docs/FAQ_SECURITY_SCANNERS.md +373 -0
- package/docs/FRAMEWORK_ROADMAP.md +41 -0
- package/docs/HOSTED_PASSPORT_SETUP.md +362 -0
- package/docs/IMPLEMENTING_YOUR_OWN_EVALUATOR.md +433 -0
- package/docs/OPENCLAW_COMPATIBILITY.md +73 -0
- package/docs/OPENCLAW_LOCAL_INTEGRATION.md +596 -0
- package/docs/OPENCLAW_TOOLS_AND_POLICIES.md +54 -0
- package/docs/QUICKSTART.md +470 -0
- package/docs/QUICKSTART_OPENCLAW_PLUGIN.md +470 -0
- package/docs/README.md +28 -0
- package/docs/RELEASE.md +87 -0
- package/docs/REPO_LAYOUT.md +47 -0
- package/docs/SKILLS_ECOSYSTEM_ANALYSIS_FEB17.md +1260 -0
- package/docs/TOOL_POLICY_MAPPING.md +46 -0
- package/docs/UPGRADE.md +46 -0
- package/docs/VERIFICATION_METHODS.md +97 -0
- package/docs/assets/README.md +8 -0
- package/docs/assets/porter.svg +54 -0
- package/docs/development/ERROR_CODES.md +616 -0
- package/docs/frameworks/GITHUB_ISSUE_PROPOSALS.md +1105 -0
- package/docs/frameworks/crewai.md +114 -0
- package/docs/frameworks/cursor.md +159 -0
- package/docs/frameworks/langchain.md +72 -0
- package/docs/frameworks/n8n.md +40 -0
- package/docs/frameworks/openclaw.md +40 -0
- package/docs/launch/ADD_APORT_AWESOME_LISTS_INSTRUCTIONS.md +146 -0
- package/docs/launch/ANNOUNCEMENT_GUIDE.md +266 -0
- package/docs/launch/AWESOME_REPOS.md +53 -0
- package/docs/launch/CURSOR_VSCODE_HOOKS_RESEARCH.md +77 -0
- package/docs/launch/DEMO_TERMINAL_OUTPUT.txt +48 -0
- package/docs/launch/DRY_AND_PLAN_CHECKLIST.md +47 -0
- package/docs/launch/EVIDENCE_README.md +61 -0
- package/docs/launch/EVIDENCE_TERMINAL_CAPTURE.txt +10 -0
- package/docs/launch/FRAMEWORK_SUPPORT_PLAN.md +1640 -0
- package/docs/launch/LAUNCH_READINESS_CHECKLIST.md +237 -0
- package/docs/launch/LAUNCH_STRATEGY_SUMMARY.md +464 -0
- package/docs/launch/OPENCLAW_FEEDBACK_AND_FIXES.md +85 -0
- package/docs/launch/POST_1_VALENTINE_IMPROVED.md +233 -0
- package/docs/launch/POST_2_GUARDRAIL_IMPROVED.md +369 -0
- package/docs/launch/PRE_LAUNCH_FIXES.md +766 -0
- package/docs/launch/QUICK_LAUNCH_CHECKLIST.md +400 -0
- package/docs/launch/READINESS_SUMMARY.md +262 -0
- package/docs/launch/README.md +68 -0
- package/docs/launch/USER_STORIES.md +327 -0
- package/docs/launch/scripts/add-aport-awesome-pr.sh +69 -0
- package/docs/operations/MONITORING.md +588 -0
- package/docs/reviews/2026-02-18-staff-review.md +268 -0
- package/extensions/openclaw-aport/README.md +415 -0
- package/extensions/openclaw-aport/index.js +625 -0
- package/extensions/openclaw-aport/openclaw-aport.js +7 -0
- package/extensions/openclaw-aport/openclaw.plugin.json +46 -0
- package/extensions/openclaw-aport/package.json +36 -0
- package/extensions/openclaw-aport/test.js +307 -0
- package/external/aport-policies/README.md +363 -0
- package/external/aport-policies/agent.session.create.v1/README.md +345 -0
- package/external/aport-policies/agent.session.create.v1/policy.json +162 -0
- package/external/aport-policies/agent.tool.register.v1/README.md +361 -0
- package/external/aport-policies/agent.tool.register.v1/policy.json +172 -0
- package/external/aport-policies/code.release.publish.v1/README.md +51 -0
- package/external/aport-policies/code.release.publish.v1/policy.json +121 -0
- package/external/aport-policies/code.repository.merge.v1/README.md +287 -0
- package/external/aport-policies/code.repository.merge.v1/express.example.js +332 -0
- package/external/aport-policies/code.repository.merge.v1/fastapi.example.py +370 -0
- package/external/aport-policies/code.repository.merge.v1/policy.json +162 -0
- package/external/aport-policies/data.export.create.v1/README.md +226 -0
- package/external/aport-policies/data.export.create.v1/express.example.js +172 -0
- package/external/aport-policies/data.export.create.v1/fastapi.example.py +165 -0
- package/external/aport-policies/data.export.create.v1/policy.json +133 -0
- package/external/aport-policies/data.report.ingest.v1/README.md +134 -0
- package/external/aport-policies/data.report.ingest.v1/express.example.js +105 -0
- package/external/aport-policies/data.report.ingest.v1/minimal-example.js +68 -0
- package/external/aport-policies/data.report.ingest.v1/policy.json +174 -0
- package/external/aport-policies/finance.crypto.trade.v1/README.md +146 -0
- package/external/aport-policies/finance.crypto.trade.v1/express.example.js +109 -0
- package/external/aport-policies/finance.crypto.trade.v1/minimal-example.js +65 -0
- package/external/aport-policies/finance.crypto.trade.v1/policy.json +176 -0
- package/external/aport-policies/finance.payment.charge.v1/README.md +326 -0
- package/external/aport-policies/finance.payment.charge.v1/express.example.js +250 -0
- package/external/aport-policies/finance.payment.charge.v1/fastapi.example.py +227 -0
- package/external/aport-policies/finance.payment.charge.v1/minimal-example.js +64 -0
- package/external/aport-policies/finance.payment.charge.v1/policy.json +224 -0
- package/external/aport-policies/finance.payment.charge.v1/tests/contexts.jsonl +12 -0
- package/external/aport-policies/finance.payment.charge.v1/tests/expected.jsonl +12 -0
- package/external/aport-policies/finance.payment.charge.v1/tests/passport.instance.json +42 -0
- package/external/aport-policies/finance.payment.charge.v1/tests/passport.template.json +40 -0
- package/external/aport-policies/finance.payment.charge.v1/tests/payments-charge-policy.test.js +817 -0
- package/external/aport-policies/finance.payment.charge.v1/tests/test_payments_charge_policy.py +486 -0
- package/external/aport-policies/finance.payment.payout.v1/README.md +78 -0
- package/external/aport-policies/finance.payment.payout.v1/policy.json +181 -0
- package/external/aport-policies/finance.payment.refund.v1/README.md +275 -0
- package/external/aport-policies/finance.payment.refund.v1/express.example.js +167 -0
- package/external/aport-policies/finance.payment.refund.v1/fastapi.example.py +136 -0
- package/external/aport-policies/finance.payment.refund.v1/minimal-example.js +183 -0
- package/external/aport-policies/finance.payment.refund.v1/policy.json +216 -0
- package/external/aport-policies/finance.payment.refund.v1/tests/refunds-policy.test.js +924 -0
- package/external/aport-policies/finance.payment.refund.v1/tests/test_refunds_policy.py +778 -0
- package/external/aport-policies/finance.transaction.execute.v1/README.md +309 -0
- package/external/aport-policies/finance.transaction.execute.v1/express.example.js +261 -0
- package/external/aport-policies/finance.transaction.execute.v1/fastapi.example.py +231 -0
- package/external/aport-policies/finance.transaction.execute.v1/minimal-example.js +78 -0
- package/external/aport-policies/finance.transaction.execute.v1/policy.json +189 -0
- package/external/aport-policies/finance.transaction.execute.v1/tests/contexts.jsonl +12 -0
- package/external/aport-policies/finance.transaction.execute.v1/tests/expected.jsonl +12 -0
- package/external/aport-policies/finance.transaction.execute.v1/tests/passport.instance.json +42 -0
- package/external/aport-policies/finance.transaction.execute.v1/tests/passport.template.json +42 -0
- package/external/aport-policies/finance.transaction.execute.v1/tests/test_transactions_policy.py +214 -0
- package/external/aport-policies/finance.transaction.execute.v1/tests/transactions-policy.test.js +306 -0
- package/external/aport-policies/governance.data.access.v1/README.md +292 -0
- package/external/aport-policies/governance.data.access.v1/express.example.js +321 -0
- package/external/aport-policies/governance.data.access.v1/fastapi.example.py +279 -0
- package/external/aport-policies/governance.data.access.v1/minimal-example.js +65 -0
- package/external/aport-policies/governance.data.access.v1/policy.json +208 -0
- package/external/aport-policies/governance.data.access.v1/tests/contexts.jsonl +12 -0
- package/external/aport-policies/governance.data.access.v1/tests/data-access-policy.test.js +308 -0
- package/external/aport-policies/governance.data.access.v1/tests/expected.jsonl +12 -0
- package/external/aport-policies/governance.data.access.v1/tests/passport.instance.json +56 -0
- package/external/aport-policies/governance.data.access.v1/tests/passport.template.json +56 -0
- package/external/aport-policies/governance.data.access.v1/tests/test_data_access_policy.py +214 -0
- package/external/aport-policies/legal.contract.review.v1/README.md +109 -0
- package/external/aport-policies/legal.contract.review.v1/policy.json +378 -0
- package/external/aport-policies/legal.contract.review.v1/tests/legal-contract-review-policy.test.js +609 -0
- package/external/aport-policies/legal.contract.review.v1/tests/passport.template.json +49 -0
- package/external/aport-policies/mcp.tool.execute.v1/README.md +301 -0
- package/external/aport-policies/mcp.tool.execute.v1/policy.json +141 -0
- package/external/aport-policies/messaging.message.send.v1/README.md +230 -0
- package/external/aport-policies/messaging.message.send.v1/express.example.js +183 -0
- package/external/aport-policies/messaging.message.send.v1/fastapi.example.py +193 -0
- package/external/aport-policies/messaging.message.send.v1/policy.json +144 -0
- package/external/aport-policies/policy-template.json +107 -0
- package/external/aport-policies/system.command.execute.v1/README.md +275 -0
- package/external/aport-policies/system.command.execute.v1/policy.json +146 -0
- package/external/aport-spec/CONTRIBUTING.md +273 -0
- package/external/aport-spec/LICENSE +21 -0
- package/external/aport-spec/README.md +168 -0
- package/external/aport-spec/conformance/README.md +294 -0
- package/external/aport-spec/conformance/cases/data.export.v1/contexts/allow_users.json +6 -0
- package/external/aport-spec/conformance/cases/data.export.v1/contexts/deny_pii.json +6 -0
- package/external/aport-spec/conformance/cases/data.export.v1/expected/allow_users.decision.json +19 -0
- package/external/aport-spec/conformance/cases/data.export.v1/expected/deny_pii.decision.json +19 -0
- package/external/aport-spec/conformance/cases/data.export.v1/passports/template.json +29 -0
- package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/allow_50usd.json +9 -0
- package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/deny_150usd.json +9 -0
- package/external/aport-spec/conformance/cases/payments.refunds.v1/contexts/deny_currency.json +9 -0
- package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/allow_50usd.decision.json +19 -0
- package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/deny_150usd.decision.json +19 -0
- package/external/aport-spec/conformance/cases/payments.refunds.v1/expected/deny_currency.decision.json +19 -0
- package/external/aport-spec/conformance/cases/payments.refunds.v1/passports/template.json +42 -0
- package/external/aport-spec/conformance/package.json +44 -0
- package/external/aport-spec/conformance/pnpm-lock.yaml +642 -0
- package/external/aport-spec/conformance/src/cases.ts +371 -0
- package/external/aport-spec/conformance/src/ed25519.ts +167 -0
- package/external/aport-spec/conformance/src/jcs.ts +85 -0
- package/external/aport-spec/conformance/src/runner.ts +533 -0
- package/external/aport-spec/conformance/src/validators.ts +185 -0
- package/external/aport-spec/conformance/test-runner.js +315 -0
- package/external/aport-spec/conformance/tsconfig.json +21 -0
- package/external/aport-spec/error-schema.json +192 -0
- package/external/aport-spec/index.json +12 -0
- package/external/aport-spec/integrations/clawmoat/README.md +12 -0
- package/external/aport-spec/integrations/shield/README.md +245 -0
- package/external/aport-spec/integrations/shield/adapters/index.js +116 -0
- package/external/aport-spec/integrations/shield/adapters/system-command-execute.js +133 -0
- package/external/aport-spec/integrations/shield/test/README.md +58 -0
- package/external/aport-spec/integrations/shield/test/shield.md +40 -0
- package/external/aport-spec/integrations/shield/test/test-shield-to-verify.js +274 -0
- package/external/aport-spec/metrics-schema.json +504 -0
- package/external/aport-spec/oap/CHANGELOG.md +54 -0
- package/external/aport-spec/oap/VERSION.md +40 -0
- package/external/aport-spec/oap/capability-registry.md +229 -0
- package/external/aport-spec/oap/conformance.md +257 -0
- package/external/aport-spec/oap/decision-schema.json +114 -0
- package/external/aport-spec/oap/examples/context.refund.usd.50.json +9 -0
- package/external/aport-spec/oap/examples/decision.allow.sample.json +20 -0
- package/external/aport-spec/oap/examples/decision.deny.sample.json +23 -0
- package/external/aport-spec/oap/examples/passport.instance.v1.json +50 -0
- package/external/aport-spec/oap/examples/passport.template.v1.json +71 -0
- package/external/aport-spec/oap/oap-spec.md +426 -0
- package/external/aport-spec/oap/passport-schema.json +396 -0
- package/external/aport-spec/oap/security.md +213 -0
- package/external/aport-spec/oap/vc/context-oap-v1.jsonld +137 -0
- package/external/aport-spec/oap/vc/examples/oap-decision-vc.json +37 -0
- package/external/aport-spec/oap/vc/examples/oap-passport-vc.json +68 -0
- package/external/aport-spec/oap/vc/tools/INTEGRATION.md +375 -0
- package/external/aport-spec/oap/vc/tools/README.md +278 -0
- package/external/aport-spec/oap/vc/tools/examples/decision-to-vc.js +66 -0
- package/external/aport-spec/oap/vc/tools/examples/passport-to-vc.js +83 -0
- package/external/aport-spec/oap/vc/tools/examples/vc-to-decision.js +77 -0
- package/external/aport-spec/oap/vc/tools/examples/vc-to-passport.js +94 -0
- package/external/aport-spec/oap/vc/tools/package.json +38 -0
- package/external/aport-spec/oap/vc/tools/pnpm-lock.yaml +472 -0
- package/external/aport-spec/oap/vc/tools/src/cli.ts +226 -0
- package/external/aport-spec/oap/vc/tools/src/crypto-utils.ts +427 -0
- package/external/aport-spec/oap/vc/tools/src/index.ts +653 -0
- package/external/aport-spec/oap/vc/tools/src/test.ts +148 -0
- package/external/aport-spec/oap/vc/tools/src/vp.ts +382 -0
- package/external/aport-spec/oap/vc/tools/test-simple.js +214 -0
- package/external/aport-spec/oap/vc/tools/tsconfig.json +19 -0
- package/external/aport-spec/oap/vc/vc-mapping.md +443 -0
- package/external/aport-spec/passport-schema.json +586 -0
- package/external/aport-spec/rate-limiting.md +136 -0
- package/external/aport-spec/transport-profile.md +325 -0
- package/external/aport-spec/webhook-spec.md +314 -0
- package/package.json +70 -0
- package/skills/aport-agent-guardrail/SKILL.md +314 -0
- package/src/evaluator.js +252 -0
- package/src/server/index.js +72 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# constants.sh - Configuration constants and defaults for APort guardrails
|
|
3
|
+
# All magic numbers and hardcoded values should be defined here
|
|
4
|
+
|
|
5
|
+
# ============================================================================
|
|
6
|
+
# TIMEOUTS (seconds)
|
|
7
|
+
# ============================================================================
|
|
8
|
+
|
|
9
|
+
# Default timeout for subprocess guardrail script execution
|
|
10
|
+
readonly DEFAULT_SUBPROCESS_TIMEOUT="${APORT_SUBPROCESS_TIMEOUT:-30}"
|
|
11
|
+
|
|
12
|
+
# Default timeout for API requests
|
|
13
|
+
readonly DEFAULT_API_TIMEOUT="${APORT_API_TIMEOUT:-15}"
|
|
14
|
+
|
|
15
|
+
# Timeout for loading policy packs
|
|
16
|
+
readonly DEFAULT_POLICY_LOAD_TIMEOUT="${APORT_POLICY_LOAD_TIMEOUT:-5}"
|
|
17
|
+
|
|
18
|
+
# ============================================================================
|
|
19
|
+
# SIZE LIMITS
|
|
20
|
+
# ============================================================================
|
|
21
|
+
|
|
22
|
+
# Maximum tool name length (characters)
|
|
23
|
+
readonly MAX_TOOL_NAME_LENGTH="${APORT_MAX_TOOL_NAME_LENGTH:-128}"
|
|
24
|
+
|
|
25
|
+
# Maximum agent ID length (characters)
|
|
26
|
+
readonly MAX_AGENT_ID_LENGTH="${APORT_MAX_AGENT_ID_LENGTH:-128}"
|
|
27
|
+
|
|
28
|
+
# Maximum policy pack ID length (characters)
|
|
29
|
+
readonly MAX_POLICY_PACK_ID_LENGTH="${APORT_MAX_POLICY_PACK_ID_LENGTH:-128}"
|
|
30
|
+
|
|
31
|
+
# Maximum context JSON size (bytes) - default 100KB
|
|
32
|
+
readonly MAX_CONTEXT_SIZE_BYTES="${APORT_MAX_CONTEXT_SIZE:-102400}"
|
|
33
|
+
|
|
34
|
+
# Maximum passport file size (bytes) - default 1MB
|
|
35
|
+
readonly MAX_PASSPORT_SIZE_BYTES="${APORT_MAX_PASSPORT_SIZE:-1048576}"
|
|
36
|
+
|
|
37
|
+
# Maximum policy pack file size (bytes) - default 10MB
|
|
38
|
+
readonly MAX_POLICY_PACK_SIZE_BYTES="${APORT_MAX_POLICY_PACK_SIZE:-10485760}"
|
|
39
|
+
|
|
40
|
+
# Maximum log message length (characters)
|
|
41
|
+
readonly MAX_LOG_MESSAGE_LENGTH="${APORT_MAX_LOG_MESSAGE_LENGTH:-200}"
|
|
42
|
+
|
|
43
|
+
# ============================================================================
|
|
44
|
+
# RATE LIMITING
|
|
45
|
+
# ============================================================================
|
|
46
|
+
|
|
47
|
+
# Default requests per minute
|
|
48
|
+
readonly DEFAULT_RATE_LIMIT_RPM="${APORT_RATE_LIMIT_REQUESTS_PER_MINUTE:-60}"
|
|
49
|
+
|
|
50
|
+
# Default burst allowance
|
|
51
|
+
readonly DEFAULT_RATE_LIMIT_BURST="${APORT_RATE_LIMIT_BURST:-10}"
|
|
52
|
+
|
|
53
|
+
# ============================================================================
|
|
54
|
+
# RETRY LOGIC
|
|
55
|
+
# ============================================================================
|
|
56
|
+
|
|
57
|
+
# Maximum API retry attempts
|
|
58
|
+
readonly MAX_API_RETRIES="${APORT_MAX_API_RETRIES:-3}"
|
|
59
|
+
|
|
60
|
+
# API retry backoff (milliseconds)
|
|
61
|
+
readonly API_RETRY_BACKOFF_MS="${APORT_API_RETRY_BACKOFF_MS:-1000}"
|
|
62
|
+
|
|
63
|
+
# ============================================================================
|
|
64
|
+
# CACHING
|
|
65
|
+
# ============================================================================
|
|
66
|
+
|
|
67
|
+
# Passport file cache TTL (seconds)
|
|
68
|
+
readonly PASSPORT_CACHE_TTL_SECONDS="${APORT_PASSPORT_CACHE_TTL:-60}"
|
|
69
|
+
|
|
70
|
+
# Policy pack cache TTL (seconds)
|
|
71
|
+
readonly POLICY_CACHE_TTL_SECONDS="${APORT_POLICY_CACHE_TTL:-60}"
|
|
72
|
+
|
|
73
|
+
# Config file cache TTL (seconds)
|
|
74
|
+
readonly CONFIG_CACHE_TTL_SECONDS="${APORT_CONFIG_CACHE_TTL:-300}"
|
|
75
|
+
|
|
76
|
+
# ============================================================================
|
|
77
|
+
# API CONFIGURATION
|
|
78
|
+
# ============================================================================
|
|
79
|
+
|
|
80
|
+
# Default API URL
|
|
81
|
+
readonly DEFAULT_API_URL="${APORT_API_URL:-https://api.aport.io}"
|
|
82
|
+
|
|
83
|
+
# ============================================================================
|
|
84
|
+
# PATHS
|
|
85
|
+
# ============================================================================
|
|
86
|
+
|
|
87
|
+
# Allowed base directories for passport files (for validation)
|
|
88
|
+
readonly ALLOWED_PASSPORT_BASE_DIRS=(
|
|
89
|
+
"$HOME/.openclaw"
|
|
90
|
+
"$HOME/.aport"
|
|
91
|
+
"/tmp/aport-"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# ============================================================================
|
|
95
|
+
# VALIDATION PATTERNS
|
|
96
|
+
# ============================================================================
|
|
97
|
+
|
|
98
|
+
# Tool name validation pattern (grep -E compatible)
|
|
99
|
+
readonly TOOL_NAME_PATTERN='^[a-zA-Z0-9._-]+$'
|
|
100
|
+
|
|
101
|
+
# Agent ID validation pattern (grep -E compatible)
|
|
102
|
+
readonly AGENT_ID_PATTERN='^ap_[a-zA-Z0-9_]+$'
|
|
103
|
+
|
|
104
|
+
# Policy pack ID validation pattern (grep -E compatible)
|
|
105
|
+
readonly POLICY_PACK_ID_PATTERN='^[a-zA-Z0-9._-]+$'
|
|
106
|
+
|
|
107
|
+
# ============================================================================
|
|
108
|
+
# LOGGING
|
|
109
|
+
# ============================================================================
|
|
110
|
+
|
|
111
|
+
# Log level (DEBUG, INFO, WARN, ERROR)
|
|
112
|
+
readonly LOG_LEVEL="${APORT_LOG_LEVEL:-INFO}"
|
|
113
|
+
|
|
114
|
+
# Log format (text, json)
|
|
115
|
+
readonly LOG_FORMAT="${APORT_LOG_FORMAT:-text}"
|
|
116
|
+
|
|
117
|
+
# ============================================================================
|
|
118
|
+
# SECURITY
|
|
119
|
+
# ============================================================================
|
|
120
|
+
|
|
121
|
+
# Sensitive field patterns for log redaction (space-separated)
|
|
122
|
+
readonly SENSITIVE_FIELD_PATTERNS="password passwd pwd secret token key api bearer"
|
|
123
|
+
|
|
124
|
+
# API key prefix patterns (space-separated)
|
|
125
|
+
readonly API_KEY_PREFIXES="aprt_ sk_ pk_"
|
|
126
|
+
|
|
127
|
+
# ============================================================================
|
|
128
|
+
# PERFORMANCE
|
|
129
|
+
# ============================================================================
|
|
130
|
+
|
|
131
|
+
# Slow operation threshold (milliseconds)
|
|
132
|
+
readonly SLOW_OPERATION_THRESHOLD_MS="${APORT_SLOW_OPERATION_THRESHOLD_MS:-200}"
|
|
133
|
+
|
|
134
|
+
# ============================================================================
|
|
135
|
+
# FEATURE FLAGS
|
|
136
|
+
# ============================================================================
|
|
137
|
+
|
|
138
|
+
# Enable policy caching (1=enabled, 0=disabled)
|
|
139
|
+
readonly ENABLE_POLICY_CACHING="${APORT_ENABLE_POLICY_CACHING:-1}"
|
|
140
|
+
|
|
141
|
+
# Enable passport caching (1=enabled, 0=disabled)
|
|
142
|
+
readonly ENABLE_PASSPORT_CACHING="${APORT_ENABLE_PASSPORT_CACHING:-1}"
|
|
143
|
+
|
|
144
|
+
# ============================================================================
|
|
145
|
+
# VERSION
|
|
146
|
+
# ============================================================================
|
|
147
|
+
|
|
148
|
+
# APort specification version
|
|
149
|
+
readonly OAP_SPEC_VERSION="oap/1.0"
|
|
150
|
+
|
|
151
|
+
# Client library version
|
|
152
|
+
readonly CLIENT_VERSION="1.0.8"
|
|
153
|
+
|
|
154
|
+
# ============================================================================
|
|
155
|
+
# MISC
|
|
156
|
+
# ============================================================================
|
|
157
|
+
|
|
158
|
+
# Audit log file name
|
|
159
|
+
readonly AUDIT_LOG_FILENAME="audit.log"
|
|
160
|
+
|
|
161
|
+
# Chain state file name
|
|
162
|
+
readonly CHAIN_STATE_FILENAME="chain-state.json"
|
|
163
|
+
|
|
164
|
+
# ============================================================================
|
|
165
|
+
# HELPER FUNCTIONS
|
|
166
|
+
# ============================================================================
|
|
167
|
+
|
|
168
|
+
# Get numeric constant with validation
|
|
169
|
+
# Usage: get_numeric_constant "var_name" "default_value" "min" "max"
|
|
170
|
+
get_numeric_constant() {
|
|
171
|
+
local var_name="$1"
|
|
172
|
+
local default_value="$2"
|
|
173
|
+
local min_value="${3:-1}"
|
|
174
|
+
local max_value="${4:-999999}"
|
|
175
|
+
|
|
176
|
+
local value="${!var_name:-$default_value}"
|
|
177
|
+
|
|
178
|
+
# Validate it's a number
|
|
179
|
+
if ! [[ "$value" =~ ^[0-9]+$ ]]; then
|
|
180
|
+
echo "$default_value"
|
|
181
|
+
return 1
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
# Validate range
|
|
185
|
+
if [ "$value" -lt "$min_value" ] || [ "$value" -gt "$max_value" ]; then
|
|
186
|
+
echo "$default_value"
|
|
187
|
+
return 1
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
echo "$value"
|
|
191
|
+
return 0
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
# Check if feature is enabled
|
|
195
|
+
# Usage: if is_feature_enabled "ENABLE_POLICY_CACHING"; then ...
|
|
196
|
+
is_feature_enabled() {
|
|
197
|
+
local feature_var="$1"
|
|
198
|
+
local value="${!feature_var:-0}"
|
|
199
|
+
|
|
200
|
+
case "$value" in
|
|
201
|
+
1 | true | TRUE | yes | YES | on | ON)
|
|
202
|
+
return 0
|
|
203
|
+
;;
|
|
204
|
+
*)
|
|
205
|
+
return 1
|
|
206
|
+
;;
|
|
207
|
+
esac
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# Get log level priority (for filtering)
|
|
211
|
+
# Returns: 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR
|
|
212
|
+
get_log_level_priority() {
|
|
213
|
+
local level="${1:-INFO}"
|
|
214
|
+
|
|
215
|
+
case "$level" in
|
|
216
|
+
DEBUG) echo 0 ;;
|
|
217
|
+
INFO) echo 1 ;;
|
|
218
|
+
WARN) echo 2 ;;
|
|
219
|
+
ERROR) echo 3 ;;
|
|
220
|
+
*) echo 1 ;; # Default to INFO
|
|
221
|
+
esac
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
# Check if should log at level
|
|
225
|
+
# Usage: if should_log "DEBUG"; then ...
|
|
226
|
+
should_log() {
|
|
227
|
+
local message_level="$1"
|
|
228
|
+
local current_priority=$(get_log_level_priority "$LOG_LEVEL")
|
|
229
|
+
local message_priority=$(get_log_level_priority "$message_level")
|
|
230
|
+
|
|
231
|
+
[ "$message_priority" -ge "$current_priority" ]
|
|
232
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Framework detection from project directory (cwd or first arg).
|
|
3
|
+
# Used by bin/agent-guardrails to skip prompt when project is detectable.
|
|
4
|
+
# detect_framework: echoes first detected framework or empty.
|
|
5
|
+
# detect_frameworks_list: echoes all detected frameworks (space-separated, unique)
|
|
6
|
+
# so the dispatcher can show "Multiple frameworks detected: X, Y. Choose one: ...".
|
|
7
|
+
|
|
8
|
+
# shellcheck source=./common.sh
|
|
9
|
+
source "$(dirname "${BASH_SOURCE[0]:-.}")/common.sh"
|
|
10
|
+
|
|
11
|
+
# Collect all detected framework names (unique, order: pyproject -> package.json -> requirements)
|
|
12
|
+
detect_frameworks_list() {
|
|
13
|
+
local dir="${1:-.}"
|
|
14
|
+
local list=()
|
|
15
|
+
|
|
16
|
+
[[ ! -d "$dir" ]] && echo "" && return 0
|
|
17
|
+
|
|
18
|
+
# Python: pyproject.toml
|
|
19
|
+
if [[ -f "$dir/pyproject.toml" ]]; then
|
|
20
|
+
grep -qi 'langchain\|langgraph' "$dir/pyproject.toml" 2> /dev/null && list+=(langchain)
|
|
21
|
+
grep -qi 'crewai' "$dir/pyproject.toml" 2> /dev/null && list+=(crewai)
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Node: package.json
|
|
25
|
+
if [[ -f "$dir/package.json" ]]; then
|
|
26
|
+
grep -qi 'openclaw\|open-claw\|agent-guardrails' "$dir/package.json" 2> /dev/null && list+=(openclaw)
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# requirements.txt fallback
|
|
30
|
+
if [[ -f "$dir/requirements.txt" ]]; then
|
|
31
|
+
grep -qi 'langchain' "$dir/requirements.txt" 2> /dev/null && list+=(langchain)
|
|
32
|
+
grep -qi 'crewai' "$dir/requirements.txt" 2> /dev/null && list+=(crewai)
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Dedupe preserving order (first occurrence wins). Safe for set -u when list is empty.
|
|
36
|
+
local seen=() out=()
|
|
37
|
+
if [[ ${#list[@]} -gt 0 ]]; then
|
|
38
|
+
for fw in "${list[@]}"; do
|
|
39
|
+
if [[ " ${seen[*]:-} " != *" $fw "* ]]; then
|
|
40
|
+
seen+=("$fw")
|
|
41
|
+
out+=("$fw")
|
|
42
|
+
fi
|
|
43
|
+
done
|
|
44
|
+
fi
|
|
45
|
+
if [[ ${#out[@]} -gt 0 ]]; then
|
|
46
|
+
echo "${out[*]}"
|
|
47
|
+
else
|
|
48
|
+
echo ""
|
|
49
|
+
fi
|
|
50
|
+
return 0
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Return first detected framework (for single-detection behavior); empty if none.
|
|
54
|
+
detect_framework() {
|
|
55
|
+
local list
|
|
56
|
+
list="$(detect_frameworks_list "${1:-.}")"
|
|
57
|
+
if [[ -n "$list" ]]; then
|
|
58
|
+
echo "${list%% *}"
|
|
59
|
+
else
|
|
60
|
+
echo ""
|
|
61
|
+
fi
|
|
62
|
+
return 0
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export -f detect_framework detect_frameworks_list
|
package/bin/lib/error.sh
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# error.sh - Standardized error handling for APort guardrails
|
|
3
|
+
# Provides consistent error codes, messages, and response formatting
|
|
4
|
+
|
|
5
|
+
# Error codes (see docs/development/ERROR_CODES.md)
|
|
6
|
+
readonly ERROR_INVALID_TOOL_NAME="oap.invalid_input.tool_name"
|
|
7
|
+
readonly ERROR_CONTEXT_TOO_LARGE="oap.invalid_input.context_too_large"
|
|
8
|
+
readonly ERROR_INVALID_AGENT_ID="oap.invalid_input.agent_id"
|
|
9
|
+
readonly ERROR_PATH_NOT_ALLOWED="oap.path.not_allowed"
|
|
10
|
+
readonly ERROR_PATH_TRAVERSAL="oap.path.traversal_attempt"
|
|
11
|
+
readonly ERROR_PATH_INVALID_CHARS="oap.path.invalid_characters"
|
|
12
|
+
readonly ERROR_PASSPORT_NOT_FOUND="oap.passport.not_found"
|
|
13
|
+
readonly ERROR_PASSPORT_INVALID="oap.passport.invalid_format"
|
|
14
|
+
readonly ERROR_PASSPORT_EXPIRED="oap.passport.expired"
|
|
15
|
+
readonly ERROR_PASSPORT_REVOKED="oap.passport.revoked"
|
|
16
|
+
readonly ERROR_PASSPORT_MISSING_CAP="oap.passport.missing_capability"
|
|
17
|
+
readonly ERROR_POLICY_NOT_FOUND="oap.policy.not_found"
|
|
18
|
+
readonly ERROR_POLICY_INVALID="oap.policy.invalid_format"
|
|
19
|
+
readonly ERROR_POLICY_EVAL_FAILED="oap.policy.evaluation_failed"
|
|
20
|
+
readonly ERROR_POLICY_TIMEOUT="oap.policy.evaluation_timeout"
|
|
21
|
+
readonly ERROR_POLICY_DENIED="oap.policy.denied"
|
|
22
|
+
readonly ERROR_API_CONNECTION="oap.api.connection_failed"
|
|
23
|
+
readonly ERROR_API_AUTH="oap.api.authentication_failed"
|
|
24
|
+
readonly ERROR_API_RATE_LIMIT="oap.api.rate_limit_exceeded"
|
|
25
|
+
readonly ERROR_API_TIMEOUT="oap.api.timeout"
|
|
26
|
+
readonly ERROR_API_ERROR="oap.api.error"
|
|
27
|
+
readonly ERROR_CONFIG_NOT_FOUND="oap.config.not_found"
|
|
28
|
+
readonly ERROR_CONFIG_INVALID="oap.config.invalid_format"
|
|
29
|
+
readonly ERROR_EVALUATOR_ERROR="oap.system.evaluator_error"
|
|
30
|
+
readonly ERROR_COMMAND_INJECTION="oap.system.command_injection_detected"
|
|
31
|
+
readonly ERROR_DEPENDENCY_MISSING="oap.system.dependency_missing"
|
|
32
|
+
readonly ERROR_MISCONFIGURED="oap.misconfigured"
|
|
33
|
+
|
|
34
|
+
# Generate unique request ID
|
|
35
|
+
generate_request_id() {
|
|
36
|
+
local timestamp=$(date +%s%3N 2> /dev/null || date +%s)
|
|
37
|
+
local random=$(openssl rand -hex 3 2> /dev/null || echo "$RANDOM")
|
|
38
|
+
echo "req_${timestamp}_${random}"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Generate ISO 8601 timestamp
|
|
42
|
+
generate_timestamp() {
|
|
43
|
+
date -u +"%Y-%m-%dT%H:%M:%S.%3NZ" 2> /dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Format error as JSON decision
|
|
47
|
+
# Usage: format_error_json "error_code" "message" ["details_json"] ["resolution"]
|
|
48
|
+
format_error_json() {
|
|
49
|
+
local code="$1"
|
|
50
|
+
local message="$2"
|
|
51
|
+
local details="${3:-}"
|
|
52
|
+
local resolution="${4:-}"
|
|
53
|
+
local request_id="${5:-$(generate_request_id)}"
|
|
54
|
+
local timestamp=$(generate_timestamp)
|
|
55
|
+
|
|
56
|
+
local reason_json
|
|
57
|
+
reason_json=$(
|
|
58
|
+
cat << EOF
|
|
59
|
+
{
|
|
60
|
+
"code": "$code",
|
|
61
|
+
"message": "$message"
|
|
62
|
+
}
|
|
63
|
+
EOF
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Add details if provided
|
|
67
|
+
if [ -n "$details" ]; then
|
|
68
|
+
reason_json=$(echo "$reason_json" | jq -c --argjson d "$details" '. + {details: $d}')
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Add resolution if provided
|
|
72
|
+
if [ -n "$resolution" ]; then
|
|
73
|
+
reason_json=$(echo "$reason_json" | jq -c --arg r "$resolution" '. + {resolution: $r}')
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Create full response
|
|
77
|
+
cat << EOF
|
|
78
|
+
{
|
|
79
|
+
"allow": false,
|
|
80
|
+
"reasons": [$reason_json],
|
|
81
|
+
"request_id": "$request_id",
|
|
82
|
+
"timestamp": "$timestamp"
|
|
83
|
+
}
|
|
84
|
+
EOF
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# Format error as plain text
|
|
88
|
+
# Usage: format_error_text "error_code" "message" ["details"] ["resolution"]
|
|
89
|
+
format_error_text() {
|
|
90
|
+
local code="$1"
|
|
91
|
+
local message="$2"
|
|
92
|
+
local details="${3:-}"
|
|
93
|
+
local resolution="${4:-}"
|
|
94
|
+
local request_id="${5:-$(generate_request_id)}"
|
|
95
|
+
|
|
96
|
+
echo "ERROR: $code"
|
|
97
|
+
echo "$message"
|
|
98
|
+
|
|
99
|
+
if [ -n "$details" ]; then
|
|
100
|
+
echo "Details: $details"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
if [ -n "$resolution" ]; then
|
|
104
|
+
echo ""
|
|
105
|
+
echo "Resolution:"
|
|
106
|
+
echo "$resolution"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
echo ""
|
|
110
|
+
echo "Request ID: $request_id"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# Write error to stderr in text format
|
|
114
|
+
# Usage: error_log "error_code" "message" ["details"]
|
|
115
|
+
error_log() {
|
|
116
|
+
local code="$1"
|
|
117
|
+
local message="$2"
|
|
118
|
+
local details="${3:-}"
|
|
119
|
+
|
|
120
|
+
format_error_text "$code" "$message" "$details" >&2
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# Write deny decision to decision file
|
|
124
|
+
# Usage: write_deny_decision "error_code" "message" ["details"] ["resolution"]
|
|
125
|
+
write_deny_decision() {
|
|
126
|
+
local code="$1"
|
|
127
|
+
local message="$2"
|
|
128
|
+
local details="${3:-}"
|
|
129
|
+
local resolution="${4:-}"
|
|
130
|
+
|
|
131
|
+
if [ -z "$DECISION_FILE" ]; then
|
|
132
|
+
error_log "oap.system.evaluator_error" "DECISION_FILE not set"
|
|
133
|
+
return 1
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
format_error_json "$code" "$message" "$details" "$resolution" > "$DECISION_FILE" 2> /dev/null || true
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
# Write allow decision to decision file
|
|
140
|
+
# Usage: write_allow_decision "message" ["policy_id"]
|
|
141
|
+
write_allow_decision() {
|
|
142
|
+
local message="${1:-All policy checks passed}"
|
|
143
|
+
local policy_id="${2:-}"
|
|
144
|
+
local request_id=$(generate_request_id)
|
|
145
|
+
local timestamp=$(generate_timestamp)
|
|
146
|
+
|
|
147
|
+
if [ -z "$DECISION_FILE" ]; then
|
|
148
|
+
error_log "oap.system.evaluator_error" "DECISION_FILE not set"
|
|
149
|
+
return 1
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
local decision_json
|
|
153
|
+
decision_json=$(
|
|
154
|
+
cat << EOF
|
|
155
|
+
{
|
|
156
|
+
"allow": true,
|
|
157
|
+
"reasons": [{"message": "$message"}],
|
|
158
|
+
"request_id": "$request_id",
|
|
159
|
+
"timestamp": "$timestamp"
|
|
160
|
+
}
|
|
161
|
+
EOF
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Add policy_id if provided
|
|
165
|
+
if [ -n "$policy_id" ]; then
|
|
166
|
+
decision_json=$(echo "$decision_json" | jq -c --arg p "$policy_id" '. + {policy_id: $p}')
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
echo "$decision_json" > "$DECISION_FILE" 2> /dev/null || true
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
# Get standard resolution message for error code
|
|
173
|
+
# Usage: resolution=$(get_resolution "error_code")
|
|
174
|
+
get_resolution() {
|
|
175
|
+
local code="$1"
|
|
176
|
+
|
|
177
|
+
case "$code" in
|
|
178
|
+
"$ERROR_INVALID_TOOL_NAME")
|
|
179
|
+
echo "Use only alphanumeric characters, dots, underscores, and hyphens in tool names. Keep tool names under 128 characters."
|
|
180
|
+
;;
|
|
181
|
+
"$ERROR_CONTEXT_TOO_LARGE")
|
|
182
|
+
echo "Reduce context data size by removing unnecessary fields or summarizing large data. Default limit: 100KB."
|
|
183
|
+
;;
|
|
184
|
+
"$ERROR_PATH_NOT_ALLOWED")
|
|
185
|
+
echo "Use standard APort directories: ~/.openclaw/, ~/.aport/, or /tmp/aport-*. Contact administrator to add custom allowed directories."
|
|
186
|
+
;;
|
|
187
|
+
"$ERROR_PATH_TRAVERSAL")
|
|
188
|
+
echo "Use absolute paths without parent directory references (../ or /..). This is a security feature to prevent path traversal attacks."
|
|
189
|
+
;;
|
|
190
|
+
"$ERROR_PASSPORT_NOT_FOUND")
|
|
191
|
+
echo "Create a passport by running: npx @aporthq/agent-guardrails openclaw. See: https://github.com/aporthq/agent-guardrails#passport-setup"
|
|
192
|
+
;;
|
|
193
|
+
"$ERROR_PASSPORT_MISSING_CAP")
|
|
194
|
+
echo "Request capability be added to passport or generate new passport with required capabilities."
|
|
195
|
+
;;
|
|
196
|
+
"$ERROR_POLICY_NOT_FOUND")
|
|
197
|
+
echo "Verify policy pack ID is correct and update policy submodule: git submodule update --init --recursive"
|
|
198
|
+
;;
|
|
199
|
+
"$ERROR_API_CONNECTION")
|
|
200
|
+
echo "Check internet connectivity, verify API URL (APORT_API_URL), and check firewall allows outbound HTTPS."
|
|
201
|
+
;;
|
|
202
|
+
"$ERROR_API_AUTH")
|
|
203
|
+
echo "Verify API key is set (APORT_API_KEY) and generate new API key if needed from APort dashboard."
|
|
204
|
+
;;
|
|
205
|
+
"$ERROR_API_RATE_LIMIT")
|
|
206
|
+
echo "Wait for rate limit to reset, reduce request frequency, or use local evaluation mode instead of API mode."
|
|
207
|
+
;;
|
|
208
|
+
"$ERROR_MISCONFIGURED")
|
|
209
|
+
echo "Run setup: npx @aporthq/agent-guardrails <framework>. Check passport exists at ~/.openclaw/passport.json"
|
|
210
|
+
;;
|
|
211
|
+
*)
|
|
212
|
+
echo ""
|
|
213
|
+
;;
|
|
214
|
+
esac
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
# Helper: Write error and exit
|
|
218
|
+
# Usage: die "error_code" "message" ["details"]
|
|
219
|
+
die() {
|
|
220
|
+
local code="$1"
|
|
221
|
+
local message="$2"
|
|
222
|
+
local details="${3:-}"
|
|
223
|
+
local resolution=$(get_resolution "$code")
|
|
224
|
+
|
|
225
|
+
write_deny_decision "$code" "$message" "$details" "$resolution"
|
|
226
|
+
error_log "$code" "$message" "$details"
|
|
227
|
+
exit 1
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
# Validate required command exists
|
|
231
|
+
# Usage: require_command "jq"
|
|
232
|
+
require_command() {
|
|
233
|
+
local cmd="$1"
|
|
234
|
+
local install_hint="${2:-}"
|
|
235
|
+
|
|
236
|
+
if ! command -v "$cmd" > /dev/null 2>&1; then
|
|
237
|
+
local details="{\"command\":\"$cmd\"}"
|
|
238
|
+
local message="Required command not found: $cmd"
|
|
239
|
+
|
|
240
|
+
if [ -n "$install_hint" ]; then
|
|
241
|
+
message="$message. Install with: $install_hint"
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
die "$ERROR_DEPENDENCY_MISSING" "$message" "$details"
|
|
245
|
+
fi
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
# Check if decision file is writable
|
|
249
|
+
# Usage: check_decision_file_writable
|
|
250
|
+
check_decision_file_writable() {
|
|
251
|
+
if [ -z "$DECISION_FILE" ]; then
|
|
252
|
+
error_log "oap.system.evaluator_error" "DECISION_FILE not set"
|
|
253
|
+
return 1
|
|
254
|
+
fi
|
|
255
|
+
|
|
256
|
+
local decision_dir=$(dirname "$DECISION_FILE")
|
|
257
|
+
|
|
258
|
+
if [ ! -d "$decision_dir" ]; then
|
|
259
|
+
error_log "oap.system.insufficient_permissions" "Decision directory does not exist: $decision_dir"
|
|
260
|
+
return 1
|
|
261
|
+
fi
|
|
262
|
+
|
|
263
|
+
if [ ! -w "$decision_dir" ]; then
|
|
264
|
+
error_log "oap.system.insufficient_permissions" "Cannot write to decision directory: $decision_dir"
|
|
265
|
+
return 1
|
|
266
|
+
fi
|
|
267
|
+
|
|
268
|
+
return 0
|
|
269
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Passport creation wizard logic (shared across frameworks)
|
|
3
|
+
# OAP v1.0 format; used by bin/aport-create-passport.sh and framework installers.
|
|
4
|
+
|
|
5
|
+
# shellcheck source=./common.sh
|
|
6
|
+
source "$(dirname "${BASH_SOURCE[0]:-.}")/common.sh"
|
|
7
|
+
|
|
8
|
+
# Placeholder: full wizard logic can be refactored from aport-create-passport.sh
|
|
9
|
+
run_passport_wizard() {
|
|
10
|
+
log_info "Running passport wizard (shared)..."
|
|
11
|
+
# Delegate to existing script if present
|
|
12
|
+
if [[ -x "$ROOT_DIR/bin/aport-create-passport.sh" ]]; then
|
|
13
|
+
"$ROOT_DIR/bin/aport-create-passport.sh" "$@"
|
|
14
|
+
else
|
|
15
|
+
log_warn "bin/aport-create-passport.sh not found; wizard stub only."
|
|
16
|
+
fi
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export -f run_passport_wizard
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Config templates per framework (e.g. aport-config.yaml, config.json)
|