Conversation
📝 WalkthroughWalkthroughThis pull request integrates real eVault backend functionality into the trust-score service, replacing mocked implementations with actual registry resolution, platform token retrieval, and GraphQL queries. It adds comprehensive test coverage, a configuration endpoint, and a static test UI. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API as Express API
participant Config as Config Manager
participant Registry as Registry Service
participant eVault as eVault/GraphQL
Client->>API: POST /config<br/>{registryUrl}
API->>Config: setRegistryUrl(url)
Config->>Config: Store registry URL
API-->>Client: {ok: true, registryUrl}
Client->>API: GET /trust-score/{eName}
API->>Config: Retrieve stored registryUrl
API->>Registry: Resolve eName to eVault URL
Registry-->>API: eVault URL
API->>eVault: Fetch platform token<br/>(with cached token)
eVault-->>API: Bearer token
API->>eVault: POST GraphQL query<br/>fetchBindingDocuments
eVault-->>API: Binding documents array
API->>API: Extract verification status,<br/>account age, key location,<br/>social connections
API-->>Client: {score, verified, age, location, connections}
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ❌ 3❌ Failed checks (3 warnings)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
a73935e to
f1c5981
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
services/trust-score/package.json (1)
16-20: Remove unused GraphQL dependencies from package.json.The dependencies
graphqlandgraphql-requestare not imported anywhere in the service. The implementation sends raw GraphQL payloads throughaxiosand these packages are not used elsewhere inservices/trust-score. Remove both to reduce the runtime surface.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@services/trust-score/package.json` around lines 16 - 20, Remove the unused GraphQL dependencies from package.json by deleting the "graphql" and "graphql-request" entries; verify no code imports or references to graphql or graphql-request exist in the services/trust-score codebase (the service currently uses axios to send raw GraphQL payloads), then run npm/yarn install to update lockfile and CI to ensure build passes without those packages.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@services/ontology/schemas/reference.json`:
- Line 3: You changed the schemaId value in
services/ontology/schemas/reference.json from
7e94fada-581d-49b0-b6f5-1fe0766da360 to c20e9437-02a4-4917-8cee-de35dabbdb6a;
either revert the change or explicitly document and propagate it: update the
repository documentation and change-log to explain why schemaId was changed,
confirm the new UUID (c20e9437-02a4-4917-8cee-de35dabbdb6a) with the
eVault/integration owners and update any mapping tables or configuration that
reference schemaId (used by the ontology service indexing, w3ds-gateway
resolution, web3 adapter mapping, and eVault operations), and add a short note
in the PR description linking this backend schemaId change to the "frontend for
Trust Service" work so reviewers have the required context.
In `@services/trust-score/src/index.js`:
- Around line 23-29: The /config POST handler (app.post("/config")) currently
allows unauthenticated callers to call setRegistryUrl and must be protected:
replace the public handler with an authenticated-only operation by adding an
auth middleware or inline check that validates a server-side admin secret or
token (from an env var) and rejects requests with 401/403 if missing/invalid;
only call setRegistryUrl when the auth check passes and log the change. Also
ensure CORS is tightened (restrict allowed origins or remove the open policy) so
browsers on third-party sites cannot call this endpoint.
In `@services/trust-score/src/userDataService.js`:
- Around line 72-83: The _platformToken is cached indefinitely in
getPlatformToken and must be refreshed when downstream auth fails; modify the
code so that on 401/403 responses from eVault calls the cached _platformToken is
cleared and a new token is fetched by re-invoking getPlatformToken (or by making
getPlatformToken always refetch after a failed call), and ensure any caller
logic using _platformToken (refer to getPlatformToken and the code paths that
consume _platformToken around lines 56–60 and 109–120) retries the request once
after clearing the cache so transient/stale-token errors recover automatically.
- Around line 109-123: The GraphQL call using axios.post (graphqlUrl,
BINDING_DOCUMENTS_QUERY, ...) currently treats any 200 response with errors as
if bindingDocuments.edges is empty; update the code around the axios response
handling (the response variable and the access of
response.data?.data?.bindingDocuments?.edges) to check for response.data.errors
(or missing response.data.data) and surface/throw an error (or return a clear
failure) instead of defaulting to [] so downstream code does not compute a false
low score; ensure the new behavior logs or propagates the GraphQL error details
(including response.data.errors and the query variables) so callers can handle
the failure.
---
Nitpick comments:
In `@services/trust-score/package.json`:
- Around line 16-20: Remove the unused GraphQL dependencies from package.json by
deleting the "graphql" and "graphql-request" entries; verify no code imports or
references to graphql or graphql-request exist in the services/trust-score
codebase (the service currently uses axios to send raw GraphQL payloads), then
run npm/yarn install to update lockfile and CI to ensure build passes without
those packages.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4dcdb44d-b462-4271-b62b-52e4bcc86967
⛔ Files ignored due to path filters (2)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlservices/trust-score/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
services/ontology/schemas/reference.jsonservices/trust-score/package.jsonservices/trust-score/src/__tests__/userDataService.test.jsservices/trust-score/src/index.jsservices/trust-score/src/public/index.htmlservices/trust-score/src/userDataService.js
| { | ||
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "schemaId": "7e94fada-581d-49b0-b6f5-1fe0766da360", | ||
| "schemaId": "c20e9437-02a4-4917-8cee-de35dabbdb6a", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for the old schema ID in the codebase
echo "=== Searching for old schema ID: 7e94fada-581d-49b0-b6f5-1fe0766da360 ==="
rg -i "7e94fada-581d-49b0-b6f5-1fe0766da360" -C 3
echo -e "\n=== Searching for partial UUID patterns ==="
rg -i "7e94fada" -C 2Repository: MetaState-Prototype-Project/prototype
Length of output: 199
🏁 Script executed:
#!/bin/bash
# Look for database migrations, seed data, or test fixtures that might reference the old ID
echo "=== Checking migrations and seed data ==="
fd -e sql -e json -e yaml -e yml -x rg -l "7e94fada-581d-49b0-b6f5-1fe0766da360" {}
echo -e "\n=== Looking for migration scripts ==="
fd migration --exec cat {}Repository: MetaState-Prototype-Project/prototype
Length of output: 51395
🏁 Script executed:
#!/bin/bash
# Search for GraphQL queries that might use schemaId
echo "=== Searching for schemaId usage in GraphQL ==="
rg -i "schemaId" --type graphql -C 3
echo -e "\n=== Searching for schemaId in JS/TS files ==="
rg -i "schemaId" --type ts --type js -C 3
echo -e "\n=== Searching for reference schema usage ==="
rg -i "reference.*schema" --type ts --type js -C 2Repository: MetaState-Prototype-Project/prototype
Length of output: 50445
Remove or clarify the schema ID change—verify the new ID is documented and intentional.
The old schema ID (7e94fada-581d-49b0-b6f5-1fe0766da360) has no references in the codebase, so there are no direct breaking changes to existing code. However, the schemaId field is actively used throughout the system (ontology service indexing, w3ds-gateway resolution, web3 adapter mapping, and eVault operations), making this a structural change that requires:
- Documentation of why this schema ID is being changed or introduced
- Confirmation that the new ID (
c20e9437-02a4-4917-8cee-de35dabbdb6a) aligns with external eVault integration or system architecture - Clarification of the relationship to the PR's "frontend for Trust Service" objective (this is a backend schema change)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/ontology/schemas/reference.json` at line 3, You changed the schemaId
value in services/ontology/schemas/reference.json from
7e94fada-581d-49b0-b6f5-1fe0766da360 to c20e9437-02a4-4917-8cee-de35dabbdb6a;
either revert the change or explicitly document and propagate it: update the
repository documentation and change-log to explain why schemaId was changed,
confirm the new UUID (c20e9437-02a4-4917-8cee-de35dabbdb6a) with the
eVault/integration owners and update any mapping tables or configuration that
reference schemaId (used by the ontology service indexing, w3ds-gateway
resolution, web3 adapter mapping, and eVault operations), and add a short note
in the PR description linking this backend schemaId change to the "frontend for
Trust Service" work so reviewers have the required context.
| app.post("/config", (req, res) => { | ||
| const { registryUrl } = req.body; | ||
| if (!registryUrl || typeof registryUrl !== "string") { | ||
| return res.status(400).json({ error: "registryUrl is required" }); | ||
| } | ||
| setRegistryUrl(registryUrl); | ||
| return res.json({ ok: true, registryUrl }); |
There was a problem hiding this comment.
Do not expose /config as an unauthenticated public endpoint.
Any caller can rewrite the process-wide REGISTRY_URL for all users. Combined with the open CORS policy on Line 11, a third-party site can repoint this service at an arbitrary host and make the backend issue outbound requests there.
Suggested fix
app.post("/config", (req, res) => {
+ if (process.env.NODE_ENV === "production") {
+ return res.status(404).end();
+ }
+
const { registryUrl } = req.body;
if (!registryUrl || typeof registryUrl !== "string") {
return res.status(400).json({ error: "registryUrl is required" });
}
+
+ let parsed;
+ try {
+ parsed = new URL(registryUrl);
+ } catch {
+ return res.status(400).json({ error: "registryUrl must be a valid URL" });
+ }
+ if (!["http:", "https:"].includes(parsed.protocol)) {
+ return res.status(400).json({ error: "registryUrl must use http or https" });
+ }
+ if (!["localhost", "127.0.0.1"].includes(parsed.hostname)) {
+ return res.status(403).json({ error: "registryUrl is not allowed" });
+ }
+
setRegistryUrl(registryUrl);
return res.json({ ok: true, registryUrl });
});📝 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.
| app.post("/config", (req, res) => { | |
| const { registryUrl } = req.body; | |
| if (!registryUrl || typeof registryUrl !== "string") { | |
| return res.status(400).json({ error: "registryUrl is required" }); | |
| } | |
| setRegistryUrl(registryUrl); | |
| return res.json({ ok: true, registryUrl }); | |
| app.post("/config", (req, res) => { | |
| if (process.env.NODE_ENV === "production") { | |
| return res.status(404).end(); | |
| } | |
| const { registryUrl } = req.body; | |
| if (!registryUrl || typeof registryUrl !== "string") { | |
| return res.status(400).json({ error: "registryUrl is required" }); | |
| } | |
| let parsed; | |
| try { | |
| parsed = new URL(registryUrl); | |
| } catch { | |
| return res.status(400).json({ error: "registryUrl must be a valid URL" }); | |
| } | |
| if (!["http:", "https:"].includes(parsed.protocol)) { | |
| return res.status(400).json({ error: "registryUrl must use http or https" }); | |
| } | |
| if (!["localhost", "127.0.0.1"].includes(parsed.hostname)) { | |
| return res.status(403).json({ error: "registryUrl is not allowed" }); | |
| } | |
| setRegistryUrl(registryUrl); | |
| return res.json({ ok: true, registryUrl }); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/trust-score/src/index.js` around lines 23 - 29, The /config POST
handler (app.post("/config")) currently allows unauthenticated callers to call
setRegistryUrl and must be protected: replace the public handler with an
authenticated-only operation by adding an auth middleware or inline check that
validates a server-side admin secret or token (from an env var) and rejects
requests with 401/403 if missing/invalid; only call setRegistryUrl when the auth
check passes and log the change. Also ensure CORS is tightened (restrict allowed
origins or remove the open policy) so browsers on third-party sites cannot call
this endpoint.
| async function getPlatformToken() { | ||
| if (_platformToken) return _platformToken; | ||
|
|
||
| const endpoint = new URL("/platforms/certification", REGISTRY_URL).toString(); | ||
| const response = await axios.post( | ||
| endpoint, | ||
| { platform: "trust-score" }, | ||
| { timeout: 10_000 }, | ||
| ); | ||
| _platformToken = response.data.token; | ||
| return _platformToken; | ||
| } |
There was a problem hiding this comment.
Refresh the cached platform token after auth failures.
_platformToken is cached indefinitely here. Once eVault starts returning 401/403 for a stale token, every later request reuses the same credential, and services/trust-score/src/index.js:56-60 turns that into a permanent 500 until the process is restarted.
Suggested fix
async function fetchBindingDocuments(eName) {
const normalized = normalizeEName(eName);
const [evaultBaseUrl, token] = await Promise.all([
resolveEVaultUrl(normalized),
getPlatformToken(),
]);
const graphqlUrl = new URL("/graphql", evaultBaseUrl).toString();
+ const requestBindingDocuments = (bearerToken) =>
+ axios.post(
+ graphqlUrl,
+ { query: BINDING_DOCUMENTS_QUERY, variables: { first: 100 } },
+ {
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${bearerToken}`,
+ "X-ENAME": normalized,
+ },
+ timeout: 10_000,
+ },
+ );
- const response = await axios.post(
- graphqlUrl,
- { query: BINDING_DOCUMENTS_QUERY, variables: { first: 100 } },
- {
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${token}`,
- "X-ENAME": normalized,
- },
- timeout: 10_000,
- },
- );
+ let response;
+ try {
+ response = await requestBindingDocuments(token);
+ } catch (error) {
+ const status = error.response?.status;
+ if (status !== 401 && status !== 403) throw error;
+
+ clearPlatformToken();
+ response = await requestBindingDocuments(await getPlatformToken());
+ }Also applies to: 109-120
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/trust-score/src/userDataService.js` around lines 72 - 83, The
_platformToken is cached indefinitely in getPlatformToken and must be refreshed
when downstream auth fails; modify the code so that on 401/403 responses from
eVault calls the cached _platformToken is cleared and a new token is fetched by
re-invoking getPlatformToken (or by making getPlatformToken always refetch after
a failed call), and ensure any caller logic using _platformToken (refer to
getPlatformToken and the code paths that consume _platformToken around lines
56–60 and 109–120) retries the request once after clearing the cache so
transient/stale-token errors recover automatically.
| const response = await axios.post( | ||
| graphqlUrl, | ||
| { query: BINDING_DOCUMENTS_QUERY, variables: { first: 100 } }, | ||
| { | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| Authorization: `Bearer ${token}`, | ||
| "X-ENAME": normalized, | ||
| }, | ||
| timeout: 10_000, | ||
| }, | ||
| ); | ||
|
|
||
| const edges = response.data?.data?.bindingDocuments?.edges ?? []; | ||
|
|
There was a problem hiding this comment.
Do not treat GraphQL failures as an empty eVault.
A 200 response with errors currently falls through to edges ?? [], which makes downstream code compute a valid-looking low score from missing data instead of surfacing the failure.
Suggested fix
const response = await axios.post(
graphqlUrl,
{ query: BINDING_DOCUMENTS_QUERY, variables: { first: 100 } },
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
"X-ENAME": normalized,
},
timeout: 10_000,
},
);
- const edges = response.data?.data?.bindingDocuments?.edges ?? [];
+ if (Array.isArray(response.data?.errors) && response.data.errors.length > 0) {
+ const messages = response.data.errors
+ .map((error) => error.message)
+ .filter(Boolean)
+ .join("; ");
+ throw new Error(
+ `eVault GraphQL query failed${messages ? `: ${messages}` : ""}`,
+ );
+ }
+
+ const edges = response.data?.data?.bindingDocuments?.edges;
+ if (!Array.isArray(edges)) {
+ throw new Error("eVault GraphQL response is missing bindingDocuments.edges");
+ }
return edges🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/trust-score/src/userDataService.js` around lines 109 - 123, The
GraphQL call using axios.post (graphqlUrl, BINDING_DOCUMENTS_QUERY, ...)
currently treats any 200 response with errors as if bindingDocuments.edges is
empty; update the code around the axios response handling (the response variable
and the access of response.data?.data?.bindingDocuments?.edges) to check for
response.data.errors (or missing response.data.data) and surface/throw an error
(or return a clear failure) instead of defaulting to [] so downstream code does
not compute a false low score; ensure the new behavior logs or propagates the
GraphQL error details (including response.data.errors and the query variables)
so callers can handle the failure.
Description of change
Issue Number
Type of change
How the change has been tested
Change checklist
Summary by CodeRabbit
New Features
Tests
Chores