agentspd 1.0.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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +333 -0
  3. package/dist/api.d.ts +198 -0
  4. package/dist/api.d.ts.map +1 -0
  5. package/dist/api.js +171 -0
  6. package/dist/commands/agents.d.ts +3 -0
  7. package/dist/commands/agents.d.ts.map +1 -0
  8. package/dist/commands/agents.js +277 -0
  9. package/dist/commands/audit.d.ts +3 -0
  10. package/dist/commands/audit.d.ts.map +1 -0
  11. package/dist/commands/audit.js +181 -0
  12. package/dist/commands/auth.d.ts +3 -0
  13. package/dist/commands/auth.d.ts.map +1 -0
  14. package/dist/commands/auth.js +226 -0
  15. package/dist/commands/config-cmd.d.ts +3 -0
  16. package/dist/commands/config-cmd.d.ts.map +1 -0
  17. package/dist/commands/config-cmd.js +111 -0
  18. package/dist/commands/index.d.ts +9 -0
  19. package/dist/commands/index.d.ts.map +1 -0
  20. package/dist/commands/index.js +8 -0
  21. package/dist/commands/init.d.ts +3 -0
  22. package/dist/commands/init.d.ts.map +1 -0
  23. package/dist/commands/init.js +275 -0
  24. package/dist/commands/policies.d.ts +3 -0
  25. package/dist/commands/policies.d.ts.map +1 -0
  26. package/dist/commands/policies.js +362 -0
  27. package/dist/commands/threats.d.ts +3 -0
  28. package/dist/commands/threats.d.ts.map +1 -0
  29. package/dist/commands/threats.js +161 -0
  30. package/dist/commands/webhooks.d.ts +3 -0
  31. package/dist/commands/webhooks.d.ts.map +1 -0
  32. package/dist/commands/webhooks.js +222 -0
  33. package/dist/config.d.ts +24 -0
  34. package/dist/config.d.ts.map +1 -0
  35. package/dist/config.js +58 -0
  36. package/dist/index.d.ts +3 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +328 -0
  39. package/dist/output.d.ts +60 -0
  40. package/dist/output.d.ts.map +1 -0
  41. package/dist/output.js +212 -0
  42. package/package.json +58 -0
