chainlesschain 0.37.12 → 0.40.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.
Files changed (48) hide show
  1. package/package.json +3 -2
  2. package/src/commands/agent.js +7 -1
  3. package/src/commands/ask.js +24 -9
  4. package/src/commands/chat.js +7 -1
  5. package/src/commands/cli-anything.js +266 -0
  6. package/src/commands/compliance.js +216 -0
  7. package/src/commands/dao.js +312 -0
  8. package/src/commands/dlp.js +278 -0
  9. package/src/commands/evomap.js +558 -0
  10. package/src/commands/hardening.js +230 -0
  11. package/src/commands/matrix.js +168 -0
  12. package/src/commands/nostr.js +185 -0
  13. package/src/commands/pqc.js +162 -0
  14. package/src/commands/scim.js +218 -0
  15. package/src/commands/serve.js +109 -0
  16. package/src/commands/siem.js +156 -0
  17. package/src/commands/social.js +480 -0
  18. package/src/commands/terraform.js +148 -0
  19. package/src/constants.js +1 -0
  20. package/src/index.js +60 -0
  21. package/src/lib/autonomous-agent.js +487 -0
  22. package/src/lib/cli-anything-bridge.js +379 -0
  23. package/src/lib/cli-context-engineering.js +472 -0
  24. package/src/lib/compliance-manager.js +290 -0
  25. package/src/lib/content-recommender.js +205 -0
  26. package/src/lib/dao-governance.js +296 -0
  27. package/src/lib/dlp-engine.js +304 -0
  28. package/src/lib/evomap-client.js +135 -0
  29. package/src/lib/evomap-federation.js +240 -0
  30. package/src/lib/evomap-governance.js +250 -0
  31. package/src/lib/evomap-manager.js +227 -0
  32. package/src/lib/git-integration.js +1 -1
  33. package/src/lib/hardening-manager.js +275 -0
  34. package/src/lib/llm-providers.js +14 -1
  35. package/src/lib/matrix-bridge.js +196 -0
  36. package/src/lib/nostr-bridge.js +195 -0
  37. package/src/lib/permanent-memory.js +370 -0
  38. package/src/lib/plan-mode.js +211 -0
  39. package/src/lib/pqc-manager.js +196 -0
  40. package/src/lib/scim-manager.js +212 -0
  41. package/src/lib/session-manager.js +38 -0
  42. package/src/lib/siem-exporter.js +137 -0
  43. package/src/lib/social-manager.js +283 -0
  44. package/src/lib/task-model-selector.js +232 -0
  45. package/src/lib/terraform-manager.js +201 -0
  46. package/src/lib/ws-server.js +474 -0
  47. package/src/repl/agent-repl.js +796 -41
  48. package/src/repl/chat-repl.js +14 -6
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Hardening commands
3
+ * chainlesschain hardening baseline|audit
4
+ */
5
+
6
+ import chalk from "chalk";
7
+ import { logger } from "../lib/logger.js";
8
+ import { bootstrap, shutdown } from "../runtime/bootstrap.js";
9
+ import {
10
+ ensureHardeningTables,
11
+ collectBaseline,
12
+ compareBaseline,
13
+ listBaselines,
14
+ runAudit,
15
+ getAuditReports,
16
+ getAuditReport,
17
+ } from "../lib/hardening-manager.js";
18
+
19
+ export function registerHardeningCommand(program) {
20
+ const hardening = program
21
+ .command("hardening")
22
+ .description(
23
+ "Security hardening — baselines, audits, regression detection",
24
+ );
25
+
26
+ // baseline subcommands
27
+ const baseline = hardening
28
+ .command("baseline")
29
+ .description("Performance baseline management");
30
+
31
+ baseline
32
+ .command("collect <name>")
33
+ .description("Collect a performance baseline")
34
+ .option("-v, --version <version>", "Baseline version", "1.0.0")
35
+ .action(async (name, options) => {
36
+ try {
37
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
38
+ if (!ctx.db) {
39
+ logger.error("Database not available");
40
+ process.exit(1);
41
+ }
42
+ const db = ctx.db.getDatabase();
43
+ ensureHardeningTables(db);
44
+
45
+ const result = collectBaseline(db, name, options.version);
46
+ logger.success("Baseline collected");
47
+ logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(result.id)}`);
48
+ logger.log(` ${chalk.bold("Name:")} ${result.name}`);
49
+ logger.log(` ${chalk.bold("Version:")} ${result.version}`);
50
+ logger.log(` ${chalk.bold("Status:")} ${result.status}`);
51
+ await shutdown();
52
+ } catch (err) {
53
+ logger.error(`Failed: ${err.message}`);
54
+ process.exit(1);
55
+ }
56
+ });
57
+
58
+ baseline
59
+ .command("compare <baseline-id>")
60
+ .description("Compare baseline against current or another baseline")
61
+ .option("-c, --current <id>", "Current baseline ID to compare against")
62
+ .option("--json", "Output as JSON")
63
+ .action(async (baselineId, options) => {
64
+ try {
65
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
66
+ if (!ctx.db) {
67
+ logger.error("Database not available");
68
+ process.exit(1);
69
+ }
70
+ const db = ctx.db.getDatabase();
71
+ ensureHardeningTables(db);
72
+
73
+ const result = compareBaseline(baselineId, options.current);
74
+ if (options.json) {
75
+ console.log(JSON.stringify(result, null, 2));
76
+ } else {
77
+ logger.log(
78
+ ` ${chalk.bold("Regressions:")} ${result.hasRegressions ? chalk.red("Yes") : chalk.green("No")}`,
79
+ );
80
+ logger.log(` ${chalk.bold("Summary:")} ${result.summary}`);
81
+ for (const r of result.regressions) {
82
+ logger.log(
83
+ ` ${chalk.yellow(r.metric)}: ${r.ratio.toFixed(2)}x (threshold: ${r.threshold}x)`,
84
+ );
85
+ }
86
+ }
87
+ await shutdown();
88
+ } catch (err) {
89
+ logger.error(`Failed: ${err.message}`);
90
+ process.exit(1);
91
+ }
92
+ });
93
+
94
+ baseline
95
+ .command("list")
96
+ .description("List collected baselines")
97
+ .option("--json", "Output as JSON")
98
+ .action(async (options) => {
99
+ try {
100
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
101
+ if (!ctx.db) {
102
+ logger.error("Database not available");
103
+ process.exit(1);
104
+ }
105
+ const db = ctx.db.getDatabase();
106
+ ensureHardeningTables(db);
107
+
108
+ const baselines = listBaselines();
109
+ if (options.json) {
110
+ console.log(JSON.stringify(baselines, null, 2));
111
+ } else if (baselines.length === 0) {
112
+ logger.info("No baselines collected.");
113
+ } else {
114
+ for (const b of baselines) {
115
+ logger.log(
116
+ ` ${chalk.cyan(b.id.slice(0, 8))} ${b.name} v${b.version} [${b.status}] samples=${b.sampleCount}`,
117
+ );
118
+ }
119
+ }
120
+ await shutdown();
121
+ } catch (err) {
122
+ logger.error(`Failed: ${err.message}`);
123
+ process.exit(1);
124
+ }
125
+ });
126
+
127
+ // audit subcommands
128
+ const audit = hardening
129
+ .command("audit")
130
+ .description("Security audit management");
131
+
132
+ audit
133
+ .command("run <name>")
134
+ .description("Run a security hardening audit")
135
+ .action(async (name) => {
136
+ try {
137
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
138
+ if (!ctx.db) {
139
+ logger.error("Database not available");
140
+ process.exit(1);
141
+ }
142
+ const db = ctx.db.getDatabase();
143
+ ensureHardeningTables(db);
144
+
145
+ const result = runAudit(db, name);
146
+ logger.success(`Audit complete: score ${result.score}%`);
147
+ logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(result.id)}`);
148
+ logger.log(
149
+ ` ${chalk.bold("Passed:")} ${result.passed}/${result.checks.length}`,
150
+ );
151
+ logger.log(
152
+ ` ${chalk.bold("Failed:")} ${result.failed}/${result.checks.length}`,
153
+ );
154
+ for (const rec of result.recommendations) {
155
+ logger.log(` ${chalk.yellow("→")} ${rec}`);
156
+ }
157
+ await shutdown();
158
+ } catch (err) {
159
+ logger.error(`Failed: ${err.message}`);
160
+ process.exit(1);
161
+ }
162
+ });
163
+
164
+ audit
165
+ .command("reports")
166
+ .description("List audit reports")
167
+ .option("--json", "Output as JSON")
168
+ .action(async (options) => {
169
+ try {
170
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
171
+ if (!ctx.db) {
172
+ logger.error("Database not available");
173
+ process.exit(1);
174
+ }
175
+ const db = ctx.db.getDatabase();
176
+ ensureHardeningTables(db);
177
+
178
+ const reports = getAuditReports();
179
+ if (options.json) {
180
+ console.log(JSON.stringify(reports, null, 2));
181
+ } else if (reports.length === 0) {
182
+ logger.info("No audit reports.");
183
+ } else {
184
+ for (const r of reports) {
185
+ logger.log(
186
+ ` ${chalk.cyan(r.id.slice(0, 8))} ${r.name} score=${r.score}% passed=${r.passed} failed=${r.failed}`,
187
+ );
188
+ }
189
+ }
190
+ await shutdown();
191
+ } catch (err) {
192
+ logger.error(`Failed: ${err.message}`);
193
+ process.exit(1);
194
+ }
195
+ });
196
+
197
+ audit
198
+ .command("report <audit-id>")
199
+ .description("Show a specific audit report")
200
+ .option("--json", "Output as JSON")
201
+ .action(async (auditId, options) => {
202
+ try {
203
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
204
+ if (!ctx.db) {
205
+ logger.error("Database not available");
206
+ process.exit(1);
207
+ }
208
+ const db = ctx.db.getDatabase();
209
+ ensureHardeningTables(db);
210
+
211
+ const report = getAuditReport(auditId);
212
+ if (options.json) {
213
+ console.log(JSON.stringify(report, null, 2));
214
+ } else {
215
+ logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(report.id)}`);
216
+ logger.log(` ${chalk.bold("Name:")} ${report.name}`);
217
+ logger.log(` ${chalk.bold("Score:")} ${report.score}%`);
218
+ for (const c of report.checks) {
219
+ const icon =
220
+ c.status === "pass" ? chalk.green("✓") : chalk.red("✗");
221
+ logger.log(` ${icon} ${c.name}: ${c.detail}`);
222
+ }
223
+ }
224
+ await shutdown();
225
+ } catch (err) {
226
+ logger.error(`Failed: ${err.message}`);
227
+ process.exit(1);
228
+ }
229
+ });
230
+ }
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Matrix commands
3
+ * chainlesschain matrix login|rooms|send|messages|join
4
+ */
5
+
6
+ import chalk from "chalk";
7
+ import { logger } from "../lib/logger.js";
8
+ import { bootstrap, shutdown } from "../runtime/bootstrap.js";
9
+ import {
10
+ ensureMatrixTables,
11
+ login,
12
+ listRooms,
13
+ sendMessage,
14
+ getMessages,
15
+ joinRoom,
16
+ getLoginState,
17
+ } from "../lib/matrix-bridge.js";
18
+
19
+ export function registerMatrixCommand(program) {
20
+ const matrix = program
21
+ .command("matrix")
22
+ .description("Matrix bridge — rooms, messaging, E2EE");
23
+
24
+ matrix
25
+ .command("login")
26
+ .description("Login to a Matrix homeserver")
27
+ .option("-s, --server <url>", "Homeserver URL", "https://matrix.org")
28
+ .requiredOption("-u, --user <id>", "User ID (e.g. @user:matrix.org)")
29
+ .requiredOption("-p, --password <pass>", "Password")
30
+ .action(async (options) => {
31
+ try {
32
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
33
+ if (!ctx.db) {
34
+ logger.error("Database not available");
35
+ process.exit(1);
36
+ }
37
+ const db = ctx.db.getDatabase();
38
+ ensureMatrixTables(db);
39
+
40
+ const result = login(
41
+ db,
42
+ options.server,
43
+ options.user,
44
+ options.password,
45
+ );
46
+ logger.success(`Logged in as ${chalk.cyan(result.userId)}`);
47
+ logger.log(` ${chalk.bold("Server:")} ${result.homeserver}`);
48
+ logger.log(` ${chalk.bold("Token:")} ${result.accessToken}`);
49
+ await shutdown();
50
+ } catch (err) {
51
+ logger.error(`Failed: ${err.message}`);
52
+ process.exit(1);
53
+ }
54
+ });
55
+
56
+ matrix
57
+ .command("rooms")
58
+ .description("List joined rooms")
59
+ .option("--json", "Output as JSON")
60
+ .action(async (options) => {
61
+ try {
62
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
63
+ if (!ctx.db) {
64
+ logger.error("Database not available");
65
+ process.exit(1);
66
+ }
67
+ const db = ctx.db.getDatabase();
68
+ ensureMatrixTables(db);
69
+
70
+ const rooms = listRooms();
71
+ if (options.json) {
72
+ console.log(JSON.stringify(rooms, null, 2));
73
+ } else if (rooms.length === 0) {
74
+ logger.info("No rooms joined.");
75
+ } else {
76
+ for (const r of rooms) {
77
+ logger.log(
78
+ ` ${chalk.cyan(r.roomId)} ${r.name || ""} members=${r.memberCount} encrypted=${r.isEncrypted}`,
79
+ );
80
+ }
81
+ }
82
+ await shutdown();
83
+ } catch (err) {
84
+ logger.error(`Failed: ${err.message}`);
85
+ process.exit(1);
86
+ }
87
+ });
88
+
89
+ matrix
90
+ .command("send <room-id> <message>")
91
+ .description("Send a message to a room")
92
+ .option("-t, --type <msgtype>", "Message type", "m.text")
93
+ .action(async (roomId, message, options) => {
94
+ try {
95
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
96
+ if (!ctx.db) {
97
+ logger.error("Database not available");
98
+ process.exit(1);
99
+ }
100
+ const db = ctx.db.getDatabase();
101
+ ensureMatrixTables(db);
102
+
103
+ const result = sendMessage(db, roomId, message, options.type);
104
+ logger.success(`Message sent to ${chalk.cyan(roomId)}`);
105
+ logger.log(` ${chalk.bold("Event:")} ${result.event.eventId}`);
106
+ await shutdown();
107
+ } catch (err) {
108
+ logger.error(`Failed: ${err.message}`);
109
+ process.exit(1);
110
+ }
111
+ });
112
+
113
+ matrix
114
+ .command("messages <room-id>")
115
+ .description("Get messages from a room")
116
+ .option("-n, --limit <n>", "Max messages", "50")
117
+ .option("--json", "Output as JSON")
118
+ .action(async (roomId, options) => {
119
+ try {
120
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
121
+ if (!ctx.db) {
122
+ logger.error("Database not available");
123
+ process.exit(1);
124
+ }
125
+ const db = ctx.db.getDatabase();
126
+ ensureMatrixTables(db);
127
+
128
+ const messages = getMessages(roomId, {
129
+ limit: parseInt(options.limit),
130
+ });
131
+ if (options.json) {
132
+ console.log(JSON.stringify(messages, null, 2));
133
+ } else if (messages.length === 0) {
134
+ logger.info("No messages found.");
135
+ } else {
136
+ for (const m of messages) {
137
+ logger.log(` ${chalk.gray(m.sender)} ${m.content.body}`);
138
+ }
139
+ }
140
+ await shutdown();
141
+ } catch (err) {
142
+ logger.error(`Failed: ${err.message}`);
143
+ process.exit(1);
144
+ }
145
+ });
146
+
147
+ matrix
148
+ .command("join <room-id>")
149
+ .description("Join a Matrix room")
150
+ .action(async (roomId) => {
151
+ try {
152
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
153
+ if (!ctx.db) {
154
+ logger.error("Database not available");
155
+ process.exit(1);
156
+ }
157
+ const db = ctx.db.getDatabase();
158
+ ensureMatrixTables(db);
159
+
160
+ const result = joinRoom(db, roomId);
161
+ logger.success(`Joined room ${chalk.cyan(result.room.roomId)}`);
162
+ await shutdown();
163
+ } catch (err) {
164
+ logger.error(`Failed: ${err.message}`);
165
+ process.exit(1);
166
+ }
167
+ });
168
+ }
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Nostr commands
3
+ * chainlesschain nostr relays|add-relay|publish|events|keygen|map-did
4
+ */
5
+
6
+ import chalk from "chalk";
7
+ import { logger } from "../lib/logger.js";
8
+ import { bootstrap, shutdown } from "../runtime/bootstrap.js";
9
+ import {
10
+ ensureNostrTables,
11
+ listRelays,
12
+ addRelay,
13
+ publishEvent,
14
+ getEvents,
15
+ generateKeypair,
16
+ mapDid,
17
+ } from "../lib/nostr-bridge.js";
18
+
19
+ export function registerNostrCommand(program) {
20
+ const nostr = program
21
+ .command("nostr")
22
+ .description("Nostr bridge — relays, events, keypairs, DID mapping");
23
+
24
+ nostr
25
+ .command("relays")
26
+ .description("List configured Nostr relays")
27
+ .option("--json", "Output as JSON")
28
+ .action(async (options) => {
29
+ try {
30
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
31
+ if (!ctx.db) {
32
+ logger.error("Database not available");
33
+ process.exit(1);
34
+ }
35
+ const db = ctx.db.getDatabase();
36
+ ensureNostrTables(db);
37
+
38
+ const relays = listRelays();
39
+ if (options.json) {
40
+ console.log(JSON.stringify(relays, null, 2));
41
+ } else if (relays.length === 0) {
42
+ logger.info(
43
+ "No relays configured. Use `nostr add-relay <url>` to add one.",
44
+ );
45
+ } else {
46
+ for (const r of relays) {
47
+ logger.log(
48
+ ` ${chalk.cyan(r.url)} [${r.status}] events=${r.eventCount}`,
49
+ );
50
+ }
51
+ }
52
+ await shutdown();
53
+ } catch (err) {
54
+ logger.error(`Failed: ${err.message}`);
55
+ process.exit(1);
56
+ }
57
+ });
58
+
59
+ nostr
60
+ .command("add-relay <url>")
61
+ .description("Add a Nostr relay")
62
+ .action(async (url) => {
63
+ try {
64
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
65
+ if (!ctx.db) {
66
+ logger.error("Database not available");
67
+ process.exit(1);
68
+ }
69
+ const db = ctx.db.getDatabase();
70
+ ensureNostrTables(db);
71
+
72
+ const relay = addRelay(db, url);
73
+ logger.success(`Relay added: ${chalk.cyan(relay.url)}`);
74
+ await shutdown();
75
+ } catch (err) {
76
+ logger.error(`Failed: ${err.message}`);
77
+ process.exit(1);
78
+ }
79
+ });
80
+
81
+ nostr
82
+ .command("publish <content>")
83
+ .description("Publish a text note event")
84
+ .option("-k, --kind <n>", "Event kind", "1")
85
+ .option("-p, --pubkey <key>", "Author public key")
86
+ .action(async (content, options) => {
87
+ try {
88
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
89
+ if (!ctx.db) {
90
+ logger.error("Database not available");
91
+ process.exit(1);
92
+ }
93
+ const db = ctx.db.getDatabase();
94
+ ensureNostrTables(db);
95
+
96
+ const result = publishEvent(
97
+ db,
98
+ parseInt(options.kind),
99
+ content,
100
+ options.pubkey,
101
+ );
102
+ logger.success("Event published");
103
+ logger.log(
104
+ ` ${chalk.bold("ID:")} ${chalk.cyan(result.event.id.slice(0, 16))}...`,
105
+ );
106
+ logger.log(` ${chalk.bold("Sent:")} ${result.sentCount} relay(s)`);
107
+ await shutdown();
108
+ } catch (err) {
109
+ logger.error(`Failed: ${err.message}`);
110
+ process.exit(1);
111
+ }
112
+ });
113
+
114
+ nostr
115
+ .command("events")
116
+ .description("List events")
117
+ .option("-k, --kind <n>", "Filter by event kind")
118
+ .option("-n, --limit <n>", "Max results", "50")
119
+ .option("--json", "Output as JSON")
120
+ .action(async (options) => {
121
+ try {
122
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
123
+ if (!ctx.db) {
124
+ logger.error("Database not available");
125
+ process.exit(1);
126
+ }
127
+ const db = ctx.db.getDatabase();
128
+ ensureNostrTables(db);
129
+
130
+ const filter = { limit: parseInt(options.limit) };
131
+ if (options.kind) filter.kinds = [parseInt(options.kind)];
132
+ const events = getEvents(filter);
133
+ if (options.json) {
134
+ console.log(JSON.stringify(events, null, 2));
135
+ } else if (events.length === 0) {
136
+ logger.info("No events found.");
137
+ } else {
138
+ for (const e of events) {
139
+ logger.log(
140
+ ` ${chalk.cyan(e.id.slice(0, 12))} kind=${e.kind} "${e.content.slice(0, 60)}"`,
141
+ );
142
+ }
143
+ }
144
+ await shutdown();
145
+ } catch (err) {
146
+ logger.error(`Failed: ${err.message}`);
147
+ process.exit(1);
148
+ }
149
+ });
150
+
151
+ nostr
152
+ .command("keygen")
153
+ .description("Generate a Nostr keypair")
154
+ .option("--json", "Output as JSON")
155
+ .action(async (options) => {
156
+ try {
157
+ const kp = generateKeypair();
158
+ if (options.json) {
159
+ console.log(JSON.stringify(kp, null, 2));
160
+ } else {
161
+ logger.success("Keypair generated");
162
+ logger.log(` ${chalk.bold("Public:")} ${chalk.cyan(kp.publicKey)}`);
163
+ logger.log(
164
+ ` ${chalk.bold("Private:")} ${kp.privateKey.slice(0, 16)}...`,
165
+ );
166
+ }
167
+ } catch (err) {
168
+ logger.error(`Failed: ${err.message}`);
169
+ process.exit(1);
170
+ }
171
+ });
172
+
173
+ nostr
174
+ .command("map-did <did> <pubkey>")
175
+ .description("Map a DID identity to a Nostr pubkey")
176
+ .action(async (did, pubkey) => {
177
+ try {
178
+ const result = mapDid(did, pubkey);
179
+ logger.success(`DID ${chalk.cyan(did)} mapped to Nostr pubkey`);
180
+ } catch (err) {
181
+ logger.error(`Failed: ${err.message}`);
182
+ process.exit(1);
183
+ }
184
+ });
185
+ }