@meltstudio/meltctl 4.26.0 → 4.28.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.
- package/dist/commands/audit.d.ts +1 -0
- package/dist/commands/audit.js +69 -19
- package/dist/commands/init.js +21 -4
- package/dist/index.js +2 -1
- package/package.json +1 -1
package/dist/commands/audit.d.ts
CHANGED
package/dist/commands/audit.js
CHANGED
|
@@ -4,7 +4,12 @@ import path from 'path';
|
|
|
4
4
|
import { getToken, tokenFetch } from '../utils/api.js';
|
|
5
5
|
import { getGitBranch, getGitCommit, getGitRepository, getProjectName, findMdFiles, } from '../utils/git.js';
|
|
6
6
|
function detectAuditType(filename) {
|
|
7
|
-
|
|
7
|
+
const lower = filename.toLowerCase();
|
|
8
|
+
if (lower.includes('security-audit'))
|
|
9
|
+
return 'security-audit';
|
|
10
|
+
if (lower.includes('ux-audit'))
|
|
11
|
+
return 'ux-audit';
|
|
12
|
+
return 'audit';
|
|
8
13
|
}
|
|
9
14
|
async function autoDetectAuditFile() {
|
|
10
15
|
const cwd = process.cwd();
|
|
@@ -13,7 +18,7 @@ async function autoDetectAuditFile() {
|
|
|
13
18
|
if (auditFiles.length > 0) {
|
|
14
19
|
return auditFiles[0] ?? null;
|
|
15
20
|
}
|
|
16
|
-
const candidates = ['AUDIT.md', 'UX-AUDIT.md'];
|
|
21
|
+
const candidates = ['AUDIT.md', 'UX-AUDIT.md', 'SECURITY-AUDIT.md'];
|
|
17
22
|
for (const name of candidates) {
|
|
18
23
|
const filePath = path.join(cwd, name);
|
|
19
24
|
if (await fs.pathExists(filePath)) {
|
|
@@ -86,6 +91,8 @@ export async function auditListCommand(options) {
|
|
|
86
91
|
params.set('type', options.type);
|
|
87
92
|
if (options.repository)
|
|
88
93
|
params.set('repository', options.repository);
|
|
94
|
+
if (options.latest)
|
|
95
|
+
params.set('latest', 'true');
|
|
89
96
|
if (options.limit)
|
|
90
97
|
params.set('limit', options.limit);
|
|
91
98
|
const query = params.toString();
|
|
@@ -106,27 +113,70 @@ export async function auditListCommand(options) {
|
|
|
106
113
|
console.log(chalk.dim('\n No audits found.\n'));
|
|
107
114
|
return;
|
|
108
115
|
}
|
|
109
|
-
console.log(chalk.bold(`\n Audits (${body.count}):\n`));
|
|
110
|
-
console.log(chalk.dim(` ${'TYPE'.padEnd(12)} ${'REPOSITORY'.padEnd(40)} ${'AUTHOR'.padEnd(30)} DATE`));
|
|
111
|
-
console.log();
|
|
112
116
|
const typeLabels = {
|
|
113
117
|
audit: 'Tech Audit',
|
|
114
118
|
'ux-audit': 'UX Audit',
|
|
119
|
+
'security-audit': 'Security',
|
|
115
120
|
};
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
121
|
+
if (options.latest) {
|
|
122
|
+
console.log(chalk.bold(`\n Latest Audits (${body.count}):\n`));
|
|
123
|
+
console.log(chalk.dim(` ${'TYPE'.padEnd(12)} ${'REPOSITORY'.padEnd(40)} ${'AGE'.padEnd(10)} ${'AUTHOR'.padEnd(30)} DATE`));
|
|
124
|
+
console.log();
|
|
125
|
+
for (const r of body.audits) {
|
|
126
|
+
const createdAt = new Date(r.created_at ?? r.createdAt);
|
|
127
|
+
const daysAgo = Math.floor((Date.now() - createdAt.getTime()) / (1000 * 60 * 60 * 24));
|
|
128
|
+
const date = createdAt.toLocaleDateString('en-US', {
|
|
129
|
+
month: 'short',
|
|
130
|
+
day: 'numeric',
|
|
131
|
+
year: 'numeric',
|
|
132
|
+
});
|
|
133
|
+
const repo = r.repository ?? r.project;
|
|
134
|
+
const label = typeLabels[r.type] ?? r.type;
|
|
135
|
+
const typeColor = r.type === 'ux-audit'
|
|
136
|
+
? chalk.yellow
|
|
137
|
+
: r.type === 'security-audit'
|
|
138
|
+
? chalk.red
|
|
139
|
+
: chalk.magenta;
|
|
140
|
+
const ageText = daysAgo === 0 ? 'today' : `${daysAgo}d ago`;
|
|
141
|
+
const isSecurityAudit = r.type === 'security-audit';
|
|
142
|
+
const ageColor = isSecurityAudit
|
|
143
|
+
? daysAgo <= 30
|
|
144
|
+
? chalk.green
|
|
145
|
+
: daysAgo <= 90
|
|
146
|
+
? chalk.yellow
|
|
147
|
+
: chalk.red
|
|
148
|
+
: daysAgo <= 7
|
|
149
|
+
? chalk.green
|
|
150
|
+
: daysAgo <= 30
|
|
151
|
+
? chalk.yellow
|
|
152
|
+
: chalk.red;
|
|
153
|
+
console.log(` ${typeColor(label.padEnd(12))} ${chalk.white(repo.padEnd(40))} ${ageColor(ageText.padEnd(10))} ${chalk.dim(r.author.padEnd(30))} ${chalk.dim(date)}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.log(chalk.bold(`\n Audits (${body.count}):\n`));
|
|
158
|
+
const hdr = ` ${'TYPE'.padEnd(12)} ${'REPOSITORY'.padEnd(40)} ${'AUTHOR'.padEnd(30)} DATE`;
|
|
159
|
+
console.log(chalk.dim(hdr));
|
|
160
|
+
console.log();
|
|
161
|
+
for (const r of body.audits) {
|
|
162
|
+
const date = new Date(r.createdAt).toLocaleDateString('en-US', {
|
|
163
|
+
month: 'short',
|
|
164
|
+
day: 'numeric',
|
|
165
|
+
year: 'numeric',
|
|
166
|
+
hour: '2-digit',
|
|
167
|
+
minute: '2-digit',
|
|
168
|
+
});
|
|
169
|
+
const repo = r.repository ?? r.project;
|
|
170
|
+
const label = typeLabels[r.type] ?? r.type;
|
|
171
|
+
const typeColor = r.type === 'ux-audit'
|
|
172
|
+
? chalk.yellow
|
|
173
|
+
: r.type === 'security-audit'
|
|
174
|
+
? chalk.red
|
|
175
|
+
: chalk.magenta;
|
|
176
|
+
console.log(` ${typeColor(label.padEnd(12))} ${chalk.white(repo.padEnd(40))} ${chalk.dim(r.author.padEnd(30))} ${chalk.dim(date)}`);
|
|
177
|
+
if (r.branch && r.branch !== 'main') {
|
|
178
|
+
console.log(` ${' '.padEnd(12)} ${chalk.dim(`branch: ${r.branch} commit: ${r.commit ?? 'N/A'}`)}`);
|
|
179
|
+
}
|
|
130
180
|
}
|
|
131
181
|
}
|
|
132
182
|
console.log();
|
package/dist/commands/init.js
CHANGED
|
@@ -75,6 +75,17 @@ description: >-
|
|
|
75
75
|
plan, scopes to the current feature and appends results to the plan file.
|
|
76
76
|
---
|
|
77
77
|
|
|
78
|
+
`,
|
|
79
|
+
'security-audit': `---
|
|
80
|
+
user-invocable: true
|
|
81
|
+
description: >-
|
|
82
|
+
Run a comprehensive security posture audit across the entire platform.
|
|
83
|
+
Use when the developer wants to assess security, says "security audit",
|
|
84
|
+
or "check our security posture". Covers infrastructure, encryption, auth,
|
|
85
|
+
application security, data protection, CI/CD, and compliance readiness.
|
|
86
|
+
Investigates all platform repositories for a holistic view.
|
|
87
|
+
---
|
|
88
|
+
|
|
78
89
|
`,
|
|
79
90
|
validate: `---
|
|
80
91
|
user-invocable: true
|
|
@@ -143,6 +154,11 @@ description: Run a comprehensive project compliance audit against team standards
|
|
|
143
154
|
description: Review the project's UI against usability heuristics using Chrome DevTools MCP.
|
|
144
155
|
---
|
|
145
156
|
|
|
157
|
+
`,
|
|
158
|
+
'security-audit': `---
|
|
159
|
+
description: Run a comprehensive security posture audit across the entire platform.
|
|
160
|
+
---
|
|
161
|
+
|
|
146
162
|
`,
|
|
147
163
|
validate: `---
|
|
148
164
|
description: Run the validation plan from the plan document after implementation.
|
|
@@ -302,6 +318,7 @@ export async function initCommand(options) {
|
|
|
302
318
|
'debug',
|
|
303
319
|
'audit',
|
|
304
320
|
'ux-audit',
|
|
321
|
+
'security-audit',
|
|
305
322
|
'update',
|
|
306
323
|
'help',
|
|
307
324
|
];
|
|
@@ -336,7 +353,7 @@ export async function initCommand(options) {
|
|
|
336
353
|
await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent, 'utf-8');
|
|
337
354
|
}
|
|
338
355
|
}
|
|
339
|
-
createdFiles.push('.claude/skills/melt-{setup,plan,validate,review,pr,debug,audit,ux-audit,update,help}/SKILL.md');
|
|
356
|
+
createdFiles.push('.claude/skills/melt-{setup,plan,validate,review,pr,debug,audit,ux-audit,security-audit,update,help}/SKILL.md');
|
|
340
357
|
}
|
|
341
358
|
// Cursor files
|
|
342
359
|
if (tools.cursor) {
|
|
@@ -347,7 +364,7 @@ export async function initCommand(options) {
|
|
|
347
364
|
await fs.writeFile(path.join(cwd, `.cursor/commands/melt-${name}.md`), workflowContent, 'utf-8');
|
|
348
365
|
}
|
|
349
366
|
}
|
|
350
|
-
createdFiles.push('.cursor/commands/melt-{setup,plan,validate,review,pr,debug,audit,ux-audit,update,help}.md');
|
|
367
|
+
createdFiles.push('.cursor/commands/melt-{setup,plan,validate,review,pr,debug,audit,ux-audit,security-audit,update,help}.md');
|
|
351
368
|
}
|
|
352
369
|
// OpenCode files
|
|
353
370
|
if (tools.opencode) {
|
|
@@ -359,7 +376,7 @@ export async function initCommand(options) {
|
|
|
359
376
|
await fs.writeFile(path.join(cwd, `.opencode/commands/melt-${name}.md`), commandContent, 'utf-8');
|
|
360
377
|
}
|
|
361
378
|
}
|
|
362
|
-
createdFiles.push('.opencode/commands/melt-{setup,plan,validate,review,pr,debug,audit,ux-audit,update,help}.md');
|
|
379
|
+
createdFiles.push('.opencode/commands/melt-{setup,plan,validate,review,pr,debug,audit,ux-audit,security-audit,update,help}.md');
|
|
363
380
|
}
|
|
364
381
|
// Print summary
|
|
365
382
|
console.log(chalk.green('Created files:'));
|
|
@@ -371,7 +388,7 @@ export async function initCommand(options) {
|
|
|
371
388
|
console.log(chalk.cyan('Want support for your tool? Let us know in #dev on Slack'));
|
|
372
389
|
console.log();
|
|
373
390
|
}
|
|
374
|
-
const commandNames = 'melt-setup, melt-plan, melt-validate, melt-review, melt-pr, melt-debug, melt-audit, melt-ux-audit, melt-update, melt-help';
|
|
391
|
+
const commandNames = 'melt-setup, melt-plan, melt-validate, melt-review, melt-pr, melt-debug, melt-audit, melt-ux-audit, melt-security-audit, melt-update, melt-help';
|
|
375
392
|
if (tools.claude) {
|
|
376
393
|
console.log(chalk.dim(`Available skills: /${commandNames.replace(/, /g, ', /')}`));
|
|
377
394
|
}
|
package/dist/index.js
CHANGED
|
@@ -102,8 +102,9 @@ audit
|
|
|
102
102
|
audit
|
|
103
103
|
.command('list')
|
|
104
104
|
.description('list submitted audits (Team Managers only)')
|
|
105
|
-
.option('--type <type>', 'filter by type (audit, ux-audit)')
|
|
105
|
+
.option('--type <type>', 'filter by type (audit, ux-audit, security-audit)')
|
|
106
106
|
.option('--repository <repo>', 'filter by repository (owner/repo)')
|
|
107
|
+
.option('--latest', 'show only the latest audit per project and type')
|
|
107
108
|
.option('--limit <n>', 'max results (default 50, max 200)')
|
|
108
109
|
.action(async (options) => {
|
|
109
110
|
await auditListCommand(options);
|
package/package.json
CHANGED