@eqtylab/explorer 0.0.0

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 (140) hide show
  1. package/.env.api +6 -0
  2. package/.env.iframe +2 -0
  3. package/.env.manifest +2 -0
  4. package/.envrc +1 -0
  5. package/.eslintrc.cjs +17 -0
  6. package/.github/workflows/ci.yml +46 -0
  7. package/.github/workflows/publish.yml +44 -0
  8. package/.husky/pre-push +2 -0
  9. package/.prettierignore +2 -0
  10. package/.prettierrc.json +13 -0
  11. package/LICENSE +201 -0
  12. package/README.md +84 -0
  13. package/flake.lock +61 -0
  14. package/flake.nix +23 -0
  15. package/index.html +13 -0
  16. package/package.json +93 -0
  17. package/postcss.config.js +5 -0
  18. package/public/logos/eci.svg +23 -0
  19. package/public/logos/eqty.svg +3 -0
  20. package/public/manifests/B-200-merged.json +773 -0
  21. package/public/manifests/amd-sev.json +426 -0
  22. package/public/manifests/anchors.json +609 -0
  23. package/public/manifests/association-no-metadata.json +1393 -0
  24. package/public/manifests/association.json +1402 -0
  25. package/public/manifests/eqty-docker.json +562 -0
  26. package/public/manifests/governance.json +1324 -0
  27. package/public/manifests/intel-tdx-with-nvidia.json +441 -0
  28. package/public/manifests/intel-tdx.json +404 -0
  29. package/public/manifests/iroh-collections.json +1285 -0
  30. package/public/manifests/model-signing.json +1536 -0
  31. package/public/manifests/multiple-registrations.json +129 -0
  32. package/public/manifests/no-vcs.json +114 -0
  33. package/public/manifests/storage.json +294 -0
  34. package/public/manifests/sub-graphs.json +1 -0
  35. package/src/animations/variants.ts +52 -0
  36. package/src/app/apiClient/integrityService/fetchAttributes.ts +29 -0
  37. package/src/app/apiClient/integrityService/fetchManifest.ts +28 -0
  38. package/src/app/apiClient/integrityService/types.ts +12 -0
  39. package/src/app/components/integrityService/IntegrityService.tsx +105 -0
  40. package/src/app/components/integrityService/components/AuthButton.tsx +26 -0
  41. package/src/app/components/integrityService/components/FiltersModal.tsx +214 -0
  42. package/src/app/components/integrityService/components/FiltersToggle.tsx +28 -0
  43. package/src/app/components/manifestViewer/ManifestViewer.tsx +90 -0
  44. package/src/app/components/manifestViewer/components/ManifestButtons.tsx +215 -0
  45. package/src/app/config.json +23 -0
  46. package/src/app/config.ts +28 -0
  47. package/src/app/pages/index.tsx +34 -0
  48. package/src/app/stores/manifestStore.ts +19 -0
  49. package/src/app/utils/appMode.ts +37 -0
  50. package/src/assets/fonts/TWKLausanne-300.woff +0 -0
  51. package/src/assets/fonts/TWKLausanne-300.woff2 +0 -0
  52. package/src/assets/fonts/TWKLausanne-400.woff +0 -0
  53. package/src/assets/fonts/TWKLausanne-400.woff2 +0 -0
  54. package/src/assets/fonts/TWKLausanne-500.woff +0 -0
  55. package/src/assets/fonts/TWKLausanne-500.woff2 +0 -0
  56. package/src/assets/fonts/TWKLausanne-600.woff +0 -0
  57. package/src/assets/fonts/TWKLausanne-600.woff2 +0 -0
  58. package/src/assets/vectors/eqtylab.svg +6 -0
  59. package/src/components/app-header.tsx +61 -0
  60. package/src/components/dark-mode-switch.tsx +16 -0
  61. package/src/components/ui/accordion.tsx +47 -0
  62. package/src/components/ui/certificate-chain.tsx +60 -0
  63. package/src/components/ui/certificate-code.tsx +39 -0
  64. package/src/components/ui/details.tsx +20 -0
  65. package/src/components/ui/display-code.tsx +47 -0
  66. package/src/components/ui/panel-label.tsx +12 -0
  67. package/src/components/ui/verify-state-badge.tsx +32 -0
  68. package/src/explorer-component/LineageExplorer.tsx +89 -0
  69. package/src/explorer-component/components/CustomEdge.tsx +28 -0
  70. package/src/explorer-component/components/LineageFlow.tsx +220 -0
  71. package/src/explorer-component/components/NodeIconLoader.tsx +26 -0
  72. package/src/explorer-component/components/nodes/ComputationNode.tsx +56 -0
  73. package/src/explorer-component/components/nodes/CustomNode.tsx +112 -0
  74. package/src/explorer-component/components/nodes/index.ts +4 -0
  75. package/src/explorer-component/components/nodes/nodes.tsx +144 -0
  76. package/src/explorer-component/components/nodes/types.ts +167 -0
  77. package/src/explorer-component/components/sidebar/SectionList.tsx +54 -0
  78. package/src/explorer-component/components/sidebar/SectionTitle.tsx +10 -0
  79. package/src/explorer-component/components/sidebar/Sidebar.tsx +70 -0
  80. package/src/explorer-component/components/sidebar/SidebarWrapper.tsx +76 -0
  81. package/src/explorer-component/components/sidebar/sections/CustomSection.tsx +238 -0
  82. package/src/explorer-component/components/sidebar/sections/FileViewer.tsx +229 -0
  83. package/src/explorer-component/components/sidebar/sections/GovernanceSection.tsx +52 -0
  84. package/src/explorer-component/components/sidebar/sections/RegistrationSection.tsx +254 -0
  85. package/src/explorer-component/components/sidebar/sections/SigstoreSection.tsx +37 -0
  86. package/src/explorer-component/components/sidebar/sections/StorageSection.tsx +73 -0
  87. package/src/explorer-component/components/sidebar/sections/custom/IrohCollectionsView.tsx +139 -0
  88. package/src/explorer-component/components/sidebar/sections/registration/VerificationIcon.tsx +108 -0
  89. package/src/explorer-component/components/sidebar/sections/registration/actor/ActorBadge.tsx +62 -0
  90. package/src/explorer-component/components/sidebar/sections/registration/actor/svg/AMDLogo.tsx +40 -0
  91. package/src/explorer-component/components/sidebar/sections/registration/actor/svg/AzureLogo.tsx +65 -0
  92. package/src/explorer-component/components/sidebar/sections/registration/actor/svg/IntelLogo.tsx +24 -0
  93. package/src/explorer-component/components/sidebar/sections/registration/actor/svg/NvidiaLogo.tsx +27 -0
  94. package/src/explorer-component/components/sidebar/sections/registration/verifierClient.ts +13 -0
  95. package/src/explorer-component/icons/AttributionIcon.svg +6 -0
  96. package/src/explorer-component/icons/BenchmarkIcon.svg +6 -0
  97. package/src/explorer-component/icons/BenchmarkResultIcon.svg +6 -0
  98. package/src/explorer-component/icons/CertificateIcon.svg +6 -0
  99. package/src/explorer-component/icons/CodeIcon.svg +6 -0
  100. package/src/explorer-component/icons/ComputationIcon.svg +6 -0
  101. package/src/explorer-component/icons/DataIcon.svg +6 -0
  102. package/src/explorer-component/icons/DatabaseIcon.svg +6 -0
  103. package/src/explorer-component/icons/DatasetIcon.svg +6 -0
  104. package/src/explorer-component/icons/DeltaLakeIcon.svg +7 -0
  105. package/src/explorer-component/icons/DocumentIcon.svg +6 -0
  106. package/src/explorer-component/icons/MediaIcon.svg +6 -0
  107. package/src/explorer-component/icons/ModelIcon.svg +6 -0
  108. package/src/explorer-component/icons/TeamIcon.svg +3 -0
  109. package/src/explorer-component/icons/TokenIcon.svg +6 -0
  110. package/src/explorer-component/icons/UnknownIcon.svg +6 -0
  111. package/src/explorer-component/icons/index.ts +35 -0
  112. package/src/explorer-component/index.ts +5 -0
  113. package/src/explorer-component/integrityTypes/AnchorTypes.ts +31 -0
  114. package/src/explorer-component/integrityTypes/StatementTypes.ts +333 -0
  115. package/src/explorer-component/integrityTypes/VCTypes.ts +85 -0
  116. package/src/explorer-component/integrityTypes/types.ts +3 -0
  117. package/src/explorer-component/utils/config.ts +163 -0
  118. package/src/explorer-component/utils/formatTimestamp.ts +5 -0
  119. package/src/explorer-component/utils/generateGraph.ts +271 -0
  120. package/src/explorer-component/utils/layoutGraph.ts +148 -0
  121. package/src/explorer-component/utils/resolveIrohBlobs.ts +117 -0
  122. package/src/explorer-component/utils/statementHelpers.ts +252 -0
  123. package/src/explorer-component/utils/stripPrefix.ts +4 -0
  124. package/src/hooks/use-mobile.tsx +19 -0
  125. package/src/index.ts +3 -0
  126. package/src/lib/resource-types.ts +31 -0
  127. package/src/lib/use-escape-key.tsx +16 -0
  128. package/src/lib/utils.ts +19 -0
  129. package/src/main.css +82 -0
  130. package/src/main.tsx +39 -0
  131. package/src/v-comp-viewer/components/container-did-details.tsx +53 -0
  132. package/src/v-comp-viewer/components/system-did-details.tsx +356 -0
  133. package/src/v-comp-viewer/useVComp.ts +196 -0
  134. package/src/v-comp-viewer/utils.tsx +824 -0
  135. package/src/vite-env.d.ts +1 -0
  136. package/tsconfig.json +33 -0
  137. package/tsconfig.node.json +10 -0
  138. package/vercel.json +13 -0
  139. package/vite.app.config.ts +48 -0
  140. package/vite.lib.config.ts +61 -0
