fix: local dev qol - #466

Closed
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol
Closed

fix: local dev qol#466
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol

Conversation

@sosweetham

@sosweethamsosweetham commented Nov 26, 2025

Copy link
Copy Markdown
Member

Description of change

adds missing script for postgres dev docker container

adds a script to get the wallet token

fixes some biome errors and runs formatter

Issue Number

n/a

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manual

Change checklist

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

Summary by CodeRabbit

  • New Features

    • Automated provisioning of multiple PostgreSQL databases.
    • Script to obtain a platform token for eid-wallet and new example env entry.
  • Bug Fixes

    • Improved Neo4j startup reliability by removing stale PID files before launch.
  • Chores

    • Broad formatting and type-safety updates, minor runtime logging added across services and UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds utility scripts (DB multi-create and eid-wallet token fetch), a Neo4j PID-cleanup wrapper in dev Docker compose, extra logging in eid-wallet onboarding, TypeScript/type-only import refinements and stricter schemas in evault-core HTTP routes, and small formatting/logging tweaks in registry services.

Changes

Cohort / File(s)Summary
DB init script
db/init-multiple-databases.sh
New Bash script that reads POSTGRES_MULTIPLE_DATABASES (comma-separated), trims entries, checks existence via psql, creates missing PostgreSQL databases, and prints status messages.
Token fetch script & env example
scripts/get-eid-wallet-token.sh, .env.example
New script posts to /platforms/certification to obtain eid-wallet token (jq or grep/sed fallback), validates output and prints instructions. .env.example appended with PUBLIC_EID_WALLET_TOKEN.
Dev Docker Compose (Neo4j cleanup)
dev-docker-compose.yaml
Neo4j service now uses an entrypoint/command wrapper that removes stale PID files from known locations (suppresses benign errors) then execs the original Neo4j startup script; healthcheck unchanged.
Client logging (eid-wallet)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Added console.log("Registry entropy:", registryEntropy) and console.log("Provision response:", provisionRes.data) for debugging; no control-flow changes.
Evault HTTP routes — types & schemas
infrastructure/evault-core/src/core/http/server.ts
Converted several imports to type-only, added/clarified request body schema for /provision, tightened type annotations on registerHttpRoutes, and reformatted route blocks; behavior preserved.
Registry formatting & logging tweaks
platforms/registry/src/index.ts, platforms/registry/src/services/HealthCheckService.ts, platforms/registry/src/services/VaultService.ts
Import reorderings, minor formatting and logging changes (including one console.log when generating entropy and one error logged as object literal); no API behavior changes.
Minor controller change
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
Reordered env var access and switched header assignment from headers["Authorization"] to headers.Authorization; no other behavior changes.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Client
participant Evault as Evault HTTP Server
participant Prov as ProvisioningService
participant DB as DbService
Client->>Evault: POST /provision {registryEntropy, namespace, verificationId, publicKey}
note right of Evault `#DDEBF7`: body validated by schema (type-only imports)
Evault->>Prov: provisionEVault(ProvisionRequest)
alt success
Prov-->>Evault: result
Evault-->>Client: 200 {result}
else failure
Prov-->>Evault: error
Evault-->>Client: 500 {error}
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • infrastructure/evault-core/src/core/http/server.ts (type-only imports, schema correctness, token validation paths)
    • db/init-multiple-databases.sh (psql invocation, quoting, heredoc behavior)
    • scripts/get-eid-wallet-token.sh (curl/jq fallback parsing and error handling)
    • dev-docker-compose.yaml (entrypoint/command wrapper permissions and exec behavior)

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • coodos
  • xPathin

Poem

🐇 I hopped through scripts and cleaned the ground,
I swept old PIDs so Neo4j's sound,
I fetched a token, parsed it with flair,
Tightened types and logs — a tidy affair,
Hooray — the rabbit left a carrot-shaped commit.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 33.33% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check❓ InconclusiveThe title 'fix: local dev qol' is vague and does not clearly convey the specific changes made in the pull request.Provide a more descriptive title that specifically mentions the key changes, such as 'fix: add postgres initialization and wallet token scripts' to better communicate the intent.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe pull request description includes all required template sections and clearly documents the changes made, testing performed, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/local-dev-qol

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c68b0 and 9f56234.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: test
🔇 Additional comments (3)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (3)

1-5: Import list reorder is fine

Reordering the PUBLIC_* imports is a no-op at runtime and keeps everything sourced from $env/static/public consistently. No issues here.


10-12: Good use of import type for UserController

Switching UserController to a type-only import aligns with TS best practices and keeps the runtime bundle leaner.


171-180: Authorization header assignment remains correct

Using headers.Authorization = \Bearer ${authToken}`on the pre-definedheaders: Record<string, string>` object is equivalent to the indexed form and keeps the conditional addition clear. No behavioural change, looks good.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

197-213: Gate new debug logs behind a dev flag to avoid leaking sensitive data

You’re logging registryEntropy and the full provision response, which is great for local debugging but exposes entropy tokens and identifiers in the browser console if this ships to production. Consider guarding these logs with a dev check:

- const registryEntropy = entropyRes.data.token;- console.log("Registry entropy:", registryEntropy);+ const registryEntropy = entropyRes.data.token;+ if (import.meta.env.DEV) {+ console.log("Registry entropy:", registryEntropy);+ }
@@
- );- console.log("Provision response:", provisionRes.data);+ );+ if (import.meta.env.DEV) {+ console.log("Provision response:", provisionRes.data);+ }
scripts/get-eid-wallet-token.sh (1)

3-45: Normalize REGISTRY_URL to avoid double slashes in request path

