@nepopsx/cli 0.0.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 (90) hide show
  1. package/bin/opsx.mjs +2 -0
  2. package/dist/commands/activate.d.ts +6 -0
  3. package/dist/commands/activate.d.ts.map +1 -0
  4. package/dist/commands/activate.js +50 -0
  5. package/dist/commands/activate.js.map +1 -0
  6. package/dist/commands/decode.d.ts +2 -0
  7. package/dist/commands/decode.d.ts.map +1 -0
  8. package/dist/commands/decode.js +57 -0
  9. package/dist/commands/decode.js.map +1 -0
  10. package/dist/commands/doctor.d.ts +6 -0
  11. package/dist/commands/doctor.d.ts.map +1 -0
  12. package/dist/commands/doctor.js +133 -0
  13. package/dist/commands/doctor.js.map +1 -0
  14. package/dist/commands/init.d.ts +6 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +385 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/install.d.ts +6 -0
  19. package/dist/commands/install.d.ts.map +1 -0
  20. package/dist/commands/install.js +29 -0
  21. package/dist/commands/install.js.map +1 -0
  22. package/dist/commands/server.d.ts +4 -0
  23. package/dist/commands/server.d.ts.map +1 -0
  24. package/dist/commands/server.js +35 -0
  25. package/dist/commands/server.js.map +1 -0
  26. package/dist/commands/sync.d.ts +8 -0
  27. package/dist/commands/sync.d.ts.map +1 -0
  28. package/dist/commands/sync.js +352 -0
  29. package/dist/commands/sync.js.map +1 -0
  30. package/dist/config/api-config.d.ts +12 -0
  31. package/dist/config/api-config.d.ts.map +1 -0
  32. package/dist/config/api-config.js +67 -0
  33. package/dist/config/api-config.js.map +1 -0
  34. package/dist/generator/builtin-templates.d.ts +12 -0
  35. package/dist/generator/builtin-templates.d.ts.map +1 -0
  36. package/dist/generator/builtin-templates.js +251 -0
  37. package/dist/generator/builtin-templates.js.map +1 -0
  38. package/dist/generator/philosophy.d.ts +12 -0
  39. package/dist/generator/philosophy.d.ts.map +1 -0
  40. package/dist/generator/philosophy.js +106 -0
  41. package/dist/generator/philosophy.js.map +1 -0
  42. package/dist/generator/render.d.ts +74 -0
  43. package/dist/generator/render.d.ts.map +1 -0
  44. package/dist/generator/render.js +229 -0
  45. package/dist/generator/render.js.map +1 -0
  46. package/dist/generator/writer.d.ts +19 -0
  47. package/dist/generator/writer.d.ts.map +1 -0
  48. package/dist/generator/writer.js +59 -0
  49. package/dist/generator/writer.js.map +1 -0
  50. package/dist/index.d.ts +2 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +61 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/licensing/fingerprint.d.ts +48 -0
  55. package/dist/licensing/fingerprint.d.ts.map +1 -0
  56. package/dist/licensing/fingerprint.js +163 -0
  57. package/dist/licensing/fingerprint.js.map +1 -0
  58. package/dist/licensing/index.d.ts +7 -0
  59. package/dist/licensing/index.d.ts.map +1 -0
  60. package/dist/licensing/index.js +7 -0
  61. package/dist/licensing/index.js.map +1 -0
  62. package/dist/licensing/license-manager.d.ts +44 -0
  63. package/dist/licensing/license-manager.d.ts.map +1 -0
  64. package/dist/licensing/license-manager.js +311 -0
  65. package/dist/licensing/license-manager.js.map +1 -0
  66. package/dist/licensing/template-fetch.d.ts +31 -0
  67. package/dist/licensing/template-fetch.d.ts.map +1 -0
  68. package/dist/licensing/template-fetch.js +92 -0
  69. package/dist/licensing/template-fetch.js.map +1 -0
  70. package/dist/security/agent-validator.d.ts +20 -0
  71. package/dist/security/agent-validator.d.ts.map +1 -0
  72. package/dist/security/agent-validator.js +67 -0
  73. package/dist/security/agent-validator.js.map +1 -0
  74. package/dist/security/index.d.ts +7 -0
  75. package/dist/security/index.d.ts.map +1 -0
  76. package/dist/security/index.js +7 -0
  77. package/dist/security/index.js.map +1 -0
  78. package/dist/security/integrity.d.ts +28 -0
  79. package/dist/security/integrity.d.ts.map +1 -0
  80. package/dist/security/integrity.js +87 -0
  81. package/dist/security/integrity.js.map +1 -0
  82. package/dist/security/scanner.d.ts +43 -0
  83. package/dist/security/scanner.d.ts.map +1 -0
  84. package/dist/security/scanner.js +172 -0
  85. package/dist/security/scanner.js.map +1 -0
  86. package/dist/utils/detect.d.ts +7 -0
  87. package/dist/utils/detect.d.ts.map +1 -0
  88. package/dist/utils/detect.js +227 -0
  89. package/dist/utils/detect.js.map +1 -0
  90. package/package.json +44 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Integrity manifest — generates and verifies SHA-256 hashes
