Skip to content

Conversation

coodos
Copy link
Contributor

@coodos coodos commented Apr 18, 2025

Description of change

Issue Number

Type of change

  • New (a change which implements a new feature)

How the change has been tested

CI

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 core eVault service with Neo4j-backed storage for meta envelopes, accessible via a GraphQL API supporting create, read, update, delete, and search operations.
    • Added access control for meta envelopes with user-based and wildcard ACL support enforced in GraphQL resolvers.
    • Enabled W3ID instances to sign JWTs, including utilities for creating, signing, verifying, and parsing JWTs.
    • Provided Docker Compose configuration for running a Neo4j database service.
  • Bug Fixes
    • None.
  • Tests
    • Added comprehensive unit, integration, and end-to-end tests covering eVault core functionality, JWT utilities, and W3ID JWT signing.
    • Introduced mock signer and storage utilities to facilitate testing.
  • Chores
    • Added automated test workflows, TypeScript and Vitest configurations, and updated package dependencies.
  • Documentation
    • Defined GraphQL schema and type definitions for envelopes and meta envelopes.

Copy link
Contributor

coderabbitai bot commented Apr 18, 2025

Walkthrough

This update introduces the foundational implementation of the "evault-core" system, including its database schema, service logic, GraphQL API, and comprehensive testing infrastructure. The changes add a Neo4j-backed service for storing and managing "meta envelopes" and their associated data, with type-safe serialization and access control mechanisms. A GraphQL server exposes these capabilities with authentication and authorization, and a full suite of integration and end-to-end tests validate the functionality. Supporting utilities, type definitions, and configuration files for TypeScript, Docker, and CI/CD workflows are also included. Additionally, the "w3id" module is extended with JWT signing utilities and related tests.

Changes

File(s) / Path(s) Change Summary
.github/workflows/tests-evault-core.yml Added a GitHub Actions workflow to automate tests for evault-core on push and pull request events, setting up Node.js, installing dependencies, and running tests.
infrastructure/evault-core/docker-compose.yml Added Docker Compose config for a Neo4j service with persistent storage and custom network.
infrastructure/evault-core/package.json Updated metadata, added scripts, and declared dependencies and devDependencies for TypeScript, Vitest, GraphQL, Neo4j, and utilities.
infrastructure/evault-core/tsconfig.json Added TypeScript configuration targeting ES2017, with strict type checking and output directories.
infrastructure/evault-core/vitest.config.ts Added Vitest configuration for Node environment, global variables, and extended timeouts.
infrastructure/evault-core/src/db/db.service.ts Introduced DbService class for managing meta envelopes and envelopes in Neo4j, with methods for CRUD, search, and value serialization.
infrastructure/evault-core/src/db/schema.ts Added schema system for serialization/deserialization of common types using JSON Schema and runtime logic.
infrastructure/evault-core/src/db/types.ts Defined TypeScript types for meta envelopes, envelopes, and related result types.
infrastructure/evault-core/src/evault.ts Added main startup module to initialize Neo4j driver, database service, and GraphQL server.
infrastructure/evault-core/src/protocol/graphql-server.ts Introduced GraphQLServer class exposing queries and mutations for meta envelopes with access control and context-based authentication.
infrastructure/evault-core/src/protocol/typedefs.ts Added GraphQL schema definition for envelopes, meta envelopes, queries, and mutations with JSON payload support.
infrastructure/evault-core/src/protocol/vault-access-guard.ts Added VaultAccessGuard class to enforce ACL-based access control on GraphQL resolvers and filter sensitive data.
infrastructure/evault-core/src/types/w3id.ts Added interfaces for generic storage and cryptographic signing, supporting test and integration scenarios.
infrastructure/evault-core/src/db/db.service.spec.ts Added integration tests for DbService covering CRUD, type handling, search, and deletion logic.
infrastructure/evault-core/tests/evault.spec.ts Added end-to-end tests for the evault system, validating storage, retrieval, authorization, wildcard ACLs, and search via the GraphQL API.
infrastructure/evault-core/tests/utils/mock-signer.ts Added mock signer utility for simulating cryptographic signing in tests.
infrastructure/evault-core/tests/utils/mock-storage.ts Added mock storage class implementing the storage interface for use in testing.
infrastructure/w3id/src/index.ts Added signJWT method to W3ID, re-exported JWT utilities, and updated imports for JWT support.
infrastructure/w3id/src/logs/log.types.ts Added JWTHeader and JWTPayload types, and updated Signer type to include alg property.
infrastructure/w3id/src/utils/jwt.ts Introduced JWT utility functions for creation, signing, verification, and parsing of JWTs, using base64url encoding.
infrastructure/w3id/tests/utils/crypto.ts Updated mock createSigner to include the alg property in returned signer objects.
infrastructure/w3id/tests/utils/jwt.test.ts Added tests for JWT utilities covering creation, signing, parsing, and verification.
infrastructure/w3id/tests/w3id.test.ts Added tests for W3ID's JWT signing capability, including error handling and header/payload validation.

Sequence Diagram(s)

Meta Envelope Storage and Retrieval Flow

sequenceDiagram
    participant Client
    participant GraphQLServer
    participant VaultAccessGuard
    participant DbService
    participant Neo4jDB

    Client->>GraphQLServer: storeMetaEnvelope(input, acl)
    GraphQLServer->>VaultAccessGuard: Check access (middleware)
    VaultAccessGuard-->>GraphQLServer: Access allowed
    GraphQLServer->>DbService: storeMetaEnvelope(input, acl)
    DbService->>Neo4jDB: Create meta-envelope and envelopes
    Neo4jDB-->>DbService: Confirmation
    DbService-->>GraphQLServer: Result (meta-envelope, envelopes)
    GraphQLServer-->>Client: Response

    Client->>GraphQLServer: getMetaEnvelopeById(id)
    GraphQLServer->>VaultAccessGuard: Check access (middleware)
    VaultAccessGuard->>DbService: findMetaEnvelopeById(id)
    DbService->>Neo4jDB: Query meta-envelope and envelopes
    Neo4jDB-->>DbService: Data
    DbService-->>VaultAccessGuard: Envelope data
    VaultAccessGuard-->>GraphQLServer: Access allowed, filter ACL
    GraphQLServer-->>Client: Response
Loading

JWT Signing with W3ID

sequenceDiagram
    participant App
    participant W3ID
    participant Signer

    App->>W3ID: signJWT(payload, header?)
    W3ID->>Signer: sign(message)
    Signer-->>W3ID: signature
    W3ID-->>App: JWT
Loading

Poem

🐇
In fields of code where data grows,
The vault now hums, the Neo4j flows.
With GraphQL gates and JWT keys,
Envelopes flutter in digital breeze.
Tests abound—rabbits leap with glee—
For every byte is safe, secure, and free!
—The CodeRabbit

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 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.

@coodos coodos marked this pull request as ready for review April 18, 2025 22:24
@coodos coodos force-pushed the feat/evault-core branch from aa88bde to 35dee92 Compare April 18, 2025 22:25
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: 16

🧹 Nitpick comments (26)
infrastructure/evault-core/src/types/w3id.ts (1)

1-9: Consider separating key-value and record storage operations in the StorageSpec interface

The StorageSpec interface combines two distinct types of storage operations: key-value operations (get, set, delete, list) and record operations (create, findOne, findMany). This might violate the Single Responsibility Principle and make implementations more complex.

Consider splitting this into two separate interfaces, such as:

export interface KeyValueStorageSpec {
  get(key: string): Promise<string | null>;
  set(key: string, value: string): Promise<void>;
  delete(key: string): Promise<void>;
  list(prefix: string): Promise<string[]>;
}

export interface RecordStorageSpec<T = any, U = any> {
  create(data: T): Promise<U>;
  findOne(query: Partial<T>): Promise<U | null>;
  findMany(query: Partial<T>): Promise<U[]>;
}

export interface StorageSpec<T = any, U = any> extends KeyValueStorageSpec, RecordStorageSpec<T, U> {}

This approach would make it easier to implement and test each aspect independently.

infrastructure/evault-core/src/db/schema.ts (1)

75-84: Consider adding schema validation during deserialization

The current implementation doesn't validate the deserialized values against their JSON schemas, which could lead to runtime errors if invalid data is stored.

Consider adding validation using a library like ajv:

import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv();
addFormats(ajv);

export function deserializeValue(value: any, type: string): any {
  const schemaType = SchemaTypes[type];
  if (!schemaType) return value;

  if (type === "object") {
    const parsed = JSON.parse(value);
    // Validate against schema
    const validate = ajv.compile(schemaType.schema);
    const valid = validate(parsed);
    if (!valid) {
      console.warn('Validation errors:', validate.errors);
    }
    return parsed;
  }

  const deserializedValue = schemaType.deserialize(value);
  // Validate against schema
  const validate = ajv.compile(schemaType.schema);
  const valid = validate(deserializedValue);
  if (!valid) {
    console.warn('Validation errors:', validate.errors);
  }
  
  return deserializedValue;
}

This would add runtime validation to ensure data integrity.

.github/workflows/tests-evault-core.yml (1)

32-33: Consider adding Neo4j service container for database tests

The tests for evault-core might require a Neo4j database to run successfully, especially if they include integration tests.

Consider adding a Neo4j service container to the workflow:

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      neo4j:
        image: neo4j:4.4
        env:
          NEO4J_AUTH: neo4j/password
        ports:
          - 7474:7474
          - 7687:7687
        options: >-
          --health-cmd "wget -O /dev/null -q http://localhost:7474 || exit 1"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

Alternatively, if you're using a mock storage implementation for tests, make sure the tests are properly configured to use it.

infrastructure/evault-core/vitest.config.ts (1)

7-8: Consider if these long timeouts are necessary

The test and hook timeouts are set to 60 seconds, which is quite long. While this may be necessary for integration tests with Neo4j, it could potentially mask performance issues.

Consider adding a comment explaining why these long timeouts are needed to prevent future confusion.

infrastructure/evault-core/src/evault.ts (2)

9-9: GraphQL server instance is not being captured

The GraphQL server instance is created but not stored, which may lead to garbage collection issues.

Store the GraphQL server instance in a variable:

-    new GraphQLServer(dbService);
+    const server = new GraphQLServer(dbService);

5-5: Unnecessary async keyword

The function is marked as async but doesn't use await anywhere, making the async keyword unnecessary.

Either remove the async keyword or use await when appropriate (e.g., for driver verification):

