@dharma-ai-labs/agent-fabric 0.2.209 → 0.2.211

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 (158) hide show
  1. package/dist/bin.js +2 -2
  2. package/dist/bin.js.map +1 -1
  3. package/dist/bootstrapHostScope.test.js +1 -1
  4. package/dist/bootstrapHostScope.test.js.map +1 -1
  5. package/dist/bootstrapProcessCaller.test.js +1 -0
  6. package/dist/bootstrapProcessCaller.test.js.map +1 -1
  7. package/dist/bootstrapVaultScope.test.js +25 -1
  8. package/dist/bootstrapVaultScope.test.js.map +1 -1
  9. package/dist/codexBoundSession.d.ts +59 -0
  10. package/dist/codexBoundSession.d.ts.map +1 -1
  11. package/dist/codexBoundSession.js +140 -1
  12. package/dist/codexBoundSession.js.map +1 -1
  13. package/dist/codexInboxSession.d.ts +1 -1
  14. package/dist/codexInboxSession.d.ts.map +1 -1
  15. package/dist/codexRecoveryController.test.d.ts +2 -0
  16. package/dist/codexRecoveryController.test.d.ts.map +1 -0
  17. package/dist/codexRecoveryController.test.js +295 -0
  18. package/dist/codexRecoveryController.test.js.map +1 -0
  19. package/dist/codexScopedDispatch.test.js +2 -1
  20. package/dist/codexScopedDispatch.test.js.map +1 -1
  21. package/dist/codexSetupChildProvider.test.js +20 -0
  22. package/dist/codexSetupChildProvider.test.js.map +1 -1
  23. package/dist/codexSetupNativeHost.test.js +2 -1
  24. package/dist/codexSetupNativeHost.test.js.map +1 -1
  25. package/dist/codexSetupSessionCaller.test.js +1 -0
  26. package/dist/codexSetupSessionCaller.test.js.map +1 -1
  27. package/dist/codexSigningRecoveryNativeHost.d.ts +50 -0
  28. package/dist/codexSigningRecoveryNativeHost.d.ts.map +1 -0
  29. package/dist/codexSigningRecoveryNativeHost.js +186 -0
  30. package/dist/codexSigningRecoveryNativeHost.js.map +1 -0
  31. package/dist/codexSigningRecoveryNativeHost.test.d.ts +2 -0
  32. package/dist/codexSigningRecoveryNativeHost.test.d.ts.map +1 -0
  33. package/dist/codexSigningRecoveryNativeHost.test.js +475 -0
  34. package/dist/codexSigningRecoveryNativeHost.test.js.map +1 -0
  35. package/dist/codexSigningRecoveryTool.d.ts +25 -0
  36. package/dist/codexSigningRecoveryTool.d.ts.map +1 -0
  37. package/dist/codexSigningRecoveryTool.js +24 -0
  38. package/dist/codexSigningRecoveryTool.js.map +1 -0
  39. package/dist/containerRelayLifecycle.d.ts +2 -1
  40. package/dist/containerRelayLifecycle.d.ts.map +1 -1
  41. package/dist/containerRelayLifecycle.js +12 -0
  42. package/dist/containerRelayLifecycle.js.map +1 -1
  43. package/dist/containerRelayLifecycle.test.js +38 -6
  44. package/dist/containerRelayLifecycle.test.js.map +1 -1
  45. package/dist/containerRelayRuntimeTrust.test.js +10 -0
  46. package/dist/containerRelayRuntimeTrust.test.js.map +1 -1
  47. package/dist/cooperativeInboxSession.d.ts +1 -1
  48. package/dist/demoPackage.d.ts +1 -1
  49. package/dist/demoWatchControl.d.ts +6 -6
  50. package/dist/deviceSigningMaintenanceController.d.ts +35 -0
  51. package/dist/deviceSigningMaintenanceController.d.ts.map +1 -0
  52. package/dist/deviceSigningMaintenanceController.js +197 -0
  53. package/dist/deviceSigningMaintenanceController.js.map +1 -0
  54. package/dist/deviceSigningMaintenanceController.test.d.ts +2 -0
  55. package/dist/deviceSigningMaintenanceController.test.d.ts.map +1 -0
  56. package/dist/deviceSigningMaintenanceController.test.js +67 -0
  57. package/dist/deviceSigningMaintenanceController.test.js.map +1 -0
  58. package/dist/deviceSigningMaintenanceFlow.test.d.ts +2 -0
  59. package/dist/deviceSigningMaintenanceFlow.test.d.ts.map +1 -0
  60. package/dist/deviceSigningMaintenanceFlow.test.js +196 -0
  61. package/dist/deviceSigningMaintenanceFlow.test.js.map +1 -0
  62. package/dist/index.d.ts +9 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +723 -470
  65. package/dist/index.js.map +1 -1
  66. package/dist/legacySigningMaintenanceBoundary.d.ts +14 -0
  67. package/dist/legacySigningMaintenanceBoundary.d.ts.map +1 -0
  68. package/dist/legacySigningMaintenanceBoundary.js +128 -0
  69. package/dist/legacySigningMaintenanceBoundary.js.map +1 -0
  70. package/dist/legacySigningMaintenanceBoundary.test.d.ts +2 -0
  71. package/dist/legacySigningMaintenanceBoundary.test.d.ts.map +1 -0
  72. package/dist/legacySigningMaintenanceBoundary.test.js +109 -0
  73. package/dist/legacySigningMaintenanceBoundary.test.js.map +1 -0
  74. package/dist/maintenanceControlCaller.test.d.ts +2 -0
  75. package/dist/maintenanceControlCaller.test.d.ts.map +1 -0
  76. package/dist/maintenanceControlCaller.test.js +119 -0
  77. package/dist/maintenanceControlCaller.test.js.map +1 -0
  78. package/dist/namedCodexThread.d.ts.map +1 -1
  79. package/dist/namedCodexThread.js +3 -1
  80. package/dist/namedCodexThread.js.map +1 -1
  81. package/dist/namedCodexThread.test.js +17 -1
  82. package/dist/namedCodexThread.test.js.map +1 -1
  83. package/dist/namedSessionMaintenance.d.ts +1 -1
  84. package/dist/namedSessionStartupFence.test.d.ts +2 -0
  85. package/dist/namedSessionStartupFence.test.d.ts.map +1 -0
  86. package/dist/namedSessionStartupFence.test.js +81 -0
  87. package/dist/namedSessionStartupFence.test.js.map +1 -0
  88. package/dist/namedSessionStoppedLock.d.ts +34 -0
  89. package/dist/namedSessionStoppedLock.d.ts.map +1 -0
  90. package/dist/namedSessionStoppedLock.js +108 -0
  91. package/dist/namedSessionStoppedLock.js.map +1 -0
  92. package/dist/namedSessionStoppedLock.test.d.ts +2 -0
  93. package/dist/namedSessionStoppedLock.test.d.ts.map +1 -0
  94. package/dist/namedSessionStoppedLock.test.js +104 -0
  95. package/dist/namedSessionStoppedLock.test.js.map +1 -0
  96. package/dist/providerSessionReplyRecovery.d.ts +1 -1
  97. package/dist/relayAutostart.d.ts +3 -0
  98. package/dist/relayAutostart.d.ts.map +1 -1
  99. package/dist/relayAutostart.js +45 -6
  100. package/dist/relayAutostart.js.map +1 -1
  101. package/dist/relayAutostart.test.js +49 -1
  102. package/dist/relayAutostart.test.js.map +1 -1
  103. package/dist/relayRuntimeUpgrade.d.ts +2 -1
  104. package/dist/relayRuntimeUpgrade.d.ts.map +1 -1
  105. package/dist/relayRuntimeUpgrade.js +3 -3
  106. package/dist/relayRuntimeUpgrade.js.map +1 -1
  107. package/dist/relayRuntimeUpgradeCaller.test.js +76 -0
  108. package/dist/relayRuntimeUpgradeCaller.test.js.map +1 -1
  109. package/dist/relaySigningMaintenanceUpgrade.d.ts +44 -0
  110. package/dist/relaySigningMaintenanceUpgrade.d.ts.map +1 -0
  111. package/dist/relaySigningMaintenanceUpgrade.js +249 -0
  112. package/dist/relaySigningMaintenanceUpgrade.js.map +1 -0
  113. package/dist/relaySigningMaintenanceUpgrade.test.d.ts +2 -0
  114. package/dist/relaySigningMaintenanceUpgrade.test.d.ts.map +1 -0
  115. package/dist/relaySigningMaintenanceUpgrade.test.js +230 -0
  116. package/dist/relaySigningMaintenanceUpgrade.test.js.map +1 -0
  117. package/dist/schemas/codex-signing-recovery-native-progress.schema.json +16 -0
  118. package/dist/schemas/device-enrollment-recovery-journal.schema.json +20 -0
  119. package/dist/schemas/device-signing-maintenance-challenge.schema.json +185 -0
  120. package/dist/schemas/device-signing-maintenance-completion.schema.json +98 -0
  121. package/dist/schemas/device-signing-maintenance-context-request.schema.json +68 -0
  122. package/dist/schemas/device-signing-maintenance-context.schema.json +137 -0
  123. package/dist/schemas/device-signing-maintenance-control.schema.json +12 -0
  124. package/dist/schemas/device-signing-maintenance-controller-progress.schema.json +26 -0
  125. package/dist/schemas/device-signing-maintenance-delivery-request.schema.json +45 -0
  126. package/dist/schemas/device-signing-maintenance-host-progress.schema.json +121 -0
  127. package/dist/schemas/device-signing-maintenance-plan.schema.json +136 -0
  128. package/dist/schemas/device-signing-maintenance-preparation.schema.json +56 -0
  129. package/dist/schemas/device-signing-recovery-candidate.schema.json +28 -0
  130. package/dist/schemas/device-signing-recovery-challenge.schema.json +52 -0
  131. package/dist/schemas/device-signing-recovery-completion.schema.json +23 -0
  132. package/dist/schemas/device-signing-recovery-delivery-request.schema.json +16 -0
  133. package/dist/schemas/device-signing-recovery-delivery.schema.json +22 -0
  134. package/dist/schemas/device-signing-recovery-host-progress.schema.json +28 -0
  135. package/dist/schemas/device-signing-recovery-offer-progress.schema.json +32 -0
  136. package/dist/schemas/device-signing-recovery-offer-read-request.schema.json +16 -0
  137. package/dist/schemas/device-signing-recovery-offer-registration-receipt.schema.json +16 -0
  138. package/dist/schemas/device-signing-recovery-offer-registration-request.schema.json +18 -0
  139. package/dist/schemas/device-signing-recovery-offer-response.schema.json +43 -0
  140. package/dist/schemas/device-signing-recovery-plan.schema.json +40 -0
  141. package/dist/schemas/device-signing-recovery-preparation.schema.json +23 -0
  142. package/dist/schemas/local-signing-maintenance-upgrade-journal.schema.json +34 -0
  143. package/dist/schemas/local-signing-maintenance-upgrade.schema.json +33 -0
  144. package/dist/schemas/provider-session-recovery-declaration.schema.json +21 -0
  145. package/dist/signingMaintenanceCohort.test.d.ts +2 -0
  146. package/dist/signingMaintenanceCohort.test.d.ts.map +1 -0
  147. package/dist/signingMaintenanceCohort.test.js +55 -0
  148. package/dist/signingMaintenanceCohort.test.js.map +1 -0
  149. package/dist/usage.d.ts.map +1 -1
  150. package/dist/usage.js +4 -2
  151. package/dist/usage.js.map +1 -1
  152. package/dist/wslRelayHost.d.ts +2 -0
  153. package/dist/wslRelayHost.d.ts.map +1 -1
  154. package/dist/wslRelayHost.js +35 -0
  155. package/dist/wslRelayHost.js.map +1 -1
  156. package/dist/wslRelayHost.test.js +81 -4
  157. package/dist/wslRelayHost.test.js.map +1 -1
  158. package/package.json +4 -4