3
+ * for all OPSX-generated files. Detects post-generation tampering.
4
+ */
5
+ export interface ManifestEntry {
6
+ path: string;
7
+ sha256: string;
8
+ }
9
+ export interface IntegrityResult {
10
+ valid: boolean;
11
+ entries: ManifestEntry[];
12
+ tampered: string[];
13
+ missing: string[];
14
+ }
15
+ /**
16
+ * Generate a manifest of SHA-256 hashes for all generated files.
17
+ * Call after writeGeneratedFiles() completes.
18
+ */
19
+ export declare function generateManifest(rootDir: string, generatedFiles: Array<{
20
+ path: string;
21
+ content: string;
22
+ }>): ManifestEntry[];
23
+ /**
24
+ * Verify the integrity of generated files against the manifest.
25
+ * Returns which files have been tampered with or are missing.
26
+ */
27
+ export declare function verifyManifest(rootDir: string): IntegrityResult;
28
+ //# sourceMappingURL=integrity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/security/integrity.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AASD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GACvD,aAAa,EAAE,CA2BjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CA6C/D"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Integrity manifest — generates and verifies SHA-256 hashes
3
+ * for all OPSX-generated files. Detects post-generation tampering.
4
+ */
5
+ import { createHash } from 'node:crypto';
6
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
7
+ import { dirname, join } from 'node:path';
8
+ const MANIFEST_DIR = '.opsx';
9
+ const MANIFEST_FILE = 'manifest.sha256';
10
+ /**
11
+ * Compute SHA-256 hash of a string.
12
+ */
13
+ function sha256(content) {
14
+ return createHash('sha256').update(content, 'utf-8').digest('hex');
15
+ }
16
+ /**
17
+ * Generate a manifest of SHA-256 hashes for all generated files.
18
+ * Call after writeGeneratedFiles() completes.
19
+ */
20
+ export function generateManifest(rootDir, generatedFiles) {
21
+ const entries = [];
22
+ for (const file of generatedFiles) {
23
+ entries.push({
24
+ path: file.path,
25
+ sha256: sha256(file.content),
26
+ });
27
+ }
28
+ // Sort for deterministic output
29
+ entries.sort((a, b) => a.path.localeCompare(b.path));
30
+ // Write manifest
31
+ const manifestPath = join(rootDir, MANIFEST_DIR, MANIFEST_FILE);
32
+ const manifestDir = dirname(manifestPath);
33
+ if (!existsSync(manifestDir)) {
34
+ mkdirSync(manifestDir, { recursive: true });
35
+ }
36
+ const manifestContent = entries
37
+ .map((e) => `${e.sha256} ${e.path}`)
38
+ .join('\n') + '\n';
39
+ writeFileSync(manifestPath, manifestContent, 'utf-8');
40
+ return entries;
41
+ }
42
+ /**
43
+ * Verify the integrity of generated files against the manifest.
44
+ * Returns which files have been tampered with or are missing.
45
+ */
46
+ export function verifyManifest(rootDir) {
47
+ const manifestPath = join(rootDir, MANIFEST_DIR, MANIFEST_FILE);
48
+ if (!existsSync(manifestPath)) {
49
+ return {
50
+ valid: false,
51
+ entries: [],
52
+ tampered: [],
53
+ missing: ['(manifest file not found — run opsx sync first)'],
54
+ };
55
+ }
56
+ const manifestContent = readFileSync(manifestPath, 'utf-8');
57
+ const entries = [];
58
+ const tampered = [];
59
+ const missing = [];
60
+ for (const line of manifestContent.trim().split('\n')) {
61
+ if (!line.trim())
62
+ continue;
63
+ // Format: "sha256hash relative/path"
64
+ const match = line.match(/^([a-f0-9]{64})\s{2}(.+)$/);
65
+ if (!match)
66
+ continue;
67
+ const [, expectedHash, filePath] = match;
68
+ entries.push({ path: filePath, sha256: expectedHash });
69
+ const fullPath = join(rootDir, filePath);
70
+ if (!existsSync(fullPath)) {
71
+ missing.push(filePath);
72
+ continue;
73
+ }
74
+ const actualContent = readFileSync(fullPath, 'utf-8');
75
+ const actualHash = sha256(actualContent);
76
+ if (actualHash !== expectedHash) {
77
+ tampered.push(filePath);
78
+ }
79
+ }
80
+ return {
81
+ valid: tampered.length === 0 && missing.length === 0,
82
+ entries,
83
+ tampered,
84
+ missing,
85
+ };
86
+ }
87
+ //# sourceMappingURL=integrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.js","sourceRoot":"","sources":["../../src/security/integrity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Content scanner — detects prompt injection and manipulation patterns
3
+ * in custom instructions, philosophy.custom[], and user-supplied text
4
+ * before it gets injected into agent templates.
5
+ */
6
+ export interface ScanThreat {
7
+ pattern: string;
8
+ match: string;
9
+ source: string;
10
+ severity: 'critical' | 'high' | 'medium';
11
+ }
12
+ export interface ScanResult {
13
+ safe: boolean;
14
+ threats: ScanThreat[];
15
+ }
16
+ /**
17
+ * Scan a piece of text for prompt injection patterns.
18
+ */
19
+ export declare function scanForInjection(content: string, source: string): ScanThreat[];
20
+ /**
21
+ * Scan text for accidentally embedded secrets.
22
+ */
23
+ export declare function scanForSecrets(content: string, source: string): ScanThreat[];
24
+ /**
25
+ * Scan custom instructions files for injection + secrets.
26
+ */
27
+ export declare function scanCustomInstructions(customs: Array<{
28
+ content: string;
29
+ source: string;
30
+ }>): ScanResult;
31
+ /**
32
+ * Scan philosophy.custom[] entries for injection + secrets.
33
+ */
34
+ export declare function scanPhilosophyCustom(customEntries: string[]): ScanResult;
35
+ /**
36
+ * Scan all string values in the workspace config for secrets.
37
+ */
38
+ export declare function scanConfigForSecrets(config: Record<string, unknown>, path?: string): ScanThreat[];
39
+ /**
40
+ * Format threats for console output.
41
+ */
42
+ export declare function formatThreats(threats: ScanThreat[]): string;
43
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/security/scanner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;CAC1C;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAyDD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAgB9E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAkB5E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAClD,UAAU,CASZ;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EAAE,GACtB,UAAU,CAUZ;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,SAAW,GAAG,UAAU,EAAE,CAsBnG;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAkC3D"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Content scanner — detects prompt injection and manipulation patterns
3
+ * in custom instructions, philosophy.custom[], and user-supplied text
4
+ * before it gets injected into agent templates.
5
+ */
6
+ // ─── Prompt injection detection patterns ────────────────────
7
+ const INJECTION_PATTERNS = [
8
+ // Direct instruction override attempts
9
+ { regex: /ignore\s+(all\s+)?(previous|prior|above|earlier)\s+(instructions|rules|guidelines|directives)/i, description: 'Instruction override attempt', severity: 'critical' },
10
+ { regex: /disregard\s+(all\s+)?(previous|prior|above|earlier|your)\s+(instructions|rules|guidelines|directives)/i, description: 'Instruction disregard attempt', severity: 'critical' },
11
+ { regex: /override\s+(the\s+)?(constitutional|safety|security|system)\s+(rules|instructions|prompt|guidelines)/i, description: 'Constitutional override attempt', severity: 'critical' },
12
+ { regex: /forget\s+(all|everything|your)\s+(previous|prior|instructions|rules|training)/i, description: 'Memory wipe attempt', severity: 'critical' },
13
+ // Role/identity hijacking
14
+ { regex: /you\s+are\s+now\s+(a|an|the)\s+/i, description: 'Role hijacking attempt', severity: 'critical' },
15
+ { regex: /pretend\s+(you\s+are|to\s+be|you're)\s+/i, description: 'Role-play injection', severity: 'high' },
16
+ { regex: /act\s+as\s+(if\s+you\s+are|a|an|the)\s+/i, description: 'Role assumption injection', severity: 'high' },
17
+ { regex: /from\s+now\s+on,?\s+(you|your|act|behave|respond)/i, description: 'Behavioral override attempt', severity: 'high' },
18
+ // System prompt extraction
19
+ { regex: /(?:show|reveal|display|output|print|repeat|echo)\s+(your|the)\s+(system|initial|original)\s+(prompt|instructions|message)/i, description: 'System prompt extraction attempt', severity: 'high' },
20
+ { regex: /what\s+(are|is)\s+your\s+(system|initial|original)\s+(prompt|instructions|rules)/i, description: 'System prompt probing', severity: 'medium' },
21
+ // Tool/permission escalation
22
+ { regex: /(?:run|execute|invoke)\s+(?:any|all|unlimited)\s+(?:commands?|tools?|scripts?)/i, description: 'Permission escalation attempt', severity: 'critical' },
23
+ { regex: /(?:disable|remove|skip|bypass)\s+(?:the\s+)?(?:safety|security|guard|check|validation|restriction)/i, description: 'Safety bypass attempt', severity: 'critical' },
24
+ { regex: /--no-verify/i, description: 'Git safety bypass (--no-verify)', severity: 'high' },
25
+ { regex: /--force\s*(?:push)?/i, description: 'Force operation pattern', severity: 'medium' },
26
+ // Hidden instruction embedding
27
+ { regex: /\[SYSTEM\]/i, description: 'Hidden system tag', severity: 'high' },
28
+ { regex: /\[INST\]/i, description: 'Hidden instruction tag', severity: 'high' },
29
+ { regex: /<\|im_start\|>system/i, description: 'ChatML injection attempt', severity: 'critical' },
30
+ { regex: /Human:|Assistant:/i, description: 'Conversation role injection', severity: 'medium' },
31
+ // Dangerous shell patterns in instruction text
32
+ { regex: /rm\s+-rf\s+[/~]/i, description: 'Destructive rm -rf command in instructions', severity: 'critical' },
33
+ { regex: /curl\s+.*\|\s*(?:bash|sh|zsh)/i, description: 'Pipe-to-shell pattern in instructions', severity: 'critical' },
34
+ { regex: /wget\s+.*&&\s*(?:bash|sh|chmod)/i, description: 'Download-and-execute pattern', severity: 'critical' },
35
+ { regex: /eval\s*\(\s*["'`]/i, description: 'Eval injection pattern', severity: 'high' },
36
+ ];
37
+ // ─── Secrets patterns (also scanned via this module) ────────
38
+ const SECRET_PATTERNS = [
39
+ { regex: /(?:^|[^a-zA-Z0-9])sk-[a-zA-Z0-9]{20,}/m, description: 'OpenAI API key' },
40
+ { regex: /(?:^|[^a-zA-Z0-9])ghp_[a-zA-Z0-9]{36,}/m, description: 'GitHub personal access token' },
41
+ { regex: /(?:^|[^a-zA-Z0-9])gho_[a-zA-Z0-9]{36,}/m, description: 'GitHub OAuth token' },
42
+ { regex: /(?:^|[^a-zA-Z0-9])github_pat_[a-zA-Z0-9_]{22,}/m, description: 'GitHub fine-grained PAT' },
43
+ { regex: /AKIA[0-9A-Z]{16}/m, description: 'AWS access key ID' },
44
+ { regex: /(?:^|[^a-zA-Z0-9])Bearer\s+[a-zA-Z0-9._\-]{20,}/m, description: 'Bearer token' },
45
+ { regex: /(?:password|passwd|secret|api_key|apikey|access_token)\s*[:=]\s*["'][^"']{6,}["']/i, description: 'Hardcoded credential' },
46
+ { regex: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/m, description: 'Private key' },
47
+ { regex: /(?:^|[^a-zA-Z0-9])xox[bpors]-[a-zA-Z0-9\-]{10,}/m, description: 'Slack token' },
48
+ { regex: /(?:^|[^a-zA-Z0-9])AIza[0-9A-Za-z\-_]{35}/m, description: 'Google API key' },
49
+ ];
50
+ // ─── Public API ─────────────────────────────────────────────
51
+ /**
52
+ * Scan a piece of text for prompt injection patterns.
53
+ */
54
+ export function scanForInjection(content, source) {
55
+ const threats = [];
56
+ for (const { regex, description, severity } of INJECTION_PATTERNS) {
57
+ const match = content.match(regex);
58
+ if (match) {
59
+ threats.push({
60
+ pattern: description,
61
+ match: match[0].substring(0, 80), // truncate long matches
62
+ source,
63
+ severity,
64
+ });
65
+ }
66
+ }
67
+ return threats;
68
+ }
69
+ /**
70
+ * Scan text for accidentally embedded secrets.
71
+ */
72
+ export function scanForSecrets(content, source) {
73
+ const threats = [];
74
+ for (const { regex, description } of SECRET_PATTERNS) {
75
+ const match = content.match(regex);
76
+ if (match) {
77
+ // Redact the match — never show secrets in output
78
+ const redacted = match[0].substring(0, 8) + '***REDACTED***';
79
+ threats.push({
80
+ pattern: description,
81
+ match: redacted,
82
+ source,
83
+ severity: 'high',
84
+ });
85
+ }
86
+ }
87
+ return threats;
88
+ }
89
+ /**
90
+ * Scan custom instructions files for injection + secrets.
91
+ */
92
+ export function scanCustomInstructions(customs) {
93
+ const threats = [];
94
+ for (const ci of customs) {
95
+ threats.push(...scanForInjection(ci.content, `customs/${ci.source}`));
96
+ threats.push(...scanForSecrets(ci.content, `customs/${ci.source}`));
97
+ }
98
+ return { safe: threats.length === 0, threats };
99
+ }
100
+ /**
101
+ * Scan philosophy.custom[] entries for injection + secrets.
102
+ */
103
+ export function scanPhilosophyCustom(customEntries) {
104
+ const threats = [];
105
+ for (let i = 0; i < customEntries.length; i++) {
106
+ const source = `philosophy.custom[${i}]`;
107
+ threats.push(...scanForInjection(customEntries[i], source));
108
+ threats.push(...scanForSecrets(customEntries[i], source));
109
+ }
110
+ return { safe: threats.length === 0, threats };
111
+ }
112
+ /**
113
+ * Scan all string values in the workspace config for secrets.
114
+ */
115
+ export function scanConfigForSecrets(config, path = 'config') {
116
+ const threats = [];
117
+ for (const [key, value] of Object.entries(config)) {
118
+ const currentPath = `${path}.${key}`;
119
+ if (typeof value === 'string') {
120
+ threats.push(...scanForSecrets(value, currentPath));
121
+ }
122
+ else if (Array.isArray(value)) {
123
+ for (let i = 0; i < value.length; i++) {
124
+ if (typeof value[i] === 'string') {
125
+ threats.push(...scanForSecrets(value[i], `${currentPath}[${i}]`));
126
+ }
127
+ else if (typeof value[i] === 'object' && value[i] !== null) {
128
+ threats.push(...scanConfigForSecrets(value[i], `${currentPath}[${i}]`));
129
+ }
130
+ }
131
+ }
132
+ else if (typeof value === 'object' && value !== null) {
133
+ threats.push(...scanConfigForSecrets(value, currentPath));
134
+ }
135
+ }
136
+ return threats;
137
+ }
138
+ /**
139
+ * Format threats for console output.
140
+ */
141
+ export function formatThreats(threats) {
142
+ if (threats.length === 0)
143
+ return '';
144
+ const lines = [];
145
+ const bySeverity = {
146
+ critical: threats.filter((t) => t.severity === 'critical'),
147
+ high: threats.filter((t) => t.severity === 'high'),
148
+ medium: threats.filter((t) => t.severity === 'medium'),
149
+ };
150
+ if (bySeverity.critical.length > 0) {
151
+ lines.push(' 🔴 CRITICAL:');
152
+ for (const t of bySeverity.critical) {
153
+ lines.push(` ${t.pattern} in ${t.source}`);
154
+ lines.push(` → "${t.match}"`);
155
+ }
156
+ }
157
+ if (bySeverity.high.length > 0) {
158
+ lines.push(' 🟠 HIGH:');
159
+ for (const t of bySeverity.high) {
160
+ lines.push(` ${t.pattern} in ${t.source}`);
161
+ lines.push(` → "${t.match}"`);
162
+ }
163
+ }
164
+ if (bySeverity.medium.length > 0) {
165
+ lines.push(' 🟡 MEDIUM:');
166
+ for (const t of bySeverity.medium) {
167
+ lines.push(` ${t.pattern} in ${t.source}`);
168
+ }
169
+ }
170
+ return lines.join('\n');
171
+ }
172
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/security/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Service } from '@nepopsx/core';
2
+ /**
3
+ * Auto-detect services in a repository by scanning for known project markers.
4
+ * Scans up to 2 levels deep.
5
+ */
6
+ export declare function detectServices(rootDir: string): Service[];
7
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/utils/detect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAA4B,MAAM,eAAe,CAAC;AAYvE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE,CAqCzD"}
@@ -0,0 +1,227 @@
1
+ import { readdirSync, readFileSync, statSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+ /**
4
+ * Auto-detect services in a repository by scanning for known project markers.
5
+ * Scans up to 2 levels deep.
6
+ */
7
+ export function detectServices(rootDir) {
8
+ const services = [];
9
+ const scanned = new Set();
10
+ // Scan root and immediate subdirectories
11
+ const candidates = [rootDir];
12
+ for (const entry of safeReaddir(rootDir)) {
13
+ const full = join(rootDir, entry);
14
+ if (isDir(full) && !isIgnored(entry)) {
15
+ candidates.push(full);
16
+ // Scan one level deeper (e.g., apps/web, services/api)
17
+ for (const sub of safeReaddir(full)) {
18
+ const subFull = join(full, sub);
19
+ if (isDir(subFull) && !isIgnored(sub)) {
20
+ candidates.push(subFull);
21
+ }
22
+ }
23
+ }
24
+ }
25
+ for (const dir of candidates) {
26
+ if (scanned.has(dir))
27
+ continue;
28
+ scanned.add(dir);
29
+ const detected = detectInDirectory(dir, rootDir);
30
+ if (detected) {
31
+ // Don't detect the root itself if it has subdirectories with their own projects
32
+ if (dir === rootDir && candidates.length > 1) {
33
+ // Only include root if no subdirectories were detected as services
34
+ continue;
35
+ }
36
+ services.push(detected);
37
+ }
38
+ }
39
+ return services;
40
+ }
41
+ function detectInDirectory(dir, rootDir) {
42
+ const files = new Set(safeReaddir(dir));
43
+ const relPath = relative(rootDir, dir) || '.';
44
+ // TypeScript/JavaScript (package.json)
45
+ if (files.has('package.json')) {
46
+ const pkg = readJsonSafe(join(dir, 'package.json'));
47
+ if (!pkg)
48
+ return null;
49
+ const isTS = files.has('tsconfig.json');
50
+ const language = isTS ? 'typescript' : 'javascript';
51
+ let framework;
52
+ let port;
53
+ let pm;
54
+ const commands = {};
55
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
56
+ // Detect framework
57
+ if (deps['next']) {
58
+ framework = 'nextjs';
59
+ port = 3000;
60
+ }
61
+ else if (deps['@nestjs/core']) {
62
+ framework = 'nestjs';
63
+ port = 3000;
64
+ }
65
+ else if (deps['express']) {
66
+ framework = 'express';
67
+ port = 3000;
68
+ }
69
+ else if (deps['fastify']) {
70
+ framework = 'fastify';
71
+ port = 3000;
72
+ }
73
+ else if (deps['react'] && !deps['next']) {
74
+ framework = 'react';
75
+ port = 5173;
76
+ }
77
+ else if (deps['vue']) {
78
+ framework = 'vue';
79
+ port = 5173;
80
+ }
81
+ else if (deps['svelte'] || deps['@sveltejs/kit']) {
82
+ framework = 'sveltekit';
83
+ port = 5173;
84
+ }
85
+ else if (deps['nuxt']) {
86
+ framework = 'nuxt';
87
+ port = 3000;
88
+ }
89
+ // Detect package manager
90
+ if (files.has('pnpm-lock.yaml'))
91
+ pm = 'pnpm';
92
+ else if (files.has('yarn.lock'))
93
+ pm = 'yarn';
94
+ else if (files.has('bun.lockb') || files.has('bun.lock'))
95
+ pm = 'bun';
96
+ else
97
+ pm = 'npm';
98
+ // Extract scripts
99
+ if (pkg.scripts) {
100
+ if (pkg.scripts.dev)
101
+ commands.dev = `${pm} dev`;
102
+ else if (pkg.scripts.start)
103
+ commands.dev = `${pm} start`;
104
+ if (pkg.scripts.build)
105
+ commands.build = `${pm} build`;
106
+ if (pkg.scripts.test)
107
+ commands.test = `${pm} test`;
108
+ if (pkg.scripts.lint)
109
+ commands.lint = `${pm} lint`;
110
+ }
111
+ const name = deriveName(relPath, pkg.name);
112
+ return { name, path: relPath, language, framework, package_manager: pm, port, commands };
113
+ }
114
+ // Python
115
+ if (files.has('pyproject.toml') || files.has('requirements.txt') || files.has('setup.py')) {
116
+ let framework;
117
+ let pm = 'pip';
118
+ if (files.has('pyproject.toml')) {
119
+ const content = readFileSafe(join(dir, 'pyproject.toml'));
120
+ if (content?.includes('[tool.poetry]'))
121
+ pm = 'poetry';
122
+ if (content?.includes('fastapi'))
123
+ framework = 'fastapi';
124
+ if (content?.includes('django'))
125
+ framework = 'django';
126
+ if (content?.includes('flask'))
127
+ framework = 'flask';
128
+ }
129
+ if (files.has('uv.lock'))
130
+ pm = 'uv';
131
+ const name = deriveName(relPath);
132
+ return { name, path: relPath, language: 'python', framework, package_manager: pm };
133
+ }
134
+ // Go
135
+ if (files.has('go.mod')) {
136
+ let framework;
137
+ const content = readFileSafe(join(dir, 'go.mod'));
138
+ if (content?.includes('github.com/gin-gonic/gin'))
139
+ framework = 'gin';
140
+ if (content?.includes('github.com/gofiber/fiber'))
141
+ framework = 'fiber';
142
+ if (content?.includes('github.com/labstack/echo'))
143
+ framework = 'echo';
144
+ if (content?.includes('github.com/gorilla/mux'))
145
+ framework = 'gorilla';
146
+ const name = deriveName(relPath);
147
+ const commands = {};
148
+ if (files.has('Makefile')) {
149
+ commands.build = 'make build';
150
+ commands.test = 'make test';
151
+ }
152
+ else {
153
+ commands.build = 'go build ./...';
154
+ commands.test = 'go test ./...';
155
+ }
156
+ return { name, path: relPath, language: 'go', framework, package_manager: 'go', commands };
157
+ }
158
+ // Rust
159
+ if (files.has('Cargo.toml')) {
160
+ const name = deriveName(relPath);
161
+ return {
162
+ name,
163
+ path: relPath,
164
+ language: 'rust',
165
+ package_manager: 'cargo',
166
+ commands: { build: 'cargo build', test: 'cargo test' },
167
+ };
168
+ }
169
+ // Java/Kotlin (Maven)
170
+ if (files.has('pom.xml')) {
171
+ const language = files.has('src/main/kotlin') ? 'kotlin' : 'java';
172
+ const name = deriveName(relPath);
173
+ return { name, path: relPath, language, framework: 'spring-boot', package_manager: 'maven' };
174
+ }
175
+ // Java/Kotlin (Gradle)
176
+ if (files.has('build.gradle') || files.has('build.gradle.kts')) {
177
+ const language = files.has('build.gradle.kts') ? 'kotlin' : 'java';
178
+ const name = deriveName(relPath);
179
+ return { name, path: relPath, language, framework: 'spring-boot', package_manager: 'gradle' };
180
+ }
181
+ return null;
182
+ }
183
+ // ─── Helpers ──────────────────────────────────────────────────
184
+ function deriveName(relPath, pkgName) {
185
+ if (relPath === '.') {
186
+ return pkgName?.replace(/^@[^/]+\//, '').replace(/[^a-z0-9-]/g, '-') ?? 'app';
187
+ }
188
+ return relPath.split('/').pop().replace(/[^a-z0-9-]/g, '-').toLowerCase();
189
+ }
190
+ function isDir(p) {
191
+ try {
192
+ return statSync(p).isDirectory();
193
+ }
194
+ catch {
195
+ return false;
196
+ }
197
+ }
198
+ function isIgnored(name) {
199
+ return name.startsWith('.') || name === 'node_modules' || name === 'vendor' ||
200
+ name === 'dist' || name === 'build' || name === '__pycache__' ||
201
+ name === '.git' || name === 'target' || name === 'coverage';
202
+ }
203
+ function safeReaddir(dir) {
204
+ try {
205
+ return readdirSync(dir);
206
+ }
207
+ catch {
208
+ return [];
209
+ }
210
+ }
211
+ function readJsonSafe(path) {
212
+ try {
213
+ return JSON.parse(readFileSync(path, 'utf-8'));
214
+ }
215
+ catch {
216
+ return null;
217
+ }
218
+ }
219
+ function readFileSafe(path) {
220
+ try {
221
+ return readFileSync(path, 'utf-8');
222
+ }
223
+ catch {
224
+ return null;
225
+ }
226
+ }
227
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/utils/detect.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@nepopsx/cli",
3
+ "version": "0.0.1",
4
+ "description": "OPSX CLI — generate AI agent workspaces from configuration",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "bin": {
8
+ "opsx": "./bin/opsx.mjs"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "clean": "rm -rf dist",
18
+ "dev": "tsc --watch",
19
+ "lint": "tsc --noEmit",
20
+ "test": "node --test dist/**/*.test.js"
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "bin"
25
+ ],
26
+ "dependencies": {
27
+ "@inquirer/prompts": "^8.4.1",
28
+ "@nepopsx/core": "workspace:*",
29
+ "chalk": "^5.4.1",
30
+ "commander": "^13.1.0",
31
+ "glob": "^11.0.1",
32
+ "handlebars": "^4.7.8",
33
+ "inquirer": "^12.3.2",
34
+ "ora": "^8.2.0",
35
+ "yaml": "^2.7.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^22.0.0",
39
+ "typescript": "^5.7.0"
40
+ },
41
+ "engines": {
42
+ "node": ">=20"
43
+ }
44
+ }