-async function startEVault() {
+function startEVault() {
infrastructure/evault-core/tsconfig.json (1)

2-15: Consider adding source map configuration for better debugging

The TypeScript configuration lacks source map generation, which would be helpful for debugging.

Add source map configuration:

		"skipLibCheck": true,
+		"sourceMap": true,
infrastructure/evault-core/package.json (1)

22-30: Consider setting up automated dependency updates

Your runtime dependencies look appropriate for a Neo4j-backed GraphQL service. Since you're using pinned versions (with ^ but specific patch versions), consider setting up dependency scanning/updating tools like Dependabot to regularly check for security updates.

infrastructure/w3id/tests/w3id.test.ts (2)

85-107: Remove console.log statement

The console.log on line 106 should be removed as it's likely debugging code that shouldn't be in the final tests.

-        console.log(signedJWT);

85-157: Consider adding JWT verification tests

The test suite covers JWT creation and signing, but doesn't test JWT verification functionality. Consider adding tests that validate the JWT can be properly verified using the signer's public key.

infrastructure/w3id/tests/utils/jwt.test.ts (1)

11-161: Consider adding tests for malformed JWTs

The test suite should include tests for handling malformed JWTs (missing parts, invalid encoding, etc.) to ensure the utilities are robust against invalid inputs.

Consider adding tests like:

  • JWT with missing parts (only header, missing signature)
  • JWT with invalid base64url encoding
  • JWT with malformed JSON in header or payload
infrastructure/evault-core/src/protocol/graphql-server.ts (2)

28-94: Consider refactoring resolver logic for better maintainability.

The instantiateServer method contains all resolver definitions which makes it lengthy. Consider extracting resolvers into separate files or modules for better maintainability.

You could refactor this to:

- private instantiateServer() {
-   const resolvers = {
-     JSON: require("graphql-type-json"),
-     Query: {
-       // Query resolvers...
-     },
-     Mutation: {
-       // Mutation resolvers...
-     },
-   };
+ private getResolvers() {
+   return {
+     JSON: require("graphql-type-json"),
+     Query: this.getQueryResolvers(),
+     Mutation: this.getMutationResolvers(),
+   };
+ }
+ 
+ private getQueryResolvers() {
+   return {
+     getMetaEnvelopeById: this.accessGuard.middleware(
+       (_: any, { id }: { id: string }) => {
+         return this.db.findMetaEnvelopeById(id);
+       }
+     ),
+     // Other query resolvers...
+   };
+ }
+ 
+ private getMutationResolvers() {
+   return {
+     storeMetaEnvelope: this.accessGuard.middleware(
+       // Implementation...
+     ),
+     // Other mutation resolvers...
+   };
+ }
+ 
+ private instantiateServer() {
+   const resolvers = this.getResolvers();

30-30: Use ES modules import instead of require().

Using require("graphql-type-json") is inconsistent with the ES module imports used elsewhere in the codebase.

- JSON: require("graphql-type-json"),
+ JSON: graphQLTypeJSON,

And add this import at the top:

import graphQLTypeJSON from 'graphql-type-json';
infrastructure/evault-core/src/db/db.service.spec.ts (1)

114-116: Improve type safety instead of using runtime error.

The code throws an error if match is undefined instead of using TypeScript's type guards or assertions.

- const match = found.find((m) => m.id === metaEnv.metaEnvelope.id);
- expect(match).toBeDefined();
- if (!match) throw new Error();
+ const match = found.find((m) => m.id === metaEnv.metaEnvelope.id);
+ expect(match).toBeDefined();
+ // Type assertion is safe after the expect check
+ const matchedEnvelope = match!;
infrastructure/evault-core/tests/utils/mock-storage.ts (4)

25-29: Consider more robust ID generation for the create method.

The current ID generation uses a simple random string that's quite short, which could potentially cause collisions in tests with many objects.

-    const id = Math.random().toString(36).substring(7);
+    const id = `${Date.now()}-${Math.random().toString(36).substring(7)}`;

31-38: Type casting needs verification.

The findOne method casts data to type U without validation. While acceptable for testing, this approach could mask type-related issues.

Consider adding a comment explaining the type casting strategy and why it's acceptable in a testing context.


50-54: matchesQuery only supports exact equality checks.

The current implementation only handles exact equality checks between field values. Consider documenting this limitation, as a real implementation might support more complex query operations.

 private matchesQuery(data: T, query: Partial<T>): boolean {
+    // Note: This simplified implementation only supports exact equality checks
     return Object.entries(query).every(([key, value]) => {
       return (data as any)[key] === value;
     });
 }

56-59: Document test-specific clear method.

The clear method is not part of the StorageSpec interface and appears to be a test-specific extension. It would be helpful to document this.

+ /**
+  * Test-specific method to clear all storage.
+  * Note: This method is not part of the StorageSpec interface.
+  */
 clear(): void {
   this.store.clear();
   this.dataStore.clear();
 }
infrastructure/w3id/src/utils/jwt.ts (1)

17-22: Add padding correction to base64url decoding.

The current implementation might not handle all base64 encoded strings correctly due to missing padding handling.

function base64urlDecode(str: string): string {
+    // Add padding if needed
+    const padding = str.length % 4;
+    const paddedStr = padding ? 
+        str + '='.repeat(4 - padding) : 
+        str;
    return Buffer.from(
-        str.replace(/-/g, "+").replace(/_/g, "/"),
+        paddedStr.replace(/-/g, "+").replace(/_/g, "/"),
        "base64",
    ).toString();
}
infrastructure/evault-core/src/db/types.ts (2)

25-33: Document relationship between MetaEnvelope and MetaEnvelopeResult.

While the type itself is well-defined, the relationship between MetaEnvelope and MetaEnvelopeResult could be better documented to explain how one is transformed into the other.

/**
 * Base result type for all database operations that return a meta-envelope.
 * Includes the parsed payload structure reconstructed from the envelopes.
+ * This is an extended version of MetaEnvelope that includes database-generated 
+ * fields like id and the parsed payload reconstructed from individual envelopes.
 */
export type MetaEnvelopeResult<
  T extends Record<string, any> = Record<string, any>,
> = {
  id: string;
  ontology: string;
  acl: string[];
  envelopes: Envelope<T[keyof T]>[];
  parsed: T;
};

38-47: Maintain type consistency across result types.

The structure of metaEnvelope in StoreMetaEnvelopeResult differs from MetaEnvelopeResult, which could be confusing for consumers. Consider aligning these structures or documenting the differences.

You could either:

  1. Use consistent field naming across types
  2. Reuse existing types to ensure consistency:
export type StoreMetaEnvelopeResult<
  T extends Record<string, any> = Record<string, any>,
> = {
-  metaEnvelope: {
-    id: string;
-    ontology: string;
-    acl: string[];
-  };
+  metaEnvelope: Omit<MetaEnvelopeResult<T>, 'envelopes' | 'parsed'>;
  envelopes: Envelope<T[keyof T]>[];
};
infrastructure/evault-core/src/protocol/typedefs.ts (3)

3-3: Add a description for the JSON scalar type.

The JSON scalar is critical for handling complex data but lacks documentation that would be helpful for GraphQL introspection.

-  scalar JSON
+  "A scalar type representing arbitrary JSON values."
+  scalar JSON

5-10: Add descriptions to types for better GraphQL documentation.

GraphQL supports descriptions for types that appear in introspection queries and documentation. Adding these would improve the API's usability.

Example for the Envelope type:

+  "An individual envelope containing a single piece of typed data."
   type Envelope {
+    "Unique identifier for the envelope"
     id: String!
+    "Ontology identifier that classifies the envelope's contents"
     ontology: String!
+    "The actual data value stored in the envelope"
     value: JSON
+    "Type information for the stored value"
     valueType: String
   }

Similar descriptions should be added to MetaEnvelope and StoreMetaEnvelopeResult.

Also applies to: 12-17, 19-22


37-41: Add data validation to mutations.

The mutations lack input validation for critical operations. Consider strengthening the schema with validation directives or custom scalars.

While GraphQL itself doesn't provide built-in validation, you could:

  1. Implement custom directives for validation
  2. Add resolver-level validation logic
  3. Use a library like graphql-constraint-directive to enforce constraints

For example, you could specify minimum/maximum length constraints for strings, ensure arrays aren't empty, etc.

Another option is to incorporate validation into your TypeScript code by using a validation library such as Zod, Yup, or class-validator alongside your GraphQL resolvers.

infrastructure/evault-core/src/protocol/vault-access-guard.ts (1)

88-99: args.id / args.envelopeId gate misses mutations that embed IDs deeper

For mutations like updateEnvelopeValue, the ID lives in args.envelopeId, but for queries such as getMetaEnvelopeById, it is args.id. Future resolvers might receive IDs under different keys (e.g. inside an input object).

Consider normalising ID extraction:

const metaEnvelopeId =
  args.id ??
  args.envelopeId ??
  (args.input?.id as string | undefined) ??
  (args.input?.envelopeId as string | undefined);

and then branching on that single variable.

infrastructure/evault-core/src/db/db.service.ts (1)

54-62: ACL parameter name clashes with local var – use distinct param for clarity

Passing acl as both the Cypher property key and the query parameter can be confusing and risks accidental shadowing when the method evolves.

-`CREATE (m:MetaEnvelope { id: $metaId, ontology: $ontology, acl: $acl })`,
+`CREATE (m:MetaEnvelope { id: $metaId, ontology: $ontology, acl: $metaAcl })`,
...
-envelopeParams: Record<string, any> = {
-  metaId: w3id.id,
-  ontology: meta.ontology,
-  acl: acl,
-};
+envelopeParams: Record<string, any> = {
+  metaId: w3id.id,
+  ontology: meta.ontology,
+  metaAcl: acl,
+};

This small rename improves readability and avoids accidental reuse of acl elsewhere.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 078e5e3 and 35dee92.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (23)
  • .github/workflows/tests-evault-core.yml (1 hunks)
  • infrastructure/evault-core/docker-compose.yml (1 hunks)
  • infrastructure/evault-core/package.json (1 hunks)
  • infrastructure/evault-core/src/db/db.service.spec.ts (1 hunks)
  • infrastructure/evault-core/src/db/db.service.ts (1 hunks)
  • infrastructure/evault-core/src/db/schema.ts (1 hunks)
  • infrastructure/evault-core/src/db/types.ts (1 hunks)
  • infrastructure/evault-core/src/evault.ts (1 hunks)
  • infrastructure/evault-core/src/protocol/graphql-server.ts (1 hunks)
  • infrastructure/evault-core/src/protocol/typedefs.ts (1 hunks)
  • infrastructure/evault-core/src/protocol/vault-access-guard.ts (1 hunks)
  • infrastructure/evault-core/src/types/w3id.ts (1 hunks)
  • infrastructure/evault-core/tests/evault.spec.ts (1 hunks)
  • infrastructure/evault-core/tests/utils/mock-signer.ts (1 hunks)
  • infrastructure/evault-core/tests/utils/mock-storage.ts (1 hunks)
  • infrastructure/evault-core/tsconfig.json (1 hunks)
  • infrastructure/evault-core/vitest.config.ts (1 hunks)
  • infrastructure/w3id/src/index.ts (1 hunks)
  • infrastructure/w3id/src/logs/log.types.ts (1 hunks)
  • infrastructure/w3id/src/utils/jwt.ts (1 hunks)
  • infrastructure/w3id/tests/utils/crypto.ts (1 hunks)
  • infrastructure/w3id/tests/utils/jwt.test.ts (1 hunks)
  • infrastructure/w3id/tests/w3id.test.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (9)
infrastructure/evault-core/tests/utils/mock-signer.ts (1)
infrastructure/evault-core/src/types/w3id.ts (1)
  • Signer (11-15)
infrastructure/w3id/tests/utils/jwt.test.ts (3)
infrastructure/evault-core/src/types/w3id.ts (1)
  • Signer (11-15)
infrastructure/w3id/src/logs/log.types.ts (2)
  • JWTHeader (17-21)
  • JWTPayload (23-32)
infrastructure/w3id/src/utils/jwt.ts (5)
  • createJWT (30-34)
  • signJWT (44-58)
  • getJWTHeader (86-89)
  • getJWTPayload (96-99)
  • verifyJWT (68-79)
infrastructure/w3id/tests/w3id.test.ts (5)
infrastructure/w3id/src/index.ts (1)
  • W3IDBuilder (32-140)
infrastructure/w3id/tests/utils/store.ts (1)
  • InMemoryStorage (4-40)
infrastructure/w3id/tests/utils/crypto.ts (1)
  • createSigner (27-39)
infrastructure/w3id/src/utils/jwt.ts (2)
  • getJWTHeader (86-89)
  • getJWTPayload (96-99)
infrastructure/w3id/src/logs/log.types.ts (1)
  • JWTHeader (17-21)
infrastructure/evault-core/src/db/db.service.spec.ts (2)
infrastructure/evault-core/src/db/types.ts (1)
  • Envelope (14-19)
infrastructure/evault-core/src/db/db.service.ts (1)
  • DbService (18-307)
infrastructure/evault-core/tests/evault.spec.ts (6)
infrastructure/evault-core/src/db/db.service.ts (1)
  • DbService (18-307)
infrastructure/evault-core/tests/utils/mock-signer.ts (1)
  • createMockSigner (3-12)
infrastructure/evault-core/tests/utils/mock-storage.ts (1)
  • MockStorage (3-60)
infrastructure/w3id/src/index.ts (1)
  • W3IDBuilder (32-140)
infrastructure/evault-core/src/protocol/graphql-server.ts (1)
  • GraphQLServer (10-138)
infrastructure/evault-core/src/protocol/vault-access-guard.ts (1)
  • VaultContext (4-6)
infrastructure/evault-core/tests/utils/mock-storage.ts (1)
infrastructure/evault-core/src/types/w3id.ts (1)
  • StorageSpec (1-9)
infrastructure/evault-core/src/protocol/vault-access-guard.ts (1)
infrastructure/evault-core/src/db/db.service.ts (1)
  • DbService (18-307)
infrastructure/w3id/src/utils/jwt.ts (2)
infrastructure/w3id/src/logs/log.types.ts (2)
  • JWTHeader (17-21)
  • JWTPayload (23-32)
infrastructure/w3id/src/index.ts (1)
  • signJWT (21-29)
infrastructure/evault-core/src/db/db.service.ts (3)
infrastructure/evault-core/src/db/types.ts (6)
  • MetaEnvelope (4-9)
  • StoreMetaEnvelopeResult (38-47)
  • Envelope (14-19)
  • SearchMetaEnvelopesResult (52-54)
  • MetaEnvelopeResult (25-33)
  • GetAllEnvelopesResult (59-59)
infrastructure/w3id/src/index.ts (1)
  • W3IDBuilder (32-140)
infrastructure/evault-core/src/db/schema.ts (2)
  • serializeValue (57-73)
  • deserializeValue (75-84)
🪛 actionlint (1.7.4)
.github/workflows/tests-evault-core.yml

19-19: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 GitHub Check: test
infrastructure/evault-core/tests/evault.spec.ts

[failure] 219-219: tests/evault.spec.ts > eVault E2E > should search meta envelopes by term
TypeError: Cannot read properties of undefined (reading 'parsed')
❯ tests/evault.spec.ts:219:51


[failure] 126-126: tests/evault.spec.ts > eVault E2E > should store and retrieve a meta envelope
AssertionError: expected [ { …(4) } ] to be undefined

  • Expected:
    undefined
  • Received:
    [
    {
    "extensions": {
    "code": "INTERNAL_SERVER_ERROR",
    },
    "locations": [
    {
    "column": 9,
    "line": 2,
    },
    ],
    "message": "Unexpected error.",
    "path": [
    "getMetaEnvelopeById",
    ],
    },
    ]

❯ tests/evault.spec.ts:126:29

🪛 GitHub Actions: Tests [evault-core]
infrastructure/evault-core/tests/evault.spec.ts

[error] 126-126: AssertionError: expected [ { …(4) } ] to be undefined. Test 'should store and retrieve a meta envelope' failed due to unexpected data returned from getMetaEnvelopeById.


[error] 219-219: TypeError: Cannot read properties of undefined (reading 'parsed'). Test 'should search meta envelopes by term' failed due to accessing 'parsed' on undefined result.

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

[error] 109-109: Error: Access denied at getMetaEnvelopeById. This error caused test failures in evault.spec.ts.

🔇 Additional comments (35)
infrastructure/evault-core/src/types/w3id.ts (1)

11-15: LGTM: The Signer interface is well-defined

The interface provides a clear contract for cryptographic signing with appropriate properties for the public key and algorithm identifier.

infrastructure/evault-core/src/db/schema.ts (1)

48-55: 🛠️ Refactor suggestion

Add explicit handling for null and undefined values

The getSchemaType function doesn't have explicit handling for null or undefined values, which could lead to unexpected behavior. Currently, null would be handled by the object type check, while undefined would fall through to the string type.

export function getSchemaType(value: any): SchemaType {
+  if (value === null || value === undefined) return SchemaTypes.string;
  if (value instanceof Date) return SchemaTypes.date;
  if (Array.isArray(value)) return SchemaTypes.array;
  if (typeof value === "object" && value !== null) return SchemaTypes.object;
  if (typeof value === "number") return SchemaTypes.number;
  if (typeof value === "boolean") return SchemaTypes.boolean;
  return SchemaTypes.string;
}

Likely an incorrect or invalid review comment.

infrastructure/w3id/tests/utils/crypto.ts (1)

30-30: LGTM: Correctly added the alg property to the Signer object

The addition of the alg property with the value "ed25519" aligns with the updated Signer interface and appropriately specifies the algorithm used for the NaCl-based signing implementation.

.github/workflows/tests-evault-core.yml (1)

3-12: Review the PR trigger paths for the workflow

The workflow triggers on pushes to main affecting infrastructure/evault-core/**, but for pull requests, it only triggers on changes to infrastructure/w3id/**. This seems inconsistent with the package being tested.

Verify if this is intentional or if the PR paths should include infrastructure/evault-core/** as well:

  pull_request:
    branches: [main]
    paths:
-      - 'infrastructure/w3id/**'
+      - 'infrastructure/evault-core/**'
+      - 'infrastructure/w3id/**'
infrastructure/evault-core/vitest.config.ts (1)

5-10: Well-structured testing configuration

The configuration is appropriate for running tests in a CI environment with Neo4j integration tests. The setup with globals enabled and Node.js environment is a good standard approach.

infrastructure/evault-core/tests/utils/mock-signer.ts (1)

3-12: Well-implemented mock for testing

This mock signer implementation properly follows the Signer interface and provides a reasonable approximation of signing behavior for testing purposes. The use of base64url encoding is a good approach for deterministic test signatures.

infrastructure/evault-core/tsconfig.json (1)

2-15: Solid TypeScript configuration

Overall, this is a good TypeScript configuration with strict type checking enabled, proper output directory configuration, and sensible module resolution settings.

infrastructure/evault-core/package.json (3)

2-3: LGTM - Version appropriate for new module

The use of version 0.1.0 is appropriate for a new development module.


7-7: Configuration looks good

Using vitest with a dedicated config file is a good practice for test configuration.


13-20: Appropriate dev dependencies

The dev dependencies match the project's testing, type checking and development requirements.

infrastructure/w3id/src/logs/log.types.ts (3)

17-21: LGTM - JWT header type follows standards

The JWTHeader type correctly defines the standard JWT header fields with proper types.


23-32: LGTM - JWT payload type follows standards

The JWTPayload type properly includes all standard registered JWT claims while allowing for additional custom claims via the index signature.


34-38: Good update to Signer interface

Adding the alg property to the Signer type is necessary for JWT signing capabilities and makes the signing algorithm explicit.

infrastructure/w3id/tests/w3id.test.ts (4)

11-12: LGTM - Proper imports for JWT functionality

Importing the JWT utilities and types needed for the new tests.


109-116: LGTM - Good error handling test

This test appropriately verifies that the system rejects JWT signing when no signer is available.


118-136: LGTM - Custom header test

Good test to verify that custom headers can be provided and are respected.


138-156: LGTM - Payload preservation test

This test correctly verifies that all payload fields, including custom ones, are preserved in the JWT.

infrastructure/w3id/tests/utils/jwt.test.ts (5)

11-16: LGTM - Simple mock signer implementation

The mock signer provides a base64url encoding implementation which is sufficient for testing the structure and format of JWTs without requiring cryptographic verification.


23-45: LGTM - Good JWT creation tests

These tests effectively verify the JWT structure and encoding rules.


47-87: LGTM - Comprehensive signing tests

These tests adequately cover the JWT signing functionality, including custom headers.


89-110: LGTM - Header and payload extraction tests

These tests properly verify that the JWT header and payload can be extracted and decoded.


112-161: LGTM - Good verification tests

The verification tests cover both valid and invalid signature scenarios.

infrastructure/evault-core/docker-compose.yml (1)

1-22:

❓ Verification inconclusive

Docker Compose configuration looks good but has security considerations for production.

The Docker Compose file effectively sets up a Neo4j database service with proper volume configuration and networking. This aligns well with the database needs described in the PR summary.

For production environments, consider:

  1. Not hardcoding the password "testpass" in the file
  2. Using Docker secrets or environment variables
  3. Restricting port exposure if external access isn't needed

🏁 Script executed:

#!/bin/bash
# Check if this compose file is used in any CI/CD pipeline scripts
grep -r "docker-compose.*up" --include="*.yml" --include="*.yaml" --include="*.sh" .

Length of output: 86


Ensure Docker Compose is production-ready

The current Compose setup correctly provisions Neo4j, but for a secure production deployment, please review the following:

  • Don’t hardcode NEO4J_AUTH=neo4j/testpass; switch to environment variables or Docker secrets.
  • Limit exposed ports to only what’s needed (e.g., remove or firewall port 7474 if HTTP access isn’t required externally).
  • Verify how and where this docker-compose.yml is invoked—no docker-compose up calls were found in CI/CD scripts, so please confirm its integration.
infrastructure/w3id/src/index.ts (3)

2-7: LGTM: Import extensions for JWT functionality.

The additional imports properly support the new JWT signing functionality.


15-29: Well-documented JWT signing implementation.

The signJWT method is properly documented with JSDoc comments and handles the basic error case of missing signer.


142-142: Appropriate export of JWT utilities.

Re-exporting all functionality from the JWT utilities module makes the JWT-related utilities available to consumers of this module.

infrastructure/evault-core/src/protocol/graphql-server.ts (2)

1-9: LGTM: Imports for GraphQL server setup.

The imports correctly include all necessary dependencies for creating a GraphQL server with the graphql-yoga library, HTTP server integration, and integration with the vault access guard.


10-26: Well-structured GraphQL server class initialization.

The class structure with dependency injection of the database service and proper initialization of the access guard follows good design principles.

infrastructure/evault-core/src/db/db.service.spec.ts (3)

1-34: Well-structured test setup using testcontainers.

The test suite correctly uses the Neo4j testcontainer to spin up a temporary database for integration testing. Setup and teardown are properly handled in the beforeAll and afterAll hooks.


36-92: Comprehensive test for various data types.

This test effectively verifies that the DbService can correctly store and retrieve different data types, ensuring proper type preservation through serialization and deserialization.


94-120: Good test for search functionality.

This test verifies the search functionality works correctly for finding meta-envelopes by search terms in their values.

infrastructure/evault-core/tests/utils/mock-storage.ts (1)

1-6: Implementation matches StorageSpec interface correctly.

The MockStorage class correctly implements the StorageSpec interface with appropriate type parameters and private data structures. Using two different maps for string storage and typed data is a good separation of concerns.

infrastructure/w3id/src/utils/jwt.ts (1)

6-12: Consider padding handling in base64url encoding.

The base64urlEncode function removes padding characters, which is standard for JWTs, but you might want to handle edge cases with input length.

infrastructure/evault-core/src/db/types.ts (2)

4-9: Generic definition of MetaEnvelope is well structured.

Good use of generic types with sensible defaults. The type clearly defines the structure of a meta-envelope with ontology, payload, and access control list.


14-19:

❌ Incorrect review comment

Consider making value and valueType properties optional or nullable.

Depending on your application logic, there might be cases where value or valueType could be null or undefined.

Examine how the Envelope type is used in practice:


🏁 Script executed:

#!/bin/bash
# Search for Envelope usage to see if null/undefined values are handled
rg -A 3 -B 3 'value: \w+' --type=ts
rg -A 3 -B 3 'valueType: \w+' --type=ts

Length of output: 13509


Keep value and valueType as required properties
Our serialization/deserialization pipeline always assigns both fields and all DB operations, GraphQL types, and tests depend on them being present. Making them optional or nullable would misrepresent the actual data invariants.

• Envelope definition: infrastructure/evault-core/src/db/types.ts
• Serialization: infrastructure/evault-core/src/db/db.service.ts
• Tests: infrastructure/evault-core/src/db/db.service.spec.ts

Likely an incorrect or invalid review comment.

Comment on lines +57 to +73
export function serializeValue(value: any): { value: any; type: string } {
const type = getSchemaType(value);
let serializedValue = value;

if (type === SchemaTypes.date) {
serializedValue = value.toISOString();
} else if (type === SchemaTypes.object) {
serializedValue = JSON.stringify(value);
}

return {
value: serializedValue,
type:
Object.keys(SchemaTypes).find((key) => SchemaTypes[key] === type) ||
"string",
};
}
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

Optimize type lookup and add circular reference protection

The function has two issues:

  1. The type lookup using Object.keys().find() is inefficient, especially when called frequently
  2. JSON.stringify() can throw on circular references
export function serializeValue(value: any): { value: any; type: string } {
  const type = getSchemaType(value);
  let serializedValue = value;
+  let typeName = "string";
+  
+  // More efficient type lookup
+  for (const [key, schemaType] of Object.entries(SchemaTypes)) {
+    if (schemaType === type) {
+      typeName = key;
+      break;
+    }
+  }

  if (type === SchemaTypes.date) {
    serializedValue = value.toISOString();
  } else if (type === SchemaTypes.object) {
-    serializedValue = JSON.stringify(value);
+    try {
+      serializedValue = JSON.stringify(value);
+    } catch (error) {
+      console.warn('Failed to stringify object, possible circular reference:', error);
+      serializedValue = JSON.stringify({
+        error: 'Failed to serialize: possible circular reference'
+      });
+    }
  }

  return {
    value: serializedValue,
-    type:
-      Object.keys(SchemaTypes).find((key) => SchemaTypes[key] === type) ||
-      "string",
+    type: typeName,
  };
}
📝 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 serializeValue(value: any): { value: any; type: string } {
const type = getSchemaType(value);
let serializedValue = value;
if (type === SchemaTypes.date) {
serializedValue = value.toISOString();
} else if (type === SchemaTypes.object) {
serializedValue = JSON.stringify(value);
}
return {
value: serializedValue,
type:
Object.keys(SchemaTypes).find((key) => SchemaTypes[key] === type) ||
"string",
};
}
export function serializeValue(value: any): { value: any; type: string } {
const type = getSchemaType(value);
let serializedValue = value;
let typeName = "string";
// More efficient type lookup
for (const [key, schemaType] of Object.entries(SchemaTypes)) {
if (schemaType === type) {
typeName = key;
break;
}
}
if (type === SchemaTypes.date) {
serializedValue = value.toISOString();
} else if (type === SchemaTypes.object) {
try {
serializedValue = JSON.stringify(value);
} catch (error) {
console.warn(
'Failed to stringify object, possible circular reference:',
error
);
serializedValue = JSON.stringify({
error: 'Failed to serialize: possible circular reference',
});
}
}
return {
value: serializedValue,
type: typeName,
};
}


steps:
- name: Checkout code
uses: actions/checkout@v3
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

Update the checkout action to the latest version

The current version of actions/checkout being used (v3) is outdated. The latest version (v4) includes improvements and bug fixes.

- uses: actions/checkout@v3
+ uses: actions/checkout@v4
📝 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
uses: actions/checkout@v3
uses: actions/checkout@v4
🧰 Tools
🪛 actionlint (1.7.4)

19-19: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Comment on lines +6 to +7
const uri = `bolt://localhost:7687`;
const driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass"));
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

Security risk: Hardcoded database credentials

The Neo4j connection uses hardcoded credentials and URI. This is a security risk and limits deployment flexibility.

Refactor to use environment variables:

-    const uri = `bolt://localhost:7687`;
-    const driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass"));
+    const uri = process.env.NEO4J_URI || 'bolt://localhost:7687';
+    const username = process.env.NEO4J_USERNAME || 'neo4j';
+    const password = process.env.NEO4J_PASSWORD || 'testpass';
+    const driver = neo4j.driver(uri, neo4j.auth.basic(username, password));
📝 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 uri = `bolt://localhost:7687`;
const driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass"));
const uri = process.env.NEO4J_URI || 'bolt://localhost:7687';
const username = process.env.NEO4J_USERNAME || 'neo4j';
const password = process.env.NEO4J_PASSWORD || 'testpass';
const driver = neo4j.driver(uri, neo4j.auth.basic(username, password));

Comment on lines +5 to +10
async function startEVault() {
const uri = `bolt://localhost:7687`;
const driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass"));
const dbService = new DbService(driver);
new GraphQLServer(dbService);
}
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

Missing error handling and proper resource management

The startEVault function lacks error handling and proper connection management, which could lead to silent failures and resource leaks.

Add proper error handling and resource management:

-async function startEVault() {
+async function startEVault() {
+    let driver;
+    try {
         const uri = `bolt://localhost:7687`;
-        const driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass"));
+        driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass"));
+        await driver.verifyConnectivity();
         const dbService = new DbService(driver);
-        new GraphQLServer(dbService);
+        const server = new GraphQLServer(dbService);
+        
+        // Handle graceful shutdown
+        process.on('SIGTERM', async () => {
+            console.log('Shutting down...');
+            await driver.close();
+            process.exit(0);
+        });
+    } catch (error) {
+        console.error('Failed to start EVault:', error);
+        if (driver) await driver.close();
+        process.exit(1);
+    }
}
📝 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
async function startEVault() {
const uri = `bolt://localhost:7687`;
const driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass"));
const dbService = new DbService(driver);
new GraphQLServer(dbService);
}
async function startEVault() {
let driver;
try {
const uri = `bolt://localhost:7687`;
driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass"));
await driver.verifyConnectivity();
const dbService = new DbService(driver);
const server = new GraphQLServer(dbService);
// Handle graceful shutdown
process.on('SIGTERM', async () => {
console.log('Shutting down...');
await driver.close();
process.exit(0);
});
} catch (error) {
console.error('Failed to start EVault:', error);
if (driver) await driver.close();
process.exit(1);
}
}

"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
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

Unusual inclusion of DOM library for a Node.js application

The configuration includes the DOM library types, which is unusual for a Node.js backend application as DOM APIs aren't available in Node.js.

Consider removing the DOM library unless it's specifically needed:

-		"lib": ["ESNext", "DOM"],
+		"lib": ["ESNext"],
📝 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
"lib": ["ESNext", "DOM"],
"lib": ["ESNext"],

Comment on lines +24 to +29
type Query {
getMetaEnvelopeById(id: String!): MetaEnvelope
findMetaEnvelopesByOntology(ontology: String!): [String!]!
searchMetaEnvelopes(ontology: String!, term: String!): [MetaEnvelope!]!
getAllEnvelopes: [Envelope!]!
}
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 pagination support for list queries.

Queries that return lists like findMetaEnvelopesByOntology, searchMetaEnvelopes, and getAllEnvelopes don't support pagination, which could cause performance issues with large datasets.

Consider implementing standard pagination:

  type Query {
    getMetaEnvelopeById(id: String!): MetaEnvelope
-    findMetaEnvelopesByOntology(ontology: String!): [String!]!
+    findMetaEnvelopesByOntology(ontology: String!, first: Int, after: String): MetaEnvelopeConnection!
-    searchMetaEnvelopes(ontology: String!, term: String!): [MetaEnvelope!]!
+    searchMetaEnvelopes(ontology: String!, term: String!, first: Int, after: String): MetaEnvelopeConnection!
-    getAllEnvelopes: [Envelope!]!
+    getAllEnvelopes(first: Int, after: String): EnvelopeConnection!
  }

+  type PageInfo {
+    hasNextPage: Boolean!
+    endCursor: String
+  }
+
+  type MetaEnvelopeConnection {
+    edges: [MetaEnvelopeEdge!]!
+    pageInfo: PageInfo!
+  }
+
+  type MetaEnvelopeEdge {
+    node: MetaEnvelope!
+    cursor: String!
+  }
+
+  type EnvelopeConnection {
+    edges: [EnvelopeEdge!]!
+    pageInfo: PageInfo!
+  }
+
+  type EnvelopeEdge {
+    node: Envelope!
+    cursor: String!
+  }
📝 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
type Query {
getMetaEnvelopeById(id: String!): MetaEnvelope
findMetaEnvelopesByOntology(ontology: String!): [String!]!
searchMetaEnvelopes(ontology: String!, term: String!): [MetaEnvelope!]!
getAllEnvelopes: [Envelope!]!
}
type Query {
getMetaEnvelopeById(id: String!): MetaEnvelope
findMetaEnvelopesByOntology(ontology: String!, first: Int, after: String): MetaEnvelopeConnection!
searchMetaEnvelopes(ontology: String!, term: String!, first: Int, after: String): MetaEnvelopeConnection!
getAllEnvelopes(first: Int, after: String): EnvelopeConnection!
}
type PageInfo {
hasNextPage: Boolean!
endCursor: String
}
type MetaEnvelopeConnection {
edges: [MetaEnvelopeEdge!]!
pageInfo: PageInfo!
}
type MetaEnvelopeEdge {
node: MetaEnvelope!
cursor: String!
}
type EnvelopeConnection {
edges: [EnvelopeEdge!]!
pageInfo: PageInfo!
}
type EnvelopeEdge {
node: Envelope!
cursor: String!
}

Comment on lines +81 to +91
const executeGraphQL = async (query, variables = {}, token) => {
const res = await fetch("http://localhost:4000/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
body: JSON.stringify({ query, variables }),
});
return res.json();
};
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

Hard‑coded port breaks when port is random & blinds CI to failures

executeGraphQL always targets http://localhost:4000/graphql. If the test switches to a random port (recommended) or the default port is in use, requests silently fail and the assertions later on receive unexpected errors / undefined payloads (as the pipeline log shows).

-const res = await fetch("http://localhost:4000/graphql", {
+const res = await fetch(`http://localhost:${port}/graphql`, {

(Remember to hoist port to outer scope or return it from the server factory.)

Fixing this removes the current AssertionError & TypeError thrown by Vitest.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +59 to +74
const yoga = createYoga({
schema: new GraphQLServer(dbService).getSchema(),
context: async ({ request }) => {
const authHeader = request.headers.get("authorization") ?? "";
const token = authHeader.replace("Bearer ", "");
return {
currentUser: token ? w3id.id : null,
} satisfies VaultContext;
},
});

const httpServer = createServer(yoga);
const port = await getFreePort();
await new Promise((resolve) => httpServer.listen(port, resolve));
server = httpServer;
});
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

Two HTTP servers are spun up but only one is used – tighten the test harness

The test suite creates its own Yoga instance that binds to a random free port (httpServer) and ‑­immediately afterwards every call in executeGraphQL is hard‑coded to hit http://localhost:4000, i.e. the different server that the GraphQLServer spins up internally.
Maintaining two servers:

  1. Wastes resources / prolongs CI.
  2. Risks port collisions on 4000 in shared runners.
  3. Makes the custom context you define here (currentUser) unused – the requests never reach this Yoga instance.

Consider keeping one of the two approaches only:

- const yoga = createYoga({      // remove whole custom server block
-   schema: new GraphQLServer(dbService).getSchema(),
-   context: async ({ request }) => ({
-     currentUser: tokenToW3id(request),          // helper
-   } satisfies VaultContext),
- });
-
- const httpServer = createServer(yoga);
- const port = await getFreePort();
- await new Promise((resolve) => httpServer.listen(port, resolve));
- server = httpServer;
+ // Rely on GraphQLServer’s own internal HTTP server (port 4000) only
+ const graph = new GraphQLServer(dbService);
+ server = graph.httpServer();     // expose/stash the instance to close in afterAll

or – if you prefer your own Yoga instance – do not let GraphQLServer open a socket, bind your instance to port, and update executeGraphQL to consume that dynamic port instead of 4000.

This will also make the ACL context you crafted actually effective.

📝 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 yoga = createYoga({
schema: new GraphQLServer(dbService).getSchema(),
context: async ({ request }) => {
const authHeader = request.headers.get("authorization") ?? "";
const token = authHeader.replace("Bearer ", "");
return {
currentUser: token ? w3id.id : null,
} satisfies VaultContext;
},
});
const httpServer = createServer(yoga);
const port = await getFreePort();
await new Promise((resolve) => httpServer.listen(port, resolve));
server = httpServer;
});
// Rely on GraphQLServer’s own internal HTTP server (port 4000) only
const graph = new GraphQLServer(dbService);
server = graph.httpServer();
});

Comment on lines +107 to +114
const hasAccess = await this.checkAccess(metaEnvelopeId, context);
if (!hasAccess) {
throw new Error("Access denied");
}

const result = await resolver(parent, args, context);
return this.filterACL(result);
};
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

Throwing breaks GraphQL contracts – return null instead of error

The guard currently throws "Access denied", which GraphQL-Yoga wraps into INTERNAL_SERVER_ERROR.
Your test expects getMetaEnvelopeById to simply return null on forbidden access – a much cleaner UX that avoids noisy stack‑traces for every ACL miss.

-const hasAccess = await this.checkAccess(metaEnvelopeId, context);
-if (!hasAccess) {
-  throw new Error("Access denied");
-}
+const hasAccess = await this.checkAccess(metaEnvelopeId, context);
+if (!hasAccess) {
+  return null;             // let resolvers return null per GraphQL spec
+}

Adjusting this aligns behaviour with the tests and GraphQL best practice (fields resolve to null when not authorised).

🧰 Tools
🪛 GitHub Actions: Tests [evault-core]

[error] 109-109: Error: Access denied at getMetaEnvelopeById. This error caused test failures in evault.spec.ts.

Comment on lines +120 to +175
async findMetaEnvelopesBySearchTerm<
T extends Record<string, any> = Record<string, any>,
>(
ontology: string,
searchTerm: string,
): Promise<SearchMetaEnvelopesResult<T>> {
const result = await this.runQuery(
`
MATCH (m:MetaEnvelope { ontology: $ontology })-[:LINKS_TO]->(e:Envelope)
WHERE
CASE e.valueType
WHEN 'string' THEN toLower(e.value) CONTAINS toLower($term)
WHEN 'array' THEN ANY(x IN e.value WHERE toLower(toString(x)) CONTAINS toLower($term))
WHEN 'object' THEN toLower(toString(e.value)) CONTAINS toLower($term)
ELSE toLower(toString(e.value)) CONTAINS toLower($term)
END
WITH m
MATCH (m)-[:LINKS_TO]->(allEnvelopes:Envelope)
RETURN m.id AS id, m.ontology AS ontology, m.acl AS acl, collect(allEnvelopes) AS envelopes
`,
{ ontology, term: searchTerm },
);

return result.records.map((record): MetaEnvelopeResult<T> => {
const envelopes = record
.get("envelopes")
.map((node: any): Envelope<T[keyof T]> => {
const properties = node.properties;
return {
id: properties.id,
ontology: properties.ontology,
value: deserializeValue(
properties.value,
properties.valueType,
) as T[keyof T],
valueType: properties.valueType,
};
});

const parsed = envelopes.reduce(
(acc: T, envelope: Envelope<T[keyof T]>) => {
(acc as any)[envelope.ontology] = envelope.value;
return acc;
},
{} as T,
);

return {
id: record.get("id"),
ontology: record.get("ontology"),
acl: record.get("acl"),
envelopes,
parsed,
};
});
}
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

findMetaEnvelopesBySearchTerm may yield duplicates & false negatives

  1. A meta‑envelope containing multiple envelopes that match the search term will be returned once per match because WITH m keeps duplicates.
  2. Neo4j string matching is case‑insensitive here, but JSON‑stringified objects (valueType === 'object') rely on toString(e.value), which produces "[object Object]", discarding content.

Consider:

MATCH (m:MetaEnvelope { ontology: $ontology })-[:LINKS_TO]->(e:Envelope)
WHERE apoc.text.lowerJson(e.value) CONTAINS toLower($term)
WITH DISTINCT m              // (1) deduplicate
...

and serialise objects to text with APOC or filter on map entries in JS after retrieval.

This will make the failing “search meta envelopes by term” test pass reliably.

@coodos coodos merged commit 6fdb407 into main Apr 18, 2025
4 of 6 checks passed
@coodos coodos deleted the feat/evault-core branch April 18, 2025 22:37
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 (2)
infrastructure/evault-core/tests/evault.spec.ts (2)

81-91: ⚠️ Potential issue

Fix the hardcoded port in executeGraphQL function

The executeGraphQL function is hardcoding port 4000, but the server is actually running on a different port (the dynamic port found by getFreePort()). This mismatch causes the tests to hit a different server or no server at all, leading to test failures.

Apply this diff to fix the issue:

const executeGraphQL = async (query, variables = {}, token) => {
-    const res = await fetch("http://localhost:4000/graphql", {
+    const res = await fetch(`http://localhost:${port}/graphql`, {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            ...(token ? { Authorization: `Bearer ${token}` } : {}),
        },
        body: JSON.stringify({ query, variables }),
    });
    return res.json();
};

Note: Make sure to hoist the port variable to the outer scope of the test suite or have the server factory return it.


59-74: 🛠️ Refactor suggestion

Simplify test setup by using only one HTTP server

As noted in a previous review, you're creating two HTTP servers but only using one. This causes confusion and potential resource waste.

Consider implementing one of these approaches:

  1. Either use only the server created in your test code
  2. Or use only the GraphQLServer's internal server

For option 1 (preferred), keep your custom server but modify executeGraphQL to use the dynamic port.
For option 2, remove your custom server setup and expose the GraphQLServer's internal HTTP server.

🧹 Nitpick comments (4)
infrastructure/evault-core/tests/evault.spec.ts (4)

94-94: Include expiration in JWT for better security testing

You're creating JWTs without expiration times, which is not a security best practice.

- const token = await w3id.signJWT({ sub: w3id.id });
+ const token = await w3id.signJWT({ 
+   sub: w3id.id,
+   exp: Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
+ });

While this doesn't affect the current tests, it would make them more realistic and would help catch any issues with token expiration handling.


15-27: Add error handling to getFreePort function

The getFreePort function doesn't handle all potential errors that could occur when creating a server.

async function getFreePort() {
    return new Promise((resolve, reject) => {
        const server = createNetServer();
+       server.on('error', (err) => {
+           reject(err);
+       });
        server.listen(0, () => {
            const address = server.address();
            if (address && typeof address === "object") {
                server.close(() => resolve(address.port));
            } else {
                server.close(() => reject(new Error("No port found")));
            }
        });
    });
}

This ensures that any errors during server creation (like permission issues) are properly caught and rejected.


97-102: Use GraphQL document variables for better maintainability

GraphQL queries are repeated as string literals throughout the tests. Extracting them as constants would improve maintainability.

Consider creating a constants file with your GraphQL documents:

// test-queries.ts
export const STORE_META_ENVELOPE = `mutation Store($input: MetaEnvelopeInput!) {
  storeMetaEnvelope(input: $input) {
    metaEnvelope { id ontology parsed }
    envelopes { id ontology value valueType }
  }
}`;

export const GET_META_ENVELOPE = `query Read($id: String!) {
  getMetaEnvelopeById(id: $id) {
    id ontology parsed envelopes { id ontology value }
  }
}`;

// etc.

Then import and use these constants in your tests:

import { STORE_META_ENVELOPE, GET_META_ENVELOPE } from './test-queries';

// ...
const store = await executeGraphQL(STORE_META_ENVELOPE, { input: {...} }, token);

Also applies to: 117-121, 182-184, 197-199, 211-213


29-41: Add timeout to test suite for CI stability

Long-running E2E tests can sometimes cause CI timeouts. Adding an explicit timeout can help prevent this.

-describe("eVault E2E", () => {
+describe("eVault E2E", () => {
+  // Set a generous timeout for E2E tests since they involve container startup
+  vi.setDefaultTimeout(60000); // 60 seconds

This makes the test behavior more predictable in CI environments where resources might be constrained.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b1ccbb5 and 7c5c44a.

📒 Files selected for processing (1)
  • infrastructure/evault-core/tests/evault.spec.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Check: test
infrastructure/evault-core/tests/evault.spec.ts

[failure] 149-149: tests/evault.spec.ts > eVault E2E > should reject unauthorized access
AssertionError: expected { Object (id) } to be null

  • Expected:
    null
  • Received:
    {
    "id": "7eb6b1b8-c736-5eeb-8e37-8c527eacb804",
    }

❯ tests/evault.spec.ts:149:49

🪛 GitHub Actions: Tests [evault-core]
infrastructure/evault-core/tests/evault.spec.ts

[error] 149-149: Test failure: expected { Object (id) } to be null but received an object with id. AssertionError at expect(result.data.getMetaEnvelopeById).toBeNull().

Comment on lines +131 to +150
it("should reject unauthorized access", async () => {
const otherSigner = createMockSigner();
const otherRepo = new MockStorage();
const other = await new W3IDBuilder()
.withSigner(otherSigner)
.withRepository(otherRepo)
.withNextKeyHash("z")
.build();
const otherToken = await other.signJWT({ sub: other.id });

const result = await executeGraphQL(
`query Read($id: String!) {
getMetaEnvelopeById(id: $id) { id }
}`,
{ id: testEnvelopeId },
otherToken,
);

expect(result.data.getMetaEnvelopeById).toBeNull();
});
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

Fix failing authorization test

The "should reject unauthorized access" test is failing. According to pipeline logs, result.data.getMetaEnvelopeById is returning an object with an ID when it should be null, indicating that unauthorized users can still access meta envelopes.

This is likely related to the port mismatch issue. Since executeGraphQL is targeting port 4000 instead of the dynamic port, the requests might be going to a server without proper access control, or the authentication tokens aren't being properly validated.

After fixing the port issue, if this test still fails, verify that:

  1. The custom context function is correctly extracting the user ID from the token
  2. The access control logic in the GraphQL resolvers is properly checking the user ID against the envelope's ACL
🧰 Tools
🪛 GitHub Check: test

[failure] 149-149: tests/evault.spec.ts > eVault E2E > should reject unauthorized access
AssertionError: expected { Object (id) } to be null

  • Expected:
    null
  • Received:
    {
    "id": "7eb6b1b8-c736-5eeb-8e37-8c527eacb804",
    }

❯ tests/evault.spec.ts:149:49

🪛 GitHub Actions: Tests [evault-core]

[error] 149-149: Test failure: expected { Object (id) } to be null but received an object with id. AssertionError at expect(result.data.getMetaEnvelopeById).toBeNull().

const authHeader = request.headers.get("authorization") ?? "";
const token = authHeader.replace("Bearer ", "");
return {
currentUser: token ? w3id.id : null,
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 token validation logic

The current token validation logic is too simplistic and doesn't actually verify the token's validity.

- currentUser: token ? w3id.id : null,
+ currentUser: token ? await w3id.verifyJWT(token).then(payload => payload.sub).catch(() => null) : null,

This ensures that:

  1. The token is actually verified cryptographically
  2. The subject from the token is used as the current user
  3. Invalid tokens result in null (unauthenticated) users
📝 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
currentUser: token ? w3id.id : null,
currentUser: token
? await w3id
.verifyJWT(token)
.then(payload => payload.sub)
.catch(() => null)
: null,

This was referenced Apr 20, 2025
coodos added a commit that referenced this pull request Jul 7, 2025
* 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
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