Skip to content
Open
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
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,13 @@ EREPUTATION_MAPPING_DB_PATH="/path/to/erep/mapping/db"
VITE_EREPUTATION_BASE_URL=http://localhost:8765

LOAD_TEST_USER_COUNT=6

PUBLIC_EID_WALLET_TOKEN=obtained-from-post-registry-service-/platforms/certification

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
Comment on lines +77 to +83
Copy link
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
# First, find the .env.example file and check its content around the specified lines
fd -name ".env.example" -type f

Repository: MetaState-Prototype-Project/prototype

Length of output: 311


🏁 Script executed:

#!/bin/bash
# Find the .env.example file
fd ".env.example" -type f

Repository: MetaState-Prototype-Project/prototype

Length of output: 251


🏁 Script executed:

#!/bin/bash
# Find the .env.example file
fd ".env.example"

Repository: MetaState-Prototype-Project/prototype

Length of output: 154


🏁 Script executed:

#!/bin/bash
# Check the content of both .env.example files, focusing on lines around 77-83
echo "=== infrastructure/control-panel/.env.example ==="
wc -l infrastructure/control-panel/.env.example
echo ""
echo "Lines 70-90:"
sed -n '70,90p' infrastructure/control-panel/.env.example

echo ""
echo "=== platforms/pictique/.env.example ==="
wc -l platforms/pictique/.env.example
echo ""
echo "Lines 70-90:"
sed -n '70,90p' platforms/pictique/.env.example

Repository: MetaState-Prototype-Project/prototype

Length of output: 277


🏁 Script executed:

#!/bin/bash
# Search for files containing LOKI_URL
echo "=== Files containing LOKI_URL ==="
rg "LOKI_URL" -l

echo ""
echo "=== Context around LOKI_URL matches ==="
rg "LOKI_URL" -B2 -A2

Repository: MetaState-Prototype-Project/prototype

Length of output: 1387


🏁 Script executed:

#!/bin/bash
# Check git diff to see what changed in the PR
echo "=== Git diff for infrastructure/control-panel/.env.example ==="
git diff HEAD infrastructure/control-panel/.env.example

echo ""
echo "=== Full content of infrastructure/control-panel/.env.example ==="
cat -n infrastructure/control-panel/.env.example

Repository: MetaState-Prototype-Project/prototype

Length of output: 443


🏁 Script executed:

#!/bin/bash
# Look for .env files in infrastructure/eid-wallet (mentioned in learnings)
echo "=== Search for .env files in infrastructure/eid-wallet ==="
fd ".env" infrastructure/eid-wallet

echo ""
echo "=== Search for any .env files in infrastructure/ ==="
fd ".env" infrastructure/

echo ""
echo "=== Check git log to see recent changes to .env.example files ==="
git log --oneline infrastructure/control-panel/.env.example | head -10

Repository: MetaState-Prototype-Project/prototype

Length of output: 341


🏁 Script executed:

#!/bin/bash
# Check current branch and git status
echo "=== Current branch info ==="
git branch -v
git log --oneline -5

echo ""
echo "=== Check if there are other .env.example files ==="
find . -name ".env*" -type f

echo ""
echo "=== Search for the IP 146.190.29.56 in the entire codebase ==="
rg "146.190.29.56"

Repository: MetaState-Prototype-Project/prototype

Length of output: 614


🏁 Script executed:

#!/bin/bash
# Check the root .env.example file
echo "=== Root .env.example file ==="
wc -l .env.example

echo ""
echo "=== Lines 70-90 of root .env.example ==="
sed -n '70,90p' .env.example

echo ""
echo "=== Search for LOKI in root .env.example ==="
grep -n "LOKI" .env.example

Repository: MetaState-Prototype-Project/prototype

Length of output: 740


🏁 Script executed:

#!/bin/bash
# Check git diff for root .env.example
echo "=== Git diff for .env.example ==="
git diff HEAD .env.example

echo ""
echo "=== Git log for .env.example ==="
git log --oneline .env.example | head -5

echo ""
echo "=== Full content of .env.example to verify context ==="
cat -n .env.example | tail -20

Repository: MetaState-Prototype-Project/prototype

Length of output: 1012


🏁 Script executed:

#!/bin/bash
# Search for .env file parsing/loading to understand how duplicates are handled
echo "=== Search for dotenv or env loading patterns ==="
rg "dotenv|process\.env|EnvConfig|env\.load" --type=ts --type=js -B2 -A2 | head -60

echo ""
echo "=== Check if .env.example is referenced in package.json or build config ==="
fd "package.json|vite.config|webpack.config|tsconfig" | xargs grep -l "env.example" 2>/dev/null || echo "No references found"

Repository: MetaState-Prototype-Project/prototype

Length of output: 4124


Remove duplicate Loki environment variables from .env.example.

Lines 77–83 contain duplicate LOKI_URL, LOKI_USERNAME, and LOKI_PASSWORD keys. The second set (lines 81–83) will overwrite the first during dotenv parsing, causing the production IP address (146.190.29.56) to be used instead of the localhost development configuration. Additionally, .env.example should contain a single canonical set of example values, not multiple configurations.

