chainlesschain 0.37.12 → 0.38.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/package.json +1 -1
- package/src/commands/agent.js +2 -0
- package/src/commands/chat.js +2 -0
- package/src/commands/compliance.js +216 -0
- package/src/commands/dao.js +312 -0
- package/src/commands/dlp.js +278 -0
- package/src/commands/evomap.js +558 -0
- package/src/commands/hardening.js +230 -0
- package/src/commands/matrix.js +168 -0
- package/src/commands/nostr.js +185 -0
- package/src/commands/pqc.js +162 -0
- package/src/commands/scim.js +218 -0
- package/src/commands/siem.js +156 -0
- package/src/commands/social.js +480 -0
- package/src/commands/terraform.js +148 -0
- package/src/index.js +48 -0
- package/src/lib/autonomous-agent.js +487 -0
- package/src/lib/cli-context-engineering.js +472 -0
- package/src/lib/compliance-manager.js +290 -0
- package/src/lib/content-recommender.js +205 -0
- package/src/lib/dao-governance.js +296 -0
- package/src/lib/dlp-engine.js +304 -0
- package/src/lib/evomap-client.js +135 -0
- package/src/lib/evomap-federation.js +240 -0
- package/src/lib/evomap-governance.js +250 -0
- package/src/lib/evomap-manager.js +227 -0
- package/src/lib/hardening-manager.js +275 -0
- package/src/lib/matrix-bridge.js +196 -0
- package/src/lib/nostr-bridge.js +195 -0
- package/src/lib/permanent-memory.js +370 -0
- package/src/lib/plan-mode.js +211 -0
- package/src/lib/pqc-manager.js +196 -0
- package/src/lib/scim-manager.js +212 -0
- package/src/lib/session-manager.js +38 -0
- package/src/lib/siem-exporter.js +137 -0
- package/src/lib/social-manager.js +283 -0
- package/src/lib/terraform-manager.js +201 -0
- package/src/repl/agent-repl.js +773 -39
package/package.json
CHANGED
package/src/commands/agent.js
CHANGED
|
@@ -19,12 +19,14 @@ export function registerAgentCommand(program) {
|
|
|
19
19
|
.option("--provider <provider>", "LLM provider (ollama, openai)", "ollama")
|
|
20
20
|
.option("--base-url <url>", "API base URL")
|
|
21
21
|
.option("--api-key <key>", "API key")
|
|
22
|
+
.option("--session <id>", "Resume a previous agent session")
|
|
22
23
|
.action(async (options) => {
|
|
23
24
|
await startAgentRepl({
|
|
24
25
|
model: options.model,
|
|
25
26
|
provider: options.provider,
|
|
26
27
|
baseUrl: options.baseUrl,
|
|
27
28
|
apiKey: options.apiKey,
|
|
29
|
+
sessionId: options.session,
|
|
28
30
|
});
|
|
29
31
|
});
|
|
30
32
|
}
|
package/src/commands/chat.js
CHANGED
|
@@ -18,12 +18,14 @@ export function registerChatCommand(program) {
|
|
|
18
18
|
"--agent",
|
|
19
19
|
"Agentic mode - AI can read/write files and run commands (like Claude Code)",
|
|
20
20
|
)
|
|
21
|
+
.option("--session <id>", "Resume a previous session (agent mode)")
|
|
21
22
|
.action(async (options) => {
|
|
22
23
|
const replOptions = {
|
|
23
24
|
model: options.model,
|
|
24
25
|
provider: options.provider,
|
|
25
26
|
baseUrl: options.baseUrl,
|
|
26
27
|
apiKey: options.apiKey,
|
|
28
|
+
sessionId: options.session,
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
if (options.agent) {
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compliance commands
|
|
3
|
+
* chainlesschain compliance evidence|report|classify|scan|policies|check-access
|
|
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
|
+
ensureComplianceTables,
|
|
11
|
+
collectEvidence,
|
|
12
|
+
generateReport,
|
|
13
|
+
classifyData,
|
|
14
|
+
scanCompliance,
|
|
15
|
+
listPolicies,
|
|
16
|
+
addPolicy,
|
|
17
|
+
checkAccess,
|
|
18
|
+
} from "../lib/compliance-manager.js";
|
|
19
|
+
|
|
20
|
+
export function registerComplianceCommand(program) {
|
|
21
|
+
const compliance = program
|
|
22
|
+
.command("compliance")
|
|
23
|
+
.description(
|
|
24
|
+
"Compliance management — evidence, reports, scanning, policies",
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// compliance evidence
|
|
28
|
+
compliance
|
|
29
|
+
.command("evidence <framework>")
|
|
30
|
+
.description("Collect compliance evidence (gdpr, soc2, hipaa, iso27001)")
|
|
31
|
+
.option("-t, --type <type>", "Evidence type", "general")
|
|
32
|
+
.option("-d, --description <text>", "Evidence description")
|
|
33
|
+
.option("-s, --source <source>", "Evidence source", "cli")
|
|
34
|
+
.action(async (framework, options) => {
|
|
35
|
+
try {
|
|
36
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
37
|
+
if (!ctx.db) {
|
|
38
|
+
logger.error("Database not available");
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
const db = ctx.db.getDatabase();
|
|
42
|
+
ensureComplianceTables(db);
|
|
43
|
+
|
|
44
|
+
const result = collectEvidence(
|
|
45
|
+
db,
|
|
46
|
+
framework,
|
|
47
|
+
options.type,
|
|
48
|
+
options.description,
|
|
49
|
+
options.source,
|
|
50
|
+
);
|
|
51
|
+
logger.success("Evidence collected");
|
|
52
|
+
logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(result.id)}`);
|
|
53
|
+
logger.log(` ${chalk.bold("Framework:")} ${result.framework}`);
|
|
54
|
+
logger.log(` ${chalk.bold("Type:")} ${result.type}`);
|
|
55
|
+
|
|
56
|
+
await shutdown();
|
|
57
|
+
} catch (err) {
|
|
58
|
+
logger.error(`Failed: ${err.message}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// compliance report
|
|
64
|
+
compliance
|
|
65
|
+
.command("report <framework>")
|
|
66
|
+
.description("Generate compliance report")
|
|
67
|
+
.option("-t, --title <title>", "Report title")
|
|
68
|
+
.option("--json", "Output as JSON")
|
|
69
|
+
.action(async (framework, options) => {
|
|
70
|
+
try {
|
|
71
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
72
|
+
if (!ctx.db) {
|
|
73
|
+
logger.error("Database not available");
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
const db = ctx.db.getDatabase();
|
|
77
|
+
ensureComplianceTables(db);
|
|
78
|
+
|
|
79
|
+
const result = generateReport(db, framework, options.title);
|
|
80
|
+
if (options.json) {
|
|
81
|
+
console.log(JSON.stringify(result, null, 2));
|
|
82
|
+
} else {
|
|
83
|
+
logger.success("Report generated");
|
|
84
|
+
logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(result.id)}`);
|
|
85
|
+
logger.log(` ${chalk.bold("Title:")} ${result.title}`);
|
|
86
|
+
logger.log(` ${chalk.bold("Score:")} ${result.score}`);
|
|
87
|
+
logger.log(` ${chalk.bold("Summary:")} ${result.summary}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
await shutdown();
|
|
91
|
+
} catch (err) {
|
|
92
|
+
logger.error(`Failed: ${err.message}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// compliance classify
|
|
98
|
+
compliance
|
|
99
|
+
.command("classify <content>")
|
|
100
|
+
.description("Classify data sensitivity")
|
|
101
|
+
.option("--json", "Output as JSON")
|
|
102
|
+
.action(async (content, options) => {
|
|
103
|
+
try {
|
|
104
|
+
const result = classifyData(content);
|
|
105
|
+
if (options.json) {
|
|
106
|
+
console.log(JSON.stringify(result, null, 2));
|
|
107
|
+
} else {
|
|
108
|
+
logger.log(
|
|
109
|
+
` ${chalk.bold("Sensitive:")} ${result.hasClassifiedData ? "Yes" : "No"}`,
|
|
110
|
+
);
|
|
111
|
+
logger.log(
|
|
112
|
+
` ${chalk.bold("Classifications:")} ${result.classifications.join(", ") || "none"}`,
|
|
113
|
+
);
|
|
114
|
+
logger.log(
|
|
115
|
+
` ${chalk.bold("Sensitivity:")} ${result.sensitivity}`,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
} catch (err) {
|
|
119
|
+
logger.error(`Failed: ${err.message}`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// compliance scan
|
|
125
|
+
compliance
|
|
126
|
+
.command("scan <framework>")
|
|
127
|
+
.description("Scan compliance posture against policies")
|
|
128
|
+
.option("--json", "Output as JSON")
|
|
129
|
+
.action(async (framework, options) => {
|
|
130
|
+
try {
|
|
131
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
132
|
+
if (!ctx.db) {
|
|
133
|
+
logger.error("Database not available");
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
const db = ctx.db.getDatabase();
|
|
137
|
+
ensureComplianceTables(db);
|
|
138
|
+
|
|
139
|
+
const result = scanCompliance(db, framework);
|
|
140
|
+
if (options.json) {
|
|
141
|
+
console.log(JSON.stringify(result, null, 2));
|
|
142
|
+
} else {
|
|
143
|
+
logger.log(` ${chalk.bold("Framework:")} ${result.framework}`);
|
|
144
|
+
logger.log(` ${chalk.bold("Score:")} ${result.score}%`);
|
|
145
|
+
logger.log(
|
|
146
|
+
` ${chalk.bold("Passed:")} ${result.passed}/${result.total}`,
|
|
147
|
+
);
|
|
148
|
+
logger.log(
|
|
149
|
+
` ${chalk.bold("Failed:")} ${result.failed}/${result.total}`,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
await shutdown();
|
|
154
|
+
} catch (err) {
|
|
155
|
+
logger.error(`Failed: ${err.message}`);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// compliance policies
|
|
161
|
+
compliance
|
|
162
|
+
.command("policies")
|
|
163
|
+
.description("List compliance policies")
|
|
164
|
+
.option("--framework <fw>", "Filter by framework")
|
|
165
|
+
.option("--json", "Output as JSON")
|
|
166
|
+
.action(async (options) => {
|
|
167
|
+
try {
|
|
168
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
169
|
+
if (!ctx.db) {
|
|
170
|
+
logger.error("Database not available");
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
const db = ctx.db.getDatabase();
|
|
174
|
+
ensureComplianceTables(db);
|
|
175
|
+
|
|
176
|
+
const policies = listPolicies(db, { framework: options.framework });
|
|
177
|
+
if (options.json) {
|
|
178
|
+
console.log(JSON.stringify(policies, null, 2));
|
|
179
|
+
} else if (policies.length === 0) {
|
|
180
|
+
logger.info("No policies configured.");
|
|
181
|
+
} else {
|
|
182
|
+
for (const p of policies) {
|
|
183
|
+
logger.log(
|
|
184
|
+
` ${chalk.cyan(p.id.slice(0, 8))} ${p.name} [${p.type}] ${p.framework} severity=${p.severity}`,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
await shutdown();
|
|
190
|
+
} catch (err) {
|
|
191
|
+
logger.error(`Failed: ${err.message}`);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// compliance check-access
|
|
197
|
+
compliance
|
|
198
|
+
.command("check-access <resource> <action> <role>")
|
|
199
|
+
.description("Check RBAC access permission")
|
|
200
|
+
.option("--json", "Output as JSON")
|
|
201
|
+
.action(async (resource, action, role, options) => {
|
|
202
|
+
try {
|
|
203
|
+
const result = checkAccess(resource, action, role);
|
|
204
|
+
if (options.json) {
|
|
205
|
+
console.log(JSON.stringify(result, null, 2));
|
|
206
|
+
} else {
|
|
207
|
+
logger.log(
|
|
208
|
+
` ${chalk.bold("Access:")} ${result.granted ? chalk.green("GRANTED") : chalk.red("DENIED")} (${role} → ${action} on ${resource})`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
} catch (err) {
|
|
212
|
+
logger.error(`Failed: ${err.message}`);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAO Governance v2 commands
|
|
3
|
+
* chainlesschain dao propose|vote|delegate|execute|treasury|allocate|stats|configure
|
|
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
|
+
ensureDAOv2Tables,
|
|
11
|
+
propose,
|
|
12
|
+
vote,
|
|
13
|
+
delegate,
|
|
14
|
+
execute,
|
|
15
|
+
getTreasury,
|
|
16
|
+
allocate,
|
|
17
|
+
depositToTreasury,
|
|
18
|
+
getStats,
|
|
19
|
+
configure,
|
|
20
|
+
} from "../lib/dao-governance.js";
|
|
21
|
+
|
|
22
|
+
export function registerDaoCommand(program) {
|
|
23
|
+
const dao = program
|
|
24
|
+
.command("dao")
|
|
25
|
+
.description("DAO Governance v2 — proposals, voting, delegation, treasury");
|
|
26
|
+
|
|
27
|
+
// dao propose
|
|
28
|
+
dao
|
|
29
|
+
.command("propose <title>")
|
|
30
|
+
.description("Create a governance proposal")
|
|
31
|
+
.option("-d, --description <text>", "Proposal description")
|
|
32
|
+
.option("-p, --proposer <id>", "Proposer identity", "cli-user")
|
|
33
|
+
.option(
|
|
34
|
+
"--voting-type <type>",
|
|
35
|
+
"Voting type: simple or quadratic",
|
|
36
|
+
"simple",
|
|
37
|
+
)
|
|
38
|
+
.action(async (title, options) => {
|
|
39
|
+
try {
|
|
40
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
41
|
+
if (!ctx.db) {
|
|
42
|
+
logger.error("Database not available");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
const db = ctx.db.getDatabase();
|
|
46
|
+
ensureDAOv2Tables(db);
|
|
47
|
+
|
|
48
|
+
const result = propose(
|
|
49
|
+
db,
|
|
50
|
+
title,
|
|
51
|
+
options.description,
|
|
52
|
+
options.proposer,
|
|
53
|
+
{
|
|
54
|
+
votingType: options.votingType,
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
logger.success("Proposal created");
|
|
58
|
+
logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(result.id)}`);
|
|
59
|
+
logger.log(` ${chalk.bold("Title:")} ${result.title}`);
|
|
60
|
+
logger.log(` ${chalk.bold("Status:")} ${result.status}`);
|
|
61
|
+
logger.log(` ${chalk.bold("Type:")} ${result.votingType}`);
|
|
62
|
+
logger.log(` ${chalk.bold("Ends:")} ${result.endsAt}`);
|
|
63
|
+
|
|
64
|
+
await shutdown();
|
|
65
|
+
} catch (err) {
|
|
66
|
+
logger.error(`Failed: ${err.message}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// dao vote
|
|
72
|
+
dao
|
|
73
|
+
.command("vote <proposal-id> <direction>")
|
|
74
|
+
.description('Vote on a proposal (direction: "for" or "against")')
|
|
75
|
+
.option("-v, --voter <id>", "Voter identity", "cli-user")
|
|
76
|
+
.option("-w, --weight <n>", "Vote weight", "1")
|
|
77
|
+
.action(async (proposalId, direction, options) => {
|
|
78
|
+
try {
|
|
79
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
80
|
+
if (!ctx.db) {
|
|
81
|
+
logger.error("Database not available");
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
const db = ctx.db.getDatabase();
|
|
85
|
+
ensureDAOv2Tables(db);
|
|
86
|
+
|
|
87
|
+
const result = vote(
|
|
88
|
+
db,
|
|
89
|
+
proposalId,
|
|
90
|
+
options.voter,
|
|
91
|
+
direction,
|
|
92
|
+
parseFloat(options.weight),
|
|
93
|
+
);
|
|
94
|
+
logger.success("Vote recorded");
|
|
95
|
+
logger.log(
|
|
96
|
+
` ${chalk.bold("Vote ID:")} ${chalk.cyan(result.voteId)}`,
|
|
97
|
+
);
|
|
98
|
+
logger.log(` ${chalk.bold("Direction:")} ${result.direction}`);
|
|
99
|
+
logger.log(` ${chalk.bold("Weight:")} ${result.weight}`);
|
|
100
|
+
|
|
101
|
+
await shutdown();
|
|
102
|
+
} catch (err) {
|
|
103
|
+
logger.error(`Failed: ${err.message}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// dao delegate
|
|
109
|
+
dao
|
|
110
|
+
.command("delegate <delegator> <delegate-to>")
|
|
111
|
+
.description("Delegate voting power")
|
|
112
|
+
.option("-w, --weight <n>", "Delegation weight", "1")
|
|
113
|
+
.action(async (delegator, delegateTo, options) => {
|
|
114
|
+
try {
|
|
115
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
116
|
+
if (!ctx.db) {
|
|
117
|
+
logger.error("Database not available");
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
const db = ctx.db.getDatabase();
|
|
121
|
+
ensureDAOv2Tables(db);
|
|
122
|
+
|
|
123
|
+
const result = delegate(
|
|
124
|
+
db,
|
|
125
|
+
delegator,
|
|
126
|
+
delegateTo,
|
|
127
|
+
parseFloat(options.weight),
|
|
128
|
+
);
|
|
129
|
+
logger.success("Delegation set");
|
|
130
|
+
logger.log(` ${chalk.bold("From:")} ${result.delegator}`);
|
|
131
|
+
logger.log(` ${chalk.bold("To:")} ${result.delegate}`);
|
|
132
|
+
logger.log(` ${chalk.bold("Weight:")} ${result.weight}`);
|
|
133
|
+
|
|
134
|
+
await shutdown();
|
|
135
|
+
} catch (err) {
|
|
136
|
+
logger.error(`Failed: ${err.message}`);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// dao execute
|
|
142
|
+
dao
|
|
143
|
+
.command("execute <proposal-id>")
|
|
144
|
+
.description("Execute a passed proposal")
|
|
145
|
+
.action(async (proposalId) => {
|
|
146
|
+
try {
|
|
147
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
148
|
+
if (!ctx.db) {
|
|
149
|
+
logger.error("Database not available");
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
const db = ctx.db.getDatabase();
|
|
153
|
+
ensureDAOv2Tables(db);
|
|
154
|
+
|
|
155
|
+
const result = execute(db, proposalId);
|
|
156
|
+
logger.success(`Proposal ${chalk.cyan(result.proposalId)} executed`);
|
|
157
|
+
|
|
158
|
+
await shutdown();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
logger.error(`Failed: ${err.message}`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// dao treasury
|
|
166
|
+
dao
|
|
167
|
+
.command("treasury")
|
|
168
|
+
.description("Show treasury balance and allocations")
|
|
169
|
+
.option("--json", "Output as JSON")
|
|
170
|
+
.action(async (options) => {
|
|
171
|
+
try {
|
|
172
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
173
|
+
if (!ctx.db) {
|
|
174
|
+
logger.error("Database not available");
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
const db = ctx.db.getDatabase();
|
|
178
|
+
ensureDAOv2Tables(db);
|
|
179
|
+
|
|
180
|
+
const result = getTreasury();
|
|
181
|
+
if (options.json) {
|
|
182
|
+
console.log(JSON.stringify(result, null, 2));
|
|
183
|
+
} else {
|
|
184
|
+
logger.log(` ${chalk.bold("Balance:")} ${result.balance}`);
|
|
185
|
+
logger.log(
|
|
186
|
+
` ${chalk.bold("Allocations:")} ${result.allocations.length}`,
|
|
187
|
+
);
|
|
188
|
+
for (const a of result.allocations) {
|
|
189
|
+
logger.log(
|
|
190
|
+
` ${chalk.cyan(a.id.slice(0, 12))} ${a.amount} — ${a.description || "N/A"}`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
await shutdown();
|
|
196
|
+
} catch (err) {
|
|
197
|
+
logger.error(`Failed: ${err.message}`);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// dao allocate
|
|
203
|
+
dao
|
|
204
|
+
.command("allocate <proposal-id> <amount>")
|
|
205
|
+
.description("Allocate treasury funds to a proposal")
|
|
206
|
+
.option("-d, --description <text>", "Allocation description")
|
|
207
|
+
.action(async (proposalId, amount, options) => {
|
|
208
|
+
try {
|
|
209
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
210
|
+
if (!ctx.db) {
|
|
211
|
+
logger.error("Database not available");
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
const db = ctx.db.getDatabase();
|
|
215
|
+
ensureDAOv2Tables(db);
|
|
216
|
+
|
|
217
|
+
const result = allocate(
|
|
218
|
+
db,
|
|
219
|
+
proposalId,
|
|
220
|
+
parseFloat(amount),
|
|
221
|
+
options.description,
|
|
222
|
+
);
|
|
223
|
+
logger.success("Funds allocated");
|
|
224
|
+
logger.log(` ${chalk.bold("ID:")} ${chalk.cyan(result.id)}`);
|
|
225
|
+
logger.log(` ${chalk.bold("Amount:")} ${result.amount}`);
|
|
226
|
+
logger.log(` ${chalk.bold("Proposal:")} ${result.proposalId}`);
|
|
227
|
+
|
|
228
|
+
await shutdown();
|
|
229
|
+
} catch (err) {
|
|
230
|
+
logger.error(`Failed: ${err.message}`);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// dao stats
|
|
236
|
+
dao
|
|
237
|
+
.command("stats")
|
|
238
|
+
.description("Show governance statistics")
|
|
239
|
+
.option("--json", "Output as JSON")
|
|
240
|
+
.action(async (options) => {
|
|
241
|
+
try {
|
|
242
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
243
|
+
if (!ctx.db) {
|
|
244
|
+
logger.error("Database not available");
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
const db = ctx.db.getDatabase();
|
|
248
|
+
ensureDAOv2Tables(db);
|
|
249
|
+
|
|
250
|
+
const result = getStats();
|
|
251
|
+
if (options.json) {
|
|
252
|
+
console.log(JSON.stringify(result, null, 2));
|
|
253
|
+
} else {
|
|
254
|
+
logger.log(
|
|
255
|
+
` ${chalk.bold("Total Proposals:")} ${result.totalProposals}`,
|
|
256
|
+
);
|
|
257
|
+
logger.log(` ${chalk.bold("Active:")} ${result.active}`);
|
|
258
|
+
logger.log(` ${chalk.bold("Executed:")} ${result.executed}`);
|
|
259
|
+
logger.log(
|
|
260
|
+
` ${chalk.bold("Delegations:")} ${result.delegations}`,
|
|
261
|
+
);
|
|
262
|
+
logger.log(` ${chalk.bold("Treasury:")} ${result.treasury}`);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
await shutdown();
|
|
266
|
+
} catch (err) {
|
|
267
|
+
logger.error(`Failed: ${err.message}`);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// dao configure
|
|
273
|
+
dao
|
|
274
|
+
.command("configure")
|
|
275
|
+
.description("Update governance configuration")
|
|
276
|
+
.option("--voting-period <ms>", "Voting period in milliseconds")
|
|
277
|
+
.option("--quorum <ratio>", "Quorum ratio (0-1)")
|
|
278
|
+
.option("--execution-delay <ms>", "Execution delay in milliseconds")
|
|
279
|
+
.action(async (options) => {
|
|
280
|
+
try {
|
|
281
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
282
|
+
if (!ctx.db) {
|
|
283
|
+
logger.error("Database not available");
|
|
284
|
+
process.exit(1);
|
|
285
|
+
}
|
|
286
|
+
const db = ctx.db.getDatabase();
|
|
287
|
+
ensureDAOv2Tables(db);
|
|
288
|
+
|
|
289
|
+
const cfg = {};
|
|
290
|
+
if (options.votingPeriod)
|
|
291
|
+
cfg.votingPeriod = parseInt(options.votingPeriod);
|
|
292
|
+
if (options.quorum) cfg.quorum = parseFloat(options.quorum);
|
|
293
|
+
if (options.executionDelay)
|
|
294
|
+
cfg.executionDelay = parseInt(options.executionDelay);
|
|
295
|
+
|
|
296
|
+
const result = configure(cfg);
|
|
297
|
+
logger.success("Configuration updated");
|
|
298
|
+
logger.log(
|
|
299
|
+
` ${chalk.bold("Voting Period:")} ${result.votingPeriod}ms`,
|
|
300
|
+
);
|
|
301
|
+
logger.log(` ${chalk.bold("Quorum:")} ${result.quorum}`);
|
|
302
|
+
logger.log(
|
|
303
|
+
` ${chalk.bold("Execution Delay:")} ${result.executionDelay}ms`,
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
await shutdown();
|
|
307
|
+
} catch (err) {
|
|
308
|
+
logger.error(`Failed: ${err.message}`);
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|