@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,229 @@
1
+ import Handlebars from 'handlebars';
2
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
3
+ import { join, basename } from 'node:path';
4
+ import { generateWatermark } from '@nepopsx/core';
5
+ import { applySteganography } from '../licensing/fingerprint.js';
6
+ // ─── Prototype pollution guard ──────────────────────────────
7
+ const BANNED_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
8
+ /**
9
+ * Deep-clone an object while stripping keys that could trigger
10
+ * Handlebars prototype pollution (e.g., {{constructor.constructor}}).
11
+ */
12
+ function sanitizeContext(obj) {
13
+ if (obj === null || obj === undefined)
14
+ return obj;
15
+ if (typeof obj !== 'object')
16
+ return obj;
17
+ if (Array.isArray(obj)) {
18
+ return obj.map(sanitizeContext);
19
+ }
20
+ const clean = {};
21
+ for (const [key, value] of Object.entries(obj)) {
22
+ if (BANNED_KEYS.has(key))
23
+ continue;
24
+ clean[key] = sanitizeContext(value);
25
+ }
26
+ return clean;
27
+ }
28
+ // ─── Register helpers ───────────────────────────────────────
29
+ Handlebars.registerHelper('eq', (a, b) => a === b);
30
+ Handlebars.registerHelper('neq', (a, b) => a !== b);
31
+ Handlebars.registerHelper('includes', (arr, val) => Array.isArray(arr) && arr.includes(val));
32
+ Handlebars.registerHelper('join', (arr, sep) => Array.isArray(arr) ? arr.join(sep) : '');
33
+ Handlebars.registerHelper('uppercase', (str) => str?.toUpperCase());
34
+ Handlebars.registerHelper('lowercase', (str) => str?.toLowerCase());
35
+ Handlebars.registerHelper('capitalize', (str) => str ? str.charAt(0).toUpperCase() + str.slice(1) : '');
36
+ // Index helper for numbered lists: {{idx @index}} → 1
37
+ Handlebars.registerHelper('idx', (i) => i + 1);
38
+ // Service filtering: {{#servicesByLang services "typescript"}}
39
+ Handlebars.registerHelper('servicesByLang', function (services, lang, options) {
40
+ const filtered = services.filter((s) => s.language === lang);
41
+ if (filtered.length === 0)
42
+ return '';
43
+ return filtered.map((s) => options.fn(s)).join('');
44
+ });
45
+ // Conditional block if workspace has a specific language
46
+ Handlebars.registerHelper('hasLanguage', function (services, lang, options) {
47
+ return services.some((s) => s.language === lang) ? options.fn(this) : '';
48
+ });
49
+ // Maturity badge
50
+ Handlebars.registerHelper('maturityBadge', (maturity) => {
51
+ switch (maturity) {
52
+ case 'production': return '[Mature]';
53
+ case 'evolving': return '[Evolving]';
54
+ case 'prototype': return '[Prototype]';
55
+ case 'legacy': return '[Legacy]';
56
+ default: return '';
57
+ }
58
+ });
59
+ // Safety rules block
60
+ Handlebars.registerHelper('safetyRules', function (config, options) {
61
+ const safety = config.safety;
62
+ if (!safety)
63
+ return '';
64
+ return options.fn(safety);
65
+ });
66
+ let _customInstructions = [];
67
+ let _philosophyBlock = '';
68
+ /**
69
+ * Set the philosophy markdown block for the current sync run.
70
+ */
71
+ export function setPhilosophyBlock(block) {
72
+ _philosophyBlock = block;
73
+ }
74
+ /**
75
+ * Set the custom instructions for the current sync run.
76
+ */
77
+ export function setCustomInstructions(customs) {
78
+ _customInstructions = customs;
79
+ }
80
+ // Helper: {{philosophyBlock}} — renders the philosophy as markdown
81
+ Handlebars.registerHelper('philosophyBlock', () => _philosophyBlock);
82
+ // Helper: {{customInstructions agentName}} — renders applicable custom instructions
83
+ // Pass "all" or omit to include all instructions. Pass an agent name to filter by applies_to.
84
+ Handlebars.registerHelper('customInstructions', (agentFileNameOrOptions) => {
85
+ if (_customInstructions.length === 0)
86
+ return '';
87
+ // When called as {{customInstructions}} with no args, Handlebars passes options as first arg
88
+ const agentFileName = typeof agentFileNameOrOptions === 'string' ? agentFileNameOrOptions : 'all';
89
+ const applicable = _customInstructions.filter((ci) => {
90
+ if (agentFileName === 'all' || agentFileName === 'worker') {
91
+ // Include all customs — no filtering by applies_to
92
+ return true;
93
+ }
94
+ // Filter by applies_to (if specified, agent name must match)
95
+ if (ci.applies_to && ci.applies_to.length > 0) {
96
+ return ci.applies_to.some((a) => agentFileName.includes(a));
97
+ }
98
+ return true;
99
+ });
100
+ if (applicable.length === 0)
101
+ return '';
102
+ const parts = [
103
+ '<!-- BEGIN CUSTOM INSTRUCTIONS -->',
104
+ '',
105
+ ];
106
+ for (const ci of applicable) {
107
+ parts.push(ci.content);
108
+ parts.push('');
109
+ }
110
+ parts.push('<!-- END CUSTOM INSTRUCTIONS -->');
111
+ return parts.join('\n');
112
+ });
113
+ /**
114
+ * Register all partials from an agent package's partials/ directory.
115
+ * .hbs partials are pre-rendered with config context; .md partials are included as-is.
116
+ */
117
+ export function registerAgentPartials(partialsDir, config, agentMeta) {
118
+ if (!existsSync(partialsDir))
119
+ return;
120
+ for (const file of readdirSync(partialsDir)) {
121
+ const fullPath = join(partialsDir, file);
122
+ const raw = readFileSync(fullPath, 'utf-8');
123
+ // Derive partial name: "constitutional.md" → "constitutional", "worker-context.md.hbs" → "worker-context"
124
+ let partialName = file;
125
+ if (partialName.endsWith('.hbs'))
126
+ partialName = partialName.slice(0, -4); // strip .hbs
127
+ if (partialName.endsWith('.md'))
128
+ partialName = partialName.slice(0, -3); // strip .md
129
+ if (file.endsWith('.hbs')) {
130
+ // Pre-render the Handlebars partial with config context, then register the output
131
+ const rendered = renderTemplate(raw, config, agentMeta);
132
+ Handlebars.registerPartial(partialName, rendered);
133
+ }
134
+ else {
135
+ // Plain markdown — register as-is
136
+ Handlebars.registerPartial(partialName, raw);
137
+ }
138
+ }
139
+ }
140
+ /**
141
+ * Unregister all partials (call between agent packages to avoid cross-contamination).
142
+ */
143
+ export function clearPartials(partialsDir) {
144
+ if (!existsSync(partialsDir))
145
+ return;
146
+ for (const file of readdirSync(partialsDir)) {
147
+ let partialName = file;
148
+ if (partialName.endsWith('.hbs'))
149
+ partialName = partialName.slice(0, -4);
150
+ if (partialName.endsWith('.md'))
151
+ partialName = partialName.slice(0, -3);
152
+ Handlebars.unregisterPartial(partialName);
153
+ }
154
+ }
155
+ /**
156
+ * Register partials from a remote template map keyed by relative file path.
157
+ * Returns the partial names so they can be unregistered after rendering.
158
+ */
159
+ export function registerAgentPartialsFromMap(templateMap, config, agentMeta) {
160
+ const partialNames = [];
161
+ for (const [relativePath, raw] of Object.entries(templateMap)) {
162
+ if (!relativePath.startsWith('partials/'))
163
+ continue;
164
+ let partialName = basename(relativePath);
165
+ if (partialName.endsWith('.hbs'))
166
+ partialName = partialName.slice(0, -4);
167
+ if (partialName.endsWith('.md'))
168
+ partialName = partialName.slice(0, -3);
169
+ if (relativePath.endsWith('.hbs')) {
170
+ Handlebars.registerPartial(partialName, renderTemplate(raw, config, agentMeta));
171
+ }
172
+ else {
173
+ Handlebars.registerPartial(partialName, raw);
174
+ }
175
+ partialNames.push(partialName);
176
+ }
177
+ return partialNames;
178
+ }
179
+ export function clearPartialNames(partialNames) {
180
+ for (const partialName of partialNames) {
181
+ Handlebars.unregisterPartial(partialName);
182
+ }
183
+ }
184
+ /**
185
+ * Render a Handlebars template string with workspace config context.
186
+ * Context is sanitized to prevent prototype pollution attacks.
187
+ */
188
+ export function renderTemplate(templateSource, config, agentMeta) {
189
+ const context = {
190
+ config,
191
+ agent: agentMeta,
192
+ timestamp: new Date().toISOString().split('T')[0],
193
+ };
194
+ const safeContext = sanitizeContext(context);
195
+ const template = Handlebars.compile(templateSource, { noEscape: true });
196
+ return template(safeContext);
197
+ }
198
+ /**
199
+ * Render a template file.
200
+ */
201
+ export function renderTemplateFile(templatePath, config, agentMeta) {
202
+ const source = readFileSync(templatePath, 'utf-8');
203
+ return renderTemplate(source, config, agentMeta);
204
+ }
205
+ // ─── Watermark + fingerprint post-processing ────────────────
206
+ let _watermarkData = null;
207
+ /**
208
+ * Set watermark data for the current sync run.
209
+ * When set, every rendered file gets a watermark header + steganographic fingerprint.
210
+ * Pass null to disable (e.g., dev mode / free tier).
211
+ */
212
+ export function setWatermarkData(data) {
213
+ _watermarkData = data;
214
+ }
215
+ /**
216
+ * Apply watermark header + steganographic fingerprint to rendered content.
217
+ * Should be called AFTER Handlebars rendering, on the final output.
218
+ */
219
+ export function applyLicenseWatermark(content) {
220
+ if (!_watermarkData)
221
+ return content;
222
+ // 1. Prepend visible watermark as first line
223
+ const watermarkLine = generateWatermark(_watermarkData);
224
+ let result = watermarkLine + '\n' + content;
225
+ // 2. Apply steganographic fingerprint
226
+ result = applySteganography(result, _watermarkData.fingerprint);
227
+ return result;
228
+ }
229
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/generator/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface WriteOperation {
2
+ path: string;
3
+ content: string;
4
+ source: string;
5
+ }
6
+ export interface WriteResult {
7
+ created: string[];
8
+ updated: string[];
9
+ unchanged: string[];
10
+ }
11
+ /**
12
+ * Write generated files to disk. Diff-aware: only writes if content changed.
13
+ */
14
+ export declare function writeGeneratedFiles(rootDir: string, operations: WriteOperation[], dryRun: boolean): WriteResult;
15
+ /**
16
+ * Print write results to console.
17
+ */
18
+ export declare function printWriteResult(result: WriteResult, dryRun: boolean): void;
19
+ //# sourceMappingURL=writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/generator/writer.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,OAAO,GAAG,WAAW,CA2B/G;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAuB3E"}
@@ -0,0 +1,59 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import chalk from 'chalk';
4
+ /**
5
+ * Write generated files to disk. Diff-aware: only writes if content changed.
6
+ */
7
+ export function writeGeneratedFiles(rootDir, operations, dryRun) {
8
+ const result = { created: [], updated: [], unchanged: [] };
9
+ for (const op of operations) {
10
+ const fullPath = join(rootDir, op.path);
11
+ const dir = dirname(fullPath);
12
+ if (existsSync(fullPath)) {
13
+ const existing = readFileSync(fullPath, 'utf-8');
14
+ if (existing === op.content) {
15
+ result.unchanged.push(op.path);
16
+ continue;
17
+ }
18
+ if (!dryRun) {
19
+ writeFileSync(fullPath, op.content, 'utf-8');
20
+ }
21
+ result.updated.push(op.path);
22
+ }
23
+ else {
24
+ if (!dryRun) {
25
+ mkdirSync(dir, { recursive: true });
26
+ writeFileSync(fullPath, op.content, 'utf-8');
27
+ }
28
+ result.created.push(op.path);
29
+ }
30
+ }
31
+ return result;
32
+ }
33
+ /**
34
+ * Print write results to console.
35
+ */
36
+ export function printWriteResult(result, dryRun) {
37
+ const prefix = dryRun ? chalk.dim('[dry-run] ') : '';
38
+ if (result.created.length > 0) {
39
+ console.log(`\n${prefix}${chalk.green('Created:')}`);
40
+ for (const f of result.created)
41
+ console.log(` ${chalk.green('+')} ${f}`);
42
+ }
43
+ if (result.updated.length > 0) {
44
+ console.log(`\n${prefix}${chalk.yellow('Updated:')}`);
45
+ for (const f of result.updated)
46
+ console.log(` ${chalk.yellow('~')} ${f}`);
47
+ }
48
+ if (result.unchanged.length > 0) {
49
+ console.log(`\n${prefix}${chalk.dim(`Unchanged: ${result.unchanged.length} file(s)`)}`);
50
+ }
51
+ const total = result.created.length + result.updated.length;
52
+ if (total === 0) {
53
+ console.log(chalk.dim('\nNo changes needed.'));
54
+ }
55
+ else {
56
+ console.log(`\n${prefix}${chalk.bold(`${total} file(s) ${dryRun ? 'would be' : ''} written.`)}`);
57
+ }
58
+ }
59
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/generator/writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ import { Command } from 'commander';
2
+ import { initCommand } from './commands/init.js';
3
+ import { syncCommand } from './commands/sync.js';
4
+ import { doctorCommand } from './commands/doctor.js';
5
+ import { installCommand } from './commands/install.js';
6
+ import { activateCommand } from './commands/activate.js';
7
+ import { decodeCommand } from './commands/decode.js';
8
+ import { serverClearCommand, serverSetCommand, serverShowCommand, } from './commands/server.js';
9
+ const program = new Command();
10
+ program
11
+ .name('opsx')
12
+ .description('OPSX — AI Agent Platform for Engineering Teams')
13
+ .version('0.0.1');
14
+ program
15
+ .command('init')
16
+ .description('Initialize a new OPSX workspace (interactive setup)')
17
+ .option('--non-interactive', 'Skip prompts, use defaults + auto-detect')
18
+ .action(initCommand);
19
+ program
20
+ .command('sync')
21
+ .description('Generate .github/ files from workspace config + installed agents')
22
+ .option('-c, --config <path>', 'Path to workspace.yaml', '.opsx/workspace.yaml')
23
+ .option('--dry-run', 'Preview changes without writing files')
24
+ .option('--dev', 'Dev mode — bypass license checks (for OPSX agent developers)')
25
+ .action(syncCommand);
26
+ program
27
+ .command('install <agent>')
28
+ .description('Install an agent package (e.g., feature-factory, qa-commander)')
29
+ .option('--version <ver>', 'Specific version to install')
30
+ .action(installCommand);
31
+ program
32
+ .command('doctor')
33
+ .description('Validate workspace.yaml and check workspace health')
34
+ .option('-c, --config <path>', 'Path to workspace.yaml', '.opsx/workspace.yaml')
35
+ .action(doctorCommand);
36
+ program
37
+ .command('activate <key>')
38
+ .description('Activate an OPSX license key for this machine')
39
+ .option('-c, --config <path>', 'Path to workspace.yaml', '.opsx/workspace.yaml')
40
+ .action(activateCommand);
41
+ program
42
+ .command('decode <file>')
43
+ .description('Forensic decode — extract fingerprint from a generated file')
44
+ .action(decodeCommand);
45
+ const serverProgram = program
46
+ .command('server')
47
+ .description('Manage the OPSX backend server URL for this workspace');
48
+ serverProgram
49
+ .command('show')
50
+ .description('Show the effective OPSX backend server URL')
51
+ .action(serverShowCommand);
52
+ serverProgram
53
+ .command('set <url>')
54
+ .description('Persist an OPSX backend server URL in .opsx/config.json')
55
+ .action(serverSetCommand);
56
+ serverProgram
57
+ .command('clear')
58
+ .description('Remove the persisted OPSX backend server URL override')
59
+ .action(serverClearCommand);
60
+ program.parse();
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,gDAAgD,CAAC;KAC7D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,qDAAqD,CAAC;KAClE,MAAM,CAAC,mBAAmB,EAAE,0CAA0C,CAAC;KACvE,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,kEAAkE,CAAC;KAC/E,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,sBAAsB,CAAC;KAC/E,MAAM,CAAC,WAAW,EAAE,uCAAuC,CAAC;KAC5D,MAAM,CAAC,OAAO,EAAE,8DAA8D,CAAC;KAC/E,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,iBAAiB,EAAE,6BAA6B,CAAC;KACxD,MAAM,CAAC,cAAc,CAAC,CAAC;AAE1B,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,oDAAoD,CAAC;KACjE,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,sBAAsB,CAAC;KAC/E,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,sBAAsB,CAAC;KAC/E,MAAM,CAAC,eAAe,CAAC,CAAC;AAE3B,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,6DAA6D,CAAC;KAC1E,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,MAAM,aAAa,GAAG,OAAO;KAC1B,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,uDAAuD,CAAC,CAAC;AAExE,aAAa;KACV,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,4CAA4C,CAAC;KACzD,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAE7B,aAAa;KACV,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,yDAAyD,CAAC;KACtE,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAE5B,aAAa;KACV,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAE9B,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Fingerprinting — embeds traceable customer identity into generated files.
3
+ *
4
+ * Two levels:
5
+ * A) Visible watermark (<!-- OPSX ... FP: abc123 -->) — handled by render.ts
6
+ * B) Steganographic fingerprint — invisible encoding in prose choices
7
+ *
8
+ * Steganographic encoding:
9
+ * - Encodes a customer ID (up to 32 bits) into binary
10
+ * - Each bit is encoded as a word/phrase variant in the template
11
+ * - Variants are semantically equivalent (same meaning)
12
+ * - Even if the visible watermark is stripped, the stego fingerprint survives
13
+ */
14
+ export interface StegoVariant {
15
+ /** Position index in the output where this variant applies */
16
+ id: string;
17
+ /** Variant for bit = 0 */
18
+ zero: string;
19
+ /** Variant for bit = 1 */
20
+ one: string;
21
+ }
22
+ /**
23
+ * Derive a numeric customer ID (24 bits) from the fingerprint hash.
24
+ */
25
+ export declare function fingerprintToId(fingerprint: string): number;
26
+ /**
27
+ * Apply steganographic fingerprint to a rendered template.
28
+ * Replaces the "zero" variants with "one" variants based on the customer's bits.
29
+ *
30
+ * Templates should be written using the "zero" variant of each phrase.
31
+ * This function selectively replaces some with the "one" variant based on fingerprint.
32
+ */
33
+ export declare function applySteganography(content: string, fingerprint: string): string;
34
+ /**
35
+ * Decode a steganographic fingerprint from a rendered file.
36
+ * Returns the extracted customer ID, or null if decoding fails.
37
+ */
38
+ export declare function decodeSteganography(content: string): number | null;
39
+ /**
40
+ * Full forensic decode: extract both visible and steganographic fingerprints.
41
+ */
42
+ export declare function forensicDecode(content: string): {
43
+ visible_fp: string | null;
44
+ stego_id: number | null;
45
+ stego_fp_hex: string | null;
46
+ confidence: number;
47
+ };
48
+ //# sourceMappingURL=fingerprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/licensing/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC;IACX,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAmCD;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAG3D;AAaD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAmB/E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwBlE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG;IAC/C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB,CA2BA"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Fingerprinting — embeds traceable customer identity into generated files.
3
+ *
4
+ * Two levels:
5
+ * A) Visible watermark (<!-- OPSX ... FP: abc123 -->) — handled by render.ts
6
+ * B) Steganographic fingerprint — invisible encoding in prose choices
7
+ *
8
+ * Steganographic encoding:
9
+ * - Encodes a customer ID (up to 32 bits) into binary
10
+ * - Each bit is encoded as a word/phrase variant in the template
11
+ * - Variants are semantically equivalent (same meaning)
12
+ * - Even if the visible watermark is stripped, the stego fingerprint survives
13
+ */
14
+ // ─── Variant table ──────────────────────────────────────────
15
+ // Each pair of phrases is semantically identical but encodes 1 bit.
16
+ // We use 24 variants = 24 bits = 16M unique customers.
17
+ const VARIANTS = [
18
+ { id: 'v01', zero: 'Before starting work', one: 'Prior to beginning work' },
19
+ { id: 'v02', zero: 'Make sure to', one: 'Ensure that you' },
20
+ { id: 'v03', zero: 'You must', one: 'You are required to' },
21
+ { id: 'v04', zero: 'when finished', one: 'upon completion' },
22
+ { id: 'v05', zero: 'check the', one: 'verify the' },
23
+ { id: 'v06', zero: 'Run the', one: 'Execute the' },
24
+ { id: 'v07', zero: 'do not', one: 'never' },
25
+ { id: 'v08', zero: 'immediately after', one: 'right after' },
26
+ { id: 'v09', zero: 'If an error occurs', one: 'In case of failure' },
27
+ { id: 'v10', zero: 'the following steps', one: 'these steps' },
28
+ { id: 'v11', zero: 'proceed with', one: 'continue with' },
29
+ { id: 'v12', zero: 'Review the output', one: 'Inspect the output' },
30
+ { id: 'v13', zero: 'as described below', one: 'as outlined below' },
31
+ { id: 'v14', zero: 'report back', one: 'provide feedback' },
32
+ { id: 'v15', zero: 'Begin by', one: 'Start by' },
33
+ { id: 'v16', zero: 'complete the task', one: 'finish the task' },
34
+ { id: 'v17', zero: 'all required', one: 'every required' },
35
+ { id: 'v18', zero: 'confirm that', one: 'validate that' },
36
+ { id: 'v19', zero: 'at this point', one: 'at this stage' },
37
+ { id: 'v20', zero: 'look for', one: 'search for' },
38
+ { id: 'v21', zero: 'important to note', one: 'worth noting' },
39
+ { id: 'v22', zero: 'as a result', one: 'consequently' },
40
+ { id: 'v23', zero: 'based on', one: 'according to' },
41
+ { id: 'v24', zero: 'in addition', one: 'additionally' },
42
+ ];
43
+ // ─── Encoding ───────────────────────────────────────────────
44
+ /**
45
+ * Derive a numeric customer ID (24 bits) from the fingerprint hash.
46
+ */
47
+ export function fingerprintToId(fingerprint) {
48
+ // Use the first 6 hex chars (24 bits) of the fingerprint
49
+ return parseInt(fingerprint.substring(0, 6), 16) & 0xFFFFFF;
50
+ }
51
+ /**
52
+ * Convert a customer ID to a 24-bit binary array.
53
+ */
54
+ function idToBits(id) {
55
+ const bits = [];
56
+ for (let i = 23; i >= 0; i--) {
57
+ bits.push(((id >> i) & 1) === 1);
58
+ }
59
+ return bits;
60
+ }
61
+ /**
62
+ * Apply steganographic fingerprint to a rendered template.
63
+ * Replaces the "zero" variants with "one" variants based on the customer's bits.
64
+ *
65
+ * Templates should be written using the "zero" variant of each phrase.
66
+ * This function selectively replaces some with the "one" variant based on fingerprint.
67
+ */
68
+ export function applySteganography(content, fingerprint) {
69
+ const customerId = fingerprintToId(fingerprint);
70
+ const bits = idToBits(customerId);
71
+ let result = content;
72
+ for (let i = 0; i < VARIANTS.length; i++) {
73
+ const variant = VARIANTS[i];
74
+ if (bits[i]) {
75
+ // Bit is 1 → replace zero variant with one variant
76
+ // Use case-insensitive match for first occurrence only
77
+ const zeroRegex = new RegExp(escapeRegex(variant.zero), 'i');
78
+ if (zeroRegex.test(result)) {
79
+ result = result.replace(zeroRegex, matchCase(variant.zero, variant.one, result));
80
+ }
81
+ }
82
+ // Bit is 0 → leave the zero variant as-is (already in template)
83
+ }
84
+ return result;
85
+ }
86
+ /**
87
+ * Decode a steganographic fingerprint from a rendered file.
88
+ * Returns the extracted customer ID, or null if decoding fails.
89
+ */
90
+ export function decodeSteganography(content) {
91
+ let bitsFound = 0;
92
+ let id = 0;
93
+ const lowerContent = content.toLowerCase();
94
+ for (let i = 0; i < VARIANTS.length; i++) {
95
+ const variant = VARIANTS[i];
96
+ const hasZero = lowerContent.includes(variant.zero.toLowerCase());
97
+ const hasOne = lowerContent.includes(variant.one.toLowerCase());
98
+ if (hasOne && !hasZero) {
99
+ // Bit is 1
100
+ id |= (1 << (23 - i));
101
+ bitsFound++;
102
+ }
103
+ else if (hasZero && !hasOne) {
104
+ // Bit is 0
105
+ bitsFound++;
106
+ }
107
+ // If neither or both found, bit is ambiguous — skip
108
+ }
109
+ // Need at least 12 clear bits to have a meaningful decode
110
+ if (bitsFound < 12)
111
+ return null;
112
+ return id;
113
+ }
114
+ /**
115
+ * Full forensic decode: extract both visible and steganographic fingerprints.
116
+ */
117
+ export function forensicDecode(content) {
118
+ // Visible fingerprint from watermark
119
+ const watermarkRegex = /FP: ([a-f0-9]+)/;
120
+ const watermarkMatch = content.match(watermarkRegex);
121
+ const visible_fp = watermarkMatch ? watermarkMatch[1] : null;
122
+ // Steganographic fingerprint
123
+ const stego_id = decodeSteganography(content);
124
+ const stego_fp_hex = stego_id !== null
125
+ ? stego_id.toString(16).padStart(6, '0')
126
+ : null;
127
+ // Confidence: count how many bits we could decode
128
+ let decodable = 0;
129
+ const lowerContent = content.toLowerCase();
130
+ for (const variant of VARIANTS) {
131
+ const hasZero = lowerContent.includes(variant.zero.toLowerCase());
132
+ const hasOne = lowerContent.includes(variant.one.toLowerCase());
133
+ if ((hasOne && !hasZero) || (hasZero && !hasOne))
134
+ decodable++;
135
+ }
136
+ return {
137
+ visible_fp,
138
+ stego_id,
139
+ stego_fp_hex,
140
+ confidence: decodable / VARIANTS.length,
141
+ };
142
+ }
143
+ // ─── Utilities ──────────────────────────────────────────────
144
+ function escapeRegex(str) {
145
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
146
+ }
147
+ /**
148
+ * Match the case pattern of the source phrase in the actual content,
149
+ * and apply it to the replacement phrase.
150
+ */
151
+ function matchCase(source, replacement, content) {
152
+ // Find the actual match in content to preserve casing
153
+ const match = content.match(new RegExp(escapeRegex(source), 'i'));
154
+ if (!match)
155
+ return replacement;
156
+ const actual = match[0];
157
+ // If source starts with uppercase in content, capitalize replacement
158
+ if (actual[0] === actual[0].toUpperCase()) {
159
+ return replacement.charAt(0).toUpperCase() + replacement.slice(1);
160
+ }
161
+ return replacement;
162
+ }
163
+ //# sourceMappingURL=fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/licensing/fingerprint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Licensing barrel — re-export all licensing modules.
3
+ */
4
+ export { readLicense, writeLicense, activateLicense, validateLicense, enforceTierLimits, isDevMode, type ActivationResult, type TierViolation, } from './license-manager.js';
5
+ export { fetchRemoteTemplates, type TemplateBundle, } from './template-fetch.js';
6
+ export { applySteganography, decodeSteganography, forensicDecode, fingerprintToId, } from './fingerprint.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/licensing/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,WAAW,EACX,YAAY,EACZ,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,eAAe,GAChB,MAAM,kBAAkB,CAAC"}