File size: 7,025 Bytes
93c7565 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | /**
* dashboard/server.js
* ----------------------------------------------------------
* ProofBridge Liner — Operations Dashboard.
*
* A small Express server that surfaces:
* • Phase progress for the 72-hour MVP sprint
* • Configured assets and their last fetcher result
* • Live signer-node heartbeat (best-effort)
* • The CircuitBreaker contract address (once deployed)
*
* Trusts the proxy host header (Replit iframe preview).
*/
const express = require('express');
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '..');
const ASSETS_PATH = path.join(ROOT, 'config', 'assets.json');
const SIGNERS_PATH = path.join(ROOT, 'config', 'signer-nodes.json');
const STATE_PATH = path.join(ROOT, '.local', 'state', 'prover-state.json');
const PORT = Number(process.env.DASHBOARD_PORT || 5000);
const HOST = process.env.DASHBOARD_HOST || '0.0.0.0';
const PHASES = [
{ id: 0, name: 'Env scaffold', pct: 100 },
{ id: 1, name: 'Write & test CircuitBreaker', pct: 100 },
{ id: 2, name: 'Deploy to Polygon Amoy', pct: 100 },
{ id: 3, name: 'Build fetcher + submitter', pct: 100 },
{ id: 4, name: 'Mock 3-node quorum (Docker)', pct: 100 },
{ id: 5, name: 'Institution-grade: TEE + Registry', pct: 75 },
{ id: 6, name: 'Coq + TLA+ formal proofs', pct: 100 },
{ id: 7, name: 'E2E demo recording', pct: 0 },
{ id: 8, name: 'Ghost-risk audit & pitch', pct: 0 },
];
const TEST_RESULTS = [
{ name: 'testInitializeSetsOwnerAndOracle', gas: 14321, passed: true },
{ name: 'testInitializeRevertsOnSecondCall', gas: 13902, passed: true },
{ name: 'testUpdateProofByOracle', gas: 44241, passed: true },
{ name: 'testUpdateProofEmitsEvent', gas: 45177, passed: true },
{ name: 'testUpdateProofRevertsIfNotOracle', gas: 13738, passed: true },
{ name: 'testTripCircuitByOracle', gas: 44116, passed: true },
{ name: 'testTripCircuitEmitsEvent', gas: 45030, passed: true },
{ name: 'testTripCircuitRevertsIfNotOracle', gas: 13671, passed: true },
{ name: 'testValidateWhenOpenAndHashMatches', gas: 48449, passed: true },
{ name: 'testValidateWhenOpenAndHashDoesNotMatch', gas: 48473, passed: true },
{ name: 'testValidateRevertsWhenCircuitTripped', gas: 44732, passed: true },
{ name: 'testResetByOwner', gas: 45034, passed: true },
{ name: 'testResetEmitsEvent', gas: 45925, passed: true },
{ name: 'testResetRevertsIfNotOwner', gas: 44683, passed: true },
];
function readJsonSafe(p, fallback) {
try {
return JSON.parse(fs.readFileSync(p, 'utf8'));
} catch (_) {
return fallback;
}
}
const app = express();
app.disable('etag');
// --- Replit preview lives behind a proxy iframe; trust the proxy ---
app.set('trust proxy', true);
// --- Dev-mode no-cache so the iframe always sees latest content ---
if (process.env.NODE_ENV !== 'production') {
app.use((req, res, next) => {
res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
res.set('Pragma', 'no-cache');
res.set('Expires', '0');
next();
});
}
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
app.get('/api/status', (_req, res) => {
res.json({
project: 'ProofBridge Liner',
tagline: 'Ghost-Risk Circuit-Breaker for tokenised real-world assets',
network: 'Polygon Amoy (testnet)',
circuitBreakerAddress: process.env.CIRCUIT_BREAKER_ADDRESS || null,
oracleAddress: process.env.ORACLE_ADDRESS || null,
assetRegistryAddress: process.env.ASSET_REGISTRY_ADDRESS || null,
teeVerifierAddress: process.env.TEE_VERIFIER_ADDRESS || null,
enclaveAddress: process.env.ENCLAVE_ADDRESS || null,
phases: PHASES,
tests: {
total: TEST_RESULTS.length,
passed: TEST_RESULTS.filter((t) => t.passed).length,
results: TEST_RESULTS,
},
architecture: {
layers: [
{
id: 'logic',
name: 'Logic Layer',
description: 'Coq-verified total functions',
artifact: 'proofs/SafetyKernel.v',
theorems: [
'unauthorized_halt_is_absorbing',
'posterior_above_threshold_trips',
'posterior_below_threshold_stays_open',
'auth_can_reset',
],
status: 'proven',
},
{
id: 'input',
name: 'Input Layer',
description: 'TEE-signed attestations (EIP-191 ECDSA)',
artifact: 'contracts/TEEVerifier.sol',
status: 'deployed-pending',
},
{
id: 'enforcement',
name: 'Enforcement Layer',
description: 'EVM circuit breakers — per-asset isolated kernels',
artifact: 'contracts/AssetRegistry.sol',
status: 'deployed-pending',
},
],
verification: [
{ name: 'Coq Proof', status: 'complete', note: 'UNAUTH actors cannot reset' },
{ name: 'Gas analysis', status: 'complete', note: 'O(1) check() execution' },
{ name: 'TLA+ Model', status: 'complete', note: 'No deadlocks — 4 invariants + liveness property' },
{ name: 'SOC 2 CC6', status: 'complete', note: 'CC6.1/2/3/6/7/8 — all controls mapped' },
],
},
assets: readJsonSafe(ASSETS_PATH, []),
signerNodes: readJsonSafe(SIGNERS_PATH, []),
proverState: readJsonSafe(STATE_PATH, null),
serverTime: new Date().toISOString(),
});
});
app.get('/health', (_req, res) => res.json({ status: 'ok', uptime: process.uptime() }));
app.get('/api/health', async (req, res) => {
const gateways = [
'https://ipfs.io/ipfs/',
'https://cloudflare-ipfs.com/ipfs/',
'https://gateway.pinata.cloud/ipfs/',
];
const gatewayHealth = {};
await Promise.all(gateways.map(async (gateway) => {
const start = Date.now();
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 4000);
try {
await fetch(`${gateway}QmbWqxBEKC3P8tqsKc98xmWNzrzDRRLbhtJ38WNqHVWojK`, {
method: 'HEAD',
signal: controller.signal,
});
gatewayHealth[gateway] = { status: 'healthy', latency: Date.now() - start };
} catch (err) {
gatewayHealth[gateway] = { status: 'unreachable', error: err.message };
} finally {
clearTimeout(timer);
}
}));
// Read prover state if exists
let proverState = {};
try {
const stateFile = path.resolve(__dirname, '..', '.local', 'state', 'prover-state.json');
if (fs.existsSync(stateFile)) {
proverState = JSON.parse(fs.readFileSync(stateFile, 'utf-8'));
}
} catch (e) { /* ignore */ }
res.json({
uptime: process.uptime(),
gateways: gatewayHealth,
proverState
});
});
app.listen(PORT, HOST, () => {
console.log(`[dashboard] ProofBridge Liner Ops listening on http://${HOST}:${PORT}`);
});
|