@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,87 @@
|
|
|
1
|
+
# Adding a new framework
|
|
2
|
+
|
|
3
|
+
This doc describes how to add a new framework so that **passport and config logic are shared** and only framework-specific steps live in the new code. Goal: **<50 lines of bash** plus a config template.
|
|
4
|
+
|
|
5
|
+
## 1. Shared layer (no copying)
|
|
6
|
+
|
|
7
|
+
All frameworks use:
|
|
8
|
+
|
|
9
|
+
- **`bin/lib/common.sh`** — logging, `ROOT_DIR`, `require_cmd`
|
|
10
|
+
- **`bin/lib/passport.sh`** — `run_passport_wizard` (delegates to `bin/aport-create-passport.sh`)
|
|
11
|
+
- **`bin/lib/config.sh`** — `get_config_dir`, `write_config_template` (creates framework config dir and copies `bin/lib/templates/config.yaml` if present)
|
|
12
|
+
- **`bin/lib/detect.sh`** — optional; add your project files so the dispatcher can detect the framework
|
|
13
|
+
|
|
14
|
+
Do **not** duplicate passport or config logic in the new framework script.
|
|
15
|
+
|
|
16
|
+
## 2. Add a framework script (<50 lines)
|
|
17
|
+
|
|
18
|
+
Create **`bin/frameworks/<name>.sh`** (e.g. `bin/frameworks/myframework.sh`):
|
|
19
|
+
|
|
20
|
+
1. Source lib: `common.sh`, `passport.sh`, `config.sh`
|
|
21
|
+
2. Call `run_passport_wizard "$@"`
|
|
22
|
+
3. Call `write_config_template <name>` to create the config dir (and optional `config.yaml`)
|
|
23
|
+
4. Print **next steps** (snippet + doc link)
|
|
24
|
+
|
|
25
|
+
Example (same pattern as LangChain/CrewAI/n8n):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
#!/usr/bin/env bash
|
|
29
|
+
# MyFramework installer/setup
|
|
30
|
+
|
|
31
|
+
LIB="$(cd "$(dirname "${BASH_SOURCE[0]:-.}")/../lib" && pwd)"
|
|
32
|
+
source "$LIB/common.sh"
|
|
33
|
+
source "$LIB/passport.sh"
|
|
34
|
+
source "$LIB/config.sh"
|
|
35
|
+
|
|
36
|
+
run_setup() {
|
|
37
|
+
log_info "Setting up APort guardrails for MyFramework..."
|
|
38
|
+
run_passport_wizard "$@"
|
|
39
|
+
config_dir="$(write_config_template myframework)"
|
|
40
|
+
echo ""
|
|
41
|
+
echo " Next steps (MyFramework):"
|
|
42
|
+
echo " 1. Config written to: $config_dir"
|
|
43
|
+
echo " 2. ... (framework-specific snippet)"
|
|
44
|
+
echo " See: docs/frameworks/myframework.md"
|
|
45
|
+
echo ""
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
run_setup "$@"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Add **`get_config_dir`** support in `bin/lib/config.sh` for your framework name and default path (e.g. `$HOME/.aport/myframework`).
|
|
52
|
+
|
|
53
|
+
## 3. Add integration directory
|
|
54
|
+
|
|
55
|
+
Create **`integrations/<name>/`** with:
|
|
56
|
+
|
|
57
|
+
- **README.md** — What this integration does; where the real implementation lives (e.g. `python/myframework_adapter/`, or “plugin in `extensions/`”).
|
|
58
|
+
- **Middleware / plugin / examples** — Framework-specific code or pointers. Can be stubs that reference the actual package (e.g. `python/langchain_adapter/`).
|
|
59
|
+
|
|
60
|
+
Optionally add **`bin/lib/templates/<name>.yaml`** if your framework needs a different config template; otherwise the shared `config.yaml` in `bin/lib/templates/` is copied by `write_config_template` for supported frameworks.
|
|
61
|
+
|
|
62
|
+
## 4. Wire up the dispatcher
|
|
63
|
+
|
|
64
|
+
- In **`bin/agent-guardrails`**, the dispatcher runs `bin/frameworks/<framework>.sh` when `--framework=<name>` or the first arg is `<name>`. Adding `bin/frameworks/myframework.sh` is enough for `--framework=myframework`.
|
|
65
|
+
- If you want **detection from the project directory**, add your project files (e.g. `myframework.toml`) to **`bin/lib/detect.sh`** in `detect_frameworks_list` / `detect_framework`.
|
|
66
|
+
|
|
67
|
+
## 5. Add a framework doc and tests
|
|
68
|
+
|
|
69
|
+
- **`docs/frameworks/<name>.md`** — Setup, config location, suspend (kill switch) = passport status, next steps.
|
|
70
|
+
- **Integration test:** In **`tests/frameworks/<name>/setup.sh`**, run the CLI (e.g. `APORT_FRAMEWORK=myframework` or `--framework=myframework` with non-interactive inputs) and assert the expected config directory and files exist.
|
|
71
|
+
|
|
72
|
+
## Checklist
|
|
73
|
+
|
|
74
|
+
- [ ] `bin/frameworks/<name>.sh` <50 lines; only sources lib + wizard + config + next steps
|
|
75
|
+
- [ ] `bin/lib/config.sh`: `get_config_dir` handles `<name>`; `write_config_template` can create its dir (template copy is automatic if `bin/lib/templates/config.yaml` exists)
|
|
76
|
+
- [ ] `integrations/<name>/README.md` (and optional middleware/examples)
|
|
77
|
+
- [ ] `docs/frameworks/<name>.md`
|
|
78
|
+
- [ ] `tests/frameworks/<name>/setup.sh` (run CLI, assert config)
|
|
79
|
+
|
|
80
|
+
## Reference: existing frameworks
|
|
81
|
+
|
|
82
|
+
| Framework | Script (lines) | Integration dir | Notes |
|
|
83
|
+
|-----------|----------------|-------------------------|--------------------------------|
|
|
84
|
+
| OpenClaw | 19 (delegates) | integrations/openclaw/ | Full installer in `bin/openclaw` |
|
|
85
|
+
| LangChain | 30 | integrations/langchain/ | Python middleware in python/ |
|
|
86
|
+
| CrewAI | 31 | integrations/crewai/ | Python decorator in python/ |
|
|
87
|
+
| n8n | 28 | integrations/n8n/ | Custom node / HTTP + credentials |
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# OpenClaw Agent Configuration
|
|
2
|
+
|
|
3
|
+
<!-- This block is auto-installed by `make openclaw-setup` into workspace/AGENTS.md. It instructs the agent to call the guardrail before effectful actions. That is best-effort (LLM may not follow). Deterministic enforcement requires OpenClaw to call the guardrail via a before_tool_call hook or core integration; see docs/OPENCLAW_COMPATIBILITY.md and docs/APORT_OPENCLAW_INTEGRATION_PROPOSAL.md. -->
|
|
4
|
+
|
|
5
|
+
## Pre-Action Authorization (APort Guardrails) ✅ REQUIRED
|
|
6
|
+
|
|
7
|
+
**CRITICAL RULE**: Before executing ANY tool that has side effects, you MUST verify authorization through APort Agent Guardrails.
|
|
8
|
+
|
|
9
|
+
### Required Steps (in order):
|
|
10
|
+
|
|
11
|
+
1. **Check Passport Status** (guardrail does this first; passport is source of truth)
|
|
12
|
+
- The guardrail checks passport `status` before any policy. If `status` is not `active` (e.g. `suspended` or `revoked`), it denies with `oap.passport_suspended`. No separate kill-switch file.
|
|
13
|
+
|
|
14
|
+
2. **Call APort Verification**
|
|
15
|
+
- Run: `~/.openclaw/.skills/aport-guardrail.sh <tool_name> '<context_json>'`
|
|
16
|
+
- Context JSON should include: tool parameters, resource identifiers, operation details
|
|
17
|
+
|
|
18
|
+
3. **Read Decision**
|
|
19
|
+
- Read `~/.openclaw/decision.json`
|
|
20
|
+
- If `allow: false`: **STOP EXECUTION**, return denial reasons to user
|
|
21
|
+
- If `allow: true`: Proceed with tool execution, log receipt ID
|
|
22
|
+
|
|
23
|
+
4. **Failure Behavior**
|
|
24
|
+
- APort script fails: DENY (fail-closed for security)
|
|
25
|
+
- Passport invalid: DENY with clear error message
|
|
26
|
+
|
|
27
|
+
5. **Never reuse a previous decision**
|
|
28
|
+
- **Always invoke the tool** when the user requests an action. Do not skip or assume a tool will be denied because a previous invocation was denied.
|
|
29
|
+
- APort is re-evaluated on every tool call; passport or limits may have changed. When using the APort plugin, it never reuses a cached decision—each call gets a fresh verify.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Effectful Tools (Require Verification)
|
|
34
|
+
|
|
35
|
+
- **Git Operations**: `git.create_pr`, `git.merge`, `git.push`
|
|
36
|
+
- **System Commands**: `exec.run`, `exec.*`, `system.*`
|
|
37
|
+
- **Messaging**: `message.send`, `messaging.*`
|
|
38
|
+
- **Data Operations**: `database.write`, `data.export`
|
|
39
|
+
|
|
40
|
+
See full documentation: https://github.com/aporthq/aport-agent-guardrails
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Staff-Level Code Review: APort Agent Guardrails
|
|
2
|
+
|
|
3
|
+
**Aligned with:** [FRAMEWORK_SUPPORT_PLAN.md](launch/FRAMEWORK_SUPPORT_PLAN.md)
|
|
4
|
+
**Reviewer lens:** Staff Engineer, infra, security. No sugarcoating.
|
|
5
|
+
**Date:** 2026-02-17
|
|
6
|
+
|
|
7
|
+
**Verification:** The "FIXED" items below are present in the current codebase (evaluator.ts fail-closed, res.ok, per-invocation decision file, realpath, chmod 600, toolToPackId in adapters, CrewAI cache, CI Jest, Python cursor choice, docs). See [2026-02-18-staff-review.md](reviews/2026-02-18-staff-review.md) for re-verification, **security re-score (100/100)**, and any outstanding findings.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Executive summary
|
|
12
|
+
|
|
13
|
+
The codebase delivers a multi-framework guardrail (Node + Python, OpenClaw/Cursor/LangChain/CrewAI) with a shared passport wizard and evaluator. **Production-critical bugs exist** (fail-open when misconfigured, `verifySync` API path/body wrong for full policy pack). Duplication (DRY), unused code, and inconsistent docs hold the score down. With the fixes and improvements below, reaching **100/100** is achievable.
|
|
14
|
+
|
|
15
|
+
**Overall score: 62/100**
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1. Bugs
|
|
20
|
+
|
|
21
|
+
| # | Severity | Location | Description |
|
|
22
|
+
|---|----------|----------|-------------|
|
|
23
|
+
| B1 | **Critical** | — | **FIXED.** Evaluator (Node and Python) is now **fail-closed by default**: when no passport path or guardrail script is found, returns `{ allow: false, reasons: [{ code: 'oap.misconfigured', ... }] }`. Legacy allow behavior: set `fail_open_when_missing_config: true` in config or `APORT_FAIL_OPEN_WHEN_MISSING_CONFIG=1`. |
|
|
24
|
+
| B2 | **High** | `packages/core/src/core/evaluator.ts` `verifySync()` | **Wrong API path and body for full policy pack** — **FIXED.** `verifySync` now uses `pathId = isFullPolicyPack(policy) ? IN_BODY_PACK_ID : packId` in the URL and sets `body.context.policy_id` accordingly. |
|
|
25
|
+
| B3 | Medium | — | **FIXED.** Python LangChain and CrewAI use `decision.get("allow", False)`. |
|
|
26
|
+
| B4 | Low | — | **FIXED.** Cursor `activate()`/`deactivate()` documented as “Reserved for future VS Code extension.” |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. Performance issues
|
|
31
|
+
|
|
32
|
+
| # | Location | Description |
|
|
33
|
+
|---|----------|-------------|
|
|
34
|
+
| P1 | — | **FIXED.** Node CrewAI uses a module-level cached Evaluator (`getCrewaiEvaluator()`). |
|
|
35
|
+
| P2 | — | **FIXED.** Python CrewAI uses `_get_crewai_evaluator()` (module-level cached Evaluator). |
|
|
36
|
+
| P3 | `packages/core/src/core/evaluator.ts` `verifySync()` (L284–298) | Sync API path writes two temp files and spawns `node -e` to run async fetch. Overhead per call (disk I/O, process spawn). Acceptable as a bridge but should be documented; consider a native sync HTTP client or worker thread in the future. |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 3. Incorrect or inadequate documentation
|
|
41
|
+
|
|
42
|
+
| # | Location | Issue |
|
|
43
|
+
|---|----------|--------|
|
|
44
|
+
| D1 | — | **FIXED.** README documents fail-closed and `fail_open_when_missing_config` / env. |
|
|
45
|
+
| D2 | — | **FIXED.** JSDoc on `verifySync` describes sync bridge (temp files + spawn). |
|
|
46
|
+
| D3 | — | **FIXED.** Framework adapter files have “Reserved for programmatic use; CLI dispatch is bin/agent-guardrails (bash).” |
|
|
47
|
+
| D4 | — | **FIXED.** docs/frameworks/cursor.md documents hook script path and guardrail resolution. |
|
|
48
|
+
| D5 | — | **FIXED.** FRAMEWORK_SUPPORT_PLAN and DEPLOYMENT_READINESS updated (fail-closed, cursor stubs). |
|
|
49
|
+
| D6 | — | **FIXED.** `build_tool_context` in Python core `__all__` and exported. |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 4. Unused code
|
|
54
|
+
|
|
55
|
+
| # | Location | Description |
|
|
56
|
+
|---|----------|-------------|
|
|
57
|
+
| U1 | — | **Documented.** cli.ts comment: “Real dispatch is bash: bin/agent-guardrails; reserved for future programmatic use.” |
|
|
58
|
+
| U2 | — | **Documented.** Framework adapters have “Reserved for programmatic use; CLI uses bin/agent-guardrails.” |
|
|
59
|
+
| U3 | — | **Documented.** base.ts comment references CLI. |
|
|
60
|
+
| U4 | — | **Deprecated.** src/evaluator.js has @deprecated notice; use @aporthq/aport-agent-guardrails-core. |
|
|
61
|
+
| U5 | — | **Documented.** integrations/README.md points to packages; stub files kept for compatibility. |
|
|
62
|
+
| U6 | — | **Documented.** Cursor activate/deactivate documented as reserved for future VS Code extension. |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 5. Slop / junior-level code
|
|
67
|
+
|
|
68
|
+
| # | Location | Issue |
|
|
69
|
+
|---|----------|--------|
|
|
70
|
+
| S1 | — | **FIXED.** Single `expandUser()` in `packages/core/src/core/pathUtils.ts`; config, passport, evaluator import it. |
|
|
71
|
+
| S2 | — | **FIXED.** Single source: `tool-pack-mapping.json` in packages/core (and copy in Python). Node: `toolPackMapping.ts` loads JSON and exports `toolToPackId`; Python: `tool_pack_mapping.py` loads same JSON. Evaluator and adapters use it. |
|
|
72
|
+
| S3 | — | **FIXED.** Single source: `default-passport-paths.json` in packages/core (and copy in Python). Node: `defaultPassportPaths.ts`; Python: `default_passport_paths.py`. bin/lib/config.sh comment references the JSON. |
|
|
73
|
+
| S4 | — | **FIXED.** Adapters derive pack ID from tool name (toolToPackId / tool_to_pack_id); pass capability per tool. Previously: Hardcoded `capability: 'system.command.execute.v1'` (or equivalent). The evaluator already maps tool name → pack ID internally; the passed “policy” is only used for IN_BODY. The hardcoded capability is misleading (suggests all tools are evaluated as exec). Either derive from tool name in the adapter or document that the evaluator ignores this for path selection. |
|
|
74
|
+
| S5 | — | **FIXED.** Catch blocks have brief comments (malformed decision, invalid passport, temp cleanup). |
|
|
75
|
+
| S6 | — | **FIXED.** Python `_call_api_sync` validates agent_id/passport before building body. |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 6. Criteria-based score (20+ criteria)
|
|
80
|
+
|
|
81
|
+
Each criterion scored 0–5 (0 = absent/bad, 5 = excellent). Total raw sum then normalized to 0–100.
|
|
82
|
+
|
|
83
|
+
| # | Criterion | Score | Notes |
|
|
84
|
+
|----|-----------|-------|--------|
|
|
85
|
+
| 1 | **DRY (Don’t Repeat Yourself)** | 2 | expandUser x3, toolToPackId x2, default paths x3, buildToolContext vs build_tool_context. |
|
|
86
|
+
| 2 | **Separation of concerns** | 3 | Evaluator does config load + path resolution + API + local; could split resolver, API client, local runner. |
|
|
87
|
+
| 3 | **Single source of truth** | 2 | Passport paths, tool→pack mapping, and “what is the CLI” spread across bash, TS, Python. |
|
|
88
|
+
| 4 | **Fail-safe default (security)** | 1 | Default is fail-open when config/passport missing. Must be fail-closed or explicitly configurable. |
|
|
89
|
+
| 5 | **Input validation** | 3 | Some validation (e.g. passport empty, context shape); API body construction in verifySync not fully aligned with API spec. |
|
|
90
|
+
| 6 | **Error handling** | 2 | Silent catch, generic messages; no structured error codes or logging strategy. |
|
|
91
|
+
| 7 | **Test coverage** | 3 | Core and LangChain have unit tests; CrewAI/Cursor minimal; no E2E for Node. |
|
|
92
|
+
| 8 | **Documentation (code)** | 2 | JSDoc/docstrings partial; fail-open and verifySync bridge undocumented. |
|
|
93
|
+
| 9 | **Documentation (user)** | 4 | README and framework docs improved; deployment readiness doc is clear. |
|
|
94
|
+
| 10 | **API consistency (Node vs Python)** | 4 | Verify/verifySync and context shape aligned; minor differences (e.g. exception types). |
|
|
95
|
+
| 11 | **Dependency hygiene** | 4 | Reasonable; no obvious bloat. |
|
|
96
|
+
| 12 | **No dead code** | 1 | cli.ts, framework adapters, src/evaluator.js, cursor activate/deactivate. |
|
|
97
|
+
| 13 | **Performance awareness** | 2 | New Evaluator per call in CrewAI; sync bridge spawns process; no caching documented. |
|
|
98
|
+
| 14 | **Security (secrets)** | 4 | API key from config/env; temp files for sync path not obviously world-readable but not explicitly restricted. |
|
|
99
|
+
| 15 | **Security (injection)** | 4 | Context passed as JSON; no obvious shell/command injection in TS; bash scripts use jq. |
|
|
100
|
+
| 16 | **Maintainability** | 3 | Structure is clear; duplication and unused code increase maintenance cost. |
|
|
101
|
+
| 17 | **Naming and clarity** | 4 | Names generally clear; some abbreviations (ctx, packId). |
|
|
102
|
+
| 18 | **Logging and observability** | 2 | Little structured logging; audit in bash only. |
|
|
103
|
+
| 19 | **Configuration** | 4 | Config file + env; framework-specific paths documented. |
|
|
104
|
+
| 20 | **Versioning and compatibility** | 4 | OAP v1.0 referenced; version in packages. |
|
|
105
|
+
| 21 | **Accessibility of public API** | 3 | build_tool_context not in __all__; cursor exports unused stubs. |
|
|
106
|
+
| 22 | **Alignment with plan** | 3 | FRAMEWORK_SUPPORT_PLAN says “no stubs”; cursor has stubs. Implementation status table is otherwise accurate. |
|
|
107
|
+
|
|
108
|
+
**Raw sum:** 67 / 110 → **Normalized to 100:** 67 × (100/110) ≈ **61**. Rounded up with partial credit: **62/100**.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 7. How to get to 100/100
|
|
113
|
+
|
|
114
|
+
### 7.1 Critical (must fix)
|
|
115
|
+
|
|
116
|
+
1. **Fail-closed by default**
|
|
117
|
+
When no passport path or no guardrail script is found, return `{ allow: false, reasons: [{ code: 'oap.misconfigured', message: '...' }] }`. Add a config/env option (e.g. `fail_open_when_missing_config: true`) for backward compatibility and document it. Update tests and DEPLOYMENT_READINESS.
|
|
118
|
+
|
|
119
|
+
2. **Fix verifySync API path and body**
|
|
120
|
+
In `packages/core/src/core/evaluator.ts` `verifySync()`:
|
|
121
|
+
- Compute `pathId = isFullPolicyPack(policy) ? IN_BODY_PACK_ID : packId`.
|
|
122
|
+
- Use `pathId` in the URL.
|
|
123
|
+
- Set `body.context.policy_id` to `pathId !== IN_BODY_PACK_ID ? pathId : (policy?.id ?? '')`.
|
|
124
|
+
Add a unit test that verifies IN_BODY request shape when policy is full pack.
|
|
125
|
+
|
|
126
|
+
### 7.2 High (should fix)
|
|
127
|
+
|
|
128
|
+
3. **Remove or implement dead code**
|
|
129
|
+
- Either remove `packages/core/src/cli.ts` or make it delegate to the same flow as the bash CLI.
|
|
130
|
+
- Remove or document `packages/core/src/frameworks/*.ts` adapters (and base class if unused).
|
|
131
|
+
- Remove or deprecate `src/evaluator.js` with a clear note.
|
|
132
|
+
- Cursor: remove `activate`/`deactivate` from exports or implement them and remove TODO.
|
|
133
|
+
|
|
134
|
+
4. **DRY: shared path and tool→pack logic**
|
|
135
|
+
- Single `expandUser` (or path helper) in Node core; use it from config, passport, evaluator.
|
|
136
|
+
- Single source for default passport paths (e.g. one JSON or TS constant imported by evaluator and documented for bash).
|
|
137
|
+
- Single source for tool→pack mapping: e.g. export `toolToPackId` from core and use in adapters; or maintain a JSON map and generate/read from both Node and Python.
|
|
138
|
+
|
|
139
|
+
5. **Performance: reuse Evaluator in CrewAI**
|
|
140
|
+
- Node: allow passing an optional `Evaluator` instance into `beforeToolCall`, or use a module-level cached Evaluator (with clear lifecycle).
|
|
141
|
+
- Python: same (cached evaluator or injectable).
|
|
142
|
+
- Document that creating one Evaluator per flow is recommended.
|
|
143
|
+
|
|
144
|
+
6. **Documentation**
|
|
145
|
+
- Document fail-open vs fail-closed and the new option.
|
|
146
|
+
- Document verifySync sync bridge (temp files, spawn).
|
|
147
|
+
- Add `build_tool_context` to Python core `__all__`.
|
|
148
|
+
- Update FRAMEWORK_SUPPORT_PLAN to mention cursor stubs and fail-open behavior until fixed.
|
|
149
|
+
|
|
150
|
+
### 7.3 Medium (improves score)
|
|
151
|
+
|
|
152
|
+
7. **Python middleware**
|
|
153
|
+
Use `decision.get("allow", False)` (or explicit check) when key is missing.
|
|
154
|
+
|
|
155
|
+
8. **Logging**
|
|
156
|
+
Replace silent catch blocks with at least debug-level logging or a single “evaluator_error” code path.
|
|
157
|
+
|
|
158
|
+
9. **Integration stubs**
|
|
159
|
+
Remove `integrations/langchain/middleware.ts` and `integrations/crewai/decorator.py` if redundant; point docs to the real packages.
|
|
160
|
+
|
|
161
|
+
10. **Tests**
|
|
162
|
+
- Add test for verifySync with full policy pack (IN_BODY path and body shape).
|
|
163
|
+
- Add E2E or integration test for Node LangChain/CrewAI with real config.
|
|
164
|
+
|
|
165
|
+
### 7.4 Polish (100/100)
|
|
166
|
+
|
|
167
|
+
11. **Structured errors**
|
|
168
|
+
Define error codes (e.g. `oap.misconfigured`, `oap.api_error`) and use them consistently; consider a small error hierarchy.
|
|
169
|
+
|
|
170
|
+
12. **Observability**
|
|
171
|
+
Optional audit/log callback or event in the Node evaluator (mirroring bash audit.log) for production debugging.
|
|
172
|
+
|
|
173
|
+
13. **Cursor hook path**
|
|
174
|
+
Document that the hook must run from the npm package root (or from a path where `bin/aport-guardrail-bash.sh` is available).
|
|
175
|
+
|
|
176
|
+
14. **Plan and docs**
|
|
177
|
+
After fixes, set FRAMEWORK_SUPPORT_PLAN and DEPLOYMENT_READINESS to “fail-closed by default” and “no dead code in shipped packages.”
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 8. Summary table
|
|
182
|
+
|
|
183
|
+
| Category | Count | Severity / impact |
|
|
184
|
+
|----------------|-------|-------------------|
|
|
185
|
+
| Bugs | 4 | 1 critical, 1 high, 2 medium/low |
|
|
186
|
+
| Performance | 3 | Evaluator per call; sync bridge overhead |
|
|
187
|
+
| Doc issues | 6 | Fail-open, verifySync, unused code, __all__ |
|
|
188
|
+
| Unused code | 6 | cli.ts, adapters, evaluator.js, stubs |
|
|
189
|
+
| Slop / junior | 6 | DRY, tool→pack, paths, silent catch |
|
|
190
|
+
| Criteria score | 22 | 62/100 overall |
|
|
191
|
+
|
|
192
|
+
**Path to 100:** Fix B1 (fail-closed), B2 (verifySync), remove or implement dead code (U1–U6), DRY (expandUser, toolToPackId, paths), CrewAI Evaluator reuse, document behavior and API, add tests and logging. Then re-score; remaining points are polish (errors, observability, plan alignment).
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Deployment readiness — what’s production vs roadmap
|
|
2
|
+
|
|
3
|
+
**Purpose:** Single source of truth for what is safe to deploy today vs what is stub, partial, or planned. Use this for launch checklists, automation (e.g. OpenClaw Agent), and support.
|
|
4
|
+
|
|
5
|
+
**Related:** [USER_STORIES.md](launch/USER_STORIES.md) (acceptance criteria and test coverage), [FRAMEWORK_ROADMAP.md](FRAMEWORK_ROADMAP.md) (supported frameworks and install). For plan-vs-reality alignment (TypeScript core and Node adapters), see [FRAMEWORK_SUPPORT_PLAN.md § Implementation status](launch/FRAMEWORK_SUPPORT_PLAN.md#implementation-status-current-vs-plan).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What `npx @aporthq/aport-agent-guardrails langchain` (or crewai) actually does
|
|
10
|
+
|
|
11
|
+
When you run **`npx @aporthq/aport-agent-guardrails`** and choose **LangChain** or **CrewAI**, the **Node** CLI runs only the **bash** framework script (`bin/frameworks/langchain.sh` or `crewai.sh`). That script:
|
|
12
|
+
|
|
13
|
+
1. Runs the **shared passport wizard** (same as OpenClaw/Cursor).
|
|
14
|
+
2. Writes **framework-specific config** (e.g. `~/.aport/langchain/config.yaml`).
|
|
15
|
+
3. Prints **next steps** (install Python package and run `aport-langchain setup` or `aport-crewai setup`).
|
|
16
|
+
|
|
17
|
+
It does **not** run Python or install any pip package. The **guardrail** (the code that blocks tool calls when policy denies) is provided by:
|
|
18
|
+
|
|
19
|
+
- **Python:** `pip install aport-agent-guardrails-langchain` / `aport-agent-guardrails-crewai` (on PyPI). **Node:** `@aporthq/aport-agent-guardrails`, `-core`, `-langchain`, `-crewai`, `-cursor` — published to npm via **release CI** on tag push (see [RELEASE.md](RELEASE.md)).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. Safe to deploy today
|
|
24
|
+
|
|
25
|
+
Everything below is **ready to deploy**: CI (`.github/workflows/release.yml`) publishes to npm and PyPI on tag push; tests and docs are in place.
|
|
26
|
+
|
|
27
|
+
| Area | What works | Notes |
|
|
28
|
+
|------|------------|--------|
|
|
29
|
+
| **Release CI** | `.github/workflows/release.yml` on push of tag `v*` | Builds workspace packages; publishes **root** + **core**, **langchain**, **crewai**, **cursor** to npm; publishes **Python** to PyPI; creates GitHub Release. Version check (tag vs root package.json) before publish. n8n package not published yet (coming soon). |
|
|
30
|
+
| **Root npm package** | `@aporthq/aport-agent-guardrails` | CLI: `bin/agent-guardrails`, framework installers (bash), docs. Published by CI on tag. |
|
|
31
|
+
| **Node/TypeScript core** | `packages/core` — evaluator (API + local bash, native fetch in sync path), config (YAML), passport, pathUtils | Fail-closed by default when passport/script missing; `fail_open_when_missing_config` or `APORT_FAIL_OPEN_WHEN_MISSING_CONFIG=1` for legacy. Jest tests (config, passport, evaluator). Published by CI on tag as `@aporthq/aport-agent-guardrails-core`. |
|
|
32
|
+
| **Node LangChain adapter** | `packages/langchain` — `APortGuardrailCallback`, `GuardrailViolationError` | Jest tests (allow/deny, error shape). Published by CI as `@aporthq/aport-agent-guardrails-langchain`. |
|
|
33
|
+
| **Node CrewAI adapter** | `packages/crewai` — `beforeToolCall`, `registerAPortGuardrail`, `withAPortGuardrail` | Feature parity with Python. Published by CI as `@aporthq/aport-agent-guardrails-crewai`. |
|
|
34
|
+
| **Node Cursor package** | `packages/cursor` — `Evaluator`, `getHookPath()` | Re-exports core; runtime is bash hook from CLI. Published by CI as `@aporthq/aport-agent-guardrails-cursor`. |
|
|
35
|
+
| **OpenClaw plugin + wizard** | `bin/openclaw`, `extensions/openclaw-aport/`, passport wizard, local/API evaluator | Full setup: config, plugin install, skill wrappers. Deterministic `before_tool_call` enforcement. |
|
|
36
|
+
| **Bash guardrail** | `bin/aport-guardrail-bash.sh`, `bin/aport-create-passport.sh` | OAP v1.0 wizard, fail-closed guardrail, audit + decision chain. Used by OpenClaw plugin and Cursor hook. |
|
|
37
|
+
| **Cursor hook** | `bin/frameworks/cursor.sh`, `bin/aport-cursor-hook.sh` | Installer writes `~/.cursor/hooks.json`; hook enforces policy; unit + integration tests. User must restart Cursor after install. |
|
|
38
|
+
| **Python LangChain adapter** | `python/langchain_adapter`, `aport-agent-guardrails-langchain` (PyPI), `aport-langchain setup` | Callback handler, shared evaluator, examples, E2E in CI. Published by CI to PyPI. |
|
|
39
|
+
| **Python CrewAI adapter** | `python/crewai_adapter`, `aport-agent-guardrails-crewai` (PyPI), `aport-crewai setup` | Before-tool-call hook, decorator, shared evaluator, examples, E2E in CI. Published by CI to PyPI. |
|
|
40
|
+
| **Dispatcher CLI** | `bin/agent-guardrails`, `bin/lib/detect.sh`, `bin/frameworks/*.sh` | Framework detection, `--framework=`, shared wizard/config; delegates to OpenClaw full installer or framework scripts. |
|
|
41
|
+
| **Docs** | `docs/frameworks/*.md`, README, RELEASE.md, FRAMEWORK_ROADMAP.md | Guardrails vs Core, setup and library usage per framework (Python and Node). |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 2. Not deploy-ready (stub, partial, or missing)
|
|
46
|
+
|
|
47
|
+
| Area | Current state | Impact |
|
|
48
|
+
|------|----------------|--------|
|
|
49
|
+
| **n8n integration** | **Coming soon.** CLI accepts `--framework=n8n` (runs wizard + config only); **@aporthq/aport-agent-guardrails-n8n is not published to npm** until the custom node is ready. Docs and `docs/frameworks/n8n.md` state coming soon. | Custom node and runtime not yet implemented. |
|
|
50
|
+
| **Framework installers (LangChain/CrewAI/n8n)** | `bin/frameworks/langchain.sh`, `crewai.sh`, `n8n.sh` run wizard + write config only; they do **not** run `pip install` or install n8n nodes | User must manually install Python or Node adapter and run framework setup. |
|
|
51
|
+
| **Python CLI (`aport`)** | `python/aport_guardrails/cli.py` — prints next-step commands per framework; does not run wizard | Python-only users run the printed commands (npx or pip) for full setup. |
|
|
52
|
+
| **Shared bash refactor** | Wizard/config logic still largely in `bin/openclaw`; `bin/lib/passport.sh` re-calls `aport-create-passport.sh` | Story B “<50-line framework scripts” holds for langchain/crewai/n8n scripts; OpenClaw path remains the full installer. |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 3. Alignment with USER_STORIES.md
|
|
57
|
+
|
|
58
|
+
- **Stories A–E** describe the **bash dispatcher**, **shared lib**, **Python adapters** (LangChain, CrewAI), and **Cursor**. Implementation status is accurate: detection, `--framework=`, wizard, config, Python packages, Cursor hook, and tests are in place.
|
|
59
|
+
- **Node/TypeScript:** Core, langchain, crewai, and cursor are **implemented** and **ready to deploy**: CI publishes them to npm on tag push. Core and langchain have Jest unit tests; crewai and cursor have feature parity with Python. n8n is **coming soon** (CLI runs wizard + config only; package not published).
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 4. Recommended wording for docs and support
|
|
64
|
+
|
|
65
|
+
- **OpenClaw:** “Production-ready: plugin, wizard, local/API, full installer.”
|
|
66
|
+
- **Cursor:** “Production-ready: hook installer and script; restart Cursor after install.”
|
|
67
|
+
- **LangChain / CrewAI:** “Production-ready **via Python packages**: `pip install aport-agent-guardrails-langchain` (or crewai) and `aport-<framework> setup`. The one-line CLI (`npx @aporthq/aport-agent-guardrails langchain`) runs the passport wizard and writes config; you still install the Python package and run setup yourself.”
|
|
68
|
+
- **n8n:** "Coming soon. CLI accepts --framework=n8n (wizard + config only). Custom node and runtime integration in progress."
|
|
69
|
+
- **Node/TypeScript packages:** “Core, LangChain, CrewAI, and Cursor packages are ready to deploy; CI publishes them to npm on tag push. Install with `npm install @aporthq/aport-agent-guardrails-core` (and `-langchain`, `-crewai`, `-cursor` as needed).”
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 5. Optional improvements (not blocking deploy)
|
|
74
|
+
|
|
75
|
+
1. **Framework installers** that install or verify the relevant package (e.g. `pip install aport-agent-guardrails-langchain` or check and prompt).
|
|
76
|
+
2. **n8n:** Deliver custom node (and credentials schema); until then n8n remains coming soon.
|
|
77
|
+
3. **Python CLI:** Wire `aport setup` to the same wizard/flow as the bash CLI or document that full setup is via `npx @aporthq/aport-agent-guardrails` + framework-specific pip/setup.
|
|
78
|
+
4. **Integration/E2E tests** for Node packages (optional; unit tests for core and langchain are in place).
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
**Production-ready today:** OpenClaw, Cursor, Python LangChain/CrewAI, **and** the Node CLI + Node packages (root, core, langchain, crewai, cursor) — all deployed via CI on tag push.
|