@@ -0,0 +1,81 @@
1
+ import assert from 'node:assert/strict';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { resolve } from 'node:path';
4
+ import { compileFunction } from 'node:vm';
5
+ import test from 'node:test';
6
+ import ts from 'typescript';
7
+ async function caller(overrides = {}) {
8
+ const source = await readFile(new URL('../src/index.ts', import.meta.url), 'utf8');
9
+ const ast = ts.createSourceFile('index.ts', source, ts.ScriptTarget.Latest, true);
10
+ const node = ast.statements.find(value => ts.isFunctionDeclaration(value) && value.name?.text === 'namedSessionCommand');
11
+ const compiled = ts.transpileModule(node.getText(ast), { compilerOptions: { target: ts.ScriptTarget.ES2023, module: ts.ModuleKind.CommonJS } });
12
+ const calls = [], identity = { organizationId: 'org_fixture', deviceId: 'device', workspaceId: 'workspace', repositoryBindingId: 'binding', endpointId: 'endpoint' };
13
+ let held = false, enabled = false;
14
+ const deps = { process: { platform: 'linux', execPath: '/fixture/node', env: {}, once: () => { }, removeListener: () => { } },
15
+ namedSessionReadinessDiagnosticRequested: () => false, currentBootstrapHostScope: () => undefined,
16
+ currentAcceptedSetupSessionScope: () => undefined, currentNamedSessionChildOwner: () => undefined,
17
+ dharmaHome: () => '/fixture/home', required: (flags, name) => flags.get(name), resolve,
18
+ configPath: () => '/fixture/home/device.json',
19
+ namedSessionPaths: () => ({ root: '/fixture/home/sessions/new-name' }),
20
+ acquireNamedSessionStartupAdmission: async () => { held = true; calls.push('acquire'); return async () => { assert.equal(held, true); held = false; calls.push('release'); }; },
21
+ registry: async () => [{ path: '/fixture/repo', ...identity }], readDeviceConfig: async () => identity,
22
+ assertBootstrapHostSource: async () => { }, repositoryRoleScope: () => identity,
23
+ readNamedSession: async () => ({ identity, enabled: false }), verifyNamedSessionVisibleSkill: () => { },
24
+ verifyAgentFabricSkillInstallation: async () => ({}), repositorySharedReady: async () => ({}),
25
+ namedSessionRequest: async () => { throw Error('stopped'); },
26
+ saveNamedSession: async () => { assert.equal(held, true); enabled = true; calls.push('enable'); },
27
+ fileURLToPath: () => '/fixture/index.js',
28
+ spawn: () => { assert.equal(held, false, 'parent must release before child can acquire'); calls.push('spawn'); return { on: () => { }, unref: () => { } }; },
29
+ observeNamedSessionStartupChild: () => ({ readFailure: () => null, dispose: () => calls.push('dispose') }),
30
+ waitForNamedSessionStartup: async () => { assert.equal(held, false); calls.push('wait'); return { ok: true }; },
31
+ mkdir: async () => { assert.equal(held, true); calls.push('mkdir'); },
32
+ openBootstrapVault: async () => { assert.equal(held, true); calls.push('vault'); throw Error('FIXTURE_VAULT_STOP'); },
33
+ namedSessionStartupPhaseError: (_phase, error) => error, ...overrides };
34
+ const run = compileFunction(compiled.outputText.replaceAll('import.meta.url', '"file:///fixture/index.js"') + '\nreturn namedSessionCommand;', ['exports', ...Object.keys(deps)])({}, ...Object.values(deps));
35
+ return { calls, run, enabled: () => enabled, held: () => held, flags: new Map([['name', 'new-name'], ['workspace-id', 'workspace'], ['apply', true]]) };
36
+ }
37
+ test('actual start and direct serve refuse maintenance contention before registration, spawn or vault', async () => {
38
+ for (const action of ['start', 'serve']) {
39
+ const f = await caller({ acquireNamedSessionStartupAdmission: async () => { throw Error('STARTUP_FENCED'); },
40
+ registry: async () => { throw Error('REGISTRY_REACHED_BEFORE_FENCE'); } });
41
+ await assert.rejects(f.run(action, f.flags), /STARTUP_FENCED/);
42
+ assert.deepEqual(f.calls, []);
43
+ }
44
+ });
45
+ test('actual start serializes disabled enablement and releases admission before child fork and wait', async () => {
46
+ const f = await caller();
47
+ assert.deepEqual(await f.run('start', f.flags), { ok: true });
48
+ assert.equal(f.enabled(), true);
49
+ assert.equal(f.held(), false);
50
+ assert.deepEqual(f.calls, ['acquire', 'enable', 'release', 'spawn', 'wait', 'dispose']);
51
+ });
52
+ test('direct serve holds startup admission before private vault access and releases on failure', async () => {
53
+ const f = await caller();
54
+ await assert.rejects(f.run('serve', f.flags), /FIXTURE_VAULT_STOP/);
55
+ assert.deepEqual(f.calls, ['acquire', 'mkdir', 'vault', 'release']);
56
+ assert.equal(f.held(), false);
57
+ });
58
+ test('early scope failure releases startup admission without starting or touching the vault', async () => {
59
+ const f = await caller({ registry: async () => [] });
60
+ await assert.rejects(f.run('start', f.flags), /named_session_scope_mismatch/);
61
+ assert.deepEqual(f.calls, ['acquire', 'release']);
62
+ assert.equal(f.held(), false);
63
+ });
64
+ test('actual direct serve hands home-wide admission to its service lock before provider startup', async () => {
65
+ const effects = [];
66
+ const f = await caller({ openBootstrapVault: async () => ({ close: async () => { effects.push('vault-close'); } }),
67
+ acquirePidLock: async () => { effects.push('service-lock'); return async () => { effects.push('service-release'); }; },
68
+ assertNamedSessionStartupRegistration: () => { effects.push('registration-recheck'); },
69
+ AgentFabricClient: { open: async () => { assert.equal(f.held(), false); effects.push('provider-boundary'); throw Error('FIXTURE_PROVIDER_STOP'); } },
70
+ namedSessionStartupPhaseError: (_phase, error) => error });
71
+ await assert.rejects(f.run('serve', f.flags), /FIXTURE_PROVIDER_STOP/);
72
+ assert.deepEqual(f.calls, ['acquire', 'mkdir', 'release']);
73
+ assert.deepEqual(effects, ['service-lock', 'registration-recheck', 'provider-boundary', 'vault-close', 'service-release']);
74
+ });
75
+ test('a new-name start releases admission before spawn and direct child admission owns the next phase', async () => {
76
+ const f = await caller({ readNamedSession: async () => null });
77
+ assert.deepEqual(await f.run('start', f.flags), { ok: true });
78
+ assert.equal(f.enabled(), false);
79
+ assert.deepEqual(f.calls, ['acquire', 'release', 'spawn', 'wait', 'dispose']);
80
+ });
81
+ //# sourceMappingURL=namedSessionStartupFence.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namedSessionStartupFence.test.js","sourceRoot":"","sources":["../src/namedSessionStartupFence.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { NamedSessionRegistration } from './namedSessionService.js';
2
+ interface Input {
3
+ home: string;
4
+ name: string;
5
+ registration: NamedSessionRegistration;
6
+ registrationSha256: string;
7
+ lockSha256: string;
8
+ apply: boolean;
9
+ }
10
+ interface Dependencies {
11
+ assertTopology(): Promise<void>;
12
+ processState(pid: number): Promise<'stopped' | 'running' | 'unknown'>;
13
+ }
14
+ /** Called only under the owning CLI's home-wide startup mutation admission. */
15
+ export declare function reconcileStoppedNamedSessionLock(input: Input, deps: Dependencies): Promise<{
16
+ state: string;
17
+ ok: boolean;
18
+ planned: boolean;
19
+ name: string;
20
+ workspaceId: string;
21
+ bindingId: string;
22
+ registrationSha256: string;
23
+ lockSha256: string;
24
+ archive: string;
25
+ previousPid: number;
26
+ registrationChanged: boolean;
27
+ budgetChanged: boolean;
28
+ providerStarted: boolean;
29
+ protectedStoreRead: boolean;
30
+ ready: boolean;
31
+ nativeContinuationAuthorized: boolean;
32
+ }>;
33
+ export {};
34
+ //# sourceMappingURL=namedSessionStoppedLock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namedSessionStoppedLock.d.ts","sourceRoot":"","sources":["../src/namedSessionStoppedLock.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,0BAA0B,CAAC;AAIvE,UAAU,KAAK;IACb,IAAI,EAAC,MAAM,CAAC;IAAC,IAAI,EAAC,MAAM,CAAC;IAAC,YAAY,EAAC,wBAAwB,CAAC;IAChE,kBAAkB,EAAC,MAAM,CAAC;IAAC,UAAU,EAAC,MAAM,CAAC;IAAC,KAAK,EAAC,OAAO,CAAC;CAC7D;AACD,UAAU,YAAY;IACpB,cAAc,IAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,YAAY,CAAC,GAAG,EAAC,MAAM,GAAE,OAAO,CAAC,SAAS,GAAC,SAAS,GAAC,SAAS,CAAC,CAAC;CACjE;AAYD,+EAA+E;AAC/E,wBAAsB,gCAAgC,CAAC,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,YAAY;;;;;;;;;;;;;;;;;GA+CnF"}
@@ -0,0 +1,108 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { constants } from 'node:fs';
3
+ import { link, lstat, open, realpath, unlink } from 'node:fs/promises';
4
+ import { join, resolve } from 'node:path';
5
+ const digest = (bytes) => createHash('sha256').update(bytes).digest('hex');
6
+ const unavailable = () => new Error('named_session_stopped_lock_unconfirmed');
7
+ async function privateFile(path, uid, limit) {
8
+ const file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
9
+ try {
10
+ const stat = await file.stat({ bigint: true });
11
+ if (!stat.isFile() || Number(stat.uid) !== uid || (Number(stat.mode) & 0o077) !== 0 || stat.size > BigInt(limit))
12
+ throw unavailable();
13
+ const bytes = await file.readFile();
14
+ if (bytes.length > limit)
15
+ throw unavailable();
16
+ return { bytes, dev: stat.dev, ino: stat.ino };
17
+ }
18
+ finally {
19
+ await file.close();
20
+ }
21
+ }
22
+ /** Called only under the owning CLI's home-wide startup mutation admission. */
23
+ export async function reconcileStoppedNamedSessionLock(input, deps) {
24
+ const uid = process.getuid?.() ?? -1;
25
+ if (process.platform !== 'linux' || uid <= 0 || resolve(input.home) !== input.home
26
+ || !/^[a-z][a-z0-9-]{0,47}$/.test(input.name) || input.registration.name !== input.name
27
+ || input.registration.enabled || input.registration.maintenanceFence
28
+ || ![input.registrationSha256, input.lockSha256].every(v => /^[a-f0-9]{64}$/.test(v)))
29
+ throw unavailable();
30
+ const root = join(input.home, 'sessions', input.name), registrationPath = join(root, 'registration.json'), lockPath = join(root, 'service.lock');
31
+ for (const path of [input.home, join(input.home, 'sessions'), root]) {
32
+ const stat = await lstat(path);
33
+ if (!stat.isDirectory() || stat.isSymbolicLink() || stat.uid !== uid || (stat.mode & 0o077) !== 0 || await realpath(path) !== path)
34
+ throw unavailable();
35
+ }
36
+ const verify = async () => {
37
+ await deps.assertTopology();
38
+ const registration = await privateFile(registrationPath, uid, 4096);
39
+ if (digest(registration.bytes) !== input.registrationSha256
40
+ || JSON.stringify(JSON.parse(registration.bytes.toString('utf8'))) !== JSON.stringify(input.registration))
41
+ throw unavailable();
42
+ const lock = await privateFile(lockPath, uid, 64), text = lock.bytes.toString('utf8');
43
+ if (digest(lock.bytes) !== input.lockSha256 || !/^([1-9][0-9]*)\n?$/.test(text))
44
+ throw unavailable();
45
+ const pid = Number(text.trim());
46
+ if (!Number.isSafeInteger(pid) || pid <= 1 || await deps.processState(pid) !== 'stopped')
47
+ throw unavailable();
48
+ return { ...lock, pid };
49
+ };
50
+ const before = await verify(), archiveName = 'service.lock.stopped.' + input.lockSha256;
51
+ const receipt = { ok: true, planned: !input.apply, name: input.name, workspaceId: input.registration.identity.workspaceId,
52
+ bindingId: input.registration.bindingId, registrationSha256: input.registrationSha256, lockSha256: input.lockSha256,
53
+ archive: archiveName, previousPid: before.pid, registrationChanged: false, budgetChanged: false, providerStarted: false, protectedStoreRead: false,
54
+ ready: false, nativeContinuationAuthorized: false };
55
+ if (!input.apply)
56
+ return { ...receipt, state: 'stopped_lock_reconciliation_planned' };
57
+ const current = await verify();
58
+ if (current.dev !== before.dev || current.ino !== before.ino)
59
+ throw unavailable();
60
+ const archive = join(root, archiveName);
61
+ try {
62
+ await link(lockPath, archive);
63
+ }
64
+ catch (error) {
65
+ if (error.code !== 'EEXIST')
66
+ throw error;
67
+ }
68
+ const retained = await privateFile(archive, uid, 64);
69
+ if (retained.dev !== before.dev || retained.ino !== before.ino || digest(retained.bytes) !== input.lockSha256)
70
+ throw unavailable();
71
+ const archiveFile = await open(archive, constants.O_RDONLY | constants.O_NOFOLLOW);
72
+ try {
73
+ await archiveFile.sync();
74
+ }
75
+ finally {
76
+ await archiveFile.close();
77
+ }
78
+ const directory = await open(root, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
79
+ try {
80
+ await directory.sync();
81
+ }
82
+ finally {
83
+ await directory.close();
84
+ }
85
+ const final = await verify();
86
+ if (final.dev !== before.dev || final.ino !== before.ino)
87
+ throw unavailable();
88
+ await unlink(lockPath);
89
+ const completedDirectory = await open(root, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
90
+ try {
91
+ await completedDirectory.sync();
92
+ }
93
+ finally {
94
+ await completedDirectory.close();
95
+ }
96
+ try {
97
+ await lstat(lockPath);
98
+ throw unavailable();
99
+ }
100
+ catch (error) {
101
+ if (error.code !== 'ENOENT')
102
+ throw error;
103
+ }
104
+ if (digest((await privateFile(registrationPath, uid, 4096)).bytes) !== input.registrationSha256)
105
+ throw unavailable();
106
+ return { ...receipt, state: 'stopped_lock_reconciled', planned: false };
107
+ }
108
+ //# sourceMappingURL=namedSessionStoppedLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namedSessionStoppedLock.js","sourceRoot":"","sources":["../src/namedSessionStoppedLock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=namedSessionStoppedLock.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namedSessionStoppedLock.test.d.ts","sourceRoot":"","sources":["../src/namedSessionStoppedLock.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
1
+ import assert from 'node:assert/strict';
2
+ import { createHash } from 'node:crypto';
3
+ import { chmod, lstat, mkdir, mkdtemp, readFile, realpath, rename, symlink, writeFile } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import test from 'node:test';
7
+ import { reconcileStoppedNamedSessionLock } from './namedSessionStoppedLock.js';
8
+ const linux = { skip: process.platform !== 'linux' }, sha = (v) => createHash('sha256').update(v).digest('hex');
9
+ async function fixture() {
10
+ const home = await realpath(await mkdtemp(join(tmpdir(), 'dharma-stopped-lock-')));
11
+ await chmod(home, 0o700);
12
+ const name = 'codex-fixture', root = join(home, 'sessions', name);
13
+ await mkdir(root, { recursive: true, mode: 0o700 });
14
+ await chmod(join(home, 'sessions'), 0o700);
15
+ const registration = { schema: 'dharma.named-session/v1', name, bindingId: '11111111-1111-4111-8111-111111111111', enabled: false,
16
+ maximumCostCents: 1000, maximumTurnCostCents: 25, identity: { organizationId: 'org_fixture', provider: 'codex',
17
+ repositoryBindingId: '22222222-2222-4222-8222-222222222222', workspaceId: '33333333-3333-4333-8333-333333333333',
18
+ endpointId: '44444444-4444-4444-8444-444444444444', membershipId: '55555555-5555-4555-8555-555555555555', deviceId: '66666666-6666-4666-8666-666666666666' } };
19
+ await writeFile(join(root, 'registration.json'), JSON.stringify(registration) + '\n', { mode: 0o600 });
20
+ const lock = join(root, 'service.lock');
21
+ await writeFile(lock, '987654\n', { mode: 0o600 });
22
+ const input = { home, name, registration, registrationSha256: sha(await readFile(join(root, 'registration.json'))), lockSha256: sha(await readFile(lock)), apply: false };
23
+ const deps = { assertTopology: async () => { }, processState: async () => 'stopped' };
24
+ return { home, root, lock, input, deps };
25
+ }
26
+ test('stopped-lock plan is inert and apply retains the exact original lock inode and registration', linux, async () => {
27
+ const f = await fixture(), before = await lstat(f.lock);
28
+ const plan = await reconcileStoppedNamedSessionLock(f.input, f.deps);
29
+ assert.equal(plan.state, 'stopped_lock_reconciliation_planned');
30
+ assert.equal((await lstat(f.lock)).ino, before.ino);
31
+ await assert.rejects(lstat(join(f.root, plan.archive)), { code: 'ENOENT' });
32
+ const result = await reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps);
33
+ assert.equal(result.state, 'stopped_lock_reconciled');
34
+ assert.equal((await lstat(join(f.root, result.archive))).ino, before.ino);
35
+ assert.equal(result.registrationChanged, false);
36
+ assert.equal(result.budgetChanged, false);
37
+ assert.equal(result.protectedStoreRead, false);
38
+ await assert.rejects(lstat(f.lock), { code: 'ENOENT' });
39
+ });
40
+ for (const cause of ['enabled', 'wrong-registration', 'wrong-lock', 'running', 'unknown', 'unsafe-parent', 'foreign-topology', 'symlink', 'malformed']) {
41
+ test('stopped-lock reconciliation refuses ' + cause + ' without removing the lock', linux, async () => {
42
+ const f = await fixture();
43
+ if (cause === 'enabled')
44
+ f.input.registration.enabled = true;
45
+ if (cause === 'wrong-registration')
46
+ f.input.registrationSha256 = '0'.repeat(64);
47
+ if (cause === 'wrong-lock')
48
+ f.input.lockSha256 = '0'.repeat(64);
49
+ if (cause === 'running' || cause === 'unknown')
50
+ f.deps.processState = async () => cause;
51
+ if (cause === 'unsafe-parent')
52
+ await chmod(f.root, 0o755);
53
+ if (cause === 'foreign-topology')
54
+ f.deps.assertTopology = async () => { throw Error('foreign controller'); };
55
+ if (cause === 'symlink') {
56
+ await writeFile(join(f.root, 'foreign'), '987654\n', { mode: 0o600 });
57
+ f.input.name = 'linked';
58
+ f.input.registration = { ...f.input.registration, name: 'linked' };
59
+ await symlink(f.root, join(f.home, 'sessions', 'linked'));
60
+ }
61
+ if (cause === 'malformed') {
62
+ await writeFile(f.lock, 'not-a-pid\n');
63
+ f.input.lockSha256 = sha(await readFile(f.lock));
64
+ }
65
+ await assert.rejects(reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps));
66
+ assert.equal((await lstat(f.lock)).isFile(), true);
67
+ });
68
+ }
69
+ test('a topology change after archive creation leaves the active lock intact', linux, async () => {
70
+ const f = await fixture();
71
+ let checks = 0;
72
+ f.deps.assertTopology = async () => { if (++checks === 3)
73
+ throw Error('topology changed'); };
74
+ await assert.rejects(reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps));
75
+ assert.equal((await lstat(f.lock)).isFile(), true);
76
+ assert.equal(sha(await readFile(join(f.root, 'service.lock.stopped.' + f.input.lockSha256))), f.input.lockSha256);
77
+ });
78
+ test('a symbolic service lock and an existing foreign archive never admit reconciliation', linux, async () => {
79
+ for (const cause of ['symlink', 'archive']) {
80
+ const f = await fixture();
81
+ if (cause === 'symlink') {
82
+ await rename(f.lock, join(f.root, 'original'));
83
+ await symlink(join(f.root, 'original'), f.lock);
84
+ }
85
+ else
86
+ await writeFile(join(f.root, 'service.lock.stopped.' + f.input.lockSha256), 'foreign\n', { mode: 0o600 });
87
+ await assert.rejects(reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps));
88
+ assert.equal(Boolean(await lstat(f.lock)), true);
89
+ }
90
+ });
91
+ test('registration replacement or a newly live PID after planning cannot remove the active lock', linux, async () => {
92
+ for (const cause of ['registration', 'pid']) {
93
+ const f = await fixture();
94
+ let n = 0;
95
+ f.deps.assertTopology = async () => { if (++n === 2 && cause === 'registration')
96
+ await writeFile(join(f.root, 'registration.json'), '{}\n'); };
97
+ let pidChecks = 0;
98
+ if (cause === 'pid')
99
+ f.deps.processState = async () => ++pidChecks === 1 ? 'stopped' : 'running';
100
+ await assert.rejects(reconcileStoppedNamedSessionLock({ ...f.input, apply: true }, f.deps));
101
+ assert.equal((await lstat(f.lock)).isFile(), true);
102
+ }
103
+ });
104
+ //# sourceMappingURL=namedSessionStoppedLock.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namedSessionStoppedLock.test.js","sourceRoot":"","sources":["../src/namedSessionStoppedLock.test.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@ export declare function reconcileProviderSessionReply(input: {
11
11
  questionId: string;