@@ -0,0 +1,356 @@
1
+ import Details from "@/components/ui/details";
2
+ import { SectionList, SectionInnerTitle } from "@/explorer-component/components/sidebar/SectionList";
3
+ import { VCompSystemInfo, UploadVerification } from "@/v-comp-viewer/utils";
4
+ import CertificateCode from "@/components/ui/certificate-code";
5
+ import CertificateChain from "@/components/ui/certificate-chain";
6
+ import DisplayCode from "@/components/ui/display-code";
7
+
8
+ interface SystemDidDetailsProps {
9
+ systemInfo: VCompSystemInfo;
10
+ vCompVerifyData: UploadVerification | null;
11
+ }
12
+
13
+ const SystemDidDetails = ({ systemInfo, vCompVerifyData }: SystemDidDetailsProps) => {
14
+ const showIntelHeading =
15
+ systemInfo.cpu.measurements.mrtd.value ||
16
+ systemInfo.cpu.measurements.rtmr0.value ||
17
+ systemInfo.cpu.measurements.rtmr1.value ||
18
+ systemInfo.cpu.measurements.rtmr2.value ||
19
+ systemInfo.cpu.measurements.rootfs.value;
20
+
21
+ const showAzureUKI =
22
+ vCompVerifyData &&
23
+ (vCompVerifyData.azureUKIPcrLog ||
24
+ vCompVerifyData.azureUKIKernel ||
25
+ vCompVerifyData.azureUKICmdLine ||
26
+ vCompVerifyData.azureUKIRootFSHash ||
27
+ vCompVerifyData.azureUKIInitRDLate ||
28
+ vCompVerifyData.azureUKIPcr.value ||
29
+ vCompVerifyData.azureUKIPcrHash.value);
30
+
31
+ const intelData = [
32
+ {
33
+ value: showIntelHeading && <SectionInnerTitle title="Intel TDX Measurement" />,
34
+ },
35
+ {
36
+ label: "MRTD",
37
+ value: (
38
+ <DisplayCode
39
+ value={`sha384:${systemInfo.cpu.measurements.mrtd.value}`}
40
+ validated={systemInfo.cpu.measurements.mrtd.validated}
41
+ />
42
+ ),
43
+ offsetTopLabel: true,
44
+ },
45
+ {
46
+ label: "RTMR 0",
47
+ value: (
48
+ <DisplayCode
49
+ value={`sha384:${systemInfo.cpu.measurements.rtmr0.value}`}
50
+ validated={systemInfo.cpu.measurements.rtmr0.validated}
51
+ />
52
+ ),
53
+ offsetTopLabel: true,
54
+ },
55
+ {
56
+ label: "RTMR 1",
57
+ value: (
58
+ <DisplayCode
59
+ value={`sha384:${systemInfo.cpu.measurements.rtmr1.value}`}
60
+ validated={systemInfo.cpu.measurements.rtmr1.validated}
61
+ />
62
+ ),
63
+ offsetTopLabel: true,
64
+ },
65
+ {
66
+ label: "RTMR 2",
67
+ value: (
68
+ <DisplayCode
69
+ value={`sha384:${systemInfo.cpu.measurements.rtmr2.value}`}
70
+ validated={systemInfo.cpu.measurements.rtmr2.validated}
71
+ />
72
+ ),
73
+ offsetTopLabel: true,
74
+ },
75
+ {
76
+ label: "User data",
77
+ value: (
78
+ <DisplayCode
79
+ value={`sha256:${systemInfo.cpu.measurements.rootfs.value}`}
80
+ validated={systemInfo.cpu.measurements.rootfs.validated}
81
+ />
82
+ ),
83
+ offsetTopLabel: true,
84
+ },
85
+ ];
86
+
87
+ const cpuAttestationData = [
88
+ {
89
+ value: <SectionInnerTitle title="CPU Attestation" />,
90
+ },
91
+ {
92
+ label: "Attestation Report",
93
+ value: systemInfo.cpu.report.value && (
94
+ <CertificateCode code={systemInfo.cpu.report.value} validated={systemInfo.cpu.report.validated} />
95
+ ),
96
+ },
97
+ {
98
+ label: "X509 Chain",
99
+ value: systemInfo.cpu.certificate.x509 && (
100
+ <CertificateCode
101
+ code={systemInfo.cpu.certificate.x509}
102
+ validated={systemInfo.cpu.certificate.validated}
103
+ />
104
+ ),
105
+ },
106
+ {
107
+ value: systemInfo.cpu.certificate.chain && (
108
+ <Details
109
+ title="Certificate Chain"
110
+ content={<CertificateChain chainItems={systemInfo.cpu.certificate.chain} />}
111
+ />
112
+ ),
113
+ },
114
+ ];
115
+
116
+ const nvidiaData = [
117
+ {
118
+ value: <SectionInnerTitle title="NVIDIA Hardware Attestation" />,
119
+ },
120
+ {
121
+ label: "Measurement",
122
+ value: systemInfo.gpu.reportData && <DisplayCode value={`hash:${systemInfo.gpu.reportData}`} />,
123
+ offsetTopLabel: true,
124
+ },
125
+ {
126
+ label: "Attestation Report",
127
+ value: systemInfo.gpu.report.value && (
128
+ <CertificateCode code={systemInfo.gpu.report.value} validated={systemInfo.gpu.report.validated} />
129
+ ),
130
+ },
131
+ {
132
+ label: "X509 Chain",
133
+ value: systemInfo.gpu.certificate.x509.value && (
134
+ <CertificateCode
135
+ code={systemInfo.gpu.certificate.x509.value as unknown as string}
136
+ validated={systemInfo.gpu.certificate.x509.validated}
137
+ />
138
+ ),
139
+ },
140
+ ];
141
+
142
+ const gpuCertificateData = [
143
+ {
144
+ value: systemInfo.gpu.certificate.chain && (
145
+ <Details
146
+ innerClassName="data-[state=open]:border-none"
147
+ title="Certificate Chain"
148
+ content={<CertificateChain chainItems={systemInfo.gpu.certificate.chain} />}
149
+ />
150
+ ),
151
+ },
152
+ ];
153
+
154
+ const linuxData = [
155
+ {
156
+ value: <SectionInnerTitle title="Linux Unified Kernel Image (UKI)" />,
157
+ },
158
+ {
159
+ label: "PCR Log (Calculated)",
160
+ value: vCompVerifyData?.azureUKIPcrLog && <CertificateCode code={vCompVerifyData?.azureUKIPcrLog} />,
161
+ },
162
+ {
163
+ label: "Linux Kernel",
164
+ value: vCompVerifyData?.azureUKIKernel && (
165
+ <DisplayCode value={`sha384:${vCompVerifyData.azureUKIKernel}`} />
166
+ ),
167
+ offsetTopLabel: true,
168
+ },
169
+ {
170
+ label: "Kernel Argument (Append)",
171
+ value: vCompVerifyData?.azureUKICmdLine && (
172
+ <DisplayCode value={`sha384:${vCompVerifyData.azureUKICmdLine}`} />
173
+ ),
174
+ offsetTopLabel: true,
175
+ },
176
+ {
177
+ label: "Root FS Hash",
178
+ value: vCompVerifyData?.azureUKIRootFSHash && (
179
+ <DisplayCode value={`sha384:${vCompVerifyData.azureUKIRootFSHash}`} />
180
+ ),
181
+ offsetTopLabel: true,
182
+ },
183
+ {
184
+ label: "Initial RAM Disk",
185
+ value: vCompVerifyData?.azureUKIInitRDLate && (
186
+ <DisplayCode value={`sha384:${vCompVerifyData.azureUKIInitRDLate}`} />
187
+ ),
188
+ offsetTopLabel: true,
189
+ },
190
+ {
191
+ label: "Extended PCR 11",
192
+ value: vCompVerifyData?.azureUKIPcr.value && (
193
+ <DisplayCode value={`sha384:${vCompVerifyData.azureUKIPcr.value}`} />
194
+ ),
195
+ offsetTopLabel: true,
196
+ },
197
+ {
198
+ label: "Hash for PCR 11",
199
+ value: vCompVerifyData?.azureUKIPcrHash.value && (
200
+ <DisplayCode
201
+ value={`sha256:${vCompVerifyData.azureUKIPcrHash.value}`}
202
+ validated={vCompVerifyData.azureUKIPcrHash.validated}
203
+ />
204
+ ),
205
+ offsetTopLabel: true,
206
+ },
207
+ ];
208
+
209
+ const azureData = [
210
+ {
211
+ value: <SectionInnerTitle title="Azure vTPM Measurement" />,
212
+ },
213
+ {
214
+ label: "Hash of PCR",
215
+ value: systemInfo.azure.tpmPCRHash.value && (
216
+ <DisplayCode
217
+ value={`sha384:${systemInfo.azure.tpmPCRHash.value}`}
218
+ validated={systemInfo.azure.tpmPCRHash.validated}
219
+ />
220
+ ),
221
+ offsetTopLabel: true,
222
+ },
223
+ {
224
+ label: "Notary Key Hex",
225
+ value: systemInfo.azure.tpmPCRHash.value && (
226
+ <DisplayCode
227
+ value={`sha384:${systemInfo.azure.tpmNotaryHex.value}`}
228
+ validated={systemInfo.azure.tpmNotaryHex.validated}
229
+ />
230
+ ),
231
+ offsetTopLabel: true,
232
+ },
233
+ {
234
+ label: "Notary Key DID",
235
+ value: systemInfo.azure.tpmPCRHash.value && (
236
+ <DisplayCode
237
+ value={`did:key:${systemInfo.azure.tpmNotaryDID.value}`}
238
+ validated={systemInfo.azure.tpmNotaryDID.validated}
239
+ />
240
+ ),
241
+ offsetTopLabel: true,
242
+ },
243
+ {
244
+ value: <SectionInnerTitle title="Azure vTPM Verification" />,
245
+ },
246
+ {
247
+ label: "TPM AK Certificate",
248
+ value: systemInfo.azure.tpmPCRHash.value && (
249
+ <CertificateCode
250
+ code={systemInfo.azure.tpmAKCertificate.value as unknown as string}
251
+ validated={systemInfo.azure.tpmAKCertificate.validated}
252
+ />
253
+ ),
254
+ },
255
+ {
256
+ label: "vTPM Quote",
257
+ value: systemInfo.azure.tpmPCRHash.value && (
258
+ <CertificateCode
259
+ code={systemInfo.azure.tpmQuote.value as unknown as string}
260
+ validated={systemInfo.azure.tpmQuote.validated}
261
+ />
262
+ ),
263
+ },
264
+ {
265
+ label: "vTPM Signature",
266
+ value: systemInfo.azure.tpmPCRHash.value && (
267
+ <CertificateCode
268
+ code={systemInfo.azure.tpmQuoteSignature.value as unknown as string}
269
+ validated={systemInfo.azure.tpmQuoteSignature.validated}
270
+ />
271
+ ),
272
+ },
273
+ {
274
+ label: "vTPM Public Key",
275
+ value: systemInfo.azure.tpmPCRHash.value && (
276
+ <DisplayCode
277
+ value={`hex:${systemInfo.azure.azureAKTPMPubKey.value}`}
278
+ validated={systemInfo.azure.azureAKTPMPubKey.validated}
279
+ />
280
+ ),
281
+ offsetTopLabel: true,
282
+ },
283
+ {
284
+ value: <SectionInnerTitle title="Azure Boot Log Verification" />,
285
+ },
286
+ {
287
+ label: "vTPM AK Key",
288
+ value: systemInfo.azure.tpmPCRHash.value && (
289
+ <DisplayCode
290
+ value={`hex:${systemInfo.azure.azureTPMAKKey.value}`}
291
+ validated={systemInfo.azure.azureTPMAKKey.validated}
292
+ />
293
+ ),
294
+ offsetTopLabel: true,
295
+ },
296
+ {
297
+ label: "Azure Boot Logs",
298
+ value: systemInfo.azure.tpmPCRHash.value && (
299
+ <CertificateCode code={systemInfo.azure.bootLog.value as unknown as string} />
300
+ ),
301
+ },
302
+ {
303
+ label: "Azure Boot Log Hash",
304
+ value: systemInfo.azure.tpmPCRHash.value && (
305
+ <DisplayCode
306
+ value={`sha256:${systemInfo.azure.bootLogHash.value}`}
307
+ validated={systemInfo.azure.bootLogHash.validated}
308
+ />
309
+ ),
310
+ offsetTopLabel: true,
311
+ },
312
+ ];
313
+
314
+ const amdData = [
315
+ {
316
+ value: <SectionInnerTitle title="AMD SEV-SNP Measurement" />,
317
+ },
318
+ {
319
+ label: "Measurement",
320
+ value: systemInfo.azure.tpmPCRHash.value && (
321
+ <DisplayCode
322
+ value={`hash:${systemInfo.cpu.measurements.amdMeasurement.value}`}
323
+ validated={systemInfo.cpu.measurements.amdMeasurement.validated}
324
+ />
325
+ ),
326
+ offsetTopLabel: true,
327
+ },
328
+ {
329
+ label: "Report Data",
330
+ value: systemInfo.cpu.measurements.amdReportData && (
331
+ <DisplayCode value={`hash:${systemInfo.cpu.measurements.amdReportData}`} />
332
+ ),
333
+ offsetTopLabel: true,
334
+ },
335
+ ];
336
+
337
+ const data = [
338
+ ...(systemInfo.cpu.type === "azure" && showAzureUKI ? linuxData : []),
339
+ ...(systemInfo.cpu.type === "azure" ? azureData : []),
340
+ ...(systemInfo.cpu.type !== "amd" && showIntelHeading ? intelData : []),
341
+ ...(systemInfo.cpu.type === "amd" ? amdData : []),
342
+ ...(systemInfo.cpu.report.value || systemInfo.cpu.certificate.x509 || systemInfo.cpu.certificate.chain
343
+ ? cpuAttestationData
344
+ : []),
345
+ ...(systemInfo.gpu.reportData || systemInfo.gpu.report.value || systemInfo.gpu.certificate.x509.value
346
+ ? nvidiaData
347
+ : []),
348
+ ...(systemInfo.gpu.certificate.chain ? gpuCertificateData : []),
349
+ ];
350
+
351
+ if (!data.length) return null;
352
+
353
+ return <Details title="Details" content={<SectionList data={data} className="mt-4 pb-4" />} />;
354
+ };
355
+
356
+ export default SystemDidDetails;
@@ -0,0 +1,196 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import {
3
+ parse,
4
+ ParsedManifest,
5
+ detectUploadsFromFile,
6
+ UploadsMap,
7
+ UploadValue,
8
+ verifyUploads,
9
+ UploadVerification,
10
+ UploadKey,
11
+ Validated,
12
+ } from "./utils";
13
+
14
+ export interface UseVCompParams {
15
+ manifestJson: unknown;
16
+ }
17
+
18
+ export const useVComp = ({ manifestJson }: UseVCompParams) => {
19
+ const [data, setData] = useState<ParsedManifest | null>(null);
20
+ const [uploads, setUploads] = useState<UploadsMap>({});
21
+ const [verify, setVerify] = useState<UploadVerification | null>(null);
22
+ const initialValidationsRef = useRef<{
23
+ containers: Record<string, { dockerComposeId: Validated }>;
24
+ systems: Record<
25
+ string,
26
+ {
27
+ cpu: { mrtd: Validated; rtmr0: Validated; rtmr1: Validated; rtmr2: Validated; rootfs: Validated };
28
+ azure: { tpmPCRHash: Validated };
29
+ }
30
+ >;
31
+ } | null>(null);
32
+
33
+ const resetVComp = () => {
34
+ setData(null);
35
+ setUploads({});
36
+ setVerify(null);
37
+ };
38
+
39
+ useEffect(() => {
40
+ if (manifestJson) {
41
+ const parseData = async () => {
42
+ try {
43
+ setUploads({});
44
+ setVerify(null);
45
+
46
+ const results = await parse(manifestJson);
47
+ // Capture initial validation snapshot for selective resets on upload deletion
48
+ initialValidationsRef.current = {
49
+ containers: Object.fromEntries(
50
+ Object.keys(results.containers).map((didKey) => [
51
+ didKey,
52
+ { dockerComposeId: results.containers[didKey].dockerComposeId.validated },
53
+ ]),
54
+ ),
55
+ systems: Object.fromEntries(
56
+ Object.keys(results.systems).map((didKey) => [
57
+ didKey,
58
+ {
59
+ cpu: {
60
+ mrtd: results.systems[didKey].cpu.measurements.mrtd.validated,
61
+ rtmr0: results.systems[didKey].cpu.measurements.rtmr0.validated,
62
+ rtmr1: results.systems[didKey].cpu.measurements.rtmr1.validated,
63
+ rtmr2: results.systems[didKey].cpu.measurements.rtmr2.validated,
64
+ rootfs: results.systems[didKey].cpu.measurements.rootfs.validated,
65
+ },
66
+ azure: {
67
+ tpmPCRHash: results.systems[didKey].azure.tpmPCRHash.validated,
68
+ },
69
+ },
70
+ ]),
71
+ ),
72
+ };
73
+ setData(results);
74
+ } catch (error) {
75
+ console.error("Error parsing manifest", error);
76
+ resetVComp();
77
+ }
78
+ };
79
+ parseData();
80
+ } else {
81
+ // Clear data when manifestJson is null/undefined
82
+ resetVComp();
83
+ }
84
+ }, [manifestJson]);
85
+
86
+ useEffect(() => {
87
+ const runVerify = async () => {
88
+ if (!data) return;
89
+ try {
90
+ const res = await verifyUploads(uploads, data);
91
+ setVerify(res);
92
+ } catch (e) {
93
+ console.error("Verify Uploads failed", e);
94
+ }
95
+ };
96
+ runVerify();
97
+ }, [uploads, data]);
98
+
99
+ const handleDetectedUploads = (detected: UploadValue[]) => {
100
+ setUploads((prev) => {
101
+ const next: UploadsMap = { ...prev };
102
+ for (const item of detected) {
103
+ if (item.kind !== "manifest") {
104
+ next[item.kind] = item.value as Uint8Array;
105
+ }
106
+ }
107
+ return next;
108
+ });
109
+ };
110
+
111
+ const onFilesSelected = async (files: FileList | null) => {
112
+ if (!files) return;
113
+ const fileArray = Array.from(files);
114
+ for (const file of fileArray) {
115
+ try {
116
+ const detected = await detectUploadsFromFile(file);
117
+ handleDetectedUploads(detected);
118
+ } catch (e) {
119
+ console.error("Failed to process file", file.name, e);
120
+ }
121
+ }
122
+ };
123
+
124
+ const handleDeleteUpload = (kind: Exclude<UploadKey, "manifest">) => {
125
+ // Remove the upload
126
+ setUploads((prev) => {
127
+ const next: UploadsMap = { ...prev };
128
+ delete (next as Record<string, unknown>)[kind];
129
+ return next;
130
+ });
131
+
132
+ // Reset validations that were impacted by this specific upload back to initial snapshot
133
+ setData((prev) => {
134
+ if (!prev || !initialValidationsRef.current) return prev;
135
+
136
+ const initial = initialValidationsRef.current;
137
+
138
+ switch (kind) {
139
+ case "compose":
140
+ const value1 = { ...prev };
141
+ for (const didKey of Object.keys(value1.containers)) {
142
+ value1.containers[didKey].dockerComposeId.validated =
143
+ initial.containers[didKey].dockerComposeId;
144
+ }
145
+ return value1;
146
+
147
+ case "ovmf":
148
+ const value2 = { ...prev };
149
+ for (const didKey of Object.keys(value2.systems)) {
150
+ value2.systems[didKey].cpu.measurements.mrtd.validated = initial.systems[didKey].cpu.mrtd;
151
+ value2.systems[didKey].cpu.measurements.rtmr0.validated = initial.systems[didKey].cpu.rtmr0;
152
+ }
153
+ return value2;
154
+
155
+ case "cmdline":
156
+ const value3 = { ...prev };
157
+ for (const didKey of Object.keys(value3.systems)) {
158
+ value3.systems[didKey].cpu.measurements.rtmr2.validated = initial.systems[didKey].cpu.rtmr2;
159
+ value3.systems[didKey].cpu.measurements.rootfs.validated = initial.systems[didKey].cpu.rootfs;
160
+ }
161
+ return value3;
162
+
163
+ case "initrd":
164
+ const value4 = { ...prev };
165
+ for (const didKey of Object.keys(value4.systems)) {
166
+ value4.systems[didKey].cpu.measurements.rtmr1.validated = initial.systems[didKey].cpu.rtmr1;
167
+ value4.systems[didKey].cpu.measurements.rtmr2.validated = initial.systems[didKey].cpu.rtmr2;
168
+ value4.systems[didKey].cpu.measurements.rootfs.validated = initial.systems[didKey].cpu.rootfs;
169
+ }
170
+ return value4;
171
+
172
+ case "kernel":
173
+ const value5 = { ...prev };
174
+ for (const didKey of Object.keys(value5.systems)) {
175
+ value5.systems[didKey].cpu.measurements.rtmr1.validated = initial.systems[didKey].cpu.rtmr1;
176
+ value5.systems[didKey].azure.tpmPCRHash.validated = initial.systems[didKey].azure.tpmPCRHash;
177
+ }
178
+ return value5;
179
+
180
+ default:
181
+ return prev;
182
+ }
183
+ });
184
+ };
185
+
186
+ return {
187
+ vCompData: data,
188
+ uploads,
189
+ vCompVerifyData: verify,
190
+ handleDetectedUploads,
191
+ onFilesSelected,
192
+ handleDeleteUpload,
193
+ };
194
+ };
195
+
196
+ export type UseVCompReturn = ReturnType<typeof useVComp>;