If PUBLIC_REGISTRY_URL is configured with a trailing / (e.g. https://registry.local/), the current concatenation will hit //platforms/certification, which some servers treat as a different path. You can harden this by stripping a trailing slash once:

-# Get the registry URL from environment or use default-REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+# Get the registry URL from environment or use default, strip trailing slash+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+REGISTRY_URL="${REGISTRY_URL%/}"

Everything else in this helper (curl error handling plus jq/grep fallback) looks good for local dev tooling. Based on learnings, this also avoids reintroducing the deprecated PUBLIC_PLATFORM_URL pattern and sticks to PUBLIC_REGISTRY_URL.

infrastructure/evault-core/src/core/http/server.ts (1)

295-363: Clarify token–eName binding in /public-key and reuse validateToken accordingly

The validateToken helper correctly verifies a Bearer JWT against the registry’s JWKS and returns its payload, but in the /public-key handler the payload is only checked for existence:

consttokenPayload=awaitvalidateToken(...);if(!tokenPayload){returnreply.status(401).send({error: "Invalid or missing authentication token"});}

There is no further check that the token is actually authorized to update the specific eName from X-ENAME (for example by matching a sub, ename, platform, or scope claim in tokenPayload).

If your security model expects tokens to be bound to a particular eName or platform, you likely want an additional check here (and a 403 if the token’s claims don’t authorize updating this eName). If, instead, any valid registry‑issued token is intentionally allowed to set any eName’s public key, the current behavior is fine but should be documented.

Also applies to: 423-464, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d94cea and e04ae8b.

⛔ Files ignored due to path filters (3)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml is excluded by !**/gen/**
📒 Files selected for processing (8)
  • db/init-multiple-databases.sh (1 hunks)
  • dev-docker-compose.yaml (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
  • infrastructure/evault-core/src/core/http/server.ts (3 hunks)
  • platforms/registry/src/index.ts (5 hunks)
  • platforms/registry/src/services/HealthCheckService.ts (4 hunks)
  • platforms/registry/src/services/VaultService.ts (1 hunks)
  • scripts/get-eid-wallet-token.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-13T10:34:52.527Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 415
File: infrastructure/eid-wallet/src/env.d.ts:8-8
Timestamp: 2025-11-13T10:34:52.527Z
Learning: In infrastructure/eid-wallet, PUBLIC_PLATFORM_URL should not be added to .env.example or configured as a static environment variable. The platform URL is extracted dynamically through URI parsing according to the protocol specification, and all fallbacks for platform URL are being removed.

Applied to files:

  • scripts/get-eid-wallet-token.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (5)
platforms/registry/src/services/HealthCheckService.ts (1)

1-87: LGTM! Formatting and code quality improvements with no behavioral changes.

The refactoring improves code consistency and readability:

  • Quote style standardization across imports and string literals
  • Multi-line formatting for complex expressions (regex, error logging) enhances readability
  • Number.parseInt on line 84 is a good practice over global parseInt

All logic remains unchanged and the improvements align with the PR's quality-of-life objective.

platforms/registry/src/services/VaultService.ts (1)

1-32: VaultService CRUD methods look correct and type usage is consistent

The switch to type-only imports and the repository-backed create/find/update/delete methods are all correct and side‑effect free. No functional or type issues spotted here.

db/init-multiple-databases.sh (1)

1-39: Multi-database init script is sensible and idempotent

The script cleanly handles an empty POSTGRES_MULTIPLE_DATABASES, trims entries, checks existence via pg_database, and only creates missing DBs. This is a solid fit for dev containers with the official Postgres entrypoint.

dev-docker-compose.yaml (1)

112-141: Neo4j PID cleanup and Postgres multi-DB wiring look correct for local dev

  • The Neo4j override (entrypoint: ["/bin/sh", "-c"] with a small shell prelude that removes stale *.pid files and then exec /startup/docker-entrypoint.sh neo4j) follows the pattern recommended in Neo4j’s own Docker docs and should resolve “stuck” dev containers due to leftover PIDs. (neo4j.com)
  • Mounting ./db/init-multiple-databases.sh into /docker-entrypoint-initdb.d together with POSTGRES_MULTIPLE_DATABASES is correct; just remember that these init scripts only run when the postgres_data volume is first created. If you later change the database list, you’ll need to recreate that volume for the script to run again.

Also applies to: 158-164

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

12-20: ---

Use Fastify's structured logger instead of console.log for production logging

The added console.log statements bypass Fastify's built-in Pino logger and produce unstructured output incompatible with log aggregation. Per Fastify best practices, replace with:

  • request.log.info("message") inside route handlers (includes automatic request context), or
  • fastify.log.info("message") for server-level events

This ensures consistent, structured logging. (Or wrap in a dev-only check if you want it only in dev environments.)

Also applies to: 41-51, 109-119

Comment on lines +55 to 84
// Whois endpoint - returns both W3ID identifier and public key
server.get(
"/whois",
{
schema: {
tags: ["identity"],
description: "Get eVault W3ID identifier and public key",
headers: {
type: "object",
required: ["X-ENAME"],
properties: {
"X-ENAME": { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
w3id: { type: "string" },
publicKey: { type: "string", nullable: true },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash# Check Fastify version and find the server filecd infrastructure/evault-core 2>/dev/null ||cd. find . -name "package.json" -type f | head -5 | xargs grep -l "fastify"2>/dev/null | head -3

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

./package.json

</shell_result>


Script executed:

#!/bin/bash# Check Fastify version
cat infrastructure/evault-core/package.json 2>/dev/null | grep -A2 -B2 "fastify"| head -20

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 },
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/formbody": "^8.0.2",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"fastify": "^4.26.2",
"graphql": "^16.10.0",
"graphql-type-json": "^0.3.2",

</shell_result>


Script executed:

#!/bin/bash# View the actual server.ts file to see the current state
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '1,100p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 1	import swagger from "@fastify/swagger";
2	import swaggerUi from "@fastify/swagger-ui";
3	import axios from "axios";
4	import fastify, { type FastifyInstance } from "fastify";
5	import * as jose from "jose";
6	import type {
7 ProvisionRequest,
8 ProvisioningService,
9	} from "../../services/ProvisioningService";
10	import type { DbService } from "../db/db.service";
11	import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
12 13	interface WatcherSignatureRequest {
14 w3id: string;
15 logEntryId: string;
16 proof: {
17 signature: string;
18 alg: string;
19 kid: string;
20 };
21	}
22 23	export async function registerHttpRoutes(
24 server: FastifyInstance,
25 evault: any, // EVault instance to access publicKey
26 provisioningService?: ProvisioningService,
27 dbService?: DbService,
28	): Promise<void> {
29 // Register Swagger
30 await server.register(swagger, {
31 swagger: {
32 info: {
33 title: "eVault Core API",
34 description: "API documentation for eVault Core HTTP endpoints",
35 version: "1.0.0",
36 },
37 tags: [
38 { name: "identity", description: "Identity related endpoints" },
39 {
40 name: "watchers",
41 description: "Watcher signature related endpoints",
42 },
43 {
44 name: "provisioning",
45 description: "eVault provisioning endpoints",
46 },
47 ],
48 },
49 });
50 51 await server.register(swaggerUi, {
52 routePrefix: "/docs",
53 });
54 55 // Whois endpoint - returns both W3ID identifier and public key
56 server.get(
57 "/whois",
58 {
59 schema: {
60 tags: ["identity"],
61 description: "Get eVault W3ID identifier and public key",
62 headers: {
63 type: "object",
64 required: ["X-ENAME"],
65 properties: {
66 "X-ENAME": { type: "string" },
67 },
68 },
69 response: {
70 200: {
71 type: "object",
72 properties: {
73 w3id: { type: "string" },
74 publicKey: { type: "string", nullable: true },
75 },
76 },
77 400: {
78 type: "object",
79 properties: {
80 error: { type: "string" },
81 },
82 },
83 },
84 },
85 },
86 async (request: TypedRequest<{}>, reply: TypedReply) => {
87 const eName =
88 request.headers["x-ename"] || request.headers["X-ENAME"];
89 90 if (!eName || typeof eName !== "string") {
91 return reply
92 .status(400)
93 .send({ error: "X-ENAME header is required" });
94 }
95 96 // Get public key from database if dbService is available
97 let publicKey: string | null = null;
98 if (dbService) {
99 try {
100 publicKey = await dbService.getPublicKey(eName);

</shell_result>


Fastify header validation case sensitivity JSON schema v5


<web_search_result>
Short answer: HTTP header names are case‑insensitive (RFC); Node lowercases header names on incoming messages; Fastify exposes those lowercased names on request.headers and therefore your JSON‑Schema (headers) should use lowercase property names. [1][2][3]

Sources

  • RFC 7230 (header field names are case‑insensitive). [3]
  • Fastify Request / Validation docs (Fastify uses request.headers and schema-based validation). [1]
  • Node.js HTTP docs (IncomingMessage/headers keys are lower-cased). [2]
    </web_search_result>

Script executed:

#!/bin/bash# View the /public-key and other endpoints mentioned in "Also applies to: 370-407"
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '350,420p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 350 if (error.code) {
351 console.error(`Token validation error code: ${error.code}`);
352 }
353 if (error.response) {
354 console.error(
355 `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
356 );
357 }
358 if (error.cause) {
359 console.error(`Token validation error cause:`, error.cause);
360 }
361 return null;
362 }
363 }
364 365 // PATCH endpoint to save public key
366 server.patch<{ Body: { publicKey: string } }>(
367 "/public-key",
368 {
369 schema: {
370 tags: ["identity"],
371 description: "Save public key for a user's eName",
372 headers: {
373 type: "object",
374 required: ["X-ENAME", "Authorization"],
375 properties: {
376 "X-ENAME": { type: "string" },
377 Authorization: { type: "string" },
378 },
379 },
380 body: {
381 type: "object",
382 required: ["publicKey"],
383 properties: {
384 publicKey: { type: "string" },
385 },
386 },
387 response: {
388 200: {
389 type: "object",
390 properties: {
391 success: { type: "boolean" },
392 message: { type: "string" },
393 },
394 },
395 400: {
396 type: "object",
397 properties: {
398 error: { type: "string" },
399 },
400 },
401 401: {
402 type: "object",
403 properties: {
404 error: { type: "string" },
405 },
406 },
407 },
408 },
409 },
410 async (
411 request: TypedRequest<{ publicKey: string }>,
412 reply: TypedReply,
413 ) => {
414 const eName =
415 request.headers["x-ename"] || request.headers["X-ENAME"];
416 417 if (!eName || typeof eName !== "string") {
418 return reply
419 .status(400)
420 .send({ error: "X-ENAME header is required" });

</shell_result>


Fix header schema casing to match Fastify's lower‑cased header keys

Fastify normalizes incoming header names to lower case, and JSON-schema validation must use lowercase property names to match. In your schemas at lines 64-66 and 374-377, you currently require mixed‑case headers:

  • /whois (line 64-66): requires "X-ENAME"
  • /public-key (line 374-377): requires "X-ENAME" and "Authorization"

Even if clients send X-ENAME or Authorization, Fastify's validator will reject the request with a 400 error because by the time validation runs, the header object only contains x-ename and authorization. The handler's fallback code checking both cases (lines 88 and 415) will never execute.

Update the schemas to use lowercase keys:

 // /whois (lines 62-68)
headers: {
type: "object",
- required: ["X-ENAME"],+ required: ["x-ename"],
properties: {
- "X-ENAME": { type: "string" },+ "x-ename": { type: "string" },
},
},
 // /public-key (lines 372-379)
headers: {
type: "object",
- required: ["X-ENAME", "Authorization"],+ required: ["x-ename", "authorization"],
properties: {
- "X-ENAME": { type: "string" },- Authorization: { type: "string" },+ "x-ename": { type: "string" },+ authorization: { type: "string" },
},
},

The handler code that reads request.headers["x-ename"] and request.headers.authorization can remain unchanged.

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

🤖 Prompt for AI Agents
in infrastructure/evault-core/src/core/http/server.ts around lines 55-84 (whois
schema) and around lines 370-380 (public-key schema), the JSON-schema header
property names use mixed-case ("X-ENAME", "Authorization") but Fastify
lowercases headers for validation; change the schema header property keys and
any entries in the required arrays to lowercase ("x-ename" and "authorization"
as applicable) so the validator matches incoming requests; leave the handler
code that reads request.headers["x-ename"] and request.headers.authorization
unchanged.

@sosweethamsosweetham mentioned this pull request Dec 3, 2025
6 tasks
@coodoscoodos closed this Dec 8, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sosweetham@coodos
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix: local dev qol - #466

Closed
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol
Closed

fix: local dev qol#466
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol

Conversation

@sosweetham

@sosweethamsosweetham commented Nov 26, 2025

Copy link
Copy Markdown
Member

Description of change

adds missing script for postgres dev docker container

adds a script to get the wallet token

fixes some biome errors and runs formatter

Issue Number

n/a

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manual

Change checklist

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

Summary by CodeRabbit

  • New Features

    • Automated provisioning of multiple PostgreSQL databases.
    • Script to obtain a platform token for eid-wallet and new example env entry.
  • Bug Fixes

    • Improved Neo4j startup reliability by removing stale PID files before launch.
  • Chores

    • Broad formatting and type-safety updates, minor runtime logging added across services and UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds utility scripts (DB multi-create and eid-wallet token fetch), a Neo4j PID-cleanup wrapper in dev Docker compose, extra logging in eid-wallet onboarding, TypeScript/type-only import refinements and stricter schemas in evault-core HTTP routes, and small formatting/logging tweaks in registry services.

Changes

Cohort / File(s)Summary
DB init script
db/init-multiple-databases.sh
New Bash script that reads POSTGRES_MULTIPLE_DATABASES (comma-separated), trims entries, checks existence via psql, creates missing PostgreSQL databases, and prints status messages.
Token fetch script & env example
scripts/get-eid-wallet-token.sh, .env.example
New script posts to /platforms/certification to obtain eid-wallet token (jq or grep/sed fallback), validates output and prints instructions. .env.example appended with PUBLIC_EID_WALLET_TOKEN.
Dev Docker Compose (Neo4j cleanup)
dev-docker-compose.yaml
Neo4j service now uses an entrypoint/command wrapper that removes stale PID files from known locations (suppresses benign errors) then execs the original Neo4j startup script; healthcheck unchanged.
Client logging (eid-wallet)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Added console.log("Registry entropy:", registryEntropy) and console.log("Provision response:", provisionRes.data) for debugging; no control-flow changes.
Evault HTTP routes — types & schemas
infrastructure/evault-core/src/core/http/server.ts
Converted several imports to type-only, added/clarified request body schema for /provision, tightened type annotations on registerHttpRoutes, and reformatted route blocks; behavior preserved.
Registry formatting & logging tweaks
platforms/registry/src/index.ts, platforms/registry/src/services/HealthCheckService.ts, platforms/registry/src/services/VaultService.ts
Import reorderings, minor formatting and logging changes (including one console.log when generating entropy and one error logged as object literal); no API behavior changes.
Minor controller change
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
Reordered env var access and switched header assignment from headers["Authorization"] to headers.Authorization; no other behavior changes.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Client
participant Evault as Evault HTTP Server
participant Prov as ProvisioningService
participant DB as DbService
Client->>Evault: POST /provision {registryEntropy, namespace, verificationId, publicKey}
note right of Evault `#DDEBF7`: body validated by schema (type-only imports)
Evault->>Prov: provisionEVault(ProvisionRequest)
alt success
Prov-->>Evault: result
Evault-->>Client: 200 {result}
else failure
Prov-->>Evault: error
Evault-->>Client: 500 {error}
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • infrastructure/evault-core/src/core/http/server.ts (type-only imports, schema correctness, token validation paths)
    • db/init-multiple-databases.sh (psql invocation, quoting, heredoc behavior)
    • scripts/get-eid-wallet-token.sh (curl/jq fallback parsing and error handling)
    • dev-docker-compose.yaml (entrypoint/command wrapper permissions and exec behavior)

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • coodos
  • xPathin

Poem

🐇 I hopped through scripts and cleaned the ground,
I swept old PIDs so Neo4j's sound,
I fetched a token, parsed it with flair,
Tightened types and logs — a tidy affair,
Hooray — the rabbit left a carrot-shaped commit.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 33.33% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check❓ InconclusiveThe title 'fix: local dev qol' is vague and does not clearly convey the specific changes made in the pull request.Provide a more descriptive title that specifically mentions the key changes, such as 'fix: add postgres initialization and wallet token scripts' to better communicate the intent.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe pull request description includes all required template sections and clearly documents the changes made, testing performed, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/local-dev-qol

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c68b0 and 9f56234.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: test
🔇 Additional comments (3)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (3)

1-5: Import list reorder is fine

Reordering the PUBLIC_* imports is a no-op at runtime and keeps everything sourced from $env/static/public consistently. No issues here.


10-12: Good use of import type for UserController

Switching UserController to a type-only import aligns with TS best practices and keeps the runtime bundle leaner.


171-180: Authorization header assignment remains correct

Using headers.Authorization = \Bearer ${authToken}`on the pre-definedheaders: Record<string, string>` object is equivalent to the indexed form and keeps the conditional addition clear. No behavioural change, looks good.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

197-213: Gate new debug logs behind a dev flag to avoid leaking sensitive data

You’re logging registryEntropy and the full provision response, which is great for local debugging but exposes entropy tokens and identifiers in the browser console if this ships to production. Consider guarding these logs with a dev check:

- const registryEntropy = entropyRes.data.token;- console.log("Registry entropy:", registryEntropy);+ const registryEntropy = entropyRes.data.token;+ if (import.meta.env.DEV) {+ console.log("Registry entropy:", registryEntropy);+ }
@@
- );- console.log("Provision response:", provisionRes.data);+ );+ if (import.meta.env.DEV) {+ console.log("Provision response:", provisionRes.data);+ }
scripts/get-eid-wallet-token.sh (1)

3-45: Normalize REGISTRY_URL to avoid double slashes in request path

If PUBLIC_REGISTRY_URL is configured with a trailing / (e.g. https://registry.local/), the current concatenation will hit //platforms/certification, which some servers treat as a different path. You can harden this by stripping a trailing slash once:

-# Get the registry URL from environment or use default-REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+# Get the registry URL from environment or use default, strip trailing slash+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+REGISTRY_URL="${REGISTRY_URL%/}"

Everything else in this helper (curl error handling plus jq/grep fallback) looks good for local dev tooling. Based on learnings, this also avoids reintroducing the deprecated PUBLIC_PLATFORM_URL pattern and sticks to PUBLIC_REGISTRY_URL.

infrastructure/evault-core/src/core/http/server.ts (1)

295-363: Clarify token–eName binding in /public-key and reuse validateToken accordingly

The validateToken helper correctly verifies a Bearer JWT against the registry’s JWKS and returns its payload, but in the /public-key handler the payload is only checked for existence:

consttokenPayload=awaitvalidateToken(...);if(!tokenPayload){returnreply.status(401).send({error: "Invalid or missing authentication token"});}

There is no further check that the token is actually authorized to update the specific eName from X-ENAME (for example by matching a sub, ename, platform, or scope claim in tokenPayload).

If your security model expects tokens to be bound to a particular eName or platform, you likely want an additional check here (and a 403 if the token’s claims don’t authorize updating this eName). If, instead, any valid registry‑issued token is intentionally allowed to set any eName’s public key, the current behavior is fine but should be documented.

Also applies to: 423-464, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d94cea and e04ae8b.

⛔ Files ignored due to path filters (3)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml is excluded by !**/gen/**
📒 Files selected for processing (8)
  • db/init-multiple-databases.sh (1 hunks)
  • dev-docker-compose.yaml (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
  • infrastructure/evault-core/src/core/http/server.ts (3 hunks)
  • platforms/registry/src/index.ts (5 hunks)
  • platforms/registry/src/services/HealthCheckService.ts (4 hunks)
  • platforms/registry/src/services/VaultService.ts (1 hunks)
  • scripts/get-eid-wallet-token.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-13T10:34:52.527Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 415
File: infrastructure/eid-wallet/src/env.d.ts:8-8
Timestamp: 2025-11-13T10:34:52.527Z
Learning: In infrastructure/eid-wallet, PUBLIC_PLATFORM_URL should not be added to .env.example or configured as a static environment variable. The platform URL is extracted dynamically through URI parsing according to the protocol specification, and all fallbacks for platform URL are being removed.

Applied to files:

  • scripts/get-eid-wallet-token.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (5)
platforms/registry/src/services/HealthCheckService.ts (1)

1-87: LGTM! Formatting and code quality improvements with no behavioral changes.

The refactoring improves code consistency and readability:

  • Quote style standardization across imports and string literals
  • Multi-line formatting for complex expressions (regex, error logging) enhances readability
  • Number.parseInt on line 84 is a good practice over global parseInt

All logic remains unchanged and the improvements align with the PR's quality-of-life objective.

platforms/registry/src/services/VaultService.ts (1)

1-32: VaultService CRUD methods look correct and type usage is consistent

The switch to type-only imports and the repository-backed create/find/update/delete methods are all correct and side‑effect free. No functional or type issues spotted here.

db/init-multiple-databases.sh (1)

1-39: Multi-database init script is sensible and idempotent

The script cleanly handles an empty POSTGRES_MULTIPLE_DATABASES, trims entries, checks existence via pg_database, and only creates missing DBs. This is a solid fit for dev containers with the official Postgres entrypoint.

dev-docker-compose.yaml (1)

112-141: Neo4j PID cleanup and Postgres multi-DB wiring look correct for local dev

  • The Neo4j override (entrypoint: ["/bin/sh", "-c"] with a small shell prelude that removes stale *.pid files and then exec /startup/docker-entrypoint.sh neo4j) follows the pattern recommended in Neo4j’s own Docker docs and should resolve “stuck” dev containers due to leftover PIDs. (neo4j.com)
  • Mounting ./db/init-multiple-databases.sh into /docker-entrypoint-initdb.d together with POSTGRES_MULTIPLE_DATABASES is correct; just remember that these init scripts only run when the postgres_data volume is first created. If you later change the database list, you’ll need to recreate that volume for the script to run again.

Also applies to: 158-164

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

12-20: ---

Use Fastify's structured logger instead of console.log for production logging

The added console.log statements bypass Fastify's built-in Pino logger and produce unstructured output incompatible with log aggregation. Per Fastify best practices, replace with:

  • request.log.info("message") inside route handlers (includes automatic request context), or
  • fastify.log.info("message") for server-level events

This ensures consistent, structured logging. (Or wrap in a dev-only check if you want it only in dev environments.)

Also applies to: 41-51, 109-119

Comment on lines +55 to 84
// Whois endpoint - returns both W3ID identifier and public key
server.get(
"/whois",
{
schema: {
tags: ["identity"],
description: "Get eVault W3ID identifier and public key",
headers: {
type: "object",
required: ["X-ENAME"],
properties: {
"X-ENAME": { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
w3id: { type: "string" },
publicKey: { type: "string", nullable: true },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash# Check Fastify version and find the server filecd infrastructure/evault-core 2>/dev/null ||cd. find . -name "package.json" -type f | head -5 | xargs grep -l "fastify"2>/dev/null | head -3

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

./package.json

</shell_result>


Script executed:

#!/bin/bash# Check Fastify version
cat infrastructure/evault-core/package.json 2>/dev/null | grep -A2 -B2 "fastify"| head -20

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 },
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/formbody": "^8.0.2",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"fastify": "^4.26.2",
"graphql": "^16.10.0",
"graphql-type-json": "^0.3.2",

</shell_result>


Script executed:

#!/bin/bash# View the actual server.ts file to see the current state
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '1,100p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 1	import swagger from "@fastify/swagger";
2	import swaggerUi from "@fastify/swagger-ui";
3	import axios from "axios";
4	import fastify, { type FastifyInstance } from "fastify";
5	import * as jose from "jose";
6	import type {
7 ProvisionRequest,
8 ProvisioningService,
9	} from "../../services/ProvisioningService";
10	import type { DbService } from "../db/db.service";
11	import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
12 13	interface WatcherSignatureRequest {
14 w3id: string;
15 logEntryId: string;
16 proof: {
17 signature: string;
18 alg: string;
19 kid: string;
20 };
21	}
22 23	export async function registerHttpRoutes(
24 server: FastifyInstance,
25 evault: any, // EVault instance to access publicKey
26 provisioningService?: ProvisioningService,
27 dbService?: DbService,
28	): Promise<void> {
29 // Register Swagger
30 await server.register(swagger, {
31 swagger: {
32 info: {
33 title: "eVault Core API",
34 description: "API documentation for eVault Core HTTP endpoints",
35 version: "1.0.0",
36 },
37 tags: [
38 { name: "identity", description: "Identity related endpoints" },
39 {
40 name: "watchers",
41 description: "Watcher signature related endpoints",
42 },
43 {
44 name: "provisioning",
45 description: "eVault provisioning endpoints",
46 },
47 ],
48 },
49 });
50 51 await server.register(swaggerUi, {
52 routePrefix: "/docs",
53 });
54 55 // Whois endpoint - returns both W3ID identifier and public key
56 server.get(
57 "/whois",
58 {
59 schema: {
60 tags: ["identity"],
61 description: "Get eVault W3ID identifier and public key",
62 headers: {
63 type: "object",
64 required: ["X-ENAME"],
65 properties: {
66 "X-ENAME": { type: "string" },
67 },
68 },
69 response: {
70 200: {
71 type: "object",
72 properties: {
73 w3id: { type: "string" },
74 publicKey: { type: "string", nullable: true },
75 },
76 },
77 400: {
78 type: "object",
79 properties: {
80 error: { type: "string" },
81 },
82 },
83 },
84 },
85 },
86 async (request: TypedRequest<{}>, reply: TypedReply) => {
87 const eName =
88 request.headers["x-ename"] || request.headers["X-ENAME"];
89 90 if (!eName || typeof eName !== "string") {
91 return reply
92 .status(400)
93 .send({ error: "X-ENAME header is required" });
94 }
95 96 // Get public key from database if dbService is available
97 let publicKey: string | null = null;
98 if (dbService) {
99 try {
100 publicKey = await dbService.getPublicKey(eName);

</shell_result>


Fastify header validation case sensitivity JSON schema v5


<web_search_result>
Short answer: HTTP header names are case‑insensitive (RFC); Node lowercases header names on incoming messages; Fastify exposes those lowercased names on request.headers and therefore your JSON‑Schema (headers) should use lowercase property names. [1][2][3]

Sources

  • RFC 7230 (header field names are case‑insensitive). [3]
  • Fastify Request / Validation docs (Fastify uses request.headers and schema-based validation). [1]
  • Node.js HTTP docs (IncomingMessage/headers keys are lower-cased). [2]
    </web_search_result>

Script executed:

#!/bin/bash# View the /public-key and other endpoints mentioned in "Also applies to: 370-407"
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '350,420p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 350 if (error.code) {
351 console.error(`Token validation error code: ${error.code}`);
352 }
353 if (error.response) {
354 console.error(
355 `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
356 );
357 }
358 if (error.cause) {
359 console.error(`Token validation error cause:`, error.cause);
360 }
361 return null;
362 }
363 }
364 365 // PATCH endpoint to save public key
366 server.patch<{ Body: { publicKey: string } }>(
367 "/public-key",
368 {
369 schema: {
370 tags: ["identity"],
371 description: "Save public key for a user's eName",
372 headers: {
373 type: "object",
374 required: ["X-ENAME", "Authorization"],
375 properties: {
376 "X-ENAME": { type: "string" },
377 Authorization: { type: "string" },
378 },
379 },
380 body: {
381 type: "object",
382 required: ["publicKey"],
383 properties: {
384 publicKey: { type: "string" },
385 },
386 },
387 response: {
388 200: {
389 type: "object",
390 properties: {
391 success: { type: "boolean" },
392 message: { type: "string" },
393 },
394 },
395 400: {
396 type: "object",
397 properties: {
398 error: { type: "string" },
399 },
400 },
401 401: {
402 type: "object",
403 properties: {
404 error: { type: "string" },
405 },
406 },
407 },
408 },
409 },
410 async (
411 request: TypedRequest<{ publicKey: string }>,
412 reply: TypedReply,
413 ) => {
414 const eName =
415 request.headers["x-ename"] || request.headers["X-ENAME"];
416 417 if (!eName || typeof eName !== "string") {
418 return reply
419 .status(400)
420 .send({ error: "X-ENAME header is required" });

</shell_result>


Fix header schema casing to match Fastify's lower‑cased header keys

Fastify normalizes incoming header names to lower case, and JSON-schema validation must use lowercase property names to match. In your schemas at lines 64-66 and 374-377, you currently require mixed‑case headers:

  • /whois (line 64-66): requires "X-ENAME"
  • /public-key (line 374-377): requires "X-ENAME" and "Authorization"

Even if clients send X-ENAME or Authorization, Fastify's validator will reject the request with a 400 error because by the time validation runs, the header object only contains x-ename and authorization. The handler's fallback code checking both cases (lines 88 and 415) will never execute.

Update the schemas to use lowercase keys:

 // /whois (lines 62-68)
headers: {
type: "object",
- required: ["X-ENAME"],+ required: ["x-ename"],
properties: {
- "X-ENAME": { type: "string" },+ "x-ename": { type: "string" },
},
},
 // /public-key (lines 372-379)
headers: {
type: "object",
- required: ["X-ENAME", "Authorization"],+ required: ["x-ename", "authorization"],
properties: {
- "X-ENAME": { type: "string" },- Authorization: { type: "string" },+ "x-ename": { type: "string" },+ authorization: { type: "string" },
},
},

The handler code that reads request.headers["x-ename"] and request.headers.authorization can remain unchanged.

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

🤖 Prompt for AI Agents
in infrastructure/evault-core/src/core/http/server.ts around lines 55-84 (whois
schema) and around lines 370-380 (public-key schema), the JSON-schema header
property names use mixed-case ("X-ENAME", "Authorization") but Fastify
lowercases headers for validation; change the schema header property keys and
any entries in the required arrays to lowercase ("x-ename" and "authorization"
as applicable) so the validator matches incoming requests; leave the handler
code that reads request.headers["x-ename"] and request.headers.authorization
unchanged.

@sosweethamsosweetham mentioned this pull request Dec 3, 2025
6 tasks
@coodoscoodos closed this Dec 8, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sosweetham@coodos
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: local dev qol - #466

Closed
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol
Closed

fix: local dev qol#466
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol

Conversation

@sosweetham

@sosweethamsosweetham commented Nov 26, 2025

Copy link
Copy Markdown
Member

Description of change

adds missing script for postgres dev docker container

adds a script to get the wallet token

fixes some biome errors and runs formatter

Issue Number

n/a

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manual

Change checklist

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

Summary by CodeRabbit

  • New Features

    • Automated provisioning of multiple PostgreSQL databases.
    • Script to obtain a platform token for eid-wallet and new example env entry.
  • Bug Fixes

    • Improved Neo4j startup reliability by removing stale PID files before launch.
  • Chores

    • Broad formatting and type-safety updates, minor runtime logging added across services and UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds utility scripts (DB multi-create and eid-wallet token fetch), a Neo4j PID-cleanup wrapper in dev Docker compose, extra logging in eid-wallet onboarding, TypeScript/type-only import refinements and stricter schemas in evault-core HTTP routes, and small formatting/logging tweaks in registry services.

Changes

Cohort / File(s)Summary
DB init script
db/init-multiple-databases.sh
New Bash script that reads POSTGRES_MULTIPLE_DATABASES (comma-separated), trims entries, checks existence via psql, creates missing PostgreSQL databases, and prints status messages.
Token fetch script & env example
scripts/get-eid-wallet-token.sh, .env.example
New script posts to /platforms/certification to obtain eid-wallet token (jq or grep/sed fallback), validates output and prints instructions. .env.example appended with PUBLIC_EID_WALLET_TOKEN.
Dev Docker Compose (Neo4j cleanup)
dev-docker-compose.yaml
Neo4j service now uses an entrypoint/command wrapper that removes stale PID files from known locations (suppresses benign errors) then execs the original Neo4j startup script; healthcheck unchanged.
Client logging (eid-wallet)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Added console.log("Registry entropy:", registryEntropy) and console.log("Provision response:", provisionRes.data) for debugging; no control-flow changes.
Evault HTTP routes — types & schemas
infrastructure/evault-core/src/core/http/server.ts
Converted several imports to type-only, added/clarified request body schema for /provision, tightened type annotations on registerHttpRoutes, and reformatted route blocks; behavior preserved.
Registry formatting & logging tweaks
platforms/registry/src/index.ts, platforms/registry/src/services/HealthCheckService.ts, platforms/registry/src/services/VaultService.ts
Import reorderings, minor formatting and logging changes (including one console.log when generating entropy and one error logged as object literal); no API behavior changes.
Minor controller change
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
Reordered env var access and switched header assignment from headers["Authorization"] to headers.Authorization; no other behavior changes.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Client
participant Evault as Evault HTTP Server
participant Prov as ProvisioningService
participant DB as DbService
Client->>Evault: POST /provision {registryEntropy, namespace, verificationId, publicKey}
note right of Evault `#DDEBF7`: body validated by schema (type-only imports)
Evault->>Prov: provisionEVault(ProvisionRequest)
alt success
Prov-->>Evault: result
Evault-->>Client: 200 {result}
else failure
Prov-->>Evault: error
Evault-->>Client: 500 {error}
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • infrastructure/evault-core/src/core/http/server.ts (type-only imports, schema correctness, token validation paths)
    • db/init-multiple-databases.sh (psql invocation, quoting, heredoc behavior)
    • scripts/get-eid-wallet-token.sh (curl/jq fallback parsing and error handling)
    • dev-docker-compose.yaml (entrypoint/command wrapper permissions and exec behavior)

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • coodos
  • xPathin

Poem

🐇 I hopped through scripts and cleaned the ground,
I swept old PIDs so Neo4j's sound,
I fetched a token, parsed it with flair,
Tightened types and logs — a tidy affair,
Hooray — the rabbit left a carrot-shaped commit.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 33.33% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check❓ InconclusiveThe title 'fix: local dev qol' is vague and does not clearly convey the specific changes made in the pull request.Provide a more descriptive title that specifically mentions the key changes, such as 'fix: add postgres initialization and wallet token scripts' to better communicate the intent.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe pull request description includes all required template sections and clearly documents the changes made, testing performed, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/local-dev-qol

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c68b0 and 9f56234.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: test
🔇 Additional comments (3)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (3)

1-5: Import list reorder is fine

Reordering the PUBLIC_* imports is a no-op at runtime and keeps everything sourced from $env/static/public consistently. No issues here.


10-12: Good use of import type for UserController

Switching UserController to a type-only import aligns with TS best practices and keeps the runtime bundle leaner.


171-180: Authorization header assignment remains correct

Using headers.Authorization = \Bearer ${authToken}`on the pre-definedheaders: Record<string, string>` object is equivalent to the indexed form and keeps the conditional addition clear. No behavioural change, looks good.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

197-213: Gate new debug logs behind a dev flag to avoid leaking sensitive data

You’re logging registryEntropy and the full provision response, which is great for local debugging but exposes entropy tokens and identifiers in the browser console if this ships to production. Consider guarding these logs with a dev check:

- const registryEntropy = entropyRes.data.token;- console.log("Registry entropy:", registryEntropy);+ const registryEntropy = entropyRes.data.token;+ if (import.meta.env.DEV) {+ console.log("Registry entropy:", registryEntropy);+ }
@@
- );- console.log("Provision response:", provisionRes.data);+ );+ if (import.meta.env.DEV) {+ console.log("Provision response:", provisionRes.data);+ }
scripts/get-eid-wallet-token.sh (1)

3-45: Normalize REGISTRY_URL to avoid double slashes in request path

If PUBLIC_REGISTRY_URL is configured with a trailing / (e.g. https://registry.local/), the current concatenation will hit //platforms/certification, which some servers treat as a different path. You can harden this by stripping a trailing slash once:

-# Get the registry URL from environment or use default-REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+# Get the registry URL from environment or use default, strip trailing slash+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+REGISTRY_URL="${REGISTRY_URL%/}"

Everything else in this helper (curl error handling plus jq/grep fallback) looks good for local dev tooling. Based on learnings, this also avoids reintroducing the deprecated PUBLIC_PLATFORM_URL pattern and sticks to PUBLIC_REGISTRY_URL.

infrastructure/evault-core/src/core/http/server.ts (1)

295-363: Clarify token–eName binding in /public-key and reuse validateToken accordingly

The validateToken helper correctly verifies a Bearer JWT against the registry’s JWKS and returns its payload, but in the /public-key handler the payload is only checked for existence:

consttokenPayload=awaitvalidateToken(...);if(!tokenPayload){returnreply.status(401).send({error: "Invalid or missing authentication token"});}

There is no further check that the token is actually authorized to update the specific eName from X-ENAME (for example by matching a sub, ename, platform, or scope claim in tokenPayload).

If your security model expects tokens to be bound to a particular eName or platform, you likely want an additional check here (and a 403 if the token’s claims don’t authorize updating this eName). If, instead, any valid registry‑issued token is intentionally allowed to set any eName’s public key, the current behavior is fine but should be documented.

Also applies to: 423-464, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d94cea and e04ae8b.

⛔ Files ignored due to path filters (3)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml is excluded by !**/gen/**
📒 Files selected for processing (8)
  • db/init-multiple-databases.sh (1 hunks)
  • dev-docker-compose.yaml (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
  • infrastructure/evault-core/src/core/http/server.ts (3 hunks)
  • platforms/registry/src/index.ts (5 hunks)
  • platforms/registry/src/services/HealthCheckService.ts (4 hunks)
  • platforms/registry/src/services/VaultService.ts (1 hunks)
  • scripts/get-eid-wallet-token.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-13T10:34:52.527Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 415
File: infrastructure/eid-wallet/src/env.d.ts:8-8
Timestamp: 2025-11-13T10:34:52.527Z
Learning: In infrastructure/eid-wallet, PUBLIC_PLATFORM_URL should not be added to .env.example or configured as a static environment variable. The platform URL is extracted dynamically through URI parsing according to the protocol specification, and all fallbacks for platform URL are being removed.

Applied to files:

  • scripts/get-eid-wallet-token.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (5)
platforms/registry/src/services/HealthCheckService.ts (1)

1-87: LGTM! Formatting and code quality improvements with no behavioral changes.

The refactoring improves code consistency and readability:

  • Quote style standardization across imports and string literals
  • Multi-line formatting for complex expressions (regex, error logging) enhances readability
  • Number.parseInt on line 84 is a good practice over global parseInt

All logic remains unchanged and the improvements align with the PR's quality-of-life objective.

platforms/registry/src/services/VaultService.ts (1)

1-32: VaultService CRUD methods look correct and type usage is consistent

The switch to type-only imports and the repository-backed create/find/update/delete methods are all correct and side‑effect free. No functional or type issues spotted here.

db/init-multiple-databases.sh (1)

1-39: Multi-database init script is sensible and idempotent

The script cleanly handles an empty POSTGRES_MULTIPLE_DATABASES, trims entries, checks existence via pg_database, and only creates missing DBs. This is a solid fit for dev containers with the official Postgres entrypoint.

dev-docker-compose.yaml (1)

112-141: Neo4j PID cleanup and Postgres multi-DB wiring look correct for local dev

  • The Neo4j override (entrypoint: ["/bin/sh", "-c"] with a small shell prelude that removes stale *.pid files and then exec /startup/docker-entrypoint.sh neo4j) follows the pattern recommended in Neo4j’s own Docker docs and should resolve “stuck” dev containers due to leftover PIDs. (neo4j.com)
  • Mounting ./db/init-multiple-databases.sh into /docker-entrypoint-initdb.d together with POSTGRES_MULTIPLE_DATABASES is correct; just remember that these init scripts only run when the postgres_data volume is first created. If you later change the database list, you’ll need to recreate that volume for the script to run again.

Also applies to: 158-164

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

12-20: ---

Use Fastify's structured logger instead of console.log for production logging

The added console.log statements bypass Fastify's built-in Pino logger and produce unstructured output incompatible with log aggregation. Per Fastify best practices, replace with:

  • request.log.info("message") inside route handlers (includes automatic request context), or
  • fastify.log.info("message") for server-level events

This ensures consistent, structured logging. (Or wrap in a dev-only check if you want it only in dev environments.)

Also applies to: 41-51, 109-119

Comment on lines +55 to 84
// Whois endpoint - returns both W3ID identifier and public key
server.get(
"/whois",
{
schema: {
tags: ["identity"],
description: "Get eVault W3ID identifier and public key",
headers: {
type: "object",
required: ["X-ENAME"],
properties: {
"X-ENAME": { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
w3id: { type: "string" },
publicKey: { type: "string", nullable: true },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash# Check Fastify version and find the server filecd infrastructure/evault-core 2>/dev/null ||cd. find . -name "package.json" -type f | head -5 | xargs grep -l "fastify"2>/dev/null | head -3

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

./package.json

</shell_result>


Script executed:

#!/bin/bash# Check Fastify version
cat infrastructure/evault-core/package.json 2>/dev/null | grep -A2 -B2 "fastify"| head -20

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 },
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/formbody": "^8.0.2",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"fastify": "^4.26.2",
"graphql": "^16.10.0",
"graphql-type-json": "^0.3.2",

</shell_result>


Script executed:

#!/bin/bash# View the actual server.ts file to see the current state
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '1,100p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 1	import swagger from "@fastify/swagger";
2	import swaggerUi from "@fastify/swagger-ui";
3	import axios from "axios";
4	import fastify, { type FastifyInstance } from "fastify";
5	import * as jose from "jose";
6	import type {
7 ProvisionRequest,
8 ProvisioningService,
9	} from "../../services/ProvisioningService";
10	import type { DbService } from "../db/db.service";
11	import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
12 13	interface WatcherSignatureRequest {
14 w3id: string;
15 logEntryId: string;
16 proof: {
17 signature: string;
18 alg: string;
19 kid: string;
20 };
21	}
22 23	export async function registerHttpRoutes(
24 server: FastifyInstance,
25 evault: any, // EVault instance to access publicKey
26 provisioningService?: ProvisioningService,
27 dbService?: DbService,
28	): Promise<void> {
29 // Register Swagger
30 await server.register(swagger, {
31 swagger: {
32 info: {
33 title: "eVault Core API",
34 description: "API documentation for eVault Core HTTP endpoints",
35 version: "1.0.0",
36 },
37 tags: [
38 { name: "identity", description: "Identity related endpoints" },
39 {
40 name: "watchers",
41 description: "Watcher signature related endpoints",
42 },
43 {
44 name: "provisioning",
45 description: "eVault provisioning endpoints",
46 },
47 ],
48 },
49 });
50 51 await server.register(swaggerUi, {
52 routePrefix: "/docs",
53 });
54 55 // Whois endpoint - returns both W3ID identifier and public key
56 server.get(
57 "/whois",
58 {
59 schema: {
60 tags: ["identity"],
61 description: "Get eVault W3ID identifier and public key",
62 headers: {
63 type: "object",
64 required: ["X-ENAME"],
65 properties: {
66 "X-ENAME": { type: "string" },
67 },
68 },
69 response: {
70 200: {
71 type: "object",
72 properties: {
73 w3id: { type: "string" },
74 publicKey: { type: "string", nullable: true },
75 },
76 },
77 400: {
78 type: "object",
79 properties: {
80 error: { type: "string" },
81 },
82 },
83 },
84 },
85 },
86 async (request: TypedRequest<{}>, reply: TypedReply) => {
87 const eName =
88 request.headers["x-ename"] || request.headers["X-ENAME"];
89 90 if (!eName || typeof eName !== "string") {
91 return reply
92 .status(400)
93 .send({ error: "X-ENAME header is required" });
94 }
95 96 // Get public key from database if dbService is available
97 let publicKey: string | null = null;
98 if (dbService) {
99 try {
100 publicKey = await dbService.getPublicKey(eName);

</shell_result>


Fastify header validation case sensitivity JSON schema v5


<web_search_result>
Short answer: HTTP header names are case‑insensitive (RFC); Node lowercases header names on incoming messages; Fastify exposes those lowercased names on request.headers and therefore your JSON‑Schema (headers) should use lowercase property names. [1][2][3]

Sources

  • RFC 7230 (header field names are case‑insensitive). [3]
  • Fastify Request / Validation docs (Fastify uses request.headers and schema-based validation). [1]
  • Node.js HTTP docs (IncomingMessage/headers keys are lower-cased). [2]
    </web_search_result>

Script executed:

#!/bin/bash# View the /public-key and other endpoints mentioned in "Also applies to: 370-407"
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '350,420p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 350 if (error.code) {
351 console.error(`Token validation error code: ${error.code}`);
352 }
353 if (error.response) {
354 console.error(
355 `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
356 );
357 }
358 if (error.cause) {
359 console.error(`Token validation error cause:`, error.cause);
360 }
361 return null;
362 }
363 }
364 365 // PATCH endpoint to save public key
366 server.patch<{ Body: { publicKey: string } }>(
367 "/public-key",
368 {
369 schema: {
370 tags: ["identity"],
371 description: "Save public key for a user's eName",
372 headers: {
373 type: "object",
374 required: ["X-ENAME", "Authorization"],
375 properties: {
376 "X-ENAME": { type: "string" },
377 Authorization: { type: "string" },
378 },
379 },
380 body: {
381 type: "object",
382 required: ["publicKey"],
383 properties: {
384 publicKey: { type: "string" },
385 },
386 },
387 response: {
388 200: {
389 type: "object",
390 properties: {
391 success: { type: "boolean" },
392 message: { type: "string" },
393 },
394 },
395 400: {
396 type: "object",
397 properties: {
398 error: { type: "string" },
399 },
400 },
401 401: {
402 type: "object",
403 properties: {
404 error: { type: "string" },
405 },
406 },
407 },
408 },
409 },
410 async (
411 request: TypedRequest<{ publicKey: string }>,
412 reply: TypedReply,
413 ) => {
414 const eName =
415 request.headers["x-ename"] || request.headers["X-ENAME"];
416 417 if (!eName || typeof eName !== "string") {
418 return reply
419 .status(400)
420 .send({ error: "X-ENAME header is required" });

</shell_result>


Fix header schema casing to match Fastify's lower‑cased header keys

Fastify normalizes incoming header names to lower case, and JSON-schema validation must use lowercase property names to match. In your schemas at lines 64-66 and 374-377, you currently require mixed‑case headers:

  • /whois (line 64-66): requires "X-ENAME"
  • /public-key (line 374-377): requires "X-ENAME" and "Authorization"

Even if clients send X-ENAME or Authorization, Fastify's validator will reject the request with a 400 error because by the time validation runs, the header object only contains x-ename and authorization. The handler's fallback code checking both cases (lines 88 and 415) will never execute.

Update the schemas to use lowercase keys:

 // /whois (lines 62-68)
headers: {
type: "object",
- required: ["X-ENAME"],+ required: ["x-ename"],
properties: {
- "X-ENAME": { type: "string" },+ "x-ename": { type: "string" },
},
},
 // /public-key (lines 372-379)
headers: {
type: "object",
- required: ["X-ENAME", "Authorization"],+ required: ["x-ename", "authorization"],
properties: {
- "X-ENAME": { type: "string" },- Authorization: { type: "string" },+ "x-ename": { type: "string" },+ authorization: { type: "string" },
},
},

The handler code that reads request.headers["x-ename"] and request.headers.authorization can remain unchanged.

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

🤖 Prompt for AI Agents
in infrastructure/evault-core/src/core/http/server.ts around lines 55-84 (whois
schema) and around lines 370-380 (public-key schema), the JSON-schema header
property names use mixed-case ("X-ENAME", "Authorization") but Fastify
lowercases headers for validation; change the schema header property keys and
any entries in the required arrays to lowercase ("x-ename" and "authorization"
as applicable) so the validator matches incoming requests; leave the handler
code that reads request.headers["x-ename"] and request.headers.authorization
unchanged.

@sosweethamsosweetham mentioned this pull request Dec 3, 2025
6 tasks
@coodoscoodos closed this Dec 8, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sosweetham@coodos
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: local dev qol - #466

Closed
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol
Closed

fix: local dev qol#466
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol

Conversation

@sosweetham

@sosweethamsosweetham commented Nov 26, 2025

Copy link
Copy Markdown
Member

Description of change

adds missing script for postgres dev docker container

adds a script to get the wallet token

fixes some biome errors and runs formatter

Issue Number

n/a

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manual

Change checklist

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

Summary by CodeRabbit

  • New Features

    • Automated provisioning of multiple PostgreSQL databases.
    • Script to obtain a platform token for eid-wallet and new example env entry.
  • Bug Fixes

    • Improved Neo4j startup reliability by removing stale PID files before launch.
  • Chores

    • Broad formatting and type-safety updates, minor runtime logging added across services and UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds utility scripts (DB multi-create and eid-wallet token fetch), a Neo4j PID-cleanup wrapper in dev Docker compose, extra logging in eid-wallet onboarding, TypeScript/type-only import refinements and stricter schemas in evault-core HTTP routes, and small formatting/logging tweaks in registry services.

Changes

Cohort / File(s)Summary
DB init script
db/init-multiple-databases.sh
New Bash script that reads POSTGRES_MULTIPLE_DATABASES (comma-separated), trims entries, checks existence via psql, creates missing PostgreSQL databases, and prints status messages.
Token fetch script & env example
scripts/get-eid-wallet-token.sh, .env.example
New script posts to /platforms/certification to obtain eid-wallet token (jq or grep/sed fallback), validates output and prints instructions. .env.example appended with PUBLIC_EID_WALLET_TOKEN.
Dev Docker Compose (Neo4j cleanup)
dev-docker-compose.yaml
Neo4j service now uses an entrypoint/command wrapper that removes stale PID files from known locations (suppresses benign errors) then execs the original Neo4j startup script; healthcheck unchanged.
Client logging (eid-wallet)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Added console.log("Registry entropy:", registryEntropy) and console.log("Provision response:", provisionRes.data) for debugging; no control-flow changes.
Evault HTTP routes — types & schemas
infrastructure/evault-core/src/core/http/server.ts
Converted several imports to type-only, added/clarified request body schema for /provision, tightened type annotations on registerHttpRoutes, and reformatted route blocks; behavior preserved.
Registry formatting & logging tweaks
platforms/registry/src/index.ts, platforms/registry/src/services/HealthCheckService.ts, platforms/registry/src/services/VaultService.ts
Import reorderings, minor formatting and logging changes (including one console.log when generating entropy and one error logged as object literal); no API behavior changes.
Minor controller change
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
Reordered env var access and switched header assignment from headers["Authorization"] to headers.Authorization; no other behavior changes.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Client
participant Evault as Evault HTTP Server
participant Prov as ProvisioningService
participant DB as DbService
Client->>Evault: POST /provision {registryEntropy, namespace, verificationId, publicKey}
note right of Evault `#DDEBF7`: body validated by schema (type-only imports)
Evault->>Prov: provisionEVault(ProvisionRequest)
alt success
Prov-->>Evault: result
Evault-->>Client: 200 {result}
else failure
Prov-->>Evault: error
Evault-->>Client: 500 {error}
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • infrastructure/evault-core/src/core/http/server.ts (type-only imports, schema correctness, token validation paths)
    • db/init-multiple-databases.sh (psql invocation, quoting, heredoc behavior)
    • scripts/get-eid-wallet-token.sh (curl/jq fallback parsing and error handling)
    • dev-docker-compose.yaml (entrypoint/command wrapper permissions and exec behavior)

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • coodos
  • xPathin

Poem

🐇 I hopped through scripts and cleaned the ground,
I swept old PIDs so Neo4j's sound,
I fetched a token, parsed it with flair,
Tightened types and logs — a tidy affair,
Hooray — the rabbit left a carrot-shaped commit.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 33.33% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check❓ InconclusiveThe title 'fix: local dev qol' is vague and does not clearly convey the specific changes made in the pull request.Provide a more descriptive title that specifically mentions the key changes, such as 'fix: add postgres initialization and wallet token scripts' to better communicate the intent.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe pull request description includes all required template sections and clearly documents the changes made, testing performed, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/local-dev-qol

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c68b0 and 9f56234.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: test
🔇 Additional comments (3)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (3)

1-5: Import list reorder is fine

Reordering the PUBLIC_* imports is a no-op at runtime and keeps everything sourced from $env/static/public consistently. No issues here.


10-12: Good use of import type for UserController

Switching UserController to a type-only import aligns with TS best practices and keeps the runtime bundle leaner.


171-180: Authorization header assignment remains correct

Using headers.Authorization = \Bearer ${authToken}`on the pre-definedheaders: Record<string, string>` object is equivalent to the indexed form and keeps the conditional addition clear. No behavioural change, looks good.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

197-213: Gate new debug logs behind a dev flag to avoid leaking sensitive data

You’re logging registryEntropy and the full provision response, which is great for local debugging but exposes entropy tokens and identifiers in the browser console if this ships to production. Consider guarding these logs with a dev check:

- const registryEntropy = entropyRes.data.token;- console.log("Registry entropy:", registryEntropy);+ const registryEntropy = entropyRes.data.token;+ if (import.meta.env.DEV) {+ console.log("Registry entropy:", registryEntropy);+ }
@@
- );- console.log("Provision response:", provisionRes.data);+ );+ if (import.meta.env.DEV) {+ console.log("Provision response:", provisionRes.data);+ }
scripts/get-eid-wallet-token.sh (1)

3-45: Normalize REGISTRY_URL to avoid double slashes in request path

If PUBLIC_REGISTRY_URL is configured with a trailing / (e.g. https://registry.local/), the current concatenation will hit //platforms/certification, which some servers treat as a different path. You can harden this by stripping a trailing slash once:

-# Get the registry URL from environment or use default-REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+# Get the registry URL from environment or use default, strip trailing slash+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+REGISTRY_URL="${REGISTRY_URL%/}"

Everything else in this helper (curl error handling plus jq/grep fallback) looks good for local dev tooling. Based on learnings, this also avoids reintroducing the deprecated PUBLIC_PLATFORM_URL pattern and sticks to PUBLIC_REGISTRY_URL.

infrastructure/evault-core/src/core/http/server.ts (1)

295-363: Clarify token–eName binding in /public-key and reuse validateToken accordingly

The validateToken helper correctly verifies a Bearer JWT against the registry’s JWKS and returns its payload, but in the /public-key handler the payload is only checked for existence:

consttokenPayload=awaitvalidateToken(...);if(!tokenPayload){returnreply.status(401).send({error: "Invalid or missing authentication token"});}

There is no further check that the token is actually authorized to update the specific eName from X-ENAME (for example by matching a sub, ename, platform, or scope claim in tokenPayload).

If your security model expects tokens to be bound to a particular eName or platform, you likely want an additional check here (and a 403 if the token’s claims don’t authorize updating this eName). If, instead, any valid registry‑issued token is intentionally allowed to set any eName’s public key, the current behavior is fine but should be documented.

Also applies to: 423-464, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d94cea and e04ae8b.

⛔ Files ignored due to path filters (3)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml is excluded by !**/gen/**
📒 Files selected for processing (8)
  • db/init-multiple-databases.sh (1 hunks)
  • dev-docker-compose.yaml (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
  • infrastructure/evault-core/src/core/http/server.ts (3 hunks)
  • platforms/registry/src/index.ts (5 hunks)
  • platforms/registry/src/services/HealthCheckService.ts (4 hunks)
  • platforms/registry/src/services/VaultService.ts (1 hunks)
  • scripts/get-eid-wallet-token.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-13T10:34:52.527Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 415
File: infrastructure/eid-wallet/src/env.d.ts:8-8
Timestamp: 2025-11-13T10:34:52.527Z
Learning: In infrastructure/eid-wallet, PUBLIC_PLATFORM_URL should not be added to .env.example or configured as a static environment variable. The platform URL is extracted dynamically through URI parsing according to the protocol specification, and all fallbacks for platform URL are being removed.

Applied to files:

  • scripts/get-eid-wallet-token.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (5)
platforms/registry/src/services/HealthCheckService.ts (1)

1-87: LGTM! Formatting and code quality improvements with no behavioral changes.

The refactoring improves code consistency and readability:

  • Quote style standardization across imports and string literals
  • Multi-line formatting for complex expressions (regex, error logging) enhances readability
  • Number.parseInt on line 84 is a good practice over global parseInt

All logic remains unchanged and the improvements align with the PR's quality-of-life objective.

platforms/registry/src/services/VaultService.ts (1)

1-32: VaultService CRUD methods look correct and type usage is consistent

The switch to type-only imports and the repository-backed create/find/update/delete methods are all correct and side‑effect free. No functional or type issues spotted here.

db/init-multiple-databases.sh (1)

1-39: Multi-database init script is sensible and idempotent

The script cleanly handles an empty POSTGRES_MULTIPLE_DATABASES, trims entries, checks existence via pg_database, and only creates missing DBs. This is a solid fit for dev containers with the official Postgres entrypoint.

dev-docker-compose.yaml (1)

112-141: Neo4j PID cleanup and Postgres multi-DB wiring look correct for local dev

  • The Neo4j override (entrypoint: ["/bin/sh", "-c"] with a small shell prelude that removes stale *.pid files and then exec /startup/docker-entrypoint.sh neo4j) follows the pattern recommended in Neo4j’s own Docker docs and should resolve “stuck” dev containers due to leftover PIDs. (neo4j.com)
  • Mounting ./db/init-multiple-databases.sh into /docker-entrypoint-initdb.d together with POSTGRES_MULTIPLE_DATABASES is correct; just remember that these init scripts only run when the postgres_data volume is first created. If you later change the database list, you’ll need to recreate that volume for the script to run again.

Also applies to: 158-164

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

12-20: ---

Use Fastify's structured logger instead of console.log for production logging

The added console.log statements bypass Fastify's built-in Pino logger and produce unstructured output incompatible with log aggregation. Per Fastify best practices, replace with:

  • request.log.info("message") inside route handlers (includes automatic request context), or
  • fastify.log.info("message") for server-level events

This ensures consistent, structured logging. (Or wrap in a dev-only check if you want it only in dev environments.)

Also applies to: 41-51, 109-119

Comment on lines +55 to 84
// Whois endpoint - returns both W3ID identifier and public key
server.get(
"/whois",
{
schema: {
tags: ["identity"],
description: "Get eVault W3ID identifier and public key",
headers: {
type: "object",
required: ["X-ENAME"],
properties: {
"X-ENAME": { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
w3id: { type: "string" },
publicKey: { type: "string", nullable: true },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash# Check Fastify version and find the server filecd infrastructure/evault-core 2>/dev/null ||cd. find . -name "package.json" -type f | head -5 | xargs grep -l "fastify"2>/dev/null | head -3

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

./package.json

</shell_result>


Script executed:

#!/bin/bash# Check Fastify version
cat infrastructure/evault-core/package.json 2>/dev/null | grep -A2 -B2 "fastify"| head -20

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 },
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/formbody": "^8.0.2",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"fastify": "^4.26.2",
"graphql": "^16.10.0",
"graphql-type-json": "^0.3.2",

</shell_result>


Script executed:

#!/bin/bash# View the actual server.ts file to see the current state
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '1,100p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 1	import swagger from "@fastify/swagger";
2	import swaggerUi from "@fastify/swagger-ui";
3	import axios from "axios";
4	import fastify, { type FastifyInstance } from "fastify";
5	import * as jose from "jose";
6	import type {
7 ProvisionRequest,
8 ProvisioningService,
9	} from "../../services/ProvisioningService";
10	import type { DbService } from "../db/db.service";
11	import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
12 13	interface WatcherSignatureRequest {
14 w3id: string;
15 logEntryId: string;
16 proof: {
17 signature: string;
18 alg: string;
19 kid: string;
20 };
21	}
22 23	export async function registerHttpRoutes(
24 server: FastifyInstance,
25 evault: any, // EVault instance to access publicKey
26 provisioningService?: ProvisioningService,
27 dbService?: DbService,
28	): Promise<void> {
29 // Register Swagger
30 await server.register(swagger, {
31 swagger: {
32 info: {
33 title: "eVault Core API",
34 description: "API documentation for eVault Core HTTP endpoints",
35 version: "1.0.0",
36 },
37 tags: [
38 { name: "identity", description: "Identity related endpoints" },
39 {
40 name: "watchers",
41 description: "Watcher signature related endpoints",
42 },
43 {
44 name: "provisioning",
45 description: "eVault provisioning endpoints",
46 },
47 ],
48 },
49 });
50 51 await server.register(swaggerUi, {
52 routePrefix: "/docs",
53 });
54 55 // Whois endpoint - returns both W3ID identifier and public key
56 server.get(
57 "/whois",
58 {
59 schema: {
60 tags: ["identity"],
61 description: "Get eVault W3ID identifier and public key",
62 headers: {
63 type: "object",
64 required: ["X-ENAME"],
65 properties: {
66 "X-ENAME": { type: "string" },
67 },
68 },
69 response: {
70 200: {
71 type: "object",
72 properties: {
73 w3id: { type: "string" },
74 publicKey: { type: "string", nullable: true },
75 },
76 },
77 400: {
78 type: "object",
79 properties: {
80 error: { type: "string" },
81 },
82 },
83 },
84 },
85 },
86 async (request: TypedRequest<{}>, reply: TypedReply) => {
87 const eName =
88 request.headers["x-ename"] || request.headers["X-ENAME"];
89 90 if (!eName || typeof eName !== "string") {
91 return reply
92 .status(400)
93 .send({ error: "X-ENAME header is required" });
94 }
95 96 // Get public key from database if dbService is available
97 let publicKey: string | null = null;
98 if (dbService) {
99 try {
100 publicKey = await dbService.getPublicKey(eName);

</shell_result>


Fastify header validation case sensitivity JSON schema v5


<web_search_result>
Short answer: HTTP header names are case‑insensitive (RFC); Node lowercases header names on incoming messages; Fastify exposes those lowercased names on request.headers and therefore your JSON‑Schema (headers) should use lowercase property names. [1][2][3]

Sources

  • RFC 7230 (header field names are case‑insensitive). [3]
  • Fastify Request / Validation docs (Fastify uses request.headers and schema-based validation). [1]
  • Node.js HTTP docs (IncomingMessage/headers keys are lower-cased). [2]
    </web_search_result>

Script executed:

#!/bin/bash# View the /public-key and other endpoints mentioned in "Also applies to: 370-407"
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '350,420p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 350 if (error.code) {
351 console.error(`Token validation error code: ${error.code}`);
352 }
353 if (error.response) {
354 console.error(
355 `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
356 );
357 }
358 if (error.cause) {
359 console.error(`Token validation error cause:`, error.cause);
360 }
361 return null;
362 }
363 }
364 365 // PATCH endpoint to save public key
366 server.patch<{ Body: { publicKey: string } }>(
367 "/public-key",
368 {
369 schema: {
370 tags: ["identity"],
371 description: "Save public key for a user's eName",
372 headers: {
373 type: "object",
374 required: ["X-ENAME", "Authorization"],
375 properties: {
376 "X-ENAME": { type: "string" },
377 Authorization: { type: "string" },
378 },
379 },
380 body: {
381 type: "object",
382 required: ["publicKey"],
383 properties: {
384 publicKey: { type: "string" },
385 },
386 },
387 response: {
388 200: {
389 type: "object",
390 properties: {
391 success: { type: "boolean" },
392 message: { type: "string" },
393 },
394 },
395 400: {
396 type: "object",
397 properties: {
398 error: { type: "string" },
399 },
400 },
401 401: {
402 type: "object",
403 properties: {
404 error: { type: "string" },
405 },
406 },
407 },
408 },
409 },
410 async (
411 request: TypedRequest<{ publicKey: string }>,
412 reply: TypedReply,
413 ) => {
414 const eName =
415 request.headers["x-ename"] || request.headers["X-ENAME"];
416 417 if (!eName || typeof eName !== "string") {
418 return reply
419 .status(400)
420 .send({ error: "X-ENAME header is required" });

</shell_result>


Fix header schema casing to match Fastify's lower‑cased header keys

Fastify normalizes incoming header names to lower case, and JSON-schema validation must use lowercase property names to match. In your schemas at lines 64-66 and 374-377, you currently require mixed‑case headers:

  • /whois (line 64-66): requires "X-ENAME"
  • /public-key (line 374-377): requires "X-ENAME" and "Authorization"

Even if clients send X-ENAME or Authorization, Fastify's validator will reject the request with a 400 error because by the time validation runs, the header object only contains x-ename and authorization. The handler's fallback code checking both cases (lines 88 and 415) will never execute.

Update the schemas to use lowercase keys:

 // /whois (lines 62-68)
headers: {
type: "object",
- required: ["X-ENAME"],+ required: ["x-ename"],
properties: {
- "X-ENAME": { type: "string" },+ "x-ename": { type: "string" },
},
},
 // /public-key (lines 372-379)
headers: {
type: "object",
- required: ["X-ENAME", "Authorization"],+ required: ["x-ename", "authorization"],
properties: {
- "X-ENAME": { type: "string" },- Authorization: { type: "string" },+ "x-ename": { type: "string" },+ authorization: { type: "string" },
},
},

The handler code that reads request.headers["x-ename"] and request.headers.authorization can remain unchanged.

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

🤖 Prompt for AI Agents
in infrastructure/evault-core/src/core/http/server.ts around lines 55-84 (whois
schema) and around lines 370-380 (public-key schema), the JSON-schema header
property names use mixed-case ("X-ENAME", "Authorization") but Fastify
lowercases headers for validation; change the schema header property keys and
any entries in the required arrays to lowercase ("x-ename" and "authorization"
as applicable) so the validator matches incoming requests; leave the handler
code that reads request.headers["x-ename"] and request.headers.authorization
unchanged.

@sosweethamsosweetham mentioned this pull request Dec 3, 2025
6 tasks
@coodoscoodos closed this Dec 8, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sosweetham@coodos
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix: local dev qol - #466

Closed
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol
Closed

fix: local dev qol#466
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol

Conversation

@sosweetham

@sosweethamsosweetham commented Nov 26, 2025

Copy link
Copy Markdown
Member

Description of change

adds missing script for postgres dev docker container

adds a script to get the wallet token

fixes some biome errors and runs formatter

Issue Number

n/a

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manual

Change checklist

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

Summary by CodeRabbit

  • New Features

    • Automated provisioning of multiple PostgreSQL databases.
    • Script to obtain a platform token for eid-wallet and new example env entry.
  • Bug Fixes

    • Improved Neo4j startup reliability by removing stale PID files before launch.
  • Chores

    • Broad formatting and type-safety updates, minor runtime logging added across services and UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds utility scripts (DB multi-create and eid-wallet token fetch), a Neo4j PID-cleanup wrapper in dev Docker compose, extra logging in eid-wallet onboarding, TypeScript/type-only import refinements and stricter schemas in evault-core HTTP routes, and small formatting/logging tweaks in registry services.

Changes

Cohort / File(s)Summary
DB init script
db/init-multiple-databases.sh
New Bash script that reads POSTGRES_MULTIPLE_DATABASES (comma-separated), trims entries, checks existence via psql, creates missing PostgreSQL databases, and prints status messages.
Token fetch script & env example
scripts/get-eid-wallet-token.sh, .env.example
New script posts to /platforms/certification to obtain eid-wallet token (jq or grep/sed fallback), validates output and prints instructions. .env.example appended with PUBLIC_EID_WALLET_TOKEN.
Dev Docker Compose (Neo4j cleanup)
dev-docker-compose.yaml
Neo4j service now uses an entrypoint/command wrapper that removes stale PID files from known locations (suppresses benign errors) then execs the original Neo4j startup script; healthcheck unchanged.
Client logging (eid-wallet)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Added console.log("Registry entropy:", registryEntropy) and console.log("Provision response:", provisionRes.data) for debugging; no control-flow changes.
Evault HTTP routes — types & schemas
infrastructure/evault-core/src/core/http/server.ts
Converted several imports to type-only, added/clarified request body schema for /provision, tightened type annotations on registerHttpRoutes, and reformatted route blocks; behavior preserved.
Registry formatting & logging tweaks
platforms/registry/src/index.ts, platforms/registry/src/services/HealthCheckService.ts, platforms/registry/src/services/VaultService.ts
Import reorderings, minor formatting and logging changes (including one console.log when generating entropy and one error logged as object literal); no API behavior changes.
Minor controller change
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
Reordered env var access and switched header assignment from headers["Authorization"] to headers.Authorization; no other behavior changes.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Client
participant Evault as Evault HTTP Server
participant Prov as ProvisioningService
participant DB as DbService
Client->>Evault: POST /provision {registryEntropy, namespace, verificationId, publicKey}
note right of Evault `#DDEBF7`: body validated by schema (type-only imports)
Evault->>Prov: provisionEVault(ProvisionRequest)
alt success
Prov-->>Evault: result
Evault-->>Client: 200 {result}
else failure
Prov-->>Evault: error
Evault-->>Client: 500 {error}
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • infrastructure/evault-core/src/core/http/server.ts (type-only imports, schema correctness, token validation paths)
    • db/init-multiple-databases.sh (psql invocation, quoting, heredoc behavior)
    • scripts/get-eid-wallet-token.sh (curl/jq fallback parsing and error handling)
    • dev-docker-compose.yaml (entrypoint/command wrapper permissions and exec behavior)

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • coodos
  • xPathin

Poem

🐇 I hopped through scripts and cleaned the ground,
I swept old PIDs so Neo4j's sound,
I fetched a token, parsed it with flair,
Tightened types and logs — a tidy affair,
Hooray — the rabbit left a carrot-shaped commit.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 33.33% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check❓ InconclusiveThe title 'fix: local dev qol' is vague and does not clearly convey the specific changes made in the pull request.Provide a more descriptive title that specifically mentions the key changes, such as 'fix: add postgres initialization and wallet token scripts' to better communicate the intent.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe pull request description includes all required template sections and clearly documents the changes made, testing performed, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/local-dev-qol

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c68b0 and 9f56234.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: test
🔇 Additional comments (3)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (3)

1-5: Import list reorder is fine

Reordering the PUBLIC_* imports is a no-op at runtime and keeps everything sourced from $env/static/public consistently. No issues here.


10-12: Good use of import type for UserController

Switching UserController to a type-only import aligns with TS best practices and keeps the runtime bundle leaner.


171-180: Authorization header assignment remains correct

Using headers.Authorization = \Bearer ${authToken}`on the pre-definedheaders: Record<string, string>` object is equivalent to the indexed form and keeps the conditional addition clear. No behavioural change, looks good.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

197-213: Gate new debug logs behind a dev flag to avoid leaking sensitive data

You’re logging registryEntropy and the full provision response, which is great for local debugging but exposes entropy tokens and identifiers in the browser console if this ships to production. Consider guarding these logs with a dev check:

- const registryEntropy = entropyRes.data.token;- console.log("Registry entropy:", registryEntropy);+ const registryEntropy = entropyRes.data.token;+ if (import.meta.env.DEV) {+ console.log("Registry entropy:", registryEntropy);+ }
@@
- );- console.log("Provision response:", provisionRes.data);+ );+ if (import.meta.env.DEV) {+ console.log("Provision response:", provisionRes.data);+ }
scripts/get-eid-wallet-token.sh (1)

3-45: Normalize REGISTRY_URL to avoid double slashes in request path

If PUBLIC_REGISTRY_URL is configured with a trailing / (e.g. https://registry.local/), the current concatenation will hit //platforms/certification, which some servers treat as a different path. You can harden this by stripping a trailing slash once:

-# Get the registry URL from environment or use default-REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+# Get the registry URL from environment or use default, strip trailing slash+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+REGISTRY_URL="${REGISTRY_URL%/}"

Everything else in this helper (curl error handling plus jq/grep fallback) looks good for local dev tooling. Based on learnings, this also avoids reintroducing the deprecated PUBLIC_PLATFORM_URL pattern and sticks to PUBLIC_REGISTRY_URL.

infrastructure/evault-core/src/core/http/server.ts (1)

295-363: Clarify token–eName binding in /public-key and reuse validateToken accordingly

The validateToken helper correctly verifies a Bearer JWT against the registry’s JWKS and returns its payload, but in the /public-key handler the payload is only checked for existence:

consttokenPayload=awaitvalidateToken(...);if(!tokenPayload){returnreply.status(401).send({error: "Invalid or missing authentication token"});}

There is no further check that the token is actually authorized to update the specific eName from X-ENAME (for example by matching a sub, ename, platform, or scope claim in tokenPayload).

If your security model expects tokens to be bound to a particular eName or platform, you likely want an additional check here (and a 403 if the token’s claims don’t authorize updating this eName). If, instead, any valid registry‑issued token is intentionally allowed to set any eName’s public key, the current behavior is fine but should be documented.

Also applies to: 423-464, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d94cea and e04ae8b.

⛔ Files ignored due to path filters (3)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml is excluded by !**/gen/**
📒 Files selected for processing (8)
  • db/init-multiple-databases.sh (1 hunks)
  • dev-docker-compose.yaml (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
  • infrastructure/evault-core/src/core/http/server.ts (3 hunks)
  • platforms/registry/src/index.ts (5 hunks)
  • platforms/registry/src/services/HealthCheckService.ts (4 hunks)
  • platforms/registry/src/services/VaultService.ts (1 hunks)
  • scripts/get-eid-wallet-token.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-13T10:34:52.527Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 415
File: infrastructure/eid-wallet/src/env.d.ts:8-8
Timestamp: 2025-11-13T10:34:52.527Z
Learning: In infrastructure/eid-wallet, PUBLIC_PLATFORM_URL should not be added to .env.example or configured as a static environment variable. The platform URL is extracted dynamically through URI parsing according to the protocol specification, and all fallbacks for platform URL are being removed.

Applied to files:

  • scripts/get-eid-wallet-token.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (5)
platforms/registry/src/services/HealthCheckService.ts (1)

1-87: LGTM! Formatting and code quality improvements with no behavioral changes.

The refactoring improves code consistency and readability:

  • Quote style standardization across imports and string literals
  • Multi-line formatting for complex expressions (regex, error logging) enhances readability
  • Number.parseInt on line 84 is a good practice over global parseInt

All logic remains unchanged and the improvements align with the PR's quality-of-life objective.

platforms/registry/src/services/VaultService.ts (1)

1-32: VaultService CRUD methods look correct and type usage is consistent

The switch to type-only imports and the repository-backed create/find/update/delete methods are all correct and side‑effect free. No functional or type issues spotted here.

db/init-multiple-databases.sh (1)

1-39: Multi-database init script is sensible and idempotent

The script cleanly handles an empty POSTGRES_MULTIPLE_DATABASES, trims entries, checks existence via pg_database, and only creates missing DBs. This is a solid fit for dev containers with the official Postgres entrypoint.

dev-docker-compose.yaml (1)

112-141: Neo4j PID cleanup and Postgres multi-DB wiring look correct for local dev

  • The Neo4j override (entrypoint: ["/bin/sh", "-c"] with a small shell prelude that removes stale *.pid files and then exec /startup/docker-entrypoint.sh neo4j) follows the pattern recommended in Neo4j’s own Docker docs and should resolve “stuck” dev containers due to leftover PIDs. (neo4j.com)
  • Mounting ./db/init-multiple-databases.sh into /docker-entrypoint-initdb.d together with POSTGRES_MULTIPLE_DATABASES is correct; just remember that these init scripts only run when the postgres_data volume is first created. If you later change the database list, you’ll need to recreate that volume for the script to run again.

Also applies to: 158-164

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

12-20: ---

Use Fastify's structured logger instead of console.log for production logging

The added console.log statements bypass Fastify's built-in Pino logger and produce unstructured output incompatible with log aggregation. Per Fastify best practices, replace with:

  • request.log.info("message") inside route handlers (includes automatic request context), or
  • fastify.log.info("message") for server-level events

This ensures consistent, structured logging. (Or wrap in a dev-only check if you want it only in dev environments.)

Also applies to: 41-51, 109-119

Comment on lines +55 to 84
// Whois endpoint - returns both W3ID identifier and public key
server.get(
"/whois",
{
schema: {
tags: ["identity"],
description: "Get eVault W3ID identifier and public key",
headers: {
type: "object",
required: ["X-ENAME"],
properties: {
"X-ENAME": { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
w3id: { type: "string" },
publicKey: { type: "string", nullable: true },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash# Check Fastify version and find the server filecd infrastructure/evault-core 2>/dev/null ||cd. find . -name "package.json" -type f | head -5 | xargs grep -l "fastify"2>/dev/null | head -3

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

./package.json

</shell_result>


Script executed:

#!/bin/bash# Check Fastify version
cat infrastructure/evault-core/package.json 2>/dev/null | grep -A2 -B2 "fastify"| head -20

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 },
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/formbody": "^8.0.2",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"fastify": "^4.26.2",
"graphql": "^16.10.0",
"graphql-type-json": "^0.3.2",

</shell_result>


Script executed:

#!/bin/bash# View the actual server.ts file to see the current state
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '1,100p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 1	import swagger from "@fastify/swagger";
2	import swaggerUi from "@fastify/swagger-ui";
3	import axios from "axios";
4	import fastify, { type FastifyInstance } from "fastify";
5	import * as jose from "jose";
6	import type {
7 ProvisionRequest,
8 ProvisioningService,
9	} from "../../services/ProvisioningService";
10	import type { DbService } from "../db/db.service";
11	import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
12 13	interface WatcherSignatureRequest {
14 w3id: string;
15 logEntryId: string;
16 proof: {
17 signature: string;
18 alg: string;
19 kid: string;
20 };
21	}
22 23	export async function registerHttpRoutes(
24 server: FastifyInstance,
25 evault: any, // EVault instance to access publicKey
26 provisioningService?: ProvisioningService,
27 dbService?: DbService,
28	): Promise<void> {
29 // Register Swagger
30 await server.register(swagger, {
31 swagger: {
32 info: {
33 title: "eVault Core API",
34 description: "API documentation for eVault Core HTTP endpoints",
35 version: "1.0.0",
36 },
37 tags: [
38 { name: "identity", description: "Identity related endpoints" },
39 {
40 name: "watchers",
41 description: "Watcher signature related endpoints",
42 },
43 {
44 name: "provisioning",
45 description: "eVault provisioning endpoints",
46 },
47 ],
48 },
49 });
50 51 await server.register(swaggerUi, {
52 routePrefix: "/docs",
53 });
54 55 // Whois endpoint - returns both W3ID identifier and public key
56 server.get(
57 "/whois",
58 {
59 schema: {
60 tags: ["identity"],
61 description: "Get eVault W3ID identifier and public key",
62 headers: {
63 type: "object",
64 required: ["X-ENAME"],
65 properties: {
66 "X-ENAME": { type: "string" },
67 },
68 },
69 response: {
70 200: {
71 type: "object",
72 properties: {
73 w3id: { type: "string" },
74 publicKey: { type: "string", nullable: true },
75 },
76 },
77 400: {
78 type: "object",
79 properties: {
80 error: { type: "string" },
81 },
82 },
83 },
84 },
85 },
86 async (request: TypedRequest<{}>, reply: TypedReply) => {
87 const eName =
88 request.headers["x-ename"] || request.headers["X-ENAME"];
89 90 if (!eName || typeof eName !== "string") {
91 return reply
92 .status(400)
93 .send({ error: "X-ENAME header is required" });
94 }
95 96 // Get public key from database if dbService is available
97 let publicKey: string | null = null;
98 if (dbService) {
99 try {
100 publicKey = await dbService.getPublicKey(eName);

</shell_result>


Fastify header validation case sensitivity JSON schema v5


<web_search_result>
Short answer: HTTP header names are case‑insensitive (RFC); Node lowercases header names on incoming messages; Fastify exposes those lowercased names on request.headers and therefore your JSON‑Schema (headers) should use lowercase property names. [1][2][3]

Sources

  • RFC 7230 (header field names are case‑insensitive). [3]
  • Fastify Request / Validation docs (Fastify uses request.headers and schema-based validation). [1]
  • Node.js HTTP docs (IncomingMessage/headers keys are lower-cased). [2]
    </web_search_result>

Script executed:

#!/bin/bash# View the /public-key and other endpoints mentioned in "Also applies to: 370-407"
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '350,420p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 350 if (error.code) {
351 console.error(`Token validation error code: ${error.code}`);
352 }
353 if (error.response) {
354 console.error(
355 `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
356 );
357 }
358 if (error.cause) {
359 console.error(`Token validation error cause:`, error.cause);
360 }
361 return null;
362 }
363 }
364 365 // PATCH endpoint to save public key
366 server.patch<{ Body: { publicKey: string } }>(
367 "/public-key",
368 {
369 schema: {
370 tags: ["identity"],
371 description: "Save public key for a user's eName",
372 headers: {
373 type: "object",
374 required: ["X-ENAME", "Authorization"],
375 properties: {
376 "X-ENAME": { type: "string" },
377 Authorization: { type: "string" },
378 },
379 },
380 body: {
381 type: "object",
382 required: ["publicKey"],
383 properties: {
384 publicKey: { type: "string" },
385 },
386 },
387 response: {
388 200: {
389 type: "object",
390 properties: {
391 success: { type: "boolean" },
392 message: { type: "string" },
393 },
394 },
395 400: {
396 type: "object",
397 properties: {
398 error: { type: "string" },
399 },
400 },
401 401: {
402 type: "object",
403 properties: {
404 error: { type: "string" },
405 },
406 },
407 },
408 },
409 },
410 async (
411 request: TypedRequest<{ publicKey: string }>,
412 reply: TypedReply,
413 ) => {
414 const eName =
415 request.headers["x-ename"] || request.headers["X-ENAME"];
416 417 if (!eName || typeof eName !== "string") {
418 return reply
419 .status(400)
420 .send({ error: "X-ENAME header is required" });

</shell_result>


Fix header schema casing to match Fastify's lower‑cased header keys

Fastify normalizes incoming header names to lower case, and JSON-schema validation must use lowercase property names to match. In your schemas at lines 64-66 and 374-377, you currently require mixed‑case headers:

  • /whois (line 64-66): requires "X-ENAME"
  • /public-key (line 374-377): requires "X-ENAME" and "Authorization"

Even if clients send X-ENAME or Authorization, Fastify's validator will reject the request with a 400 error because by the time validation runs, the header object only contains x-ename and authorization. The handler's fallback code checking both cases (lines 88 and 415) will never execute.

Update the schemas to use lowercase keys:

 // /whois (lines 62-68)
headers: {
type: "object",
- required: ["X-ENAME"],+ required: ["x-ename"],
properties: {
- "X-ENAME": { type: "string" },+ "x-ename": { type: "string" },
},
},
 // /public-key (lines 372-379)
headers: {
type: "object",
- required: ["X-ENAME", "Authorization"],+ required: ["x-ename", "authorization"],
properties: {
- "X-ENAME": { type: "string" },- Authorization: { type: "string" },+ "x-ename": { type: "string" },+ authorization: { type: "string" },
},
},

The handler code that reads request.headers["x-ename"] and request.headers.authorization can remain unchanged.

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

🤖 Prompt for AI Agents
in infrastructure/evault-core/src/core/http/server.ts around lines 55-84 (whois
schema) and around lines 370-380 (public-key schema), the JSON-schema header
property names use mixed-case ("X-ENAME", "Authorization") but Fastify
lowercases headers for validation; change the schema header property keys and
any entries in the required arrays to lowercase ("x-ename" and "authorization"
as applicable) so the validator matches incoming requests; leave the handler
code that reads request.headers["x-ename"] and request.headers.authorization
unchanged.

@sosweethamsosweetham mentioned this pull request Dec 3, 2025
6 tasks
@coodoscoodos closed this Dec 8, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sosweetham@coodos
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: local dev qol - #466

Closed
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol
Closed

fix: local dev qol#466
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol

Conversation

@sosweetham

@sosweethamsosweetham commented Nov 26, 2025

Copy link
Copy Markdown
Member

Description of change

adds missing script for postgres dev docker container

adds a script to get the wallet token

fixes some biome errors and runs formatter

Issue Number

n/a

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manual

Change checklist

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

Summary by CodeRabbit

  • New Features

    • Automated provisioning of multiple PostgreSQL databases.
    • Script to obtain a platform token for eid-wallet and new example env entry.
  • Bug Fixes

    • Improved Neo4j startup reliability by removing stale PID files before launch.
  • Chores

    • Broad formatting and type-safety updates, minor runtime logging added across services and UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds utility scripts (DB multi-create and eid-wallet token fetch), a Neo4j PID-cleanup wrapper in dev Docker compose, extra logging in eid-wallet onboarding, TypeScript/type-only import refinements and stricter schemas in evault-core HTTP routes, and small formatting/logging tweaks in registry services.

Changes

Cohort / File(s)Summary
DB init script
db/init-multiple-databases.sh
New Bash script that reads POSTGRES_MULTIPLE_DATABASES (comma-separated), trims entries, checks existence via psql, creates missing PostgreSQL databases, and prints status messages.
Token fetch script & env example
scripts/get-eid-wallet-token.sh, .env.example
New script posts to /platforms/certification to obtain eid-wallet token (jq or grep/sed fallback), validates output and prints instructions. .env.example appended with PUBLIC_EID_WALLET_TOKEN.
Dev Docker Compose (Neo4j cleanup)
dev-docker-compose.yaml
Neo4j service now uses an entrypoint/command wrapper that removes stale PID files from known locations (suppresses benign errors) then execs the original Neo4j startup script; healthcheck unchanged.
Client logging (eid-wallet)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Added console.log("Registry entropy:", registryEntropy) and console.log("Provision response:", provisionRes.data) for debugging; no control-flow changes.
Evault HTTP routes — types & schemas
infrastructure/evault-core/src/core/http/server.ts
Converted several imports to type-only, added/clarified request body schema for /provision, tightened type annotations on registerHttpRoutes, and reformatted route blocks; behavior preserved.
Registry formatting & logging tweaks
platforms/registry/src/index.ts, platforms/registry/src/services/HealthCheckService.ts, platforms/registry/src/services/VaultService.ts
Import reorderings, minor formatting and logging changes (including one console.log when generating entropy and one error logged as object literal); no API behavior changes.
Minor controller change
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
Reordered env var access and switched header assignment from headers["Authorization"] to headers.Authorization; no other behavior changes.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Client
participant Evault as Evault HTTP Server
participant Prov as ProvisioningService
participant DB as DbService
Client->>Evault: POST /provision {registryEntropy, namespace, verificationId, publicKey}
note right of Evault `#DDEBF7`: body validated by schema (type-only imports)
Evault->>Prov: provisionEVault(ProvisionRequest)
alt success
Prov-->>Evault: result
Evault-->>Client: 200 {result}
else failure
Prov-->>Evault: error
Evault-->>Client: 500 {error}
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • infrastructure/evault-core/src/core/http/server.ts (type-only imports, schema correctness, token validation paths)
    • db/init-multiple-databases.sh (psql invocation, quoting, heredoc behavior)
    • scripts/get-eid-wallet-token.sh (curl/jq fallback parsing and error handling)
    • dev-docker-compose.yaml (entrypoint/command wrapper permissions and exec behavior)

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • coodos
  • xPathin

Poem

🐇 I hopped through scripts and cleaned the ground,
I swept old PIDs so Neo4j's sound,
I fetched a token, parsed it with flair,
Tightened types and logs — a tidy affair,
Hooray — the rabbit left a carrot-shaped commit.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 33.33% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check❓ InconclusiveThe title 'fix: local dev qol' is vague and does not clearly convey the specific changes made in the pull request.Provide a more descriptive title that specifically mentions the key changes, such as 'fix: add postgres initialization and wallet token scripts' to better communicate the intent.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe pull request description includes all required template sections and clearly documents the changes made, testing performed, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/local-dev-qol

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c68b0 and 9f56234.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: test
🔇 Additional comments (3)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (3)

1-5: Import list reorder is fine

Reordering the PUBLIC_* imports is a no-op at runtime and keeps everything sourced from $env/static/public consistently. No issues here.


10-12: Good use of import type for UserController

Switching UserController to a type-only import aligns with TS best practices and keeps the runtime bundle leaner.


171-180: Authorization header assignment remains correct

Using headers.Authorization = \Bearer ${authToken}`on the pre-definedheaders: Record<string, string>` object is equivalent to the indexed form and keeps the conditional addition clear. No behavioural change, looks good.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

197-213: Gate new debug logs behind a dev flag to avoid leaking sensitive data

You’re logging registryEntropy and the full provision response, which is great for local debugging but exposes entropy tokens and identifiers in the browser console if this ships to production. Consider guarding these logs with a dev check:

- const registryEntropy = entropyRes.data.token;- console.log("Registry entropy:", registryEntropy);+ const registryEntropy = entropyRes.data.token;+ if (import.meta.env.DEV) {+ console.log("Registry entropy:", registryEntropy);+ }
@@
- );- console.log("Provision response:", provisionRes.data);+ );+ if (import.meta.env.DEV) {+ console.log("Provision response:", provisionRes.data);+ }
scripts/get-eid-wallet-token.sh (1)

3-45: Normalize REGISTRY_URL to avoid double slashes in request path

If PUBLIC_REGISTRY_URL is configured with a trailing / (e.g. https://registry.local/), the current concatenation will hit //platforms/certification, which some servers treat as a different path. You can harden this by stripping a trailing slash once:

-# Get the registry URL from environment or use default-REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+# Get the registry URL from environment or use default, strip trailing slash+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+REGISTRY_URL="${REGISTRY_URL%/}"

Everything else in this helper (curl error handling plus jq/grep fallback) looks good for local dev tooling. Based on learnings, this also avoids reintroducing the deprecated PUBLIC_PLATFORM_URL pattern and sticks to PUBLIC_REGISTRY_URL.

infrastructure/evault-core/src/core/http/server.ts (1)

295-363: Clarify token–eName binding in /public-key and reuse validateToken accordingly

The validateToken helper correctly verifies a Bearer JWT against the registry’s JWKS and returns its payload, but in the /public-key handler the payload is only checked for existence:

consttokenPayload=awaitvalidateToken(...);if(!tokenPayload){returnreply.status(401).send({error: "Invalid or missing authentication token"});}

There is no further check that the token is actually authorized to update the specific eName from X-ENAME (for example by matching a sub, ename, platform, or scope claim in tokenPayload).

If your security model expects tokens to be bound to a particular eName or platform, you likely want an additional check here (and a 403 if the token’s claims don’t authorize updating this eName). If, instead, any valid registry‑issued token is intentionally allowed to set any eName’s public key, the current behavior is fine but should be documented.

Also applies to: 423-464, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d94cea and e04ae8b.

⛔ Files ignored due to path filters (3)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml is excluded by !**/gen/**
📒 Files selected for processing (8)
  • db/init-multiple-databases.sh (1 hunks)
  • dev-docker-compose.yaml (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
  • infrastructure/evault-core/src/core/http/server.ts (3 hunks)
  • platforms/registry/src/index.ts (5 hunks)
  • platforms/registry/src/services/HealthCheckService.ts (4 hunks)
  • platforms/registry/src/services/VaultService.ts (1 hunks)
  • scripts/get-eid-wallet-token.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-13T10:34:52.527Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 415
File: infrastructure/eid-wallet/src/env.d.ts:8-8
Timestamp: 2025-11-13T10:34:52.527Z
Learning: In infrastructure/eid-wallet, PUBLIC_PLATFORM_URL should not be added to .env.example or configured as a static environment variable. The platform URL is extracted dynamically through URI parsing according to the protocol specification, and all fallbacks for platform URL are being removed.

Applied to files:

  • scripts/get-eid-wallet-token.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (5)
platforms/registry/src/services/HealthCheckService.ts (1)

1-87: LGTM! Formatting and code quality improvements with no behavioral changes.

The refactoring improves code consistency and readability:

  • Quote style standardization across imports and string literals
  • Multi-line formatting for complex expressions (regex, error logging) enhances readability
  • Number.parseInt on line 84 is a good practice over global parseInt

All logic remains unchanged and the improvements align with the PR's quality-of-life objective.

platforms/registry/src/services/VaultService.ts (1)

1-32: VaultService CRUD methods look correct and type usage is consistent

The switch to type-only imports and the repository-backed create/find/update/delete methods are all correct and side‑effect free. No functional or type issues spotted here.

db/init-multiple-databases.sh (1)

1-39: Multi-database init script is sensible and idempotent

The script cleanly handles an empty POSTGRES_MULTIPLE_DATABASES, trims entries, checks existence via pg_database, and only creates missing DBs. This is a solid fit for dev containers with the official Postgres entrypoint.

dev-docker-compose.yaml (1)

112-141: Neo4j PID cleanup and Postgres multi-DB wiring look correct for local dev

  • The Neo4j override (entrypoint: ["/bin/sh", "-c"] with a small shell prelude that removes stale *.pid files and then exec /startup/docker-entrypoint.sh neo4j) follows the pattern recommended in Neo4j’s own Docker docs and should resolve “stuck” dev containers due to leftover PIDs. (neo4j.com)
  • Mounting ./db/init-multiple-databases.sh into /docker-entrypoint-initdb.d together with POSTGRES_MULTIPLE_DATABASES is correct; just remember that these init scripts only run when the postgres_data volume is first created. If you later change the database list, you’ll need to recreate that volume for the script to run again.

Also applies to: 158-164

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

12-20: ---

Use Fastify's structured logger instead of console.log for production logging

The added console.log statements bypass Fastify's built-in Pino logger and produce unstructured output incompatible with log aggregation. Per Fastify best practices, replace with:

  • request.log.info("message") inside route handlers (includes automatic request context), or
  • fastify.log.info("message") for server-level events

This ensures consistent, structured logging. (Or wrap in a dev-only check if you want it only in dev environments.)

Also applies to: 41-51, 109-119

Comment on lines +55 to 84
// Whois endpoint - returns both W3ID identifier and public key
server.get(
"/whois",
{
schema: {
tags: ["identity"],
description: "Get eVault W3ID identifier and public key",
headers: {
type: "object",
required: ["X-ENAME"],
properties: {
"X-ENAME": { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
w3id: { type: "string" },
publicKey: { type: "string", nullable: true },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash# Check Fastify version and find the server filecd infrastructure/evault-core 2>/dev/null ||cd. find . -name "package.json" -type f | head -5 | xargs grep -l "fastify"2>/dev/null | head -3

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

./package.json

</shell_result>


Script executed:

#!/bin/bash# Check Fastify version
cat infrastructure/evault-core/package.json 2>/dev/null | grep -A2 -B2 "fastify"| head -20

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 },
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/formbody": "^8.0.2",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"fastify": "^4.26.2",
"graphql": "^16.10.0",
"graphql-type-json": "^0.3.2",

</shell_result>


Script executed:

#!/bin/bash# View the actual server.ts file to see the current state
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '1,100p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 1	import swagger from "@fastify/swagger";
2	import swaggerUi from "@fastify/swagger-ui";
3	import axios from "axios";
4	import fastify, { type FastifyInstance } from "fastify";
5	import * as jose from "jose";
6	import type {
7 ProvisionRequest,
8 ProvisioningService,
9	} from "../../services/ProvisioningService";
10	import type { DbService } from "../db/db.service";
11	import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
12 13	interface WatcherSignatureRequest {
14 w3id: string;
15 logEntryId: string;
16 proof: {
17 signature: string;
18 alg: string;
19 kid: string;
20 };
21	}
22 23	export async function registerHttpRoutes(
24 server: FastifyInstance,
25 evault: any, // EVault instance to access publicKey
26 provisioningService?: ProvisioningService,
27 dbService?: DbService,
28	): Promise<void> {
29 // Register Swagger
30 await server.register(swagger, {
31 swagger: {
32 info: {
33 title: "eVault Core API",
34 description: "API documentation for eVault Core HTTP endpoints",
35 version: "1.0.0",
36 },
37 tags: [
38 { name: "identity", description: "Identity related endpoints" },
39 {
40 name: "watchers",
41 description: "Watcher signature related endpoints",
42 },
43 {
44 name: "provisioning",
45 description: "eVault provisioning endpoints",
46 },
47 ],
48 },
49 });
50 51 await server.register(swaggerUi, {
52 routePrefix: "/docs",
53 });
54 55 // Whois endpoint - returns both W3ID identifier and public key
56 server.get(
57 "/whois",
58 {
59 schema: {
60 tags: ["identity"],
61 description: "Get eVault W3ID identifier and public key",
62 headers: {
63 type: "object",
64 required: ["X-ENAME"],
65 properties: {
66 "X-ENAME": { type: "string" },
67 },
68 },
69 response: {
70 200: {
71 type: "object",
72 properties: {
73 w3id: { type: "string" },
74 publicKey: { type: "string", nullable: true },
75 },
76 },
77 400: {
78 type: "object",
79 properties: {
80 error: { type: "string" },
81 },
82 },
83 },
84 },
85 },
86 async (request: TypedRequest<{}>, reply: TypedReply) => {
87 const eName =
88 request.headers["x-ename"] || request.headers["X-ENAME"];
89 90 if (!eName || typeof eName !== "string") {
91 return reply
92 .status(400)
93 .send({ error: "X-ENAME header is required" });
94 }
95 96 // Get public key from database if dbService is available
97 let publicKey: string | null = null;
98 if (dbService) {
99 try {
100 publicKey = await dbService.getPublicKey(eName);

</shell_result>


Fastify header validation case sensitivity JSON schema v5


<web_search_result>
Short answer: HTTP header names are case‑insensitive (RFC); Node lowercases header names on incoming messages; Fastify exposes those lowercased names on request.headers and therefore your JSON‑Schema (headers) should use lowercase property names. [1][2][3]

Sources

  • RFC 7230 (header field names are case‑insensitive). [3]
  • Fastify Request / Validation docs (Fastify uses request.headers and schema-based validation). [1]
  • Node.js HTTP docs (IncomingMessage/headers keys are lower-cased). [2]
    </web_search_result>

Script executed:

#!/bin/bash# View the /public-key and other endpoints mentioned in "Also applies to: 370-407"
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '350,420p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 350 if (error.code) {
351 console.error(`Token validation error code: ${error.code}`);
352 }
353 if (error.response) {
354 console.error(
355 `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
356 );
357 }
358 if (error.cause) {
359 console.error(`Token validation error cause:`, error.cause);
360 }
361 return null;
362 }
363 }
364 365 // PATCH endpoint to save public key
366 server.patch<{ Body: { publicKey: string } }>(
367 "/public-key",
368 {
369 schema: {
370 tags: ["identity"],
371 description: "Save public key for a user's eName",
372 headers: {
373 type: "object",
374 required: ["X-ENAME", "Authorization"],
375 properties: {
376 "X-ENAME": { type: "string" },
377 Authorization: { type: "string" },
378 },
379 },
380 body: {
381 type: "object",
382 required: ["publicKey"],
383 properties: {
384 publicKey: { type: "string" },
385 },
386 },
387 response: {
388 200: {
389 type: "object",
390 properties: {
391 success: { type: "boolean" },
392 message: { type: "string" },
393 },
394 },
395 400: {
396 type: "object",
397 properties: {
398 error: { type: "string" },
399 },
400 },
401 401: {
402 type: "object",
403 properties: {
404 error: { type: "string" },
405 },
406 },
407 },
408 },
409 },
410 async (
411 request: TypedRequest<{ publicKey: string }>,
412 reply: TypedReply,
413 ) => {
414 const eName =
415 request.headers["x-ename"] || request.headers["X-ENAME"];
416 417 if (!eName || typeof eName !== "string") {
418 return reply
419 .status(400)
420 .send({ error: "X-ENAME header is required" });

</shell_result>


Fix header schema casing to match Fastify's lower‑cased header keys

Fastify normalizes incoming header names to lower case, and JSON-schema validation must use lowercase property names to match. In your schemas at lines 64-66 and 374-377, you currently require mixed‑case headers:

  • /whois (line 64-66): requires "X-ENAME"
  • /public-key (line 374-377): requires "X-ENAME" and "Authorization"

Even if clients send X-ENAME or Authorization, Fastify's validator will reject the request with a 400 error because by the time validation runs, the header object only contains x-ename and authorization. The handler's fallback code checking both cases (lines 88 and 415) will never execute.

Update the schemas to use lowercase keys:

 // /whois (lines 62-68)
headers: {
type: "object",
- required: ["X-ENAME"],+ required: ["x-ename"],
properties: {
- "X-ENAME": { type: "string" },+ "x-ename": { type: "string" },
},
},
 // /public-key (lines 372-379)
headers: {
type: "object",
- required: ["X-ENAME", "Authorization"],+ required: ["x-ename", "authorization"],
properties: {
- "X-ENAME": { type: "string" },- Authorization: { type: "string" },+ "x-ename": { type: "string" },+ authorization: { type: "string" },
},
},

The handler code that reads request.headers["x-ename"] and request.headers.authorization can remain unchanged.

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

🤖 Prompt for AI Agents
in infrastructure/evault-core/src/core/http/server.ts around lines 55-84 (whois
schema) and around lines 370-380 (public-key schema), the JSON-schema header
property names use mixed-case ("X-ENAME", "Authorization") but Fastify
lowercases headers for validation; change the schema header property keys and
any entries in the required arrays to lowercase ("x-ename" and "authorization"
as applicable) so the validator matches incoming requests; leave the handler
code that reads request.headers["x-ename"] and request.headers.authorization
unchanged.

@sosweethamsosweetham mentioned this pull request Dec 3, 2025
6 tasks
@coodoscoodos closed this Dec 8, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sosweetham@coodos
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: local dev qol - #466

Closed
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol
Closed

fix: local dev qol#466
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol

Conversation

@sosweetham

@sosweethamsosweetham commented Nov 26, 2025

Copy link
Copy Markdown
Member

Description of change

adds missing script for postgres dev docker container

adds a script to get the wallet token

fixes some biome errors and runs formatter

Issue Number

n/a

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manual

Change checklist

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

Summary by CodeRabbit

  • New Features

    • Automated provisioning of multiple PostgreSQL databases.
    • Script to obtain a platform token for eid-wallet and new example env entry.
  • Bug Fixes

    • Improved Neo4j startup reliability by removing stale PID files before launch.
  • Chores

    • Broad formatting and type-safety updates, minor runtime logging added across services and UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds utility scripts (DB multi-create and eid-wallet token fetch), a Neo4j PID-cleanup wrapper in dev Docker compose, extra logging in eid-wallet onboarding, TypeScript/type-only import refinements and stricter schemas in evault-core HTTP routes, and small formatting/logging tweaks in registry services.

Changes

Cohort / File(s)Summary
DB init script
db/init-multiple-databases.sh
New Bash script that reads POSTGRES_MULTIPLE_DATABASES (comma-separated), trims entries, checks existence via psql, creates missing PostgreSQL databases, and prints status messages.
Token fetch script & env example
scripts/get-eid-wallet-token.sh, .env.example
New script posts to /platforms/certification to obtain eid-wallet token (jq or grep/sed fallback), validates output and prints instructions. .env.example appended with PUBLIC_EID_WALLET_TOKEN.
Dev Docker Compose (Neo4j cleanup)
dev-docker-compose.yaml
Neo4j service now uses an entrypoint/command wrapper that removes stale PID files from known locations (suppresses benign errors) then execs the original Neo4j startup script; healthcheck unchanged.
Client logging (eid-wallet)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Added console.log("Registry entropy:", registryEntropy) and console.log("Provision response:", provisionRes.data) for debugging; no control-flow changes.
Evault HTTP routes — types & schemas
infrastructure/evault-core/src/core/http/server.ts
Converted several imports to type-only, added/clarified request body schema for /provision, tightened type annotations on registerHttpRoutes, and reformatted route blocks; behavior preserved.
Registry formatting & logging tweaks
platforms/registry/src/index.ts, platforms/registry/src/services/HealthCheckService.ts, platforms/registry/src/services/VaultService.ts
Import reorderings, minor formatting and logging changes (including one console.log when generating entropy and one error logged as object literal); no API behavior changes.
Minor controller change
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
Reordered env var access and switched header assignment from headers["Authorization"] to headers.Authorization; no other behavior changes.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Client
participant Evault as Evault HTTP Server
participant Prov as ProvisioningService
participant DB as DbService
Client->>Evault: POST /provision {registryEntropy, namespace, verificationId, publicKey}
note right of Evault `#DDEBF7`: body validated by schema (type-only imports)
Evault->>Prov: provisionEVault(ProvisionRequest)
alt success
Prov-->>Evault: result
Evault-->>Client: 200 {result}
else failure
Prov-->>Evault: error
Evault-->>Client: 500 {error}
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • infrastructure/evault-core/src/core/http/server.ts (type-only imports, schema correctness, token validation paths)
    • db/init-multiple-databases.sh (psql invocation, quoting, heredoc behavior)
    • scripts/get-eid-wallet-token.sh (curl/jq fallback parsing and error handling)
    • dev-docker-compose.yaml (entrypoint/command wrapper permissions and exec behavior)

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • coodos
  • xPathin

Poem

🐇 I hopped through scripts and cleaned the ground,
I swept old PIDs so Neo4j's sound,
I fetched a token, parsed it with flair,
Tightened types and logs — a tidy affair,
Hooray — the rabbit left a carrot-shaped commit.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 33.33% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check❓ InconclusiveThe title 'fix: local dev qol' is vague and does not clearly convey the specific changes made in the pull request.Provide a more descriptive title that specifically mentions the key changes, such as 'fix: add postgres initialization and wallet token scripts' to better communicate the intent.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe pull request description includes all required template sections and clearly documents the changes made, testing performed, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/local-dev-qol

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c68b0 and 9f56234.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: test
🔇 Additional comments (3)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (3)

1-5: Import list reorder is fine

Reordering the PUBLIC_* imports is a no-op at runtime and keeps everything sourced from $env/static/public consistently. No issues here.


10-12: Good use of import type for UserController

Switching UserController to a type-only import aligns with TS best practices and keeps the runtime bundle leaner.


171-180: Authorization header assignment remains correct

Using headers.Authorization = \Bearer ${authToken}`on the pre-definedheaders: Record<string, string>` object is equivalent to the indexed form and keeps the conditional addition clear. No behavioural change, looks good.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

197-213: Gate new debug logs behind a dev flag to avoid leaking sensitive data

You’re logging registryEntropy and the full provision response, which is great for local debugging but exposes entropy tokens and identifiers in the browser console if this ships to production. Consider guarding these logs with a dev check:

- const registryEntropy = entropyRes.data.token;- console.log("Registry entropy:", registryEntropy);+ const registryEntropy = entropyRes.data.token;+ if (import.meta.env.DEV) {+ console.log("Registry entropy:", registryEntropy);+ }
@@
- );- console.log("Provision response:", provisionRes.data);+ );+ if (import.meta.env.DEV) {+ console.log("Provision response:", provisionRes.data);+ }
scripts/get-eid-wallet-token.sh (1)

3-45: Normalize REGISTRY_URL to avoid double slashes in request path

If PUBLIC_REGISTRY_URL is configured with a trailing / (e.g. https://registry.local/), the current concatenation will hit //platforms/certification, which some servers treat as a different path. You can harden this by stripping a trailing slash once:

-# Get the registry URL from environment or use default-REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+# Get the registry URL from environment or use default, strip trailing slash+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+REGISTRY_URL="${REGISTRY_URL%/}"

Everything else in this helper (curl error handling plus jq/grep fallback) looks good for local dev tooling. Based on learnings, this also avoids reintroducing the deprecated PUBLIC_PLATFORM_URL pattern and sticks to PUBLIC_REGISTRY_URL.

infrastructure/evault-core/src/core/http/server.ts (1)

295-363: Clarify token–eName binding in /public-key and reuse validateToken accordingly

The validateToken helper correctly verifies a Bearer JWT against the registry’s JWKS and returns its payload, but in the /public-key handler the payload is only checked for existence:

consttokenPayload=awaitvalidateToken(...);if(!tokenPayload){returnreply.status(401).send({error: "Invalid or missing authentication token"});}

There is no further check that the token is actually authorized to update the specific eName from X-ENAME (for example by matching a sub, ename, platform, or scope claim in tokenPayload).

If your security model expects tokens to be bound to a particular eName or platform, you likely want an additional check here (and a 403 if the token’s claims don’t authorize updating this eName). If, instead, any valid registry‑issued token is intentionally allowed to set any eName’s public key, the current behavior is fine but should be documented.

Also applies to: 423-464, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d94cea and e04ae8b.

⛔ Files ignored due to path filters (3)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml is excluded by !**/gen/**
📒 Files selected for processing (8)
  • db/init-multiple-databases.sh (1 hunks)
  • dev-docker-compose.yaml (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
  • infrastructure/evault-core/src/core/http/server.ts (3 hunks)
  • platforms/registry/src/index.ts (5 hunks)
  • platforms/registry/src/services/HealthCheckService.ts (4 hunks)
  • platforms/registry/src/services/VaultService.ts (1 hunks)
  • scripts/get-eid-wallet-token.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-13T10:34:52.527Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 415
File: infrastructure/eid-wallet/src/env.d.ts:8-8
Timestamp: 2025-11-13T10:34:52.527Z
Learning: In infrastructure/eid-wallet, PUBLIC_PLATFORM_URL should not be added to .env.example or configured as a static environment variable. The platform URL is extracted dynamically through URI parsing according to the protocol specification, and all fallbacks for platform URL are being removed.

Applied to files:

  • scripts/get-eid-wallet-token.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (5)
platforms/registry/src/services/HealthCheckService.ts (1)

1-87: LGTM! Formatting and code quality improvements with no behavioral changes.

The refactoring improves code consistency and readability:

  • Quote style standardization across imports and string literals
  • Multi-line formatting for complex expressions (regex, error logging) enhances readability
  • Number.parseInt on line 84 is a good practice over global parseInt

All logic remains unchanged and the improvements align with the PR's quality-of-life objective.

platforms/registry/src/services/VaultService.ts (1)

1-32: VaultService CRUD methods look correct and type usage is consistent

The switch to type-only imports and the repository-backed create/find/update/delete methods are all correct and side‑effect free. No functional or type issues spotted here.

db/init-multiple-databases.sh (1)

1-39: Multi-database init script is sensible and idempotent

The script cleanly handles an empty POSTGRES_MULTIPLE_DATABASES, trims entries, checks existence via pg_database, and only creates missing DBs. This is a solid fit for dev containers with the official Postgres entrypoint.

dev-docker-compose.yaml (1)

112-141: Neo4j PID cleanup and Postgres multi-DB wiring look correct for local dev

  • The Neo4j override (entrypoint: ["/bin/sh", "-c"] with a small shell prelude that removes stale *.pid files and then exec /startup/docker-entrypoint.sh neo4j) follows the pattern recommended in Neo4j’s own Docker docs and should resolve “stuck” dev containers due to leftover PIDs. (neo4j.com)
  • Mounting ./db/init-multiple-databases.sh into /docker-entrypoint-initdb.d together with POSTGRES_MULTIPLE_DATABASES is correct; just remember that these init scripts only run when the postgres_data volume is first created. If you later change the database list, you’ll need to recreate that volume for the script to run again.

Also applies to: 158-164

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

12-20: ---

Use Fastify's structured logger instead of console.log for production logging

The added console.log statements bypass Fastify's built-in Pino logger and produce unstructured output incompatible with log aggregation. Per Fastify best practices, replace with:

  • request.log.info("message") inside route handlers (includes automatic request context), or
  • fastify.log.info("message") for server-level events

This ensures consistent, structured logging. (Or wrap in a dev-only check if you want it only in dev environments.)

Also applies to: 41-51, 109-119

Comment on lines +55 to 84
// Whois endpoint - returns both W3ID identifier and public key
server.get(
"/whois",
{
schema: {
tags: ["identity"],
description: "Get eVault W3ID identifier and public key",
headers: {
type: "object",
required: ["X-ENAME"],
properties: {
"X-ENAME": { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
w3id: { type: "string" },
publicKey: { type: "string", nullable: true },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash# Check Fastify version and find the server filecd infrastructure/evault-core 2>/dev/null ||cd. find . -name "package.json" -type f | head -5 | xargs grep -l "fastify"2>/dev/null | head -3

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

./package.json

</shell_result>


Script executed:

#!/bin/bash# Check Fastify version
cat infrastructure/evault-core/package.json 2>/dev/null | grep -A2 -B2 "fastify"| head -20

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 },
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/formbody": "^8.0.2",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"fastify": "^4.26.2",
"graphql": "^16.10.0",
"graphql-type-json": "^0.3.2",

</shell_result>


Script executed:

#!/bin/bash# View the actual server.ts file to see the current state
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '1,100p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 1	import swagger from "@fastify/swagger";
2	import swaggerUi from "@fastify/swagger-ui";
3	import axios from "axios";
4	import fastify, { type FastifyInstance } from "fastify";
5	import * as jose from "jose";
6	import type {
7 ProvisionRequest,
8 ProvisioningService,
9	} from "../../services/ProvisioningService";
10	import type { DbService } from "../db/db.service";
11	import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
12 13	interface WatcherSignatureRequest {
14 w3id: string;
15 logEntryId: string;
16 proof: {
17 signature: string;
18 alg: string;
19 kid: string;
20 };
21	}
22 23	export async function registerHttpRoutes(
24 server: FastifyInstance,
25 evault: any, // EVault instance to access publicKey
26 provisioningService?: ProvisioningService,
27 dbService?: DbService,
28	): Promise<void> {
29 // Register Swagger
30 await server.register(swagger, {
31 swagger: {
32 info: {
33 title: "eVault Core API",
34 description: "API documentation for eVault Core HTTP endpoints",
35 version: "1.0.0",
36 },
37 tags: [
38 { name: "identity", description: "Identity related endpoints" },
39 {
40 name: "watchers",
41 description: "Watcher signature related endpoints",
42 },
43 {
44 name: "provisioning",
45 description: "eVault provisioning endpoints",
46 },
47 ],
48 },
49 });
50 51 await server.register(swaggerUi, {
52 routePrefix: "/docs",
53 });
54 55 // Whois endpoint - returns both W3ID identifier and public key
56 server.get(
57 "/whois",
58 {
59 schema: {
60 tags: ["identity"],
61 description: "Get eVault W3ID identifier and public key",
62 headers: {
63 type: "object",
64 required: ["X-ENAME"],
65 properties: {
66 "X-ENAME": { type: "string" },
67 },
68 },
69 response: {
70 200: {
71 type: "object",
72 properties: {
73 w3id: { type: "string" },
74 publicKey: { type: "string", nullable: true },
75 },
76 },
77 400: {
78 type: "object",
79 properties: {
80 error: { type: "string" },
81 },
82 },
83 },
84 },
85 },
86 async (request: TypedRequest<{}>, reply: TypedReply) => {
87 const eName =
88 request.headers["x-ename"] || request.headers["X-ENAME"];
89 90 if (!eName || typeof eName !== "string") {
91 return reply
92 .status(400)
93 .send({ error: "X-ENAME header is required" });
94 }
95 96 // Get public key from database if dbService is available
97 let publicKey: string | null = null;
98 if (dbService) {
99 try {
100 publicKey = await dbService.getPublicKey(eName);

</shell_result>


Fastify header validation case sensitivity JSON schema v5


<web_search_result>
Short answer: HTTP header names are case‑insensitive (RFC); Node lowercases header names on incoming messages; Fastify exposes those lowercased names on request.headers and therefore your JSON‑Schema (headers) should use lowercase property names. [1][2][3]

Sources

  • RFC 7230 (header field names are case‑insensitive). [3]
  • Fastify Request / Validation docs (Fastify uses request.headers and schema-based validation). [1]
  • Node.js HTTP docs (IncomingMessage/headers keys are lower-cased). [2]
    </web_search_result>

Script executed:

#!/bin/bash# View the /public-key and other endpoints mentioned in "Also applies to: 370-407"
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '350,420p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 350 if (error.code) {
351 console.error(`Token validation error code: ${error.code}`);
352 }
353 if (error.response) {
354 console.error(
355 `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
356 );
357 }
358 if (error.cause) {
359 console.error(`Token validation error cause:`, error.cause);
360 }
361 return null;
362 }
363 }
364 365 // PATCH endpoint to save public key
366 server.patch<{ Body: { publicKey: string } }>(
367 "/public-key",
368 {
369 schema: {
370 tags: ["identity"],
371 description: "Save public key for a user's eName",
372 headers: {
373 type: "object",
374 required: ["X-ENAME", "Authorization"],
375 properties: {
376 "X-ENAME": { type: "string" },
377 Authorization: { type: "string" },
378 },
379 },
380 body: {
381 type: "object",
382 required: ["publicKey"],
383 properties: {
384 publicKey: { type: "string" },
385 },
386 },
387 response: {
388 200: {
389 type: "object",
390 properties: {
391 success: { type: "boolean" },
392 message: { type: "string" },
393 },
394 },
395 400: {
396 type: "object",
397 properties: {
398 error: { type: "string" },
399 },
400 },
401 401: {
402 type: "object",
403 properties: {
404 error: { type: "string" },
405 },
406 },
407 },
408 },
409 },
410 async (
411 request: TypedRequest<{ publicKey: string }>,
412 reply: TypedReply,
413 ) => {
414 const eName =
415 request.headers["x-ename"] || request.headers["X-ENAME"];
416 417 if (!eName || typeof eName !== "string") {
418 return reply
419 .status(400)
420 .send({ error: "X-ENAME header is required" });

</shell_result>


Fix header schema casing to match Fastify's lower‑cased header keys

Fastify normalizes incoming header names to lower case, and JSON-schema validation must use lowercase property names to match. In your schemas at lines 64-66 and 374-377, you currently require mixed‑case headers:

  • /whois (line 64-66): requires "X-ENAME"
  • /public-key (line 374-377): requires "X-ENAME" and "Authorization"

Even if clients send X-ENAME or Authorization, Fastify's validator will reject the request with a 400 error because by the time validation runs, the header object only contains x-ename and authorization. The handler's fallback code checking both cases (lines 88 and 415) will never execute.

Update the schemas to use lowercase keys:

 // /whois (lines 62-68)
headers: {
type: "object",
- required: ["X-ENAME"],+ required: ["x-ename"],
properties: {
- "X-ENAME": { type: "string" },+ "x-ename": { type: "string" },
},
},
 // /public-key (lines 372-379)
headers: {
type: "object",
- required: ["X-ENAME", "Authorization"],+ required: ["x-ename", "authorization"],
properties: {
- "X-ENAME": { type: "string" },- Authorization: { type: "string" },+ "x-ename": { type: "string" },+ authorization: { type: "string" },
},
},

The handler code that reads request.headers["x-ename"] and request.headers.authorization can remain unchanged.

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

🤖 Prompt for AI Agents
in infrastructure/evault-core/src/core/http/server.ts around lines 55-84 (whois
schema) and around lines 370-380 (public-key schema), the JSON-schema header
property names use mixed-case ("X-ENAME", "Authorization") but Fastify
lowercases headers for validation; change the schema header property keys and
any entries in the required arrays to lowercase ("x-ename" and "authorization"
as applicable) so the validator matches incoming requests; leave the handler
code that reads request.headers["x-ename"] and request.headers.authorization
unchanged.

@sosweethamsosweetham mentioned this pull request Dec 3, 2025
6 tasks
@coodoscoodos closed this Dec 8, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sosweetham@coodos
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix: local dev qol - #466

Closed
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol
Closed

fix: local dev qol#466
sosweetham wants to merge 3 commits into
mainfrom
fix/local-dev-qol

Conversation

@sosweetham

@sosweethamsosweetham commented Nov 26, 2025

Copy link
Copy Markdown
Member

Description of change

adds missing script for postgres dev docker container

adds a script to get the wallet token

fixes some biome errors and runs formatter

Issue Number

n/a

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manual

Change checklist

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

Summary by CodeRabbit

  • New Features

    • Automated provisioning of multiple PostgreSQL databases.
    • Script to obtain a platform token for eid-wallet and new example env entry.
  • Bug Fixes

    • Improved Neo4j startup reliability by removing stale PID files before launch.
  • Chores

    • Broad formatting and type-safety updates, minor runtime logging added across services and UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds utility scripts (DB multi-create and eid-wallet token fetch), a Neo4j PID-cleanup wrapper in dev Docker compose, extra logging in eid-wallet onboarding, TypeScript/type-only import refinements and stricter schemas in evault-core HTTP routes, and small formatting/logging tweaks in registry services.

Changes

Cohort / File(s)Summary
DB init script
db/init-multiple-databases.sh
New Bash script that reads POSTGRES_MULTIPLE_DATABASES (comma-separated), trims entries, checks existence via psql, creates missing PostgreSQL databases, and prints status messages.
Token fetch script & env example
scripts/get-eid-wallet-token.sh, .env.example
New script posts to /platforms/certification to obtain eid-wallet token (jq or grep/sed fallback), validates output and prints instructions. .env.example appended with PUBLIC_EID_WALLET_TOKEN.
Dev Docker Compose (Neo4j cleanup)
dev-docker-compose.yaml
Neo4j service now uses an entrypoint/command wrapper that removes stale PID files from known locations (suppresses benign errors) then execs the original Neo4j startup script; healthcheck unchanged.
Client logging (eid-wallet)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Added console.log("Registry entropy:", registryEntropy) and console.log("Provision response:", provisionRes.data) for debugging; no control-flow changes.
Evault HTTP routes — types & schemas
infrastructure/evault-core/src/core/http/server.ts
Converted several imports to type-only, added/clarified request body schema for /provision, tightened type annotations on registerHttpRoutes, and reformatted route blocks; behavior preserved.
Registry formatting & logging tweaks
platforms/registry/src/index.ts, platforms/registry/src/services/HealthCheckService.ts, platforms/registry/src/services/VaultService.ts
Import reorderings, minor formatting and logging changes (including one console.log when generating entropy and one error logged as object literal); no API behavior changes.
Minor controller change
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
Reordered env var access and switched header assignment from headers["Authorization"] to headers.Authorization; no other behavior changes.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Client
participant Evault as Evault HTTP Server
participant Prov as ProvisioningService
participant DB as DbService
Client->>Evault: POST /provision {registryEntropy, namespace, verificationId, publicKey}
note right of Evault `#DDEBF7`: body validated by schema (type-only imports)
Evault->>Prov: provisionEVault(ProvisionRequest)
alt success
Prov-->>Evault: result
Evault-->>Client: 200 {result}
else failure
Prov-->>Evault: error
Evault-->>Client: 500 {error}
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • infrastructure/evault-core/src/core/http/server.ts (type-only imports, schema correctness, token validation paths)
    • db/init-multiple-databases.sh (psql invocation, quoting, heredoc behavior)
    • scripts/get-eid-wallet-token.sh (curl/jq fallback parsing and error handling)
    • dev-docker-compose.yaml (entrypoint/command wrapper permissions and exec behavior)

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • coodos
  • xPathin

Poem

🐇 I hopped through scripts and cleaned the ground,
I swept old PIDs so Neo4j's sound,
I fetched a token, parsed it with flair,
Tightened types and logs — a tidy affair,
Hooray — the rabbit left a carrot-shaped commit.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 33.33% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check❓ InconclusiveThe title 'fix: local dev qol' is vague and does not clearly convey the specific changes made in the pull request.Provide a more descriptive title that specifically mentions the key changes, such as 'fix: add postgres initialization and wallet token scripts' to better communicate the intent.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe pull request description includes all required template sections and clearly documents the changes made, testing performed, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/local-dev-qol

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c68b0 and 9f56234.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: test
🔇 Additional comments (3)
infrastructure/eid-wallet/src/lib/global/controllers/evault.ts (3)

1-5: Import list reorder is fine

Reordering the PUBLIC_* imports is a no-op at runtime and keeps everything sourced from $env/static/public consistently. No issues here.


10-12: Good use of import type for UserController

Switching UserController to a type-only import aligns with TS best practices and keeps the runtime bundle leaner.


171-180: Authorization header assignment remains correct

Using headers.Authorization = \Bearer ${authToken}`on the pre-definedheaders: Record<string, string>` object is equivalent to the indexed form and keeps the conditional addition clear. No behavioural change, looks good.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (1)

197-213: Gate new debug logs behind a dev flag to avoid leaking sensitive data

You’re logging registryEntropy and the full provision response, which is great for local debugging but exposes entropy tokens and identifiers in the browser console if this ships to production. Consider guarding these logs with a dev check:

- const registryEntropy = entropyRes.data.token;- console.log("Registry entropy:", registryEntropy);+ const registryEntropy = entropyRes.data.token;+ if (import.meta.env.DEV) {+ console.log("Registry entropy:", registryEntropy);+ }
@@
- );- console.log("Provision response:", provisionRes.data);+ );+ if (import.meta.env.DEV) {+ console.log("Provision response:", provisionRes.data);+ }
scripts/get-eid-wallet-token.sh (1)

3-45: Normalize REGISTRY_URL to avoid double slashes in request path

If PUBLIC_REGISTRY_URL is configured with a trailing / (e.g. https://registry.local/), the current concatenation will hit //platforms/certification, which some servers treat as a different path. You can harden this by stripping a trailing slash once:

-# Get the registry URL from environment or use default-REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+# Get the registry URL from environment or use default, strip trailing slash+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"+REGISTRY_URL="${REGISTRY_URL%/}"

Everything else in this helper (curl error handling plus jq/grep fallback) looks good for local dev tooling. Based on learnings, this also avoids reintroducing the deprecated PUBLIC_PLATFORM_URL pattern and sticks to PUBLIC_REGISTRY_URL.

infrastructure/evault-core/src/core/http/server.ts (1)

295-363: Clarify token–eName binding in /public-key and reuse validateToken accordingly

The validateToken helper correctly verifies a Bearer JWT against the registry’s JWKS and returns its payload, but in the /public-key handler the payload is only checked for existence:

consttokenPayload=awaitvalidateToken(...);if(!tokenPayload){returnreply.status(401).send({error: "Invalid or missing authentication token"});}

There is no further check that the token is actually authorized to update the specific eName from X-ENAME (for example by matching a sub, ename, platform, or scope claim in tokenPayload).

If your security model expects tokens to be bound to a particular eName or platform, you likely want an additional check here (and a 403 if the token’s claims don’t authorize updating this eName). If, instead, any valid registry‑issued token is intentionally allowed to set any eName’s public key, the current behavior is fine but should be documented.

Also applies to: 423-464, 509-516

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d94cea and e04ae8b.

⛔ Files ignored due to path filters (3)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml is excluded by !**/gen/**
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml is excluded by !**/gen/**
📒 Files selected for processing (8)
  • db/init-multiple-databases.sh (1 hunks)
  • dev-docker-compose.yaml (1 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (2 hunks)
  • infrastructure/evault-core/src/core/http/server.ts (3 hunks)
  • platforms/registry/src/index.ts (5 hunks)
  • platforms/registry/src/services/HealthCheckService.ts (4 hunks)
  • platforms/registry/src/services/VaultService.ts (1 hunks)
  • scripts/get-eid-wallet-token.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-13T10:34:52.527Z
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 415
File: infrastructure/eid-wallet/src/env.d.ts:8-8
Timestamp: 2025-11-13T10:34:52.527Z
Learning: In infrastructure/eid-wallet, PUBLIC_PLATFORM_URL should not be added to .env.example or configured as a static environment variable. The platform URL is extracted dynamically through URI parsing according to the protocol specification, and all fallbacks for platform URL are being removed.

Applied to files:

  • scripts/get-eid-wallet-token.sh
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test-web3-adapter-integration
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (5)
platforms/registry/src/services/HealthCheckService.ts (1)

1-87: LGTM! Formatting and code quality improvements with no behavioral changes.

The refactoring improves code consistency and readability:

  • Quote style standardization across imports and string literals
  • Multi-line formatting for complex expressions (regex, error logging) enhances readability
  • Number.parseInt on line 84 is a good practice over global parseInt

All logic remains unchanged and the improvements align with the PR's quality-of-life objective.

platforms/registry/src/services/VaultService.ts (1)

1-32: VaultService CRUD methods look correct and type usage is consistent

The switch to type-only imports and the repository-backed create/find/update/delete methods are all correct and side‑effect free. No functional or type issues spotted here.

db/init-multiple-databases.sh (1)

1-39: Multi-database init script is sensible and idempotent

The script cleanly handles an empty POSTGRES_MULTIPLE_DATABASES, trims entries, checks existence via pg_database, and only creates missing DBs. This is a solid fit for dev containers with the official Postgres entrypoint.

dev-docker-compose.yaml (1)

112-141: Neo4j PID cleanup and Postgres multi-DB wiring look correct for local dev

  • The Neo4j override (entrypoint: ["/bin/sh", "-c"] with a small shell prelude that removes stale *.pid files and then exec /startup/docker-entrypoint.sh neo4j) follows the pattern recommended in Neo4j’s own Docker docs and should resolve “stuck” dev containers due to leftover PIDs. (neo4j.com)
  • Mounting ./db/init-multiple-databases.sh into /docker-entrypoint-initdb.d together with POSTGRES_MULTIPLE_DATABASES is correct; just remember that these init scripts only run when the postgres_data volume is first created. If you later change the database list, you’ll need to recreate that volume for the script to run again.

Also applies to: 158-164

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

12-20: ---

Use Fastify's structured logger instead of console.log for production logging

The added console.log statements bypass Fastify's built-in Pino logger and produce unstructured output incompatible with log aggregation. Per Fastify best practices, replace with:

  • request.log.info("message") inside route handlers (includes automatic request context), or
  • fastify.log.info("message") for server-level events

This ensures consistent, structured logging. (Or wrap in a dev-only check if you want it only in dev environments.)

Also applies to: 41-51, 109-119

Comment on lines +55 to 84
// Whois endpoint - returns both W3ID identifier and public key
server.get(
"/whois",
{
schema: {
tags: ["identity"],
description: "Get eVault W3ID identifier and public key",
headers: {
type: "object",
required: ["X-ENAME"],
properties: {
"X-ENAME": { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
w3id: { type: "string" },
publicKey: { type: "string", nullable: true },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash# Check Fastify version and find the server filecd infrastructure/evault-core 2>/dev/null ||cd. find . -name "package.json" -type f | head -5 | xargs grep -l "fastify"2>/dev/null | head -3

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

./package.json

</shell_result>


Script executed:

#!/bin/bash# Check Fastify version
cat infrastructure/evault-core/package.json 2>/dev/null | grep -A2 -B2 "fastify"| head -20

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 },
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/formbody": "^8.0.2",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"fastify": "^4.26.2",
"graphql": "^16.10.0",
"graphql-type-json": "^0.3.2",

</shell_result>


Script executed:

#!/bin/bash# View the actual server.ts file to see the current state
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '1,100p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 1	import swagger from "@fastify/swagger";
2	import swaggerUi from "@fastify/swagger-ui";
3	import axios from "axios";
4	import fastify, { type FastifyInstance } from "fastify";
5	import * as jose from "jose";
6	import type {
7 ProvisionRequest,
8 ProvisioningService,
9	} from "../../services/ProvisioningService";
10	import type { DbService } from "../db/db.service";
11	import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
12 13	interface WatcherSignatureRequest {
14 w3id: string;
15 logEntryId: string;
16 proof: {
17 signature: string;
18 alg: string;
19 kid: string;
20 };
21	}
22 23	export async function registerHttpRoutes(
24 server: FastifyInstance,
25 evault: any, // EVault instance to access publicKey
26 provisioningService?: ProvisioningService,
27 dbService?: DbService,
28	): Promise<void> {
29 // Register Swagger
30 await server.register(swagger, {
31 swagger: {
32 info: {
33 title: "eVault Core API",
34 description: "API documentation for eVault Core HTTP endpoints",
35 version: "1.0.0",
36 },
37 tags: [
38 { name: "identity", description: "Identity related endpoints" },
39 {
40 name: "watchers",
41 description: "Watcher signature related endpoints",
42 },
43 {
44 name: "provisioning",
45 description: "eVault provisioning endpoints",
46 },
47 ],
48 },
49 });
50 51 await server.register(swaggerUi, {
52 routePrefix: "/docs",
53 });
54 55 // Whois endpoint - returns both W3ID identifier and public key
56 server.get(
57 "/whois",
58 {
59 schema: {
60 tags: ["identity"],
61 description: "Get eVault W3ID identifier and public key",
62 headers: {
63 type: "object",
64 required: ["X-ENAME"],
65 properties: {
66 "X-ENAME": { type: "string" },
67 },
68 },
69 response: {
70 200: {
71 type: "object",
72 properties: {
73 w3id: { type: "string" },
74 publicKey: { type: "string", nullable: true },
75 },
76 },
77 400: {
78 type: "object",
79 properties: {
80 error: { type: "string" },
81 },
82 },
83 },
84 },
85 },
86 async (request: TypedRequest<{}>, reply: TypedReply) => {
87 const eName =
88 request.headers["x-ename"] || request.headers["X-ENAME"];
89 90 if (!eName || typeof eName !== "string") {
91 return reply
92 .status(400)
93 .send({ error: "X-ENAME header is required" });
94 }
95 96 // Get public key from database if dbService is available
97 let publicKey: string | null = null;
98 if (dbService) {
99 try {
100 publicKey = await dbService.getPublicKey(eName);

</shell_result>


Fastify header validation case sensitivity JSON schema v5


<web_search_result>
Short answer: HTTP header names are case‑insensitive (RFC); Node lowercases header names on incoming messages; Fastify exposes those lowercased names on request.headers and therefore your JSON‑Schema (headers) should use lowercase property names. [1][2][3]

Sources

  • RFC 7230 (header field names are case‑insensitive). [3]
  • Fastify Request / Validation docs (Fastify uses request.headers and schema-based validation). [1]
  • Node.js HTTP docs (IncomingMessage/headers keys are lower-cased). [2]
    </web_search_result>

Script executed:

#!/bin/bash# View the /public-key and other endpoints mentioned in "Also applies to: 370-407"
cat -n infrastructure/evault-core/src/core/http/server.ts | sed -n '350,420p'

Repository: MetaState-Prototype-Project/prototype


<shell_result>
Repository: MetaState-Prototype-Project/prototype
Exit code: 0

stdout:

 350 if (error.code) {
351 console.error(`Token validation error code: ${error.code}`);
352 }
353 if (error.response) {
354 console.error(
355 `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
356 );
357 }
358 if (error.cause) {
359 console.error(`Token validation error cause:`, error.cause);
360 }
361 return null;
362 }
363 }
364 365 // PATCH endpoint to save public key
366 server.patch<{ Body: { publicKey: string } }>(
367 "/public-key",
368 {
369 schema: {
370 tags: ["identity"],
371 description: "Save public key for a user's eName",
372 headers: {
373 type: "object",
374 required: ["X-ENAME", "Authorization"],
375 properties: {
376 "X-ENAME": { type: "string" },
377 Authorization: { type: "string" },
378 },
379 },
380 body: {
381 type: "object",
382 required: ["publicKey"],
383 properties: {
384 publicKey: { type: "string" },
385 },
386 },
387 response: {
388 200: {
389 type: "object",
390 properties: {
391 success: { type: "boolean" },
392 message: { type: "string" },
393 },
394 },
395 400: {
396 type: "object",
397 properties: {
398 error: { type: "string" },
399 },
400 },
401 401: {
402 type: "object",
403 properties: {
404 error: { type: "string" },
405 },
406 },
407 },
408 },
409 },
410 async (
411 request: TypedRequest<{ publicKey: string }>,
412 reply: TypedReply,
413 ) => {
414 const eName =
415 request.headers["x-ename"] || request.headers["X-ENAME"];
416 417 if (!eName || typeof eName !== "string") {
418 return reply
419 .status(400)
420 .send({ error: "X-ENAME header is required" });

</shell_result>


Fix header schema casing to match Fastify's lower‑cased header keys

Fastify normalizes incoming header names to lower case, and JSON-schema validation must use lowercase property names to match. In your schemas at lines 64-66 and 374-377, you currently require mixed‑case headers:

  • /whois (line 64-66): requires "X-ENAME"
  • /public-key (line 374-377): requires "X-ENAME" and "Authorization"

Even if clients send X-ENAME or Authorization, Fastify's validator will reject the request with a 400 error because by the time validation runs, the header object only contains x-ename and authorization. The handler's fallback code checking both cases (lines 88 and 415) will never execute.

Update the schemas to use lowercase keys:

 // /whois (lines 62-68)
headers: {
type: "object",
- required: ["X-ENAME"],+ required: ["x-ename"],
properties: {
- "X-ENAME": { type: "string" },+ "x-ename": { type: "string" },
},
},
 // /public-key (lines 372-379)
headers: {
type: "object",
- required: ["X-ENAME", "Authorization"],+ required: ["x-ename", "authorization"],
properties: {
- "X-ENAME": { type: "string" },- Authorization: { type: "string" },+ "x-ename": { type: "string" },+ authorization: { type: "string" },
},
},

The handler code that reads request.headers["x-ename"] and request.headers.authorization can remain unchanged.

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

🤖 Prompt for AI Agents
in infrastructure/evault-core/src/core/http/server.ts around lines 55-84 (whois
schema) and around lines 370-380 (public-key schema), the JSON-schema header
property names use mixed-case ("X-ENAME", "Authorization") but Fastify
lowercases headers for validation; change the schema header property keys and
any entries in the required arrays to lowercase ("x-ename" and "authorization"
as applicable) so the validator matches incoming requests; leave the handler
code that reads request.headers["x-ename"] and request.headers.authorization
unchanged.

@sosweethamsosweetham mentioned this pull request Dec 3, 2025
6 tasks
@coodoscoodos closed this Dec 8, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@sosweetham@coodos