@dharma-ai-labs/agent-fabric 0.2.124 → 0.2.126

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.
@@ -7,9 +7,10 @@ import { join } from 'node:path';
7
7
  import test from 'node:test';
8
8
  import { fileURLToPath, pathToFileURL } from 'node:url';
9
9
  import { promisify } from 'node:util';
10
- import { acceptedTrajectoryHead, activateAgyPlugin, attestAgySkillActivation, attestHermesSkillBundleActivation, actionDecisionCapabilityFreshUntil, canonicalFilesystemPath, controlAgentDecisionUrl, installAvailableNativeAgentFabricBootstraps, assertCapsuleAuthorizedByCurrentPolicy, assertRecoveredTaskWorkspacePolicy, assertTaskWorkspacePolicy, assertTaskSkillPin, installNativeAgentFabricBootstrap, installClaudeReadOnlyProjectPermissions, installRepositoryAgentFabricSkill, isDirectExecution, isTransientBootstrapError, loadAgentFabricOnboardingContract, loadOrCreateInstallationId, materializeWorkspacePolicy, applyServerEvidencePolicy, materializeInlineSkillFiles, validateSkillBundleSources, nativeSkillDirectory, nativeSkillDirectoryForWorkspace, nativeSkillRootMatchingAuthorization, normalizeGitRemoteIdentity, postTaskOutcome, parseCliOptions, parseSelectedProviderIds, pathExistsOrThrow, portalUrl, providerHintFromEnvironment, providerHintFromProcessArgv, probeRelayConnection, preflightBootstrapWorkspaceIdentity, rawLocalRetentionDays, syncPendingRetentionCapsules, requireCompletedBootstrapEvidence, retryBootstrapOnboarding, synchronizeBootstrapEvidence, deferUnavailableRelayRetention, recoverLegacySkillBundleIdAfterAuthorizationFailure, installedBundleIdForSkillPollAfterAuthorizationFailure, recoveredTaskPolicyWasSuperseded, acquireRelayProcessLease, acquireRelaySupervisorLease, relayProcessState, relaySupervisorProcessState, releaseDailyContentUpload, reserveDailyContentUpload, run, runAssistantCommand, sourceRepositoryFingerprint, stableRepositoryLauncherContents, summarizeBootstrapOrganizationApi, ensureAgyReadOnlyAttestationPermission, attestAgySkillBundleActivation, responseTextFromEvent, taskResponsePreview, taskReceiptSession, taskSkillPinFailureCode, verifyAgentFabricSkillInstallation, waitForRelayReadiness, withWorkspacePolicyRefreshLock, withRelayStartupMutation, withWorkspaceSkillActivationLock, } from './index.js';
10
+ import { acceptedTrajectoryHead, activateAgyPlugin, attestAgySkillActivation, attestHermesSkillBundleActivation, actionDecisionCapabilityFreshUntil, canonicalFilesystemPath, controlAgentDecisionUrl, installAvailableNativeAgentFabricBootstraps, assertCapsuleAuthorizedByCurrentPolicy, assertRecoveredTaskWorkspacePolicy, assertTaskWorkspacePolicy, assertTaskSkillPin, installNativeAgentFabricBootstrap, installClaudeReadOnlyProjectPermissions, installRepositoryAgentFabricSkill, initialBootstrapEvidenceDisposition, isDirectExecution, isTransientBootstrapError, loadAgentFabricOnboardingContract, loadOrCreateInstallationId, materializeWorkspacePolicy, applyServerEvidencePolicy, materializeInlineSkillFiles, validateSkillBundleSources, nativeSkillDirectory, nativeSkillDirectoryForWorkspace, nativeSkillRootMatchingAuthorization, normalizeGitRemoteIdentity, postTaskOutcome, parseCliOptions, parseSelectedProviderIds, pathExistsOrThrow, portalUrl, providerHintFromEnvironment, providerHintFromProcessArgv, probeRelayConnection, preflightBootstrapWorkspaceIdentity, publishedPackageCanDeferSecretEvidence, rawLocalRetentionDays, syncPendingRetentionCapsules, requireCompletedBootstrapEvidence, retryBootstrapOnboarding, synchronizeBootstrapEvidence, deferUnavailableRelayRetention, recoverLegacySkillBundleIdAfterAuthorizationFailure, installedBundleIdForSkillPollAfterAuthorizationFailure, recoveredTaskPolicyWasSuperseded, acquireRelayProcessLease, acquireRelaySupervisorLease, relayProcessState, relaySupervisorProcessState, releaseDailyContentUpload, reserveDailyContentUpload, run, runAssistantCommand, sourceRepositoryFingerprint, stableRepositoryLauncherContents, summarizeBootstrapOrganizationApi, ensureAgyReadOnlyAttestationPermission, attestAgySkillBundleActivation, responseTextFromEvent, taskResponsePreview, taskReceiptSession, taskSkillPinFailureCode, verifyAgentFabricSkillInstallation, waitForRelayReadiness, withWorkspacePolicyRefreshLock, withRelayStartupMutation, withWorkspaceSkillActivationLock, } from './index.js';
11
11
  import { canonicalize, signCanonicalObject } from '@dharma-ai-labs/agent-fabric-contracts';
12
12
  import { buildTrajectoryCapsule, trajectoryCapsuleHash } from '@dharma-ai-labs/agent-fabric-evidence-reduction';
13
+ import { AgentFabricRequestError } from '@dharma-ai-labs/agent-fabric-relay-client';
13
14
  import { CLI_USAGE } from './usage.js';
14
15
  import { workspaceIdForDevice } from './onboardingWorkspace.js';
15
16
  import { isSupportedNodeVersion, launchWithRuntime, nodeRuntimeCandidates, runtimeBootstrapHint, } from './runtime-bootstrap.js';
@@ -140,20 +141,37 @@ test('bootstrap defers policy-rejected evidence without weakening the disclosure
140
141
  });
141
142
  assert.deepEqual(result, {
142
143
  state: 'deferred',
143
- captured: 0,
144
- synced: 0,
144
+ captured: null,
145
+ synced: null,
145
146
  reason: 'policy_boundary',
146
147
  errorCode: 'local_path_disclosure_forbidden',
147
148
  });
148
149
  });
150
+ test('only a published package under the same source policy can defer a definitive secret rejection', async () => {
151
+ const denied = await synchronizeBootstrapEvidence(async () => {
152
+ throw new AgentFabricRequestError({ error: { code: 'policy_boundary',
153
+ message: 'secret_disclosure_forbidden' } }, 403, true);
154
+ });
155
+ assert.equal(denied.errorCode, 'secret_disclosure_forbidden');
156
+ const published = { state: 'published', releaseId: '11111111-1111-4111-8111-111111111111',
157
+ sourcePolicyGenerationId: '22222222-2222-4222-8222-222222222222' };
158
+ assert.equal(publishedPackageCanDeferSecretEvidence(denied, published, '22222222-2222-4222-8222-222222222222'), true);
159
+ assert.equal(publishedPackageCanDeferSecretEvidence(denied, published, '33333333-3333-4333-8333-333333333333'), false);
160
+ assert.equal(publishedPackageCanDeferSecretEvidence(denied, { ...published, state: 'accepted' }, '22222222-2222-4222-8222-222222222222'), false);
161
+ const ambiguous = await synchronizeBootstrapEvidence(async () => {
162
+ throw new AgentFabricRequestError({ error: { code: 'policy_boundary',
163
+ message: 'secret_disclosure_forbidden' } }, 503, false);
164
+ });
165
+ assert.equal(publishedPackageCanDeferSecretEvidence(ambiguous, published, '22222222-2222-4222-8222-222222222222'), false);
166
+ });
149
167
  test('bootstrap reports non-policy evidence failures without returning sensitive error text', async () => {
150
168
  const result = await synchronizeBootstrapEvidence(async () => {
151
169
  throw new Error('fetch failed for C:/Users/customer/private-session.json');
152
170
  });
153
171
  assert.deepEqual(result, {
154
172
  state: 'deferred',
155
- captured: 0,
156
- synced: 0,
173
+ captured: null,
174
+ synced: null,
157
175
  reason: 'capture_unavailable',
158
176
  errorCode: 'evidence_capture_failed',
159
177
  });
@@ -165,8 +183,8 @@ test('bootstrap identifies unavailable retention without weakening other capture
165
183
  });
166
184
  assert.deepEqual(result, {
167
185
  state: 'deferred',
168
- captured: 0,
169
- synced: 0,
186
+ captured: null,
187
+ synced: null,
170
188
  reason: 'retention_not_ready',
171
189
  errorCode: 'agent_fabric_retention_not_ready',
172
190
  });
@@ -175,6 +193,16 @@ test('bootstrap records successful evidence synchronization', async () => {
175
193
  const result = await synchronizeBootstrapEvidence(async () => ({ captured: 2, synced: 2 }));
176
194
  assert.deepEqual(result, { state: 'synchronized', captured: 2, synced: 2 });
177
195
  });
196
+ test('eligible history without disclosure is reported as denied, not synchronized', () => {
197
+ assert.deepEqual(initialBootstrapEvidenceDisposition(3, false), {
198
+ state: 'denied_disclosure', captured: 0, synced: 0,
199
+ reason: 'policy_boundary', errorCode: 'automatic_disclosure_not_ready',
200
+ });
201
+ assert.deepEqual(initialBootstrapEvidenceDisposition(0, false), {
202
+ state: 'synchronized', captured: 0, synced: 0,
203
+ });
204
+ assert.throws(() => initialBootstrapEvidenceDisposition(Number.NaN, true), /invalid trajectory count/);
205
+ });
178
206
  test('relay defers unavailable retention without stopping signed task polling', async () => {
179
207
  const result = await deferUnavailableRelayRetention(async () => {
180
208
  throw new Error('agent_fabric_retention_not_ready: Content synchronization is unavailable until retention is enabled.');
@@ -1480,6 +1508,61 @@ test('queued capsules from a replaced device are retained locally but never sent
1480
1508
  assert.deepEqual(sent, [current.trajectoryId]);
1481
1509
  assert.equal(old.deviceId, '11111111-1111-4111-8111-111111111111');
1482
1510
  });
1511
+ test('definitive secret rejection retires only its upload queue row and leaves later work eligible', async () => {
1512
+ const base = await materializeWorkspacePolicy({
1513
+ workspace: await mkdtemp(join(tmpdir(), 'dharma-secret-rejection-')),
1514
+ organizationId: 'org_northstar', revision: 'local',
1515
+ });
1516
+ const deviceId = '22222222-2222-4222-8222-222222222222';
1517
+ const session = (sessionId) => ({
1518
+ provider: 'codex', sessionId, sourcePath: '/private/codex.jsonl',
1519
+ workspace: '/repo', coverage: 'observed',
1520
+ startedAt: '2026-09-23T00:00:00.000Z', endedAt: '2026-09-23T00:00:01.000Z',
1521
+ records: [{ native: { type: 'message' }, sourcePath: '/private/codex.jsonl', line: 1,
1522
+ workspace: '/repo', timestamp: '2026-09-23T00:00:00.000Z', kind: 'metadata' }],
1523
+ });
1524
+ const capsules = ['denied', 'allowed'].map(sessionId => buildTrajectoryCapsule({
1525
+ organizationId: 'org_northstar', deviceId, workspaceId: 'workspace-northstar',
1526
+ session: session(sessionId), policy: base.policy,
1527
+ rawContentId: `sha256:${'a'.repeat(64)}`, rawBytes: 32,
1528
+ }));
1529
+ const pending = [...capsules];
1530
+ const discarded = [];
1531
+ const synced = [];
1532
+ const vault = {
1533
+ listPendingCapsuleSyncs: async () => pending.map(capsule => ({ trajectoryId: capsule.trajectoryId,
1534
+ revision: capsule.revision, capsule })),
1535
+ markCapsuleSynced: (trajectoryId) => {
1536
+ synced.push(trajectoryId);
1537
+ pending.splice(pending.findIndex(c => c.trajectoryId === trajectoryId), 1);
1538
+ },
1539
+ discardPendingCapsuleSync: (trajectoryId, _revision, reason) => {
1540
+ discarded.push(reason);
1541
+ pending.splice(pending.findIndex(c => c.trajectoryId === trajectoryId), 1);
1542
+ },
1543
+ };
1544
+ const fabric = {
1545
+ config: { organizationId: 'org_northstar', deviceId },
1546
+ syncTrajectory: async (capsule) => {
1547
+ if (capsule.trajectoryId === capsules[0].trajectoryId) {
1548
+ throw new AgentFabricRequestError({ error: { code: 'policy_boundary',
1549
+ message: 'secret_disclosure_forbidden' } }, 403, true);
1550
+ }
1551
+ },
1552
+ };
1553
+ assert.equal(await syncPendingRetentionCapsules(vault, fabric, base.policy, 'workspace-northstar'), 1);
1554
+ assert.deepEqual(discarded, ['secret_disclosure_forbidden']);
1555
+ assert.deepEqual(synced, [capsules[1].trajectoryId]);
1556
+ assert.equal(pending.length, 0);
1557
+ pending.push(capsules[0]);
1558
+ fabric.syncTrajectory = async () => {
1559
+ throw new AgentFabricRequestError({ error: { code: 'policy_boundary',
1560
+ message: 'secret_disclosure_forbidden' } }, 503, false);
1561
+ };
1562
+ await assert.rejects(() => syncPendingRetentionCapsules(vault, fabric, base.policy, 'workspace-northstar'), /secret_disclosure_forbidden/);
1563
+ assert.equal(pending.length, 1);
1564
+ assert.deepEqual(discarded, ['secret_disclosure_forbidden']);
1565
+ });
1483
1566
  test('oversized queued current-device revision is retired only after checking the accepted head', async () => {
1484
1567
  const base = await materializeWorkspacePolicy({
1485
1568
  workspace: await mkdtemp(join(tmpdir(), 'dharma-oversized-capsule-')),