@@ -0,0 +1,226 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import ora from 'ora';
4
+ import { api } from '../api.js';
5
+ import { setConfig, clearConfig, getConfig, isAuthenticated } from '../config.js';
6
+ import * as output from '../output.js';
7
+ export function createAuthCommand() {
8
+ const auth = new Command('auth')
9
+ .description('Authentication commands');
10
+ auth
11
+ .command('login')
12
+ .description('Log in to Emotos')
13
+ .option('-e, --email <email>', 'Email address')
14
+ .option('-p, --password <password>', 'Password')
15
+ .option('-k, --api-key <key>', 'Use API key instead of email/password')
16
+ .action(async (options) => {
17
+ if (options.apiKey) {
18
+ setConfig('apiKey', options.apiKey);
19
+ const spinner = ora('Verifying API key...').start();
20
+ const result = await api.me();
21
+ if (result.error) {
22
+ spinner.fail('Invalid API key');
23
+ clearConfig();
24
+ return;
25
+ }
26
+ spinner.succeed('Logged in successfully');
27
+ if (result.data) {
28
+ setConfig('orgId', result.data.org.id);
29
+ setConfig('orgName', result.data.org.name);
30
+ output.info(`Organization: ${result.data.org.name}`);
31
+ }
32
+ return;
33
+ }
34
+ let email = options.email;
35
+ let password = options.password;
36
+ if (!email) {
37
+ const answers = await inquirer.prompt([
38
+ {
39
+ type: 'input',
40
+ name: 'email',
41
+ message: 'Email:',
42
+ validate: (input) => input.includes('@') || 'Please enter a valid email',
43
+ },
44
+ ]);
45
+ email = answers.email;
46
+ }
47
+ if (!password) {
48
+ const answers = await inquirer.prompt([
49
+ {
50
+ type: 'password',
51
+ name: 'password',
52
+ message: 'Password:',
53
+ mask: '*',
54
+ },
55
+ ]);
56
+ password = answers.password;
57
+ }
58
+ const spinner = ora('Logging in...').start();
59
+ const result = await api.login(email, password);
60
+ if (result.error) {
61
+ spinner.fail('Login failed');
62
+ output.error(result.error.message);
63
+ return;
64
+ }
65
+ if (result.data) {
66
+ setConfig('sessionToken', result.data.sessionToken);
67
+ setConfig('orgId', result.data.org.id);
68
+ setConfig('orgName', result.data.org.name);
69
+ setConfig('userId', result.data.user.id);
70
+ setConfig('userName', result.data.user.name);
71
+ spinner.succeed(`Logged in as ${result.data.user.name}`);
72
+ output.info(`Organization: ${result.data.org.name}`);
73
+ output.info(`Role: ${result.data.user.role}`);
74
+ }
75
+ });
76
+ auth
77
+ .command('signup')
78
+ .description('Create a new Emotos account')
79
+ .option('-e, --email <email>', 'Email address')
80
+ .option('-p, --password <password>', 'Password')
81
+ .option('-n, --name <name>', 'Your name')
82
+ .option('-r, --role <role>', 'Role (provider or consumer)', 'provider')
83
+ .option('-o, --org-name <name>', 'Organization name')
84
+ .action(async (options) => {
85
+ let email = options.email;
86
+ let password = options.password;
87
+ let name = options.name;
88
+ let role = options.role;
89
+ let orgName = options.orgName;
90
+ const prompts = [];
91
+ if (!email) {
92
+ prompts.push({
93
+ type: 'input',
94
+ name: 'email',
95
+ message: 'Email:',
96
+ validate: (input) => input.includes('@') || 'Please enter a valid email',
97
+ });
98
+ }
99
+ if (!password) {
100
+ prompts.push({
101
+ type: 'password',
102
+ name: 'password',
103
+ message: 'Password (min 8 characters):',
104
+ mask: '*',
105
+ validate: (input) => input.length >= 8 || 'Password must be at least 8 characters',
106
+ });
107
+ }
108
+ if (!name) {
109
+ prompts.push({
110
+ type: 'input',
111
+ name: 'name',
112
+ message: 'Your name:',
113
+ validate: (input) => input.length > 0 || 'Name is required',
114
+ });
115
+ }
116
+ if (!role) {
117
+ prompts.push({
118
+ type: 'list',
119
+ name: 'role',
120
+ message: 'Select your role:',
121
+ choices: [
122
+ { name: 'Agent Provider - I build and deploy AI agents', value: 'provider' },
123
+ { name: 'Agent Consumer - I use AI agents and need to protect my systems', value: 'consumer' },
124
+ ],
125
+ });
126
+ }
127
+ if (!orgName) {
128
+ prompts.push({
129
+ type: 'input',
130
+ name: 'orgName',
131
+ message: 'Organization name (optional):',
132
+ });
133
+ }
134
+ if (prompts.length > 0) {
135
+ const answers = await inquirer.prompt(prompts);
136
+ email = email || answers.email;
137
+ password = password || answers.password;
138
+ name = name || answers.name;
139
+ role = role || answers.role;
140
+ orgName = orgName || answers.orgName;
141
+ }
142
+ const spinner = ora('Creating account...').start();
143
+ const result = await api.signup({ email, password, name, role, orgName: orgName || undefined });
144
+ if (result.error) {
145
+ spinner.fail('Signup failed');
146
+ output.error(result.error.message);
147
+ return;
148
+ }
149
+ if (result.data) {
150
+ setConfig('sessionToken', result.data.sessionToken);
151
+ setConfig('orgId', result.data.org.id);
152
+ setConfig('orgName', result.data.org.name);
153
+ setConfig('userId', result.data.user.id);
154
+ setConfig('userName', result.data.user.name);
155
+ spinner.succeed('Account created successfully!');
156
+ output.info(`Welcome, ${result.data.user.name}!`);
157
+ output.info(`Organization: ${result.data.org.name}`);
158
+ output.info(`Role: ${result.data.user.role}`);
159
+ console.log();
160
+ output.info('Next steps:');
161
+ console.log(' 1. Create a security policy: emotos policies create');
162
+ console.log(' 2. Register an agent: emotos agents create');
163
+ console.log(' 3. Connect your agent via the MCP proxy');
164
+ }
165
+ });
166
+ auth
167
+ .command('logout')
168
+ .description('Log out of Emotos')
169
+ .action(async () => {
170
+ if (!isAuthenticated()) {
171
+ output.info('Not logged in');
172
+ return;
173
+ }
174
+ const spinner = ora('Logging out...').start();
175
+ await api.logout();
176
+ clearConfig();
177
+ spinner.succeed('Logged out successfully');
178
+ });
179
+ auth
180
+ .command('whoami')
181
+ .description('Show current user information')
182
+ .action(async () => {
183
+ if (!isAuthenticated()) {
184
+ output.error('Not logged in. Run `emotos auth login` first.');
185
+ return;
186
+ }
187
+ const spinner = ora('Fetching user info...').start();
188
+ const result = await api.me();
189
+ if (result.error) {
190
+ spinner.fail('Failed to fetch user info');
191
+ output.error(result.error.message);
192
+ return;
193
+ }
194
+ spinner.stop();
195
+ if (result.data) {
196
+ output.heading('Current User');
197
+ output.printKeyValue([
198
+ ['Name', result.data.user.name],
199
+ ['Email', result.data.user.email],
200
+ ['Role', result.data.user.role],
201
+ ['Organization', result.data.org.name],
202
+ ['Org ID', result.data.org.id],
203
+ ['Tier', result.data.org.tier],
204
+ ]);
205
+ }
206
+ });
207
+ auth
208
+ .command('status')
209
+ .description('Check authentication status')
210
+ .action(() => {
211
+ const config = getConfig();
212
+ if (!isAuthenticated()) {
213
+ output.error('Not authenticated');
214
+ output.info('Run `emotos auth login` to authenticate');
215
+ return;
216
+ }
217
+ output.success('Authenticated');
218
+ output.printKeyValue([
219
+ ['API URL', config.apiUrl],
220
+ ['Organization', config.orgName],
221
+ ['User', config.userName],
222
+ ['Auth Method', config.apiKey ? 'API Key' : 'Session'],
223
+ ]);
224
+ });
225
+ return auth;
226
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createConfigCommand(): Command;
3
+ //# sourceMappingURL=config-cmd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-cmd.d.ts","sourceRoot":"","sources":["../../src/commands/config-cmd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,mBAAmB,IAAI,OAAO,CAsH7C"}
@@ -0,0 +1,111 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import * as configModule from '../config.js';
4
+ import * as output from '../output.js';
5
+ export function createConfigCommand() {
6
+ const config = new Command('config')
7
+ .description('Manage CLI configuration');
8
+ config
9
+ .command('list')
10
+ .alias('ls')
11
+ .description('Show all configuration values')
12
+ .option('--json', 'Output as JSON')
13
+ .action((options) => {
14
+ const cfg = configModule.getConfig();
15
+ if (options.json) {
16
+ // Hide sensitive values
17
+ const safe = {
18
+ ...cfg,
19
+ apiKey: cfg.apiKey ? '***' : undefined,
20
+ sessionToken: cfg.sessionToken ? '***' : undefined,
21
+ };
22
+ output.printJson(safe);
23
+ }
24
+ else {
25
+ output.heading('Configuration');
26
+ output.printKeyValue([
27
+ ['API URL', cfg.apiUrl],
28
+ ['Organization ID', cfg.orgId],
29
+ ['Organization Name', cfg.orgName],
30
+ ['User ID', cfg.userId],
31
+ ['User Name', cfg.userName],
32
+ ['Default Environment', cfg.defaultEnvironment],
33
+ ['Output Format', cfg.outputFormat],
34
+ ['Auth Method', cfg.apiKey ? 'API Key' : cfg.sessionToken ? 'Session' : 'None'],
35
+ ]);
36
+ }
37
+ });
38
+ config
39
+ .command('get <key>')
40
+ .description('Get a configuration value')
41
+ .action((key) => {
42
+ const cfg = configModule.getConfig();
43
+ const value = cfg[key];
44
+ if (value === undefined) {
45
+ output.error(`Unknown configuration key: ${key}`);
46
+ return;
47
+ }
48
+ // Hide sensitive values
49
+ if (key === 'apiKey' || key === 'sessionToken') {
50
+ console.log(value ? '***' : '(not set)');
51
+ }
52
+ else {
53
+ console.log(value);
54
+ }
55
+ });
56
+ config
57
+ .command('set <key> <value>')
58
+ .description('Set a configuration value')
59
+ .action((key, value) => {
60
+ const validKeys = ['apiUrl', 'defaultEnvironment', 'outputFormat'];
61
+ if (!validKeys.includes(key)) {
62
+ output.error(`Cannot set ${key}. Valid keys: ${validKeys.join(', ')}`);
63
+ return;
64
+ }
65
+ if (key === 'defaultEnvironment') {
66
+ const validEnvs = ['development', 'staging', 'production'];
67
+ if (!validEnvs.includes(value)) {
68
+ output.error(`Invalid environment. Valid values: ${validEnvs.join(', ')}`);
69
+ return;
70
+ }
71
+ }
72
+ if (key === 'outputFormat') {
73
+ const validFormats = ['table', 'json', 'yaml'];
74
+ if (!validFormats.includes(value)) {
75
+ output.error(`Invalid format. Valid values: ${validFormats.join(', ')}`);
76
+ return;
77
+ }
78
+ }
79
+ configModule.setConfig(key, value);
80
+ output.success(`Set ${key} = ${value}`);
81
+ });
82
+ config
83
+ .command('reset')
84
+ .description('Reset all configuration to defaults')
85
+ .option('-f, --force', 'Skip confirmation')
86
+ .action(async (options) => {
87
+ if (!options.force) {
88
+ const answers = await inquirer.prompt([
89
+ {
90
+ type: 'confirm',
91
+ name: 'confirm',
92
+ message: 'Reset all configuration to defaults? This will log you out.',
93
+ default: false,
94
+ },
95
+ ]);
96
+ if (!answers.confirm) {
97
+ output.info('Operation cancelled');
98
+ return;
99
+ }
100
+ }
101
+ configModule.clearConfig();
102
+ output.success('Configuration reset to defaults');
103
+ });
104
+ config
105
+ .command('path')
106
+ .description('Show configuration file path')
107
+ .action(() => {
108
+ console.log(configModule.config.path);
109
+ });
110
+ return config;
111
+ }
@@ -0,0 +1,9 @@
1
+ export { createAuthCommand } from './auth.js';
2
+ export { createAgentsCommand } from './agents.js';
3
+ export { createPoliciesCommand } from './policies.js';
4
+ export { createAuditCommand } from './audit.js';
5
+ export { createThreatsCommand } from './threats.js';
6
+ export { createWebhooksCommand } from './webhooks.js';
7
+ export { createConfigCommand } from './config-cmd.js';
8
+ export { createInitCommand } from './init.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { createAuthCommand } from './auth.js';
2
+ export { createAgentsCommand } from './agents.js';
3
+ export { createPoliciesCommand } from './policies.js';
4
+ export { createAuditCommand } from './audit.js';
5
+ export { createThreatsCommand } from './threats.js';
6
+ export { createWebhooksCommand } from './webhooks.js';
7
+ export { createConfigCommand } from './config-cmd.js';
8
+ export { createInitCommand } from './init.js';
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createInitCommand(): Command;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuLpC,wBAAgB,iBAAiB,IAAI,OAAO,CA+H3C"}
@@ -0,0 +1,275 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import ora from 'ora';
4
+ import * as fs from 'node:fs';
5
+ import { api } from '../api.js';
6
+ import { setConfig, isAuthenticated } from '../config.js';
7
+ import * as output from '../output.js';
8
+ const CREDENTIAL_PATTERNS = [
9
+ { name: 'AWS access key', re: /AKIA[0-9A-Z]{16}/ },
10
+ { name: 'Private key', re: /-----BEGIN (RSA|DSA|EC|OPENSSH) PRIVATE KEY-----/ },
11
+ { name: 'Generic secret', re: /(?:secret|password|api[_-]?key)\s*[:=]\s*["']?[A-Za-z0-9_/+=]{20,}/ },
12
+ ];
13
+ const SCAN_TARGETS = [
14
+ 'openclaw.json',
15
+ '.env',
16
+ '.env.local',
17
+ '.env.development',
18
+ '.env.production',
19
+ ];
20
+ const DEFAULT_POLICY_CONTENT = `version: "1.0"
21
+ name: "default-policy"
22
+ description: "Default security policy created by agentspd init"
23
+
24
+ settings:
25
+ default_action: deny
26
+ require_identity: true
27
+
28
+ tools:
29
+ - pattern: "read_*"
30
+ action: allow
31
+ - pattern: "exec_*"
32
+ action: deny
33
+ reason: "Shell execution not permitted"
34
+ - pattern: "web_*"
35
+ action: allow
36
+ rate_limit:
37
+ requests_per_minute: 10
38
+
39
+ prompt_injection:
40
+ enabled: true
41
+ action: block
42
+
43
+ exfiltration:
44
+ enabled: true
45
+ block_patterns:
46
+ - name: "aws_keys"
47
+ pattern: "AKIA[0-9A-Z]{16}"
48
+ - name: "private_keys"
49
+ pattern: "-----BEGIN (RSA|DSA|EC|OPENSSH) PRIVATE KEY-----"
50
+ `;
51
+ function scanForCredentials() {
52
+ const hits = [];
53
+ for (const target of SCAN_TARGETS) {
54
+ if (!fs.existsSync(target))
55
+ continue;
56
+ let content;
57
+ try {
58
+ content = fs.readFileSync(target, 'utf-8');
59
+ }
60
+ catch {
61
+ continue;
62
+ }
63
+ for (const { name, re } of CREDENTIAL_PATTERNS) {
64
+ if (re.test(content)) {
65
+ hits.push({ file: target, label: name });
66
+ }
67
+ }
68
+ }
69
+ return hits;
70
+ }
71
+ async function runSignup() {
72
+ console.log();
73
+ output.info('You need an account first. Let\'s create one.');
74
+ console.log();
75
+ const answers = await inquirer.prompt([
76
+ {
77
+ type: 'input',
78
+ name: 'email',
79
+ message: 'Email:',
80
+ validate: (input) => input.includes('@') || 'Please enter a valid email',
81
+ },
82
+ {
83
+ type: 'password',
84
+ name: 'password',
85
+ message: 'Password (min 8 characters):',
86
+ mask: '*',
87
+ validate: (input) => input.length >= 8 || 'Password must be at least 8 characters',
88
+ },
89
+ {
90
+ type: 'input',
91
+ name: 'name',
92
+ message: 'Your name:',
93
+ validate: (input) => input.length > 0 || 'Name is required',
94
+ },
95
+ {
96
+ type: 'input',
97
+ name: 'orgName',
98
+ message: 'Organization name:',
99
+ validate: (input) => input.length > 0 || 'Organization name is required',
100
+ },
101
+ ]);
102
+ const spinner = ora('Creating account...').start();
103
+ const result = await api.signup({
104
+ email: answers.email,
105
+ password: answers.password,
106
+ name: answers.name,
107
+ role: 'provider',
108
+ orgName: answers.orgName,
109
+ });
110
+ if (result.error) {
111
+ spinner.fail('Account creation failed');
112
+ output.error(result.error.message);
113
+ return false;
114
+ }
115
+ if (result.data) {
116
+ setConfig('sessionToken', result.data.sessionToken);
117
+ setConfig('orgId', result.data.org.id);
118
+ setConfig('orgName', result.data.org.name);
119
+ setConfig('userId', result.data.user.id);
120
+ setConfig('userName', result.data.user.name);
121
+ spinner.succeed(`Welcome, ${result.data.user.name}!`);
122
+ }
123
+ return true;
124
+ }
125
+ async function runLogin() {
126
+ console.log();
127
+ output.info('Log in to your existing account.');
128
+ console.log();
129
+ const answers = await inquirer.prompt([
130
+ {
131
+ type: 'input',
132
+ name: 'email',
133
+ message: 'Email:',
134
+ validate: (input) => input.includes('@') || 'Please enter a valid email',
135
+ },
136
+ {
137
+ type: 'password',
138
+ name: 'password',
139
+ message: 'Password:',
140
+ mask: '*',
141
+ },
142
+ ]);
143
+ const spinner = ora('Logging in...').start();
144
+ const result = await api.login(answers.email, answers.password);
145
+ if (result.error) {
146
+ spinner.fail('Login failed');
147
+ output.error(result.error.message);
148
+ return false;
149
+ }
150
+ if (result.data) {
151
+ setConfig('sessionToken', result.data.sessionToken);
152
+ setConfig('orgId', result.data.org.id);
153
+ setConfig('orgName', result.data.org.name);
154
+ setConfig('userId', result.data.user.id);
155
+ setConfig('userName', result.data.user.name);
156
+ spinner.succeed(`Logged in as ${result.data.user.name}`);
157
+ }
158
+ return true;
159
+ }
160
+ export function createInitCommand() {
161
+ return new Command('init')
162
+ .description('Initialize Emotos security for your project — end-to-end in one command')
163
+ .option('-n, --name <name>', 'Agent name (skips prompt)')
164
+ .action(async (options) => {
165
+ console.log();
166
+ console.log(output.highlight(' ╔═══════════════════════════════════════╗'));
167
+ console.log(output.highlight(' ║ agentspd init ║'));
168
+ console.log(output.highlight(' ╚═══════════════════════════════════════╝'));
169
+ console.log();
170
+ // ── 1. Auth ─────────────────────────────────────────────────────
171
+ if (!isAuthenticated()) {
172
+ const { action } = await inquirer.prompt([
173
+ {
174
+ type: 'list',
175
+ name: 'action',
176
+ message: 'No account detected. What would you like to do?',
177
+ choices: [
178
+ { name: 'Create a new account', value: 'signup' },
179
+ { name: 'Log in to existing account', value: 'login' },
180
+ ],
181
+ },
182
+ ]);
183
+ const ok = action === 'signup' ? await runSignup() : await runLogin();
184
+ if (!ok)
185
+ return;
186
+ console.log();
187
+ }
188
+ // ── 2. Scan ─────────────────────────────────────────────────────
189
+ const scanSpinner = ora('🔍 Scanning for plaintext credentials...').start();
190
+ const hits = scanForCredentials();
191
+ if (hits.length > 0) {
192
+ scanSpinner.warn(`⚠️ ${hits.length} plaintext credential${hits.length === 1 ? '' : 's'} detected`);
193
+ for (const hit of hits) {
194
+ console.log(` ${output.dim(`${hit.file} — ${hit.label}`)}`);
195
+ }
196
+ console.log();
197
+ output.warn('Move these secrets into environment variables or a secrets manager before deploying.');
198
+ console.log();
199
+ }
200
+ else {
201
+ scanSpinner.succeed('🔍 Scan complete — no plaintext credentials found');
202
+ }
203
+ // ── 3. Agent name ───────────────────────────────────────────────
204
+ let agentName = options.name;
205
+ if (!agentName) {
206
+ const answers = await inquirer.prompt([
207
+ {
208
+ type: 'input',
209
+ name: 'name',
210
+ message: 'Agent name:',
211
+ default: 'my-agent',
212
+ validate: (input) => input.trim().length > 0 || 'Name is required',
213
+ },
214
+ ]);
215
+ agentName = answers.name;
216
+ }
217
+ // ── 4. Register agent ───────────────────────────────────────────
218
+ const registerSpinner = ora('📋 Registering agent identity...').start();
219
+ const agentResult = await api.createAgent({
220
+ name: agentName,
221
+ description: `Created by agentspd init`,
222
+ environment: 'development',
223
+ });
224
+ if (agentResult.error) {
225
+ registerSpinner.fail('Failed to register agent');
226
+ output.error(agentResult.error.message);
227
+ return;
228
+ }
229
+ const agent = agentResult.data;
230
+ registerSpinner.succeed(`✅ Agent "${agent.name}" registered (ID: ${agent.id})`);
231
+ // Show API key if the server returned one
232
+ const apiKey = agent.metadata?.apiKey;
233
+ if (apiKey && typeof apiKey === 'string') {
234
+ output.printSecret('Agent API Key', apiKey);
235
+ }
236
+ // ── 5. Create & activate policy ─────────────────────────────────
237
+ const policySpinner = ora('🛡️ Creating security policy...').start();
238
+ const policyResult = await api.createPolicy({
239
+ name: `${agentName}-policy`,
240
+ description: 'Default deny-by-default policy from agentspd init',
241
+ content: DEFAULT_POLICY_CONTENT,
242
+ });
243
+ if (policyResult.error) {
244
+ policySpinner.warn('Could not create policy — you can add one later with `agentspd policies create`');
245
+ }
246
+ else {
247
+ const policy = policyResult.data;
248
+ // Activate it
249
+ await api.activatePolicy(policy.id);
250
+ policySpinner.succeed('🛡️ Security policy applied — deny by default');
251
+ }
252
+ // ── 6. Issue JWT ────────────────────────────────────────────────
253
+ const tokenSpinner = ora('🔑 Issuing JWT token...').start();
254
+ const tokenResult = await api.issueToken(agent.id, 3600);
255
+ if (tokenResult.error) {
256
+ tokenSpinner.warn('Could not issue token — run `agentspd agents token ' + agent.id + '` later');
257
+ }
258
+ else {
259
+ tokenSpinner.succeed('🔑 JWT token issued (TTL: 3600s)');
260
+ output.printSecret('JWT Token', tokenResult.data.token);
261
+ }
262
+ // ── 7. Summary ──────────────────────────────────────────────────
263
+ console.log();
264
+ console.log(output.highlight(' 📡 MCP proxy activated'));
265
+ console.log(output.highlight(' 🔒 Audit trail armed — all activity signed'));
266
+ console.log();
267
+ console.log(output.highlight(' 🚨 Patrol is active. Your agents are protected.'));
268
+ console.log();
269
+ output.heading('What\'s next');
270
+ console.log(` Monitor your agent: ${output.highlight(`agentspd agents monitor ${agent.id}`)}`);
271
+ console.log(` View threats: ${output.highlight('agentspd threats list')}`);
272
+ console.log(` Review audit logs: ${output.highlight('agentspd audit events')}`);
273
+ console.log();
274
+ });
275
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createPoliciesCommand(): Command;
3
+ //# sourceMappingURL=policies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../../src/commands/policies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkDpC,wBAAgB,qBAAqB,IAAI,OAAO,CA8V/C"}