Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ VITE_DREAMSYNC_BASE_URL="http://localhost:8888"
EREPUTATION_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ereputation
EREPUTATION_MAPPING_DB_PATH="/path/to/erep/mapping/db"
VITE_EREPUTATION_BASE_URL=http://localhost:8765
PUBLIC_EREPUTATION_BASE_URL=http://localhost:8765

LOAD_TEST_USER_COUNT=6

Expand All @@ -108,9 +109,11 @@ LOKI_URL=http://localhost:3100
LOKI_USERNAME=admin
LOKI_PASSWORD=admin

LOKI_URL=http://146.190.29.56:3100
LOKI_USERNAME=admin
LOKI_PASSWORD=admin
# Control Panel
PUBLIC_CONTROL_PANEL_URL=http://localhost:5173
CONTROL_PANEL_JWT_SECRET=replace-with-a-strong-secret
CONTROL_PANEL_ADMIN_ENAMES_FILE=config/admin-enames.json
VISUALIZER_API_KEY=
Comment on lines +112 to +116
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Mar 15, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check which services import Control Panel environment variables

echo "=== Searching for CONTROL_PANEL_JWT_SECRET usage ==="
rg -n 'CONTROL_PANEL_JWT_SECRET' --type=ts --type=js -C2

echo -e "\n=== Searching for CONTROL_PANEL_ADMIN_ENAMES_FILE usage ==="
rg -n 'CONTROL_PANEL_ADMIN_ENAMES_FILE' --type=ts --type=js -C2

echo -e "\n=== Searching for VISUALIZER_API_KEY usage ==="
rg -n 'VISUALIZER_API_KEY' --type=ts --type=js -C2

echo -e "\n=== Searching for PUBLIC_CONTROL_PANEL_URL usage ==="
rg -n 'PUBLIC_CONTROL_PANEL_URL' --type=ts --type=js -C2

Repository: MetaState-Prototype-Project/prototype

Length of output: 6113


Reconsider which Control Panel variables belong at the root level.

Lines 112-116 add several configuration variables that partially duplicate infrastructure/control-panel/.env.example. The placement of these variables should be reviewed:

  • CONTROL_PANEL_JWT_SECRET: Used only within control-panel's auth logic (infrastructure/control-panel/src/lib/server/auth/token.ts). No other services reference it. Consider keeping this local to control-panel.
  • CONTROL_PANEL_ADMIN_ENAMES_FILE: Used only within control-panel's allowlist logic (infrastructure/control-panel/src/lib/server/auth/allowlist.ts). No other services reference it. Consider keeping this local to control-panel.
  • VISUALIZER_API_KEY: Used by both the ereputation service (platforms/ereputation/api/src/controllers/ReferenceController.ts) and control-panel. Justifies root-level placement for cross-service coordination.

The duplication of control-panel-only variables creates maintenance overhead. Move CONTROL_PANEL_JWT_SECRET and CONTROL_PANEL_ADMIN_ENAMES_FILE back to the control-panel-local .env.example, keeping only VISUALIZER_API_KEY at the root level.

🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 114-114: [UnorderedKey] The CONTROL_PANEL_JWT_SECRET key should go before the PUBLIC_CONTROL_PANEL_URL key

(UnorderedKey)


[warning] 115-115: [UnorderedKey] The CONTROL_PANEL_ADMIN_ENAMES_FILE key should go before the CONTROL_PANEL_JWT_SECRET key

(UnorderedKey)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.example around lines 112 - 116, Remove CONTROL_PANEL_JWT_SECRET and
CONTROL_PANEL_ADMIN_ENAMES_FILE from the root .env.example and re-add them only
to the control-panel's local .env.example to avoid duplication; keep
VISUALIZER_API_KEY at the root since it is referenced by multiple services (see
control-panel auth token logic in
infrastructure/control-panel/src/lib/server/auth/token.ts and allowlist logic in
infrastructure/control-panel/src/lib/server/auth/allowlist.ts, and the
ereputation ReferenceController.ts) so update the root and control-panel example
files accordingly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No this is planned otherwise it just leads to bad dx, I mean at the env vars are injected in prod anyways so who cares

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.

