Skip to content

Conversation

coodos
Copy link
Contributor

@coodos coodos commented Jun 3, 2025

Description of change

Issue Number

Type of change

  • Breaking (any change that would cause existing functionality to not work as expected)
  • New (a change which implements a new feature)
  • Update (a change which updates existing functionality)
  • Fix (a change which fixes an issue)
  • Docs (changes to the documentation)
  • Chore (refactoring, build scripts or anything else that isn't user-facing)

How the change has been tested

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Introduced a multi-step, real-time identity verification flow with passport and selfie capture, integrated with backend services for status updates and approval.
    • Added dynamic user and vault data loading, replacing static placeholders throughout the app.
    • Implemented a utility for string capitalization and exposed it for use in components.
    • Added a "nuke wallet" action in settings to clear user data and reset onboarding.
    • Integrated CORS support in backend services for improved cross-origin compatibility.
    • Added database support for verification sessions, including migrations, entities, and real-time event streaming.
  • Bug Fixes

    • Improved error handling and state management in user and vault controllers.
  • Refactor

    • Reformatted UI components and route handlers for clarity and maintainability.
    • Updated environment and build configurations for better development and production support.
  • Chores

    • Updated and expanded package dependencies for both frontend and backend projects.
    • Added new scripts and configuration for database migrations and development workflows.
  • Tests

    • Introduced Svelte stores and utility modules to support new verification flows and state management.

Copy link
Contributor

coderabbitai bot commented Jun 3, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces a comprehensive identity verification and vault provisioning flow, spanning both the frontend (eid-wallet) and backend (evault-provisioner, registry). It adds new verification steps, dynamic user and document data handling, backend API integration, TypeORM-based persistence, event-driven status updates, and utility enhancements. Several new modules, entities, controllers, and configuration improvements are included.

Changes

Files/Groups Change Summary
infrastructure/eid-wallet/package.json
infrastructure/evault-provisioner/package.json
platforms/registry/package.json
Added/updated dependencies and scripts for verification, HTTP, CORS, TypeORM, and utilities.
infrastructure/eid-wallet/src/lib/fragments/IdentityCard/IdentityCard.svelte
infrastructure/eid-wallet/src/lib/ui/Button/ButtonAction.svelte
Code formatting and minor markup adjustments for clarity; no logic changes.
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts New VaultController class for vault state management.
infrastructure/eid-wallet/src/lib/global/controllers/user.ts Added document getter/setter to UserController with async and error handling.
infrastructure/eid-wallet/src/lib/global/state.ts Added vaultController property to GlobalState.
infrastructure/eid-wallet/src/lib/utils/capitalize.ts
infrastructure/eid-wallet/src/lib/utils/index.ts
Added and exported new capitalize utility function.
infrastructure/eid-wallet/src/routes/(app)/ePassport/+page.svelte
infrastructure/eid-wallet/src/routes/(app)/main/+page.svelte
infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte
infrastructure/eid-wallet/src/routes/(auth)/e-passport/+page.svelte
infrastructure/eid-wallet/src/routes/(auth)/review/+page.svelte
Refactored to fetch and display dynamic user, document, and vault data from global state; removed hardcoded values; added wallet reset logic.
infrastructure/eid-wallet/src/routes/(auth)/verify/+page.svelte Major rewrite: implements multi-step, real-time verification flow with backend API, SSE, and vault provisioning.
infrastructure/eid-wallet/src/routes/(auth)/verify/steps/passport.svelte
infrastructure/eid-wallet/src/routes/(auth)/verify/steps/selfie.svelte
New components for passport and selfie capture, camera access, and image upload.
infrastructure/eid-wallet/src/routes/(auth)/verify/store.ts New Svelte store module for verification step, media, and status state.
infrastructure/eid-wallet/src/routes/+layout.svelte Added container height and scroll classes; enabled style block.
infrastructure/eid-wallet/svelte.config.js Added SvelteKit env directory configuration.
infrastructure/evault-provisioner/src/config/database.ts New TypeORM DataSource setup for PostgreSQL with env config.
infrastructure/evault-provisioner/src/controllers/VerificationController.ts New controller for verification session management, SSE, media upload, webhooks, and API integration.
infrastructure/evault-provisioner/src/entities/Verification.ts New TypeORM entity for verification records.
infrastructure/evault-provisioner/src/index.ts Integrated CORS, database, new verification endpoints, and improved provision request validation.
infrastructure/evault-provisioner/src/migrations/1748932757644-migration.ts
infrastructure/evault-provisioner/src/migrations/1748966722767-migration.ts
infrastructure/evault-provisioner/src/migrations/1748968097591-migration.ts
New database migrations for verification table and schema evolution.
infrastructure/evault-provisioner/src/services/VerificationService.ts New service for verification entity CRUD and queries.
infrastructure/evault-provisioner/src/utils/eventEmitter.ts New event emitter utility for SSE and event-driven updates.
infrastructure/evault-provisioner/src/utils/hmac.ts New HMAC signature creation and verification utilities.
infrastructure/evault-provisioner/tsconfig.json Switched to CommonJS, enabled decorators and metadata.
platforms/registry/src/index.ts Added CORS, improved formatting, and re-enabled entropy endpoint.

Sequence Diagram(s)

End-to-End Verification and Vault Provisioning Flow

sequenceDiagram
    participant User as User (Frontend)
    participant EidWallet as eid-wallet (Svelte)
    participant Provisioner as evault-provisioner (Backend)
    participant Veriff as Veriff API
    participant Registry as Registry Service

    User->>EidWallet: Start verification
    EidWallet->>Provisioner: POST /verification (create session)
    Provisioner->>Veriff: Create session via API
    Veriff-->>Provisioner: Session ID
    Provisioner-->>EidWallet: Session ID

    User->>EidWallet: Capture passport & selfie
    EidWallet->>Provisioner: POST /verification/:id/media (upload images)
    Provisioner->>Veriff: Forward images

    Veriff-->>Provisioner: Webhook (verification decision)
    Provisioner->>EidWallet: SSE status updates

    EidWallet->>Provisioner: POST /provision (with verificationId)
    Provisioner->>Registry: POST /register (register vault)
    Registry-->>Provisioner: Vault info
    Provisioner-->>EidWallet: Vault details

    EidWallet->>User: Display vault & onboarding complete
Loading

Possibly related PRs

Suggested reviewers

  • sosweetham
  • JulienAuvo

Poem

🐇
A passport snap, a selfie bright,
Through streams and steps, we check what's right.
The vault now opens, safe and sound,
With backend bits and bytes abound.
From code to cloud, our journey's spun—
Identity, secure, begun!
🗝️✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5992cac and e5bfecd.

📒 Files selected for processing (2)
  • infrastructure/eid-wallet/src/lib/utils/capitalize.ts (1 hunks)
  • infrastructure/evault-provisioner/src/utils/hmac.ts (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 33

🔭 Outside diff range comments (1)
infrastructure/evault-provisioner/src/index.ts (1)

141-149: 🛠️ Refactor suggestion

Improve error handling specificity

The current error handling loses the original error message when it's not an Axios error.

         } catch (error) {
-            const axiosError = error as AxiosError;
-            res.status(500).json({
-                success: false,
-                error: axiosError.response?.data || axiosError.message,
-                message: "Failed to provision evault instance",
-            });
+            if (error instanceof AxiosError) {
+                res.status(500).json({
+                    success: false,
+                    error: error.response?.data || error.message,
+                    message: "Failed to provision evault instance",
+                });
+            } else {
+                res.status(500).json({
+                    success: false,
+                    error: error instanceof Error ? error.message : String(error),
+                    message: "Failed to provision evault instance",
+                });
+            }
         }
🧹 Nitpick comments (24)
infrastructure/evault-provisioner/src/utils/hmac.ts (1)

1-1: Use node: protocol for Node.js imports.

Following Node.js best practices, builtin modules should be imported with the node: protocol for better clarity and explicit indication of Node.js modules.

-import { createHmac } from "crypto";
+import { createHmac } from "node:crypto";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

infrastructure/evault-provisioner/src/utils/eventEmitter.ts (1)

1-1: Use the node: protocol for Node.js builtin imports.

The import should use the node: protocol to be more explicit about importing a Node.js builtin module, following modern best practices.

-import { EventEmitter } from "events"
+import { EventEmitter } from "node:events"
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

infrastructure/evault-provisioner/src/migrations/1748966722767-migration.ts (1)

1-1: Optimize imports for better tree-shaking.

Use import type for type-only imports to ensure they are removed by the compiler and avoid loading unnecessary modules.

-import { MigrationInterface, QueryRunner } from "typeorm";
+import type { MigrationInterface, QueryRunner } from "typeorm";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

infrastructure/evault-provisioner/src/migrations/1748968097591-migration.ts (1)

1-1: Optimize imports by using import type for TypeORM interfaces.

The static analysis tool correctly identifies that these imports are only used as types. Using import type ensures they're removed during compilation and avoids loading unnecessary modules.

-import { MigrationInterface, QueryRunner } from "typeorm";
+import type { MigrationInterface, QueryRunner } from "typeorm";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

infrastructure/eid-wallet/src/routes/(app)/ePassport/+page.svelte (2)

11-13: Remove unused shareEPassport function.

The shareEPassport function is no longer used since the share button was removed from the UI. Consider removing it to keep the code clean.

-    function shareEPassport() {
-        alert("EPassport Code shared!");
-    }

21-21: Consider removing debug console.log.

The console.log(userData) appears to be for debugging purposes and should be removed in production code.

-        console.log(userData);
infrastructure/evault-provisioner/src/migrations/1748932757644-migration.ts (1)

1-1: Optimize imports by using import type for TypeORM interfaces.

Same as the other migration file - these imports are only used as types and should use import type.

-import { MigrationInterface, QueryRunner } from "typeorm";
+import type { MigrationInterface, QueryRunner } from "typeorm";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (2)

18-22: LGTM! Consider adding confirmation dialog for wallet reset.

The nukeWallet function correctly clears user data and security PIN before navigating to onboarding. This provides a clean reset mechanism for the wallet.

Consider adding a confirmation dialog before executing the wallet reset to prevent accidental data loss.


57-57: Replace placeholder text with meaningful label.

The ButtonAction component contains placeholder text "asdfasdf" which should be replaced with a descriptive label for the wallet reset functionality.

-    <ButtonAction callback={nukeWallet}>asdfasdf</ButtonAction>
+    <ButtonAction callback={nukeWallet}>Reset Wallet</ButtonAction>
infrastructure/evault-provisioner/src/config/database.ts (1)

4-4: Use Node.js import protocol for built-in modules.

Following the static analysis hint, use the node: protocol for Node.js built-in modules for better clarity and explicit indication.

-import { join } from "path"
+import { join } from "node:path"
🧰 Tools
🪛 Biome (1.9.4)

[error] 4-4: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (1)

17-17: Consider more descriptive variable name.

The variable name resolvedUser in the promise resolution should be resolvedVault to match the context.

-                .then((resolvedUser) => {
-                    this.#store.set("vault", resolvedUser);
+                .then((resolvedVault) => {
+                    this.#store.set("vault", resolvedVault);
🧰 Tools
🪛 Biome (1.9.4)

[error] 17-17: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '.'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 17-17: Expected a parameter but instead found '('.

Expected a parameter here.

(parse)


[error] 17-17: expected , but instead found resolvedUser

Remove resolvedUser

(parse)


[error] 17-17: Expected a class method body but instead found '=>'.

Expected a class method body here.

(parse)


[error] 17-17: Do not add then to a class.

(lint/suspicious/noThenProperty)

infrastructure/eid-wallet/src/lib/fragments/IdentityCard/IdentityCard.svelte (1)

44-44: Break down the long CSS class string for better readability.

This single line contains a complex conditional expression that's difficult to read and maintain. Consider extracting this logic into a computed property or breaking it into multiple lines.

-    const baseClasses = `relative ${variant === "eName" ? "bg-black-900" : variant === "ePassport" ? "bg-primary" : "bg-gray"}  rounded-3xl w-full min-h-[150px] text-white overflow-hidden`;
+    const getBackgroundClass = (variant: string) => {
+        switch (variant) {
+            case "eName": return "bg-black-900";
+            case "ePassport": return "bg-primary"; 
+            default: return "bg-gray";
+        }
+    };
+    
+    const baseClasses = `relative ${getBackgroundClass(variant)} rounded-3xl w-full min-h-[150px] text-white overflow-hidden`;
platforms/registry/src/index.ts (1)

38-47: Improve authorization header validation.

The authorization header validation could be more robust and provide clearer error messages.

 const checkSharedSecret = async (request: any, reply: any) => {
     const authHeader = request.headers.authorization;
-    if (!authHeader || !authHeader.startsWith("Bearer ")) {
+    if (!authHeader) {
+        return reply
+            .status(401)
+            .send({ error: "Authorization header is required" });
+    }
+    
+    if (!authHeader.startsWith("Bearer ")) {
         return reply
             .status(401)
-            .send({ error: "Missing or invalid authorization header" });
+            .send({ error: "Authorization header must use Bearer token format" });
     }
infrastructure/eid-wallet/src/routes/(auth)/verify/steps/passport.svelte (1)

52-52: Remove debug console.log statements.

Debug console.log statements should be removed from production code.

-            console.log("huh?");
             const context1 = canvas1.getContext("2d");
             // ...
-                console.log("here???");

Also applies to: 72-72

infrastructure/evault-provisioner/src/entities/Verification.ts (1)

20-21: Consider more specific typing for the data field.

The Record<string, unknown> type is quite loose. Consider defining a more specific interface for the expected data structure.

+interface VerificationData {
+    // Define specific fields based on your verification data structure
+    [key: string]: unknown;
+}

-    @Column({ type: "jsonb", nullable: true })
-    data!: Record<string, unknown>;
+    @Column({ type: "jsonb", nullable: true })
+    data?: VerificationData | null;
infrastructure/evault-provisioner/src/services/VerificationService.ts (2)

1-2: Use import type for type-only imports.

Following the static analysis hint, imports that are only used as types should use import type to ensure they're removed during compilation.

-import { DeepPartial, Repository } from "typeorm";
-import { Verification } from "../entities/Verification";
+import type { DeepPartial, Repository } from "typeorm";
+import type { Verification } from "../entities/Verification";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


[error] 2-2: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


9-12: Consider adding input validation.

The create method should validate input data to ensure data integrity and provide better error messages.

     async create(data: Partial<Verification>): Promise<Verification> {
+        if (!data || Object.keys(data).length === 0) {
+            throw new Error("Verification data cannot be empty");
+        }
+        
         const verification = this.verificationRepository.create(data);
         return await this.verificationRepository.save(verification);
     }
infrastructure/evault-provisioner/src/index.ts (3)

8-8: Use Node.js protocol for builtin module import

For better clarity and consistency with modern Node.js practices.

-import path from "path";
+import path from "node:path";
🧰 Tools
🪛 Biome (1.9.4)

[error] 8-8: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)


9-9: Remove unused import

The createHmacSignature import is not used in this file.

-import { createHmacSignature } from "./utils/hmac";

99-103: Simplify URL construction

The template literal is not needed here as noted by static analysis.

-                new URL(
-                    `/.well-known/jwks.json`,
-                    process.env.PUBLIC_REGISTRY_URL,
-                ).toString(),
+                new URL(
+                    "/.well-known/jwks.json",
+                    process.env.PUBLIC_REGISTRY_URL,
+                ).toString(),
🧰 Tools
🪛 Biome (1.9.4)

[error] 100-100: Do not use template literals if interpolation and special-character handling are not needed.

Unsafe fix: Replace with string literal

(lint/style/noUnusedTemplateLiteral)

infrastructure/eid-wallet/src/lib/global/controllers/user.ts (1)

57-72: Consider extracting common promise handling logic

Both user and document setters have identical promise handling logic. Consider extracting this to reduce duplication.

private async handleAsyncSetter<T>(
    key: string,
    value: Promise<T | undefined> | T | undefined
): Promise<void> {
    if (value instanceof Promise) {
        try {
            const resolved = await value;
            await this.#store.set(key, resolved);
        } catch (error) {
            console.error(`Failed to set ${key}:`, error);
        }
    } else {
        await this.#store.set(key, value);
    }
}

set user(user: Promise<Record<string, string> | undefined> | Record<string, string> | undefined) {
    this.handleAsyncSetter("user", user);
}

set document(document: Promise<Record<string, string> | undefined> | Record<string, string> | undefined) {
    this.handleAsyncSetter("doc", document);
}

Also applies to: 89-106

🧰 Tools
🪛 Biome (1.9.4)

[error] 61-61: expected ) but instead found ,

Remove ,

(parse)


[error] 63-63: expected a semicolon to end the class property, but found none

(parse)


[error] 63-63: expected a semicolon to end the class property, but found none

(parse)


[error] 63-63: expected a semicolon to end the class property, but found none

(parse)


[error] 63-63: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found ')'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 64-64: expected a semicolon to end the class property, but found none

(parse)


[error] 64-64: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '.'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 64-64: Expected a parameter but instead found '('.

Expected a parameter here.

(parse)


[error] 64-64: expected , but instead found resolvedUser

Remove resolvedUser

(parse)


[error] 64-64: Expected a class method body but instead found '=>'.

Expected a class method body here.

(parse)


[error] 65-65: expected a semicolon to end the class property, but found none

(parse)


[error] 65-65: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '.'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 65-65: expected a semicolon to end the class property, but found none

(parse)


[error] 65-65: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found ')'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 66-66: Expected a statement but instead found ').catch((error) =>'.

Expected a statement here.

(parse)


[error] 68-68: Expected a statement but instead found ')'.

Expected a statement here.

(parse)


[error] 69-69: Expected a statement but instead found '} else'.

Expected a statement here.

(parse)


[error] 63-63: Duplicate class member name "user"

(lint/suspicious/noDuplicateClassMembers)


[error] 64-64: Duplicate class member name "user"

(lint/suspicious/noDuplicateClassMembers)


[error] 65-65: Duplicate private class member "#store"

(syntax/correctness/noDuplicatePrivateClassMembers)


[error] 64-64: Do not add then to a class.

(lint/suspicious/noThenProperty)


[error] 66-68: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)


[error] 69-71: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)

infrastructure/eid-wallet/src/routes/(auth)/verify/store.ts (1)

5-7: Initialize writable stores with explicit null values

For consistency and clarity, consider initializing all nullable stores with explicit null values.

-export const DocFront = writable<string | null>();
-export const Selfie = writable<string | null>();
-export const verificaitonId = writable<string | null>();
+export const DocFront = writable<string | null>(null);
+export const Selfie = writable<string | null>(null);
+export const verificationId = writable<string | null>(null);
infrastructure/evault-provisioner/src/controllers/VerificationController.ts (2)

1-2: Use import type for type-only imports

These imports are only used as types and should use import type syntax.

-import { Request, Response } from "express";
-import { VerificationService } from "../services/VerificationService";
+import type { Request, Response } from "express";
+import type { VerificationService } from "../services/VerificationService";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


[error] 2-2: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


12-20: Remove unnecessary axios interceptor

The response interceptor doesn't add any functionality and can be removed.

-veriffClient.interceptors.response.use(
-    (response) => {
-        return response;
-    },
-    async function (error) {
-        if (!error.response) return Promise.reject(error);
-        return Promise.reject(error);
-    },
-);
🧰 Tools
🪛 Biome (1.9.4)

[error] 16-19: This function expression can be turned into an arrow function.

Function expressions that don't use this can be turned into arrow functions.
Safe fix: Use an arrow function instead.

(lint/complexity/useArrowFunction)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60bf4eb and c645a19.

⛔ Files ignored due to path filters (4)
  • infrastructure/eid-wallet/src-tauri/gen/apple/eid-wallet.xcodeproj/project.pbxproj is excluded by !**/gen/**
  • infrastructure/eid-wallet/static/images/CameraCircle.svg is excluded by !**/*.svg
  • infrastructure/eid-wallet/static/images/CameraFrame.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • infrastructure/eid-wallet/package.json (1 hunks)
  • infrastructure/eid-wallet/src/lib/fragments/IdentityCard/IdentityCard.svelte (1 hunks)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (1 hunks)
  • infrastructure/eid-wallet/src/lib/global/controllers/user.ts (2 hunks)
  • infrastructure/eid-wallet/src/lib/global/state.ts (2 hunks)
  • infrastructure/eid-wallet/src/lib/ui/Button/ButtonAction.svelte (1 hunks)
  • infrastructure/eid-wallet/src/lib/utils/capitalize.ts (1 hunks)
  • infrastructure/eid-wallet/src/lib/utils/index.ts (1 hunks)
  • infrastructure/eid-wallet/src/routes/(app)/ePassport/+page.svelte (1 hunks)
  • infrastructure/eid-wallet/src/routes/(app)/main/+page.svelte (3 hunks)
  • infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/e-passport/+page.svelte (3 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/review/+page.svelte (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/verify/+page.svelte (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/verify/steps/passport.svelte (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/verify/steps/selfie.svelte (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/verify/store.ts (1 hunks)
  • infrastructure/eid-wallet/src/routes/+layout.svelte (2 hunks)
  • infrastructure/eid-wallet/svelte.config.js (1 hunks)
  • infrastructure/evault-provisioner/package.json (1 hunks)
  • infrastructure/evault-provisioner/src/config/database.ts (1 hunks)
  • infrastructure/evault-provisioner/src/controllers/VerificationController.ts (1 hunks)
  • infrastructure/evault-provisioner/src/entities/Verification.ts (1 hunks)
  • infrastructure/evault-provisioner/src/index.ts (4 hunks)
  • infrastructure/evault-provisioner/src/migrations/1748932757644-migration.ts (1 hunks)
  • infrastructure/evault-provisioner/src/migrations/1748966722767-migration.ts (1 hunks)
  • infrastructure/evault-provisioner/src/migrations/1748968097591-migration.ts (1 hunks)
  • infrastructure/evault-provisioner/src/services/VerificationService.ts (1 hunks)
  • infrastructure/evault-provisioner/src/utils/eventEmitter.ts (1 hunks)
  • infrastructure/evault-provisioner/src/utils/hmac.ts (1 hunks)
  • infrastructure/evault-provisioner/tsconfig.json (2 hunks)
  • platforms/registry/package.json (2 hunks)
  • platforms/registry/src/index.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
infrastructure/eid-wallet/src/lib/global/state.ts (1)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (1)
  • VaultController (3-42)
infrastructure/evault-provisioner/src/controllers/VerificationController.ts (3)
infrastructure/evault-provisioner/src/services/VerificationService.ts (1)
  • VerificationService (4-50)
infrastructure/evault-provisioner/src/utils/eventEmitter.ts (1)
  • eventEmitter (3-3)
infrastructure/evault-provisioner/src/utils/hmac.ts (1)
  • createHmacSignature (3-7)
🪛 Biome (1.9.4)
infrastructure/evault-provisioner/src/utils/eventEmitter.ts

[error] 1-1: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

infrastructure/evault-provisioner/src/migrations/1748966722767-migration.ts

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

infrastructure/eid-wallet/src/lib/global/controllers/evault.ts

[error] 13-13: expected ) but instead found ,

Remove ,

(parse)


[error] 15-15: expected a semicolon to end the class property, but found none

(parse)


[error] 15-15: expected a semicolon to end the class property, but found none

(parse)


[error] 15-15: expected a semicolon to end the class property, but found none

(parse)


[error] 15-15: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found ')'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 17-17: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '.'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 17-17: Expected a parameter but instead found '('.

Expected a parameter here.

(parse)


[error] 17-17: expected , but instead found resolvedUser

Remove resolvedUser

(parse)


[error] 17-17: Expected a class method body but instead found '=>'.

Expected a class method body here.

(parse)


[error] 18-18: expected a semicolon to end the class property, but found none

(parse)


[error] 18-18: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '.'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 18-18: expected a semicolon to end the class property, but found none

(parse)


[error] 18-18: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found ')'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 19-20: Expected a statement but instead found ')
.catch((error) =>'.

Expected a statement here.

(parse)


[error] 22-22: Expected a statement but instead found ')'.

Expected a statement here.

(parse)


[error] 23-23: Expected a statement but instead found '} else'.

Expected a statement here.

(parse)


[error] 26-28: Expected a statement but instead found '}

get vault()'.

Expected a statement here.

(parse)


[error] 29-40: Illegal return statement outside of a function

(parse)


[error] 41-42: Expected a statement but instead found '}'.

Expected a statement here.

(parse)


[error] 15-15: Duplicate class member name "vault"

(lint/suspicious/noDuplicateClassMembers)


[error] 16-16: Duplicate class member name "vault"

(lint/suspicious/noDuplicateClassMembers)


[error] 18-18: Duplicate private class member "#store"

(syntax/correctness/noDuplicatePrivateClassMembers)


[error] 17-17: Do not add then to a class.

(lint/suspicious/noThenProperty)


[error] 20-22: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)


[error] 23-25: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)


[error] 28-41: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)

infrastructure/evault-provisioner/src/config/database.ts

[error] 4-4: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

infrastructure/evault-provisioner/src/services/VerificationService.ts

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


[error] 2-2: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

infrastructure/evault-provisioner/src/utils/hmac.ts

[error] 1-1: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)


[error] 3-3: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 10-10: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

infrastructure/evault-provisioner/src/migrations/1748968097591-migration.ts

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

infrastructure/eid-wallet/src/lib/global/controllers/user.ts

[error] 61-61: expected ) but instead found ,

Remove ,

(parse)


[error] 89-89: Expected a semicolon or an implicit semicolon after a statement, but found none

An explicit or implicit semicolon is expected here...

...Which is required to end this statement

(parse)


[error] 90-90: expected , but instead found :

Remove :

(parse)


[error] 91-91: expected , but instead found |

Remove |

(parse)


[error] 94-94: Expected a semicolon or an implicit semicolon after a statement, but found none

An explicit or implicit semicolon is expected here...

...Which is required to end this statement

(parse)


[error] 108-108: Expected a semicolon or an implicit semicolon after a statement, but found none

An explicit or implicit semicolon is expected here...

...Which is required to end this statement

(parse)


[error] 108-108: Expected a semicolon or an implicit semicolon after a statement, but found none

An explicit or implicit semicolon is expected here...

...Which is required to end this statement

(parse)


[error] 109-120: Illegal return statement outside of a function

(parse)


[error] 94-106: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)


[error] 108-121: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)

infrastructure/evault-provisioner/src/migrations/1748932757644-migration.ts

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

infrastructure/evault-provisioner/src/index.ts

[error] 8-8: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)


