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,354 @@
1
+ /**
2
+ * Feature Gate Module
3
+ *
4
+ * Singleton class that validates feature availability based on license cache.
5
+ * Supports exact feature ID matching and wildcard patterns.
6
+ *
7
+ * Usage:
8
+ * const { featureGate } = require('./feature-gate');
9
+ *
10
+ * // Check availability
11
+ * if (featureGate.isAvailable('pro.squads.premium')) {
12
+ * // Feature is licensed
13
+ * }
14
+ *
15
+ * // Require feature (throws if not available)
16
+ * featureGate.require('pro.squads.premium', 'Premium Squads');
17
+ *
18
+ * @module pro/license/feature-gate
19
+ * @see ADR-PRO-003 - Feature Gating & Licensing
20
+ * @see Story PRO-6 - License Key & Feature Gating System
21
+ */
22
+
23
+ 'use strict';
24
+
25
+ const fs = require('fs');
26
+ const path = require('path');
27
+ const yaml = require('yaml');
28
+ const { readLicenseCache, isExpired, isInGracePeriod, getLicenseState } = require('./license-cache');
29
+ const { ProFeatureError } = require('./errors');
30
+
31
+ /**
32
+ * Path to the feature registry YAML file.
33
+ */
34
+ const REGISTRY_PATH = path.join(__dirname, '..', 'feature-registry.yaml');
35
+
36
+ /**
37
+ * FeatureGate class - validates feature availability.
38
+ *
39
+ * Singleton pattern ensures consistent state across the application.
40
+ */
41
+ class FeatureGate {
42
+ constructor() {
43
+ this._cache = null;
44
+ this._licensedFeatures = new Set();
45
+ this._registeredFeatures = new Map();
46
+ this._lastLoadTime = null;
47
+ this._cacheLoaded = false;
48
+ this._registryLoaded = false;
49
+ }
50
+
51
+ /**
52
+ * Load the feature registry from YAML.
53
+ *
54
+ * @private
55
+ */
56
+ _loadRegistry() {
57
+ if (this._registryLoaded) {
58
+ return;
59
+ }
60
+
61
+ try {
62
+ if (fs.existsSync(REGISTRY_PATH)) {
63
+ const content = fs.readFileSync(REGISTRY_PATH, 'utf8');
64
+ const registry = yaml.parse(content);
65
+
66
+ // Extract all features from modules
67
+ const modules = ['squads', 'memory', 'metrics', 'integrations', 'agents', 'cli', 'config'];
68
+
69
+ for (const module of modules) {
70
+ if (registry[module] && Array.isArray(registry[module])) {
71
+ for (const feature of registry[module]) {
72
+ this._registeredFeatures.set(feature.id, {
73
+ id: feature.id,
74
+ name: feature.name,
75
+ description: feature.description,
76
+ module: feature.module,
77
+ });
78
+ }
79
+ }
80
+ }
81
+
82
+ this._registryLoaded = true;
83
+ }
84
+ } catch {
85
+ // Registry load failed, features will still work via license patterns
86
+ this._registryLoaded = true;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Load the license cache and populate licensed features.
92
+ *
93
+ * @private
94
+ * @param {boolean} [force=false] - Force reload even if already loaded
95
+ */
96
+ _loadCache(force = false) {
97
+ if (this._cacheLoaded && !force) {
98
+ return;
99
+ }
100
+
101
+ // Load registry if not loaded
102
+ this._loadRegistry();
103
+
104
+ // Read license cache
105
+ this._cache = readLicenseCache();
106
+ this._licensedFeatures.clear();
107
+ this._lastLoadTime = Date.now();
108
+
109
+ if (!this._cache) {
110
+ this._cacheLoaded = true;
111
+ return;
112
+ }
113
+
114
+ // Check if cache is valid (not expired, or in grace period)
115
+ const state = getLicenseState(this._cache);
116
+
117
+ if (state === 'Expired') {
118
+ // Expired and past grace period - no features available
119
+ // Keep cache reference so getLicenseState can report 'Expired'
120
+ this._cacheLoaded = true;
121
+ return;
122
+ }
123
+
124
+ // Populate licensed features from cache
125
+ if (this._cache.features && Array.isArray(this._cache.features)) {
126
+ for (const featurePattern of this._cache.features) {
127
+ this._licensedFeatures.add(featurePattern);
128
+ }
129
+ }
130
+
131
+ this._cacheLoaded = true;
132
+ }
133
+
134
+ /**
135
+ * Check if a feature pattern matches a feature ID using wildcard matching.
136
+ *
137
+ * Supports:
138
+ * - Exact match: "pro.squads.premium" matches "pro.squads.premium"
139
+ * - Wildcard: "pro.squads.*" matches "pro.squads.premium", "pro.squads.custom"
140
+ * - Module wildcard: "pro.*" matches any pro feature
141
+ *
142
+ * @private
143
+ * @param {string} featureId - Feature ID to check
144
+ * @param {string} pattern - Pattern from license
145
+ * @returns {boolean} true if pattern matches feature ID
146
+ */
147
+ _matchWildcard(featureId, pattern) {
148
+ // Exact match
149
+ if (pattern === featureId) {
150
+ return true;
151
+ }
152
+
153
+ // Wildcard match: "pro.*" matches "pro.squads.premium"
154
+ if (pattern.endsWith('.*')) {
155
+ const prefix = pattern.slice(0, -1); // Remove trailing * → "pro."
156
+ return featureId.startsWith(prefix);
157
+ }
158
+
159
+ // BUG-7 fix (INS-1): Bare module pattern without dots (e.g., "pro")
160
+ // should match all features under that module (equivalent to "pro.*")
161
+ if (!pattern.includes('.') && featureId.startsWith(pattern + '.')) {
162
+ return true;
163
+ }
164
+
165
+ return false;
166
+ }
167
+
168
+ /**
169
+ * Check if a feature is available (licensed).
170
+ *
171
+ * Performance: < 5ms (cache read only, per AC-13)
172
+ *
173
+ * @param {string} featureId - Feature ID to check (e.g., "pro.squads.premium")
174
+ * @returns {boolean} true if feature is licensed and available
175
+ */
176
+ isAvailable(featureId) {
177
+ this._loadCache();
178
+
179
+ if (this._licensedFeatures.size === 0) {
180
+ return false;
181
+ }
182
+
183
+ // Check direct match first (O(1))
184
+ if (this._licensedFeatures.has(featureId)) {
185
+ return true;
186
+ }
187
+
188
+ // Check wildcard patterns
189
+ for (const pattern of this._licensedFeatures) {
190
+ if (this._matchWildcard(featureId, pattern)) {
191
+ return true;
192
+ }
193
+ }
194
+
195
+ return false;
196
+ }
197
+
198
+ /**
199
+ * Require a feature to be available, throw if not.
200
+ *
201
+ * Use this to gate premium functionality:
202
+ *
203
+ * featureGate.require('pro.squads.premium', 'Premium Squads');
204
+ *
205
+ * @param {string} featureId - Feature ID to require
206
+ * @param {string} [friendlyName] - Human-friendly feature name for error message
207
+ * @throws {ProFeatureError} If feature is not licensed
208
+ */
209
+ require(featureId, friendlyName) {
210
+ if (!this.isAvailable(featureId)) {
211
+ const name = friendlyName || this._getFeatureName(featureId) || featureId;
212
+ throw new ProFeatureError(featureId, name);
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Get the friendly name of a feature from registry.
218
+ *
219
+ * @private
220
+ * @param {string} featureId - Feature ID
221
+ * @returns {string|null} Feature name or null
222
+ */
223
+ _getFeatureName(featureId) {
224
+ this._loadRegistry();
225
+ const feature = this._registeredFeatures.get(featureId);
226
+ return feature ? feature.name : null;
227
+ }
228
+
229
+ /**
230
+ * List all available (licensed) feature IDs.
231
+ *
232
+ * Returns the resolved list of feature IDs, expanding wildcards
233
+ * against the registry.
234
+ *
235
+ * @returns {string[]} Array of available feature IDs
236
+ */
237
+ listAvailable() {
238
+ this._loadCache();
239
+ this._loadRegistry();
240
+
241
+ const available = new Set();
242
+
243
+ // Check each registered feature against licensed patterns
244
+ for (const [featureId] of this._registeredFeatures) {
245
+ if (this.isAvailable(featureId)) {
246
+ available.add(featureId);
247
+ }
248
+ }
249
+
250
+ return Array.from(available).sort();
251
+ }
252
+
253
+ /**
254
+ * List all registered features with their availability status.
255
+ *
256
+ * @returns {Array<{ id: string, name: string, description: string, module: string, available: boolean }>}
257
+ */
258
+ listAll() {
259
+ this._loadCache();
260
+ this._loadRegistry();
261
+
262
+ const features = [];
263
+
264
+ for (const [featureId, feature] of this._registeredFeatures) {
265
+ features.push({
266
+ ...feature,
267
+ available: this.isAvailable(featureId),
268
+ });
269
+ }
270
+
271
+ return features.sort((a, b) => a.id.localeCompare(b.id));
272
+ }
273
+
274
+ /**
275
+ * List features grouped by module.
276
+ *
277
+ * @returns {Object<string, Array<{ id: string, name: string, available: boolean }>>}
278
+ */
279
+ listByModule() {
280
+ const all = this.listAll();
281
+ const grouped = {};
282
+
283
+ for (const feature of all) {
284
+ if (!grouped[feature.module]) {
285
+ grouped[feature.module] = [];
286
+ }
287
+ grouped[feature.module].push(feature);
288
+ }
289
+
290
+ return grouped;
291
+ }
292
+
293
+ /**
294
+ * Force reload of the license cache.
295
+ *
296
+ * Call this after activation to pick up new features.
297
+ */
298
+ reload() {
299
+ this._cacheLoaded = false;
300
+ this._loadCache(true);
301
+ }
302
+
303
+ /**
304
+ * Get the current license state.
305
+ *
306
+ * @returns {'Active'|'Expired'|'Grace'|'Not Activated'} License state
307
+ */
308
+ getLicenseState() {
309
+ this._loadCache();
310
+ return getLicenseState(this._cache);
311
+ }
312
+
313
+ /**
314
+ * Get license information for display.
315
+ *
316
+ * @returns {{ state: string, features: string[], inGrace: boolean } | null}
317
+ */
318
+ getLicenseInfo() {
319
+ this._loadCache();
320
+
321
+ if (!this._cache) {
322
+ return null;
323
+ }
324
+
325
+ return {
326
+ state: getLicenseState(this._cache),
327
+ features: Array.from(this._licensedFeatures),
328
+ inGrace: isInGracePeriod(this._cache),
329
+ isExpired: isExpired(this._cache),
330
+ };
331
+ }
332
+
333
+ /**
334
+ * Clear internal state (for testing).
335
+ *
336
+ * @private
337
+ */
338
+ _reset() {
339
+ this._cache = null;
340
+ this._licensedFeatures.clear();
341
+ this._registeredFeatures.clear();
342
+ this._lastLoadTime = null;
343
+ this._cacheLoaded = false;
344
+ this._registryLoaded = false;
345
+ }
346
+ }
347
+
348
+ // Singleton instance
349
+ const featureGate = new FeatureGate();
350
+
351
+ module.exports = {
352
+ FeatureGate,
353
+ featureGate,
354
+ };
@@ -0,0 +1,181 @@
1
+ /**
2
+ * License Module - Public API
3
+ *
4
+ * This module provides the public interface for license management
5
+ * and feature gating in AIOS Pro.
6
+ *
7
+ * Usage:
8
+ * const { featureGate, licenseApi } = require('@aios-fullstack/pro/license');
9
+ *
10
+ * // Check feature availability
11
+ * if (featureGate.isAvailable('pro.squads.premium')) {
12
+ * // Feature is licensed
13
+ * }
14
+ *
15
+ * // Require feature (throws if not available)
16
+ * featureGate.require('pro.squads.premium', 'Premium Squads');
17
+ *
18
+ * // Activate license
19
+ * await licenseApi.activate(key, machineId, version);
20
+ *
21
+ * @module pro/license
22
+ * @see ADR-PRO-003 - Feature Gating & Licensing
23
+ * @see Story PRO-6 - License Key & Feature Gating System
24
+ */
25
+
26
+ 'use strict';
27
+
28
+ // Feature gating
29
+ const { FeatureGate, featureGate } = require('./feature-gate');
30
+
31
+ // License cache operations
32
+ const {
33
+ writeLicenseCache,
34
+ readLicenseCache,
35
+ deleteLicenseCache,
36
+ isExpired,
37
+ isInGracePeriod,
38
+ getDaysRemaining,
39
+ getExpiryDate,
40
+ getLicenseState,
41
+ setPendingDeactivation,
42
+ hasPendingDeactivation,
43
+ markPendingDeactivationSynced,
44
+ clearPendingDeactivation,
45
+ } = require('./license-cache');
46
+
47
+ // License API client
48
+ const { LicenseApiClient, licenseApi } = require('./license-api');
49
+
50
+ // Crypto utilities
51
+ const {
52
+ generateMachineId,
53
+ maskKey,
54
+ validateKeyFormat,
55
+ } = require('./license-crypto');
56
+
57
+ // Error classes
58
+ const {
59
+ ProFeatureError,
60
+ LicenseActivationError,
61
+ LicenseValidationError,
62
+ } = require('./errors');
63
+
64
+ // Graceful degradation utilities
65
+ const {
66
+ withGracefulDegradation,
67
+ ifProAvailable,
68
+ getFeatureFriendlyName,
69
+ logDegradationMessage,
70
+ createDegradationWrapper,
71
+ isInDegradedMode,
72
+ getDegradationStatus,
73
+ } = require('./degradation');
74
+
75
+ /**
76
+ * Convenience function to check if a feature is available.
77
+ *
78
+ * @param {string} featureId - Feature ID to check
79
+ * @returns {boolean} true if feature is licensed
80
+ */
81
+ function isFeatureAvailable(featureId) {
82
+ return featureGate.isAvailable(featureId);
83
+ }
84
+
85
+ /**
86
+ * Convenience function to require a feature.
87
+ *
88
+ * @param {string} featureId - Feature ID to require
89
+ * @param {string} [friendlyName] - Human-friendly name for error message
90
+ * @throws {ProFeatureError} If feature is not licensed
91
+ */
92
+ function requireFeature(featureId, friendlyName) {
93
+ featureGate.require(featureId, friendlyName);
94
+ }
95
+
96
+ /**
97
+ * Convenience function to get the current license state.
98
+ *
99
+ * @returns {'Active'|'Expired'|'Grace'|'Not Activated'} License state
100
+ */
101
+ function getCurrentLicenseState() {
102
+ return featureGate.getLicenseState();
103
+ }
104
+
105
+ /**
106
+ * Convenience function to get license info.
107
+ *
108
+ * @returns {{ state: string, features: string[], inGrace: boolean } | null}
109
+ */
110
+ function getLicenseInfo() {
111
+ return featureGate.getLicenseInfo();
112
+ }
113
+
114
+ /**
115
+ * Convenience function to list available features.
116
+ *
117
+ * @returns {string[]} Array of available feature IDs
118
+ */
119
+ function listAvailableFeatures() {
120
+ return featureGate.listAvailable();
121
+ }
122
+
123
+ /**
124
+ * Reload license cache (after activation/deactivation).
125
+ */
126
+ function reloadLicense() {
127
+ featureGate.reload();
128
+ }
129
+
130
+ module.exports = {
131
+ // Primary exports - Feature Gate
132
+ FeatureGate,
133
+ featureGate,
134
+
135
+ // Primary exports - API Client
136
+ LicenseApiClient,
137
+ licenseApi,
138
+
139
+ // Error classes
140
+ ProFeatureError,
141
+ LicenseActivationError,
142
+ LicenseValidationError,
143
+
144
+ // Cache operations
145
+ writeLicenseCache,
146
+ readLicenseCache,
147
+ deleteLicenseCache,
148
+ isExpired,
149
+ isInGracePeriod,
150
+ getDaysRemaining,
151
+ getExpiryDate,
152
+ getLicenseState,
153
+
154
+ // Pending deactivation
155
+ setPendingDeactivation,
156
+ hasPendingDeactivation,
157
+ markPendingDeactivationSynced,
158
+ clearPendingDeactivation,
159
+
160
+ // Crypto utilities
161
+ generateMachineId,
162
+ maskKey,
163
+ validateKeyFormat,
164
+
165
+ // Convenience functions
166
+ isFeatureAvailable,
167
+ requireFeature,
168
+ getCurrentLicenseState,
169
+ getLicenseInfo,
170
+ listAvailableFeatures,
171
+ reloadLicense,
172
+
173
+ // Graceful degradation (AC-8)
174
+ withGracefulDegradation,
175
+ ifProAvailable,
176
+ getFeatureFriendlyName,
177
+ logDegradationMessage,
178
+ createDegradationWrapper,
179
+ isInDegradedMode,
180
+ getDegradationStatus,
181
+ };