@aarmos/bridge 0.1.0

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.
Files changed (43) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +280 -0
  3. package/dist/bridge.js +129 -0
  4. package/dist/bridge.js.map +1 -0
  5. package/dist/commands/attest.js +62 -0
  6. package/dist/commands/attest.js.map +1 -0
  7. package/dist/commands/demo.js +169 -0
  8. package/dist/commands/demo.js.map +1 -0
  9. package/dist/commands/dev.js +56 -0
  10. package/dist/commands/dev.js.map +1 -0
  11. package/dist/commands/pack.js +94 -0
  12. package/dist/commands/pack.js.map +1 -0
  13. package/dist/commands/playbook.js +55 -0
  14. package/dist/commands/playbook.js.map +1 -0
  15. package/dist/commands/run.js +279 -0
  16. package/dist/commands/run.js.map +1 -0
  17. package/dist/commands/simulate.js +181 -0
  18. package/dist/commands/simulate.js.map +1 -0
  19. package/dist/commands/verify.js +81 -0
  20. package/dist/commands/verify.js.map +1 -0
  21. package/dist/index.js +231 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/lib/attest.js +160 -0
  24. package/dist/lib/attest.js.map +1 -0
  25. package/dist/lib/http-broker.js +82 -0
  26. package/dist/lib/http-broker.js.map +1 -0
  27. package/dist/lib/mcp-broker.js +80 -0
  28. package/dist/lib/mcp-broker.js.map +1 -0
  29. package/dist/lib/pack.js +80 -0
  30. package/dist/lib/pack.js.map +1 -0
  31. package/dist/lib/playbook.js +199 -0
  32. package/dist/lib/playbook.js.map +1 -0
  33. package/dist/lib/scope-templates.js +129 -0
  34. package/dist/lib/scope-templates.js.map +1 -0
  35. package/dist/rpc/router.js +321 -0
  36. package/dist/rpc/router.js.map +1 -0
  37. package/dist/session.js +100 -0
  38. package/dist/session.js.map +1 -0
  39. package/dist/watchers/files.js +31 -0
  40. package/dist/watchers/files.js.map +1 -0
  41. package/dist/watchers/git.js +39 -0
  42. package/dist/watchers/git.js.map +1 -0
  43. package/package.json +67 -0