Apply this diff to keep only the development configuration:

 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

Alternatively, if production configuration reference is needed:

 LOKI_URL=http://localhost:3100
 LOKI_USERNAME=admin
 LOKI_PASSWORD=admin
+
+# Production Loki configuration (use via environment secrets, not this file):
+# LOKI_URL=http://146.190.29.56:3100
+# LOKI_USERNAME=admin
+# LOKI_PASSWORD=admin
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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
LOKI_URL=http://localhost:3100
LOKI_USERNAME=admin
LOKI_PASSWORD=admin
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 79-79: [UnorderedKey] The LOKI_PASSWORD key should go before the LOKI_URL key

(UnorderedKey)


[warning] 81-81: [DuplicatedKey] The LOKI_URL key is duplicated

(DuplicatedKey)


[warning] 82-82: [DuplicatedKey] The LOKI_USERNAME key is duplicated

(DuplicatedKey)


[warning] 83-83: [DuplicatedKey] The LOKI_PASSWORD key is duplicated

(DuplicatedKey)


[warning] 83-83: [UnorderedKey] The LOKI_PASSWORD key should go before the LOKI_URL key

(UnorderedKey)

🤖 Prompt for AI Agents
In .env.example around lines 77 to 83, there are duplicate
LOKI_URL/LOKI_USERNAME/LOKI_PASSWORD entries; remove the duplicate production
block so only the development configuration (LOKI_URL=http://localhost:3100,
LOKI_USERNAME=admin, LOKI_PASSWORD=admin) remains, deleting the second set (the
146.190.29.56 lines) to ensure a single canonical example and prevent dotenv
from being overwritten by the production IP.

Empty file added asd
Empty file.
39 changes: 39 additions & 0 deletions db/init-multiple-databases.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash
set -e

# Get the list of databases from environment variable
# Default to empty if not set
POSTGRES_MULTIPLE_DATABASES=${POSTGRES_MULTIPLE_DATABASES:-}

# If no databases specified, exit
if [ -z "$POSTGRES_MULTIPLE_DATABASES" ]; then
echo "No databases specified in POSTGRES_MULTIPLE_DATABASES"
exit 0
fi

echo "Creating multiple databases..."

# Split the comma-separated list and create each database
IFS=',' read -ra DATABASES <<< "$POSTGRES_MULTIPLE_DATABASES"
for db in "${DATABASES[@]}"; do
# Trim whitespace
db=$(echo "$db" | xargs)

