Skip to content

Commit 1328414

Browse files
authored
Feat/eid onboarding flow restructure (#877)
* feat: new onboarding scaffold * fix: dev sandbox token caching * feat: new verification flow with didit * feat: working verification * feat: basic auth handling * feat: prevention of duplicates * feat: upgrade route * feat: recovery onboarding flow * feat: recovery functional * fix: recovery issue with facesearch: * feat: code rabbit fixes part1 * chore: fix format * fix: tests * fix: lint
1 parent d1cf0c6 commit 1328414

153 files changed

Lines changed: 7360 additions & 4270 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ PROVISIONER_DATABASE_URL="postgres://postgres:postgres@localhost:5432/provisione
1616
PUBLIC_VERIFF_KEY="your-veriff-key"
1717
VERIFF_HMAC_KEY="your-veriff-hmac-key"
1818

19+
# Didit KYC
20+
DIDIT_API_KEY="your-didit-api-key"
21+
DIDIT_WORKFLOW_ID="your-didit-workflow-id"
22+
DIDIT_WEBHOOK_SECRET="your-didit-webhook-secret"
23+
24+
# Provisioner signing key (32-byte hex seed for ed25519)
25+
PROVISIONER_SIGNING_SEED="your-32-byte-hex-seed"
26+
PROVISIONER_KID="provisioner-1"
27+
1928
# set this to allow or deny
2029
DUPLICATES_POLICY="DENY"
2130
IP_ADDR="localhost"
@@ -63,6 +72,11 @@ PUBLIC_APP_STORE_EID_WALLET=""
6372
PUBLIC_PLAY_STORE_EID_WALLET=""
6473
NOTIFICATION_SHARED_SECRET=your-notification-secret-key
6574

75+
# Shared secret between eid-wallet frontend and evault-core provisioner
76+
# Backend reads PROVISIONER_SHARED_SECRET, wallet reads PUBLIC_PROVISIONER_SHARED_SECRET
77+
PROVISIONER_SHARED_SECRET="your-provisioner-shared-secret"
78+
PUBLIC_PROVISIONER_SHARED_SECRET="your-provisioner-shared-secret"
79+
6680
PUBLIC_ESIGNER_BASE_URL="http://localhost:3004"
6781
PUBLIC_FILE_MANAGER_BASE_URL="http://localhost:3005"
6882

infrastructure/control-panel/src/routes/+layout.svelte

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,26 +79,48 @@
7979
// Fetch evaults if we have IDs
8080
if (evaultsData) {
8181
const evaultIds = JSON.parse(evaultsData);
82-
if (Array.isArray(evaultIds) && evaultIds.length > 0 && typeof evaultIds[0] === 'string') {
83-
const { EVaultService } = await import('$lib/services/evaultService');
82+
if (
83+
Array.isArray(evaultIds) &&
84+
evaultIds.length > 0 &&
85+
typeof evaultIds[0] === 'string'
86+
) {
87+
const { EVaultService } =
88+
await import('$lib/services/evaultService');
8489
const allEVaults = await EVaultService.getEVaults();
8590
const evaultObjects = evaultIds
86-
.map((id: string) => allEVaults.find((e: any) => (e.evault || e.ename || e.id) === id))
91+
.map((id: string) =>
92+
allEVaults.find(
93+
(e: any) => (e.evault || e.ename || e.id) === id
94+
)
95+
)
8796
.filter(Boolean);
88-
sessionStorage.setItem('selectedEVaultsData', JSON.stringify(evaultObjects));
97+
sessionStorage.setItem(
98+
'selectedEVaultsData',
99+
JSON.stringify(evaultObjects)
100+
);
89101
}
90102
}
91103

92104
// Fetch platforms if we have URLs
93105
if (platformsData) {
94106
const platformUrls = JSON.parse(platformsData);
95-
if (Array.isArray(platformUrls) && platformUrls.length > 0 && typeof platformUrls[0] === 'string') {
96-
const { registryService } = await import('$lib/services/registry');
107+
if (
108+
Array.isArray(platformUrls) &&
109+
platformUrls.length > 0 &&
110+
typeof platformUrls[0] === 'string'
111+
) {
112+
const { registryService } =
113+
await import('$lib/services/registry');
97114
const allPlatforms = await registryService.getPlatforms();
98115
const platformObjects = platformUrls
99-
.map((url: string) => allPlatforms.find((p: any) => p.url === url))
116+
.map((url: string) =>
117+
allPlatforms.find((p: any) => p.url === url)
118+
)
100119
.filter(Boolean);
101-
sessionStorage.setItem('selectedPlatformsData', JSON.stringify(platformObjects));
120+
sessionStorage.setItem(
121+
'selectedPlatformsData',
122+
JSON.stringify(platformObjects)
123+
);
102124
}
103125
}
104126
} catch (error) {
@@ -107,8 +129,7 @@
107129

108130
// Navigate to monitoring
109131
goto('/monitoring');
110-
}}
111-
>Start Monitoring</ButtonAction
132+
}}>Start Monitoring</ButtonAction
112133
>
113134
</div>
114135
{:else}

