@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,470 @@
|
|
|
1
|
+
# QuickStart: OpenClaw Plugin (Deterministic Enforcement)
|
|
2
|
+
|
|
3
|
+
**5-minute setup for deterministic, platform-level policy enforcement in OpenClaw.**
|
|
4
|
+
|
|
5
|
+
**One command to get started** (recommended — no clone):
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @aporthq/aport-agent-guardrails
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
If you already have an agent_id from aport.io (e.g. after creating a passport there), run `npx @aporthq/aport-agent-guardrails <agent_id>` to use a hosted passport and skip the passport prompt. See [Hosted passport setup](HOSTED_PASSPORT_SETUP.md).
|
|
12
|
+
|
|
13
|
+
This uses the [npm package](https://www.npmjs.com/package/@aporthq/aport-agent-guardrails): it downloads the package (policies + plugin), runs the setup wizard, installs the APort OpenClaw plugin, and runs a smoke test.
|
|
14
|
+
|
|
15
|
+
Then start OpenClaw with the generated config (e.g. `openclaw gateway start --config ~/.openclaw/config.yaml`). The plugin will enforce policies on every tool call.
|
|
16
|
+
|
|
17
|
+
**Alternative: clone the repo** (e.g. to hack on the code or use without npm):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/aporthq/aport-agent-guardrails.git && \
|
|
21
|
+
cd aport-agent-guardrails && \
|
|
22
|
+
git submodule update --init --recursive && \
|
|
23
|
+
./bin/openclaw
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
*Already have the repo?* From the repo root run: `./bin/openclaw`
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Why Use the Plugin?
|
|
31
|
+
|
|
32
|
+
| Approach | Deterministic? | Bypass Risk | Security Level |
|
|
33
|
+
|----------|----------------|-------------|----------------|
|
|
34
|
+
| **OpenClaw Plugin** ✅ | Yes | None | 🟢 Secure |
|
|
35
|
+
| AGENTS.md prompts | No | High | 🔴 Not secure |
|
|
36
|
+
|
|
37
|
+
**Bottom line:** With the plugin, the platform enforces policy before every tool execution. The AI cannot bypass it.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Installation (Automatic)
|
|
42
|
+
|
|
43
|
+
**Recommended:** Use `npx @aporthq/aport-agent-guardrails` (see top of this doc). If you cloned the repo instead, from the repo root run:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
./bin/openclaw
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The script will:
|
|
50
|
+
1. Ask for your OpenClaw config directory (default `~/.openclaw`)
|
|
51
|
+
2. Create your passport (OAP v1.0) there
|
|
52
|
+
3. Prompt to install the APort OpenClaw plugin
|
|
53
|
+
4. Ask for mode (default: **API**; or local) and generate `config.yaml` with plugin settings (passport path, guardrail script path, apiUrl for API mode)
|
|
54
|
+
5. Install guardrail wrappers in the config dir’s `.skills/` (including `aport-guardrail-bash.sh` used by the plugin in local mode)
|
|
55
|
+
6. **Update your passport** — the installer sets `allowed_commands: ["*"]` automatically so normal exec works with no manual editing. You only need to edit the passport later if you want to restrict commands more tightly.
|
|
56
|
+
7. Run a **self-check** (guardrail invoked the same way OpenClaw will use it); if it’s denied, the script exits with a clear message so you know the setup is incomplete.
|
|
57
|
+
8. Optionally install the APort skill and AGENTS.md rule, and run a smoke test
|
|
58
|
+
9. Verify plugin installation
|
|
59
|
+
|
|
60
|
+
**That's it!** Start OpenClaw with that config (e.g. `openclaw gateway start --config ~/.openclaw/config.yaml`). The plugin will enforce policies on every tool call; no extra steps required.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Installation (Manual)
|
|
65
|
+
|
|
66
|
+
If you prefer manual installation:
|
|
67
|
+
|
|
68
|
+
### 1. Create Passport
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
./bin/aport-create-passport.sh --output ~/.openclaw/aport/passport.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 2. Install Plugin
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
openclaw plugins install /path/to/aport-agent-guardrails/extensions/openclaw-aport
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 3. Configure Plugin
|
|
81
|
+
|
|
82
|
+
Create or edit `~/.openclaw/config.yaml`:
|
|
83
|
+
|
|
84
|
+
```yaml
|
|
85
|
+
plugins:
|
|
86
|
+
enabled: true
|
|
87
|
+
entries:
|
|
88
|
+
openclaw-aport:
|
|
89
|
+
enabled: true
|
|
90
|
+
config:
|
|
91
|
+
# Mode: "api" (default, recommended) or "local" (guardrail script, no network)
|
|
92
|
+
mode: api
|
|
93
|
+
|
|
94
|
+
# Passport file location
|
|
95
|
+
passportFile: ~/.openclaw/aport/passport.json
|
|
96
|
+
|
|
97
|
+
# For local mode: path to guardrail script
|
|
98
|
+
guardrailScript: ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
99
|
+
|
|
100
|
+
# Fail-closed: block on error (default: true)
|
|
101
|
+
failClosed: true
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
For **API mode (default)**, set:
|
|
105
|
+
```yaml
|
|
106
|
+
mode: api
|
|
107
|
+
apiUrl: https://api.aport.io
|
|
108
|
+
```
|
|
109
|
+
Set `APORT_API_KEY` in the environment if your API requires auth. Do not put `${APORT_API_KEY}` in the config file (OpenClaw will require the var to exist at load time).
|
|
110
|
+
|
|
111
|
+
### 4. Install Guardrail Scripts (local mode only)
|
|
112
|
+
|
|
113
|
+
If you **did not** run `./bin/openclaw`, you need the guardrail script for local mode. If you **did** run the setup script, it already created `CONFIG_DIR/.skills/aport-guardrail-bash.sh`; skip this step.
|
|
114
|
+
|
|
115
|
+
Otherwise:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
mkdir -p ~/.openclaw/.skills
|
|
119
|
+
# Create wrapper that points to this repo (replace /path/to with real path)
|
|
120
|
+
cat > ~/.openclaw/.skills/aport-guardrail-bash.sh << 'EOF'
|
|
121
|
+
#!/bin/bash
|
|
122
|
+
APORT_REPO_ROOT="/path/to/aport-agent-guardrails"
|
|
123
|
+
export OPENCLAW_PASSPORT_FILE="${OPENCLAW_PASSPORT_FILE:-$HOME/.openclaw/aport/passport.json}"
|
|
124
|
+
export OPENCLAW_DECISION_FILE="${OPENCLAW_DECISION_FILE:-$HOME/.openclaw/aport/decision.json}"
|
|
125
|
+
exec "$APORT_REPO_ROOT/bin/aport-guardrail-bash.sh" "$@"
|
|
126
|
+
EOF
|
|
127
|
+
chmod +x ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 5. Verify Installation
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Check plugin is installed
|
|
134
|
+
openclaw plugins list | grep openclaw-aport
|
|
135
|
+
|
|
136
|
+
# Should show: openclaw-aport (enabled)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## How It Works
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
User → AI: "Delete all log files"
|
|
145
|
+
↓
|
|
146
|
+
OpenClaw: AI wants to use tool "exec.run"
|
|
147
|
+
↓
|
|
148
|
+
Platform: Fires before_tool_call hook
|
|
149
|
+
↓
|
|
150
|
+
APort Plugin: Maps "exec.run" → "system.command.execute.v1"
|
|
151
|
+
↓
|
|
152
|
+
APort Plugin: Calls guardrail script/API
|
|
153
|
+
↓
|
|
154
|
+
Guardrail: Evaluates against passport + limits
|
|
155
|
+
↓
|
|
156
|
+
┌──────────┴──────────┐
|
|
157
|
+
│ │
|
|
158
|
+
ALLOW DENY
|
|
159
|
+
│ │
|
|
160
|
+
↓ ↓
|
|
161
|
+
Tool executes Returns { block: true, blockReason }
|
|
162
|
+
↓
|
|
163
|
+
OpenClaw throws error
|
|
164
|
+
↓
|
|
165
|
+
Tool NEVER executes
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Key:** The platform enforces policy. The AI cannot skip this check.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Testing
|
|
173
|
+
|
|
174
|
+
### 1. Start OpenClaw with Plugin
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
openclaw gateway start --config ~/.openclaw/config.yaml
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 2. Test Allowed Action
|
|
181
|
+
|
|
182
|
+
Try a simple command that should be allowed:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# Via OpenClaw agent
|
|
186
|
+
"Run: node --version"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Expected: Command executes (allowed by passport limits)
|
|
190
|
+
|
|
191
|
+
### 3. Test Denied Action
|
|
192
|
+
|
|
193
|
+
Try a command that exceeds your passport limits:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Via OpenClaw agent
|
|
197
|
+
"Delete all files in /tmp"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Expected: Tool blocked with message:
|
|
201
|
+
```
|
|
202
|
+
🛡️ APort Policy Denied
|
|
203
|
+
|
|
204
|
+
Policy: system.command.execute.v1
|
|
205
|
+
Reason: Command exceeds allowed scope
|
|
206
|
+
|
|
207
|
+
To override, update your passport at: ~/.openclaw/aport/passport.json (or ~/.openclaw/passport.json for legacy)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Modes
|
|
213
|
+
|
|
214
|
+
**API mode** is still the default and recommended. **Local mode** now has full parity with API for exec mapping (fixed); both evaluate the same policies. Messaging runs at assurance L0 by default.
|
|
215
|
+
|
|
216
|
+
### API Mode (default, recommended)
|
|
217
|
+
|
|
218
|
+
**Best for:** Production, full OAP policy (JSON Schema, assurance, evaluation rules), signed decisions, cloud kill switch, audit logs.
|
|
219
|
+
|
|
220
|
+
```yaml
|
|
221
|
+
config:
|
|
222
|
+
mode: api
|
|
223
|
+
passportFile: ~/.openclaw/aport/passport.json
|
|
224
|
+
apiUrl: https://api.aport.io
|
|
225
|
+
```
|
|
226
|
+
Set `APORT_API_KEY` in the environment only if your API requires auth.
|
|
227
|
+
|
|
228
|
+
**How it works:**
|
|
229
|
+
- Plugin loads local passport
|
|
230
|
+
- Sends passport + context to APort API
|
|
231
|
+
- API evaluates (passport NOT stored, stateless)
|
|
232
|
+
- Returns signed decision
|
|
233
|
+
- **Network required**
|
|
234
|
+
|
|
235
|
+
### Local Mode
|
|
236
|
+
|
|
237
|
+
**Best for:** Privacy, offline use, no network dependency
|
|
238
|
+
|
|
239
|
+
```yaml
|
|
240
|
+
config:
|
|
241
|
+
mode: local
|
|
242
|
+
passportFile: ~/.openclaw/aport/passport.json
|
|
243
|
+
guardrailScript: ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**How it works:**
|
|
247
|
+
- Plugin calls local bash script
|
|
248
|
+
- Script evaluates policy using local passport (subset of OAP; see [Verification methods](VERIFICATION_METHODS.md))
|
|
249
|
+
- Returns decision (exit 0 = allow, exit 1 = deny)
|
|
250
|
+
- **No network required**
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Troubleshooting
|
|
255
|
+
|
|
256
|
+
### Plugin not loading
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
# Check plugin list
|
|
260
|
+
openclaw plugins list
|
|
261
|
+
|
|
262
|
+
# Should show: openclaw-aport (enabled)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
If not listed:
|
|
266
|
+
1. Verify installation: `openclaw plugins install /path/to/extensions/openclaw-aport`
|
|
267
|
+
2. Check config.yaml has `plugins.entries.openclaw-aport.enabled: true`
|
|
268
|
+
3. Restart OpenClaw gateway
|
|
269
|
+
|
|
270
|
+
### Tools not being blocked
|
|
271
|
+
|
|
272
|
+
Check:
|
|
273
|
+
1. **Plugin enabled?** `openclaw plugins list` should show `openclaw-aport (enabled)`
|
|
274
|
+
2. **Tool mapped?** See tool-to-policy mapping in plugin README
|
|
275
|
+
3. **Passport allows it?** The installer sets `allowed_commands: ["*"]` by default. If you intentionally tightened the allowlist, re-add the commands you need to `limits.system.command.execute.allowed_commands` in your passport.
|
|
276
|
+
4. **Script working?** Test directly:
|
|
277
|
+
```bash
|
|
278
|
+
~/.openclaw/.skills/aport-guardrail-bash.sh system.command.execute '{"command":"ls"}'
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Error: "Failed to run guardrail script"
|
|
282
|
+
|
|
283
|
+
Check:
|
|
284
|
+
1. Script exists: `ls -l ~/.openclaw/.skills/aport-guardrail-bash.sh`
|
|
285
|
+
2. Script executable: `chmod +x ~/.openclaw/.skills/aport-guardrail-bash.sh`
|
|
286
|
+
3. Script works: Run test command above
|
|
287
|
+
|
|
288
|
+
### Guardrail DENY / `oap.passport_version_mismatch`
|
|
289
|
+
|
|
290
|
+
If the guardrail denies every call and `~/.openclaw/aport/decision.json` (or `~/.openclaw/decision.json`) shows reason `oap.passport_version_mismatch` ("Passport spec version is 'unknown', expected 'oap/1.0'"):
|
|
291
|
+
|
|
292
|
+
1. **Passport must have `spec_version: "oap/1.0"`** (OAP spec). If your passport has only `"version": "1.0.0"` in metadata and no top-level `spec_version`, it was created by an older or non–spec-compliant tool.
|
|
293
|
+
2. **Limits must be nested per capability.** The verifier expects e.g. `limits["system.command.execute"]` with `allowed_commands`, `blocked_patterns`, not a flat `limits.allowed_commands` at the top level.
|
|
294
|
+
|
|
295
|
+
**Fix:** Re-run the installer so it can normalize the passport:
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
npx @aporthq/aport-agent-guardrails
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Choose to overwrite the existing passport when prompted, or run the wizard with `--output` to a new file. The installer now ensures `spec_version: "oap/1.0"` and nested limits. If you prefer to fix the file manually, add `"spec_version": "oap/1.0"` at the top level and move any top-level `allowed_commands` / `blocked_patterns` under `limits["system.command.execute"]`. See [agent-passport/spec/oap](https://github.com/aporthq/agent-passport/tree/main/spec/oap) for the canonical schema.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Configuration Reference
|
|
306
|
+
|
|
307
|
+
### Minimum Configuration (API mode — default)
|
|
308
|
+
|
|
309
|
+
```yaml
|
|
310
|
+
plugins:
|
|
311
|
+
enabled: true
|
|
312
|
+
entries:
|
|
313
|
+
openclaw-aport:
|
|
314
|
+
enabled: true
|
|
315
|
+
config:
|
|
316
|
+
mode: api
|
|
317
|
+
passportFile: ~/.openclaw/aport/passport.json
|
|
318
|
+
apiUrl: https://api.aport.io
|
|
319
|
+
failClosed: true
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Full Configuration (API mode)
|
|
323
|
+
|
|
324
|
+
```yaml
|
|
325
|
+
plugins:
|
|
326
|
+
enabled: true
|
|
327
|
+
entries:
|
|
328
|
+
openclaw-aport:
|
|
329
|
+
enabled: true
|
|
330
|
+
config:
|
|
331
|
+
# Mode: "api" (default) or "local"
|
|
332
|
+
mode: api
|
|
333
|
+
|
|
334
|
+
# Passport file location
|
|
335
|
+
passportFile: ~/.openclaw/aport/passport.json
|
|
336
|
+
|
|
337
|
+
# For local mode: path to guardrail script
|
|
338
|
+
guardrailScript: ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
339
|
+
|
|
340
|
+
# For API mode: APort API endpoint
|
|
341
|
+
apiUrl: https://api.aport.io # or your self-hosted API URL
|
|
342
|
+
# Optional: set APORT_API_KEY in the environment if your API requires auth
|
|
343
|
+
|
|
344
|
+
# Fail-closed: block on error (default: true)
|
|
345
|
+
failClosed: true
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Minimum Configuration (Local mode)
|
|
349
|
+
|
|
350
|
+
```yaml
|
|
351
|
+
plugins:
|
|
352
|
+
enabled: true
|
|
353
|
+
entries:
|
|
354
|
+
openclaw-aport:
|
|
355
|
+
enabled: true
|
|
356
|
+
config:
|
|
357
|
+
mode: local
|
|
358
|
+
passportFile: ~/.openclaw/aport/passport.json
|
|
359
|
+
guardrailScript: ~/.openclaw/.skills/aport-guardrail-bash.sh
|
|
360
|
+
failClosed: true
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Tool-to-Policy Mapping
|
|
366
|
+
|
|
367
|
+
The plugin automatically maps OpenClaw tool names to APort policy packs:
|
|
368
|
+
|
|
369
|
+
| OpenClaw Tool | APort Policy |
|
|
370
|
+
|---------------|--------------|
|
|
371
|
+
| `git.create_pr`, `git.merge`, `git.push` | `code.repository.merge.v1` |
|
|
372
|
+
| `exec.run`, `system.command.*`, `bash` | `system.command.execute.v1` |
|
|
373
|
+
| `message.send`, `messaging.*` | `messaging.message.send.v1` |
|
|
374
|
+
| `mcp.*` | `mcp.tool.execute.v1` |
|
|
375
|
+
| `session.create` | `agent.session.create.v1` |
|
|
376
|
+
| `tool.register` | `agent.tool.register.v1` |
|
|
377
|
+
| `payment.refund` | `finance.payment.refund.v1` |
|
|
378
|
+
| `payment.charge` | `finance.payment.charge.v1` |
|
|
379
|
+
| `data.export` | `data.export.create.v1` |
|
|
380
|
+
|
|
381
|
+
Unmapped tools are allowed (fail-open for flexibility).
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Security Considerations
|
|
386
|
+
|
|
387
|
+
### Fail-Closed by Default
|
|
388
|
+
|
|
389
|
+
By default, `failClosed: true` means **any error blocks the tool**:
|
|
390
|
+
- Script not found → BLOCK
|
|
391
|
+
- API unreachable → BLOCK
|
|
392
|
+
- Invalid passport → BLOCK
|
|
393
|
+
|
|
394
|
+
This is secure-by-default. To fail-open (not recommended):
|
|
395
|
+
|
|
396
|
+
```yaml
|
|
397
|
+
config:
|
|
398
|
+
failClosed: false # Allow on error (NOT RECOMMENDED)
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Plugin Trust
|
|
402
|
+
|
|
403
|
+
Plugins run **in-process** with full access to OpenClaw. Only install from trusted sources:
|
|
404
|
+
- Official APort plugin (this)
|
|
405
|
+
- Your own forks/modifications
|
|
406
|
+
|
|
407
|
+
Use `plugins.allow` allowlist in config.yaml:
|
|
408
|
+
|
|
409
|
+
```yaml
|
|
410
|
+
plugins:
|
|
411
|
+
allow:
|
|
412
|
+
- openclaw-aport
|
|
413
|
+
- your-other-trusted-plugin
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Bypass Prevention
|
|
417
|
+
|
|
418
|
+
**With plugin:** AI **cannot** bypass policy enforcement. The platform calls `before_tool_call` before every tool.
|
|
419
|
+
|
|
420
|
+
**Without plugin (AGENTS.md only):** AI **can** bypass via:
|
|
421
|
+
- Prompt injection
|
|
422
|
+
- Forgetting to call guardrail
|
|
423
|
+
- Deciding action is "safe"
|
|
424
|
+
|
|
425
|
+
**Bottom line:** Plugin = deterministic. AGENTS.md = best-effort (not secure).
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Next Steps
|
|
430
|
+
|
|
431
|
+
1. **Run the setup (once):** From repo root: `./bin/openclaw`. Use the default config dir or choose a path.
|
|
432
|
+
2. **Choose "yes"** when prompted to install the plugin.
|
|
433
|
+
3. **Start OpenClaw** with the generated config: `openclaw gateway start --config <your-config-dir>/config.yaml` (e.g. `~/.openclaw/config.yaml`).
|
|
434
|
+
4. **Test enforcement:** Run the agent; try an allowed action (e.g. `node --version`) and one that should be blocked by your passport (e.g. `rm -rf /`). The plugin blocks before the tool runs.
|
|
435
|
+
5. **Customize passport:** Edit `<config-dir>/aport/passport.json` (or `<config-dir>/passport.json` for legacy) to adjust limits and allowed commands.
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Support
|
|
440
|
+
|
|
441
|
+
- **Full documentation:** [`extensions/openclaw-aport/README.md`](../extensions/openclaw-aport/README.md)
|
|
442
|
+
- **Issues:** [GitHub Issues](https://github.com/aporthq/aport-agent-guardrails/issues)
|
|
443
|
+
- **Discord:** [discord.gg/aport](https://discord.gg/aport)
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## Summary
|
|
448
|
+
|
|
449
|
+
✅ **One command:** Run `./bin/openclaw` from the repo root to create passport, install plugin, write config and wrappers, and verify. You only need this once per config dir.
|
|
450
|
+
✅ **Deterministic enforcement:** The plugin runs before every tool; the platform enforces, the AI cannot bypass.
|
|
451
|
+
✅ **Fail-closed:** Blocks on error by default.
|
|
452
|
+
✅ **API (default) or local:** Full OAP via API, or local script for offline/privacy.
|
|
453
|
+
✅ **Zero OpenClaw core changes:** Uses the existing OpenClaw plugin API.
|
|
454
|
+
|
|
455
|
+
**After setup, start OpenClaw with the generated config—your agent is then secured by APort policy.**
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
## How it all fits together
|
|
460
|
+
|
|
461
|
+
| Step | What happens |
|
|
462
|
+
|------|----------------|
|
|
463
|
+
| You run `./bin/openclaw` | Script asks for config dir, creates passport, installs plugin, writes `config.yaml`, installs wrappers in `<config-dir>/.skills/`, and **updates the passport** with default `allowed_commands` (bash, sh, ls, mkdir, npm, etc.) so normal exec works. |
|
|
464
|
+
| `config.yaml` | Contains `passportFile` and `guardrailScript` pointing to `<config-dir>/aport/passport.json` and `<config-dir>/.skills/aport-guardrail-bash.sh`. |
|
|
465
|
+
| Passport allowlist | The installer sets `allowed_commands: ["*"]` automatically. No manual editing needed unless you want to restrict commands. |
|
|
466
|
+
| Wrapper script | `<config-dir>/.skills/aport-guardrail-bash.sh` is a small script that calls this repo’s `bin/aport-guardrail-bash.sh` with the same args and env (passport path, etc.). |
|
|
467
|
+
| You start OpenClaw | `openclaw gateway start --config <config-dir>/config.yaml` (or use that config when running the agent). |
|
|
468
|
+
| On every tool call | OpenClaw runs the plugin’s `before_tool_call` hook → plugin calls the guardrail script with tool name and params → script evaluates against passport and policy → allow = tool runs, deny = plugin returns `block: true` and the tool never runs. |
|
|
469
|
+
|
|
470
|
+
**So: one run of `./bin/openclaw` is all you need.** No manual editing of config or wrapper paths if you use the default config dir.
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# APort Agent Guardrails — Documentation
|
|
2
|
+
|
|
3
|
+
**Public documentation** (for users integrating OpenClaw + APort guardrails):
|
|
4
|
+
|
|
5
|
+
| Doc | Purpose |
|
|
6
|
+
|-----|---------|
|
|
7
|
+
| [QUICKSTART_OPENCLAW_PLUGIN.md](QUICKSTART_OPENCLAW_PLUGIN.md) | **OpenClaw plugin** — 5-minute setup, deterministic enforcement (RECOMMENDED) |
|
|
8
|
+
| [**HOSTED_PASSPORT_SETUP.md**](HOSTED_PASSPORT_SETUP.md) | **Use passport from aport.io** — create at aport.io, then `npx @aporthq/aport-agent-guardrails <agent_id>` (or choose hosted in wizard) |
|
|
9
|
+
| [QUICKSTART.md](QUICKSTART.md) | Interactive setup and step-by-step with passport wizard |
|
|
10
|
+
| [OPENCLAW_LOCAL_INTEGRATION.md](OPENCLAW_LOCAL_INTEGRATION.md) | Full OpenClaw setup: API, passport, policies, Python example |
|
|
11
|
+
| [OPENCLAW_TOOLS_AND_POLICIES.md](OPENCLAW_TOOLS_AND_POLICIES.md) | exec, allowed_commands, unmapped tools, passport limits |
|
|
12
|
+
| [TOOL_POLICY_MAPPING.md](TOOL_POLICY_MAPPING.md) | How tool names map to policy packs |
|
|
13
|
+
| [IMPLEMENTING_YOUR_OWN_EVALUATOR.md](IMPLEMENTING_YOUR_OWN_EVALUATOR.md) | Build your own evaluator from the OAP spec |
|
|
14
|
+
| [OPENCLAW_COMPATIBILITY.md](OPENCLAW_COMPATIBILITY.md) | OpenClaw version alignment, paths, OPENCLAW_HOME |
|
|
15
|
+
| [AGENTS.md.example](AGENTS.md.example) | Example AGENTS.md section for pre-action authorization |
|
|
16
|
+
| [REPO_LAYOUT.md](REPO_LAYOUT.md) | What `bin/`, `src/`, `extensions/`, `external/` do |
|
|
17
|
+
|
|
18
|
+
**Launch & checklists** (internal / maintainers):
|
|
19
|
+
|
|
20
|
+
| Doc | Purpose |
|
|
21
|
+
|-----|---------|
|
|
22
|
+
| [LAUNCH_READINESS_CHECKLIST.md](LAUNCH_READINESS_CHECKLIST.md) | Launch checklist + guardrail execution gate |
|
|
23
|
+
| [launch/LAUNCH_STRATEGY_SUMMARY.md](launch/LAUNCH_STRATEGY_SUMMARY.md) | Timing, content, evidence, pre-flight |
|
|
24
|
+
| [launch/QUICK_LAUNCH_CHECKLIST.md](launch/QUICK_LAUNCH_CHECKLIST.md) | Final verification before each post |
|
|
25
|
+
| [launch/OPENCLAW_FEEDBACK_AND_FIXES.md](launch/OPENCLAW_FEEDBACK_AND_FIXES.md) | OpenClaw feedback summary + two fixes (allowlist, capabilities) |
|
|
26
|
+
| [launch/POST_1_VALENTINE_IMPROVED.md](launch/POST_1_VALENTINE_IMPROVED.md) | Post 1 draft (Valentine) |
|
|
27
|
+
| [launch/POST_2_GUARDRAIL_IMPROVED.md](launch/POST_2_GUARDRAIL_IMPROVED.md) | Post 2 draft (Guardrail) |
|
|
28
|
+
| [ANNOUNCEMENT_GUIDE.md](ANNOUNCEMENT_GUIDE.md) | Announcement messaging and materials |
|
package/docs/RELEASE.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Release process and version policy
|
|
2
|
+
|
|
3
|
+
**Current release:** 1.0.8 (see [CHANGELOG.md](../CHANGELOG.md)).
|
|
4
|
+
|
|
5
|
+
We keep **one version number** across all published packages (Node core, Python core, and every framework adapter). That avoids “core is 1.2 but CLI is 0.9” and keeps the story simple for users and support.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Version policy summary
|
|
10
|
+
|
|
11
|
+
| What | Policy |
|
|
12
|
+
|------|--------|
|
|
13
|
+
| **Core packages** | `@aporthq/aport-agent-guardrails` (root/CLI), `@aporthq/aport-agent-guardrails-core`, `aport-agent-guardrails` (Python) always share the same version (e.g. `1.3.0`). |
|
|
14
|
+
| **Framework adapters** | Node: `@aporthq/aport-agent-guardrails-langchain`, `-crewai`, `-cursor` (published). `-n8n` is **not published yet** (coming soon). Python: `aport-agent-guardrails-langchain`, `aport-agent-guardrails-crewai`. They depend on core with `>=` and publish with the same version as core. |
|
|
15
|
+
| **Repo tag** | Git tag `v1.3.0` matches the released version so docs and installs stay aligned. |
|
|
16
|
+
|
|
17
|
+
So: **one version for the whole suite.** If only the LangChain adapter changed, we still bump core (and all other packages) to the same new version so everything stays in lockstep.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1.1. Why two npm packages: @aporthq/aport-agent-guardrails vs @aporthq/aport-agent-guardrails-core?
|
|
22
|
+
|
|
23
|
+
| Package | What it is | Who installs it |
|
|
24
|
+
|---------|------------|------------------|
|
|
25
|
+
| **@aporthq/aport-agent-guardrails** (root) | The **CLI and setup tool**: `bin/agent-guardrails`, framework installers (bash scripts), docs, OpenClaw extension. No TypeScript evaluator — it runs the passport wizard and writes config. | Users who want the one-line setup: `npx @aporthq/aport-agent-guardrails langchain` (or cursor, crewai, openclaw). |
|
|
26
|
+
| **@aporthq/aport-agent-guardrails-core** | The **Node library**: Evaluator, config, passport loading, `verify` / `verifySync`. Used inside your app to enforce policy. | Anyone using the **framework adapters** (e.g. `@aporthq/aport-agent-guardrails-langchain`) — they depend on core. Also apps that want only the evaluator without the CLI. |
|
|
27
|
+
|
|
28
|
+
So: **root = CLI/setup**; **core = library**. We publish core so that (1) the adapters can declare it as a dependency and npm can resolve it, and (2) users can install just the evaluator if they don’t need the full CLI.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 2. Tooling
|
|
33
|
+
|
|
34
|
+
- **Changesets** (Node): fixed mode so all workspace packages are in one “fixed” group and get the same version on release.
|
|
35
|
+
- **sync-version script**: after `changeset version`, copies the new version from root `package.json` into all Python `pyproject.toml` and `aport_guardrails/__init__.py`.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 3. Release flow
|
|
40
|
+
|
|
41
|
+
1. **Merge PRs** → run automated tests (e.g. CI).
|
|
42
|
+
2. **Bump version and changelogs**
|
|
43
|
+
```bash
|
|
44
|
+
npm run version
|
|
45
|
+
```
|
|
46
|
+
This runs `changeset version` (updates all Node `package.json` and CHANGELOGs) then `node scripts/sync-version.mjs` (updates Python packages to the same version).
|
|
47
|
+
3. **Commit** the version bump and changelog updates (e.g. “chore(release): 1.3.0”).
|
|
48
|
+
4. **Tag and push** — this triggers the release workflow and publishes both npm and PyPI:
|
|
49
|
+
```bash
|
|
50
|
+
git tag v1.3.0
|
|
51
|
+
git push origin v1.3.0
|
|
52
|
+
```
|
|
53
|
+
5. **CI (`.github/workflows/release.yml`)**: on tag push `v*`:
|
|
54
|
+
- **publish-npm**: publishes the **root** package `@aporthq/aport-agent-guardrails` (CLI) and workspace packages `@aporthq/aport-agent-guardrails-core`, `-langchain`, `-crewai`, `-cursor` to npm. The **n8n** package is not published yet (coming soon). Uses `NPM_TOKEN` secret.
|
|
55
|
+
- **publish-python**: builds and publishes `aport-agent-guardrails`, `aport-agent-guardrails-langchain`, and `aport-agent-guardrails-crewai` to PyPI (uses `PYPI_TOKEN` secret). Skips upload if aport-agent-guardrails version already exists.
|
|
56
|
+
- **create-release**: creates the GitHub Release with install notes for both ecosystems.
|
|
57
|
+
|
|
58
|
+
**PyPI**: In [PyPI project settings](https://pypi.org/help/#project-urls), set Repository and (if using trusted publishing) add this repo and workflow name **Release**. Otherwise configure the `PYPI_TOKEN` secret in the GitHub repo.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 4. Adding a changeset (before release)
|
|
63
|
+
|
|
64
|
+
After making any change that should go into the next release:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx changeset
|
|
68
|
+
# or
|
|
69
|
+
npm run changeset
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- Choose **patch** / **minor** / **major**.
|
|
73
|
+
- Write a short summary for the changelog.
|
|
74
|
+
- Commit the new file under `.changeset/`.
|
|
75
|
+
|
|
76
|
+
When you run `npm run version`, that changeset will drive a single version bump for the whole fixed group; then `sync-version` keeps Python in sync.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 5. Long-term flexibility
|
|
81
|
+
|
|
82
|
+
If we later need finer control (e.g. enterprise adapters that shouldn’t force a full suite release), we can:
|
|
83
|
+
|
|
84
|
+
- Move to independent versioning for some adapters, and/or
|
|
85
|
+
- Introduce a “meta” package that pins compatible versions.
|
|
86
|
+
|
|
87
|
+
For now, a single version across all packages keeps the ecosystem coherent and avoids support confusion.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Repository Layout
|
|
2
|
+
|
|
3
|
+
Quick reference for what each part of the repo does.
|
|
4
|
+
|
|
5
|
+
## `bin/`
|
|
6
|
+
|
|
7
|
+
CLI and guardrail entrypoints used by OpenClaw (or any framework):
|
|
8
|
+
|
|
9
|
+
| Script | Purpose |
|
|
10
|
+
|--------|---------|
|
|
11
|
+
| **openclaw** | One-command setup: passport wizard, plugin install, config, `.skills` wrappers |
|
|
12
|
+
| **aport-create-passport.sh** | Interactive OAP v1.0 passport wizard (capabilities, limits, L0 default) |
|
|
13
|
+
| **aport-guardrail-bash.sh** | **Local evaluator** — evaluates policy using passport + `external/aport-policies`; no API, no network |
|
|
14
|
+
| **aport-guardrail-api.sh** | Calls APort API (cloud or self-hosted); uses **src/evaluator.js** |
|
|
15
|
+
| **aport-guardrail.sh** | Backward-compat wrapper → runs bash guardrail |
|
|
16
|
+
| **aport-guardrail-v2.sh** | Backward-compat wrapper → runs API guardrail |
|
|
17
|
+
| **aport-status.sh** | Show passport summary and status |
|
|
18
|
+
|
|
19
|
+
## `src/`
|
|
20
|
+
|
|
21
|
+
Node.js code for **API-based** evaluation and optional proxy:
|
|
22
|
+
|
|
23
|
+
| File | Purpose |
|
|
24
|
+
|------|---------|
|
|
25
|
+
| **evaluator.js** | **APort API client** — calls `POST /api/verify/policy/{packId}` with passport (local mode) or `agent_id` (cloud mode). Used by `bin/aport-guardrail-api.sh` and by any programmatic caller (e.g. `require('./src/evaluator')`). Supports `APORT_API_URL`, `APORT_AGENT_ID`, `APORT_API_KEY`. Loads policy packs from `external/aport-policies` and passports from file. |
|
|
26
|
+
| **server/index.js** | **Optional HTTP proxy** — forwards requests to the agent-passport API (e.g. `APORT_API_BASE=https://api.aport.io`). Run with `npm run server` (port 8788). Use when you need a proxy in front of the API; most users call the API directly. |
|
|
27
|
+
|
|
28
|
+
**Summary:** For **local evaluation with no network**, the repo uses **bin/aport-guardrail-bash.sh** (bash + jq + policies from submodule). For **API evaluation** (cloud or self-hosted agent-passport), it uses **src/evaluator.js** (Node) and **bin/aport-guardrail-api.sh** (which invokes the evaluator).
|
|
29
|
+
|
|
30
|
+
## `extensions/openclaw-aport/`
|
|
31
|
+
|
|
32
|
+
OpenClaw plugin — `before_tool_call` hook that invokes the guardrail script or API before every tool execution. Deterministic enforcement; AI cannot bypass.
|
|
33
|
+
|
|
34
|
+
## `external/`
|
|
35
|
+
|
|
36
|
+
Git submodules (run `npm run sync-submodules` or `sync-submodules:latest`):
|
|
37
|
+
|
|
38
|
+
- **aport-spec** — OAP passport/decision schema and spec
|
|
39
|
+
- **aport-policies** — Policy packs (system.command.execute, messaging.message.send, mcp.tool.execute, etc.)
|
|
40
|
+
|
|
41
|
+
## `local-overrides/`
|
|
42
|
+
|
|
43
|
+
Local policy and passport templates that override or extend the submodule content (e.g. `system.command.execute.v1` when the policy is not yet in aport-policies).
|
|
44
|
+
|
|
45
|
+
## `tests/`
|
|
46
|
+
|
|
47
|
+
OAP v1 test suite: guardrail allow/deny, passport creation, suspend (passport status), four verification methods, API evaluator (when API is up). Run with `make test`.
|