@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,46 @@
|
|
|
1
|
+
# Tool → policy pack mapping
|
|
2
|
+
|
|
3
|
+
OpenClaw (or any caller) invokes the guardrail with a **tool name** and **context JSON**. The guardrail maps the tool name to a **policy pack** in `external/aport-policies/` and evaluates the request against that policy and the passport.
|
|
4
|
+
|
|
5
|
+
This mapping is implemented in `bin/aport-guardrail-api.sh` and `bin/aport-guardrail-bash.sh`. The table below is the single source of truth for documentation.
|
|
6
|
+
|
|
7
|
+
## Mapping table
|
|
8
|
+
|
|
9
|
+
| Tool name (pattern) | Policy pack ID | Policy location |
|
|
10
|
+
|---------------------|----------------|------------------|
|
|
11
|
+
| `git.create_pr`, `git.merge`, `git.push`, `git.*` | `code.repository.merge.v1` | `external/aport-policies/code.repository.merge.v1/` |
|
|
12
|
+
| `exec.run`, `exec.*`, `system.command.*`, `system.*` | `system.command.execute.v1` | `local-overrides` or API |
|
|
13
|
+
| `message.send`, `message.*`, `messaging.*` | `messaging.message.send.v1` | `external/aport-policies/messaging.message.send.v1/` |
|
|
14
|
+
| `mcp.tool.*`, `mcp.*` | `mcp.tool.execute.v1` | API / evaluator |
|
|
15
|
+
| `agent.session.*`, `session.create`, `session.*` | `agent.session.create.v1` | API / evaluator |
|
|
16
|
+
| `agent.tool.*`, `tool.register`, `tool.*` | `agent.tool.register.v1` | API / evaluator |
|
|
17
|
+
| `payment.refund`, `payment.*`, `finance.payment.refund` | `finance.payment.refund.v1` | `external/aport-policies/finance.payment.refund.v1/` |
|
|
18
|
+
| `payment.charge`, `finance.payment.charge` | `finance.payment.charge.v1` | `external/aport-policies/finance.payment.charge.v1/` |
|
|
19
|
+
| `database.write`, `database.*`, `data.export` | `data.export.create.v1` | `external/aport-policies/data.export.create.v1/` |
|
|
20
|
+
|
|
21
|
+
**Unknown tool:** In the **bash/API guardrail script**, an unknown tool name results in deny (exit 1). In the **OpenClaw plugin**, unmapped tools are **allowed** by default so custom skills and ClawHub tools work; set `allowUnmappedTools: false` in plugin config for strict (block unmapped).
|
|
22
|
+
|
|
23
|
+
## How OpenClaw uses it
|
|
24
|
+
|
|
25
|
+
1. OpenClaw (or your integration code) decides to run a tool, e.g. `system.command.execute` with `{"command":"npm install"}`.
|
|
26
|
+
2. Before executing, it calls the guardrail script with that tool name and context:
|
|
27
|
+
```bash
|
|
28
|
+
~/.openclaw/.skills/aport-guardrail.sh system.command.execute '{"command":"npm install"}'
|
|
29
|
+
```
|
|
30
|
+
3. The script maps `system.command.execute` → `system.command.execute.v1`, loads the passport and policy (or calls the API), and evaluates.
|
|
31
|
+
4. Exit 0 = allow, exit 1 = deny. Decision details are in `~/.openclaw/decision.json` (or your configured path).
|
|
32
|
+
|
|
33
|
+
## Adding or changing mappings
|
|
34
|
+
|
|
35
|
+
To add a new tool → policy mapping, edit the `case` block in:
|
|
36
|
+
|
|
37
|
+
- `bin/aport-guardrail-api.sh`
|
|
38
|
+
- `bin/aport-guardrail-bash.sh`
|
|
39
|
+
|
|
40
|
+
and add a new pattern and policy pack ID. The policy pack must exist under `external/aport-policies/<pack_id>/` (or in local-overrides / API).
|
|
41
|
+
|
|
42
|
+
## Reference
|
|
43
|
+
|
|
44
|
+
- OAP spec: `external/aport-spec/`
|
|
45
|
+
- Policy packs: `external/aport-policies/`
|
|
46
|
+
- AGENTS.md example: [AGENTS.md.example](AGENTS.md.example)
|
package/docs/UPGRADE.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Upgrade Guide
|
|
2
|
+
|
|
3
|
+
## Upgrading from 0.1.0 to 1.0.0
|
|
4
|
+
|
|
5
|
+
### Breaking Changes
|
|
6
|
+
None - 1.0.0 is the first production release.
|
|
7
|
+
|
|
8
|
+
### New Features
|
|
9
|
+
- OpenClaw plugin with `before_tool_call` enforcement
|
|
10
|
+
- API mode support (in addition to local mode)
|
|
11
|
+
- Enhanced exec handling with recursive guardrail detection
|
|
12
|
+
- Improved error messages with OAP codes
|
|
13
|
+
|
|
14
|
+
### Migration Steps
|
|
15
|
+
|
|
16
|
+
**If upgrading from 0.1.0:**
|
|
17
|
+
|
|
18
|
+
1. Update your installation:
|
|
19
|
+
```bash
|
|
20
|
+
git pull
|
|
21
|
+
git submodule update --init --recursive
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
2. Re-run setup to install plugin:
|
|
25
|
+
```bash
|
|
26
|
+
./bin/openclaw
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
3. Update OpenClaw config (if using plugin):
|
|
30
|
+
```yaml
|
|
31
|
+
plugins:
|
|
32
|
+
entries:
|
|
33
|
+
openclaw-aport:
|
|
34
|
+
enabled: true
|
|
35
|
+
config:
|
|
36
|
+
mode: local # or "api"
|
|
37
|
+
passportFile: ~/.openclaw/passport.json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
4. Verify passport has `allowed_commands`:
|
|
41
|
+
```bash
|
|
42
|
+
jq '.limits.system.command.execute.allowed_commands' ~/.openclaw/passport.json
|
|
43
|
+
```
|
|
44
|
+
If empty or missing, re-run passport wizard or add manually.
|
|
45
|
+
|
|
46
|
+
**No other changes required.**
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Verification methods: Local vs API
|
|
2
|
+
|
|
3
|
+
This doc compares how policy is evaluated in **local mode** (bash guardrail script) vs **API mode** (APort cloud or self-hosted agent-passport using the generic evaluator). It also summarizes the four ways you can run the guardrail (standalone bash, standalone API, plugin + local, plugin + API).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Summary: when to use which
|
|
8
|
+
|
|
9
|
+
| Method | Best for | Robustness | Network |
|
|
10
|
+
|--------|----------|------------|---------|
|
|
11
|
+
| **API (default)** | Production, full OAP parity, new policy rules without code changes | Full: JSON Schema, assurance, regions, taxonomy, MCP, evaluation_rules from policy JSON, signed decisions | Yes (api.aport.io or self-hosted) |
|
|
12
|
+
| **Local (bash)** | Privacy, offline, air-gapped, or no API key | Core checks only; same policy packs but hand-coded per policy; new rules need script updates | No |
|
|
13
|
+
|
|
14
|
+
**Recommendation:** Use **API mode** (default in `./bin/openclaw`) for full policy fidelity and future policy packs. Use **local mode** when you must avoid the network or run fully offline.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Four ways to run the guardrail
|
|
19
|
+
|
|
20
|
+
| # | Method | How | Typical use |
|
|
21
|
+
|---|--------|-----|-------------|
|
|
22
|
+
| 1 | **Standalone bash** | `OPENCLAW_PASSPORT_FILE=... ./bin/aport-guardrail-bash.sh <tool> '<context_json>'` | Scripts, CI, manual checks |
|
|
23
|
+
| 2 | **Standalone API** | `./bin/aport-guardrail-api.sh <tool> '<context_json>'` with `APORT_API_URL` | Same as above, but evaluation in cloud |
|
|
24
|
+
| 3 | **Plugin + local** | OpenClaw `before_tool_call` → plugin spawns `aport-guardrail-bash.sh` | OpenClaw with no API / offline |
|
|
25
|
+
| 4 | **Plugin + API** | OpenClaw `before_tool_call` → plugin calls APort API | OpenClaw with full OAP (default) |
|
|
26
|
+
|
|
27
|
+
All four produce OAP v1.0–shaped decisions (allow, reasons, policy_id, etc.). The **evaluation logic** differs between local (bash) and API (generic evaluator).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Local evaluator (bash) vs API generic evaluator
|
|
32
|
+
|
|
33
|
+
The **APort API** (and self-hosted agent-passport) uses a **generic evaluator** that loads policy JSON and runs a full OAP pipeline. The **local guardrail** in this repo (`bin/aport-guardrail-bash.sh`) implements a **subset** of that pipeline in bash + jq.
|
|
34
|
+
|
|
35
|
+
### What the API generic evaluator does (full OAP)
|
|
36
|
+
|
|
37
|
+
1. **Passport status** — suspended/revoked → deny
|
|
38
|
+
2. **Required context (JSON Schema)** — validates `required_context` from policy JSON against the request
|
|
39
|
+
3. **Capabilities** — passport must have required capabilities (e.g. `system.command.execute`, `messaging.send`)
|
|
40
|
+
4. **Assurance level** — `min_assurance` from policy (e.g. L2) vs passport assurance
|
|
41
|
+
5. **Limits** — uses `evaluation_rules` from policy JSON (expression + custom_validator); supports capability-scoped limits, DB-backed rate limits, idempotency
|
|
42
|
+
6. **Regions** — `requires_regions` from policy
|
|
43
|
+
7. **Taxonomy** — policy-defined taxonomy checks
|
|
44
|
+
8. **MCP** — MCP allowlist/validation when defined
|
|
45
|
+
9. **Custom evaluation rules** — runs each `evaluation_rules` entry (expression or custom_validator) from the policy pack
|
|
46
|
+
10. **Signed decisions** — Ed25519 signatures, optional chained audit
|
|
47
|
+
|
|
48
|
+
Reference: [agent-passport generic-evaluator](https://github.com/aporthq/agent-passport) (`functions/utils/policy/generic-evaluator.ts`).
|
|
49
|
+
|
|
50
|
+
### What the local (bash) evaluator does
|
|
51
|
+
|
|
52
|
+
1. **Passport status** — local verify checks passport status first; if `status` is not `active` (e.g. `suspended` or `revoked`) → deny with `oap.passport_suspended`. Passport is the source of truth (no separate kill-switch file).
|
|
53
|
+
2. **Passport load** — read passport JSON; invalid or missing → deny
|
|
54
|
+
3. **Passport status** — `status !== "active"` → deny
|
|
55
|
+
4. **Spec version** — must be `oap/1.0`
|
|
56
|
+
5. **Tool → policy mapping** — fixed `case` (e.g. `exec.*`/`system.*` → `system.command.execute.v1`, `messaging.*` → `messaging.message.send.v1`)
|
|
57
|
+
6. **Capabilities** — passport must list required capability (with alias e.g. `messaging.message.send` → `messaging.send`)
|
|
58
|
+
7. **Policy-specific limits (hand-coded):**
|
|
59
|
+
- **code.repository.merge** — PR size (`max_pr_size_kb`), `allowed_repos`, `allowed_base_branches`
|
|
60
|
+
- **system.command.execute** — `allowed_commands` (prefix or `*`), `blocked_patterns`
|
|
61
|
+
- **messaging.message.send** — `allowed_recipients` (optional)
|
|
62
|
+
8. **Decision output** — OAP-shaped decision (allow, reasons, policy_id, passport_digest, content_hash, chain)
|
|
63
|
+
9. **No** JSON Schema validation of context
|
|
64
|
+
10. **No** assurance, regions, taxonomy, MCP, or generic `evaluation_rules` from policy JSON
|
|
65
|
+
|
|
66
|
+
So: **local is robust enough for the core policies** (exec, messaging, repo merge) for allowlist/blocklist and the limits implemented in bash. It is **not** a full reimplementation of the generic evaluator. New policy packs or new rules in existing packs (e.g. `working_directory`, `environment_variables` in system.command.execute) require either API mode or updates to the bash script.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Feature comparison (local vs API)
|
|
71
|
+
|
|
72
|
+
| Feature | Local (bash) | API (generic evaluator) |
|
|
73
|
+
|---------|--------------|--------------------------|
|
|
74
|
+
| Passport status check | ✅ | ✅ |
|
|
75
|
+
| Kill switch | ✅ (file-based) | N/A (handled by registry/suspend) |
|
|
76
|
+
| Capability check | ✅ (with messaging alias) | ✅ |
|
|
77
|
+
| JSON Schema required_context | ❌ | ✅ |
|
|
78
|
+
| Assurance level | ❌ | ✅ |
|
|
79
|
+
| Regions | ❌ | ✅ |
|
|
80
|
+
| Taxonomy | ❌ | ✅ |
|
|
81
|
+
| MCP validation | ❌ | ✅ |
|
|
82
|
+
| Limits from policy JSON | Hand-coded subset only | ✅ Full (evaluation_rules, custom_validators) |
|
|
83
|
+
| system.command.execute | allowed_commands, blocked_patterns | + execution_time, working_directory, env (if in policy) |
|
|
84
|
+
| code.repository.merge | PR size, allowed_repos, allowed_base_branches | Same + path_allowlist, require_review if in policy |
|
|
85
|
+
| messaging.message.send | allowed_recipients | + rate limits (msgs_per_min/day), channel allowlist (if in policy) |
|
|
86
|
+
| New policy packs | Requires bash changes | Load from policy JSON |
|
|
87
|
+
| Signed decisions | Local-unsigned only | Ed25519 signed (cloud) |
|
|
88
|
+
| Rate limits / idempotency | ❌ | ✅ (when API uses DB) |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Conclusion
|
|
93
|
+
|
|
94
|
+
- **Local (bash):** Useful for privacy, offline, and the core use cases (exec allowlist/blocklist, messaging recipient, repo/PR limits). For full OAP parity and future policy packs, use **API mode**.
|
|
95
|
+
- **API (default):** Recommended for production and when you want the same behavior as [APort in Goose](https://raw.githubusercontent.com/aporthq/.github/refs/heads/main/profile/APORT_GOOSE_ARCHITECTURE.md) and the full generic evaluator (JSON Schema, assurance, regions, evaluation_rules, signed decisions).
|
|
96
|
+
|
|
97
|
+
The installer (`./bin/openclaw`) defaults to **API mode**; choose local only when you need to run without the network.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Assets for docs and README
|
|
2
|
+
|
|
3
|
+
- **Porter (mascot):** Use SVGs and the interactive playground from [APort Brand — Meet Porter](https://aport.io/brand-mascot-agent/). You can download the page or copy the mascot SVGs for use in docs or the main README.
|
|
4
|
+
- **Demo GIF:** Add a short GIF here (e.g. `porter-demo.gif` or `guardrail-demo.gif`) showing:
|
|
5
|
+
- Terminal: one ALLOW and one DENY from the guardrail, or
|
|
6
|
+
- Plugin config + passport snippet, or
|
|
7
|
+
- Porter verifying a command (from the brand page).
|
|
8
|
+
Then reference it in the root README, e.g. ``.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<svg width="120" height="120" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
2
|
+
<defs>
|
|
3
|
+
<filter id="softShadow" x="-50%" y="-50%" width="200%" height="200%">
|
|
4
|
+
<feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
|
|
5
|
+
<feOffset dx="0" dy="2" result="offsetblur"/>
|
|
6
|
+
<feComponentTransfer>
|
|
7
|
+
<feFuncA type="linear" slope="0.15"/>
|
|
8
|
+
</feComponentTransfer>
|
|
9
|
+
<feMerge>
|
|
10
|
+
<feMergeNode/>
|
|
11
|
+
<feMergeNode in="SourceGraphic"/>
|
|
12
|
+
</feMerge>
|
|
13
|
+
</filter>
|
|
14
|
+
<radialGradient id="innerGlow" cx="50%" cy="40%" r="60%">
|
|
15
|
+
<stop offset="0%" stop-color="white" stop-opacity="0.2"/>
|
|
16
|
+
<stop offset="100%" stop-color="white" stop-opacity="0"/>
|
|
17
|
+
</radialGradient>
|
|
18
|
+
</defs>
|
|
19
|
+
<circle cx="50" cy="50" r="48" fill="#0A84FF" opacity="0.05"/>
|
|
20
|
+
<rect x="30" y="35" width="40" height="40" rx="20" fill="#007AFF" filter="url(#softShadow)"/>
|
|
21
|
+
<rect x="30" y="35" width="40" height="40" rx="20" fill="url(#innerGlow)"/>
|
|
22
|
+
<rect x="33" y="38" width="34" height="34" rx="17" fill="#F5F5F7" opacity="0.12"/>
|
|
23
|
+
<line x1="38" y1="48" x2="54" y2="48" stroke="#0A84FF" stroke-width="1" opacity="0.3"/>
|
|
24
|
+
<line x1="38" y1="52" x2="62" y2="52" stroke="#0A84FF" stroke-width="1" opacity="0.3"/>
|
|
25
|
+
<line x1="38" y1="56" x2="58" y2="56" stroke="#0A84FF" stroke-width="1" opacity="0.3"/>
|
|
26
|
+
<g transform="translate(0, -2)">
|
|
27
|
+
<ellipse cx="50" cy="35" rx="22" ry="11" fill="#1D1D1F" opacity="0.9"/>
|
|
28
|
+
<ellipse cx="50" cy="37" rx="26" ry="6" fill="#1D1D1F" opacity="0.7"/>
|
|
29
|
+
</g>
|
|
30
|
+
<ellipse cx="50" cy="30" rx="6" ry="7" fill="#FF9500" opacity="0.9"/>
|
|
31
|
+
<text x="50" y="33" text-anchor="middle" font-size="5" fill="white" font-weight="bold">AP</text>
|
|
32
|
+
<ellipse cx="42" cy="48" rx="4" ry="4" fill="white" opacity="0.95"/>
|
|
33
|
+
<circle cx="42" cy="48" r="2.5" fill="#1D1D1F"/>
|
|
34
|
+
<ellipse cx="58" cy="48" rx="4" ry="4" fill="white" opacity="0.95"/>
|
|
35
|
+
<circle cx="58" cy="48" r="2.5" fill="#1D1D1F"/>
|
|
36
|
+
<circle cx="40.5" cy="46.5" r="0.8" fill="white" opacity="0.9"/>
|
|
37
|
+
<circle cx="56.5" cy="46.5" r="0.8" fill="white" opacity="0.9"/>
|
|
38
|
+
<ellipse cx="35" cy="56" rx="3.5" ry="2.5" fill="#FF9AA2" opacity="0.25"/>
|
|
39
|
+
<ellipse cx="65" cy="56" rx="3.5" ry="2.5" fill="#FF9AA2" opacity="0.25"/>
|
|
40
|
+
<path d="M 42 58 Q 50 63 58 58" fill="none" stroke="#1D1D1F" stroke-width="2" stroke-linecap="round" opacity="0.9"/>
|
|
41
|
+
<ellipse cx="50" cy="66" rx="8" ry="6" fill="#FF9500" opacity="0.9"/>
|
|
42
|
+
<text x="50" y="68" text-anchor="middle" font-size="3.5" fill="white" font-weight="bold">APORT</text>
|
|
43
|
+
<ellipse cx="26" cy="55" rx="6" ry="12" fill="#007AFF" opacity="0.95"/>
|
|
44
|
+
<ellipse cx="74" cy="55" rx="6" ry="12" fill="#007AFF" opacity="0.95"/>
|
|
45
|
+
<ellipse cx="42" cy="78" rx="7" ry="10" fill="#007AFF" opacity="0.95"/>
|
|
46
|
+
<ellipse cx="58" cy="78" rx="7" ry="10" fill="#007AFF" opacity="0.95"/>
|
|
47
|
+
<ellipse cx="42" cy="77" rx="5" ry="2" fill="#1D1D1F" opacity="0.3"/>
|
|
48
|
+
<ellipse cx="58" cy="77" rx="5" ry="2" fill="#1D1D1F" opacity="0.3"/>
|
|
49
|
+
<g>
|
|
50
|
+
<circle cx="50" cy="55" r="16" fill="#34C759" opacity="0.15"/>
|
|
51
|
+
<circle cx="50" cy="55" r="13" fill="none" stroke="#34C759" stroke-width="2.5" opacity="0.9"/>
|
|
52
|
+
<path d="M 42 55 L 48 61 L 60 48" fill="none" stroke="#34C759" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" opacity="0.9"/>
|
|
53
|
+
</g>
|
|
54
|
+
</svg>
|