[error] 2-2: Some named imports are only used as types.

This import is only used as a type.

This import is only used as a type.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.

(lint/style/useImportType)


[error] 3-3: Some named imports are only used as types.

This import is only used as a type.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.

(lint/style/useImportType)


[error] 100-100: Do not use template literals if interpolation and special-character handling are not needed.

Unsafe fix: Replace with string literal

(lint/style/noUnusedTemplateLiteral)

infrastructure/evault-provisioner/src/controllers/VerificationController.ts

[error] 16-19: This function expression can be turned into an arrow function.

Function expressions that don't use this can be turned into arrow functions.
Safe fix: Use an arrow function instead.

(lint/complexity/useArrowFunction)


[error] 25-25: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 46-46: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


[error] 2-2: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

🔇 Additional comments (32)
platforms/registry/package.json (1)

4-4: LGTM: Description update aligns with vault provisioning focus.

The updated description accurately reflects the service's role in managing vault entries, which is consistent with the PR objectives for evault provisioning.

infrastructure/eid-wallet/src/lib/ui/Button/ButtonAction.svelte (1)

109-109: LGTM: Consistent comment formatting.

Good practice to maintain consistent formatting by removing the extra space in the HTML comment.

infrastructure/evault-provisioner/tsconfig.json (2)

4-4: LGTM: Module system change supports Node.js backend.

