@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,7 @@
1
+ /**
2
+ * Licensing barrel — re-export all licensing modules.
3
+ */
4
+ export { readLicense, writeLicense, activateLicense, validateLicense, enforceTierLimits, isDevMode, } from './license-manager.js';
5
+ export { fetchRemoteTemplates, } from './template-fetch.js';
6
+ export { applySteganography, decodeSteganography, forensicDecode, fingerprintToId, } from './fingerprint.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/licensing/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,WAAW,EACX,YAAY,EACZ,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,SAAS,GAGV,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,oBAAoB,GAErB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * License manager — handles license activation, validation,
3
+ * online refresh, and tier-based feature gating.
4
+ */
5
+ import { type License, type LicenseStatus, type LicenseTier, type WorkspaceConfig } from '@nepopsx/core';
6
+ /**
7
+ * Read the local license file. Returns null if not found or invalid.
8
+ */
9
+ export declare function readLicense(rootDir: string): License | null;
10
+ /**
11
+ * Write license to disk. Creates .opsx/ if needed.
12
+ */
13
+ export declare function writeLicense(rootDir: string, license: License): void;
14
+ export interface ActivationResult {
15
+ success: boolean;
16
+ license?: License;
17
+ error?: string;
18
+ }
19
+ /**
20
+ * Activate a license key for this machine + workspace.
21
+ * Calls the remote API to validate the key and bind it.
22
+ */
23
+ export declare function activateLicense(rootDir: string, licenseKey: string, workspaceName: string): Promise<ActivationResult>;
24
+ /**
25
+ * Validate the current license. Attempts online refresh if expired.
26
+ * Returns detailed status.
27
+ */
28
+ export declare function validateLicense(rootDir: string, config: WorkspaceConfig): Promise<LicenseStatus>;
29
+ export interface TierViolation {
30
+ feature: string;
31
+ limit: string;
32
+ actual: string;
33
+ required_tier: LicenseTier;
34
+ }
35
+ /**
36
+ * Check if the workspace config exceeds the license tier's limits.
37
+ */
38
+ export declare function enforceTierLimits(config: WorkspaceConfig, tier: LicenseTier): TierViolation[];
39
+ /**
40
+ * Check if the CLI is running in dev mode (for OPSX agent developers).
41
+ * Set OPSX_DEV=1 to bypass license checks.
42
+ */
43
+ export declare function isDevMode(): boolean;
44
+ //# sourceMappingURL=license-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-manager.d.ts","sourceRoot":"","sources":["../../src/licensing/license-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACL,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAmB,KAAK,eAAe,EAG1F,MAAM,eAAe,CAAC;AAYvB;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAiB3D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAUpE;AAID,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAoD3B;AAID;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,aAAa,CAAC,CAkIxB;AA+CD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,WAAW,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,GAAG,aAAa,EAAE,CAgD7F;AAID;;;GAGG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC"}
@@ -0,0 +1,311 @@
1
+ /**
2
+ * License manager — handles license activation, validation,
3
+ * online refresh, and tier-based feature gating.
4
+ */
5
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { TIER_LIMITS, generateMachineId, generateFingerprint, checkExpiry, } from '@nepopsx/core';
8
+ import { resolveApiBase } from '../config/api-config.js';
9
+ const LICENSE_DIR = '.opsx';
10
+ const LICENSE_FILE = 'license.json';
11
+ // ─── API configuration ──────────────────────────────────────
12
+ const REQUEST_TIMEOUT_MS = 10_000;
13
+ // ─── License file operations ────────────────────────────────
14
+ /**
15
+ * Read the local license file. Returns null if not found or invalid.
16
+ */
17
+ export function readLicense(rootDir) {
18
+ const licensePath = join(rootDir, LICENSE_DIR, LICENSE_FILE);
19
+ if (!existsSync(licensePath))
20
+ return null;
21
+ try {
22
+ const raw = readFileSync(licensePath, 'utf-8');
23
+ const data = JSON.parse(raw);
24
+ // Basic shape validation
25
+ if (!data.key || !data.org || !data.tier || !data.valid_until || !data.machine_id) {
26
+ return null;
27
+ }
28
+ return data;
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ /**
35
+ * Write license to disk. Creates .opsx/ if needed.
36
+ */
37
+ export function writeLicense(rootDir, license) {
38
+ const dir = join(rootDir, LICENSE_DIR);
39
+ if (!existsSync(dir)) {
40
+ mkdirSync(dir, { recursive: true });
41
+ }
42
+ writeFileSync(join(dir, LICENSE_FILE), JSON.stringify(license, null, 2) + '\n', 'utf-8');
43
+ }
44
+ /**
45
+ * Activate a license key for this machine + workspace.
46
+ * Calls the remote API to validate the key and bind it.
47
+ */
48
+ export async function activateLicense(rootDir, licenseKey, workspaceName) {
49
+ const machineId = generateMachineId();
50
+ const apiBase = resolveApiBase(rootDir);
51
+ try {
52
+ const response = await fetchWithTimeout(`${apiBase}/license/activate`, {
53
+ method: 'POST',
54
+ headers: { 'Content-Type': 'application/json' },
55
+ body: JSON.stringify({
56
+ key: licenseKey,
57
+ machine_id: machineId,
58
+ workspace: workspaceName,
59
+ }),
60
+ });
61
+ if (!response.ok) {
62
+ const body = await response.text();
63
+ return {
64
+ success: false,
65
+ error: `Activation failed (${response.status}): ${body}`,
66
+ };
67
+ }
68
+ const data = await response.json();
69
+ const license = {
70
+ key: licenseKey,
71
+ org: data.org,
72
+ tier: data.tier,
73
+ valid_until: data.valid_until,
74
+ refresh_token: data.refresh_token,
75
+ machine_id: machineId,
76
+ workspace: workspaceName,
77
+ activated_at: new Date().toISOString(),
78
+ last_refreshed: new Date().toISOString(),
79
+ };
80
+ writeLicense(rootDir, license);
81
+ return { success: true, license };
82
+ }
83
+ catch (err) {
84
+ // Network failure — might be offline
85
+ return {
86
+ success: false,
87
+ error: `Cannot reach OPSX API: ${err.message}. Check your internet connection.`,
88
+ };
89
+ }
90
+ }
91
+ // ─── Validation ─────────────────────────────────────────────
92
+ /**
93
+ * Validate the current license. Attempts online refresh if expired.
94
+ * Returns detailed status.
95
+ */
96
+ export async function validateLicense(rootDir, config) {
97
+ const license = readLicense(rootDir);
98
+ const apiBase = resolveApiBase(rootDir);
99
+ // No license file
100
+ if (!license) {
101
+ return {
102
+ valid: false,
103
+ expired: true,
104
+ days_remaining: 0,
105
+ tier: 'free',
106
+ org: '',
107
+ fingerprint: '',
108
+ message: 'No license found. Run `opsx activate <key>` to activate.',
109
+ };
110
+ }
111
+ // Machine binding check
112
+ const currentMachineId = generateMachineId();
113
+ if (license.machine_id !== currentMachineId) {
114
+ return {
115
+ valid: false,
116
+ expired: false,
117
+ days_remaining: 0,
118
+ tier: license.tier,
119
+ org: license.org,
120
+ fingerprint: '',
121
+ message: 'License is bound to a different machine. Run `opsx activate <key>` to re-activate.',
122
+ };
123
+ }
124
+ const { expired, daysRemaining } = checkExpiry(license.valid_until);
125
+ const fingerprint = generateFingerprint(license.org, license.key, license.workspace);
126
+ // Still valid — return immediately
127
+ if (!expired) {
128
+ try {
129
+ const response = await fetchWithTimeout(`${apiBase}/license/validate`, {
130
+ method: 'POST',
131
+ headers: { 'Content-Type': 'application/json' },
132
+ body: JSON.stringify({
133
+ key: license.key,
134
+ machine_id: license.machine_id,
135
+ workspace: license.workspace,
136
+ }),
137
+ });
138
+ if (response.ok) {
139
+ const data = await response.json();
140
+ if (data.valid) {
141
+ const updatedLicense = {
142
+ ...license,
143
+ org: data.org,
144
+ tier: data.tier,
145
+ valid_until: data.valid_until,
146
+ last_refreshed: new Date().toISOString(),
147
+ };
148
+ writeLicense(rootDir, updatedLicense);
149
+ const onlineExpiry = checkExpiry(updatedLicense.valid_until);
150
+ return {
151
+ valid: true,
152
+ expired: false,
153
+ days_remaining: onlineExpiry.daysRemaining,
154
+ tier: updatedLicense.tier,
155
+ org: updatedLicense.org,
156
+ fingerprint,
157
+ message: data.message,
158
+ };
159
+ }
160
+ return {
161
+ valid: false,
162
+ expired: false,
163
+ days_remaining: daysRemaining,
164
+ tier: license.tier,
165
+ org: license.org,
166
+ fingerprint,
167
+ message: data.message,
168
+ };
169
+ }
170
+ }
171
+ catch {
172
+ // Fall back to local validation when offline or backend is unavailable.
173
+ }
174
+ return {
175
+ valid: true,
176
+ expired: false,
177
+ days_remaining: daysRemaining,
178
+ tier: license.tier,
179
+ org: license.org,
180
+ fingerprint,
181
+ message: daysRemaining <= 7
182
+ ? `License expires in ${daysRemaining} day(s). Renew at opsx.dev.`
183
+ : `Licensed to ${license.org} (${license.tier}).`,
184
+ };
185
+ }
186
+ // Expired — attempt online refresh
187
+ const refreshed = await refreshLicense(rootDir, license);
188
+ if (refreshed) {
189
+ const newExpiry = checkExpiry(refreshed.valid_until);
190
+ return {
191
+ valid: true,
192
+ expired: false,
193
+ days_remaining: newExpiry.daysRemaining,
194
+ tier: refreshed.tier,
195
+ org: refreshed.org,
196
+ fingerprint,
197
+ message: `License refreshed. Valid until ${refreshed.valid_until}.`,
198
+ };
199
+ }
200
+ // Refresh failed — license is truly expired
201
+ return {
202
+ valid: false,
203
+ expired: true,
204
+ days_remaining: daysRemaining,
205
+ tier: license.tier,
206
+ org: license.org,
207
+ fingerprint,
208
+ message: `License expired on ${license.valid_until}. Renew at opsx.dev or run \`opsx activate <key>\`.`,
209
+ };
210
+ }
211
+ // ─── Refresh ────────────────────────────────────────────────
212
+ /**
213
+ * Attempt to refresh the license via the remote API.
214
+ * Returns updated license on success, null on failure.
215
+ */
216
+ async function refreshLicense(rootDir, license) {
217
+ const apiBase = resolveApiBase(rootDir);
218
+ try {
219
+ const response = await fetchWithTimeout(`${apiBase}/license/refresh`, {
220
+ method: 'POST',
221
+ headers: { 'Content-Type': 'application/json' },
222
+ body: JSON.stringify({
223
+ refresh_token: license.refresh_token,
224
+ machine_id: license.machine_id,
225
+ }),
226
+ });
227
+ if (!response.ok)
228
+ return null;
229
+ const data = await response.json();
230
+ const updated = {
231
+ ...license,
232
+ tier: data.tier,
233
+ valid_until: data.valid_until,
234
+ refresh_token: data.refresh_token,
235
+ last_refreshed: new Date().toISOString(),
236
+ };
237
+ writeLicense(rootDir, updated);
238
+ return updated;
239
+ }
240
+ catch {
241
+ // Network failure — can't refresh
242
+ return null;
243
+ }
244
+ }
245
+ /**
246
+ * Check if the workspace config exceeds the license tier's limits.
247
+ */
248
+ export function enforceTierLimits(config, tier) {
249
+ const limits = TIER_LIMITS[tier];
250
+ const violations = [];
251
+ // Service count
252
+ if (config.services.length > limits.max_services) {
253
+ violations.push({
254
+ feature: 'services',
255
+ limit: `${limits.max_services}`,
256
+ actual: `${config.services.length}`,
257
+ required_tier: tier === 'free' ? 'team' : 'enterprise',
258
+ });
259
+ }
260
+ // Agent count
261
+ if (config.agents) {
262
+ const enabledAgents = Object.values(config.agents).filter((a) => a.enabled).length;
263
+ if (enabledAgents > limits.max_agents) {
264
+ violations.push({
265
+ feature: 'agents',
266
+ limit: `${limits.max_agents}`,
267
+ actual: `${enabledAgents}`,
268
+ required_tier: tier === 'free' ? 'team' : 'enterprise',
269
+ });
270
+ }
271
+ }
272
+ // Customs
273
+ if (config.customs_dir && !limits.customs_allowed) {
274
+ violations.push({
275
+ feature: 'customs',
276
+ limit: 'not available',
277
+ actual: 'customs_dir configured',
278
+ required_tier: 'team',
279
+ });
280
+ }
281
+ // Philosophy
282
+ if (config.philosophy && !limits.philosophy_allowed) {
283
+ violations.push({
284
+ feature: 'philosophy',
285
+ limit: 'not available',
286
+ actual: 'philosophy configured',
287
+ required_tier: 'team',
288
+ });
289
+ }
290
+ return violations;
291
+ }
292
+ // ─── Dev mode bypass ────────────────────────────────────────
293
+ /**
294
+ * Check if the CLI is running in dev mode (for OPSX agent developers).
295
+ * Set OPSX_DEV=1 to bypass license checks.
296
+ */
297
+ export function isDevMode() {
298
+ return process.env.OPSX_DEV === '1';
299
+ }
300
+ // ─── Utilities ──────────────────────────────────────────────
301
+ async function fetchWithTimeout(url, init) {
302
+ const controller = new AbortController();
303
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
304
+ try {
305
+ return await fetch(url, { ...init, signal: controller.signal });
306
+ }
307
+ finally {
308
+ clearTimeout(timeout);
309
+ }
310
+ }
311
+ //# sourceMappingURL=license-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-manager.js","sourceRoot":"","sources":["../../src/licensing/license-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Remote template fetch client — retrieves agent templates from the
3
+ * OPSX API instead of shipping them in the npm package.
4
+ *
5
+ * Flow:
6
+ * 1. CLI sends license key + agent name + version to API
7
+ * 2. API validates license, checks tier, returns encrypted template bundle
8
+ * 3. CLI decrypts bundle IN MEMORY (never writes .hbs to disk)
9
+ * 4. Returns template map for the rendering engine
10
+ *
11
+ * In dev mode (OPSX_DEV=1) or for free tier, falls back to local templates.
12
+ */
13
+ import type { License } from '@nepopsx/core';
14
+ export interface TemplateBundle {
15
+ /** Agent name (e.g., "feature-factory") */
16
+ agent: string;
17
+ /** Agent version */
18
+ version: string;
19
+ /** Map of relative path → template content */
20
+ templates: Record<string, string>;
21
+ /** Whether this came from remote or local fallback */
22
+ source: 'remote' | 'local';
23
+ }
24
+ /**
25
+ * Fetch agent templates from the remote OPSX API.
26
+ * Templates are encrypted and decrypted in memory.
27
+ *
28
+ * @returns TemplateBundle on success, null on failure (caller should use local fallback)
29
+ */
30
+ export declare function fetchRemoteTemplates(rootDir: string, license: License, agentName: string, agentVersion: string): Promise<TemplateBundle | null>;
31
+ //# sourceMappingURL=template-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-fetch.d.ts","sourceRoot":"","sources":["../../src/licensing/template-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAO7C,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,sDAAsD;IACtD,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC5B;AAiBD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAoChC"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Remote template fetch client — retrieves agent templates from the
3
+ * OPSX API instead of shipping them in the npm package.
4
+ *
5
+ * Flow:
6
+ * 1. CLI sends license key + agent name + version to API
7
+ * 2. API validates license, checks tier, returns encrypted template bundle
8
+ * 3. CLI decrypts bundle IN MEMORY (never writes .hbs to disk)
9
+ * 4. Returns template map for the rendering engine
10
+ *
11
+ * In dev mode (OPSX_DEV=1) or for free tier, falls back to local templates.
12
+ */
13
+ import { createDecipheriv, createHash } from 'node:crypto';
14
+ import { resolveApiBase } from '../config/api-config.js';
15
+ const REQUEST_TIMEOUT_MS = 30_000;
16
+ // ─── Public API ─────────────────────────────────────────────
17
+ /**
18
+ * Fetch agent templates from the remote OPSX API.
19
+ * Templates are encrypted and decrypted in memory.
20
+ *
21
+ * @returns TemplateBundle on success, null on failure (caller should use local fallback)
22
+ */
23
+ export async function fetchRemoteTemplates(rootDir, license, agentName, agentVersion) {
24
+ const apiBase = resolveApiBase(rootDir);
25
+ try {
26
+ const response = await fetchWithTimeout(`${apiBase}/templates/${agentName}/${agentVersion}`, {
27
+ method: 'POST',
28
+ headers: {
29
+ 'Content-Type': 'application/json',
30
+ 'Authorization': `Bearer ${license.key}`,
31
+ },
32
+ body: JSON.stringify({
33
+ machine_id: license.machine_id,
34
+ workspace: license.workspace,
35
+ }),
36
+ });
37
+ if (!response.ok) {
38
+ return null;
39
+ }
40
+ const encrypted = await response.json();
41
+ const templates = decryptBundle(encrypted, license.key);
42
+ return {
43
+ agent: agentName,
44
+ version: agentVersion,
45
+ templates,
46
+ source: 'remote',
47
+ };
48
+ }
49
+ catch {
50
+ // Network failure — caller should fall back to local templates
51
+ return null;
52
+ }
53
+ }
54
+ // ─── Decryption ─────────────────────────────────────────────
55
+ /**
56
+ * Derive the AES-256 key from the license key.
57
+ * Key = SHA-256(license_key + "opsx-template-key")
58
+ */
59
+ function deriveKey(licenseKey) {
60
+ return createHash('sha256')
61
+ .update(`${licenseKey}:opsx-template-key`)
62
+ .digest();
63
+ }
64
+ /**
65
+ * Decrypt an AES-256-GCM encrypted template bundle.
66
+ * Returns the template map (path → content).
67
+ */
68
+ function decryptBundle(bundle, licenseKey) {
69
+ const key = deriveKey(licenseKey);
70
+ const iv = Buffer.from(bundle.iv, 'base64');
71
+ const tag = Buffer.from(bundle.tag, 'base64');
72
+ const encrypted = Buffer.from(bundle.payload, 'base64');
73
+ const decipher = createDecipheriv('aes-256-gcm', key, iv);
74
+ decipher.setAuthTag(tag);
75
+ const decrypted = Buffer.concat([
76
+ decipher.update(encrypted),
77
+ decipher.final(),
78
+ ]);
79
+ return JSON.parse(decrypted.toString('utf-8'));
80
+ }
81
+ // ─── Utilities ──────────────────────────────────────────────
82
+ async function fetchWithTimeout(url, init) {
83
+ const controller = new AbortController();
84
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
85
+ try {
86
+ return await fetch(url, { ...init, signal: controller.signal });
87
+ }
88
+ finally {
89
+ clearTimeout(timeout);
90
+ }
91
+ }
92
+ //# sourceMappingURL=template-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-fetch.js","sourceRoot":"","sources":["../../src/licensing/template-fetch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Agent package validator — validates structure and safety of
3
+ * agent packages before loading their templates.
4
+ */
5
+ import { type ScanThreat } from './scanner.js';
6
+ export interface AgentValidationResult {
7
+ valid: boolean;
8
+ errors: string[];
9
+ warnings: string[];
10
+ threats: ScanThreat[];
11
+ }
12
+ /**
13
+ * Validate an agent package directory for safety:
14
+ * 1. Check structural requirements
15
+ * 2. Ensure no override of protected partials
16
+ * 3. Scan templates for injection patterns
17
+ * 4. Check for unrestricted dangerous tool usage
18
+ */
19
+ export declare function validateAgentPackage(agentDir: string, agentName: string): AgentValidationResult;
20
+ //# sourceMappingURL=agent-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-validator.d.ts","sourceRoot":"","sources":["../../src/security/agent-validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAYD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,qBAAqB,CAoD/F"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Agent package validator — validates structure and safety of
3
+ * agent packages before loading their templates.
4
+ */
5
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { scanForInjection } from './scanner.js';
8
+ // Partials exist per-agent-package (registered then cleared between packages).
9
+ // No cross-contamination is possible in the current architecture.
10
+ // Content scanning handles injection detection in partial files.
11
+ // Tool patterns that require safety context in agent templates
12
+ const DANGEROUS_TOOL_PATTERNS = [
13
+ /run_in_terminal.*mode.*async/is,
14
+ /run_in_terminal[^}]*(?!.*confirm)/is, // run_in_terminal without confirm mention nearby
15
+ ];
16
+ /**
17
+ * Validate an agent package directory for safety:
18
+ * 1. Check structural requirements
19
+ * 2. Ensure no override of protected partials
20
+ * 3. Scan templates for injection patterns
21
+ * 4. Check for unrestricted dangerous tool usage
22
+ */
23
+ export function validateAgentPackage(agentDir, agentName) {
24
+ const result = {
25
+ valid: true,
26
+ errors: [],
27
+ warnings: [],
28
+ threats: [],
29
+ };
30
+ // 1. Structural checks
31
+ const requiredDirs = ['agents'];
32
+ for (const dir of requiredDirs) {
33
+ if (!existsSync(join(agentDir, dir))) {
34
+ result.warnings.push(`Agent "${agentName}" is missing ${dir}/ directory.`);
35
+ }
36
+ }
37
+ // 2. Scan all template files for injection patterns
38
+ const templateDirs = ['agents', 'prompts', 'instructions', 'partials'];
39
+ for (const dir of templateDirs) {
40
+ const dirPath = join(agentDir, dir);
41
+ if (!existsSync(dirPath))
42
+ continue;
43
+ for (const file of readdirSync(dirPath)) {
44
+ if (!file.endsWith('.md') && !file.endsWith('.hbs'))
45
+ continue;
46
+ const content = readFileSync(join(dirPath, file), 'utf-8');
47
+ const fileSource = `agent:${agentName}/${dir}/${file}`;
48
+ const threats = scanForInjection(content, fileSource);
49
+ // Only flag critical threats as errors for agent packages
50
+ // (agent templates may legitimately mention security concepts)
51
+ const critical = threats.filter((t) => t.severity === 'critical');
52
+ if (critical.length > 0) {
53
+ result.threats.push(...critical);
54
+ result.errors.push(`Agent "${agentName}" template ${dir}/${file} contains ${critical.length} critical security pattern(s).`);
55
+ result.valid = false;
56
+ }
57
+ // Non-critical threats are warnings
58
+ const nonCritical = threats.filter((t) => t.severity !== 'critical');
59
+ if (nonCritical.length > 0) {
60
+ result.threats.push(...nonCritical);
61
+ result.warnings.push(`Agent "${agentName}" template ${dir}/${file} has ${nonCritical.length} security pattern(s) — review recommended.`);
62
+ }
63
+ }
64
+ }
65
+ return result;
66
+ }
67
+ //# sourceMappingURL=agent-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-validator.js","sourceRoot":"","sources":["../../src/security/agent-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Security barrel — re-export all security modules from a single entry point.
3
+ */
4
+ export { scanForInjection, scanForSecrets, scanCustomInstructions, scanPhilosophyCustom, scanConfigForSecrets, formatThreats, type ScanThreat, type ScanResult, } from './scanner.js';
5
+ export { validateAgentPackage, type AgentValidationResult, } from './agent-validator.js';
6
+ export { generateManifest, verifyManifest, type ManifestEntry, type IntegrityResult, } from './integrity.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Security barrel — re-export all security modules from a single entry point.
3
+ */
4
+ export { scanForInjection, scanForSecrets, scanCustomInstructions, scanPhilosophyCustom, scanConfigForSecrets, formatThreats, } from './scanner.js';
5
+ export { validateAgentPackage, } from './agent-validator.js';
6
+ export { generateManifest, verifyManifest, } from './integrity.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,GAGd,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,oBAAoB,GAErB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,gBAAgB,EAChB,cAAc,GAGf,MAAM,gBAAgB,CAAC"}