if [ -n "$db" ]; then
# Check if database exists
DB_EXISTS=$(psql -v ON_ERROR_STOP=0 --username "$POSTGRES_USER" --dbname postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$db'" 2>/dev/null || echo "")

if [ "$DB_EXISTS" = "1" ]; then
echo "Database $db already exists, skipping..."
else
echo "Creating database: $db"
# Create the database directly (not inside a function)
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres <<-EOSQL
CREATE DATABASE "$db";
EOSQL
fi
fi
done

echo "Multiple databases created successfully!"

25 changes: 25 additions & 0 deletions dev-docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ services:
networks:
- metastate-network
<<: *common-host-access
entrypoint: ["/bin/sh", "-c"]
command:
- |
# Remove any stale PID files before starting Neo4j
# Neo4j stores PID files in /var/lib/neo4j/run/neo4j.pid
rm -f /var/lib/neo4j/run/neo4j.pid 2>/dev/null || true
rm -f /var/lib/neo4j/data/run/neo4j.pid 2>/dev/null || true
rm -f /var/lib/neo4j/data/neo4j.pid 2>/dev/null || true
# Also clean up any other PID files
find /var/lib/neo4j -name "*.pid" -type f -delete 2>/dev/null || true
find /var/lib/neo4j/data -name "*.pid" -type f -delete 2>/dev/null || true
# Start Neo4j with the original entrypoint
exec /startup/docker-entrypoint.sh neo4j
healthcheck:
test: [ "CMD-SHELL", "cypher-shell -u neo4j -p ${NEO4J_PASSWORD:-neo4j} 'RETURN 1' || exit 1" ]
interval: 10s
Expand Down Expand Up @@ -557,6 +570,18 @@ services:
- metastate-network
<<: *common-host-access

# Loki for log aggregation
loki:
profiles:
- all
image: grafana/loki:latest
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
networks:
- metastate-network
<<: *common-host-access

volumes:
postgres_data:
neo4j_data:
Expand Down
36 changes: 14 additions & 22 deletions infrastructure/control-panel/src/lib/components/EVaultList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
<div class="py-8 text-center">
<p class="text-gray-500">No eVaults found</p>
<p class="mt-1 text-sm text-gray-400">
Try refreshing or check your Kubernetes connection
Try refreshing or check your registry connection
</p>
</div>
{:else}
Expand All @@ -155,7 +155,7 @@
<th
class="px-6 py-3 text-left text-xs font-medium tracking-wider text-gray-500 uppercase"
>
Namespace
eName (w3id)
</th>
<th
class="px-6 py-3 text-left text-xs font-medium tracking-wider text-gray-500 uppercase"
Expand All @@ -165,12 +165,7 @@
<th
class="px-6 py-3 text-left text-xs font-medium tracking-wider text-gray-500 uppercase"
>
Age
</th>
<th
class="px-6 py-3 text-left text-xs font-medium tracking-wider text-gray-500 uppercase"
>
Service URL
URI
</th>
</tr>
</thead>
Expand All @@ -180,38 +175,35 @@
<td
class="px-6 py-4 text-sm font-medium whitespace-nowrap text-gray-900"
>
{evault.name}
{evault.name || evault.ename || evault.evault}
</td>
<td class="px-6 py-4 text-sm whitespace-nowrap text-gray-500">
{evault.namespace}
{evault.ename || 'N/A'}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span
class="inline-flex rounded-full px-2 py-1 text-xs font-semibold {evault.status ===
'Running'
'Active'
? 'bg-green-100 text-green-800'
: evault.status === 'Pending'
? 'bg-yellow-100 text-yellow-800'
: 'bg-red-100 text-red-800'}"
: evault.status === 'Inactive'
? 'bg-red-100 text-red-800'
: 'bg-gray-100 text-gray-800'}"
>
{evault.status}
{evault.status || 'Unknown'}
</span>
</td>
<td class="px-6 py-4 text-sm whitespace-nowrap text-gray-500">
{evault.age || 'Unknown'}
</td>
<td class="px-6 py-4 text-sm whitespace-nowrap text-gray-500">
{#if evault.serviceUrl}
{#if evault.uri || evault.serviceUrl}
<a
href={evault.serviceUrl}
href={evault.uri || evault.serviceUrl}
target="_blank"
rel="noopener noreferrer"
class="text-blue-600 underline hover:text-blue-800"
>
{evault.serviceUrl}
{evault.uri || evault.serviceUrl}
</a>
{:else}
<span class="text-gray-400">No external access</span>
<span class="text-gray-400">No URI available</span>
{/if}
</td>
</tr>
Expand Down
25 changes: 12 additions & 13 deletions infrastructure/control-panel/src/lib/services/evaultService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,15 @@ export class EVaultService {
}

/**
* Get logs for a specific eVault pod
* Get logs for a specific eVault by evaultId
*/
/**
* Get logs for a specific eVault pod
*/
static async getEVaultLogs(namespace: string, podName: string): Promise<string[]> {
static async getEVaultLogs(evaultId: string, tail?: number): Promise<string[]> {
try {
const response = await fetch(
`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/logs`
);
const url = new URL(`/api/evaults/${encodeURIComponent(evaultId)}/logs`, window.location.origin);
if (tail) {
url.searchParams.set('tail', tail.toString());
}
const response = await fetch(url.toString());
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
Expand All @@ -97,20 +96,20 @@ export class EVaultService {
}

/**
* Get metrics for a specific eVault pod
* Get details for a specific eVault by evaultId
*/
static async getEVaultMetrics(namespace: string, podName: string): Promise<any> {
static async getEVaultDetails(evaultId: string): Promise<any> {
try {
const response = await fetch(
`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/metrics`
`/api/evaults/${encodeURIComponent(evaultId)}/details`
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.metrics || {};
return data.evault || {};
} catch (error) {
console.error('Failed to fetch eVault metrics:', error);
console.error('Failed to fetch eVault details:', error);
throw error;
}
}
Expand Down
43 changes: 43 additions & 0 deletions infrastructure/control-panel/src/lib/services/loki.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,49 @@ export class LokiService {
.filter((event): event is FlowEvent => event !== null);
}

/**
* Query logs for a specific evault by identifier
* Supports querying by evault field or ename (w3id) in log labels
*/
async getEVaultLogs(
evaultId: string,
ename?: string,
limit: number = 100,
start?: string,
end?: string
): Promise<string[]> {
// Try multiple query patterns to find logs for this evault
// First try by evault field, then by ename/w3id
const queries = [
`{evault="${evaultId}"}`,
...(ename ? [`{ename="${ename}"}`, `{w3id="${ename}"}`] : [])
];

const allLogs: LogEntry[] = [];

// Try each query pattern
for (const query of queries) {
try {
const logs = await this.queryLogs(query, start, end);
allLogs.push(...logs);
} catch (error) {
console.log(`Query ${query} failed, trying next pattern`);
}
}

// Remove duplicates and sort by timestamp
const uniqueLogs = Array.from(
new Map(allLogs.map((log) => [`${log.timestamp}-${log.line}`, log])).values()
).sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());

// Extract log lines and limit to requested number
const logLines = uniqueLogs
.map((log) => log.line)
.slice(-limit); // Get last N lines

return logLines;
}

parseLogEntry(log: LogEntry): FlowEvent | null {
try {
// Parse the JSON log line
Expand Down
Loading
Loading