@coodos, understood — keeping all variables consolidated in the root .env.example is an intentional choice for developer experience, since it gives contributors a single place to configure everything locally without hunting across sub-project directories. And with production vars being injected externally anyway, the duplication concern is moot. Thanks for the context!


✏️ Learnings added
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 920
File: .env.example:112-116
Timestamp: 2026-03-15T19:21:53.065Z
Learning: In MetaState-Prototype-Project/prototype, consolidating all environment variables (including service-specific ones like CONTROL_PANEL_JWT_SECRET and CONTROL_PANEL_ADMIN_ENAMES_FILE) in the root .env.example is intentional for developer experience. Contributors should have a single place to configure everything locally. In production, variables are injected directly, so root-level duplication of service-specific vars is acceptable and by design.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
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.

Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 458
File: platforms/eReputation-api/src/services/ReferenceSigningSessionService.ts:60-60
Timestamp: 2025-11-21T15:49:12.904Z
Learning: In platforms/eReputation-api/src/services/ReferenceSigningSessionService.ts, the VITE_EREPUTATION_BASE_URL environment variable intentionally has no fallback value. The service should fail if this environment variable is not set, following a fail-fast design pattern.


DREAMSYNC_JWT_SECRET="secret"
ECURRENCY_JWT_SECRET="secret"
Expand Down
8 changes: 8 additions & 0 deletions infrastructure/control-panel/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ LOKI_PASSWORD=admin
PUBLIC_REGISTRY_URL=https://registry.staging.metastate.foundation
PUBLIC_CONTROL_PANEL_URL=http://localhost:5173

# Provisioner
PUBLIC_PROVISIONER_URL=http://localhost:3001

# Notification Trigger (for Notifications tab proxy)
NOTIFICATION_TRIGGER_URL=http://localhost:3998
NOTIFICATION_TRIGGER_PORT=3998

# eReputation / Visualizer
PUBLIC_EREPUTATION_BASE_URL=http://localhost:8765
VISUALIZER_API_KEY=

# W3DS Auth Configuration
CONTROL_PANEL_JWT_SECRET=replace-with-a-strong-secret
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import {
NOTIFICATION_TRIGGER_PORT,
NOTIFICATION_TRIGGER_URL,
PROVISIONER_URL,
PUBLIC_PROVISIONER_URL
} from '$env/static/private';
import { PUBLIC_PROVISIONER_URL } from '$env/static/public';
import { NOTIFICATION_TRIGGER_PORT, NOTIFICATION_TRIGGER_URL } from '$env/static/private';

export interface NotificationPayload {
title: string;
Expand Down Expand Up @@ -54,7 +50,7 @@ export async function sendNotification(request: SendNotificationRequest): Promis
}

export async function getDevicesWithTokens(): Promise<{ token: string; eName: string }[]> {
const provisionerUrl = PUBLIC_PROVISIONER_URL || PROVISIONER_URL || 'http://localhost:3001';
const provisionerUrl = PUBLIC_PROVISIONER_URL || 'http://localhost:3001';
try {
const response = await fetch(`${provisionerUrl}/api/devices/list`, {
signal: AbortSignal.timeout(10000)
Expand All @@ -71,7 +67,7 @@ export async function getDevicesWithTokens(): Promise<{ token: string; eName: st
export async function getDevicesByEName(
eName: string
): Promise<{ token: string; eName: string }[]> {
const provisionerUrl = PUBLIC_PROVISIONER_URL || PROVISIONER_URL || 'http://localhost:3001';
const provisionerUrl = PUBLIC_PROVISIONER_URL || 'http://localhost:3001';
try {
const response = await fetch(
`${provisionerUrl}/api/devices/by-ename/${encodeURIComponent(eName)}`,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { json } from '@sveltejs/kit';
import type { RequestHandler } from '@sveltejs/kit';
import { EREPUTATION_BASE_URL, VISUALIZER_API_KEY } from '$env/static/private';
import { PUBLIC_EREPUTATION_BASE_URL } from '$env/static/public';
import { VISUALIZER_API_KEY } from '$env/static/private';

export const GET: RequestHandler = async () => {
const baseUrl = EREPUTATION_BASE_URL || 'http://localhost:8765';
const baseUrl = PUBLIC_EREPUTATION_BASE_URL || 'http://localhost:8765';

try {
const controller = new AbortController();
Expand Down
Loading