12
12
  taskId: string;
13
13
  completionHash: string;
14
- reasonCode: "content_or_contract_blocked" | "receipt_invalid" | "delivery_unconfirmed";
14
+ reasonCode: "delivery_unconfirmed" | "content_or_contract_blocked" | "receipt_invalid";
15
15
  dispositionHash?: undefined;
16
16
  delivered?: undefined;
17
17
  replyReceiptHash?: undefined;
@@ -62,6 +62,8 @@ export declare function enableRelayAutostart(options: RelayAutostartOptions & {
62
62
  policy: string | null;
63
63
  version: string;
64
64
  preserveStandardAnchor?: boolean;
65
+ /** Existing Linux registration only; keep its controller paused during a signing-maintenance upgrade. */
66
+ pauseForSigningMaintenance?: boolean;
65
67
  }): Promise<RelayAutostartState>;
66
68
  export declare function disableRelayAutostart(options: RelayAutostartOptions): Promise<RelayAutostartState>;
67
69
  export declare function startRelayAutostart(options: RelayAutostartOptions): Promise<{
@@ -72,6 +74,7 @@ export declare function startRelayAutostart(options: RelayAutostartOptions): Pro
72
74
  export declare function inspectOwnedRelayAutostart(options: RelayAutostartOptions, inspection?: {
73
75
  allowLegacy?: boolean;
74
76
  }): Promise<RelayAutostartRegistration>;
77
+ export declare function assertRelayAutostartPaused(options: RelayAutostartOptions): Promise<void>;
75
78
  export declare function stopRelayAutostart(options: RelayAutostartOptions): Promise<{
76
79
  state: "stop_requested";
77
80
  backend: "container-entrypoint" | "systemd-user" | "windows-task" | "launchd-user";
@@ -1 +1 @@
1
- {"version":3,"file":"relayAutostart.d.ts","sourceRoot":"","sources":["../src/relayAutostart.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relayAutostart.d.ts","sourceRoot":"","sources":["../src/relayAutostart.ts"],"names":[],"mappings":"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"}
@@ -4,9 +4,9 @@ import { lstat, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
4
4
  import { homedir } from 'node:os';
5
5
  import { dirname, isAbsolute, join, posix } from 'node:path';
6
6
  import { promisify } from 'node:util';
7
- import { assertContainerStartupOwnership, containerEntrypointAvailable, containerStartupControl, containerStartupState, ownsContainerStartup, writeContainerRegistration, readContainerRegistration } from './containerRelayLifecycle.js';
7
+ import { assertContainerStartupOwnership, containerEntrypointAvailable, containerStartupControl, containerStartupState, ownsContainerStartup, containerStartupPaused, writeContainerRegistration, readContainerRegistration } from './containerRelayLifecycle.js';
8
8
  import { currentBootstrapHostScope } from './bootstrapHostScope.js';
9
- import { assertWslHostPreflight, disableWslRelayHost, enableWslRelayHost, startWslRelayHost, wslRelayHostStatus } from './wslRelayHost.js';
9
+ import { assertWslHostPreflight, assertWslRelayHostPaused, pauseWslRelayHost, disableWslRelayHost, enableWslRelayHost, startWslRelayHost, wslRelayHostStatus } from './wslRelayHost.js';
10
10
  const execFileAsync = promisify(execFile);
11
11
  const UNIT_NAME = 'dharma-agent-fabric.service';
12
12
  const MAC_LABEL = 'io.dharma.agent-fabric.relay';
@@ -341,6 +341,9 @@ export async function relayAutostartStatus(options) {
341
341
  }
342
342
  export async function enableRelayAutostart(options) {
343
343
  const platform = options.platform || process.platform;
344
+ if (options.pauseForSigningMaintenance && (platform !== 'linux' || options.preserveStandardAnchor)) {
345
+ throw new Error('relay_signing_maintenance_startup_scope_invalid');
346
+ }
344
347
  if (platform !== 'linux' && platform !== 'win32' && platform !== 'darwin') {
345
348
  throw new Error(`Relay autostart is unsupported on ${platform}.`);
346
349
  }
@@ -349,6 +352,8 @@ export async function enableRelayAutostart(options) {
349
352
  const userHome = options.userHome || homedir();
350
353
  const run = options.run || defaultRunner;
351
354
  const previous = await readRegistration(options);
355
+ if (options.pauseForSigningMaintenance && !previous)
356
+ throw new Error('relay_signing_maintenance_startup_scope_invalid');
352
357
  const backend = platform === 'linux'
353
358
  ? await containerEntrypointAvailable(options) ? 'container-entrypoint' : 'systemd-user'
354
359
  : platform === 'darwin' ? 'launchd-user' : 'windows-task';
@@ -393,7 +398,7 @@ export async function enableRelayAutostart(options) {
393
398
  if (previous && !await ownsStartupFile(options, previous))
394
399
  throw new Error('autostart_conflict: container startup is not owned.');
395
400
  await writeContainerRegistration(options, registration);
396
- await containerStartupControl(options, registration, true);
401
+ await containerStartupControl(options, registration, !options.pauseForSigningMaintenance);
397
402
  return containerStartupState(options, registration);
398
403
  }
399
404
  if (platform === 'win32' && !previous) {
@@ -451,8 +456,11 @@ export async function enableRelayAutostart(options) {
451
456
  await writeFile(registrationPath(options.home), `${JSON.stringify(registration, null, 2)}\n`, { mode: 0o600 });
452
457
  if (platform === 'linux') {
453
458
  await run('systemctl', ['--user', 'daemon-reload']);
454
- await run('systemctl', ['--user', 'enable', UNIT_NAME]);
455
- await enableWslRelayHost(options);
459
+ await run('systemctl', ['--user', options.pauseForSigningMaintenance ? 'disable' : 'enable', UNIT_NAME]);
460
+ if (options.pauseForSigningMaintenance)
461
+ await pauseWslRelayHost(options);
462
+ else
463
+ await enableWslRelayHost(options);
456
464
  }
457
465
  else if (platform === 'darwin') {
458
466
  await run('/usr/bin/plutil', ['-lint', destination]);
@@ -474,7 +482,7 @@ export async function enableRelayAutostart(options) {
474
482
  await run('powershell.exe', encodedPowerShell(command));
475
483
  }
476
484
  const status = await relayAutostartStatus(options);
477
- if (status.state !== 'enabled')
485
+ if (status.state !== (options.pauseForSigningMaintenance ? 'disabled' : 'enabled'))
478
486
  throw new Error(`Relay autostart registration was not verified (${status.state}).`);
479
487
  return status;
480
488
  }
@@ -561,6 +569,37 @@ export async function inspectOwnedRelayAutostart(options, inspection = {}) {
561
569
  await macLoaded(options, registration);
562
570
  return registration;
563
571
  }
572
+ export async function assertRelayAutostartPaused(options) {
573
+ const registration = await inspectOwnedRelayAutostart(options);
574
+ if (registration.backend === 'container-entrypoint') {
575
+ // Only a valid paused control awaiting its new matching heartbeat is polled.
576
+ // Identity, permission, malformed metadata and other failures stop immediately.
577
+ for (let attempt = 0; attempt < 50; attempt++) {
578
+ if (await containerStartupPaused(options, registration))
579
+ return;
580
+ if (attempt < 49)
581
+ await new Promise(resolve => setTimeout(resolve, 100));
582
+ }
583
+ throw Error('relay_startup_pause_unconfirmed');
584
+ }
585
+ if (registration.backend !== 'systemd-user' || (await relayAutostartStatus(options)).state !== 'disabled') {
586
+ throw Error('relay_startup_pause_unconfirmed');
587
+ }
588
+ const run = options.run || defaultRunner;
589
+ let active;
590
+ try {
591
+ active = (await run('systemctl', ['--user', 'is-active', UNIT_NAME])).stdout.trim();
592
+ }
593
+ catch (error) {
594
+ const e = error;
595
+ if (e.code !== 3 || typeof e.stdout !== 'string' || e.stdout.trim() !== 'inactive')
596
+ throw error;
597
+ active = 'inactive';
598
+ }
599
+ if (active !== 'inactive')
600
+ throw Error('relay_startup_pause_unconfirmed');
601
+ await assertWslRelayHostPaused(options);
602
+ }
564
603
  export async function stopRelayAutostart(options) {
565
604
  const registration = await inspectOwnedRelayAutostart(options);
566
605
  const run = options.run || defaultRunner;