Changing from ESNext to commonjs is appropriate for a Node.js backend service and aligns with TypeORM requirements.


14-15: LGTM: Decorator support enables TypeORM integration.

Adding experimental decorators and decorator metadata emission is essential for TypeORM entities and dependency injection, supporting the new verification services mentioned in the AI summary.

infrastructure/eid-wallet/src/routes/+layout.svelte (1)

105-105: LGTM! Layout changes support dynamic content well.

The addition of h-[100dvh] and overflow-scroll classes properly sets up the layout for full viewport height with scrolling capability, which aligns with the dynamic data-driven UI components mentioned in the summary.

infrastructure/eid-wallet/src/lib/utils/index.ts (1)

3-3: LGTM! Clean utility export addition.

The export follows the established pattern for utility re-exports and properly exposes the new capitalize function.

infrastructure/eid-wallet/src/lib/utils/capitalize.ts (1)

1-7: LGTM! Solid utility implementation with minor behavior note.

The capitalize function correctly handles the common use case of capitalizing words. Note that multiple consecutive spaces will be collapsed to single spaces due to the split/join operation, which is likely acceptable for UI text formatting purposes.

infrastructure/evault-provisioner/src/utils/eventEmitter.ts (1)

3-3: LGTM! Appropriate singleton pattern for event-driven communication.

The singleton EventEmitter instance is well-suited for facilitating real-time communication between the webhook endpoint and SSE clients in the verification flow.

infrastructure/eid-wallet/svelte.config.js (1)

12-14: LGTM! Environment configuration properly set for monorepo structure.

The env.dir configuration pointing to the project root ("../../") is appropriate for a monorepo setup and aligns with the new identity verification features that require environment variable access.

infrastructure/eid-wallet/src/lib/global/state.ts (2)

4-4: LGTM! Proper import added for VaultController.

The import follows the established pattern and supports the new vault management functionality.


27-27: LGTM! VaultController properly integrated into GlobalState.

The vaultController property and initialization follow the same consistent pattern as the existing securityController and userController. The integration maintains the singleton pattern and provides centralized access to vault operations.

Also applies to: 33-33

infrastructure/eid-wallet/package.json (1)

30-32: LGTM! Dependencies appropriately added for identity verification features.

The new dependencies support the comprehensive identity verification flow:

  • Veriff SDKs for identity verification services
  • axios for HTTP requests to backend APIs
  • dotenv for environment variable management
  • svelte-loading-spinners for UI feedback
  • uuid for unique identifier generation

These align well with the new verification functionality described in the PR.

Also applies to: 34-34, 37-40

infrastructure/evault-provisioner/src/migrations/1748966722767-migration.ts (1)

6-8: LGTM! Migration properly adds documentId column to verification table.

The migration correctly:

  • Adds a nullable documentId column of type character varying
  • Provides proper rollback in the down method
  • Follows TypeORM migration conventions

This supports the enhanced verification system that tracks document IDs associated with verifications.

Also applies to: 10-12

infrastructure/evault-provisioner/src/migrations/1748968097591-migration.ts (2)

6-8: Migration logic looks correct.

The addition of the consumed boolean column with NOT NULL DEFAULT false is well-implemented. This supports tracking whether verification records have been used, which aligns with the verification workflow described in the AI summary.


10-12: Proper rollback implementation.

The down migration correctly drops the added column, ensuring clean rollbacks.

infrastructure/evault-provisioner/package.json (4)

8-8: Development script change looks good.

The switch from tsx watch to ts-node-dev with --respawn --transpile-only flags is appropriate for TypeORM-based development, providing better compatibility and faster transpilation.


11-14: TypeORM migration scripts are well-configured.

The TypeORM scripts properly reference the database configuration file and follow standard conventions for migration management.


19-26: Dependencies align with verification workflow requirements.

The added dependencies support the new verification system:

  • cors: For cross-origin requests from the frontend
  • pg: PostgreSQL client for database operations
  • reflect-metadata: Required for TypeORM decorators
  • typeorm: ORM for database management

30-35: Development dependencies are appropriate.

The type definitions and ts-node-dev support the development workflow changes effectively.

infrastructure/eid-wallet/src/routes/(app)/ePassport/+page.svelte (2)

15-22: Good refactoring to dynamic data fetching.

The replacement of hardcoded dummy data with asynchronous fetching from the global state is a significant improvement. The pattern properly handles the async nature of data retrieval.


28-42: Conditional rendering prevents errors.

The conditional rendering based on data availability is well-implemented and prevents rendering errors when data is still loading or unavailable.

infrastructure/evault-provisioner/src/migrations/1748932757644-migration.ts (2)

7-7: Well-designed verification table schema.

The table schema is comprehensive and well-designed:

  • UUID primary key with auto-generation for distributed systems
  • JSONB data field for flexible verification data storage
  • Proper timestamp handling with automatic defaults
  • Optional fields appropriately defined

10-12: Clean rollback implementation.

The down migration properly drops the entire table, ensuring complete rollback capability.

infrastructure/eid-wallet/src/routes/(auth)/review/+page.svelte (2)

16-19: Excellent implementation of dynamic vault data loading.

The onMount function properly fetches vault data asynchronously and updates the ename state. This replaces hardcoded data with live vault information.


31-31: Good use of loading state for better UX.

The template literal with fallback text "Loading..." provides good user feedback while vault data is being fetched asynchronously.

infrastructure/evault-provisioner/src/config/database.ts (1)

9-17: Verify database connection security in production.

The database configuration looks appropriate. Ensure that in production environments:

  1. PROVISIONER_DATABASE_URL is properly secured and not logged
  2. The default fallback URL is only used in development
  3. Database credentials use proper authentication mechanisms
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (1)

3-42: Well-implemented async vault controller with good error handling.

The VaultController class provides a clean interface for managing vault data with the Tauri store. Key strengths:

  • Proper encapsulation with private store instance
  • Handles both direct values and promises in the setter
  • Comprehensive error handling with logging
  • Async getter that gracefully handles missing data

The static analysis errors appear to be false positives from the linter not correctly parsing TypeScript class property getter/setter syntax.

🧰 Tools
🪛 Biome (1.9.4)

[error] 13-13: expected ) but instead found ,

Remove ,

(parse)


[error] 15-15: expected a semicolon to end the class property, but found none

(parse)


[error] 15-15: expected a semicolon to end the class property, but found none

(parse)


[error] 15-15: expected a semicolon to end the class property, but found none

(parse)


[error] 15-15: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found ')'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 17-17: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '.'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 17-17: Expected a parameter but instead found '('.

Expected a parameter here.

(parse)


[error] 17-17: expected , but instead found resolvedUser

Remove resolvedUser

(parse)


[error] 17-17: Expected a class method body but instead found '=>'.

Expected a class method body here.

(parse)


[error] 18-18: expected a semicolon to end the class property, but found none

(parse)


[error] 18-18: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found '.'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 18-18: expected a semicolon to end the class property, but found none

(parse)


[error] 18-18: Expected an identifier, a string literal, a number literal, a private field name, or a computed name but instead found ')'.

Expected an identifier, a string literal, a number literal, a private field name, or a computed name here.

(parse)


[error] 19-20: Expected a statement but instead found ')
.catch((error) =>'.

Expected a statement here.

(parse)


[error] 22-22: Expected a statement but instead found ')'.

Expected a statement here.

(parse)


[error] 23-23: Expected a statement but instead found '} else'.

Expected a statement here.

(parse)


[error] 26-28: Expected a statement but instead found '}

get vault()'.

Expected a statement here.

(parse)


[error] 29-40: Illegal return statement outside of a function

(parse)


[error] 41-42: Expected a statement but instead found '}'.

Expected a statement here.

(parse)


[error] 15-15: Duplicate class member name "vault"

(lint/suspicious/noDuplicateClassMembers)


[error] 16-16: Duplicate class member name "vault"

(lint/suspicious/noDuplicateClassMembers)


[error] 18-18: Duplicate private class member "#store"

(syntax/correctness/noDuplicatePrivateClassMembers)


[error] 17-17: Do not add then to a class.

(lint/suspicious/noThenProperty)


[error] 20-22: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)


[error] 23-25: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)


[error] 28-41: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.

(lint/complexity/noUselessLoneBlockStatements)

infrastructure/eid-wallet/src/lib/fragments/IdentityCard/IdentityCard.svelte (2)

120-120: Good addition of capitalize class for better formatting.

The addition of the capitalize class improves the user experience by properly formatting field names in the ePassport variant.


113-113:

✅ Verification successful

Verify the removal of "@" prefix is intentional.

The userId display no longer includes the "@" prefix. Ensure this change aligns with the design requirements and doesn't break consistency with other parts of the application.


🏁 Script executed:

#!/bin/bash
# Search for other usages of userId to check consistency
rg -A 2 -B 2 "userId.*@" --type svelte

Length of output: 71


🏁 Script executed:

#!/bin/bash
# Search all .svelte files for occurrences of userId with surrounding context
rg --context 2 "userId" -g '*.svelte' -n

Length of output: 2875


No “@” prefix found for userId in codebase — removal is consistent

I searched every .svelte file for occurrences of userId paired with an “@” prefix and found none. All IdentityCard usages now pass the raw string (e.g. {ename}) without prepending “@”.

• No instances of @${userId} or similar patterns in any .svelte file
• All <IdentityCard> props use userId={…} directly

Since the change is consistent across the codebase, it’s safe to consider the “@” removal intentional and resolve this comment.

infrastructure/eid-wallet/src/routes/(app)/main/+page.svelte (1)

55-55: Good implementation of loading state for ename.

The fallback to "Loading..." while data is being fetched provides good user feedback.

platforms/registry/src/index.ts (1)

80-88: Good addition of the entropy endpoint with proper error handling.

The re-addition of the /entropy endpoint with improved formatting and consistent error handling enhances the API's functionality.

infrastructure/evault-provisioner/src/index.ts (1)

30-33:

❓ Verification inconclusive

Large payload limit may pose security risks

The 50MB limit for JSON and URL-encoded payloads is quite large and could be exploited for DoS attacks. Consider if this large limit is necessary for your use case.

What's the expected maximum size of verification data and documents? If significantly less than 50MB, consider reducing this limit to a more reasonable value.


🏁 Script executed:

#!/bin/bash
# Display initial portion of index.ts to understand endpoints and payload usage
sed -n '1,200p' infrastructure/evault-provisioner/src/index.ts

Length of output: 5330


🏁 Script executed:

#!/bin/bash
# Locate and display VerificationController to inspect routes and payload usage
FILE=$(fd 'VerificationController.ts' -u)
if [ -z "$FILE" ]; then
  echo "VerificationController.ts not found"
  exit 1
fi
echo "Found: $FILE"
sed -n '1,200p' "$FILE"

Length of output: 7414


Review payload limits in index.ts

