✅ server: use single postgres instance for test#610
Conversation
🦋 Changeset detectedLatest commit: db322a6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThis PR replaces the test-time PGlite mock with an embedded PostgreSQL setup for tests, adds a test database globalSetup utility, updates vitest configuration and devDependencies, removes the mock database module, and adjusts many tests to use fixed credential IDs and the real DB setup. Changes
Sequence Diagram(s)sequenceDiagram
participant Vitest as Vitest (test runner)
participant GlobalSetup as test/database.ts (globalSetup)
participant EmbeddedPG as EmbeddedPostgres
participant Drizzle as Drizzle ORM
participant FS as Filesystem / Artifact
participant Shutdown as Detached shutdown helper
Vitest->>GlobalSetup: invoke global setup
GlobalSetup->>FS: remove existing pg-data dir
GlobalSetup->>EmbeddedPG: start instance (persisted dir)
EmbeddedPG-->>GlobalSetup: connection info / ready
GlobalSetup->>Shutdown: spawn detached shutdown helper
GlobalSetup->>Drizzle: connect with DB URL and schema
Note over GlobalSetup,Drizzle: suppress stdout during schema push
GlobalSetup->>Drizzle: deploy schema (schema.push)
Drizzle-->>GlobalSetup: schema deployed
GlobalSetup->>FS: read factory artifact JSON
FS-->>GlobalSetup: factory artifact (address, owner)
GlobalSetup->>GlobalSetup: derive test account from factory/owner
GlobalSetup->>Drizzle: insert test credentials row(s)
Drizzle-->>GlobalSetup: credentials persisted
GlobalSetup-->>Vitest: return teardown fn
Note over Vitest,EmbeddedPG: tests run against real Postgres
Vitest->>GlobalSetup: invoke teardown
GlobalSetup->>EmbeddedPG: stop instance
EmbeddedPG-->>Vitest: stopped / cleanup complete
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Summary of ChangesHello @cruzdanilo, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly overhauls the server's testing infrastructure by transitioning from an in-memory Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request is a significant improvement to the testing infrastructure. It replaces pglite with a single embedded-postgres instance for all tests, which will make the tests more reliable and closer to the production environment. The centralization of test data setup in server/test/database.ts and the cleanup of individual test files are excellent changes that improve maintainability and readability.
I've left a few comments on potential improvements, mostly related to making the new test setup even more robust and fixing a minor inconsistency in one of the updated tests. Overall, this is a great piece of work.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
server/test/api/card.test.ts (1)
172-191: Bug: Query targets wrong credential ID.The test posts with
"test-credential-id": "sig"but queries for"default". This should query for the newly created card associated with "sig".🔎 Proposed fix
const created = await database.query.cards.findFirst({ columns: { mode: true }, - where: eq(cards.credentialId, "default"), + where: eq(cards.credentialId, "sig"), });
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (15)
.changeset/ready-experts-fly.mdpackage.jsonpatches/embedded-postgres.patchserver/.gitignoreserver/package.jsonserver/test/api/activity.test.tsserver/test/api/auth.test.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/database.tsserver/test/hooks/activity.test.tsserver/test/hooks/panda.test.tsserver/test/hooks/persona.test.tsserver/test/mocks/database.tsserver/vitest.config.mts
💤 Files with no reviewable changes (4)
- server/test/hooks/panda.test.ts
- server/test/hooks/activity.test.ts
- server/test/mocks/database.ts
- server/test/api/auth.test.ts
🧰 Additional context used
📓 Path-based instructions (7)
server/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/server.mdc)
server/**/*.ts: Usec.varobject to pass strongly-typed data between Hono middleware and route handlers; do not usec.set
All request validation (headers, body, params) must be handled by@hono/valibot-validatormiddleware; do not perform manual validation inside route handlers
Use Hono's built-in error handling by throwingnew HTTPException()for expected errors; unhandled errors will be caught and logged automatically
Enforce Node.js best practices using ESLintplugin:n/recommendedconfiguration
Enforce Drizzle ORM best practices using ESLintplugin:drizzle/allconfiguration, including requiringwhereclauses forupdateanddeleteoperations
Use Drizzle ORM query builder for all database interactions; do not write raw SQL queries unless absolutely unavoidable
All authentication and authorization logic must be implemented in Hono middleware
Do not accessprocess.envdirectly in application code; load all configuration and secrets once at startup and pass them through dependency injection or context
Avoid long-running, synchronous operations; useasync/awaitcorrectly and be mindful of CPU-intensive tasks to prevent blocking the event loop
Files:
server/test/api/activity.test.tsserver/test/database.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/hooks/persona.test.ts
**/*.{js,ts,tsx,jsx,sol}
📄 CodeRabbit inference engine (AGENTS.md)
Follow linter/formatter (eslint, prettier, solhint) strictly with high strictness level. No
anytype.
Files:
server/test/api/activity.test.tsserver/test/database.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/hooks/persona.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Omit redundant type names in variable declarations - let the type system explain itself
**/*.{ts,tsx}: Use PascalCase for TypeScript types and interfaces
Use valibot for all runtime validation of API inputs, environment variables, and other data; define schemas once and reuse them
Infer TypeScript types from valibot schemas usingtype User = v.Input<typeof UserSchema>instead of manually defining interfaces
Files:
server/test/api/activity.test.tsserver/test/database.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/hooks/persona.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Omit contextual names - don't repeat class/module names in members
Omit meaningless words like 'data', 'state', 'manager', 'engine', 'value' from variable and function names unless they add disambiguation
**/*.{ts,tsx,js,jsx}: Prefer function declarations for all multi-line functions; use function expressions or arrow functions only for single-line implementations
Preferconstfor all variable declarations by default; only useletif the variable's value will be reassigned
Declare each variable on its own line with its ownconstorletkeyword, not multiple declarations on one line
Use camelCase for TypeScript variables and functions
Always useimport type { ... }for type imports
Use relative paths for all imports within the project; avoid tsconfig path aliases
Follow eslint-plugin-import order: react, external libraries, then relative paths
Use object and array destructuring to access and use properties
Use object method shorthand syntax when a function is a property of an object
Prefer optional chaining (?.), nullish coalescing (??), object and array spreading (...), andfor...ofloops over traditional syntax
Do not use abbreviations or cryptic names; write out full words likeerror,parameters,requestinstead oferr,params,req
UseNumber.parseInt()instead of the globalparseInt()function when parsing numbers
All classes called withnewmust use PascalCase
UseBuffer.from(),Buffer.alloc(), orBuffer.allocUnsafe()instead of the deprecatednew Buffer()
Use@ts-expect-errorinstead of@ts-ignore; follow it immediately with a single-line lowercase comment explaining why the error is expected, without separators like-or:
Do not include the type in a variable's name; let the static type system do its job (e.g., useconst user: Usernotconst userObject: User)
Do not repeat the name of a class or module within its members; omit contextual names (e.g., use `class User { getProfil...
Files:
server/test/api/activity.test.tsserver/test/database.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/hooks/persona.test.ts
server/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
server/**/*.{ts,tsx}: Server API: implement schema-first approach using OpenAPI via hono with validation via valibot middleware
Server database: drizzle schema is source of truth. Migrations required. No direct database access in handlers - usec.var.db
Files:
server/test/api/activity.test.tsserver/test/database.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/hooks/persona.test.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/style.mdc)
For files with a single
defaultexport, name the file identically to the export; for files with multiple exports, use camelCase with a strong preference for a single word
Files:
server/test/api/activity.test.tsserver/test/database.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/hooks/persona.test.ts
**/.changeset/*.md
📄 CodeRabbit inference engine (.cursor/rules/style.mdc)
Use a lowercase sentence in the imperative present tense for changeset summaries
Files:
.changeset/ready-experts-fly.md
🧠 Learnings (13)
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Zero config local dev environment: no `.env` files, mock all external services
Applied to files:
server/test/api/activity.test.tsserver/vitest.config.mtsserver/test/api/card.test.tsserver/test/api/kyc.test.ts
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Applies to server/**/*.{ts,tsx} : Server database: drizzle schema is source of truth. Migrations required. No direct database access in handlers - use `c.var.db`
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/database/schema.ts : Database schema must be defined in `server/database/schema.ts` as the single source of truth for database structure
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Use Drizzle ORM query builder for all database interactions; do not write raw SQL queries unless absolutely unavoidable
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/database/schema.ts : Define relations explicitly in the schema file to enable Drizzle to generate typed query results including related entities
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Enforce Drizzle ORM best practices using ESLint `plugin:drizzle/all` configuration, including requiring `where` clauses for `update` and `delete` operations
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:56:56.405Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/dev.mdc:0-0
Timestamp: 2025-12-23T19:56:56.405Z
Learning: Server (exactly/server) uses Hono (framework), Node.js, Drizzle ORM (database), and PostgreSQL
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Do not access `process.env` directly in application code; load all configuration and secrets once at startup and pass them through dependency injection or context
Applied to files:
server/vitest.config.mts
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Use `nx` for running tasks (build, lint, test, e2e) instead of underlying tooling directly
Applied to files:
server/package.json
📚 Learning: 2025-12-23T19:56:43.683Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-23T19:56:43.683Z
Learning: Applies to contracts/**/*.t.sol : Test files must end with .t.sol and mirror the name of the contract they test (e.g., ExaPlugin.sol -> ExaPlugin.t.sol)
Applied to files:
server/package.json
📚 Learning: 2025-12-23T19:56:56.405Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/dev.mdc:0-0
Timestamp: 2025-12-23T19:56:56.405Z
Learning: Design all tests to run without `.env` files or external services
Applied to files:
server/test/api/kyc.test.tsserver/test/hooks/persona.test.ts
📚 Learning: 2025-12-23T19:56:43.683Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-23T19:56:43.683Z
Learning: Applies to contracts/**/*.t.sol : Use vm.prank to simulate calls from different addresses; avoid changing msg.sender through other means
Applied to files:
server/test/api/kyc.test.tsserver/test/hooks/persona.test.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/api/**/*.ts : The database client (`db`) should be passed via Hono's context (`c.var.db`), not imported directly into route handlers
Applied to files:
server/test/api/kyc.test.ts
🧬 Code graph analysis (4)
server/test/api/activity.test.ts (4)
common/deriveAddress.ts (1)
deriveAddress(18-55).maestro/src/server.ts (1)
activity(20-46)server/api/activity.ts (8)
DebitActivity(473-476)DebitActivity(585-585)CreditActivity(478-488)CreditActivity(584-584)InstallmentsActivity(490-515)InstallmentsActivity(587-587)PandaActivity(300-369)PandaActivity(589-589)server/database/schema.ts (1)
cards(25-34)
server/test/database.ts (1)
common/deriveAddress.ts (1)
deriveAddress(18-55)
server/test/api/card.test.ts (4)
common/deriveAddress.ts (1)
deriveAddress(18-55)server/database/schema.ts (2)
credentials(9-23)cards(25-34)common/panda.ts (1)
SIGNATURE_PRODUCT_ID(2-2).maestro/src/server.ts (1)
keeper(130-130)
server/test/hooks/persona.test.ts (1)
server/database/schema.ts (1)
credentials(9-23)
🔇 Additional comments (21)
server/.gitignore (1)
7-8: LGTM!The
pg-dataignore rule is correctly added to prevent committing the embedded PostgreSQL data directory created during test runs.package.json (1)
234-235: LGTM!The
embedded-postgrespatch entry is correctly added topatchedDependencies.server/test/api/activity.test.ts (3)
20-23: LGTM!The fixed account derivation using
padHex("0xb0b")simplifies test setup while maintaining correctness. The account is correctly used for querying on-chain events while the "bob" credential ID is used for API authentication.
43-56: LGTM!The test correctly uses the fixed "bob" credential ID for authentication, simplifying the test setup without compromising test coverage.
65-66: LGTM!The card insertion correctly associates with the "bob" credential, aligning with the simplified test credential flow.
server/test/hooks/persona.test.ts (2)
23-25: LGTM!Good improvement using camelCase
"pandaId"instead of kebab-case"panda-id", and simplifying the mocksessionKeyvalue.
262-262: LGTM!Setting the default
referenceIdto"bob"aligns with the standardized test credential flow. Individual tests correctly override this when testing different scenarios (e.g., line 76 for the "already-created" credential test).server/test/api/kyc.test.ts (3)
16-16: LGTM!Simplified test setup that removes complex account derivation while maintaining test isolation through mock restoration.
19-46: LGTM!The test correctly uses the fixed "bob" credential for all database operations and authentication, simplifying the test while maintaining coverage.
87-87: LGTM!The mock assertion correctly verifies that
getInquiryis called with the "bob" credential ID.server/package.json (2)
145-145: Clarify the NX outputs path change.The generate:broadcasts outputs path changed from a specific
Protocol.s.solpath to a wildcard pattern*/31337/run-latest.json. While this makes the configuration more flexible, it seems unrelated to the PostgreSQL migration. Is this an intentional improvement, or should it be in a separate PR?
68-83: No action needed. Verification confirms that embedded-postgres does not have a stable (non-beta) release available—only beta versions are published. Usingembedded-postgres@^18.1.0-beta.15for test infrastructure is the appropriate choice.patches/embedded-postgres.patch (1)
9-10: Confirm explicit PostgreSQL shutdown is properly integrated with test framework.The patch removes automatic graceful shutdown hook registration (
AsyncExitHook(gracefulShutdown)), which eliminates automatic cleanup on process exit. The explicit teardown at lines 63-65 inserver/test/database.tscorrectly callsawait postgres.stop()and is properly returned from the setup function. However, verify that this teardown is registered with the test framework's lifecycle hooks (e.g.,afterAll) to ensure it executes consistently across all test runs. Without the AsyncExitHook safety net, orphaned PostgreSQL processes can occur if teardown fails to execute.server/test/api/card.test.ts (3)
23-37: LGTM! Clean test data setup with fixed credential IDs.The simplified approach using string-based credential IDs makes the test setup more readable and maintainable compared to derived addresses.
60-60: LGTM!Simplified cleanup that relies on mock restoration. Test isolation is maintained through unique IDs for additional inserts.
271-301: LGTM!Templates updated to use consistent string identifiers that align with the test credential setup.
server/test/database.ts (2)
36-43: Pragmatic workaround for noisy output.Suppressing stdout during schema push is unconventional but acceptable for test setup. Be aware that any errors during this phase won't be visible in stdout.
63-65: LGTM!Clean teardown pattern that properly stops the embedded PostgreSQL instance.
server/vitest.config.mts (3)
7-10: LGTM!Good configuration additions:
test/database.tsin globalSetup integrates the embedded PostgreSQL setup.- Timeouts of ~37s appropriately accommodate the
waitOntimeouts (33s) in database setup.- Coverage with lcov reporter enables CI integration.
31-31: LGTM!POSTGRES_URL updated to match the embedded PostgreSQL connection string defined in
test/database.ts.
38-42: LGTM!E2E configuration properly disables the summary reporter to reduce noise during end-to-end test runs.
|
@cursor review |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #610 +/- ##
==========================================
+ Coverage 49.19% 53.38% +4.18%
==========================================
Files 41 48 +7
Lines 7096 7772 +676
Branches 522 624 +102
==========================================
+ Hits 3491 4149 +658
- Misses 3589 3607 +18
Partials 16 16
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (14)
.changeset/ready-experts-fly.mdpackage.jsonpatches/embedded-postgres.patchserver/package.jsonserver/test/api/activity.test.tsserver/test/api/auth.test.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/database.tsserver/test/hooks/activity.test.tsserver/test/hooks/panda.test.tsserver/test/hooks/persona.test.tsserver/test/mocks/database.tsserver/vitest.config.mts
💤 Files with no reviewable changes (4)
- server/test/api/auth.test.ts
- server/test/mocks/database.ts
- server/test/hooks/panda.test.ts
- server/test/hooks/activity.test.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/.changeset/*.md
📄 CodeRabbit inference engine (.cursor/rules/style.mdc)
Use a lowercase sentence in the imperative present tense for changeset summaries
Files:
.changeset/ready-experts-fly.md
server/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/server.mdc)
server/**/*.ts: Usec.varobject to pass strongly-typed data between Hono middleware and route handlers; do not usec.set
All request validation (headers, body, params) must be handled by@hono/valibot-validatormiddleware; do not perform manual validation inside route handlers
Use Hono's built-in error handling by throwingnew HTTPException()for expected errors; unhandled errors will be caught and logged automatically
Enforce Node.js best practices using ESLintplugin:n/recommendedconfiguration
Enforce Drizzle ORM best practices using ESLintplugin:drizzle/allconfiguration, including requiringwhereclauses forupdateanddeleteoperations
Use Drizzle ORM query builder for all database interactions; do not write raw SQL queries unless absolutely unavoidable
All authentication and authorization logic must be implemented in Hono middleware
Do not accessprocess.envdirectly in application code; load all configuration and secrets once at startup and pass them through dependency injection or context
Avoid long-running, synchronous operations; useasync/awaitcorrectly and be mindful of CPU-intensive tasks to prevent blocking the event loop
Files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.tsserver/test/api/card.test.tsserver/test/database.ts
**/*.{js,ts,tsx,jsx,sol}
📄 CodeRabbit inference engine (AGENTS.md)
Follow linter/formatter (eslint, prettier, solhint) strictly with high strictness level. No
anytype.
Files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.tsserver/test/api/card.test.tsserver/test/database.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Omit redundant type names in variable declarations - let the type system explain itself
**/*.{ts,tsx}: Use PascalCase for TypeScript types and interfaces
Use valibot for all runtime validation of API inputs, environment variables, and other data; define schemas once and reuse them
Infer TypeScript types from valibot schemas usingtype User = v.Input<typeof UserSchema>instead of manually defining interfaces
Files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.tsserver/test/api/card.test.tsserver/test/database.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Omit contextual names - don't repeat class/module names in members
Omit meaningless words like 'data', 'state', 'manager', 'engine', 'value' from variable and function names unless they add disambiguation
**/*.{ts,tsx,js,jsx}: Prefer function declarations for all multi-line functions; use function expressions or arrow functions only for single-line implementations
Preferconstfor all variable declarations by default; only useletif the variable's value will be reassigned
Declare each variable on its own line with its ownconstorletkeyword, not multiple declarations on one line
Use camelCase for TypeScript variables and functions
Always useimport type { ... }for type imports
Use relative paths for all imports within the project; avoid tsconfig path aliases
Follow eslint-plugin-import order: react, external libraries, then relative paths
Use object and array destructuring to access and use properties
Use object method shorthand syntax when a function is a property of an object
Prefer optional chaining (?.), nullish coalescing (??), object and array spreading (...), andfor...ofloops over traditional syntax
Do not use abbreviations or cryptic names; write out full words likeerror,parameters,requestinstead oferr,params,req
UseNumber.parseInt()instead of the globalparseInt()function when parsing numbers
All classes called withnewmust use PascalCase
UseBuffer.from(),Buffer.alloc(), orBuffer.allocUnsafe()instead of the deprecatednew Buffer()
Use@ts-expect-errorinstead of@ts-ignore; follow it immediately with a single-line lowercase comment explaining why the error is expected, without separators like-or:
Do not include the type in a variable's name; let the static type system do its job (e.g., useconst user: Usernotconst userObject: User)
Do not repeat the name of a class or module within its members; omit contextual names (e.g., use `class User { getProfil...
Files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.tsserver/test/api/card.test.tsserver/test/database.ts
server/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
server/**/*.{ts,tsx}: Server API: implement schema-first approach using OpenAPI via hono with validation via valibot middleware
Server database: drizzle schema is source of truth. Migrations required. No direct database access in handlers - usec.var.db
Files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.tsserver/test/api/card.test.tsserver/test/database.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/style.mdc)
For files with a single
defaultexport, name the file identically to the export; for files with multiple exports, use camelCase with a strong preference for a single word
Files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.tsserver/test/api/card.test.tsserver/test/database.ts
🧠 Learnings (19)
📚 Learning: 2025-12-31T00:23:55.034Z
Learnt from: cruzdanilo
Repo: exactly/exa PR: 610
File: .changeset/ready-experts-fly.md:1-2
Timestamp: 2025-12-31T00:23:55.034Z
Learning: In the exactly/exa repository, allow and require empty changeset files (containing only --- separators) when changes are not user-facing and do not warrant a version bump. This is needed because CI runs changeset status --since origin/main and requires a changeset file to exist. Ensure such empty changesets are used only for non-user-facing changes and document the rationale in the commit or changelog notes.
Applied to files:
.changeset/ready-experts-fly.md
📚 Learning: 2025-12-30T15:03:28.449Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/style.mdc:0-0
Timestamp: 2025-12-30T15:03:28.449Z
Learning: Applies to **/.changeset/*.md : Use a lowercase sentence in the imperative present tense for changeset summaries
Applied to files:
.changeset/ready-experts-fly.md
📚 Learning: 2025-12-30T15:03:28.449Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/style.mdc:0-0
Timestamp: 2025-12-30T15:03:28.449Z
Learning: When implementing changes, follow all rules in `.mdc` files for any code, documentation, or rules you create, including meta-rules like the lowercase prose convention
Applied to files:
.changeset/ready-experts-fly.md
📚 Learning: 2025-12-23T19:56:43.683Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-23T19:56:43.683Z
Learning: Applies to contracts/**/*.t.sol : Use vm.prank to simulate calls from different addresses; avoid changing msg.sender through other means
Applied to files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.ts
📚 Learning: 2025-12-23T19:56:56.405Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/dev.mdc:0-0
Timestamp: 2025-12-23T19:56:56.405Z
Learning: Design all tests to run without `.env` files or external services
Applied to files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.ts
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Zero config local dev environment: no `.env` files, mock all external services
Applied to files:
server/test/api/kyc.test.tsserver/vitest.config.mtsserver/test/api/activity.test.tsserver/test/api/card.test.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/api/**/*.ts : The database client (`db`) should be passed via Hono's context (`c.var.db`), not imported directly into route handlers
Applied to files:
server/test/api/kyc.test.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Do not access `process.env` directly in application code; load all configuration and secrets once at startup and pass them through dependency injection or context
Applied to files:
server/vitest.config.mts
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Applies to server/**/*.{ts,tsx} : Server database: drizzle schema is source of truth. Migrations required. No direct database access in handlers - use `c.var.db`
Applied to files:
server/package.jsonserver/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Enforce Node.js best practices using ESLint `plugin:n/recommended` configuration
Applied to files:
server/package.json
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Use `nx` for running tasks (build, lint, test, e2e) instead of underlying tooling directly
Applied to files:
server/package.json
📚 Learning: 2025-12-23T19:56:43.683Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-23T19:56:43.683Z
Learning: Applies to contracts/**/*.t.sol : Test files must end with .t.sol and mirror the name of the contract they test (e.g., ExaPlugin.sol -> ExaPlugin.t.sol)
Applied to files:
server/package.json
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/database/schema.ts : Database schema must be defined in `server/database/schema.ts` as the single source of truth for database structure
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Use Drizzle ORM query builder for all database interactions; do not write raw SQL queries unless absolutely unavoidable
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/database/schema.ts : Define relations explicitly in the schema file to enable Drizzle to generate typed query results including related entities
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Enforce Drizzle ORM best practices using ESLint `plugin:drizzle/all` configuration, including requiring `where` clauses for `update` and `delete` operations
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-30T15:03:28.449Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/style.mdc:0-0
Timestamp: 2025-12-30T15:03:28.449Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Prefer self-documenting code; avoid comments explaining 'what' the code does; comments should explain 'why' code is written a certain way
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-31T00:20:09.555Z
Learnt from: cruzdanilo
Repo: exactly/exa PR: 610
File: server/test/database.ts:56-60
Timestamp: 2025-12-31T00:20:09.555Z
Learning: In server code: SIWE credentials store the Ethereum address as `publicKey` (20 bytes via `hexToBytes(address)`). The `decodePublicKey` utility has special handling for 20-byte inputs that bypasses COSE decoding, padding to 32 bytes for x-coordinate and using zero bytes for y-coordinate. Only passkey/WebAuthn credentials use COSE-encoded public keys.
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:56:56.405Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/dev.mdc:0-0
Timestamp: 2025-12-23T19:56:56.405Z
Learning: Server (exactly/server) uses Hono (framework), Node.js, Drizzle ORM (database), and PostgreSQL
Applied to files:
server/test/database.ts
🧬 Code graph analysis (5)
server/test/hooks/persona.test.ts (1)
server/database/schema.ts (1)
credentials(9-23)
server/test/api/kyc.test.ts (2)
server/database/schema.ts (1)
credentials(9-23)server/utils/persona.ts (2)
getInquiry(44-55)getAccount(36-42)
server/test/api/activity.test.ts (2)
common/deriveAddress.ts (1)
deriveAddress(18-55)server/database/schema.ts (1)
cards(25-34)
server/test/api/card.test.ts (3)
common/deriveAddress.ts (1)
deriveAddress(18-55)server/database/schema.ts (2)
credentials(9-23)cards(25-34)common/panda.ts (1)
SIGNATURE_PRODUCT_ID(2-2)
server/test/database.ts (1)
common/deriveAddress.ts (1)
deriveAddress(18-55)
🔇 Additional comments (30)
server/test/hooks/persona.test.ts (6)
1-17: LGTM: Import simplification aligns with test migration.The removal of account derivation imports and
beforeAllhook is consistent with the PR's goal of using fixed credential IDs instead of derived accounts. This simplifies the test setup significantly.
52-88: LGTM: Test properly isolates its own data.This test correctly creates its own credential with a unique ID and verifies that the webhook handler skips Panda account creation when
pandaIdalready exists. The test is self-contained and clear.
90-239: LGTM: Error handling tests are comprehensive.The tests properly verify:
- Missing credential scenario with mocked database query
- Invalid payload validation with appropriate error messages
- Webhook convention of returning 200 for all cases while logging errors
The use of
eslint-disable unicorn/no-useless-undefinedon line 91 is appropriate for explicitly mocking a return value.
242-262: LGTM: Payload referenceId aligns with fixed credential approach.The change from
"reference-123"to"bob"on line 262 is consistent with the PR's migration to fixed credential IDs. This matches the credential ID used in the test query on line 43.
42-45: Document or verify the "bob" credential setup.This test queries for a credential with
id: "bob"but doesn't create it within the test. This implies the credential is created in a global test setup (consistent with the PR's centralized test database approach). However, this dependency is not immediately clear from reading this test file.Consider either:
- Adding a comment explaining that "bob" is created in the global test setup
- Verifying that the test database setup in
server/test/database.tsproperly creates this credential#!/bin/bash # Verify that test database setup creates the "bob" credential rg -n -C5 'bob.*credential|insert.*credentials.*bob' server/test/
25-25: No action needed. The change from"test-session-123"to"test"for thesessionKeymock value is safe and follows best practices.The
sessionKeyvalidation only requires a string type with max 100 characters. Both values pass validation. More importantly, the mock'ssessionKeyvalue is not used in application logic—real session keys come from the request payload. The test has no assertions onsessionKey, so using simpler mock data is actually preferable.package.json (1)
234-235: LGTM!The embedded-postgres patch entry correctly supports the new test infrastructure migration.
server/package.json (2)
68-68: LGTM!The new dependencies correctly support the embedded PostgreSQL test infrastructure. The addition of
wait-onand its types will help ensure the database is ready before tests execute.Also applies to: 73-73, 83-83
145-145: LGTM!The wildcard pattern provides flexibility for multiple deployment scripts while maintaining the same directory structure requirement.
server/test/api/activity.test.ts (3)
20-23: LGTM!The fixed account constant using "bob" credentials provides deterministic test behavior and simplifies test setup.
40-56: LGTM!The validation tests correctly use distinct credential IDs: "activity" for error cases and "bob" for successful authentication flows.
65-66: LGTM!The card setup correctly references the fixed "bob" credential, maintaining consistency with the new test infrastructure approach.
server/test/api/kyc.test.ts (2)
19-19: LGTM!The database operations correctly reference the fixed "bob" credential ID, relying on the global test setup for credential seeding.
Also applies to: 49-49, 65-65
87-87: LGTM!All Persona API function calls consistently use "bob" as the reference ID, maintaining alignment with the fixed credential approach.
Also applies to: 107-107, 131-132, 155-155
server/vitest.config.mts (4)
7-7: LGTM!The addition of
test/database.tstoglobalSetupcorrectly integrates the embedded PostgreSQL instance into the test lifecycle.
8-10: LGTM!Coverage reporting enabled and timeouts increased appropriately for database and blockchain setup operations in tests.
31-31: LGTM!The full PostgreSQL connection string correctly configures the embedded instance with appropriate test credentials and disabled SSL for the local environment.
38-42: LGTM!The e2e-specific configuration appropriately customizes test discovery and reporting for end-to-end test scenarios.
server/test/api/card.test.ts (5)
24-57: LGTM!The test setup effectively uses a hybrid approach: fixed credential IDs for most tests and a derived account for blockchain operations. This balances test simplicity with realistic blockchain interaction testing.
62-142: LGTM!The card retrieval tests correctly use distinct credential IDs for different product types (platinum vs signature) and error scenarios.
172-191: LGTM!The card creation test correctly uses "sig" credential for both the request and database query, addressing the previous review feedback.
236-267: LGTM!The migration tests correctly handle card upgrades using the "default" credential, ensuring proper card lifecycle management during migrations.
271-301: LGTM!The test templates have been appropriately updated to use simplified IDs that align with the fixed credential approach.
patches/embedded-postgres.patch (1)
9-10: No action needed—cleanup is properly handled.The removal of
AsyncExitHook(gracefulShutdown)is intentional for the test environment. Theserver/test/database.tssetup function provides explicit cleanup: the returnedteardown()function callspostgres.stop(), the database client is closed withdatabase.$client.end(), and a spawned child process ensures the postgres instance is killed even if teardown is not called.server/test/database.ts (6)
1-13: LGTM: Imports are well-organized.All imports follow the project guidelines with proper use of
import typefor type-only imports and relative paths for project files.
15-23: LGTM: Database initialization follows best practices.The setup properly cleans up any existing data and configures the embedded PostgreSQL instance with appropriate test settings.
39-48: LGTM: Proper service readiness handling.The explicit wait for PostgreSQL on port 5432 (Line 39) ensures the database is ready before schema operations, preventing race conditions during test setup. The parallel execution of schema push and Anvil readiness check is efficient.
50-60: LGTM: Robust factory address extraction with validation.Using Valibot for runtime validation of the factory JSON structure provides type safety and clear error messages if the deployment output format changes.
61-66: LGTM: Test fixture setup with proper cleanup.The test credential setup correctly uses SIWE-compatible public key format (20-byte address), and properly closes the database connection after inserting the test data.
68-70: LGTM: Clean teardown implementation.The teardown function properly stops the embedded PostgreSQL instance, ensuring test resources are cleaned up after the test suite completes.
|
@cursor review |
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (14)
.changeset/ready-experts-fly.mdpackage.jsonpatches/embedded-postgres.patchserver/package.jsonserver/test/api/activity.test.tsserver/test/api/auth.test.tsserver/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/database.tsserver/test/hooks/activity.test.tsserver/test/hooks/panda.test.tsserver/test/hooks/persona.test.tsserver/test/mocks/database.tsserver/vitest.config.mts
💤 Files with no reviewable changes (4)
- server/test/hooks/panda.test.ts
- server/test/hooks/activity.test.ts
- server/test/mocks/database.ts
- server/test/api/auth.test.ts
🧰 Additional context used
📓 Path-based instructions (7)
server/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/server.mdc)
server/**/*.ts: Usec.varobject to pass strongly-typed data between Hono middleware and route handlers; do not usec.set
All request validation (headers, body, params) must be handled by@hono/valibot-validatormiddleware; do not perform manual validation inside route handlers
Use Hono's built-in error handling by throwingnew HTTPException()for expected errors; unhandled errors will be caught and logged automatically
Enforce Node.js best practices using ESLintplugin:n/recommendedconfiguration
Enforce Drizzle ORM best practices using ESLintplugin:drizzle/allconfiguration, including requiringwhereclauses forupdateanddeleteoperations
Use Drizzle ORM query builder for all database interactions; do not write raw SQL queries unless absolutely unavoidable
All authentication and authorization logic must be implemented in Hono middleware
Do not accessprocess.envdirectly in application code; load all configuration and secrets once at startup and pass them through dependency injection or context
Avoid long-running, synchronous operations; useasync/awaitcorrectly and be mindful of CPU-intensive tasks to prevent blocking the event loop
Files:
server/test/hooks/persona.test.tsserver/test/api/card.test.tsserver/test/database.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.ts
**/*.{js,ts,tsx,jsx,sol}
📄 CodeRabbit inference engine (AGENTS.md)
Follow linter/formatter (eslint, prettier, solhint) strictly with high strictness level. No
anytype.
Files:
server/test/hooks/persona.test.tsserver/test/api/card.test.tsserver/test/database.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Omit redundant type names in variable declarations - let the type system explain itself
**/*.{ts,tsx}: Use PascalCase for TypeScript types and interfaces
Use valibot for all runtime validation of API inputs, environment variables, and other data; define schemas once and reuse them
Infer TypeScript types from valibot schemas usingtype User = v.Input<typeof UserSchema>instead of manually defining interfaces
Files:
server/test/hooks/persona.test.tsserver/test/api/card.test.tsserver/test/database.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Omit contextual names - don't repeat class/module names in members
Omit meaningless words like 'data', 'state', 'manager', 'engine', 'value' from variable and function names unless they add disambiguation
**/*.{ts,tsx,js,jsx}: Prefer function declarations for all multi-line functions; use function expressions or arrow functions only for single-line implementations
Preferconstfor all variable declarations by default; only useletif the variable's value will be reassigned
Declare each variable on its own line with its ownconstorletkeyword, not multiple declarations on one line
Use camelCase for TypeScript variables and functions
Always useimport type { ... }for type imports
Use relative paths for all imports within the project; avoid tsconfig path aliases
Follow eslint-plugin-import order: react, external libraries, then relative paths
Use object and array destructuring to access and use properties
Use object method shorthand syntax when a function is a property of an object
Prefer optional chaining (?.), nullish coalescing (??), object and array spreading (...), andfor...ofloops over traditional syntax
Do not use abbreviations or cryptic names; write out full words likeerror,parameters,requestinstead oferr,params,req
UseNumber.parseInt()instead of the globalparseInt()function when parsing numbers
All classes called withnewmust use PascalCase
UseBuffer.from(),Buffer.alloc(), orBuffer.allocUnsafe()instead of the deprecatednew Buffer()
Use@ts-expect-errorinstead of@ts-ignore; follow it immediately with a single-line lowercase comment explaining why the error is expected, without separators like-or:
Do not include the type in a variable's name; let the static type system do its job (e.g., useconst user: Usernotconst userObject: User)
Do not repeat the name of a class or module within its members; omit contextual names (e.g., use `class User { getProfil...
Files:
server/test/hooks/persona.test.tsserver/test/api/card.test.tsserver/test/database.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.ts
server/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
server/**/*.{ts,tsx}: Server API: implement schema-first approach using OpenAPI via hono with validation via valibot middleware
Server database: drizzle schema is source of truth. Migrations required. No direct database access in handlers - usec.var.db
Files:
server/test/hooks/persona.test.tsserver/test/api/card.test.tsserver/test/database.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/style.mdc)
For files with a single
defaultexport, name the file identically to the export; for files with multiple exports, use camelCase with a strong preference for a single word
Files:
server/test/hooks/persona.test.tsserver/test/api/card.test.tsserver/test/database.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.ts
**/.changeset/*.md
📄 CodeRabbit inference engine (.cursor/rules/style.mdc)
Use a lowercase sentence in the imperative present tense for changeset summaries
Files:
.changeset/ready-experts-fly.md
🧠 Learnings (16)
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Applies to server/**/*.{ts,tsx} : Server database: drizzle schema is source of truth. Migrations required. No direct database access in handlers - use `c.var.db`
Applied to files:
server/package.jsonserver/test/database.ts
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Use `nx` for running tasks (build, lint, test, e2e) instead of underlying tooling directly
Applied to files:
server/package.json
📚 Learning: 2025-12-23T19:56:43.683Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-23T19:56:43.683Z
Learning: Applies to contracts/**/*.t.sol : Test files must end with .t.sol and mirror the name of the contract they test (e.g., ExaPlugin.sol -> ExaPlugin.t.sol)
Applied to files:
server/package.json
📚 Learning: 2025-12-23T19:56:43.683Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-23T19:56:43.683Z
Learning: Applies to contracts/**/*.t.sol : Use vm.prank to simulate calls from different addresses; avoid changing msg.sender through other means
Applied to files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.ts
📚 Learning: 2025-12-23T19:56:56.405Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/dev.mdc:0-0
Timestamp: 2025-12-23T19:56:56.405Z
Learning: Design all tests to run without `.env` files or external services
Applied to files:
server/test/hooks/persona.test.tsserver/test/api/kyc.test.ts
📚 Learning: 2025-12-23T19:58:16.574Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T19:58:16.574Z
Learning: Zero config local dev environment: no `.env` files, mock all external services
Applied to files:
server/test/api/card.test.tsserver/test/api/kyc.test.tsserver/test/api/activity.test.tsserver/vitest.config.mts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/database/schema.ts : Database schema must be defined in `server/database/schema.ts` as the single source of truth for database structure
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Use Drizzle ORM query builder for all database interactions; do not write raw SQL queries unless absolutely unavoidable
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-30T15:03:28.449Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/style.mdc:0-0
Timestamp: 2025-12-30T15:03:28.449Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Prefer self-documenting code; avoid comments explaining 'what' the code does; comments should explain 'why' code is written a certain way
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-31T00:20:09.555Z
Learnt from: cruzdanilo
Repo: exactly/exa PR: 610
File: server/test/database.ts:56-60
Timestamp: 2025-12-31T00:20:09.555Z
Learning: In server code: SIWE credentials store the Ethereum address as `publicKey` (20 bytes via `hexToBytes(address)`). The `decodePublicKey` utility has special handling for 20-byte inputs that bypasses COSE decoding, padding to 32 bytes for x-coordinate and using zero bytes for y-coordinate. Only passkey/WebAuthn credentials use COSE-encoded public keys.
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:56:56.405Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/dev.mdc:0-0
Timestamp: 2025-12-23T19:56:56.405Z
Learning: Server (exactly/server) uses Hono (framework), Node.js, Drizzle ORM (database), and PostgreSQL
Applied to files:
server/test/database.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/api/**/*.ts : The database client (`db`) should be passed via Hono's context (`c.var.db`), not imported directly into route handlers
Applied to files:
server/test/api/kyc.test.ts
📚 Learning: 2025-12-23T19:57:35.503Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/server.mdc:0-0
Timestamp: 2025-12-23T19:57:35.503Z
Learning: Applies to server/**/*.ts : Do not access `process.env` directly in application code; load all configuration and secrets once at startup and pass them through dependency injection or context
Applied to files:
server/vitest.config.mts
📚 Learning: 2025-12-31T00:23:55.034Z
Learnt from: cruzdanilo
Repo: exactly/exa PR: 610
File: .changeset/ready-experts-fly.md:1-2
Timestamp: 2025-12-31T00:23:55.034Z
Learning: In the exactly/exa repository, allow and require empty changeset files (containing only --- separators) when changes are not user-facing and do not warrant a version bump. This is needed because CI runs changeset status --since origin/main and requires a changeset file to exist. Ensure such empty changesets are used only for non-user-facing changes and document the rationale in the commit or changelog notes.
Applied to files:
.changeset/ready-experts-fly.md
📚 Learning: 2025-12-30T15:03:28.449Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/style.mdc:0-0
Timestamp: 2025-12-30T15:03:28.449Z
Learning: Applies to **/.changeset/*.md : Use a lowercase sentence in the imperative present tense for changeset summaries
Applied to files:
.changeset/ready-experts-fly.md
📚 Learning: 2025-12-30T15:03:28.449Z
Learnt from: CR
Repo: exactly/exa PR: 0
File: .cursor/rules/style.mdc:0-0
Timestamp: 2025-12-30T15:03:28.449Z
Learning: When implementing changes, follow all rules in `.mdc` files for any code, documentation, or rules you create, including meta-rules like the lowercase prose convention
Applied to files:
.changeset/ready-experts-fly.md
🧬 Code graph analysis (4)
server/test/hooks/persona.test.ts (1)
server/database/schema.ts (1)
credentials(9-23)
server/test/database.ts (1)
common/deriveAddress.ts (1)
deriveAddress(18-55)
server/test/api/kyc.test.ts (3)
server/database/schema.ts (1)
credentials(9-23)server/utils/persona.ts (2)
getInquiry(44-55)getAccount(36-42).maestro/src/server.ts (1)
persona(92-128)
server/test/api/activity.test.ts (4)
common/deriveAddress.ts (1)
deriveAddress(18-55).maestro/src/server.ts (1)
activity(20-46)server/api/activity.ts (8)
DebitActivity(473-476)DebitActivity(585-585)CreditActivity(478-488)CreditActivity(584-584)InstallmentsActivity(490-515)InstallmentsActivity(587-587)PandaActivity(300-369)PandaActivity(589-589)server/database/schema.ts (1)
cards(25-34)
🔇 Additional comments (13)
.changeset/ready-experts-fly.md (1)
1-2: Empty changeset is appropriate for this test infrastructure change.Based on learnings, this empty changeset correctly signals that no version bump is needed while satisfying the CI requirement for
changeset status --since origin/main.package.json (1)
234-235: LGTM!The patched dependencies are correctly configured to apply the embedded-postgres patch across the monorepo.
server/test/hooks/persona.test.ts (2)
23-24: Test data simplified with consistent IDs.The mock data now uses simpler, more consistent identifiers (
"pandaId"and"test"instead of"panda-id"and"test-session-123"), improving test readability.
42-42: The "bob" credential is properly seeded in the global test setup intest/database.ts(lines 58-62), where it is inserted withid: "bob"andpandaId: "pandaId". The test dependency is satisfied and the code is correct.server/test/api/activity.test.ts (1)
20-23: Good separation of account address and credential ID.The test now correctly derives an account address for blockchain operations while using the fixed credential ID
"bob"for database queries. This better reflects the production architecture where account addresses and credential IDs are distinct concepts.server/vitest.config.mts (2)
9-10: Timeouts increased to accommodate embedded PostgreSQL.The test and hook timeouts have been significantly increased to ~36 seconds, which is appropriate for the embedded PostgreSQL startup time. This aligns with the observed 66,666ms timeout in activity tests.
31-31: PostgreSQL connection parameters are correctly configured and match the embedded setup.The POSTGRES_URL in vitest.config.mts (
postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable) is identical to the connection string used in test/database.ts and aligns with the EmbeddedPostgres configuration (password: "postgres", port: 5432, database: postgres). The sslmode=disable parameter is appropriate for local testing.server/test/api/kyc.test.ts (2)
7-7: Test setup significantly simplified.The removal of
beforeAlland dynamic credential generation simplifies the test lifecycle. Tests now rely on the global setup intest/database.ts, making them more maintainable.
87-87: Consistent credential ID usage across assertions.All Persona API calls now use
"bob"as the reference ID, maintaining consistency with the credential lookup. This makes the test flow easier to follow and debug.patches/embedded-postgres.patch (1)
9-9: Shutdown is properly managed through explicit teardown.Removing the
AsyncExitHook(gracefulShutdown)registration means the embedded PostgreSQL instance will not automatically shut down on process exit. This is intentional—the test setup function explicitly manages shutdown by returning a teardown function that callspostgres.stop()(line 66 of server/test/database.ts). The setup also includes a custom process monitor that kills the postgres process with SIGINT when the test harness closes, ensuring graceful shutdown through the test framework's lifecycle rather than global exit hooks.server/package.json (1)
73-73: Consider the implications of using a beta version in CI/CD, or document why 18.1.0-beta.15 is required.The
embedded-postgresdependency uses version18.1.0-beta.15, which is a pre-release. While no known stability issues have been reported for this specific version, beta releases may introduce breaking changes or instability. If this version is necessary for required features, document the rationale. Otherwise, evaluate whether a stable version (e.g., 17.x) would be more appropriate for CI/CD reliability.server/test/database.ts (1)
15-67: LGTM: Test database setup is well-structured.The embedded PostgreSQL setup correctly:
- Provisions a clean database instance with proper lifecycle management
- Uses Drizzle ORM to push schema (schema-first approach)
- Waits for service readiness before proceeding
- Seeds test credentials with valid SIWE publicKey format (20-byte address via
hexToBytes)- Provides proper teardown for cleanup
The implementation follows coding guidelines and properly integrates with the test infrastructure.
server/test/api/card.test.ts (1)
22-269: Test migration to string-based IDs looks good.The test suite correctly:
- Uses fixed string credential IDs ("eth", "default", "sig", "404") consistently throughout
- Updates all header references and database queries to match
- Simplifies cleanup with shared database instance (line 60)
- Maintains proper test coverage for card operations, migration scenarios, and edge cases
The string-based approach aligns well with the single PostgreSQL instance test infrastructure.
Summary by CodeRabbit
Tests
Chores
Misc
✏️ Tip: You can customize this high-level summary in your review settings.