infrastructure/dev-sandbox/src/routes/+page.svelte

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,20 @@ function setDebug(info: DebugInfo): void {
133133
lastDebug = info;
134134
}
135135
136+
async function getPlatformToken(): Promise<string> {
137+
const res = await fetch(
138+
new URL("/platforms/certification", config.registryUrl).toString(),
139+
{
140+
method: "POST",
141+
headers: { "Content-Type": "application/json" },
142+
body: JSON.stringify({ platform: config.platformName }),
143+
},
144+
);
145+
if (!res.ok) throw new Error(`Platform token failed: ${res.status}`);
146+
const data = (await res.json()) as { token: string };
147+
return data.token;
148+
}
149+
136150
async function ensurePlatformToken(identity: Identity): Promise<string> {
137151
const now = Date.now();
138152
if (
@@ -257,8 +271,7 @@ function escapeHtml(str: string): string {
257271
.replace(/</g, "&lt;")
258272
.replace(/>/g, "&gt;")
259273
.replace(/"/g, "&quot;")
260-
.replace(/'/g, "&#39;")
261-
.replace(/\//g, "&#47;");
274+
.replace(/'/g, "&#39;");
262275
}
263276
264277
function highlightJson(json: string): string {
@@ -284,34 +297,59 @@ function highlightJson(json: string): string {
284297
}
285298
286299
async function loadMetaEnvelopes(): Promise<void> {
287-
if (!selectedOntologyId || !selectedIdentity) return;
300+
if (!selectedOntologyId) return;
301+
302+
const ename = inspectorEName.trim() || selectedIdentity?.w3id;
303+
if (!ename) {
304+
pageError = "Enter an eName or provision an identity first.";
305+
return;
306+
}
307+
288308
pageLoading = true;
289309
pageError = null;
290310
try {
291-
const token = await ensurePlatformToken(selectedIdentity);
292-
const gqlUrl = `${selectedIdentity.uri.replace(/\/+$/, "")}/graphql`;
311+
// Always get a platform token — metaEnvelopes requires Bearer auth
312+
const token = await getPlatformToken();
313+
314+
// Resolve eVault URI
315+
let gqlUrl: string;
316+
const lookupEName = inspectorEName.trim();
317+
if (!lookupEName && selectedIdentity) {
318+
gqlUrl = `${selectedIdentity.uri.replace(/\/+$/, "")}/graphql`;
319+
} else {
320+
const resolveRes = await fetch(
321+
new URL(`resolve?w3id=${encodeURIComponent(ename)}`, registryUrl).toString(),
322+
);
323+
if (!resolveRes.ok) throw new Error(`Registry resolve failed: ${resolveRes.status}`);
324+
const resolveData = await resolveRes.json();
325+
if (!resolveData.uri) throw new Error("Registry returned no URI for that eName.");
326+
gqlUrl = `${resolveData.uri.replace(/\/+$/, "")}/graphql`;
327+
}
328+
293329
const useBefore = beforeCursor !== null;
294330
const query = useBefore
295331
? "query ($ontologyId: ID!, $last: Int, $before: String) {\n metaEnvelopes(filter: {ontologyId: $ontologyId}, last: $last, before: $before) {\n edges { cursor node { id ontology parsed } }\n pageInfo { hasNextPage hasPreviousPage startCursor endCursor }\n totalCount\n }\n}"
296332
: "query ($ontologyId: ID!, $first: Int, $after: String) {\n metaEnvelopes(filter: {ontologyId: $ontologyId}, first: $first, after: $after) {\n edges { cursor node { id ontology parsed } }\n pageInfo { hasNextPage hasPreviousPage startCursor endCursor }\n totalCount\n }\n}";
297333
const variables = useBefore
298334
? { ontologyId: selectedOntologyId, last: pageSize, before: beforeCursor }
299335
: { ontologyId: selectedOntologyId, first: pageSize, after: afterCursor };
336+
337+
const headers: Record<string, string> = {
338+
"Content-Type": "application/json",
339+
"X-ENAME": ename,
340+
};
341+
if (token) headers["Authorization"] = `Bearer ${token}`;
342+
300343
const res = await fetch(gqlUrl, {
301344
method: "POST",
302-
headers: {
303-
"Content-Type": "application/json",
304-
"X-ENAME": inspectorEName || selectedIdentity.w3id,
305-
Authorization: `Bearer ${token}`,
306-
},
345+
headers,
307346
body: JSON.stringify({ query, variables }),
308347
});
309348
const json = await res.json();
349+
if (json.errors?.length) throw new Error(json.errors[0].message);
310350
const data = json.data.metaEnvelopes;
311351
envelopes = data.edges.map(
312-
(e: {
313-
node: { id: string; ontology: string; parsed: unknown };
314-
}) => e.node,
352+
(e: { node: { id: string; ontology: string; parsed: unknown } }) => e.node,
315353
);
316354
pageInfo = data.pageInfo;
317355
totalCount = data.totalCount;
@@ -930,7 +968,7 @@ async function doSign() {
930968
<button class="btn-secondary" disabled={schemasLoading} onclick={loadOntologies}>
931969
{schemasLoading ? "Loading schemas…" : "Refresh schemas"}
932970
</button>
933-
<button disabled={pageLoading || !selectedOntologyId} onclick={loadEnvelopes}>
971+
<button disabled={pageLoading || !selectedOntologyId || (!inspectorEName.trim() && !selectedIdentity)} onclick={loadEnvelopes}>
934972
{pageLoading ? "Loading…" : "Load MetaEnvelopes"}
935973
</button>
936974
</div>

infrastructure/eid-wallet/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"license": "MIT",
2121
"dependencies": {
2222
"@auvo/tauri-plugin-crypto-hw-api": "^0.1.0",
23+
"@didit-protocol/sdk-web": "^0.1.6",
2324
"@hugeicons/core-free-icons": "^1.0.13",
2425
"@hugeicons/svelte": "^1.0.2",
2526
"@iconify/svelte": "^5.0.1",
@@ -46,6 +47,7 @@
4647
"svelte-loading-spinners": "^0.3.6",
4748
"svelte-qrcode": "^1.0.1",
4849
"tailwind-merge": "^3.0.2",
50+
"ts-md5": "^2.0.1",
4951
"uuid": "^11.1.0",
5052
"wallet-sdk": "workspace:*"
5153
},
@@ -66,7 +68,7 @@
6668
"@tailwindcss/forms": "^0.5.10",
6769
"@tailwindcss/typography": "^0.5.16",
6870
"@tailwindcss/vite": "^4.0.14",
69-
"@tauri-apps/cli": "^2.9.4",
71+
"@tauri-apps/cli": "^2.10.0",
7072
"@types/node": "^22.13.10",
7173
"@vitest/browser": "^3.0.9",
7274
"@vitest/coverage-v8": "^3.0.9",

infrastructure/eid-wallet/src-tauri/gen/android/.idea/AndroidProjectSystem.xml

Lines changed: 0 additions & 6 deletions
This file was deleted.

infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml

Lines changed: 0 additions & 123 deletions
This file was deleted.

infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml

Lines changed: 0 additions & 5 deletions
This file was deleted.

infrastructure/eid-wallet/src-tauri/gen/android/.idea/compiler.xml

Lines changed: 0 additions & 6 deletions
This file was deleted.

infrastructure/eid-wallet/src-tauri/gen/android/.idea/deploymentTargetSelector.xml

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)