aiox-core 5.0.0 → 5.0.2

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 (91) hide show
  1. package/.aiox-core/data/entity-registry.yaml +5297 -1814
  2. package/.aiox-core/data/registry-update-log.jsonl +2 -0
  3. package/.aiox-core/development/templates/service-template/README.md.hbs +158 -158
  4. package/.aiox-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
  5. package/.aiox-core/development/templates/service-template/client.ts.hbs +403 -403
  6. package/.aiox-core/development/templates/service-template/errors.ts.hbs +182 -182
  7. package/.aiox-core/development/templates/service-template/index.ts.hbs +120 -120
  8. package/.aiox-core/development/templates/service-template/package.json.hbs +87 -87
  9. package/.aiox-core/development/templates/service-template/types.ts.hbs +145 -145
  10. package/.aiox-core/development/templates/squad-template/LICENSE +21 -21
  11. package/.aiox-core/infrastructure/scripts/tool-resolver.js +4 -4
  12. package/.aiox-core/infrastructure/templates/aiox-sync.yaml.template +182 -182
  13. package/.aiox-core/infrastructure/templates/coderabbit.yaml.template +279 -279
  14. package/.aiox-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
  15. package/.aiox-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
  16. package/.aiox-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
  17. package/.aiox-core/infrastructure/templates/gitignore/gitignore-aiox-base.tmpl +63 -63
  18. package/.aiox-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
  19. package/.aiox-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
  20. package/.aiox-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
  21. package/.aiox-core/install-manifest.yaml +58 -58
  22. package/.aiox-core/local-config.yaml.template +71 -71
  23. package/.aiox-core/monitor/hooks/lib/__init__.py +1 -1
  24. package/.aiox-core/monitor/hooks/lib/enrich.py +58 -58
  25. package/.aiox-core/monitor/hooks/lib/send_event.py +47 -47
  26. package/.aiox-core/monitor/hooks/notification.py +29 -29
  27. package/.aiox-core/monitor/hooks/post_tool_use.py +45 -45
  28. package/.aiox-core/monitor/hooks/pre_compact.py +29 -29
  29. package/.aiox-core/monitor/hooks/pre_tool_use.py +40 -40
  30. package/.aiox-core/monitor/hooks/stop.py +29 -29
  31. package/.aiox-core/monitor/hooks/subagent_stop.py +29 -29
  32. package/.aiox-core/monitor/hooks/user_prompt_submit.py +38 -38
  33. package/.aiox-core/product/templates/adr.hbs +125 -125
  34. package/.aiox-core/product/templates/dbdr.hbs +241 -241
  35. package/.aiox-core/product/templates/engine/elicitation.js +2 -3
  36. package/.aiox-core/product/templates/epic.hbs +212 -212
  37. package/.aiox-core/product/templates/pmdr.hbs +186 -186
  38. package/.aiox-core/product/templates/prd-v2.0.hbs +216 -216
  39. package/.aiox-core/product/templates/prd.hbs +201 -201
  40. package/.aiox-core/product/templates/story.hbs +263 -263
  41. package/.aiox-core/product/templates/task.hbs +170 -170
  42. package/.aiox-core/product/templates/tmpl-comment-on-examples.sql +158 -158
  43. package/.aiox-core/product/templates/tmpl-migration-script.sql +91 -91
  44. package/.aiox-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
  45. package/.aiox-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
  46. package/.aiox-core/product/templates/tmpl-rls-roles.sql +135 -135
  47. package/.aiox-core/product/templates/tmpl-rls-simple.sql +77 -77
  48. package/.aiox-core/product/templates/tmpl-rls-tenant.sql +152 -152
  49. package/.aiox-core/product/templates/tmpl-rollback-script.sql +77 -77
  50. package/.aiox-core/product/templates/tmpl-seed-data.sql +140 -140
  51. package/.aiox-core/product/templates/tmpl-smoke-test.sql +16 -16
  52. package/.aiox-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
  53. package/.aiox-core/product/templates/tmpl-stored-proc.sql +140 -140
  54. package/.aiox-core/product/templates/tmpl-trigger.sql +152 -152
  55. package/.aiox-core/product/templates/tmpl-view-materialized.sql +133 -133
  56. package/.aiox-core/product/templates/tmpl-view.sql +177 -177
  57. package/.aiox-core/scripts/pm.sh +0 -0
  58. package/.claude/hooks/code-intel-pretool.cjs +107 -0
  59. package/.claude/hooks/enforce-architecture-first.py +196 -196
  60. package/.claude/hooks/mind-clone-governance.py +192 -192
  61. package/.claude/hooks/read-protection.py +151 -151
  62. package/.claude/hooks/slug-validation.py +176 -176
  63. package/.claude/hooks/sql-governance.py +182 -182
  64. package/.claude/hooks/write-path-validation.py +194 -194
  65. package/LICENSE +33 -33
  66. package/bin/aiox-graph.js +0 -0
  67. package/bin/aiox-minimal.js +0 -0
  68. package/bin/aiox.js +0 -0
  69. package/docs/guides/aios-workflows/README.md +247 -0
  70. package/docs/guides/aios-workflows/bob-orchestrator-workflow.md +1536 -0
  71. package/package.json +1 -1
  72. package/packages/aiox-install/bin/aiox-install.js +0 -0
  73. package/packages/aiox-install/bin/edmcp.js +0 -0
  74. package/packages/aiox-pro-cli/bin/aiox-pro.js +0 -0
  75. package/packages/installer/src/wizard/pro-setup.js +210 -123
  76. package/pro/README.md +66 -0
  77. package/pro/license/degradation.js +220 -0
  78. package/pro/license/errors.js +450 -0
  79. package/pro/license/feature-gate.js +354 -0
  80. package/pro/license/index.js +181 -0
  81. package/pro/license/license-api.js +679 -0
  82. package/pro/license/license-cache.js +523 -0
  83. package/pro/license/license-crypto.js +303 -0
  84. package/scripts/check-markdown-links.py +352 -352
  85. package/scripts/dashboard-parallel-dev.sh +0 -0
  86. package/scripts/dashboard-parallel-phase3.sh +0 -0
  87. package/scripts/dashboard-parallel-phase4.sh +0 -0
  88. package/scripts/glue/README.md +355 -0
  89. package/scripts/glue/compose-agent-prompt.cjs +362 -0
  90. package/scripts/install-monitor-hooks.sh +0 -0
  91. package/.aiox-core/lib/build.json +0 -1
