@sibyllinesoft/smith-installer 0.1.1

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/dist/lib.js ADDED
@@ -0,0 +1,265 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from "fs";
2
+ import { resolve, join } from "path";
3
+ export function parseArgs(argv) {
4
+ const args = {
5
+ nonInteractive: false,
6
+ provider: "anthropic",
7
+ model: "claude-sonnet-4-20250514",
8
+ thinkingLevel: "medium",
9
+ force: false,
10
+ help: false,
11
+ };
12
+ for (let i = 2; i < argv.length; i++) {
13
+ switch (argv[i]) {
14
+ case "--non-interactive":
15
+ args.nonInteractive = true;
16
+ break;
17
+ case "--provider":
18
+ args.provider = argv[++i];
19
+ break;
20
+ case "--model":
21
+ args.model = argv[++i];
22
+ break;
23
+ case "--thinking":
24
+ args.thinkingLevel = argv[++i];
25
+ break;
26
+ case "--step":
27
+ args.step = argv[++i];
28
+ break;
29
+ case "--force":
30
+ args.force = true;
31
+ break;
32
+ case "--repo":
33
+ args.repo = argv[++i];
34
+ break;
35
+ case "--help":
36
+ case "-h":
37
+ args.help = true;
38
+ break;
39
+ default:
40
+ throw new Error(`Unknown option: ${argv[i]} (try --help)`);
41
+ }
42
+ }
43
+ return args;
44
+ }
45
+ export function findSmithRoot(startDir) {
46
+ let dir = resolve(startDir);
47
+ const root = resolve("/");
48
+ while (dir !== root) {
49
+ const looksLikeRepoRoot = existsSync(join(dir, "Cargo.toml")) &&
50
+ existsSync(join(dir, "docker-compose.yaml")) &&
51
+ existsSync(join(dir, "justfile")) &&
52
+ existsSync(join(dir, "installer", "package.json"));
53
+ if (looksLikeRepoRoot) {
54
+ return dir;
55
+ }
56
+ dir = resolve(dir, "..");
57
+ }
58
+ return null;
59
+ }
60
+ export function loadSkills(skillsDir) {
61
+ const skills = [];
62
+ let entries;
63
+ try {
64
+ entries = readdirSync(skillsDir);
65
+ }
66
+ catch {
67
+ return skills;
68
+ }
69
+ for (const entry of entries) {
70
+ const skillDir = join(skillsDir, entry);
71
+ const skillFile = join(skillDir, "SKILL.md");
72
+ try {
73
+ if (!statSync(skillDir).isDirectory())
74
+ continue;
75
+ const content = readFileSync(skillFile, "utf8");
76
+ // Extract description from frontmatter
77
+ const match = content.match(/^---\s*\ndescription:\s*(.+)\n---/);
78
+ const description = match?.[1] ?? entry;
79
+ skills.push({ name: entry, description, content });
80
+ }
81
+ catch {
82
+ // Skip skills without SKILL.md
83
+ }
84
+ }
85
+ return skills;
86
+ }
87
+ export function buildSystemPrompt(opts) {
88
+ let prompt = "You are the Smith Core installer and configuration agent.\n\n";
89
+ prompt += `smith-core repo root: ${opts.smithRoot}\n`;
90
+ if (process.platform === "darwin") {
91
+ prompt +=
92
+ "\nThis host is macOS. Ensure Gondolin-backed persistent VM sessions are enabled by setting:\n" +
93
+ "- SMITH_EXECUTOR_VM_POOL_ENABLED=true\n" +
94
+ "- SMITH_EXECUTOR_VM_METHOD=gondolin\n" +
95
+ "- SMITH_EXECUTOR_GONDOLIN_COMMAND=gondolin\n" +
96
+ "- SMITH_EXECUTOR_GONDOLIN_ARGS=exec,--\n";
97
+ }
98
+ if (opts.step) {
99
+ prompt += `\nThe user wants to run installer step '${opts.step}' only.\n`;
100
+ }
101
+ const configSteps = ["configure-policy", "policy"];
102
+ if (opts.step && configSteps.includes(opts.step.toLowerCase())) {
103
+ prompt += "You are in configuration mode (not bootstrapping). " +
104
+ "Focus on inspecting and configuring the policy system. " +
105
+ "Do not run build or infrastructure setup commands.\n";
106
+ }
107
+ if (opts.force) {
108
+ prompt += "--force is set — recreate infrastructure before bootstrapping.\n";
109
+ }
110
+ if (opts.securityWarnings && opts.securityWarnings.length > 0) {
111
+ prompt +=
112
+ "\nLocal security posture warnings were detected. These are non-blocking, " +
113
+ "but you must present them clearly before continuing:\n";
114
+ for (const warning of opts.securityWarnings) {
115
+ prompt += `- ${warning}\n`;
116
+ }
117
+ prompt +=
118
+ "Explicitly warn when deployment is not on a private network and recommend " +
119
+ "VPN/tunnel controls (for example Cloudflare Tunnel or Tailscale).\n";
120
+ }
121
+ return prompt;
122
+ }
123
+ function parseEnvFile(path) {
124
+ const vars = {};
125
+ const content = readFileSync(path, "utf8");
126
+ for (const rawLine of content.split("\n")) {
127
+ const line = rawLine.trim();
128
+ if (!line || line.startsWith("#"))
129
+ continue;
130
+ const eq = line.indexOf("=");
131
+ if (eq <= 0)
132
+ continue;
133
+ const key = line.slice(0, eq).trim();
134
+ let value = line.slice(eq + 1).trim();
135
+ if ((value.startsWith('"') && value.endsWith('"')) ||
136
+ (value.startsWith("'") && value.endsWith("'"))) {
137
+ value = value.slice(1, -1);
138
+ }
139
+ vars[key] = value;
140
+ }
141
+ return vars;
142
+ }
143
+ function hasNonEmpty(vars, keys) {
144
+ return keys.some((key) => (vars[key] ?? "").trim().length > 0);
145
+ }
146
+ function looksLikeWeakSecret(value, weakValues) {
147
+ const normalized = value.trim();
148
+ return normalized.length === 0 || weakValues.includes(normalized);
149
+ }
150
+ function isLikelyLoopbackListen(value) {
151
+ const v = value.trim().toLowerCase();
152
+ return (v.includes("127.0.0.1") ||
153
+ v.includes("localhost") ||
154
+ v.includes("[::1]") ||
155
+ v === "::1" ||
156
+ v.startsWith("::1:"));
157
+ }
158
+ export function evaluateInstallerSecurity(smithRoot) {
159
+ const envPath = join(smithRoot, ".env");
160
+ const envExamplePath = join(smithRoot, ".env.example");
161
+ const sourceFile = existsSync(envPath)
162
+ ? envPath
163
+ : existsSync(envExamplePath)
164
+ ? envExamplePath
165
+ : null;
166
+ if (!sourceFile) {
167
+ return {
168
+ sourceFile: null,
169
+ warnings: [
170
+ {
171
+ id: "missing-env",
172
+ message: "No .env or .env.example was found to evaluate security posture.",
173
+ recommendation: "Create .env from .env.example and review secrets plus network exposure settings.",
174
+ },
175
+ ],
176
+ };
177
+ }
178
+ const vars = parseEnvFile(sourceFile);
179
+ const warnings = [];
180
+ const weakSecrets = [
181
+ [
182
+ "POSTGRES_PASSWORD",
183
+ ["smith-dev", "postgres", "password", "changeme"],
184
+ "Set POSTGRES_PASSWORD to a unique, high-entropy value.",
185
+ ],
186
+ [
187
+ "CLICKHOUSE_PASSWORD",
188
+ ["observability-dev", "clickhouse", "password", "changeme"],
189
+ "Set CLICKHOUSE_PASSWORD to a unique, high-entropy value.",
190
+ ],
191
+ [
192
+ "GRAFANA_ADMIN_PASSWORD",
193
+ ["admin", "grafana", "password", "changeme"],
194
+ "Set GRAFANA_ADMIN_PASSWORD to a unique, high-entropy value.",
195
+ ],
196
+ ];
197
+ for (const [key, weakValues, recommendation] of weakSecrets) {
198
+ const value = (vars[key] ?? "").trim();
199
+ if (looksLikeWeakSecret(value, weakValues)) {
200
+ warnings.push({
201
+ id: `weak-${key.toLowerCase()}`,
202
+ message: `${key} is empty or set to a known weak default.`,
203
+ recommendation,
204
+ });
205
+ }
206
+ }
207
+ const mcpToken = (vars.MCP_INDEX_API_TOKEN ?? "").trim();
208
+ if (mcpToken.length < 24) {
209
+ warnings.push({
210
+ id: "weak-mcp-index-token",
211
+ message: "MCP_INDEX_API_TOKEN is missing or too short; MCP index APIs may be unauthenticated or weakly protected.",
212
+ recommendation: "Set MCP_INDEX_API_TOKEN to a long random secret (at least 24 characters).",
213
+ });
214
+ }
215
+ const capabilityDigest = (vars.AGENTD_CAPABILITY_DIGEST ?? "").trim();
216
+ if (!/^[a-fA-F0-9]{64}$/.test(capabilityDigest)) {
217
+ warnings.push({
218
+ id: "invalid-capability-digest",
219
+ message: "AGENTD_CAPABILITY_DIGEST is missing or not a valid 64-character hex digest.",
220
+ recommendation: "Set AGENTD_CAPABILITY_DIGEST to the intended capability bundle digest before production use.",
221
+ });
222
+ }
223
+ else if (/^0{64}$/.test(capabilityDigest)) {
224
+ warnings.push({
225
+ id: "zero-capability-digest",
226
+ message: "AGENTD_CAPABILITY_DIGEST is all zeros and will be rejected by secure defaults.",
227
+ recommendation: "Set AGENTD_CAPABILITY_DIGEST to a real digest, or only allow zero in local development overrides.",
228
+ });
229
+ }
230
+ const cloudflareKeys = [
231
+ "CLOUDFLARED_TUNNEL_TOKEN",
232
+ "CLOUDFLARE_TUNNEL_TOKEN",
233
+ "CLOUDFLARE_TUNNEL_ID",
234
+ "CLOUDFLARE_TUNNEL_HOSTNAME",
235
+ "CLOUDFLARE_TUNNEL_E2E_URL",
236
+ "CF_TUNNEL_TOKEN",
237
+ "TUNNEL_TOKEN",
238
+ ];
239
+ const tailscaleKeys = [
240
+ "TAILSCALE_AUTHKEY",
241
+ "TS_AUTHKEY",
242
+ "TAILSCALE_OAUTH_CLIENT_ID",
243
+ "TAILSCALE_HOSTNAME",
244
+ "TAILSCALE_TUNNEL_E2E_URL",
245
+ ];
246
+ const hasCloudflare = hasNonEmpty(vars, cloudflareKeys);
247
+ const hasTailscale = hasNonEmpty(vars, tailscaleKeys);
248
+ if (!hasCloudflare && !hasTailscale) {
249
+ warnings.push({
250
+ id: "missing-private-network-indicator",
251
+ message: "No Cloudflare Tunnel or Tailscale configuration indicators were found.",
252
+ recommendation: "Use a private network path (VPN/tunnel), and avoid exposing management endpoints directly to public networks.",
253
+ });
254
+ }
255
+ const grpcListen = (vars.AGENTD_GRPC_LISTEN ?? "").trim();
256
+ if (grpcListen && !isLikelyLoopbackListen(grpcListen)) {
257
+ warnings.push({
258
+ id: "agentd-grpc-non-loopback",
259
+ message: `AGENTD_GRPC_LISTEN is set to a non-loopback address (${grpcListen}).`,
260
+ recommendation: "Keep AGENTD_GRPC_LISTEN on loopback or enforce network controls before exposing it beyond trusted private networks.",
261
+ });
262
+ }
263
+ return { sourceFile, warnings };
264
+ }
265
+ //# sourceMappingURL=lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@sibyllinesoft/smith-installer",
3
+ "version": "0.1.1",
4
+ "description": "AI-guided Smith platform installer powered by pi-agent",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/sibyllinesoft/smith-core.git",
9
+ "directory": "installer"
10
+ },
11
+ "homepage": "https://smithcore.dev",
12
+ "bugs": {
13
+ "url": "https://github.com/sibyllinesoft/smith-core/issues"
14
+ },
15
+ "type": "module",
16
+ "bin": {
17
+ "smith-install": "./dist/cli.js"
18
+ },
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "import": "./dist/index.js",
24
+ "types": "./dist/index.d.ts"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "agents.md",
30
+ "skills"
31
+ ],
32
+ "scripts": {
33
+ "build": "rm -rf dist && tsc",
34
+ "dev": "tsc --watch",
35
+ "typecheck": "tsc --noEmit",
36
+ "test": "vitest run",
37
+ "test:watch": "vitest"
38
+ },
39
+ "engines": {
40
+ "node": ">=22"
41
+ },
42
+ "dependencies": {
43
+ "@mariozechner/pi-coding-agent": "^0.52.0",
44
+ "@mariozechner/pi-ai": "^0.52.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^20.0.0",
48
+ "typescript": "^5.4.0",
49
+ "vitest": "^2.0.0"
50
+ }
51
+ }
@@ -0,0 +1,49 @@
1
+ ---
2
+ description: Build Node workspaces required by installer and bridge services
3
+ ---
4
+ # Build Client
5
+
6
+ Run:
7
+
8
+ ```bash
9
+ npm install
10
+ npm run build --workspaces --if-present
11
+ ```
12
+
13
+ ## What It Does
14
+
15
+ This skill builds TypeScript/Node workspace packages used by Smith Core.
16
+
17
+ 1. Installs workspace dependencies.
18
+ 2. Builds workspaces that expose a `build` script.
19
+ 3. Verifies installer and bridge artifacts compile.
20
+ 4. Ensures runtime JS entrypoints exist before launch.
21
+
22
+ ## Prerequisites
23
+
24
+ - Node.js 22+.
25
+ - npm available.
26
+ - Internet access for package installation.
27
+
28
+ ## Expected Output
29
+
30
+ - `npm install` completes without fatal errors.
31
+ - Build runs for `@smith/pi-bridge` and `@sibyllinesoft/smith-installer`.
32
+
33
+ ## Reading Results
34
+
35
+ - TypeScript compile failures indicate code/config drift.
36
+ - Missing workspace build output blocks installer CLI execution.
37
+
38
+ ## Common Failures
39
+
40
+ | Symptom | Cause | Fix |
41
+ |---------|-------|-----|
42
+ | npm install fails | Network/auth/registry issues | Fix npm connectivity and retry |
43
+ | TypeScript errors in build | Source mismatch | Fix TS errors before bootstrap |
44
+ | Wrong Node version | Node < 22 | Upgrade Node runtime |
45
+ | Workspace not built | Missing `build` script | Add or correct workspace script |
46
+
47
+ ## Notes
48
+
49
+ Use this before running installer commands that depend on `dist/` outputs.
@@ -0,0 +1,48 @@
1
+ ---
2
+ description: Choose deployment profile for Smith Core installation
3
+ ---
4
+ # Choose Deployment
5
+
6
+ Run:
7
+
8
+ ```bash
9
+ export SMITH_DEPLOYMENT_MODE=local
10
+ ```
11
+
12
+ ## What It Does
13
+
14
+ This skill sets deployment intent for the installer session.
15
+
16
+ 1. Selects local-first deployment for open-source Smith Core.
17
+ 2. Keeps infrastructure on local Docker networking.
18
+ 3. Avoids assumptions about external managed tunnel services.
19
+ 4. Ensures follow-up commands target local endpoints.
20
+
21
+ ## Prerequisites
22
+
23
+ - User decision on local vs externally exposed deployment.
24
+
25
+ ## Expected Output
26
+
27
+ Environment reflects local mode:
28
+
29
+ ```text
30
+ SMITH_DEPLOYMENT_MODE=local
31
+ ```
32
+
33
+ ## Reading Results
34
+
35
+ - `local` means services run via `docker compose` on this machine.
36
+ - Any external ingress should be configured separately after bootstrap.
37
+
38
+ ## Common Failures
39
+
40
+ | Symptom | Cause | Fix |
41
+ |---------|-------|-----|
42
+ | Variable not visible in later commands | Exported in another shell | Export in the active shell/session |
43
+ | Confusion about cloud mode | Legacy docs mention tunnels | Use local mode for core OSS bootstrap |
44
+ | External access needed | Out-of-scope for default installer | Configure reverse proxy separately |
45
+
46
+ ## Notes
47
+
48
+ Current installer implementation validates and bootstraps local development flows.
@@ -0,0 +1,74 @@
1
+ ---
2
+ description: Configure environment and path defaults used by agentd and bridge components
3
+ ---
4
+ # Configure Agentd
5
+
6
+ Run:
7
+
8
+ ```bash
9
+ cp -n .env.example .env || true
10
+
11
+ if [ "$(uname -s)" = "Darwin" ]; then
12
+ command -v gondolin >/dev/null
13
+ grep -q '^SMITH_EXECUTOR_VM_POOL_ENABLED=' .env || echo 'SMITH_EXECUTOR_VM_POOL_ENABLED=true' >> .env
14
+ grep -q '^SMITH_EXECUTOR_VM_METHOD=' .env || echo 'SMITH_EXECUTOR_VM_METHOD=gondolin' >> .env
15
+ grep -q '^SMITH_EXECUTOR_GONDOLIN_COMMAND=' .env || echo 'SMITH_EXECUTOR_GONDOLIN_COMMAND=gondolin' >> .env
16
+ grep -q '^SMITH_EXECUTOR_GONDOLIN_ARGS=' .env || echo 'SMITH_EXECUTOR_GONDOLIN_ARGS=exec,--' >> .env
17
+ fi
18
+ ```
19
+
20
+ ## What It Does
21
+
22
+ This skill establishes baseline environment configuration for local runs.
23
+
24
+ 1. Creates `.env` from `.env.example` when missing.
25
+ 2. Ensures key URLs and credentials are available for local services.
26
+ 3. Makes bridge and stack configuration explicit and reproducible.
27
+ 4. Avoids hidden machine-specific defaults.
28
+ 5. On macOS, enables Gondolin-backed persistent VM sessions by default.
29
+
30
+ ## Prerequisites
31
+
32
+ - Repository root writable.
33
+ - `.env.example` present.
34
+
35
+ ## Expected Output
36
+
37
+ - `.env` exists at repository root.
38
+ - Variables for NATS/Postgres/Grafana/stack endpoints are present.
39
+ - On macOS, Gondolin VM defaults are present:
40
+ - `SMITH_EXECUTOR_VM_POOL_ENABLED=true`
41
+ - `SMITH_EXECUTOR_VM_METHOD=gondolin`
42
+ - `SMITH_EXECUTOR_GONDOLIN_COMMAND=gondolin`
43
+ - `SMITH_EXECUTOR_GONDOLIN_ARGS=exec,--`
44
+
45
+ ## Reading Results
46
+
47
+ Review and customize at minimum:
48
+
49
+ - `POSTGRES_PASSWORD`
50
+ - `GRAFANA_ADMIN_PASSWORD`
51
+ - `MCP_INDEX_API_TOKEN`
52
+ - `AGENTD_CONFIG`
53
+ - `SMITH_NATS_URL`
54
+ - `SMITH_DATABASE_URL`
55
+ - `AGENTD_URL`
56
+ - `SMITH_EXECUTOR_VM_POOL_ENABLED` (set to `true` on macOS)
57
+ - `SMITH_EXECUTOR_VM_METHOD` (set to `gondolin` on macOS)
58
+
59
+ If this system is not isolated to a private network, set up a private access path
60
+ (for example Cloudflare Tunnel or Tailscale) before exposing services.
61
+
62
+ ## Common Failures
63
+
64
+ | Symptom | Cause | Fix |
65
+ |---------|-------|-----|
66
+ | `.env` not created | Permission/path issue | Create file manually and retry |
67
+ | Service auth failures | Password mismatch with compose | Align `.env` values and restart stack |
68
+ | Bridge cannot reach agentd | Bad `AGENTD_URL` | Set reachable URL and rerun |
69
+ | Unexpected defaults used | Variable unset | Populate `.env` explicitly |
70
+ | `gondolin` not found on macOS | Gondolin missing from PATH | Install Gondolin and retry |
71
+
72
+ ## Notes
73
+
74
+ There is no generated `agentd.toml` workflow in the current installer path.
@@ -0,0 +1,134 @@
1
+ ---
2
+ description: Inspect and configure OPA security policies for agentd intent evaluation and gateway authorization
3
+ ---
4
+ # Configure Policy
5
+
6
+ Run these read-only inspection commands to understand the current policy state:
7
+
8
+ ```bash
9
+ # Query opa_policies table for active policy records
10
+ docker compose exec -T postgres psql -U smith -d smith -c "SELECT id, name, updated_at FROM opa_policies ORDER BY updated_at DESC;"
11
+
12
+ # View tool-access policy data (most commonly edited artifact)
13
+ docker compose exec -T postgres psql -U smith -d smith -c "SELECT data FROM opa_policies WHERE name = 'tool_access';"
14
+
15
+ # Check OPA server health (Docker-internal only, port 8181 is not published to host)
16
+ docker compose exec -T opa-management wget -qO- http://localhost:8181/health
17
+
18
+ # List loaded OPA policies
19
+ docker compose exec -T opa-management wget -qO- http://localhost:8181/v1/policies
20
+
21
+ # Show executor.policy section from agentd config
22
+ grep -A 20 '^\[executor\.policy\]' agent/agentd/config/agentd.toml || echo "No [executor.policy] section found"
23
+
24
+ # List Rego policy files
25
+ ls -la agent/agentd/policy/*.rego 2>/dev/null || echo "No .rego files found"
26
+ ```
27
+
28
+ ## What It Does
29
+
30
+ This skill inspects and configures the OPA (Open Policy Agent) security policy system that governs agentd intent evaluation and gateway authorization.
31
+
32
+ ### Security Profiles
33
+
34
+ Smith Core ships three security profiles:
35
+
36
+ 1. **Permissive** (workstation) — broad tool access; suitable for local development.
37
+ 2. **Strict** (server) — restricted tool set; requires explicit allowlisting.
38
+ 3. **Paranoid** (max security) — minimal defaults; every tool must be individually approved.
39
+
40
+ ### Architecture
41
+
42
+ - 10 Rego policy files live at `agent/agentd/policy/*.rego`.
43
+ - Policy data is stored in PostgreSQL (`opa_policies` table) and synced to the OPA management server.
44
+ - Sync flow: **PostgreSQL** -> **admission service** -> **OPA server (8181)** -> **Envoy ext_authz (9292)**.
45
+ - Separately, agentd evaluates policies in-process via the `regorus` embedded Rego engine using `[executor.policy]` config in `agentd.toml`.
46
+
47
+ ### Important: OPA is Docker-internal only
48
+
49
+ OPA uses `expose: ["8181"]` in docker-compose (no `ports:` mapping), so `curl localhost:8181` will **not** work from the host. All OPA API commands must use `docker compose exec -T opa-management` to reach the OPA API.
50
+
51
+ ## Mutation Commands
52
+
53
+ These commands modify policy state. Use them interactively after inspecting current state:
54
+
55
+ ### Edit tool-access policy data
56
+
57
+ ```bash
58
+ docker compose exec -T postgres psql -U smith -d smith -c "UPDATE opa_policies SET data = '<new-json>' WHERE name = 'tool_access';"
59
+ ```
60
+
61
+ ### Build policy bundle
62
+
63
+ ```bash
64
+ bash agent/agentd/scripts/build-policy-bundle.sh
65
+ ```
66
+
67
+ ### Validate Rego files (requires OPA CLI on host)
68
+
69
+ ```bash
70
+ opa check agent/agentd/policy/
71
+ ```
72
+
73
+ ### Force re-sync from PostgreSQL to OPA
74
+
75
+ ```bash
76
+ docker compose restart opa-management
77
+ ```
78
+
79
+ ## Prerequisites
80
+
81
+ - Docker stack running (`docker compose ps` shows `postgres` and `opa-management` healthy).
82
+ - `opa_policies` table populated (happens during initial `start-stack` phase).
83
+ - `agent/agentd/config/agentd.toml` present.
84
+
85
+ ## Expected Output
86
+
87
+ - `opa_policies` table lists active policy records with timestamps.
88
+ - OPA health endpoint returns `{"status": "ok"}` or similar.
89
+ - Rego files are listed at `agent/agentd/policy/*.rego`.
90
+ - `[executor.policy]` config section is visible in `agentd.toml`.
91
+
92
+ ## Common Failures
93
+
94
+ | Symptom | Cause | Fix |
95
+ |---------|-------|-----|
96
+ | `psql` connection refused | Postgres container not running | `docker compose up -d postgres` |
97
+ | OPA health check fails | `opa-management` container not running | `docker compose up -d opa-management` |
98
+ | Empty `opa_policies` table | Policies not seeded | Re-run `start-stack` skill or seed manually |
99
+ | `regorus` evaluation errors in agentd logs | Rego syntax error in policy files | Run `opa check agent/agentd/policy/` to validate |
100
+ | Changes not reflected in authorization | Sync lag or stale cache | `docker compose restart opa-management` |
101
+
102
+ ## Notes
103
+
104
+ ### Tool-Access Policy Data Structure
105
+
106
+ The `tool_access` policy record in `opa_policies` stores a JSON document with the following structure:
107
+
108
+ ```json
109
+ {
110
+ "default": "permissive",
111
+ "exceptions": {
112
+ "strict": {
113
+ "allowed_tools": ["shell_exec", "file_read", "file_write"],
114
+ "denied_tools": ["network_raw", "kernel_module"]
115
+ },
116
+ "paranoid": {
117
+ "allowed_tools": ["file_read"],
118
+ "denied_tools": ["*"]
119
+ }
120
+ },
121
+ "source_restrictions": {
122
+ "untrusted": {
123
+ "untrusted_allowed_tools": ["file_read", "shell_exec"]
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ - **`default`**: The active security profile name (`permissive`, `strict`, or `paranoid`).
130
+ - **`exceptions`**: Per-profile overrides that define `allowed_tools` and `denied_tools` lists.
131
+ - **`source_restrictions`**: Controls which tools are available to untrusted request sources.
132
+ - **`untrusted_allowed_tools`**: Subset of tools that untrusted callers may invoke regardless of profile.
133
+
134
+ To change the active profile, update the `default` field. To customize tool access within a profile, modify the corresponding entry in `exceptions`.