@@ -0,0 +1,80 @@
1
+ // Certified playbook packs — versioned bundles of playbooks, scope
2
+ // templates, and pre-classified risk rankings.
3
+ //
4
+ // Format (single JSON file, optionally signed):
5
+ // {
6
+ // "name": "@aarmos/k8s-safeguards",
7
+ // "version": "0.1.0",
8
+ // "instructions": "Governed kubectl playbooks for restart / scale / drain.",
9
+ // "playbooks": [ Playbook, ... ], // same shape as a standalone playbook
10
+ // "allow": {
11
+ // "shell": ["kubectl"],
12
+ // "http": ["api.github.com"],
13
+ // "mcp": ["https://mcp.example/atlassian"]
14
+ // },
15
+ // "signature"?: { alg: "ed25519", pubKey, sig }
16
+ // }
17
+ //
18
+ // The pack itself is signed with the SAME ed25519 primitive as
19
+ // playbooks (see lib/playbook.ts). `aarmos pack verify` and
20
+ // `aarmos run --enforce-signatures` both accept a pack pubkey.
21
+ //
22
+ // Install writes to `.aarmos/packs/<safe-name>-<version>/pack.json`
23
+ // so packs are inspectable, diff-able in git, and never mutate the
24
+ // operator's global state.
25
+ import fs from "node:fs/promises";
26
+ import path from "node:path";
27
+ import crypto from "node:crypto";
28
+ import { canonicalize } from "./playbook.js";
29
+ export function packBody(pack) {
30
+ const { signature: _s, ...rest } = pack;
31
+ void _s;
32
+ return canonicalize(rest);
33
+ }
34
+ export function hashPack(pack) {
35
+ return crypto.createHash("sha256").update(packBody(pack)).digest("hex");
36
+ }
37
+ export async function loadPack(p) {
38
+ const raw = await fs.readFile(path.resolve(p), "utf8");
39
+ const parsed = JSON.parse(raw);
40
+ if (!parsed?.name || typeof parsed.name !== "string")
41
+ throw new Error("pack.name required");
42
+ if (!parsed.version || typeof parsed.version !== "string")
43
+ throw new Error("pack.version required");
44
+ if (!Array.isArray(parsed.playbooks) || parsed.playbooks.length === 0) {
45
+ throw new Error("pack.playbooks must be a non-empty array");
46
+ }
47
+ return parsed;
48
+ }
49
+ const SAFE_NAME_RE = /[^a-zA-Z0-9._-]/g;
50
+ export function packInstallDir(pack, rootDir) {
51
+ const safe = pack.name.replace(SAFE_NAME_RE, "_");
52
+ return path.join(rootDir, `${safe}-${pack.version}`);
53
+ }
54
+ export async function installPack(source, rootDir) {
55
+ const pack = await loadPack(source);
56
+ const dir = packInstallDir(pack, rootDir);
57
+ await fs.mkdir(dir, { recursive: true });
58
+ const dest = path.join(dir, "pack.json");
59
+ await fs.writeFile(dest, JSON.stringify(pack, null, 2) + "\n", "utf8");
60
+ return { pack, installed: dest };
61
+ }
62
+ export async function listInstalledPacks(rootDir) {
63
+ const out = [];
64
+ try {
65
+ const entries = await fs.readdir(rootDir, { withFileTypes: true });
66
+ for (const e of entries) {
67
+ if (!e.isDirectory())
68
+ continue;
69
+ const file = path.join(rootDir, e.name, "pack.json");
70
+ try {
71
+ const raw = await fs.readFile(file, "utf8");
72
+ out.push(JSON.parse(raw));
73
+ }
74
+ catch { /* ignore malformed */ }
75
+ }
76
+ }
77
+ catch { /* no packs dir yet */ }
78
+ return out;
79
+ }
80
+ //# sourceMappingURL=pack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pack.js","sourceRoot":"","sources":["../../src/lib/pack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,199 @@
1
+ // Shared playbook loader, canonicalizer, and Ed25519 signer/verifier.
2
+ //
3
+ // Design contract:
4
+ // - Signing is OPTIONAL. Dev mode ignores signatures entirely; only
5
+ // `aarmos run --enforce-signatures` refuses unsigned/invalid playbooks.
6
+ // - Signature covers a canonical JSON of the playbook body with the
7
+ // `signature` field stripped, matching the shape used by the PWA's
8
+ // `signObject` in src/lib/observability/signer.ts (sorted keys, no
9
+ // whitespace). Same primitive — a receipt viewer can verify both.
10
+ // - Keys are Ed25519 raw 32-byte public keys, base64url-encoded. Private
11
+ // keys are PKCS8 PEM on disk. We never load private keys at `run` time.
12
+ import fs from "node:fs/promises";
13
+ import path from "node:path";
14
+ import crypto from "node:crypto";
15
+ // ---------------- load + validate --------------------------------------------
16
+ export async function loadPlaybook(p) {
17
+ const raw = await fs.readFile(path.resolve(p), "utf8");
18
+ let parsed;
19
+ try {
20
+ parsed = JSON.parse(raw);
21
+ }
22
+ catch (err) {
23
+ throw new Error(`playbook is not valid JSON: ${err.message}`);
24
+ }
25
+ if (!parsed || typeof parsed !== "object")
26
+ throw new Error("playbook must be an object");
27
+ const pb = parsed;
28
+ if (!pb.name || typeof pb.name !== "string")
29
+ throw new Error("playbook.name is required");
30
+ if (!Array.isArray(pb.steps) || pb.steps.length === 0) {
31
+ throw new Error("playbook.steps must be a non-empty array");
32
+ }
33
+ const seen = new Set();
34
+ for (const s of pb.steps) {
35
+ if (!s.id || typeof s.id !== "string")
36
+ throw new Error("each step needs an id");
37
+ if (seen.has(s.id))
38
+ throw new Error(`duplicate step id: ${s.id}`);
39
+ seen.add(s.id);
40
+ if (s.kind !== "shell.exec" && s.kind !== "fs.write" && s.kind !== "http.call" && s.kind !== "mcp.tool") {
41
+ throw new Error(`step ${s.id}: kind must be one of shell.exec, fs.write, http.call, mcp.tool`);
42
+ }
43
+ if (!s.params || typeof s.params !== "object") {
44
+ throw new Error(`step ${s.id}: params object required`);
45
+ }
46
+ }
47
+ return pb;
48
+ }
49
+ /**
50
+ * Structural lint — catches the class of problems that don't need the
51
+ * runtime gate (unknown fields, missing intervals, autoApply on shell
52
+ * without an explicit allowlist hint, etc.). This is the compile-time
53
+ * safety net; runtime enforcement still runs on every step regardless.
54
+ */
55
+ export function lintPlaybook(pb) {
56
+ const out = [];
57
+ if (pb.steps.length > 100) {
58
+ out.push({ level: "warn", message: `playbook has ${pb.steps.length} steps — consider splitting` });
59
+ }
60
+ for (const s of pb.steps) {
61
+ if (!s.label)
62
+ out.push({ level: "warn", stepId: s.id, message: "missing human-readable label" });
63
+ if (s.intervalSec !== undefined && (typeof s.intervalSec !== "number" || s.intervalSec < 1)) {
64
+ out.push({ level: "error", stepId: s.id, message: "intervalSec must be a positive number" });
65
+ }
66
+ if (s.kind === "shell.exec") {
67
+ const p = s.params;
68
+ if (typeof p.bin !== "string" || !p.bin) {
69
+ out.push({ level: "error", stepId: s.id, message: "shell.exec: params.bin (string) required" });
70
+ }
71
+ if (p.args !== undefined && !Array.isArray(p.args)) {
72
+ out.push({ level: "error", stepId: s.id, message: "shell.exec: params.args must be an array" });
73
+ }
74
+ if (s.autoApply) {
75
+ out.push({
76
+ level: "info",
77
+ stepId: s.id,
78
+ message: "shell.exec has autoApply=true — will execute unattended if bin is in allowlist",
79
+ });
80
+ }
81
+ }
82
+ if (s.kind === "fs.write") {
83
+ const p = s.params;
84
+ if (typeof p.path !== "string" || !p.path) {
85
+ out.push({ level: "error", stepId: s.id, message: "fs.write: params.path (string) required" });
86
+ }
87
+ if (p.data !== undefined && typeof p.data !== "string") {
88
+ out.push({ level: "error", stepId: s.id, message: "fs.write: params.data must be a string" });
89
+ }
90
+ }
91
+ if (s.kind === "http.call") {
92
+ const p = s.params;
93
+ if (typeof p.url !== "string" || !/^https?:\/\//.test(p.url)) {
94
+ out.push({ level: "error", stepId: s.id, message: "http.call: params.url (http(s) URL) required" });
95
+ }
96
+ if (p.method !== undefined && typeof p.method !== "string") {
97
+ out.push({ level: "error", stepId: s.id, message: "http.call: params.method must be a string" });
98
+ }
99
+ }
100
+ if (s.kind === "mcp.tool") {
101
+ const p = s.params;
102
+ if (typeof p.endpoint !== "string" || !/^https?:\/\//.test(p.endpoint)) {
103
+ out.push({ level: "error", stepId: s.id, message: "mcp.tool: params.endpoint (http(s) URL) required" });
104
+ }
105
+ if (typeof p.tool !== "string" || !p.tool) {
106
+ out.push({ level: "error", stepId: s.id, message: "mcp.tool: params.tool (string) required" });
107
+ }
108
+ }
109
+ }
110
+ return out;
111
+ }
112
+ // ---------------- canonicalize + sign/verify ---------------------------------
113
+ /** Sorted-key JSON, no whitespace. Matches PWA signer.ts canonicalize().
114
+ * Skips keys whose values are `undefined` so the canonical form matches
115
+ * what JSON.stringify produces after a write/read roundtrip. */
116
+ export function canonicalize(v) {
117
+ if (v === undefined)
118
+ return "null";
119
+ if (v === null || typeof v !== "object")
120
+ return JSON.stringify(v);
121
+ if (Array.isArray(v))
122
+ return "[" + v.map((x) => canonicalize(x)).join(",") + "]";
123
+ const obj = v;
124
+ const keys = Object.keys(obj).filter((k) => obj[k] !== undefined).sort();
125
+ return ("{" +
126
+ keys.map((k) => JSON.stringify(k) + ":" + canonicalize(obj[k])).join(",") +
127
+ "}");
128
+ }
129
+ function playbookBody(pb) {
130
+ const { signature: _s, ...rest } = pb;
131
+ void _s;
132
+ return canonicalize(rest);
133
+ }
134
+ function b64u(buf) {
135
+ return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
136
+ }
137
+ function b64uDecode(s) {
138
+ const b64 = s.replace(/-/g, "+").replace(/_/g, "/") + "===".slice((s.length + 3) % 4);
139
+ return Buffer.from(b64, "base64");
140
+ }
141
+ export async function generateSigningKeyPair(outDir, name) {
142
+ const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
143
+ const pem = privateKey.export({ format: "pem", type: "pkcs8" }).toString();
144
+ const raw = publicKey.export({ format: "der", type: "spki" });
145
+ // Ed25519 SPKI DER header is 12 bytes; the trailing 32 are the raw key.
146
+ const rawKey = raw.subarray(raw.length - 32);
147
+ const pubB64u = b64u(rawKey);
148
+ await fs.mkdir(outDir, { recursive: true });
149
+ const privPath = path.join(outDir, `${name}.key.pem`);
150
+ const pubPath = path.join(outDir, `${name}.pub`);
151
+ await fs.writeFile(privPath, pem, { mode: 0o600 });
152
+ await fs.writeFile(pubPath, pubB64u + "\n");
153
+ return { privatePem: privPath, publicKey: pubB64u };
154
+ }
155
+ export async function signPlaybook(pb, privateKeyPem) {
156
+ const key = crypto.createPrivateKey(privateKeyPem);
157
+ const bytes = Buffer.from(playbookBody(pb));
158
+ const sig = crypto.sign(null, bytes, key);
159
+ // Derive matching public key so the signed file is self-verifiable.
160
+ const pubDer = crypto.createPublicKey(key).export({ format: "der", type: "spki" });
161
+ const rawPub = pubDer.subarray(pubDer.length - 32);
162
+ return {
163
+ ...pb,
164
+ signature: { alg: "ed25519", pubKey: b64u(rawPub), sig: b64u(sig) },
165
+ };
166
+ }
167
+ export function verifyPlaybookSignature(pb) {
168
+ if (!pb.signature)
169
+ return { ok: false, reason: "playbook is not signed" };
170
+ if (pb.signature.alg !== "ed25519") {
171
+ return { ok: false, reason: `unsupported alg: ${pb.signature.alg}` };
172
+ }
173
+ try {
174
+ // Reconstruct SPKI DER from raw 32-byte Ed25519 public key.
175
+ const spkiPrefix = Buffer.from([
176
+ 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
177
+ ]);
178
+ const rawPub = b64uDecode(pb.signature.pubKey);
179
+ if (rawPub.length !== 32)
180
+ return { ok: false, reason: "pubKey must be 32 bytes" };
181
+ const der = Buffer.concat([spkiPrefix, rawPub]);
182
+ const key = crypto.createPublicKey({ key: der, format: "der", type: "spki" });
183
+ const bytes = Buffer.from(playbookBody(pb));
184
+ const sig = b64uDecode(pb.signature.sig);
185
+ const ok = crypto.verify(null, bytes, key, sig);
186
+ return ok ? { ok: true } : { ok: false, reason: "signature does not match playbook body" };
187
+ }
188
+ catch (err) {
189
+ return { ok: false, reason: err.message };
190
+ }
191
+ }
192
+ /** Deterministic sha256 over the canonical playbook body (sans signature). */
193
+ export function hashPlaybook(pb) {
194
+ return crypto.createHash("sha256").update(playbookBody(pb)).digest("hex");
195
+ }
196
+ export async function writePlaybook(p, pb) {
197
+ await fs.writeFile(path.resolve(p), JSON.stringify(pb, null, 2) + "\n", "utf8");
198
+ }
199
+ //# sourceMappingURL=playbook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playbook.js","sourceRoot":"","sources":["../../src/lib/playbook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,129 @@
1
+ // Scope templates + risk classification.
2
+ //
3
+ // Compile-time governance primitives shared by `simulate` and `run`.
4
+ // Every step kind resolves to a `RiskRank`:
5
+ // - "read" → observability only; safe to auto-apply
6
+ // - "write" → mutating but reversible; auto-apply if autoApply=true
7
+ // - "destructive" → deletes / drops / drains / push --force; ALWAYS needs
8
+ // human approval unless the step sets
9
+ // `acknowledgeDestructive: true` AND the playbook is
10
+ // signed with a trusted pubkey (enforced in run.ts).
11
+ //
12
+ // Templates are additive: unknown verbs default to "write" so we err on
13
+ // the side of showing an approval card. Adding a new SaaS is a pure data
14
+ // change (append to KUBECTL_VERBS / JIRA_ENDPOINTS / ...) — no gate rewrite.
15
+ // ---------------- kubectl -----------------------------------------------------
16
+ const KUBECTL_READ = new Set([
17
+ "get", "describe", "logs", "top", "version", "api-resources",
18
+ "api-versions", "explain", "config", "cluster-info", "auth",
19
+ ]);
20
+ const KUBECTL_WRITE = new Set([
21
+ "apply", "create", "scale", "patch", "rollout", "edit", "label",
22
+ "annotate", "set", "expose", "run", "autoscale", "replace", "taint",
23
+ ]);
24
+ const KUBECTL_DESTRUCTIVE = new Set([
25
+ "delete", "drain", "cordon", "uncordon", "evict", "exec",
26
+ ]);
27
+ // ---------------- git ---------------------------------------------------------
28
+ const GIT_DESTRUCTIVE_FLAGS = ["--force", "-f", "--hard", "-D"];
29
+ const GIT_DESTRUCTIVE_SUBCMDS = new Set(["push", "reset", "clean", "branch", "rebase"]);
30
+ // ---------------- gh (GitHub CLI) ---------------------------------------------
31
+ const GH_READ = new Set(["view", "list", "status", "search", "browse", "auth"]);
32
+ const GH_DESTRUCTIVE = new Set(["delete", "close"]);
33
+ // ---------------- HTTP verbs --------------------------------------------------
34
+ function httpRisk(method) {
35
+ const m = method.toUpperCase();
36
+ if (m === "GET" || m === "HEAD" || m === "OPTIONS")
37
+ return "read";
38
+ if (m === "DELETE")
39
+ return "destructive";
40
+ return "write";
41
+ }
42
+ // ---------------- classifier --------------------------------------------------
43
+ export function classifyStep(step) {
44
+ const p = step.params;
45
+ // Explicit operator override on the step wins (used inside signed packs
46
+ // where the pack author has already reviewed the endpoint).
47
+ const explicit = step.risk;
48
+ if (explicit)
49
+ return { rank: explicit, reason: "explicit step.risk override" };
50
+ if (step.kind === "fs.write") {
51
+ return { rank: "write", reason: "fs.write mutates workspace" };
52
+ }
53
+ if (step.kind === "shell.exec") {
54
+ const bin = String(p.bin ?? "");
55
+ const args = Array.isArray(p.args) ? p.args : [];
56
+ if (bin === "kubectl") {
57
+ const sub = args.find((a) => !a.startsWith("-")) ?? "";
58
+ if (KUBECTL_DESTRUCTIVE.has(sub)) {
59
+ return { rank: "destructive", reason: `kubectl ${sub}`, template: "kubectl" };
60
+ }
61
+ if (KUBECTL_WRITE.has(sub)) {
62
+ return { rank: "write", reason: `kubectl ${sub}`, template: "kubectl" };
63
+ }
64
+ if (KUBECTL_READ.has(sub)) {
65
+ return { rank: "read", reason: `kubectl ${sub}`, template: "kubectl" };
66
+ }
67
+ return { rank: "write", reason: `kubectl ${sub || "(unknown)"} — defaulted`, template: "kubectl" };
68
+ }
69
+ if (bin === "git") {
70
+ const sub = args.find((a) => !a.startsWith("-")) ?? "";
71
+ const hasForce = args.some((a) => GIT_DESTRUCTIVE_FLAGS.includes(a));
72
+ if (GIT_DESTRUCTIVE_SUBCMDS.has(sub) && hasForce) {
73
+ return { rank: "destructive", reason: `git ${sub} with force flag`, template: "git" };
74
+ }
75
+ if (sub === "push")
76
+ return { rank: "write", reason: "git push", template: "git" };
77
+ if (sub === "commit" || sub === "add" || sub === "checkout") {
78
+ return { rank: "write", reason: `git ${sub}`, template: "git" };
79
+ }
80
+ return { rank: "read", reason: `git ${sub || "status"}`, template: "git" };
81
+ }
82
+ if (bin === "gh") {
83
+ const sub = args.find((a) => !a.startsWith("-")) ?? "";
84
+ if (GH_DESTRUCTIVE.has(sub)) {
85
+ return { rank: "destructive", reason: `gh ${sub}`, template: "gh" };
86
+ }
87
+ if (GH_READ.has(sub))
88
+ return { rank: "read", reason: `gh ${sub}`, template: "gh" };
89
+ return { rank: "write", reason: `gh ${sub || "(unknown)"}`, template: "gh" };
90
+ }
91
+ return { rank: "write", reason: `shell.exec ${bin} — defaulted` };
92
+ }
93
+ if (step.kind === "http.call") {
94
+ const method = String(p.method ?? "GET");
95
+ const url = String(p.url ?? "");
96
+ // Jira write endpoints of interest → mark destructive on hard deletes
97
+ if (/\/rest\/api\/\d+\/issue\/[^/]+$/.test(url) && method.toUpperCase() === "DELETE") {
98
+ return { rank: "destructive", reason: "Jira DELETE /issue/{id}", template: "jira" };
99
+ }
100
+ return { rank: httpRisk(method), reason: `HTTP ${method.toUpperCase()}` };
101
+ }
102
+ if (step.kind === "mcp.tool") {
103
+ const hint = String(p.riskHint ?? "");
104
+ if (hint === "read" || hint === "write" || hint === "destructive") {
105
+ return { rank: hint, reason: `mcp.tool riskHint=${hint}` };
106
+ }
107
+ return { rank: "write", reason: "mcp.tool defaulted to write" };
108
+ }
109
+ return { rank: "write", reason: `unknown kind ${String(step.kind)} — defaulted` };
110
+ }
111
+ /** Runtime approval resolver — used by `run.ts` on every tick. */
112
+ export function resolveEffectiveApproval(step, cls, opts) {
113
+ const requested = Boolean(step.autoApply);
114
+ if (cls.rank !== "destructive") {
115
+ return { autoApply: requested, forcedApproval: false };
116
+ }
117
+ const ack = Boolean(step.acknowledgeDestructive);
118
+ if (ack && opts.playbookSigned) {
119
+ return { autoApply: requested, forcedApproval: false };
120
+ }
121
+ return {
122
+ autoApply: false,
123
+ forcedApproval: true,
124
+ reason: ack
125
+ ? "destructive + acknowledgeDestructive requires a signed playbook — forcing approval"
126
+ : "destructive step — forcing approval (set acknowledgeDestructive on a signed playbook to auto-apply)",
127
+ };
128
+ }
129
+ //# sourceMappingURL=scope-templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-templates.js","sourceRoot":"","sources":["../../src/lib/scope-templates.ts"],"names":[],"mappings":"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"}