-
Notifications
You must be signed in to change notification settings - Fork 2
Feat/evault core #100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/evault core #100
Conversation
WalkthroughThis 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
Sequence Diagram(s)Meta Envelope Storage and Retrieval FlowsequenceDiagram
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
JWT Signing with W3IDsequenceDiagram
participant App
participant W3ID
participant Signer
App->>W3ID: signJWT(payload, header?)
W3ID->>Signer: sign(message)
Signer-->>W3ID: signature
W3ID-->>App: JWT
Poem
Tip ⚡💬 Agentic Chat (Pro Plan, General Availability)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
aa88bde
to
35dee92
Compare
There was a problem hiding this 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 interfaceThe
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 deserializationThe 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 testsThe 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 5Alternatively, 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 necessaryThe 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 capturedThe 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 keywordThe 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 debuggingThe 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 updatesYour 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 statementThe 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 testsThe 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 JWTsThe 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 thecreate
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 castsdata
to typeU
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-specificclear
method.The
clear
method is not part of theStorageSpec
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
andMetaEnvelopeResult
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
inStoreMetaEnvelopeResult
differs fromMetaEnvelopeResult
, which could be confusing for consumers. Consider aligning these structures or documenting the differences.You could either:
- Use consistent field naming across types
- 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
andStoreMetaEnvelopeResult
.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:
- Implement custom directives for validation
- Add resolver-level validation logic
- Use a library like
graphql-constraint-directive
to enforce constraintsFor 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 deeperFor mutations like
updateEnvelopeValue
, the ID lives inargs.envelopeId
, but for queries such asgetMetaEnvelopeById
, it isargs.id
. Future resolvers might receive IDs under different keys (e.g. inside aninput
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 clarityPassing
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
⛔ 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-definedThe 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 suggestionAdd explicit handling for null and undefined values
The
getSchemaType
function doesn't have explicit handling fornull
orundefined
values, which could lead to unexpected behavior. Currently,null
would be handled by the object type check, whileundefined
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 objectThe addition of the
alg
property with the value "ed25519" aligns with the updatedSigner
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 workflowThe workflow triggers on pushes to
main
affectinginfrastructure/evault-core/**
, but for pull requests, it only triggers on changes toinfrastructure/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 configurationThe 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 testingThis 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 configurationOverall, 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 moduleThe use of version 0.1.0 is appropriate for a new development module.
7-7
: Configuration looks goodUsing vitest with a dedicated config file is a good practice for test configuration.
13-20
: Appropriate dev dependenciesThe 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 standardsThe JWTHeader type correctly defines the standard JWT header fields with proper types.
23-32
: LGTM - JWT payload type follows standardsThe 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 interfaceAdding 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 functionalityImporting the JWT utilities and types needed for the new tests.
109-116
: LGTM - Good error handling testThis test appropriately verifies that the system rejects JWT signing when no signer is available.
118-136
: LGTM - Custom header testGood test to verify that custom headers can be provided and are respected.
138-156
: LGTM - Payload preservation testThis 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 implementationThe 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 testsThese tests effectively verify the JWT structure and encoding rules.
47-87
: LGTM - Comprehensive signing testsThese tests adequately cover the JWT signing functionality, including custom headers.
89-110
: LGTM - Header and payload extraction testsThese tests properly verify that the JWT header and payload can be extracted and decoded.
112-161
: LGTM - Good verification testsThe 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:
- Not hardcoding the password "testpass" in the file
- Using Docker secrets or environment variables
- 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—nodocker-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 theStorageSpec
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=tsLength of output: 13509
Keep
value
andvalueType
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.tsLikely an incorrect or invalid review comment.
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", | ||
}; | ||
} |
There was a problem hiding this comment.
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:
- The type lookup using
Object.keys().find()
is inefficient, especially when called frequently 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.
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 |
There was a problem hiding this comment.
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.
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)
const uri = `bolt://localhost:7687`; | ||
const driver = neo4j.driver(uri, neo4j.auth.basic("neo4j", "testpass")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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)); |
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); | ||
} |
There was a problem hiding this comment.
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.
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"], |
There was a problem hiding this comment.
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.
"lib": ["ESNext", "DOM"], | |
"lib": ["ESNext"], |
type Query { | ||
getMetaEnvelopeById(id: String!): MetaEnvelope | ||
findMetaEnvelopesByOntology(ontology: String!): [String!]! | ||
searchMetaEnvelopes(ontology: String!, term: String!): [MetaEnvelope!]! | ||
getAllEnvelopes: [Envelope!]! | ||
} |
There was a problem hiding this comment.
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.
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! | |
} |
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(); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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; | ||
}); |
There was a problem hiding this comment.
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:
- Wastes resources / prolongs CI.
- Risks port collisions on 4000 in shared runners.
- 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.
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(); | |
}); |
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); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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, | ||
}; | ||
}); | ||
} |
There was a problem hiding this comment.
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
- A meta‑envelope containing multiple envelopes that match the search term will be returned once per match because
WITH m
keeps duplicates. - Neo4j string matching is case‑insensitive here, but JSON‑stringified objects (
valueType === 'object'
) rely ontoString(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.
There was a problem hiding this 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 issueFix 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 bygetFreePort()
). 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 suggestionSimplify 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:
- Either use only the server created in your test code
- 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 testingYou'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 functionThe
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 maintainabilityGraphQL 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 stabilityLong-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 secondsThis 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
📒 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().
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(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
- The custom context function is correctly extracting the user ID from the token
- 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, |
There was a problem hiding this comment.
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:
- The token is actually verified cryptographically
- The subject from the token is used as the current user
- 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.
currentUser: token ? w3id.id : null, | |
currentUser: token | |
? await w3id | |
.verifyJWT(token) | |
.then(payload => payload.sub) | |
.catch(() => null) | |
: null, |
* 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
* 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]>
Description of change
Issue Number
Type of change
How the change has been tested
CI
Change checklist
Summary by CodeRabbit