{"_id":"@bastion-ai/bastion","name":"@bastion-ai/bastion","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@bastion-ai/bastion","version":"0.1.0","description":"OpenClaw plugin for Bastion — adds a Bastion-backed HTTP tool and blocks direct bypasses for protected URLs","license":"MIT","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","homepage":"https://github.com/Matthieuhakim/Bastion#readme","repository":{"type":"git","url":"git+https://github.com/Matthieuhakim/Bastion.git","directory":"packages/openclaw-plugin"},"bugs":{"url":"https://github.com/Matthieuhakim/Bastion/issues"},"keywords":["ai","agents","security","proxy","audit","openclaw","plugin","typescript"],"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"openclaw":{"extensions":["./dist/index.js"],"install":{"npmSpec":"@bastion-ai/bastion","defaultChoice":"npm"}},"sideEffects":false,"publishConfig":{"access":"public"},"engines":{"node":">=22.0.0"},"peerDependencies":{"openclaw":">=2026.2.12"},"scripts":{"clean":"node --eval \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","build":"npm run clean && tsc","ci:verify-tarball":"bash ./scripts/ci-verify-tarball.sh","dev":"tsc --watch","prepack":"npm run build","test":"vitest run","test:e2e":"bash ./scripts/ci-openclaw-e2e.sh","test:integration":"bash ./scripts/ci-openclaw-install-smoke.sh && bash ./scripts/ci-openclaw-config-validate.sh","test:watch":"vitest"},"dependencies":{"@bastion-ai/sdk":"^0.1.0"},"devDependencies":{"typescript":"^5.7.0","vitest":"^3.0.0"},"_id":"@bastion-ai/bastion@0.1.0","gitHead":"08e30b7151025277bf9820e75e1f36697fbd4094","_nodeVersion":"22.22.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-mlqcdvEr1U1sMbsqLf4cYFaIQO4cLDArzejCGSJZd4y6hQMZYZ4TdBIZLxRXUlEDyeKaIA/5r05rZS58fHaW9g==","shasum":"13427c82948db75327ab56e39d6fdf017febc1b6","tarball":"https://registry.npmjs.org/@bastion-ai/bastion/-/bastion-0.1.0.tgz","fileCount":35,"unpackedSize":54453,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHoGU5vqgsL1CAJGZd4bGIW06xYNZxrBdCD8zPeCjwjhAiAIKTfWOR0wU5qzWMS+rhRl+UUU3lg/OxpMfcn6sFAbmA=="}]},"_npmUser":{"name":"matthieu-hakim","email":"commandobob@outlook.com"},"directories":{},"maintainers":[{"name":"matthieu-hakim","email":"commandobob@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bastion_0.1.0_1773765008244_0.6338823609828736"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-17T16:30:08.181Z","0.1.0":"2026-03-17T16:30:08.389Z","modified":"2026-03-17T16:30:08.558Z"},"maintainers":[{"name":"matthieu-hakim","email":"commandobob@outlook.com"}],"description":"OpenClaw plugin for Bastion — adds a Bastion-backed HTTP tool and blocks direct bypasses for protected URLs","homepage":"https://github.com/Matthieuhakim/Bastion#readme","keywords":["ai","agents","security","proxy","audit","openclaw","plugin","typescript"],"repository":{"type":"git","url":"git+https://github.com/Matthieuhakim/Bastion.git","directory":"packages/openclaw-plugin"},"bugs":{"url":"https://github.com/Matthieuhakim/Bastion/issues"},"license":"MIT","readme":"# @bastion-ai/bastion\n\nOpenClaw plugin for [Bastion](https://github.com/Matthieuhakim/Bastion).\n\nIt ships a `bastion_fetch` tool that sends outbound HTTP requests through Bastion, so Bastion can enforce policy, inject credentials, handle HITL approval, and append audit records. It can also block direct calls to protected URLs on built-in tools like `web_fetch`.\n\n## Compatibility\n\n- OpenClaw `2026.2.12+`\n- Node.js `22+`\n- A running Bastion server\n\nThis plugin targets the current released OpenClaw runtime by registering an explicit tool. It does not rely on unreleased transparent result-injection hooks.\n\n## Installation\n\n### From npm\n\n```bash\nopenclaw plugins install @bastion-ai/bastion\n```\n\nThe installed plugin ID is `bastion`, so configure it under `plugins.entries[\"bastion\"]`.\nThe package is install-first: it loads in an idle state until you add `serverUrl`, `agentSecret`, and at least one rule.\n\n### Local development / pre-publish\n\nFrom the Bastion repo root:\n\n```bash\nnpm run build --workspace=packages/openclaw-plugin\nopenclaw plugins install -l ./packages/openclaw-plugin\n```\n\nOr install a packed tarball:\n\n```bash\nnpm pack --workspace=packages/openclaw-plugin\nopenclaw plugins install ./bastion-ai-bastion-0.1.0.tgz\n```\n\n## Bastion Setup\n\n1. Create an agent and save the returned `agentSecret` (`bst_...`):\n\n```bash\ncurl -X POST http://localhost:3000/v1/agents \\\n  -H \"Authorization: Bearer $PROJECT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"my-openclaw-agent\"}'\n```\n\n2. Store the upstream credential Bastion should inject:\n\n```bash\ncurl -X POST http://localhost:3000/v1/credentials \\\n  -H \"Authorization: Bearer $PROJECT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"Stripe API Key\", \"type\": \"API_KEY\", \"value\": \"sk_live_...\", \"agentId\": \"<agentId>\"}'\n```\n\n3. Create a policy that allows the action:\n\n```bash\ncurl -X POST http://localhost:3000/v1/policies \\\n  -H \"Authorization: Bearer $PROJECT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"agentId\": \"<agentId>\", \"credentialId\": \"<credentialId>\", \"allowedActions\": [\"stripe.*\"]}'\n```\n\n## OpenClaw Configuration\n\nAdd this to `openclaw.json`:\n\n```json\n{\n  \"plugins\": {\n    \"allow\": [\"bastion\"],\n    \"entries\": {\n      \"bastion\": {\n        \"enabled\": true,\n        \"config\": {\n          \"serverUrl\": \"http://localhost:3000\",\n          \"agentSecret\": { \"$env\": \"BASTION_AGENT_SECRET\" },\n          \"rules\": [\n            {\n              \"tool\": \"web_fetch\",\n              \"urlPattern\": \"https://api.stripe.com/**\",\n              \"credentialId\": \"cred_abc123\",\n              \"action\": \"stripe.charges\"\n            },\n            {\n              \"tool\": \"web_fetch\",\n              \"urlPattern\": \"https://api.github.com/**\",\n              \"credentialId\": \"cred_def456\",\n              \"action\": \"github.api\",\n              \"injection\": { \"location\": \"header\", \"key\": \"Authorization\" }\n            }\n          ],\n          \"timeout\": 30000\n        }\n      }\n    }\n  }\n}\n```\n\nSet your agent secret:\n\n```bash\nexport BASTION_AGENT_SECRET=bst_...\n```\n\n## How Users Implement It\n\nAgents should call `bastion_fetch` for protected outbound API requests.\n\nExample tool call:\n\n```json\n{\n  \"tool\": \"bastion_fetch\",\n  \"params\": {\n    \"url\": \"https://api.stripe.com/v1/charges\",\n    \"method\": \"POST\",\n    \"body\": {\n      \"amount\": 5000,\n      \"currency\": \"usd\"\n    }\n  }\n}\n```\n\nThe plugin matches the request URL against the configured rules, resolves the Bastion credential/action pair, calls Bastion's `/v1/proxy/execute`, and returns a structured tool result containing:\n\n- `status`\n- `headers`\n- `body`\n- `url`\n- `_bastion` metadata (`credentialId`, `action`, `policyDecision`, `durationMs`, optional `hitlRequestId`)\n\nIf a rule includes `tool`, the plugin also blocks direct calls to that tool for matching URLs. For example, `tool: \"web_fetch\"` prevents the model from bypassing Bastion for those domains.\n\n## Prompting Guidance\n\nIn your agent instructions, tell the model:\n\n```text\nUse `bastion_fetch` for requests to protected APIs such as Stripe or GitHub. Do not use `web_fetch` for those domains.\n```\n\nThat keeps the workflow deterministic and lets the plugin enforce policy cleanly.\n\n## `agentSecret` formats\n\n| Format | Example |\n|--------|---------|\n| Plain string | `\"bst_abc123...\"` |\n| Environment variable | `{ \"$env\": \"BASTION_AGENT_SECRET\" }` |\n| File | `{ \"$file\": \"/run/secrets/bastion_secret\" }` |\n\n## Rule Options\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `tool` | No | Built-in tool to block for matching URLs, e.g. `web_fetch` |\n| `urlPattern` | Yes | Glob pattern. `*` matches one path segment, `**` matches any depth |\n| `credentialId` | Yes | Bastion credential ID |\n| `action` | Yes | Action name for Bastion policy evaluation |\n| `injection` | No | Override credential injection (`header` / `query` / `body`) |\n| `params` | No | Dot-paths to extract Bastion policy params, e.g. `{ \"amount\": \"body.amount\" }` |\n\nRules are evaluated in order. Put more specific patterns before broader wildcards.\n\n## Troubleshooting\n\n**Plugin logs \"server is unreachable\"**  \nBastion is not running or not reachable from OpenClaw. Start it with `docker compose up -d && npm run dev`.\n\n**`openclaw plugins install` succeeds but the plugin looks idle**  \nThat is expected until you provide `serverUrl`, `agentSecret`, and `rules`. The plugin intentionally installs cleanly before configuration so npm installs do not create invalid OpenClaw state.\n\n**`bastion_fetch` returns \"Blocked by Bastion policy\"**  \nThe agent's policy denied the action. Check Bastion policies or audit entries.\n\n**`bastion_fetch` hangs for minutes**  \nThe request hit a HITL rule and Bastion is waiting for approval. Review pending requests via `GET /v1/hitl/pending`.\n\n**Direct `web_fetch` calls are blocked**  \nThat is expected when a matching rule defines `tool: \"web_fetch\"`. Use `bastion_fetch` instead.\n\n## Release Gates\n\nBefore publishing a new version, make sure all of these pass:\n\n- `npm run test --workspace=packages/openclaw-plugin`\n- `npm run test:integration --workspace=packages/openclaw-plugin`\n- `npm run test:e2e --workspace=packages/openclaw-plugin`\n- `npm run ci:verify-tarball --workspace=packages/openclaw-plugin`\n- GitHub Actions workflow `.github/workflows/openclaw-plugin-ci.yml`\n\nThat workflow enforces three release-confidence stages:\n\n- `Plugin Unit + Package`: build, unit tests, lint, and tarball verification\n- `OpenClaw Compat`: install/config validation against OpenClaw `2026.2.12` and `2026.3.13`\n- `Plugin E2E (Dockerized)`: real Bastion API + OpenClaw gateway exercise of `bastion_fetch`, audit logging, and protected-tool blocking\n","readmeFilename":"README.md","_rev":"1-fb2124e34cb1a419841ff2946bba99e8"}