@@ -0,0 +1,303 @@
1
+ /**
2
+ * License Crypto Module
3
+ *
4
+ * Provides cryptographic utilities for license cache encryption:
5
+ * - Machine ID generation (deterministic fingerprint)
6
+ * - PBKDF2 key derivation
7
+ * - AES-256-GCM encryption/decryption
8
+ * - HMAC-SHA256 integrity verification
9
+ *
10
+ * @module pro/license/license-crypto
11
+ * @see ADR-PRO-003 - Feature Gating & Licensing
12
+ * @see Story PRO-6 - License Key & Feature Gating System
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const crypto = require('crypto');
18
+ const os = require('os');
19
+
20
+ /**
21
+ * Configuration constants for cryptographic operations.
22
+ * These values follow security best practices per ADR-PRO-003.
23
+ */
24
+ const CONFIG = {
25
+ // PBKDF2 settings
26
+ PBKDF2_ITERATIONS: 100000, // Minimum per ADR-PRO-003
27
+ PBKDF2_KEY_LENGTH: 32, // 256 bits for AES-256
28
+ PBKDF2_DIGEST: 'sha256',
29
+
30
+ // AES-256-GCM settings
31
+ AES_ALGORITHM: 'aes-256-gcm',
32
+ AES_IV_LENGTH: 12, // 96 bits recommended for GCM
33
+ AES_TAG_LENGTH: 16, // 128 bits auth tag
34
+
35
+ // HMAC settings
36
+ HMAC_ALGORITHM: 'sha256',
37
+
38
+ // Salt settings
39
+ SALT_LENGTH: 16, // 128 bits
40
+ };
41
+
42
+ /**
43
+ * Generate a deterministic machine identifier.
44
+ *
45
+ * Combines hostname + CPU model + first MAC address to create
46
+ * a unique but reproducible identifier for this machine.
47
+ *
48
+ * @returns {string} SHA-256 hash of machine fingerprint components
49
+ */
50
+ function generateMachineId() {
51
+ const components = [];
52
+
53
+ // Hostname
54
+ const hostname = os.hostname();
55
+ components.push(hostname);
56
+
57
+ // CPU model (first CPU)
58
+ const cpus = os.cpus();
59
+ if (cpus.length > 0) {
60
+ components.push(cpus[0].model);
61
+ }
62
+
63
+ // First non-internal MAC address
64
+ const networkInterfaces = os.networkInterfaces();
65
+ for (const [, interfaces] of Object.entries(networkInterfaces)) {
66
+ for (const iface of interfaces) {
67
+ if (!iface.internal && iface.mac && iface.mac !== '00:00:00:00:00:00') {
68
+ components.push(iface.mac);
69
+ break;
70
+ }
71
+ }
72
+ // Only use first valid MAC
73
+ if (components.length > 2) {
74
+ break;
75
+ }
76
+ }
77
+
78
+ // Create deterministic hash
79
+ const fingerprint = components.join('|');
80
+ return crypto.createHash('sha256').update(fingerprint).digest('hex');
81
+ }
82
+
83
+ /**
84
+ * Generate a cryptographically secure random salt.
85
+ *
86
+ * @param {number} [length=16] - Salt length in bytes
87
+ * @returns {Buffer} Random salt buffer
88
+ */
89
+ function generateSalt(length = CONFIG.SALT_LENGTH) {
90
+ return crypto.randomBytes(length);
91
+ }
92
+
93
+ /**
94
+ * Derive an encryption key from machine ID using PBKDF2.
95
+ *
96
+ * Uses 100,000 iterations minimum per ADR-PRO-003 security requirements.
97
+ *
98
+ * @param {string} machineId - Machine identifier from generateMachineId()
99
+ * @param {Buffer|string} salt - Random salt (Buffer or hex string)
100
+ * @returns {Buffer} 256-bit derived key
101
+ */
102
+ function deriveCacheKey(machineId, salt) {
103
+ const saltBuffer = Buffer.isBuffer(salt) ? salt : Buffer.from(salt, 'hex');
104
+
105
+ return crypto.pbkdf2Sync(
106
+ machineId,
107
+ saltBuffer,
108
+ CONFIG.PBKDF2_ITERATIONS,
109
+ CONFIG.PBKDF2_KEY_LENGTH,
110
+ CONFIG.PBKDF2_DIGEST,
111
+ );
112
+ }
113
+
114
+ /**
115
+ * Encrypt data using AES-256-GCM.
116
+ *
117
+ * Returns an object containing the encrypted ciphertext, initialization vector,
118
+ * and authentication tag for integrity verification.
119
+ *
120
+ * @param {string|object} data - Data to encrypt (objects are JSON stringified)
121
+ * @param {Buffer|string} key - 256-bit encryption key (Buffer or hex string)
122
+ * @returns {{ ciphertext: string, iv: string, tag: string }} Encrypted data components (hex encoded)
123
+ * @throws {Error} If encryption fails
124
+ */
125
+ function encrypt(data, key) {
126
+ const keyBuffer = Buffer.isBuffer(key) ? key : Buffer.from(key, 'hex');
127
+
128
+ if (keyBuffer.length !== 32) {
129
+ throw new Error('Encryption key must be 256 bits (32 bytes)');
130
+ }
131
+
132
+ // Generate random IV
133
+ const iv = crypto.randomBytes(CONFIG.AES_IV_LENGTH);
134
+
135
+ // Stringify objects
136
+ const plaintext = typeof data === 'object' ? JSON.stringify(data) : String(data);
137
+
138
+ // Create cipher and encrypt
139
+ const cipher = crypto.createCipheriv(CONFIG.AES_ALGORITHM, keyBuffer, iv, {
140
+ authTagLength: CONFIG.AES_TAG_LENGTH,
141
+ });
142
+
143
+ let ciphertext = cipher.update(plaintext, 'utf8', 'hex');
144
+ ciphertext += cipher.final('hex');
145
+
146
+ // Get auth tag
147
+ const tag = cipher.getAuthTag();
148
+
149
+ return {
150
+ ciphertext,
151
+ iv: iv.toString('hex'),
152
+ tag: tag.toString('hex'),
153
+ };
154
+ }
155
+
156
+ /**
157
+ * Decrypt data using AES-256-GCM.
158
+ *
159
+ * Verifies the authentication tag to ensure data integrity.
160
+ *
161
+ * @param {{ ciphertext: string, iv: string, tag: string }} encryptedData - Encrypted data object
162
+ * @param {Buffer|string} key - 256-bit encryption key (Buffer or hex string)
163
+ * @param {boolean} [parseJson=true] - Whether to parse result as JSON
164
+ * @returns {string|object} Decrypted data
165
+ * @throws {Error} If decryption fails or authentication fails
166
+ */
167
+ function decrypt(encryptedData, key, parseJson = true) {
168
+ const { ciphertext, iv, tag } = encryptedData;
169
+
170
+ const keyBuffer = Buffer.isBuffer(key) ? key : Buffer.from(key, 'hex');
171
+
172
+ if (keyBuffer.length !== 32) {
173
+ throw new Error('Decryption key must be 256 bits (32 bytes)');
174
+ }
175
+
176
+ const ivBuffer = Buffer.from(iv, 'hex');
177
+ const tagBuffer = Buffer.from(tag, 'hex');
178
+
179
+ // Create decipher
180
+ const decipher = crypto.createDecipheriv(CONFIG.AES_ALGORITHM, keyBuffer, ivBuffer, {
181
+ authTagLength: CONFIG.AES_TAG_LENGTH,
182
+ });
183
+
184
+ decipher.setAuthTag(tagBuffer);
185
+
186
+ let plaintext = decipher.update(ciphertext, 'hex', 'utf8');
187
+ plaintext += decipher.final('utf8');
188
+
189
+ // Optionally parse as JSON
190
+ if (parseJson) {
191
+ try {
192
+ return JSON.parse(plaintext);
193
+ } catch {
194
+ // Return as string if not valid JSON
195
+ return plaintext;
196
+ }
197
+ }
198
+
199
+ return plaintext;
200
+ }
201
+
202
+ /**
203
+ * Compute HMAC-SHA256 for data integrity verification.
204
+ *
205
+ * @param {string|Buffer} data - Data to compute HMAC for
206
+ * @param {Buffer|string} key - HMAC key (Buffer or hex string)
207
+ * @returns {string} HMAC as hex string
208
+ */
209
+ function computeHMAC(data, key) {
210
+ const keyBuffer = Buffer.isBuffer(key) ? key : Buffer.from(key, 'hex');
211
+ const dataString = Buffer.isBuffer(data) ? data.toString('utf8') : String(data);
212
+
213
+ return crypto.createHmac(CONFIG.HMAC_ALGORITHM, keyBuffer).update(dataString).digest('hex');
214
+ }
215
+
216
+ /**
217
+ * Verify HMAC matches expected value.
218
+ *
219
+ * Uses timing-safe comparison to prevent timing attacks.
220
+ *
221
+ * @param {string|Buffer} data - Data to verify
222
+ * @param {Buffer|string} key - HMAC key
223
+ * @param {string} expectedHmac - Expected HMAC value (hex string)
224
+ * @returns {boolean} true if HMAC matches
225
+ */
226
+ function verifyHMAC(data, key, expectedHmac) {
227
+ const computedHmac = computeHMAC(data, key);
228
+
229
+ // Use timing-safe comparison
230
+ const computedBuffer = Buffer.from(computedHmac, 'hex');
231
+ const expectedBuffer = Buffer.from(expectedHmac, 'hex');
232
+
233
+ if (computedBuffer.length !== expectedBuffer.length) {
234
+ return false;
235
+ }
236
+
237
+ return crypto.timingSafeEqual(computedBuffer, expectedBuffer);
238
+ }
239
+
240
+ /**
241
+ * Mask a license key for display.
242
+ *
243
+ * Shows only first and last 4 characters: PRO-XXXX-****-****-XXXX
244
+ * CRITICAL: Always use this function when logging or displaying keys.
245
+ *
246
+ * @param {string} key - Full license key
247
+ * @returns {string} Masked key for display
248
+ */
249
+ function maskKey(key) {
250
+ if (!key || typeof key !== 'string') {
251
+ return '****-****-****-****';
252
+ }
253
+
254
+ // Handle PRO-XXXX-XXXX-XXXX-XXXX format
255
+ const parts = key.split('-');
256
+ if (parts.length !== 5 || parts[0] !== 'PRO') {
257
+ // Non-standard format, mask all but first/last 4
258
+ if (key.length <= 8) {
259
+ return '****';
260
+ }
261
+ return `${key.slice(0, 4)}-****-****-${key.slice(-4)}`;
262
+ }
263
+
264
+ // Standard format: PRO-XXXX-XXXX-XXXX-XXXX
265
+ return `${parts[0]}-${parts[1]}-****-****-${parts[4]}`;
266
+ }
267
+
268
+ /**
269
+ * Validate license key format.
270
+ *
271
+ * Expected format: PRO-XXXX-XXXX-XXXX-XXXX
272
+ * Where X is alphanumeric (A-Z0-9)
273
+ *
274
+ * @param {string} key - License key to validate
275
+ * @returns {boolean} true if format is valid
276
+ */
277
+ function validateKeyFormat(key) {
278
+ if (!key || typeof key !== 'string') {
279
+ return false;
280
+ }
281
+
282
+ // Format: PRO-XXXX-XXXX-XXXX-XXXX (uppercase alphanumeric)
283
+ const pattern = /^PRO-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/;
284
+ return pattern.test(key);
285
+ }
286
+
287
+ module.exports = {
288
+ // Core functions per ADR-PRO-003
289
+ generateMachineId,
290
+ deriveCacheKey,
291
+ encrypt,
292
+ decrypt,
293
+ computeHMAC,
294
+
295
+ // Additional utilities
296
+ generateSalt,
297
+ verifyHMAC,
298
+ maskKey,
299
+ validateKeyFormat,
300
+
301
+ // Exported for testing
302
+ _CONFIG: CONFIG,
303
+ };