Skip to content

Commit 93b0b9f

Browse files
authored
feat(license): sync stable machine id to core [Story PRO-13.2]
Admin merge authorized by Rafael via /devops -admin. Checks were green; repository ruleset and review gate were temporarily relaxed and restored immediately after merge.
1 parent 571ea2a commit 93b0b9f

12 files changed

Lines changed: 285 additions & 134 deletions

File tree

.aiox-core/development/scripts/unified-activation-pipeline.js

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ class UnifiedActivationPipeline {
209209
const metrics = { loaders: {} };
210210

211211
// --- Tier 1: Critical (AgentConfig) ---
212-
const tier1Budget = LOADER_TIERS.critical.timeout;
212+
const tier1Budget = this._resolveLoaderTimeout('critical', LOADER_TIERS.critical.timeout);
213213
const agentComplete = await this._profileLoader('agentConfig', metrics, tier1Budget, () => {
214214
const loader = new AgentConfigLoader(agentId);
215215
return loader.loadComplete(coreConfig);
@@ -231,7 +231,7 @@ class UnifiedActivationPipeline {
231231
}
232232

233233
// --- Tier 2: High (PermissionMode + GitConfig) — parallel ---
234-
const tier2Budget = LOADER_TIERS.high.timeout;
234+
const tier2Budget = this._resolveLoaderTimeout('high', LOADER_TIERS.high.timeout);
235235
const elapsedAfterT1 = Date.now() - pipelineStart;
236236
const tier2Remaining = Math.max(tier2Budget - elapsedAfterT1, 20);
237237

@@ -277,7 +277,7 @@ class UnifiedActivationPipeline {
277277
}
278278

279279
// --- Tier 3: Best-effort (SessionContext + ProjectStatus) — parallel ---
280-
const tier3Budget = LOADER_TIERS.bestEffort.timeout;
280+
const tier3Budget = this._resolveLoaderTimeout('bestEffort', LOADER_TIERS.bestEffort.timeout);
281281
const elapsedAfterT2 = Date.now() - pipelineStart;
282282
const tier3Remaining = Math.max(tier3Budget - elapsedAfterT2, 20);
283283

@@ -467,6 +467,32 @@ class UnifiedActivationPipeline {
467467
return DEFAULT_PIPELINE_TIMEOUT_MS;
468468
}
469469

470+
/**
471+
* Resolve per-tier loader timeout.
472+
*
473+
* Intended mainly for constrained CI/test environments where cold filesystem
474+
* reads can exceed the production performance budget without indicating a
475+
* functional activation failure.
476+
*
477+
* @private
478+
* @param {'critical'|'high'|'bestEffort'} tierName
479+
* @param {number} defaultTimeout
480+
* @returns {number}
481+
*/
482+
_resolveLoaderTimeout(tierName, defaultTimeout) {
483+
const envKey = `AIOX_LOADER_TIMEOUT_${tierName.replace(/([A-Z])/g, '_$1').toUpperCase()}`;
484+
const envTimeout = process.env[envKey];
485+
486+
if (envTimeout) {
487+
const parsed = parseInt(envTimeout, 10);
488+
if (!isNaN(parsed) && parsed > 0) {
489+
return parsed;
490+
}
491+
}
492+
493+
return defaultTimeout;
494+
}
495+
470496
/**
471497
* Build agent definition from loaded config data.
472498
* @private

.aiox-core/install-manifest.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
# - SHA256 hashes for change detection
88
# - File types for categorization
99
#
10-
version: 5.0.3
11-
generated_at: "2026-05-05T23:14:42.150Z"
10+
version: 5.0.8
11+
generated_at: "2026-05-06T19:40:38.959Z"
1212
generator: scripts/generate-install-manifest.js
1313
file_count: 1103
1414
files:
@@ -1689,9 +1689,9 @@ files:
16891689
type: script
16901690
size: 17607
16911691
- path: development/scripts/unified-activation-pipeline.js
1692-
hash: sha256:de2d4a10b01da32d31c1f810feed429804da6869bb958d5a5ebe626589d0a2f6
1692+
hash: sha256:6910a7f6b0cef65a0886e0b29bbcb0ee401ca4fb444eb255a7a368cb67327aa7
16931693
type: script
1694-
size: 30125
1694+
size: 30996
16951695
- path: development/scripts/usage-tracker.js
16961696
hash: sha256:6057623755bf0ee1d9e0fb36740fc41914a5f8ca8ad994d40edec260e273744b
16971697
type: script

.github/workflows/ci.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,54 @@ jobs:
188188
fail_ci_if_error: false
189189
continue-on-error: true
190190

191+
pro-machine-id-stability:
192+
name: Pro Machine ID Stability (${{ matrix.os }})
193+
needs: changes
194+
if: ${{ needs.changes.outputs.tests == 'true' || needs.changes.outputs.config == 'true' }}
195+
runs-on: ${{ matrix.os }}
196+
timeout-minutes: 10
197+
strategy:
198+
fail-fast: false
199+
matrix:
200+
os: [ubuntu-latest, macos-latest, windows-latest]
201+
202+
steps:
203+
- name: Checkout code
204+
uses: actions/checkout@v4
205+
206+
- name: Setup Node.js
207+
uses: actions/setup-node@v4
208+
with:
209+
node-version: '20'
210+
cache: 'npm'
211+
cache-dependency-path: package-lock.json
212+
213+
- name: Install dependencies
214+
run: npm ci
215+
216+
- name: Detect Pro submodule availability
217+
id: pro
218+
shell: pwsh
219+
run: |
220+
if (Test-Path "pro/license/license-crypto.js") {
221+
"available=true" >> $env:GITHUB_OUTPUT
222+
} else {
223+
"available=false" >> $env:GITHUB_OUTPUT
224+
Write-Host "pro/ submodule is not available with the default CI token."
225+
Write-Host "Cross-platform Pro runtime validation runs in the aiox-pro CI matrix."
226+
}
227+
228+
- name: Run machine ID stability tests
229+
if: steps.pro.outputs.available == 'true'
230+
run: npx jest --runTestsByPath tests/license/machine-id-stability.test.js --runInBand --testPathIgnorePatterns=/node_modules/
231+
232+
- name: Record private submodule skip
233+
if: steps.pro.outputs.available != 'true'
234+
shell: pwsh
235+
run: |
236+
Write-Host "Skipping aiox-core Pro machine ID job because pro/ is private in default-token CI."
237+
Write-Host "See https://github.com/SynkraAI/aiox-pro/pull/11 for the cross-platform Pro runtime matrix."
238+
191239
story-validation:
192240
name: Story Checkbox Validation
193241
needs: changes

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,12 @@ O **AIOX Pro** é o módulo premium do AIOX, oferecendo funcionalidades avançad
614614
npx aiox-pro install
615615
```
616616

617+
### Identificação Estável de Máquina (>= 5.0.8)
618+
619+
O AIOX Pro agora usa o UUID nativo do sistema operacional para gerar `machineId`, preservando o hash SHA-256 e evitando consumo extra de assentos quando o macOS, VPNs ou redes Wi-Fi alteram o MAC/interface ativa.
620+
621+
Caches locais de licença criados pelo algoritmo antigo são migrados automaticamente na próxima leitura. A janela de fallback legacy é de 90 dias; depois disso, instalações antigas precisam reativar online.
622+
617623
### Features Premium
618624

619625
- **Squads Avançados** - Squads especializados com capacidades expandidas

bin/utils/validate-publish.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const PROJECT_ROOT = path.join(__dirname, '..', '..');
2323
const PRO_DIR = path.join(PROJECT_ROOT, 'pro');
2424
const CRITICAL_FILE = path.join(PRO_DIR, 'license', 'license-api.js');
2525
const MIN_FILE_COUNT = 50;
26+
const PACK_DRY_RUN_TIMEOUT_MS = 120000;
2627

2728
// CI environments may not have access to the private pro submodule
2829
const IS_CI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
@@ -75,7 +76,7 @@ try {
7576
const packOutput = execSync('npm pack --dry-run 2>&1', {
7677
encoding: 'utf8',
7778
cwd: PROJECT_ROOT,
78-
timeout: 30000,
79+
timeout: PACK_DRY_RUN_TIMEOUT_MS,
7980
});
8081
// npm pack --dry-run outputs lines starting with "npm notice" for each file
8182
const fileLines = packOutput.split('\n').filter(line =>

package-lock.json

Lines changed: 9 additions & 121 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)