The 50 MB limits for JSON and URL-encoded bodies (in infrastructure/evault-provisioner/src/index.ts lines 30–33) may be excessive and open the service to DoS via oversized payloads (e.g. base64-encoded images).

• Confirm your最大expected request size—for instance, the largest document or image you’ll send (typically well under 50 MB).
• If your real-world payloads are significantly smaller, reduce these limits to the minimum safe threshold (e.g. 5 MB).

Lines to adjust:

// Increase JSON payload limit
app.use(express.json({ limit: "50mb" }));
// Increase URL-encoded payload limit
app.use(express.urlencoded({ limit: "50mb", extended: true }));

Comment on lines +9 to +16
export function verifyHmacSignature(
body: Record<string, any>,
signature: string,
secret: string,
) {
const expectedSignature = createHmacSignature(body, secret);
return expectedSignature === signature;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve signature verification security and type safety.

Two improvements needed:

  1. Replace any type with unknown for better type safety
  2. Use timing-safe comparison to prevent timing attacks
 export function verifyHmacSignature(
-    body: Record<string, any>,
+    body: Record<string, unknown>,
     signature: string,
     secret: string,
 ) {
+    const crypto = require("node:crypto");
     const expectedSignature = createHmacSignature(body, secret);
-    return expectedSignature === signature;
+    return crypto.timingSafeEqual(
+        Buffer.from(expectedSignature, "hex"),
+        Buffer.from(signature, "hex")
+    );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function verifyHmacSignature(
body: Record<string, any>,
signature: string,
secret: string,
) {
const expectedSignature = createHmacSignature(body, secret);
return expectedSignature === signature;
}
export function verifyHmacSignature(
body: Record<string, unknown>,
signature: string,
secret: string,
) {
const crypto = require("node:crypto");
const expectedSignature = createHmacSignature(body, secret);
return crypto.timingSafeEqual(
Buffer.from(expectedSignature, "hex"),
Buffer.from(signature, "hex")
);
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 10-10: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

🤖 Prompt for AI Agents
In infrastructure/evault-provisioner/src/utils/hmac.ts around lines 9 to 16,
replace the type of the `body` parameter from `Record<string, any>` to
`Record<string, unknown>` to improve type safety. Additionally, change the
signature comparison from a simple equality check to a timing-safe comparison
method, such as using `crypto.timingSafeEqual`, to prevent timing attacks during
HMAC verification.

"flag-icons": "^7.3.2",
"tailwind-merge": "^3.0.2"
"import": "^0.0.6",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify the "import" package dependency.

The import package at version ^0.0.6 appears unusual and potentially problematic. This package name is very generic and the version suggests it might be outdated or incorrect.


🏁 Script executed:

#!/bin/bash
# Description: Check if the "import" package is legitimate and current
# Expected: Verify package exists, check its purpose, and validate version

# Check package info on npm
npm view import versions --json
npm view import description
npm view import repository

Length of output: 257


🏁 Script executed:

#!/bin/bash
# Search for any direct imports of the "import" package in the codebase
rg -n "require\(['\"]import['\"]" 
rg -n "from ['\"]import['\"] import"

Length of output: 82


🏁 Script executed:

#!/bin/bash
# Inspect the 'scripts' and 'bin' sections in infrastructure/eid-wallet/package.json
jq '{scripts, bin}' infrastructure/eid-wallet/package.json

Length of output: 717


Remove unused “import” dependency

The “import” package (v^0.0.6) isn’t referenced anywhere in your codebase or npm scripts, so it appears to be unused. Please either remove it from infrastructure/eid-wallet/package.json or document why it’s needed.

• File: infrastructure/eid-wallet/package.json
– Line with "import": "^0.0.6"

🤖 Prompt for AI Agents
In infrastructure/eid-wallet/package.json at line 36, the "import" package
dependency with version "^0.0.6" is not used anywhere in the codebase or npm
scripts. Remove this dependency line from the package.json file to clean up
unused packages, unless there is a specific documented reason to keep it.

usedStorage={15}
totalStorage={100}
/>
<IdentityCard variant="eVault" usedStorage={15} totalStorage={100} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use dynamic vault data instead of hardcoded values.

The eVault component still uses static storage values (15, 100) while other components have been updated to use dynamic data. This creates inconsistency.

-    <IdentityCard variant="eVault" usedStorage={15} totalStorage={100} />
+    <IdentityCard variant="eVault" usedStorage={vaultData?.usedStorage ?? 0} totalStorage={vaultData?.totalStorage ?? 100} />

You'll need to make the vault data available in the component scope.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<IdentityCard variant="eVault" usedStorage={15} totalStorage={100} />
<IdentityCard
variant="eVault"
usedStorage={vaultData?.usedStorage ?? 0}
totalStorage={vaultData?.totalStorage ?? 100}
/>
🤖 Prompt for AI Agents
In infrastructure/eid-wallet/src/routes/(app)/main/+page.svelte at line 68,
replace the hardcoded storage values (15 and 100) passed to the IdentityCard
component with dynamic vault data available in the component's scope. Ensure
that the dynamic values for usedStorage and totalStorage are properly fetched or
passed into the component so the IdentityCard reflects current vault storage
information consistently with other components.

export class VerificationController {
constructor(private readonly verificationService: VerificationService) {}

registerRoutes(app: any) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace any type with proper Express type

Use proper typing instead of any for better type safety.

-    registerRoutes(app: any) {
+    registerRoutes(app: Express.Application) {

Add the import at the top:

import type { Application } from "express";
🧰 Tools
🪛 Biome (1.9.4)

[error] 25-25: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

🤖 Prompt for AI Agents
In infrastructure/evault-provisioner/src/controllers/VerificationController.ts
at line 25, replace the parameter type 'any' in the registerRoutes method with
the proper Express type 'Application'. Import 'Application' from 'express' at
the top of the file using 'import type { Application } from "express";' and
update the method signature to use 'app: Application' for better type safety.

Comment on lines +46 to +49
const handler = (data: any) => {
console.log("hi?");
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove debug console.log and fix type

Remove debug statement and add proper typing.

-                const handler = (data: any) => {
-                    console.log("hi?");
+                const handler = (data: Record<string, any>) => {
                     res.write(`data: ${JSON.stringify(data)}\n\n`);
                 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handler = (data: any) => {
console.log("hi?");
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
const handler = (data: Record<string, any>) => {
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
🧰 Tools
🪛 Biome (1.9.4)

[error] 46-46: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

🤖 Prompt for AI Agents
In infrastructure/evault-provisioner/src/controllers/VerificationController.ts
between lines 46 and 49, remove the debug console.log statement "hi?" and
replace the parameter type of the handler function from any to a more specific
type that matches the expected data structure being handled. This improves code
cleanliness and type safety.

Comment on lines +161 to +185
app.patch("/verification/:id", async (req: Request, res: Response) => {
const verification = await this.verificationService.findById(
req.params.id,
);
const body = {
verification: {
status: "submitted",
},
};
const signature = createHmacSignature(
body,
process.env.VERIFF_HMAC_KEY as string,
);
await veriffClient.patch(
`/v1/sessions/${verification?.veriffId}`,
body,
{
headers: {
"X-HMAC-SIGNATURE": signature,
"X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
},
},
);
res.sendStatus(201);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null check for verification

The endpoint uses optional chaining but doesn't handle the case where verification is not found.

 app.patch("/verification/:id", async (req: Request, res: Response) => {
     const verification = await this.verificationService.findById(
         req.params.id,
     );
+    
+    if (!verification) {
+        return res.status(404).json({ error: "Verification not found" });
+    }
+    
     const body = {
         verification: {
             status: "submitted",
         },
     };
     const signature = createHmacSignature(
         body,
         process.env.VERIFF_HMAC_KEY as string,
     );
-    await veriffClient.patch(
-        `/v1/sessions/${verification?.veriffId}`,
+    
+    try {
+        await veriffClient.patch(
+            `/v1/sessions/${verification.veriffId}`,
             body,
             {
                 headers: {
                     "X-HMAC-SIGNATURE": signature,
                     "X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
                 },
             },
         );
         res.sendStatus(201);
+    } catch (error) {
+        console.error("Failed to update verification status:", error);
+        return res.status(500).json({ error: "Failed to update verification status" });
+    }
 });
🤖 Prompt for AI Agents
In infrastructure/evault-provisioner/src/controllers/VerificationController.ts
around lines 161 to 185, the code uses optional chaining on verification but
does not handle the case when verification is null or undefined. Add a null
check after fetching verification; if it is not found, respond with an
appropriate error status (e.g., 404) and message, and only proceed with the
patch request if verification exists.

Comment on lines 187 to 236
// Webhook for verification decisions
app.post(
"/verification/decisions",
async (req: Request, res: Response) => {
const body = req.body;
console.log(body);
const id = body.vendorData;

const verification =
await this.verificationService.findById(id);
if (!verification) {
return res
.status(404)
.json({ error: "Verification not found" });
}

const affirmativeStatusTypes = [
"approved",
"declined",
"expired",
"abandoned",
];
if (
affirmativeStatusTypes.includes(
body.data.verification.decision,
)
) {
const approved =
body.data.verification.decision === "approved";
await this.verificationService.findByIdAndUpdate(id, {
approved,
data: {
person: body.data.verification.person,
document: body.data.verification.document,
},
documentId:
body.data.verification.document.number.value,
});
}

eventEmitter.emit(id, {
reason: body.data.verification.reason,
status: body.data.verification.decision,
person: body.data.verification.person ?? null,
document: body.data.verification.document,
});

return res.json({ success: true });
},
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Add HMAC signature verification for webhook security

The webhook endpoint lacks HMAC signature verification, which is critical for ensuring the authenticity of webhook calls from Veriff. This is a security vulnerability that could allow unauthorized parties to manipulate verification decisions.

Additionally, remove the debug console.log statement.

 app.post(
     "/verification/decisions",
     async (req: Request, res: Response) => {
+        // Verify HMAC signature
+        const signature = req.headers['x-hmac-signature'] as string;
+        if (!signature) {
+            return res.status(401).json({ error: "Missing signature" });
+        }
+        
+        const expectedSignature = createHmacSignature(
+            req.body,
+            process.env.VERIFF_WEBHOOK_SECRET as string
+        );
+        
+        if (signature !== expectedSignature) {
+            return res.status(401).json({ error: "Invalid signature" });
+        }
+        
         const body = req.body;
-        console.log(body);
         const id = body.vendorData;

         const verification =
             await this.verificationService.findById(id);
         if (!verification) {
             return res
                 .status(404)
                 .json({ error: "Verification not found" });
         }
         
         // ... rest of the code

Verify that Veriff sends HMAC signatures with their webhooks:


🌐 Web query:

Does Veriff API send HMAC signatures in webhook headers for verification decision webhooks?

💡 Result:

Yes, Veriff's API includes HMAC signatures in the headers of verification decision webhooks. These signatures are provided in the X-HMAC-SIGNATURE header, allowing you to verify the authenticity and integrity of the webhook payloads. (developers.veriff.com)

To validate the webhook requests:

  1. Extract the Signature and Timestamp: Retrieve the X-HMAC-SIGNATURE header from the incoming request. This header contains the timestamp and the HMAC signature, formatted as t=<timestamp>,s=<signature>.

  2. Prepare the Payload: Concatenate the timestamp and the request body, separated by a dot (.). For example, if the timestamp is 1582267948 and the request body is {"verification": {"status": "approved"}}, the payload would be 1582267948.{"verification": {"status": "approved"}}.

  3. Generate the Expected Signature: Use your shared secret key to compute an HMAC-SHA256 hash of the prepared payload. This can be done using cryptographic libraries available in your programming language.

  4. Compare the Signatures: Compare the computed HMAC signature with the one extracted from the X-HMAC-SIGNATURE header. If they match, the request is authentic and has not been tampered with.

For detailed information and code examples on verifying webhook signatures, refer to Veriff's developer documentation. (developers.veriff.com)

Citations:


Implement HMAC-SHA256 webhook signature verification

Ensure that only genuine Veriff webhooks are processed by:

  • Removing the debug console.log(body).
  • Extracting and parsing the X-HMAC-SIGNATURE header (t=<timestamp>,s=<signature>).
  • Concatenating <timestamp>.<JSON-stringified body>, computing an HMAC-SHA256 hash with your VERIFF_WEBHOOK_SECRET, and comparing it to the provided signature.
  • Returning HTTP 401 on missing or invalid signatures.
  • (Optional) Enforcing a maximum age on the timestamp (e.g. 5 minutes) to mitigate replay attacks.

Apply the following diff in
infrastructure/evault-provisioner/src/controllers/VerificationController.ts (around lines 187–236):

@@ -187,6 +187,24 @@ app.post(
     "/verification/decisions",
     async (req: Request, res: Response) => {
+        // HMAC signature verification (t=<timestamp>,s=<signature>)
+        const signatureHeader = req.headers['x-hmac-signature'] as string;
+        if (!signatureHeader) {
+            return res.status(401).json({ error: "Missing signature" });
+        }
+        const parts = signatureHeader.split(',');
+        const timestamp = parts[0].split('=')[1];
+        const signature = parts[1].split('=')[1];
+
+        // Optional: reject if timestamp is too old
+        // const age = Date.now()/1000 - Number(timestamp);
+        // if (age > 300) return res.status(401).json({ error: "Stale request" });
+
+        const payload = `${timestamp}.${JSON.stringify(req.body)}`;
+        const expected = crypto
+            .createHmac('sha256', process.env.VERIFF_WEBHOOK_SECRET!)
+            .update(payload)
+            .digest('hex');
+        if (signature !== expected) {
+            return res.status(401).json({ error: "Invalid signature" });
+        }
+
         const body = req.body;
-        console.log(body);
         const id = body.vendorData;

         const verification =
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Webhook for verification decisions
app.post(
"/verification/decisions",
async (req: Request, res: Response) => {
const body = req.body;
console.log(body);
const id = body.vendorData;
const verification =
await this.verificationService.findById(id);
if (!verification) {
return res
.status(404)
.json({ error: "Verification not found" });
}
const affirmativeStatusTypes = [
"approved",
"declined",
"expired",
"abandoned",
];
if (
affirmativeStatusTypes.includes(
body.data.verification.decision,
)
) {
const approved =
body.data.verification.decision === "approved";
await this.verificationService.findByIdAndUpdate(id, {
approved,
data: {
person: body.data.verification.person,
document: body.data.verification.document,
},
documentId:
body.data.verification.document.number.value,
});
}
eventEmitter.emit(id, {
reason: body.data.verification.reason,
status: body.data.verification.decision,
person: body.data.verification.person ?? null,
document: body.data.verification.document,
});
return res.json({ success: true });
},
);
// Webhook for verification decisions
app.post(
"/verification/decisions",
async (req: Request, res: Response) => {
+ // HMAC signature verification (t=<timestamp>,s=<signature>)
+ const signatureHeader = req.headers['x-hmac-signature'] as string;
+ if (!signatureHeader) {
+ return res.status(401).json({ error: "Missing signature" });
+ }
+ const parts = signatureHeader.split(',');
+ const timestamp = parts[0].split('=')[1];
+ const signature = parts[1].split('=')[1];
+
+ // Optional: reject if timestamp is too old
+ // const age = Date.now()/1000 - Number(timestamp);
+ // if (age > 300) return res.status(401).json({ error: "Stale request" });
+
+ const payload = `${timestamp}.${JSON.stringify(req.body)}`;
+ const expected = crypto
+ .createHmac('sha256', process.env.VERIFF_WEBHOOK_SECRET!)
+ .update(payload)
+ .digest('hex');
+ if (signature !== expected) {
+ return res.status(401).json({ error: "Invalid signature" });
+ }
+
const body = req.body;
- console.log(body);
const id = body.vendorData;
const verification =
await this.verificationService.findById(id);
if (!verification) {
return res
.status(404)
.json({ error: "Verification not found" });
}
const affirmativeStatusTypes = [
"approved",
"declined",
"expired",
"abandoned",
];
if (
affirmativeStatusTypes.includes(
body.data.verification.decision,
)
) {
const approved =
body.data.verification.decision === "approved";
await this.verificationService.findByIdAndUpdate(id, {
approved,
data: {
person: body.data.verification.person,
document: body.data.verification.document,
},
documentId:
body.data.verification.document.number.value,
});
}
eventEmitter.emit(id, {
reason: body.data.verification.reason,
status: body.data.verification.decision,
person: body.data.verification.person ?? null,
document: body.data.verification.document,
});
return res.json({ success: true });
},
);
🤖 Prompt for AI Agents
In infrastructure/evault-provisioner/src/controllers/VerificationController.ts
around lines 187 to 236, remove the debug console.log statement and implement
HMAC-SHA256 verification for the webhook. Extract the X-HMAC-SIGNATURE header,
parse out the timestamp and signature, then concatenate the timestamp and the
raw JSON string of the request body separated by a dot. Compute the HMAC-SHA256
hash of this concatenated string using the VERIFF_WEBHOOK_SECRET environment
variable and compare it to the signature from the header. If the signature is
missing or invalid, respond with HTTP 401 Unauthorized. Optionally, validate
that the timestamp is recent (e.g., within 5 minutes) to prevent replay attacks
before processing the webhook logic.

Comment on lines +67 to +103
app.post(
"/verification/:id/media",
async (req: Request, res: Response) => {
const { img, type } = req.body;
const types = ["document-front", "document-back", "face"];
if (!types.includes(type))
throw new Error(
`Wrong type specified, accepted types are ${types}`,
);
const verification = await this.verificationService.findById(
req.params.id,
);
if (!verification) throw new Error("Verification not found");
const veriffBody = {
image: {
context: type,
content: img,
},
};

const signature = createHmacSignature(
veriffBody,
process.env.VERIFF_HMAC_KEY as string,
);
await veriffClient.post(
`/v1/sessions/${verification.veriffId}/media`,
veriffBody,
{
headers: {
"X-HMAC-SIGNATURE": signature,
"X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
},
},
);
res.sendStatus(201);
},
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Improve error handling and add validation

The endpoint throws errors instead of returning proper HTTP responses, and lacks validation for the image content.

 app.post(
     "/verification/:id/media",
     async (req: Request, res: Response) => {
         const { img, type } = req.body;
+        
+        if (!img || typeof img !== 'string') {
+            return res.status(400).json({ error: "Invalid or missing image data" });
+        }
+        
         const types = ["document-front", "document-back", "face"];
         if (!types.includes(type))
-            throw new Error(
-                `Wrong type specified, accepted types are ${types}`,
-            );
+            return res.status(400).json({ 
+                error: `Wrong type specified, accepted types are ${types.join(", ")}`
+            });
+            
         const verification = await this.verificationService.findById(
             req.params.id,
         );
-        if (!verification) throw new Error("Verification not found");
+        if (!verification) {
+            return res.status(404).json({ error: "Verification not found" });
+        }
+        
+        const hmacKey = process.env.VERIFF_HMAC_KEY;
+        const authClient = process.env.PUBLIC_VERIFF_KEY;
+        
+        if (!hmacKey || !authClient) {
+            console.error("Missing Veriff configuration");
+            return res.status(500).json({ error: "Server configuration error" });
+        }
+        
         const veriffBody = {
             image: {
                 context: type,
                 content: img,
             },
         };

         const signature = createHmacSignature(
             veriffBody,
-            process.env.VERIFF_HMAC_KEY as string,
+            hmacKey,
         );
-        await veriffClient.post(
-            `/v1/sessions/${verification.veriffId}/media`,
-            veriffBody,
-            {
-                headers: {
-                    "X-HMAC-SIGNATURE": signature,
-                    "X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
+        
+        try {
+            await veriffClient.post(
+                `/v1/sessions/${verification.veriffId}/media`,
+                veriffBody,
+                {
+                    headers: {
+                        "X-HMAC-SIGNATURE": signature,
+                        "X-AUTH-CLIENT": authClient,
+                    },
                 },
-            },
-        );
-        res.sendStatus(201);
+            );
+            res.sendStatus(201);
+        } catch (error) {
+            console.error("Failed to upload media to Veriff:", error);
+            return res.status(500).json({ error: "Failed to upload media" });
+        }
     },
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.post(
"/verification/:id/media",
async (req: Request, res: Response) => {
const { img, type } = req.body;
const types = ["document-front", "document-back", "face"];
if (!types.includes(type))
throw new Error(
`Wrong type specified, accepted types are ${types}`,
);
const verification = await this.verificationService.findById(
req.params.id,
);
if (!verification) throw new Error("Verification not found");
const veriffBody = {
image: {
context: type,
content: img,
},
};
const signature = createHmacSignature(
veriffBody,
process.env.VERIFF_HMAC_KEY as string,
);
await veriffClient.post(
`/v1/sessions/${verification.veriffId}/media`,
veriffBody,
{
headers: {
"X-HMAC-SIGNATURE": signature,
"X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
},
},
);
res.sendStatus(201);
},
);
app.post(
"/verification/:id/media",
async (req: Request, res: Response) => {
const { img, type } = req.body;
if (!img || typeof img !== 'string') {
return res.status(400).json({ error: "Invalid or missing image data" });
}
const types = ["document-front", "document-back", "face"];
if (!types.includes(type)) {
return res.status(400).json({
error: `Wrong type specified, accepted types are ${types.join(", ")}`
});
}
const verification = await this.verificationService.findById(
req.params.id,
);
if (!verification) {
return res.status(404).json({ error: "Verification not found" });
}
const hmacKey = process.env.VERIFF_HMAC_KEY;
const authClient = process.env.PUBLIC_VERIFF_KEY;
if (!hmacKey || !authClient) {
console.error("Missing Veriff configuration");
return res.status(500).json({ error: "Server configuration error" });
}
const veriffBody = {
image: {
context: type,
content: img,
},
};
const signature = createHmacSignature(
veriffBody,
hmacKey,
);
try {
await veriffClient.post(
`/v1/sessions/${verification.veriffId}/media`,
veriffBody,
{
headers: {
"X-HMAC-SIGNATURE": signature,
"X-AUTH-CLIENT": authClient,
},
},
);
res.sendStatus(201);
} catch (error) {
console.error("Failed to upload media to Veriff:", error);
return res.status(500).json({ error: "Failed to upload media" });
}
},
);
🤖 Prompt for AI Agents
In infrastructure/evault-provisioner/src/controllers/VerificationController.ts
between lines 67 and 103, the endpoint currently throws errors directly and does
not validate the image content. Refactor the code to catch errors and respond
with appropriate HTTP status codes and messages instead of throwing exceptions.
Add validation to ensure the 'img' field is present and correctly formatted
before proceeding. Use try-catch blocks around the async logic and send
meaningful error responses to the client.

coderabbitai bot added a commit that referenced this pull request Jun 3, 2025
Docstrings generation was requested by @coodos.

* #188 (comment)

The following files were modified:

* `infrastructure/eid-wallet/src/lib/utils/capitalize.ts`
* `infrastructure/evault-provisioner/src/utils/hmac.ts`
Copy link
Contributor

coderabbitai bot commented Jun 3, 2025

Note

Generated docstrings for this pull request at #189

Docstrings generation was requested by @coodos.

* #188 (comment)

The following files were modified:

* `infrastructure/eid-wallet/src/lib/utils/capitalize.ts`
* `infrastructure/evault-provisioner/src/utils/hmac.ts`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@coodos coodos merged commit 7ffc9ff into main Jun 3, 2025
0 of 3 checks passed
@coodos coodos deleted the feat/evault-provisioning-via-phone branch June 3, 2025 20:20
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (9)
infrastructure/eid-wallet/src/routes/(auth)/verify/+page.svelte (4)

17-17: Fix typo in import name

The import verificaitonId contains a typo and should be verificationId.

-        verificaitonId,
+        verificationId,

33-40: Add error handling for verification initiation

The function lacks error handling for the HTTP request and still uses the typo verificaitonId, both of which were flagged in previous reviews.

 async function handleVerification() {
+    try {
         const { data } = await axios.post(
             new URL("/verification", PUBLIC_PROVISIONER_URL).toString(),
         );
-        verificaitonId.set(data.id);
+        verificationId.set(data.id);
         showVeriffModal = true;
         watchEventStream(data.id);
+    } catch (error) {
+        console.error("Failed to initiate verification:", error);
+        status.set("error");
+        reason.set("Failed to initiate verification. Please try again.");
+        showVeriffModal = true;
+    }
 }

42-67: Remove console.log statements and add error handling

The function still contains debug console.log statements and lacks error handling for EventSource failures, as previously flagged.

 function watchEventStream(id: string) {
     const sseUrl = new URL(
         `/verification/sessions/${id}`,
         PUBLIC_PROVISIONER_URL,
     ).toString();
     const eventSource = new EventSource(sseUrl);

     eventSource.onopen = function (e) {
-        console.log("Successfully connected.");
+        // Connection established
     };

     eventSource.onmessage = function (e) {
         const data = JSON.parse(e.data);
-        if (!data.status) console.log(data);
-        console.log("STATUS", data);
         status.set(data.status);
         reason.set(data.reason);
         person = data.person;
         document = data.document;
         if (data.status === "resubmission_requested") {
             DocFront.set(null);
             Selfie.set(null);
         }
         verifStep.set(2);
     };
+
+    eventSource.onerror = function (error) {
+        console.error("SSE connection error:", error);
+        eventSource.close();
+        // Consider showing error to user
+        status.set("error");
+        reason.set("Connection error. Please try again.");
+    };
+
+    return eventSource;
 }

71-120: Add comprehensive error handling and resource cleanup

Multiple issues remain unresolved from previous reviews: missing error handling for API calls, hardcoded timeout, typo in variable name, and lack of resource cleanup.

+    let eventSource: EventSource | null = null;
+    let navigationTimeout: ReturnType<typeof setTimeout> | null = null;
+    const NAVIGATION_DELAY = 10_000;

     onMount(() => {
         globalState = getContext<() => GlobalState>("globalState")();
         
         handleContinue = async () => {
             if ($status !== "approved") return verifStep.set(0);
             if (!globalState) throw new Error("Global state is not defined");

             loading = true;
+            try {
                 globalState.userController.user = {
                     name: capitalize(
                         person.firstName.value + " " + person.lastName.value,
                     ),
                     "Date of Birth": new Date(
                         person.dateOfBirth.value,
                     ).toDateString(),
                     "ID submitted": "Passport - " + person.nationality.value,
                     "Passport Number": document.number.value,
                 };
                 globalState.userController.document = {
                     "Valid From": new Date(document.validFrom.value).toDateString(),
                     "Valid Until": new Date(
                         document.validUntil.value,
                     ).toDateString(),
                     "Verified On": new Date().toDateString(),
                 };
                 const {
                     data: { token: registryEntropy },
                 } = await axios.get(
                     new URL("/entropy", PUBLIC_REGISTRY_URL).toString(),
                 );
                 const { data } = await axios.post(
                     new URL("/provision", PUBLIC_PROVISIONER_URL).toString(),
                     {
                         registryEntropy,
                         namespace: uuidv4(),
-                        verificationId: $verificaitonId,
+                        verificationId: $verificationId,
                     },
                 );
                 if (data.success === true) {
                     globalState.vaultController.vault = {
                         uri: data.uri,
                         ename: data.w3id,
                     };
                 }
-                setTimeout(() => {
+                navigationTimeout = setTimeout(() => {
                     goto("/register");
-                }, 10_000);
+                }, NAVIGATION_DELAY);
+            } catch (error) {
+                console.error("Failed to complete verification:", error);
+                loading = false;
+                status.set("error");
+                reason.set("Failed to complete verification. Please try again.");
+            }
         };
+
+        // Update watchEventStream call
+        // In handleVerification function, store the returned EventSource:
+        // eventSource = watchEventStream(data.id);
+
+        return () => {
+            // Cleanup on component destroy
+            if (eventSource) {
+                eventSource.close();
+            }
+            if (navigationTimeout) {
+                clearTimeout(navigationTimeout);
+            }
+        };
     });
infrastructure/evault-provisioner/src/controllers/VerificationController.ts (5)

25-25: Replace any type with proper Express type

Use proper typing instead of any for better type safety.

-    registerRoutes(app: any) {
+    registerRoutes(app: Application) {

Add the import at the top:

import type { Application } from "express";
🧰 Tools
🪛 Biome (1.9.4)

[error] 25-25: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


46-49: Remove debug console.log and fix type

Remove debug statement and add proper typing.

-                const handler = (data: any) => {
-                    console.log("hi?");
+                const handler = (data: Record<string, any>) => {
                     res.write(`data: ${JSON.stringify(data)}\n\n`);
                 };
🧰 Tools
🪛 Biome (1.9.4)

[error] 46-46: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


67-103: Improve error handling and add validation

The endpoint throws errors instead of returning proper HTTP responses, and lacks validation for the image content.

 app.post(
     "/verification/:id/media",
     async (req: Request, res: Response) => {
         const { img, type } = req.body;
+        
+        if (!img || typeof img !== 'string') {
+            return res.status(400).json({ error: "Invalid or missing image data" });
+        }
+        
         const types = ["document-front", "document-back", "face"];
         if (!types.includes(type))
-            throw new Error(
-                `Wrong type specified, accepted types are ${types}`,
-            );
+            return res.status(400).json({ 
+                error: `Wrong type specified, accepted types are ${types.join(", ")}`
+            });
+            
         const verification = await this.verificationService.findById(
             req.params.id,
         );
-        if (!verification) throw new Error("Verification not found");
+        if (!verification) {
+            return res.status(404).json({ error: "Verification not found" });
+        }

161-185: Add null check for verification

The endpoint uses optional chaining but doesn't handle the case where verification is not found.

 app.patch("/verification/:id", async (req: Request, res: Response) => {
     const verification = await this.verificationService.findById(
         req.params.id,
     );
+    
+    if (!verification) {
+        return res.status(404).json({ error: "Verification not found" });
+    }
+    
     const body = {
         verification: {
             status: "submitted",
         },
     };
     const signature = createHmacSignature(
         body,
         process.env.VERIFF_HMAC_KEY as string,
     );
-    await veriffClient.patch(
-        `/v1/sessions/${verification?.veriffId}`,
+    
+    try {
+        await veriffClient.patch(
+            `/v1/sessions/${verification.veriffId}`,
             body,
             {
                 headers: {
                     "X-HMAC-SIGNATURE": signature,
                     "X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
                 },
             },
         );
         res.sendStatus(201);
+    } catch (error) {
+        console.error("Failed to update verification status:", error);
+        return res.status(500).json({ error: "Failed to update verification status" });
+    }
 });

187-253: Implement HMAC-SHA256 webhook signature verification

The webhook endpoint lacks HMAC signature verification and contains debug logging.

 app.post(
     "/verification/decisions",
     async (req: Request, res: Response) => {
+        // HMAC signature verification (t=<timestamp>,s=<signature>)
+        const signatureHeader = req.headers['x-hmac-signature'] as string;
+        if (!signatureHeader) {
+            return res.status(401).json({ error: "Missing signature" });
+        }
+        const parts = signatureHeader.split(',');
+        const timestamp = parts[0].split('=')[1];
+        const signature = parts[1].split('=')[1];
+
+        const payload = `${timestamp}.${JSON.stringify(req.body)}`;
+        const expected = crypto
+            .createHmac('sha256', process.env.VERIFF_WEBHOOK_SECRET!)
+            .update(payload)
+            .digest('hex');
+        if (signature !== expected) {
+            return res.status(401).json({ error: "Invalid signature" });
+        }
+
         const body = req.body;
-        console.log(body);
         const id = body.vendorData;

Also add the crypto import at the top:

import crypto from 'crypto';
🧹 Nitpick comments (5)
infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (1)

47-49: Enhance the delete button with better UX patterns

While the ButtonAction implementation is correct, consider improving the user experience:

  1. Visual distinction - Use a destructive variant/styling
  2. Better placement - Consider separating from other settings
  3. Loading state - Show loading during deletion process
-    <ButtonAction class="mt-5 w-full" callback={nukeWallet}
-        >Delete Account</ButtonAction
-    >
+    <div class="mt-8 pt-4 border-t border-gray-200">
+        <ButtonAction 
+            class="w-full bg-red-600 hover:bg-red-700 text-white" 
+            callback={nukeWallet}
+            disabled={isDeleting}
+        >
+            {isDeleting ? 'Deleting...' : 'Delete Account'}
+        </ButtonAction>
+    </div>

Note: You'll need to add an isDeleting reactive variable to track the deletion state.

infrastructure/eid-wallet/src/routes/(auth)/verify/+page.svelte (1)

138-180: Consider adding loading state management for verification steps

The template handles different verification states well, but consider adding loading indicators for individual verification steps to improve user experience.

     <Drawer bind:isPaneOpen={showVeriffModal}>
         {#if $verifStep === 0}
             <Passport></Passport>
         {:else if $verifStep === 1}
             <Selfie></Selfie>
         {:else if loading}
             <div class="my-20">
                 <div
                     class="align-center flex w-full flex-col items-center justify-center gap-6"
                 >
                     <Shadow size={40} color="rgb(142, 82, 255);" />
                     <h3>Generating your eName</h3>
                 </div>
             </div>
         {:else}
             <div class="flex flex-col gap-6">
                 {#if $status === "approved"}
                     <div>
                         <h3>Your verification was a success</h3>
                         <p>You can now continue on to create your eName</p>
                     </div>
                 {:else if $status === "resubmission_requested"}
                     <h3>Your verification failed due to the reason</h3>
                     <p>{$reason}</p>
+                {:else if $status === "error"}
+                    <h3>An error occurred</h3>
+                    <p>{$reason}</p>
                 {:else}
                     <h3>Your verification failed</h3>
                     <p>{$reason}</p>
                 {/if}
             </div>
infrastructure/evault-provisioner/src/controllers/VerificationController.ts (3)

1-2: Use import type for type-only imports

The imports for Request, Response, and VerificationService are only used as types, not runtime values.

-import { Request, Response } from "express";
-import { VerificationService } from "../services/VerificationService";
+import type { Request, Response } from "express";
+import type { VerificationService } from "../services/VerificationService";
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


[error] 2-2: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


12-20: Simplify redundant response interceptor

The response interceptor doesn't add any value - it just returns the response or rejects with the same error.

-veriffClient.interceptors.response.use(
-    (response) => {
-        return response;
-    },
-    async function (error) {
-        if (!error.response) return Promise.reject(error);
-        return Promise.reject(error);
-    },
-);

Consider removing this interceptor entirely or adding meaningful error handling/logging if needed.

🧰 Tools
🪛 Biome (1.9.4)

[error] 16-19: This function expression can be turned into an arrow function.

Function expressions that don't use this can be turned into arrow functions.
Safe fix: Use an arrow function instead.

(lint/complexity/useArrowFunction)


222-225: Remove debug logging from production code

Debug console.log statements should be removed from production code.

                        const verificationMatch =
                            await this.verificationService.findOne({
                                documentId:
                                body.data.verification.document.number.value
                            });
-                        console.log("matched", verificationMatch)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c645a19 and 5992cac.

📒 Files selected for processing (3)
  • infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/verify/+page.svelte (1 hunks)
  • infrastructure/evault-provisioner/src/controllers/VerificationController.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
infrastructure/evault-provisioner/src/controllers/VerificationController.ts

[error] 16-19: This function expression can be turned into an arrow function.

Function expressions that don't use this can be turned into arrow functions.
Safe fix: Use an arrow function instead.

(lint/complexity/useArrowFunction)


[error] 25-25: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 46-46: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 1-1: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)


[error] 2-2: All these imports are only used as types.

Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.

(lint/style/useImportType)

🔇 Additional comments (4)
infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte (4)

2-14: LGTM - Clean import organization

The imports are well-organized and include all necessary dependencies for the settings page functionality.


16-16: LGTM - Proper global state access

Using Svelte's context to access global state follows the established pattern mentioned in the AI summary.


24-26: LGTM - Standard page title setup

The effect properly sets the page title in the runtime header.


31-45: LGTM - Well-structured navigation buttons

The settings navigation buttons are properly implemented with appropriate icons and routes.

Comment on lines +18 to +22
function nukeWallet() {
globalState.userController.user = null;
globalState.securityController.clearPin();
goto("/onboarding");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add user confirmation and error handling for account deletion

The nukeWallet function immediately deletes user data without confirmation, which could lead to accidental data loss. Consider implementing safety measures:

  1. User confirmation dialog - Require explicit confirmation before deletion
  2. Error handling - Handle potential failures in state clearing
  3. Async operation - Consider if backend cleanup is needed
-    function nukeWallet() {
-        globalState.userController.user = null;
-        globalState.securityController.clearPin();
-        goto("/onboarding");
-    }
+    async function nukeWallet() {
+        const confirmed = confirm("Are you sure you want to delete your account? This action cannot be undone.");
+        if (!confirmed) return;
+        
+        try {
+            globalState.userController.user = null;
+            globalState.securityController.clearPin();
+            // Add any additional cleanup operations here
+            goto("/onboarding");
+        } catch (error) {
+            console.error("Failed to delete account:", error);
+            // Show error message to user
+        }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function nukeWallet() {
globalState.userController.user = null;
globalState.securityController.clearPin();
goto("/onboarding");
}
async function nukeWallet() {
const confirmed = confirm("Are you sure you want to delete your account? This action cannot be undone.");
if (!confirmed) return;
try {
globalState.userController.user = null;
globalState.securityController.clearPin();
// Add any additional cleanup operations here
goto("/onboarding");
} catch (error) {
console.error("Failed to delete account:", error);
// Show error message to user
}
}
🤖 Prompt for AI Agents
In infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte around lines
18 to 22, the nukeWallet function deletes user data immediately without
confirmation or error handling. Modify the function to first show a user
confirmation dialog and proceed only if confirmed. Add try-catch blocks to
handle any errors during user state clearing and securityController.clearPin
calls. If backend cleanup is required, make the function async and await the
necessary asynchronous operations before navigating to the onboarding page.

Comment on lines +118 to +159
app.post("/verification", async (req: Request, res: Response) => {
const { referenceId } = req.body;

if (referenceId) {
const existing = await this.verificationService.findOne({
referenceId,
});
if (existing) {
return res
.status(409)
.json({ error: "Reference ID Already Exists" });
}
}

const verification = await this.verificationService.create({
referenceId,
});
const veriffBody = {
verification: {
vendorData: verification.id,
},
};
const signature = createHmacSignature(
veriffBody,
process.env.VERIFF_HMAC_KEY as string,
);
const { data: veriffSession } = await veriffClient.post(
"/v1/sessions",
veriffBody,
{
headers: {
"X-HMAC-SIGNATURE": signature,
"X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
},
},
);
await this.verificationService.findByIdAndUpdate(verification.id, {
veriffId: veriffSession.verification.id,
});

return res.status(201).json(verification);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for external API calls

The verification creation endpoint lacks proper error handling for the Veriff API call.

-            const { data: veriffSession } = await veriffClient.post(
-                "/v1/sessions",
-                veriffBody,
-                {
-                    headers: {
-                        "X-HMAC-SIGNATURE": signature,
-                        "X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
-                    },
-                },
-            );
-            await this.verificationService.findByIdAndUpdate(verification.id, {
-                veriffId: veriffSession.verification.id,
-            });
+            try {
+                const { data: veriffSession } = await veriffClient.post(
+                    "/v1/sessions",
+                    veriffBody,
+                    {
+                        headers: {
+                            "X-HMAC-SIGNATURE": signature,
+                            "X-AUTH-CLIENT": process.env.PUBLIC_VERIFF_KEY,
+                        },
+                    },
+                );
+                await this.verificationService.findByIdAndUpdate(verification.id, {
+                    veriffId: veriffSession.verification.id,
+                });
+            } catch (error) {
+                console.error("Failed to create Veriff session:", error);
+                await this.verificationService.delete(verification.id);
+                return res.status(500).json({ error: "Failed to create verification session" });
+            }
🤖 Prompt for AI Agents
In infrastructure/evault-provisioner/src/controllers/VerificationController.ts
between lines 118 and 159, the code calls the external Veriff API without error
handling, which can cause unhandled exceptions. Wrap the Veriff API call and
subsequent update in a try-catch block to catch any errors. In the catch block,
log the error and return an appropriate error response (e.g., status 500 with an
error message) to the client to handle failures gracefully.

coodos added a commit that referenced this pull request Jul 7, 2025
* feat: eid wallet basic ui for verification

* chore: evault provisioning

* feat: working wallet with provisioning

* feat: restrict people on dupes

* 📝 Add docstrings to `feat/evault-provisioning-via-phone` (#189)

Docstrings generation was requested by @coodos.

* #188 (comment)

The following files were modified:

* `infrastructure/eid-wallet/src/lib/utils/capitalize.ts`
* `infrastructure/evault-provisioner/src/utils/hmac.ts`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
coodos added a commit that referenced this pull request Jul 7, 2025
* initial commit

* chore: add w3id readme (#3)

* chore: add w3id readme

* chore: bold text

* chore: better formatting

* docs: add w3id details

* chore: format

* chore: add links

* fix: id spec considerations addressal (#8)

* fix: id spec considerations addressal

* fix: identity -> indentifier

* chore: expand on trust list based recovery

* chore: expand on AKA

---------

Co-authored-by: Merul Dhiman <[email protected]>

* Docs/eid wallet (#10)

* chore: add eid-wallet folder

* chore: add eid wallet docs

* feat: add (#9)

* feat(w3id): basic setup (#11)

* feat(w3id): basic setup

* fix(root): add infrastructure workspaces

* update: lock file

* feat(eidw): setup tauri (#40)

* Feat/setup daisyui (#46)

* feat: setup-daisyui

* fix: index file

* feat: colors added

* feat: Archivo font added

* fix: postcss added

* fix: +layout.svelte file added

* fix: packages

* fix: fully migrating to tailwind v4

* feat: add Archivo font

* feat: add danger colors

* feat: twmerge and clsx added

* feat: shadcn function added

---------

Co-authored-by: Bekiboo <[email protected]>
Co-authored-by: Julien <[email protected]>

* feat: add storybook (#45)

* feat: add storybook

* update: lockfile

* feat: created connection button (#48)

* created connection button

* added restprops to parent class

* added onClick btn and storybook

* fix: make font work in storybook (#54)

* Feat/header (#55)

* feat: add icons lib

* fix: make font work in storybook

* feat: Header

* feat: runtime global added, icon library created, icons added, type file added

* feat: header props added

* fix: remove icons and type file as we are using lib for icons

* fix: heading style

* fix: color and icons, git merge branch 51, 54

* fix: color

* fix: header-styling

* fix: classes

* chore: handlers added

* chore: handlers added

* fix: added heading

---------

Co-authored-by: Soham Jaiswal <[email protected]>

* Alternative w3id diagram (#52)

* Feat/cupertino pane (#49)

* feat: Drawer

* feat: Drawer and added a function for clickoutside in utils

* fix: classes

* fix: drawer button position

* fix: style and clickoutside

* fix: pane height

* fix: border-radius

* fix: drawer as bulletin

* fix: styling

* fix: component with inbuilt features

* fix: remove redundant code

* fix: remove redundant code

* fix: cancel button

* fix: css in storybook

* fix: position

* fix: height of pane

* fix: remove redundant code

* feat: add button action component (#47)

* feat: add button action component

* fix: add correct weights to Archivo fontt

* feat: add base button

* fix: set prop classes last

* feat: improve loading state

* chore: cleanup

* feat: add button action component

* fix: add correct weights to Archivo fontt

* feat: add base button

* fix: set prop classes last

* feat: improve loading state

* chore: cleanup

* chore: add documentation

* fix: configure Storybook

* chore: storybook gunk removal

* feat: enhance ButtonAction component with type prop and better error handling

---------

Co-authored-by: JulienAuvo <[email protected]>

* Feat/splash screen (#63)

* feat: SplashScreen

* fix: remove redundant code

* fix: as per given suggestion

* fix: font-size

* fix: logo

* feat: input-pin (#56)

* feat: input-pin

* fix: styling as per our design

* fix: added small variant

* fix: hide pin on select

* fix: gap between pins

* fix: color of focus state

* fix: removed legacy code and also fix some css to tailwind css

* fix: css

* fix: optional props

* feat: added color variants

* Feat/improve button component (#60)

* feat: add white variant

* feat: add small variant

* chore: update doc and story for button

* chore: rename cb into callback

* update: improve small size

* update: modify loading style

* fix: return getAbsolutePath function to storybook (#58)

Co-authored-by: Bekiboo <[email protected]>

* feat: add selector component (#59)

* feat: add selector component

* feat: improve selector + add flag-icon lib

* feat: improve selector + doc

* feat: add utility function to get language with country name

* feat: test page for language selectors

* chore: add Selector Story

* chore: clean test page

* fix: types

* fix: normalize custom tailwind colors (#71)

* feat: workflows (#64)

* feat: workflows

* fix: node version

* fix: use pnpm 10

* fix: check message

* Fix/codebase linting (#73)

* fix: Check Lint / lint

* fix: Check Lint / lint

* fix: Check Lint / lint

* fix: Check Lint / lint

* fix: Check Code / lint

* fix: Check Format / lint

* fix: Check Code / lint

* fix: Check Format / lint

* fix: Check Code / lint

* fix: Check Format / lint

* fix: Check Code / lint

* fix: Check Code / lint

* fix: Check Format / lint

* fix: unknown property warning

* fix: unknown property warning

* chore: improve args type

* settings nav button :) (#75)

* setting bav button all done :)

* lint fixski

* added component to index.ts

* Feat/#32 identity card fragment (#74)

* identity card

* identity card

* lint fixski

* lint fixski

* lint fixski

* fixed the font weight

* added component to index.ts

* changed span to buttton

* feat: add icon button component (#68)

* feat: add icon button component

* feat: finish up buttonIcon + stories

* fix: update with new color naming

* feat: polish button icon (and button action too)

* chore: format lint

* chore: sort imports

* chore: format, not sure why

* Feat/onboarding flow (#67)

* feat: onboarding-page

* fix: line height and added handlers

* fix: button variant

* fix: text-decoration

* fix: subtext

* fix: underline

* fix: padding and button spacing

* fix: according to design update

* feat: Drawer

* feat: verify-pae

* fix: verify-page styling

* feat: drawer for both confirm pin and add bio metrics added

* feat: modal added in fragments

* fix: icons and flow

* feat: Identifier Card

* fix: copy to clipboard

* feat: e-passport page

* fix: error state

* fix: colors

* fix: lint error

* fix: lint

* feat: Typography

* fix: typograpy

* fix: as per given suggestion

* fix: font-sizing

* fix: identity card implementation

* fix: spacing

* fix: padding

* fix: padding and spacing

* fix: splashscreen

* fix: error state

* fix: styling to avoid

* fix:typo

* Fix/remove daisyui (#82)

* refactoring: remove DaisyUI + refactor some tailwind classes and logic

* refactoring: remove DaisyUI + refactor some tailwind classes and logic

* feat: add Button.Nav (#77)

* feat: add Button.Nav

* chore: format

* chore: sort imports

* update: remove unused snippet and add missing props

* feat: stick to fragment definition

* update: documentation

* fix: stories

* chore: sort imports

* Feat/splashscreen animation (#81)

* feat: add animation to splashScreen

* feat: implement data loading logic with splash screen delay

* chore: sort import

* update: use ButtonIcon is IdentityCard (#78)

* update: use ButtonIcon is IdentityCard

* feat: refactor ButtonIcon to be used anywhere in the app

* chore: format indent

* chore: remove useless change

* feat: setup safe area (#80)

* feat: setup safe area

* chore: simplify implementation

* chore: format

* Feat/uuidv5 generation (#61)

* feat: setup uuidv5

* chore: add test for deterministic UUID

* feat: add Hero fragment (#88)

* feat: add Hero fragment

* chore: sort imports + add doc

* feat: add storage specification abstract class (#92)

* feat: add storage specification abstract class

* chore: format and ignore lint

* chore: change format checker on w3id

* feat: settings-flow (#86)

* feat: settings-flow

* feat: settings and language page

* feat
: history page

* feat: change pin page

* fix: height of selector

* fix: pin change page

* fix: size of input pin

* fix: spacing of pins

* feat: AppNav fragment

* fix: height of page

* fix: padding

* fix: remove redundant code

* feat: privacy page

* chore: add doc

* fix: error state

* feat: remove redundant code

* chore: used app nav component

---------

Co-authored-by: JulienAuvo <[email protected]>

* feat: AppNav fragment (#90)

* feat: AppNav fragment

* chore: add doc

* feat: Main page flow (#93)

* feat: create root page + layout

* feat: complete main page flow beta

* chore: fix ts block

* chore: sort imports

* feat: integrate-flows (#94)

* feat: intigrate-flows

* fix: spacing in e-passport page

* fix: page connectivity

* feat: app page transitions

* fix: z index

* fix: pages

* fix: view transition effect on splashscreen

* fix: drawer pill and cancel button removed

* fix: share button removed when onboarding

* fix: remove share and view button when on onboarding flow

* fix: remove view button

* fix: ci checks

* fix: transitions

* fix: transititon according to direction

* fix: lint error

* fix: loop holes

* Feat/w3id log generation (#98)

* chore: create basic log generation mechanism

* chore: add hashing utility function

* chore: rotation event

* feat: genesis entry

* feat: generalize hash function

* feat: append entry

* chore: basic tests

* chore: add tests for rotation

* feat: add malform throws

* chore: add the right errors

* chore: fix CI stuff

* chore: add missing file

* chore: fix event type enum

* chore: format

* feat: add proper error

* chore: format

* chore: remove eventtypes enum

* chore: add new error for bad options

* chore: add options tests

* feat: add codec tests

* fix: err handling && jsdoc

* fix: run format

* fix: remove unused import

* fix: improve default error messages

* fix: move redundant logic to function

* fix: run format

* fix: type shadow

* fix: useless conversion/cast

* fix: run format

---------

Co-authored-by: Soham Jaiswal <[email protected]>

* Feat/core id creation logic (#99)

* feat: create w3id builder

* fix: w3id builder

* feat: add global config var for w3id

* chore: add docs

* chore: change rand to crng

* chore: add ts type again

* chore: fix lint and format

* chore: add w3id tests github workflow

* Feat/evault core (#100)

* feat: migrate neo4j

* chore: envelope logic works

* chore: envelope logic works

* feat: parsed envelopes search

* feat: generics

* feat: protocol

* feat: jwt sigs in w3id

* chore: stuff works

* chore: tests for evault core

* chore: format

* chore: fix test

* Feat/docker compose and docs (#101)

* chore: stash dockerfile progress

* fix: getEnvelopesByOntology thing

* chore: fix tests

* Update infrastructure/evault-core/src/protocol/vault-access-guard.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* chore: remove unused import

* chore: remove package

* chore: fix pnpm lock

* chore: fix workflow

* chore: fix port in dockerfile

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Feat/registry and evault provisioning (#106)

* feat: evault provisioning

* chore: fianlly fixed provisioner

* feat: add logic for metadata in consul

* feat: registry

* chore: format

* Feat/watchers logs (#114)

* feat: alloc according to entropy and namespace

* chore: move exports

* chore: docs

* feat: `whois` endpoint

* feat: watcher endpoints

* chore: fix format and lint

* chore: fix tests

* feat: web3 adapter (#115)

* feat: tauri plugins setup (#97)

* feat: tauri plugins setup

* fix: add editorconfig

* fix: add missing biome json

* fix: run formatter

* feat: biometry homework

* feat: add pin set logic

* feat: add biometric enabling logic

* fix: sec controller qol

* feat: stub user controller

* fix: run format && lint

* fix: sort imports

* fix: import statement sort

* feat: user controller

* feat: pin flow

* feat: biometrics unavailable

* fix: pin input not working

* feat: make checks pass

* fix: scan works

* fix: actions

* feat: format on save

* fix: coderabbit suggestions

* chore: run format lint check

* fix: scan on decline too

* feat: documentation links (#117)

* feat: bad namespace test (#116)

* fix: layouts (#119)

* fix: layouts

* fix: Onboarding page scroll fixed

* fix: page layout and prevent from scroll in all devices

* fix: pages layout

* chore: try to fix emulator

* fix: units

* fix: safezones for ios

* fix: styling

---------

Co-authored-by: Soham Jaiswal <[email protected]>

* feat: setup-metagram (#121)

* feat: setup-metagram

* chore: tailwind css worked

* feat: fonts added

* feat: typography

* fix: removed stories and fixed setup for icons lib

* feat: icons and story file

* fix: type of args in story

* fix: lint errors

* feat: colors added

* feat: Button

* fix: format and lint

* fix: colors

* fix: spinner

* fix: code rebbit suggestions

* fix: code rebbit suggestions

* fix: paraglide removed

* fix: lock file

* feat: added user avatar. (#130)

* feat: Button (#129)

* feat: Button

* fix: colors of variants

* feat: Input (#131)

* feat: Input

* feat: styling added

* fix: styling

* fix: styling

* fix: added a new story

* fix: focus states

* fix: input states

* Feat/settings navigation button (#140)

* feat: settings-navigation-button

* fix: handler added

* chore: another variant added

* fix: as per given suggestion

* feat: BottomNav (#132)

* feat: BottomNav

* fix: icons

* feat: profile icons created

* feat: handler added

* feat: handler added

* fix: correct tags

* fix: as per given suggestion, bottomnav moved to fragments and also implemented on page

* fix: handler

* chore: routes added

* feat: app transitions added

* fix: direction of transition

* fix: transition css

* fix: directionable transition

* fix: used button instead of label, and used page from state

* feat: added post fragment. (#137)

* feat: FileInput (#150)

* feat: FileInput

* fix: added icon

* feat: cancel upload

* fix: remove redundant code

* fix: usage docs added and as per requirements
'

* fix: moved to framents

* feat: Toggle Switch (#143)

* feat: Toggle Switch

* feat: Toggle Switch

* fix: as per our design

* fix: as per our design

* feat: Label (#146)

* feat: Select (#148)

* feat: Select

* fix: as per our design

* fix: code format and as per svelte 5

* fix: font-size

* fix: font-size

* fix: icon

* feat: message-input (#144)

* feat: message-input

* fix: classes merge and a files as a prop

* feat: variant added

* feat: icon replaced

* fix: as per code rabbit suggestions

* fix: icon

* fix: input file button

* fix: as per suggestion

* fix: classes

* fix: no need of error and disabled classes

* fix: input

* feat: invalid inputs

* feat: add number input storybook

---------

Co-authored-by: Soham Jaiswal <[email protected]>

* feat:Drawer (#152)

* feat:Drawer

* feat: Drawer with clickoutside

* fix: settings

* Feat/metagram header (#133)

* feat: added metagram header primary linear gradient.

* feat: added flash icon.

* feat: added secondary state of header.

* feat: added secondary state of header with menu.

* chore: cleaned some code.

* docs: updated component docs.

---------

Co-authored-by: SoSweetHam <[email protected]>

* Feat/metagram message (#135)

* feat: added metagram message component.

* feat: added both states of message component.

* docs: added usage docs.

* chore: exposed component from ui.

* fix: component -> fragement

---------

Co-authored-by: SoSweetHam <[email protected]>

* feat: modal (#154)

* fix: styling of modal

* fix: modal props

* fix: conflicting styles

* fix: styles of drawer

* fix: hide scrollbar in drawer

* fix: padding

* fix: used native method for dismissing of drawer

* feat: Context-Menu (#156)

* feat: Context-Menu

* fix: name of component

* fix: as per suggestion

* fix: action menu position

* fix: class

* feat: responsive-setup (#157)

* feat: responsive-setup

* fix: background color

* fix: added font fmaily

* feat: responsive setup for mobile and desktop (#159)

* feat: responsive setup for mobile and desktop

* fix: width of sidebar and rightaside

* fix: responsive layout

* feat: SideBar

* fix: added some finishing touches to sidebar and button

* fix: prevent pages transition on desktop

* fix: icon center

* feat: settings page and icon added

* feat/layout-enhancement (#168)

* feat/infinite-scroll (#170)

* feat/infinite-scroll

* fix: aspect ratio of post

* fix: bottom nav background

* settings page (#169)

* settings page layout done

* settings page layout done

* formt fix

* format fix

* format fix

* routing for settings page fixed

* settings page buttons

* merge conflict

* settings page tertiary pages

* settings pages all done

* settings pages unnecessary page deleted

* requested changes done

* requested changes done

* Feat/comments pane (#171)

* feat/comments-pane

* fix: overflow and drawer swipe

* feat: Comment fragment

* fix: comments added

* fix: comment fragment

* feat: Comments reply

* fix: message input position

* fix: post type shifted to types file

* fix: one level deep only

* fix: drawer should only be render on mobile

* fix: comments on layout page

* fix: format

* feat: messages (#174)

* feat: messages

* feat: ChatMessae

* feat: messages by id

* fix: messages page

* fix: icon name

* fix: hide bottom nav for chat

* fix: header

* fix: message bubble

* fix: message bubble

* fix: message bubble

* fix: as per suggestion

* fix: messaging

* chore: change from nomad to k8s (#179)

* chore: change from nomad to k8s

* Update infrastructure/eid-wallet/src/routes/+layout.svelte

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* feat: uri extraction

* feat: regitry stuff

* feat: registry using local db

* 📝 Add docstrings to `feat/switch-to-k8s` (#181)

Docstrings generation was requested by @coodos.

* #179 (comment)

The following files were modified:

* `infrastructure/evault-provisioner/src/templates/evault.nomad.ts`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* chore: format

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: make scan qr page work again (#185)

* feat: Discover Page (#180)

* refactor/Post (#186)

* refactor/Post

* fix: format and lint

* fix: added dots for gallery

* fix: added dots for gallery

* fix: added dots for gallery

* fix: plural name

* feat: splash-screen (#187)

* Feat/evault provisioning via phone (#188)

* feat: eid wallet basic ui for verification

* chore: evault provisioning

* feat: working wallet with provisioning

* feat: restrict people on dupes

* 📝 Add docstrings to `feat/evault-provisioning-via-phone` (#189)

Docstrings generation was requested by @coodos.

* #188 (comment)

The following files were modified:

* `infrastructure/eid-wallet/src/lib/utils/capitalize.ts`
* `infrastructure/evault-provisioner/src/utils/hmac.ts`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* feat: added uploaded post view component. (#182)

* feat: added uploaded post view component.

* fix: fixed the outline and color.

* fix: moved function to external definition.

* fix: fixed the restProps.

* profile page (#178)

* basic layout for profile page

* fixed alt text

* merge conflict

* profile page for other users implemented

* fix: profile pages and logics

* fixed all the pages of profile

* fixed all the pages of profile

* fix: format

---------

Co-authored-by: gourav <[email protected]>

* Feat/radio input (#176)

* feat: added a radio button custom

* docs: added name option in docs.

* chore: cleaned the unnecessary classes and variables for input type radio.

* fix: moved input radio to its own component.

* fix: keydown events added.

* feat: added settings tile component. (#184)

* feat: added settings tile component.

* chore: fixed the naming convention

* chore: renamed callback to onclick

* fix: fixed the use of restProps

* fix: fixed the unnecessary onclick expose.

* fix: fixed the join function params.

* Feat/textarea (#194)

* chore: removed redundant radio

* feat: added textarea.

* fix: tabindex

* fix: removed type inconsitency.

* Feat/mobile upload flow (#193)

* fix: header logic in secondary

* fix: fixed the text in header in post

* feat: trying some hack to get file image input.

* feat: added image input on clicking the post bottom nav

* chore: got rid of non-required code.

* feat: added the logic to get the images from user on clicking post tab.

* feat: added store.

* feat: added correct conversion of files.

* feat: added the correct display of image when uploading.

* feat: added settings tile to the post page and fixed the settingsTile component type of currentStatus

* feat: added hte correct header for the audience page.

* fix: fixed the page transition not happening to audience page.

* feat: added audience setting

* feat: added store to audience.

* chore: removed console log

* feat: added post button.

* feat: correct button placement

* fix: horizontal scroll

* fix: positioning of the post button.

* fix: protecting post route when no image is selected.

* fix: improved type saftey

* feat: added memory helper function

* feat: added memory cleanup.

* Feat/social media platforms (#195)

* chore: this part works now wooohooo

* chore: stash progress

* chore: stash progress

* chore: init message data models

* feat: different socials

* chore: blabsy ready for redesign

* Feat/social media platforms (#196)

* chore: this part works now wooohooo

* chore: stash progress

* chore: stash progress

* chore: init message data models

* feat: different socials

* chore: blabsy ready for redesign

* chore: add other socials

* Feat/blabsy add clone (#198)

* chore: clone twitter

* feat: custom auth with firebase using w3ds

* chore: add chat

* feat: chat works with sync

* feat: twittex

* feat: global schemas

* feat: blabsy adapter

* refactor: shift some text messages to work on blabsy (#199)

* chore: stash progress

* chore: stash adapters

* chore: stash working extractor

* feat: adapter working properly for translating to global with globalIDs

* feat: adapter toGlobal pristine

* chore: stash

* feat: adapter working

* chore: stash until global translation from pictique

* feat: bi-directional sync prestino

* feat: bidir adapters

* chore: login redir

* chore: swap out for sqlite3

* chore: swap out for sqlite3

* chore: server conf

* feat: messages one way

* feat: ready to deploy

* feat: ready to deploy

* chore: auth thing pictique

* chore: set adapter to node

* chore: fix auth token thingy

* chore: auth thing

* chore: fix auth token thingy

* chore: port for blabsy

* feat: provision stuff

* feat: provision

* feat: provision

* feat: provision

* chore: fix sync

* feat: temporary id thing

* chore: android

* chore: fix mapper sync

* chore: fallback

* feat: add error handling on stores

* feat: fix issue with posts

* chore: fix retry loop

* Fix/author details (#229)

* fix: author-details

* fix: owner-details

* fix: author avatar

* fix: auth user avatar

* fix: error handling

* fix: author image in bottom nav

---------

Co-authored-by: Merul Dhiman <[email protected]>

* Fix/change name (#228)

* fix: corrected the name to blabsy

* fix: extra shit comming.

* fix: fixed the alignment of the display in more to look more like current twitter.

* fix: avatars (#226)

* fix: avatars

* fix: avatar in follow request page

* fix: images uploaded shown in user profile

* fix: button size

* fix: avatar

---------

Co-authored-by: Merul Dhiman <[email protected]>

* chore: temp fix sync

* chore: stash progress

* Fix/post context menu (#231)

* fix: post-context-menu

* fix: user id with post

* fix: removed redundant code

* fix: images

* fix: profile data

* fix: profile data

* fix: image cover

* fix: logout

* Fix/wallet text (#234)

* changed text as per the request and fixed styling on pages with useless scroll

* added settings button in main page which went missing somehow

* fix: consistent padding

* chore: change tags

* feat: change icon

* feat: webhook dynamic registry

* feat: make camera permission work properlyh

* chore: removed all locking mechanism thing from platforms

* feat: synchronization works perfectly

* feat: fixed everything up

* feat: changes

* chore: stats fix

* chore: fix pictique visual issues

* chore: fix cosmetic name issue

* feat: fix sync issue

* chore: fix logical issue here

* chore: add qrcode ename

* feat: add packages (#235)

* feat: add packages

* feat: add sample funcs + docs

* fixed the filled color on like icon for liked post (#239)

* feat: fake passport name

* feat: double confirmation

* chore: fix pictique login issue

* fix: make no user case redir to login

* fix: issues with wallet

---------

Co-authored-by: Soham Jaiswal <[email protected]>
Co-authored-by: SoSweetHam <[email protected]>
Co-authored-by: Gourav Saini <[email protected]>
Co-authored-by: Bekiboo <[email protected]>
Co-authored-by: Julien <[email protected]>
Co-authored-by: Ananya Rana <[email protected]>
Co-authored-by: Sergey <[email protected]>
Co-authored-by: Julien Connault <[email protected]>
Co-authored-by: Ananya Rana <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Sahil Garg <[email protected]>
Co-authored-by: Sahil Garg <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant