@dharma-ai-labs/agent-fabric 0.2.49 → 0.2.51

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 (198) hide show
  1. package/dist/index.d.ts +88 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +840 -175
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.test.js +2 -2
  6. package/dist/repositoryCandidateSync.d.ts +55 -0
  7. package/dist/repositoryCandidateSync.d.ts.map +1 -0
  8. package/dist/repositoryCandidateSync.js +177 -0
  9. package/dist/repositoryCandidateSync.js.map +1 -0
  10. package/dist/repositoryCandidateSync.test.d.ts +2 -0
  11. package/dist/repositoryCandidateSync.test.d.ts.map +1 -0
  12. package/dist/repositoryCandidateSync.test.js +141 -0
  13. package/dist/repositoryCandidateSync.test.js.map +1 -0
  14. package/dist/repositoryInstalledKnowledge.d.ts +13 -0
  15. package/dist/repositoryInstalledKnowledge.d.ts.map +1 -0
  16. package/dist/repositoryInstalledKnowledge.js +25 -0
  17. package/dist/repositoryInstalledKnowledge.js.map +1 -0
  18. package/dist/repositoryInstallerFiles.d.ts +6 -0
  19. package/dist/repositoryInstallerFiles.d.ts.map +1 -0
  20. package/dist/repositoryInstallerFiles.js +113 -0
  21. package/dist/repositoryInstallerFiles.js.map +1 -0
  22. package/dist/repositoryKnowledge.d.ts +119 -0
  23. package/dist/repositoryKnowledge.d.ts.map +1 -0
  24. package/dist/repositoryKnowledge.js +462 -0
  25. package/dist/repositoryKnowledge.js.map +1 -0
  26. package/dist/repositoryKnowledge.test.d.ts +2 -0
  27. package/dist/repositoryKnowledge.test.d.ts.map +1 -0
  28. package/dist/repositoryKnowledge.test.js +245 -0
  29. package/dist/repositoryKnowledge.test.js.map +1 -0
  30. package/dist/repositoryKnowledgeRetention.test.d.ts +2 -0
  31. package/dist/repositoryKnowledgeRetention.test.d.ts.map +1 -0
  32. package/dist/repositoryKnowledgeRetention.test.js +386 -0
  33. package/dist/repositoryKnowledgeRetention.test.js.map +1 -0
  34. package/dist/repositoryOnboardingCaller.test.d.ts +2 -0
  35. package/dist/repositoryOnboardingCaller.test.d.ts.map +1 -0
  36. package/dist/repositoryOnboardingCaller.test.js +216 -0
  37. package/dist/repositoryOnboardingCaller.test.js.map +1 -0
  38. package/dist/repositoryOnboardingFlow.test.d.ts +2 -0
  39. package/dist/repositoryOnboardingFlow.test.d.ts.map +1 -0
  40. package/dist/repositoryOnboardingFlow.test.js +47 -0
  41. package/dist/repositoryOnboardingFlow.test.js.map +1 -0
  42. package/dist/repositoryPackage.d.ts +115 -0
  43. package/dist/repositoryPackage.d.ts.map +1 -0
  44. package/dist/repositoryPackage.js +1095 -0
  45. package/dist/repositoryPackage.js.map +1 -0
  46. package/dist/repositoryPackage.test.d.ts +2 -0
  47. package/dist/repositoryPackage.test.d.ts.map +1 -0
  48. package/dist/repositoryPackage.test.js +709 -0
  49. package/dist/repositoryPackage.test.js.map +1 -0
  50. package/dist/repositoryPackageDelivery.d.ts +29 -0
  51. package/dist/repositoryPackageDelivery.d.ts.map +1 -0
  52. package/dist/repositoryPackageDelivery.js +140 -0
  53. package/dist/repositoryPackageDelivery.js.map +1 -0
  54. package/dist/repositoryPackageDelivery.test.d.ts +2 -0
  55. package/dist/repositoryPackageDelivery.test.d.ts.map +1 -0
  56. package/dist/repositoryPackageDelivery.test.js +787 -0
  57. package/dist/repositoryPackageDelivery.test.js.map +1 -0
  58. package/dist/repositoryPackageDeliveryCaller.test.d.ts +2 -0
  59. package/dist/repositoryPackageDeliveryCaller.test.d.ts.map +1 -0
  60. package/dist/repositoryPackageDeliveryCaller.test.js +18 -0
  61. package/dist/repositoryPackageDeliveryCaller.test.js.map +1 -0
  62. package/dist/repositoryPackageDeliveryPreflight.test.d.ts +2 -0
  63. package/dist/repositoryPackageDeliveryPreflight.test.d.ts.map +1 -0
  64. package/dist/repositoryPackageDeliveryPreflight.test.js +29 -0
  65. package/dist/repositoryPackageDeliveryPreflight.test.js.map +1 -0
  66. package/dist/repositoryPackageTransfer.d.ts +85 -0
  67. package/dist/repositoryPackageTransfer.d.ts.map +1 -0
  68. package/dist/repositoryPackageTransfer.js +233 -0
  69. package/dist/repositoryPackageTransfer.js.map +1 -0
  70. package/dist/repositoryPackageTransfer.test.d.ts +2 -0
  71. package/dist/repositoryPackageTransfer.test.d.ts.map +1 -0
  72. package/dist/repositoryPackageTransfer.test.js +173 -0
  73. package/dist/repositoryPackageTransfer.test.js.map +1 -0
  74. package/dist/repositoryPackageTransferV2.test.d.ts +2 -0
  75. package/dist/repositoryPackageTransferV2.test.d.ts.map +1 -0
  76. package/dist/repositoryPackageTransferV2.test.js +549 -0
  77. package/dist/repositoryPackageTransferV2.test.js.map +1 -0
  78. package/dist/repositoryPackageTransferV2Schema.test.d.ts +2 -0
  79. package/dist/repositoryPackageTransferV2Schema.test.d.ts.map +1 -0
  80. package/dist/repositoryPackageTransferV2Schema.test.js +48 -0
  81. package/dist/repositoryPackageTransferV2Schema.test.js.map +1 -0
  82. package/dist/repositoryReleaseMetadata.d.ts +37 -0
  83. package/dist/repositoryReleaseMetadata.d.ts.map +1 -0
  84. package/dist/repositoryReleaseMetadata.js +251 -0
  85. package/dist/repositoryReleaseMetadata.js.map +1 -0
  86. package/dist/repositoryReleaseMetadata.test.d.ts +2 -0
  87. package/dist/repositoryReleaseMetadata.test.d.ts.map +1 -0
  88. package/dist/repositoryReleaseMetadata.test.js +297 -0
  89. package/dist/repositoryReleaseMetadata.test.js.map +1 -0
  90. package/dist/repositoryRoleDerivation.d.ts +11 -0
  91. package/dist/repositoryRoleDerivation.d.ts.map +1 -0
  92. package/dist/repositoryRoleDerivation.js +59 -0
  93. package/dist/repositoryRoleDerivation.js.map +1 -0
  94. package/dist/repositoryRoleDerivation.test.d.ts +2 -0
  95. package/dist/repositoryRoleDerivation.test.d.ts.map +1 -0
  96. package/dist/repositoryRoleDerivation.test.js +33 -0
  97. package/dist/repositoryRoleDerivation.test.js.map +1 -0
  98. package/dist/repositoryRoleMetadata.d.ts +63 -0
  99. package/dist/repositoryRoleMetadata.d.ts.map +1 -0
  100. package/dist/repositoryRoleMetadata.js +203 -0
  101. package/dist/repositoryRoleMetadata.js.map +1 -0
  102. package/dist/repositoryRoleMetadata.test.d.ts +2 -0
  103. package/dist/repositoryRoleMetadata.test.d.ts.map +1 -0
  104. package/dist/repositoryRoleMetadata.test.js +296 -0
  105. package/dist/repositoryRoleMetadata.test.js.map +1 -0
  106. package/dist/repositoryRoleQuestion.d.ts +36 -0
  107. package/dist/repositoryRoleQuestion.d.ts.map +1 -0
  108. package/dist/repositoryRoleQuestion.js +68 -0
  109. package/dist/repositoryRoleQuestion.js.map +1 -0
  110. package/dist/repositoryRoleQuestion.test.d.ts +2 -0
  111. package/dist/repositoryRoleQuestion.test.d.ts.map +1 -0
  112. package/dist/repositoryRoleQuestion.test.js +66 -0
  113. package/dist/repositoryRoleQuestion.test.js.map +1 -0
  114. package/dist/repositorySourceAuthorization.d.ts +43 -0
  115. package/dist/repositorySourceAuthorization.d.ts.map +1 -0
  116. package/dist/repositorySourceAuthorization.js +164 -0
  117. package/dist/repositorySourceAuthorization.js.map +1 -0
  118. package/dist/repositorySourceCapture.test.d.ts +2 -0
  119. package/dist/repositorySourceCapture.test.d.ts.map +1 -0
  120. package/dist/repositorySourceCapture.test.js +303 -0
  121. package/dist/repositorySourceCapture.test.js.map +1 -0
  122. package/dist/repositorySourceSync.d.ts +54 -0
  123. package/dist/repositorySourceSync.d.ts.map +1 -0
  124. package/dist/repositorySourceSync.js +88 -0
  125. package/dist/repositorySourceSync.js.map +1 -0
  126. package/dist/repositorySourceSync.test.d.ts +2 -0
  127. package/dist/repositorySourceSync.test.d.ts.map +1 -0
  128. package/dist/repositorySourceSync.test.js +218 -0
  129. package/dist/repositorySourceSync.test.js.map +1 -0
  130. package/dist/schemas/repository-knowledge-retention-v1.schema.json +26 -0
  131. package/dist/schemas/repository-knowledge-v2.schema.json +74 -0
  132. package/dist/schemas/repository-knowledge.schema.json +63 -0
  133. package/dist/schemas/repository-package-chunk-v2.schema.json +15 -0
  134. package/dist/schemas/repository-package-chunk.schema.json +18 -0
  135. package/dist/schemas/repository-package-delivery-v1.schema.json +51 -0
  136. package/dist/schemas/repository-package-envelope-v1.schema.json +16 -0
  137. package/dist/schemas/repository-package-transfer-v2.schema.json +36 -0
  138. package/dist/schemas/repository-package-transfer.schema.json +34 -0
  139. package/dist/schemas/repository-package-v2.schema.json +491 -0
  140. package/dist/schemas/repository-package-v3.schema.json +36 -0
  141. package/dist/schemas/repository-package.schema.json +94 -0
  142. package/dist/schemas/repository-release-manifest.schema.json +34 -0
  143. package/dist/schemas/repository-role-metadata.schema.json +82 -0
  144. package/dist/schemas/skill-preparation-pointer-v1.schema.json +28 -0
  145. package/dist/schemas/skill-preparation-v1.schema.json +32 -0
  146. package/dist/skillPollResponse.test.d.ts +2 -0
  147. package/dist/skillPollResponse.test.d.ts.map +1 -0
  148. package/dist/skillPollResponse.test.js +37 -0
  149. package/dist/skillPollResponse.test.js.map +1 -0
  150. package/dist/skillPreparation.test.d.ts +2 -0
  151. package/dist/skillPreparation.test.d.ts.map +1 -0
  152. package/dist/skillPreparation.test.js +163 -0
  153. package/dist/skillPreparation.test.js.map +1 -0
  154. package/dist/skillPreparationCache.d.ts +34 -0
  155. package/dist/skillPreparationCache.d.ts.map +1 -0
  156. package/dist/skillPreparationCache.js +371 -0
  157. package/dist/skillPreparationCache.js.map +1 -0
  158. package/dist/skillPreparationCache.test.d.ts +2 -0
  159. package/dist/skillPreparationCache.test.d.ts.map +1 -0
  160. package/dist/skillPreparationCache.test.js +316 -0
  161. package/dist/skillPreparationCache.test.js.map +1 -0
  162. package/dist/skillPreparationCaller.test.d.ts +2 -0
  163. package/dist/skillPreparationCaller.test.d.ts.map +1 -0
  164. package/dist/skillPreparationCaller.test.js +32 -0
  165. package/dist/skillPreparationCaller.test.js.map +1 -0
  166. package/dist/skillPreparationPump.d.ts +11 -0
  167. package/dist/skillPreparationPump.d.ts.map +1 -0
  168. package/dist/skillPreparationPump.js +41 -0
  169. package/dist/skillPreparationPump.js.map +1 -0
  170. package/dist/skillPreparationPump.test.d.ts +2 -0
  171. package/dist/skillPreparationPump.test.d.ts.map +1 -0
  172. package/dist/skillPreparationPump.test.js +87 -0
  173. package/dist/skillPreparationPump.test.js.map +1 -0
  174. package/dist/skillPreparationRecord.d.ts +2 -0
  175. package/dist/skillPreparationRecord.d.ts.map +1 -0
  176. package/dist/skillPreparationRecord.js +36 -0
  177. package/dist/skillPreparationRecord.js.map +1 -0
  178. package/dist/skillPreparationTransaction.d.ts +13 -0
  179. package/dist/skillPreparationTransaction.d.ts.map +1 -0
  180. package/dist/skillPreparationTransaction.js +236 -0
  181. package/dist/skillPreparationTransaction.js.map +1 -0
  182. package/dist/skillPreparationTransaction.test.d.ts +2 -0
  183. package/dist/skillPreparationTransaction.test.d.ts.map +1 -0
  184. package/dist/skillPreparationTransaction.test.js +181 -0
  185. package/dist/skillPreparationTransaction.test.js.map +1 -0
  186. package/dist/skillSyncPolicy.test.d.ts +2 -0
  187. package/dist/skillSyncPolicy.test.d.ts.map +1 -0
  188. package/dist/skillSyncPolicy.test.js +156 -0
  189. package/dist/skillSyncPolicy.test.js.map +1 -0
  190. package/dist/usage.d.ts +1 -1
  191. package/dist/usage.d.ts.map +1 -1
  192. package/dist/usage.js +1 -1
  193. package/dist/usage.js.map +1 -1
  194. package/dist/windowsProcessPortability.test.d.ts +2 -0
  195. package/dist/windowsProcessPortability.test.d.ts.map +1 -0
  196. package/dist/windowsProcessPortability.test.js +14 -0
  197. package/dist/windowsProcessPortability.test.js.map +1 -0
  198. package/package.json +7 -4
@@ -1555,13 +1555,13 @@ test('relay probe opens an authenticated session without polling or leasing work
1555
1555
  },
1556
1556
  openSession: async (version) => {
1557
1557
  sessions += 1;
1558
- assert.equal(version, '0.2.49');
1558
+ assert.equal(version, '0.2.51');
1559
1559
  return { ok: true };
1560
1560
  },
1561
1561
  }));
1562
1562
  assert.equal(sessions, 1);
1563
1563
  assert.deepEqual(result, {
1564
- ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.49',
1564
+ ok: true, connected: true, organizationId: 'org_test', deviceId: 'device_test', relayVersion: '0.2.51',
1565
1565
  });
1566
1566
  });
1567
1567
  test('relay probe fails closed when the server does not acknowledge the session', async () => {
@@ -0,0 +1,55 @@
1
+ import { type RepositoryPackageSnapshot } from './repositoryPackage.js';
2
+ export type RepositoryCandidateState = 'accepted' | 'processing' | 'published' | 'blocked';
3
+ export interface RepositoryCandidateScope {
4
+ organizationId: string;
5
+ workspaceId: string;
6
+ repositoryBindingId: string;
7
+ repositoryAgentId: string;
8
+ }
9
+ export interface RepositoryCandidateTransport {
10
+ signedGet(route: string): Promise<Record<string, unknown>>;
11
+ signedPost(route: string, body: unknown): Promise<Record<string, unknown>>;
12
+ }
13
+ export type RepositoryCandidateReceipt = {
14
+ candidateId: string;
15
+ operationId: string;
16
+ snapshotHash: string;
17
+ state: RepositoryCandidateState;
18
+ releaseId: string | null;
19
+ };
20
+ type CandidateOutbox = {
21
+ schema: 'dharma.repository-candidate-outbox/v1';
22
+ scope: RepositoryCandidateScope;
23
+ operationId: string;
24
+ sourceManifestHash: string;
25
+ snapshotHash: string;
26
+ consolidation: {
27
+ mode: 'initial_repository' | 'repository_update';
28
+ includeApprovedOutputs: true;
29
+ requireAtlasAssociation: true;
30
+ };
31
+ candidateId: string | null;
32
+ state: 'pending_upload' | RepositoryCandidateState;
33
+ releaseId: string | null;
34
+ };
35
+ export declare function synchronizeRepositoryCandidate(input: {
36
+ transport: RepositoryCandidateTransport;
37
+ outboxRoot: string;
38
+ scope: RepositoryCandidateScope;
39
+ snapshot: RepositoryPackageSnapshot;
40
+ initialRepository: boolean;
41
+ }): Promise<RepositoryCandidateReceipt>;
42
+ export declare function pollRepositoryCandidate(input: {
43
+ transport: Pick<RepositoryCandidateTransport, 'signedGet'>;
44
+ outboxRoot: string;
45
+ scope: RepositoryCandidateScope;
46
+ }): Promise<RepositoryCandidateReceipt | null>;
47
+ export declare function adoptRepositoryCandidate(input: {
48
+ outboxRoot: string;
49
+ scope: RepositoryCandidateScope;
50
+ sourceManifestHash: string;
51
+ consolidationMode: CandidateOutbox['consolidation']['mode'];
52
+ candidate: RepositoryCandidateReceipt;
53
+ }): Promise<RepositoryCandidateReceipt>;
54
+ export {};
55
+ //# sourceMappingURL=repositoryCandidateSync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryCandidateSync.d.ts","sourceRoot":"","sources":["../src/repositoryCandidateSync.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,wBAAwB,CAAC;AAEhC,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;AAE3F,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC5E;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,wBAAwB,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,uCAAuC,CAAC;IAChD,KAAK,EAAE,wBAAwB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE;QACb,IAAI,EAAE,oBAAoB,GAAG,mBAAmB,CAAC;QACjD,sBAAsB,EAAE,IAAI,CAAC;QAC7B,uBAAuB,EAAE,IAAI,CAAC;KAC/B,CAAC;IACF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,gBAAgB,GAAG,wBAAwB,CAAC;IACnD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAiGF,wBAAsB,8BAA8B,CAAC,KAAK,EAAE;IAC1D,SAAS,EAAE,4BAA4B,CAAC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,wBAAwB,CAAC;IAChC,QAAQ,EAAE,yBAAyB,CAAC;IACpC,iBAAiB,EAAE,OAAO,CAAC;CAC5B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA8CtC;AAED,wBAAsB,uBAAuB,CAAC,KAAK,EAAE;IACnD,SAAS,EAAE,IAAI,CAAC,4BAA4B,EAAE,WAAW,CAAC,CAAC;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,wBAAwB,CAAC;CACjC,GAAG,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC,CAgB7C;AAED,wBAAsB,wBAAwB,CAAC,KAAK,EAAE;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,wBAAwB,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5D,SAAS,EAAE,0BAA0B,CAAC;CACvC,GAAG,OAAO,CAAC,0BAA0B,CAAC,CActC"}
@@ -0,0 +1,177 @@
1
+ import { constants } from 'node:fs';
2
+ import { mkdir, open, readFile, rename, rm } from 'node:fs/promises';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { canonicalize, sha256 } from '@dharma-ai-labs/agent-fabric-contracts';
5
+ import { serializeRepositoryPackageSnapshot, } from './repositoryPackage.js';
6
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$(?![\s\S])/i;
7
+ const HASH = /^sha256:[0-9a-f]{64}$(?![\s\S])/;
8
+ const ORG = /^org_[A-Za-z0-9_]{1,156}$(?![\s\S])/;
9
+ const STATES = new Set(['accepted', 'processing', 'published', 'blocked']);
10
+ const OUTBOX_STATES = new Set(['pending_upload', ...STATES]);
11
+ function requireFact(value, message) {
12
+ if (!value)
13
+ throw new Error(message);
14
+ }
15
+ function checkedScope(value) {
16
+ requireFact(ORG.test(value.organizationId), 'Repository candidate organization is invalid.');
17
+ for (const id of [value.workspaceId, value.repositoryBindingId, value.repositoryAgentId]) {
18
+ requireFact(typeof id === 'string' && UUID.test(id), 'Repository candidate scope is incomplete.');
19
+ }
20
+ return { ...value };
21
+ }
22
+ function receipt(value, scope, operationId, snapshotHash) {
23
+ requireFact(value !== null && typeof value === 'object' && !Array.isArray(value), 'Repository candidate response is invalid.');
24
+ const response = value;
25
+ requireFact(response.ok === true && response.organizationId === scope.organizationId
26
+ && response.candidate !== null && typeof response.candidate === 'object' && !Array.isArray(response.candidate), 'Repository candidate response scope is invalid.');
27
+ const candidate = response.candidate;
28
+ requireFact(Reflect.ownKeys(candidate).every(key => typeof key === 'string')
29
+ && ['candidateId', 'operationId', 'snapshotHash', 'state', 'releaseId'].every(key => Object.hasOwn(candidate, key))
30
+ && Object.keys(candidate).every(key => ['candidateId', 'operationId', 'snapshotHash', 'state', 'releaseId'].includes(key)), 'Repository candidate receipt is invalid.');
31
+ requireFact(typeof candidate.candidateId === 'string' && UUID.test(candidate.candidateId)
32
+ && candidate.operationId === operationId && candidate.snapshotHash === snapshotHash
33
+ && typeof candidate.state === 'string' && STATES.has(candidate.state)
34
+ && (candidate.releaseId === null || typeof candidate.releaseId === 'string' && UUID.test(candidate.releaseId))
35
+ && (candidate.state === 'published') === (candidate.releaseId !== null), 'Repository candidate receipt is inconsistent.');
36
+ return candidate;
37
+ }
38
+ function outboxPath(root, scope) {
39
+ return resolve(root, `${scope.workspaceId}.json`);
40
+ }
41
+ async function writeOutbox(path, value) {
42
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
43
+ const temporary = `${path}.${process.pid}.${Date.now()}.tmp`;
44
+ const bytes = `${canonicalize(value)}\n`;
45
+ const handle = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW || 0), 0o600);
46
+ try {
47
+ await handle.writeFile(bytes);
48
+ await handle.sync();
49
+ }
50
+ finally {
51
+ await handle.close();
52
+ }
53
+ try {
54
+ await rename(temporary, path);
55
+ }
56
+ finally {
57
+ await rm(temporary, { force: true });
58
+ }
59
+ }
60
+ function outbox(value, expectedScope) {
61
+ requireFact(value !== null && typeof value === 'object' && !Array.isArray(value), 'Repository candidate outbox is invalid.');
62
+ const row = value;
63
+ const keys = ['schema', 'scope', 'operationId', 'sourceManifestHash', 'snapshotHash', 'consolidation',
64
+ 'candidateId', 'state', 'releaseId'];
65
+ requireFact(row.schema === 'dharma.repository-candidate-outbox/v1'
66
+ && Reflect.ownKeys(row).every(key => typeof key === 'string')
67
+ && keys.every(key => Object.hasOwn(row, key)) && Object.keys(row).every(key => keys.includes(key)), 'Repository candidate outbox is invalid.');
68
+ const scope = checkedScope(row.scope);
69
+ if (expectedScope)
70
+ requireFact(canonicalize(scope) === canonicalize(expectedScope), 'Repository candidate outbox scope is invalid.');
71
+ requireFact(typeof row.operationId === 'string' && HASH.test(row.operationId)
72
+ && typeof row.sourceManifestHash === 'string' && HASH.test(row.sourceManifestHash)
73
+ && typeof row.snapshotHash === 'string' && HASH.test(row.snapshotHash)
74
+ && typeof row.state === 'string' && OUTBOX_STATES.has(row.state)
75
+ && (row.candidateId === null || typeof row.candidateId === 'string' && UUID.test(row.candidateId))
76
+ && (row.releaseId === null || typeof row.releaseId === 'string' && UUID.test(row.releaseId))
77
+ && (row.state === 'pending_upload') === (row.candidateId === null)
78
+ && (row.state === 'published') === (row.releaseId !== null), 'Repository candidate outbox is inconsistent.');
79
+ requireFact(row.consolidation !== null && typeof row.consolidation === 'object' && !Array.isArray(row.consolidation), 'Repository candidate consolidation is invalid.');
80
+ const consolidation = row.consolidation;
81
+ requireFact(Object.keys(consolidation).sort().join(',') === 'includeApprovedOutputs,mode,requireAtlasAssociation'
82
+ && ['initial_repository', 'repository_update'].includes(String(consolidation.mode))
83
+ && consolidation.includeApprovedOutputs === true && consolidation.requireAtlasAssociation === true, 'Repository candidate consolidation is invalid.');
84
+ return { schema: 'dharma.repository-candidate-outbox/v1', scope,
85
+ operationId: row.operationId, sourceManifestHash: row.sourceManifestHash,
86
+ snapshotHash: row.snapshotHash, consolidation: consolidation,
87
+ candidateId: row.candidateId, state: row.state,
88
+ releaseId: row.releaseId };
89
+ }
90
+ async function readOutbox(path, expectedScope) {
91
+ try {
92
+ const bytes = await readFile(path);
93
+ requireFact(bytes.length <= 65_536, 'Repository candidate outbox exceeds its byte limit.');
94
+ return outbox(JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes)), expectedScope);
95
+ }
96
+ catch (error) {
97
+ if (error.code === 'ENOENT')
98
+ return null;
99
+ throw error;
100
+ }
101
+ }
102
+ export async function synchronizeRepositoryCandidate(input) {
103
+ const scope = checkedScope(input.scope);
104
+ const serialized = serializeRepositoryPackageSnapshot(input.snapshot);
105
+ requireFact(Buffer.byteLength(serialized) <= 8_388_608, 'Repository candidate exceeds its upload byte limit.');
106
+ const snapshot = JSON.parse(serialized);
107
+ requireFact(snapshot.manifest.organizationId === scope.organizationId
108
+ && snapshot.manifest.workspaceId === scope.workspaceId
109
+ && snapshot.manifest.knowledge?.repositoryAgentId === scope.repositoryAgentId
110
+ && HASH.test(snapshot.manifest.snapshotHash), 'Repository candidate snapshot scope is invalid.');
111
+ const sourceManifestHash = sha256(canonicalize(snapshot.manifest));
112
+ const consolidation = {
113
+ mode: input.initialRepository ? 'initial_repository' : 'repository_update',
114
+ includeApprovedOutputs: true, requireAtlasAssociation: true,
115
+ };
116
+ const operationId = sha256(canonicalize({ schema: 'dharma.repository-candidate-operation/v1', ...scope,
117
+ snapshotHash: snapshot.manifest.snapshotHash, sourceManifestHash, consolidation }));
118
+ const path = outboxPath(input.outboxRoot, scope);
119
+ const prior = await readOutbox(path, scope);
120
+ if (prior && (prior.operationId !== operationId || canonicalize(prior.scope) !== canonicalize(scope))) {
121
+ requireFact(['published', 'blocked'].includes(prior.state), 'A different repository candidate is still pending.');
122
+ }
123
+ const pending = prior?.operationId === operationId ? prior : {
124
+ schema: 'dharma.repository-candidate-outbox/v1', scope, operationId,
125
+ sourceManifestHash, snapshotHash: snapshot.manifest.snapshotHash, consolidation,
126
+ candidateId: null, state: 'pending_upload', releaseId: null,
127
+ };
128
+ requireFact(pending.sourceManifestHash === sourceManifestHash && pending.snapshotHash === snapshot.manifest.snapshotHash
129
+ && canonicalize(pending.consolidation) === canonicalize(consolidation), 'Repository candidate outbox does not match the current upload.');
130
+ await writeOutbox(path, pending);
131
+ const route = `/agent-fabric/repository-agents/${encodeURIComponent(scope.repositoryAgentId)}/package-candidates`;
132
+ let accepted;
133
+ if (pending.candidateId) {
134
+ const query = new URLSearchParams({ workspaceId: scope.workspaceId, operationId });
135
+ accepted = receipt(await input.transport.signedGet(`${route}/${encodeURIComponent(pending.candidateId)}?${query}`), scope, operationId, snapshot.manifest.snapshotHash);
136
+ }
137
+ else {
138
+ accepted = receipt(await input.transport.signedPost(route, {
139
+ schema: 'dharma.repository-candidate-upload/v1', operationId, workspaceId: scope.workspaceId,
140
+ repositoryBindingId: scope.repositoryBindingId, repositoryAgentId: scope.repositoryAgentId,
141
+ sourceSnapshotHash: snapshot.manifest.snapshotHash, sourceManifestHash: pending.sourceManifestHash,
142
+ consolidation: pending.consolidation, snapshot,
143
+ }), scope, operationId, snapshot.manifest.snapshotHash);
144
+ }
145
+ await writeOutbox(path, { ...pending, candidateId: accepted.candidateId, state: accepted.state, releaseId: accepted.releaseId });
146
+ return accepted;
147
+ }
148
+ export async function pollRepositoryCandidate(input) {
149
+ const scope = checkedScope(input.scope);
150
+ const path = outboxPath(input.outboxRoot, scope);
151
+ const pending = await readOutbox(path, scope);
152
+ if (!pending || pending.state === 'pending_upload')
153
+ return null;
154
+ if (pending.state === 'published' || pending.state === 'blocked') {
155
+ return { candidateId: pending.candidateId, operationId: pending.operationId, snapshotHash: pending.snapshotHash,
156
+ state: pending.state, releaseId: pending.releaseId };
157
+ }
158
+ const route = `/agent-fabric/repository-agents/${encodeURIComponent(scope.repositoryAgentId)}/package-candidates`;
159
+ const query = new URLSearchParams({ workspaceId: scope.workspaceId, operationId: pending.operationId });
160
+ const current = receipt(await input.transport.signedGet(`${route}/${encodeURIComponent(pending.candidateId)}?${query}`), scope, pending.operationId, pending.snapshotHash);
161
+ await writeOutbox(path, { ...pending, candidateId: current.candidateId, state: current.state, releaseId: current.releaseId });
162
+ return current;
163
+ }
164
+ export async function adoptRepositoryCandidate(input) {
165
+ const scope = checkedScope(input.scope);
166
+ requireFact(HASH.test(input.sourceManifestHash), 'Canonical repository candidate manifest hash is invalid.');
167
+ const candidate = receipt({ ok: true, organizationId: scope.organizationId, candidate: input.candidate }, scope, input.candidate.operationId, input.candidate.snapshotHash);
168
+ requireFact(candidate.state !== 'accepted' || candidate.candidateId !== null, 'Canonical repository candidate is incomplete.');
169
+ await writeOutbox(outboxPath(input.outboxRoot, scope), {
170
+ schema: 'dharma.repository-candidate-outbox/v1', scope, operationId: candidate.operationId,
171
+ sourceManifestHash: input.sourceManifestHash, snapshotHash: candidate.snapshotHash,
172
+ consolidation: { mode: input.consolidationMode, includeApprovedOutputs: true, requireAtlasAssociation: true },
173
+ candidateId: candidate.candidateId, state: candidate.state, releaseId: candidate.releaseId,
174
+ });
175
+ return candidate;
176
+ }
177
+ //# sourceMappingURL=repositoryCandidateSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryCandidateSync.js","sourceRoot":"","sources":["../src/repositoryCandidateSync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=repositoryCandidateSync.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryCandidateSync.test.d.ts","sourceRoot":"","sources":["../src/repositoryCandidateSync.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,141 @@
1
+ import assert from 'node:assert/strict';
2
+ import { createHash } from 'node:crypto';
3
+ import { mkdir, mkdtemp, readFile, rm, 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 { canonicalize } from '@dharma-ai-labs/agent-fabric-contracts';
8
+ import { pollRepositoryCandidate, synchronizeRepositoryCandidate } from './repositoryCandidateSync.js';
9
+ import { inventoryRepositoryPackage } from './repositoryPackage.js';
10
+ import { initializeRepositoryKnowledge } from './repositoryKnowledge.js';
11
+ const ids = {
12
+ workspaceId: '056b63dc-ebed-48ed-85d8-02c72f623ea8',
13
+ repositoryBindingId: '73a95988-fd64-41ba-a0b9-6c8867d03788',
14
+ repositoryAgentId: '57f61652-a5eb-46e4-930c-9478cd4a9c31',
15
+ };
16
+ async function snapshot(root) {
17
+ const workspace = join(root, 'repository');
18
+ await mkdir(join(workspace, '.agents/skills/dharma-agent-fabric'), { recursive: true });
19
+ await writeFile(join(workspace, '.agents/skills/dharma-agent-fabric/.dharma-agent-fabric.json'), JSON.stringify({ managedBy: 'dharma-agent-fabric', workspaceId: ids.workspaceId }));
20
+ await writeFile(join(workspace, 'README.md'), '# Governed repository\n');
21
+ const operation = { action: 'authorize', confirmed: true,
22
+ requestId: '5ff2ee1b-6cb3-459e-a977-ea99c757bf30', repositoryBindingId: ids.repositoryBindingId,
23
+ expectedRevision: 0, allowedContentClasses: ['approved_outputs', 'repository_content', 'repository_skills'],
24
+ approvedRepositoryPaths: ['README.md'], approvedOutputFolders: [], automaticValidatedPublication: true,
25
+ retentionDays: 30, maximumFileBytes: 262144, maximumSnapshotBytes: 4194304,
26
+ maximumDailyUploadBytes: 1073741824, expiresAt: '2031-01-01T00:00:00.000Z' };
27
+ const generationId = '67f61652-a5eb-46e4-930c-9478cd4a9c31';
28
+ const sourceAuthorization = { schema: 'dharma.repository-source-authorization/v1', organizationId: 'org_fixture',
29
+ workspaceId: ids.workspaceId, repositoryBindingId: ids.repositoryBindingId, repositoryAgentId: ids.repositoryAgentId,
30
+ revision: 1, generationId, receiptId: `repo_consent_${generationId}`,
31
+ policyRevision: `repository-source-${generationId}`,
32
+ policyHash: `sha256:${createHash('sha256').update(canonicalize(operation)).digest('hex')}`,
33
+ confirmedAt: '2030-01-01T00:00:00.000Z', policy: operation };
34
+ const input = { workspace, organizationId: 'org_fixture', ...ids, sourceAuthorization,
35
+ now: new Date('2030-01-02T00:00:00.000Z') };
36
+ await initializeRepositoryKnowledge(input);
37
+ return inventoryRepositoryPackage(input);
38
+ }
39
+ test('repository candidate upload persists an exact outbox and polls the same operation after a lost caller response', async () => {
40
+ const root = await mkdtemp(join(tmpdir(), 'dharma-candidate-'));
41
+ const calls = [];
42
+ const candidateId = '77f61652-a5eb-46e4-930c-9478cd4a9c31';
43
+ try {
44
+ const transport = {
45
+ signedPost: async (route, body) => {
46
+ calls.push({ method: 'POST', route, body });
47
+ const request = body;
48
+ return { ok: true, organizationId: 'org_fixture', candidate: { candidateId,
49
+ operationId: request.operationId, snapshotHash: request.sourceSnapshotHash, state: 'processing', releaseId: null } };
50
+ },
51
+ signedGet: async (route) => {
52
+ calls.push({ method: 'GET', route });
53
+ const stored = JSON.parse(await readFile(join(root, 'outbox', `${ids.workspaceId}.json`), 'utf8'));
54
+ return { ok: true, organizationId: 'org_fixture', candidate: { candidateId,
55
+ operationId: stored.operationId, snapshotHash: stored.snapshotHash,
56
+ state: 'published', releaseId: '87f61652-a5eb-46e4-930c-9478cd4a9c31' } };
57
+ },
58
+ };
59
+ const input = { transport, outboxRoot: join(root, 'outbox'), scope: { organizationId: 'org_fixture', ...ids },
60
+ snapshot: await snapshot(root), initialRepository: true };
61
+ const first = await synchronizeRepositoryCandidate(input);
62
+ assert.equal(first.state, 'processing');
63
+ const second = await synchronizeRepositoryCandidate(input);
64
+ assert.equal(second.state, 'published');
65
+ assert.deepEqual(calls.map(call => call.method), ['POST', 'GET']);
66
+ const request = calls[0]?.body;
67
+ assert.deepEqual(request.consolidation, { mode: 'initial_repository', includeApprovedOutputs: true,
68
+ requireAtlasAssociation: true });
69
+ const stored = await readFile(join(root, 'outbox', `${ids.workspaceId}.json`), 'utf8');
70
+ assert.doesNotMatch(stored, /contentBase64|Governed repository/);
71
+ }
72
+ finally {
73
+ await rm(root, { recursive: true, force: true });
74
+ }
75
+ });
76
+ test('repository candidate status polling is independent of repository source observation', async () => {
77
+ const root = await mkdtemp(join(tmpdir(), 'dharma-candidate-'));
78
+ const candidateId = '77f61652-a5eb-46e4-930c-9478cd4a9c31';
79
+ try {
80
+ const candidateSnapshot = await snapshot(root);
81
+ const scope = { organizationId: 'org_fixture', ...ids };
82
+ const first = await synchronizeRepositoryCandidate({ outboxRoot: join(root, 'outbox'), scope,
83
+ snapshot: candidateSnapshot, initialRepository: false, transport: { signedGet: async () => ({}),
84
+ signedPost: async (_route, body) => ({ ok: true, organizationId: scope.organizationId, candidate: {
85
+ candidateId, operationId: body.operationId,
86
+ snapshotHash: body.sourceSnapshotHash, state: 'accepted', releaseId: null
87
+ } }) } });
88
+ const current = await pollRepositoryCandidate({ outboxRoot: join(root, 'outbox'), scope,
89
+ transport: { signedGet: async (route) => {
90
+ assert.match(route, new RegExp(candidateId));
91
+ return { ok: true, organizationId: scope.organizationId, candidate: { ...first, state: 'published',
92
+ releaseId: '87f61652-a5eb-46e4-930c-9478cd4a9c31' } };
93
+ } } });
94
+ assert.equal(current?.state, 'published');
95
+ }
96
+ finally {
97
+ await rm(root, { recursive: true, force: true });
98
+ }
99
+ });
100
+ test('repository candidate rejects tampered durable metadata before transport', async () => {
101
+ const root = await mkdtemp(join(tmpdir(), 'dharma-candidate-'));
102
+ let calls = 0;
103
+ try {
104
+ const candidateSnapshot = await snapshot(root);
105
+ const input = { outboxRoot: join(root, 'outbox'), scope: { organizationId: 'org_fixture', ...ids },
106
+ snapshot: candidateSnapshot, initialRepository: true, transport: { signedGet: async () => { calls += 1; return {}; },
107
+ signedPost: async (_route, body) => ({ ok: true, organizationId: 'org_fixture', candidate: {
108
+ candidateId: '77f61652-a5eb-46e4-930c-9478cd4a9c31', operationId: body.operationId,
109
+ snapshotHash: body.sourceSnapshotHash, state: 'processing', releaseId: null
110
+ } }) } };
111
+ await synchronizeRepositoryCandidate(input);
112
+ const path = join(root, 'outbox', `${ids.workspaceId}.json`);
113
+ const stored = JSON.parse(await readFile(path, 'utf8'));
114
+ stored.consolidation.includeApprovedOutputs = false;
115
+ await writeFile(path, JSON.stringify(stored));
116
+ await assert.rejects(() => pollRepositoryCandidate({ outboxRoot: join(root, 'outbox'), scope: input.scope,
117
+ transport: input.transport }), /outbox|consolidation|current upload/i);
118
+ assert.equal(calls, 0);
119
+ }
120
+ finally {
121
+ await rm(root, { recursive: true, force: true });
122
+ }
123
+ });
124
+ test('repository candidate upload rejects foreign or inconsistent receipts without advancing the outbox', async () => {
125
+ const root = await mkdtemp(join(tmpdir(), 'dharma-candidate-'));
126
+ try {
127
+ const candidateSnapshot = await snapshot(root);
128
+ await assert.rejects(() => synchronizeRepositoryCandidate({
129
+ outboxRoot: join(root, 'outbox'), scope: { organizationId: 'org_fixture', ...ids },
130
+ snapshot: candidateSnapshot, initialRepository: false,
131
+ transport: { signedGet: async () => ({}), signedPost: async (_route, body) => ({ ok: true,
132
+ organizationId: 'org_foreign', candidate: { candidateId: ids.workspaceId,
133
+ operationId: body.operationId,
134
+ snapshotHash: body.sourceSnapshotHash, state: 'published', releaseId: null } }) },
135
+ }), /scope|receipt|response/i);
136
+ }
137
+ finally {
138
+ await rm(root, { recursive: true, force: true });
139
+ }
140
+ });
141
+ //# sourceMappingURL=repositoryCandidateSync.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryCandidateSync.test.js","sourceRoot":"","sources":["../src/repositoryCandidateSync.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ProviderId } from '@dharma-ai-labs/agent-fabric-contracts';
2
+ type Bytes = {
3
+ catalogBytes: Buffer;
4
+ manifestBytes: Buffer;
5
+ };
6
+ export declare function selectInstalledRepositoryKnowledge(input: {
7
+ organizationId: string;
8
+ repositoryBindingId: string;
9
+ repositoryAgentId: string;
10
+ loadProvider: (provider: ProviderId) => Promise<Bytes | null>;
11
+ }): Promise<Bytes | null>;
12
+ export {};
13
+ //# sourceMappingURL=repositoryInstalledKnowledge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryInstalledKnowledge.d.ts","sourceRoot":"","sources":["../src/repositoryInstalledKnowledge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAGzE,KAAK,KAAK,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAI7D,wBAAsB,kCAAkC,CAAC,KAAK,EAAE;IAC9D,cAAc,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAC/E,YAAY,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;CAC/D,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAmBxB"}
@@ -0,0 +1,25 @@
1
+ import { validateRepositoryKnowledgeRetention } from './repositoryKnowledge.js';
2
+ // Installed-tree verification belongs to the loader; carrier authority still
3
+ // belongs to the server. Divergent claims at one generation must not be merged.
4
+ export async function selectInstalledRepositoryKnowledge(input) {
5
+ const generations = new Map();
6
+ let latest = 0;
7
+ for (const provider of ['codex', 'claude', 'agy', 'hermes']) {
8
+ const observed = await input.loadProvider(provider);
9
+ if (!observed)
10
+ continue;
11
+ if (![observed.catalogBytes, observed.manifestBytes].every(bytes => Buffer.isBuffer(bytes) && bytes.length > 0 && bytes.length <= 262144)) {
12
+ throw new Error('Installed repository knowledge byte limit exceeded.');
13
+ }
14
+ const bytes = { catalogBytes: Buffer.from(observed.catalogBytes), manifestBytes: Buffer.from(observed.manifestBytes) };
15
+ const retained = validateRepositoryKnowledgeRetention({ identity: input, ...bytes });
16
+ const previous = generations.get(retained.reference.generation);
17
+ if (previous && (!previous.catalogBytes.equals(bytes.catalogBytes) || !previous.manifestBytes.equals(bytes.manifestBytes))) {
18
+ throw new Error('Installed repository knowledge generation conflict.');
19
+ }
20
+ generations.set(retained.reference.generation, bytes);
21
+ latest = Math.max(latest, retained.reference.generation);
22
+ }
23
+ return generations.get(latest) || null;
24
+ }
25
+ //# sourceMappingURL=repositoryInstalledKnowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryInstalledKnowledge.js","sourceRoot":"","sources":["../src/repositoryInstalledKnowledge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oCAAoC,EAAE,MAAM,0BAA0B,CAAC;AAIhF,6EAA6E;AAC7E,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,kCAAkC,CAAC,KAGxD;IACC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC7C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,QAAQ,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAU,EAAE,CAAC;QACrE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC;YAC1I,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,GAAG,EAAE,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACvH,MAAM,QAAQ,GAAG,oCAAoC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QACrF,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAChE,IAAI,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YAC3H,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QACD,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACtD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;AACzC,CAAC"}
@@ -0,0 +1,6 @@
1
+ declare const FILES: readonly [".agents/skills/dharma-agent-fabric/.dharma-agent-fabric.json", ".agents/skills/dharma-agent-fabric/SKILL.md", ".agents/skills/dharma-agent-fabric/references/organization.md", ".dharma/agent-fabric.json", ".dharma/repository-agent.json"];
2
+ type InstallerFile = typeof FILES[number];
3
+ export declare function assertRepositoryInstallerOwnership(workspace: string, workspaceId: string): Promise<void>;
4
+ export declare function writeRepositoryInstallerFile(workspace: string, path: InstallerFile, content: string): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=repositoryInstallerFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryInstallerFiles.d.ts","sourceRoot":"","sources":["../src/repositoryInstallerFiles.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,KAAK,yPAC6D,CAAC;AACzE,KAAK,aAAa,GAAG,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;AA4B1C,wBAAsB,kCAAkC,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBA6B9F;AAGD,wBAAsB,4BAA4B,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,iBAqBzG"}
@@ -0,0 +1,113 @@
1
+ import { constants } from 'node:fs';
2
+ import { lstat, open, rename, unlink } from 'node:fs/promises';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { dirname, isAbsolute, relative, resolve } from 'node:path';
5
+ const ROOT = '.agents/skills/dharma-agent-fabric';
6
+ const MARKER = `${ROOT}/.dharma-agent-fabric.json`;
7
+ const FILES = [MARKER, `${ROOT}/SKILL.md`, `${ROOT}/references/organization.md`,
8
+ '.dharma/agent-fabric.json', '.dharma/repository-agent.json'];
9
+ async function checkedPath(workspace, path, leaf) {
10
+ const boundary = resolve(workspace), within = relative(boundary, path);
11
+ if (isAbsolute(within) || within === '..' || within.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
12
+ throw new Error('Repository installer path escapes the workspace.');
13
+ }
14
+ const components = [path];
15
+ // System ancestors may be aliases (for example macOS /var); owned paths may not.
16
+ while (components[0] !== boundary)
17
+ components.unshift(dirname(components[0]));
18
+ let exists = false;
19
+ for (const [index, component] of components.entries()) {
20
+ let metadata;
21
+ try {
22
+ metadata = await lstat(component);
23
+ }
24
+ catch (error) {
25
+ if (error.code === 'ENOENT')
26
+ return false;
27
+ throw error;
28
+ }
29
+ if (metadata.isSymbolicLink())
30
+ throw new Error('Repository installer symlink is forbidden.');
31
+ const isLeaf = index === components.length - 1;
32
+ if ((!isLeaf || leaf === 'directory') && !metadata.isDirectory()) {
33
+ throw new Error('Invalid repository installer directory.');
34
+ }
35
+ if (isLeaf && leaf === 'file' && (!metadata.isFile() || metadata.nlink !== 1)) {
36
+ throw new Error('Repository installer hardlink or non-regular destination is forbidden.');
37
+ }
38
+ exists = isLeaf;
39
+ }
40
+ return exists;
41
+ }
42
+ export async function assertRepositoryInstallerOwnership(workspace, workspaceId) {
43
+ if (!await checkedPath(workspace, resolve(workspace), 'directory'))
44
+ throw new Error('Repository installer workspace is missing.');
45
+ const rootExists = await checkedPath(workspace, resolve(workspace, ROOT), 'directory');
46
+ for (const path of FILES)
47
+ await checkedPath(workspace, resolve(workspace, path), 'file');
48
+ if (!rootExists)
49
+ return;
50
+ const markerPath = resolve(workspace, MARKER);
51
+ if (!await checkedPath(workspace, markerPath, 'file')) {
52
+ throw new Error('Refusing to replace an unmanaged repository skill at .agents/skills/dharma-agent-fabric.');
53
+ }
54
+ const handle = await open(markerPath, constants.O_RDONLY | (constants.O_NOFOLLOW || 0) | (constants.O_NONBLOCK || 0));
55
+ try {
56
+ const before = await handle.stat();
57
+ if (!before.isFile() || before.nlink !== 1 || before.size > 4096)
58
+ throw new Error('Invalid repository skill ownership marker.');
59
+ const buffer = Buffer.alloc(4097);
60
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
61
+ const after = await handle.stat(), current = await lstat(markerPath);
62
+ if (bytesRead !== before.size || before.size !== after.size || before.mtimeMs !== after.mtimeMs
63
+ || current.isSymbolicLink() || current.ino !== before.ino || current.dev !== before.dev
64
+ || current.nlink !== 1 || current.mtimeMs !== after.mtimeMs)
65
+ throw new Error('Repository ownership marker changed.');
66
+ let marker;
67
+ try {
68
+ marker = JSON.parse(buffer.subarray(0, bytesRead).toString('utf8'));
69
+ }
70
+ catch {
71
+ throw new Error('Invalid repository skill ownership marker.');
72
+ }
73
+ if (!marker || typeof marker !== 'object' || Array.isArray(marker)
74
+ || Object.keys(marker).sort().join(',') !== 'managedBy,workspaceId'
75
+ || marker.managedBy !== 'dharma-agent-fabric'
76
+ || marker.workspaceId !== workspaceId) {
77
+ throw new Error('Invalid or foreign repository skill ownership marker.');
78
+ }
79
+ }
80
+ finally {
81
+ await handle.close();
82
+ }
83
+ }
84
+ // Replace owned generated leaves atomically; never truncate an existing inode.
85
+ export async function writeRepositoryInstallerFile(workspace, path, content) {
86
+ if (!FILES.includes(path))
87
+ throw new Error('Unsupported repository installer file.');
88
+ const target = resolve(workspace, path);
89
+ await checkedPath(workspace, dirname(target), 'directory');
90
+ await checkedPath(workspace, target, 'file');
91
+ const temporary = `${target}.staging-${randomUUID()}`;
92
+ const handle = await open(temporary, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY
93
+ | (constants.O_NOFOLLOW || 0), 0o600);
94
+ let published = false;
95
+ try {
96
+ try {
97
+ await handle.writeFile(content);
98
+ await handle.sync();
99
+ }
100
+ finally {
101
+ await handle.close();
102
+ }
103
+ await checkedPath(workspace, dirname(target), 'directory');
104
+ await checkedPath(workspace, target, 'file');
105
+ await rename(temporary, target);
106
+ published = true;
107
+ }
108
+ finally {
109
+ if (!published && await checkedPath(workspace, temporary, 'file'))
110
+ await unlink(temporary);
111
+ }
112
+ }
113
+ //# sourceMappingURL=repositoryInstallerFiles.js.map