@agent-relay/dashboard-server 2.0.38 → 2.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.js +47 -6
- package/dist/server.js.map +1 -1
- package/out/404.html +1 -1
- package/out/_next/static/chunks/983-598ff3b7e6dffb8f.js +1 -0
- package/out/about.html +1 -1
- package/out/about.txt +1 -1
- package/out/app/onboarding.html +1 -1
- package/out/app/onboarding.txt +1 -1
- package/out/app.html +1 -1
- package/out/app.txt +2 -2
- package/out/blog.html +1 -1
- package/out/blog.txt +1 -1
- package/out/careers.html +1 -1
- package/out/careers.txt +1 -1
- package/out/changelog.html +1 -1
- package/out/changelog.txt +1 -1
- package/out/cloud/link.html +1 -1
- package/out/cloud/link.txt +1 -1
- package/out/complete-profile.html +1 -1
- package/out/complete-profile.txt +1 -1
- package/out/connect-repos.html +1 -1
- package/out/connect-repos.txt +1 -1
- package/out/contact.html +1 -1
- package/out/contact.txt +1 -1
- package/out/docs.html +1 -1
- package/out/docs.txt +1 -1
- package/out/history.html +1 -1
- package/out/history.txt +1 -1
- package/out/index.html +1 -1
- package/out/index.txt +2 -2
- package/out/login.html +1 -1
- package/out/login.txt +1 -1
- package/out/metrics.html +1 -1
- package/out/metrics.txt +1 -1
- package/out/pricing.html +1 -1
- package/out/pricing.txt +1 -1
- package/out/privacy.html +1 -1
- package/out/privacy.txt +1 -1
- package/out/providers/setup/claude.html +1 -1
- package/out/providers/setup/claude.txt +1 -1
- package/out/providers/setup/codex.html +1 -1
- package/out/providers/setup/codex.txt +1 -1
- package/out/providers/setup/cursor.html +1 -1
- package/out/providers/setup/cursor.txt +1 -1
- package/out/providers.html +1 -1
- package/out/providers.txt +1 -1
- package/out/security.html +1 -1
- package/out/security.txt +1 -1
- package/out/signup.html +1 -1
- package/out/signup.txt +1 -1
- package/out/terms.html +1 -1
- package/out/terms.txt +1 -1
- package/package.json +1 -1
- package/out/_next/static/chunks/983-ae0bbf38febd0c61.js +0 -1
- /package/out/_next/static/{5Gm-p6vZlC7ybV6NrMmHU → ihGidN_vO8k4Yv_u6eOpR}/_buildManifest.js +0 -0
- /package/out/_next/static/{5Gm-p6vZlC7ybV6NrMmHU → ihGidN_vO8k4Yv_u6eOpR}/_ssgManifest.js +0 -0
package/dist/server.js
CHANGED
|
@@ -3317,6 +3317,39 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
3317
3317
|
});
|
|
3318
3318
|
});
|
|
3319
3319
|
// ===== CLI Auth API (for workspace-based provider authentication) =====
|
|
3320
|
+
/**
|
|
3321
|
+
* Middleware to validate workspace token for internal endpoints.
|
|
3322
|
+
* In cloud mode, requests to /auth/cli/* must include a valid WORKSPACE_TOKEN
|
|
3323
|
+
* to prevent unauthorized access to auth sessions.
|
|
3324
|
+
*/
|
|
3325
|
+
const validateWorkspaceToken = (req, res, next) => {
|
|
3326
|
+
// Skip auth validation in local mode (no WORKSPACE_TOKEN set)
|
|
3327
|
+
const expectedToken = process.env.WORKSPACE_TOKEN;
|
|
3328
|
+
if (!expectedToken) {
|
|
3329
|
+
return next();
|
|
3330
|
+
}
|
|
3331
|
+
// Extract token from Authorization header
|
|
3332
|
+
const authHeader = req.headers.authorization;
|
|
3333
|
+
const token = authHeader?.startsWith('Bearer ')
|
|
3334
|
+
? authHeader.substring(7)
|
|
3335
|
+
: null;
|
|
3336
|
+
// Use timing-safe comparison to prevent timing attacks
|
|
3337
|
+
if (!token) {
|
|
3338
|
+
console.warn('[dashboard] Unauthorized CLI auth request - missing workspace token');
|
|
3339
|
+
return res.status(401).json({ error: 'Unauthorized - invalid workspace token' });
|
|
3340
|
+
}
|
|
3341
|
+
const tokenBuffer = Buffer.from(token);
|
|
3342
|
+
const expectedBuffer = Buffer.from(expectedToken);
|
|
3343
|
+
const isValidToken = tokenBuffer.length === expectedBuffer.length &&
|
|
3344
|
+
crypto.timingSafeEqual(tokenBuffer, expectedBuffer);
|
|
3345
|
+
if (!isValidToken) {
|
|
3346
|
+
console.warn('[dashboard] Unauthorized CLI auth request - invalid workspace token');
|
|
3347
|
+
return res.status(401).json({ error: 'Unauthorized - invalid workspace token' });
|
|
3348
|
+
}
|
|
3349
|
+
next();
|
|
3350
|
+
};
|
|
3351
|
+
// Apply workspace token validation to all CLI auth endpoints
|
|
3352
|
+
app.use('/auth/cli', validateWorkspaceToken);
|
|
3320
3353
|
/**
|
|
3321
3354
|
* POST /auth/cli/:provider/start - Start CLI auth flow
|
|
3322
3355
|
* Body: { useDeviceFlow?: boolean, userId?: string }
|
|
@@ -3575,9 +3608,13 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
3575
3608
|
lastSeen: a.lastSeen ?? new Date().toISOString(),
|
|
3576
3609
|
}));
|
|
3577
3610
|
}
|
|
3578
|
-
// Get messages for throughput calculation
|
|
3579
|
-
|
|
3580
|
-
|
|
3611
|
+
// Get messages for throughput calculation - use storage directly for metrics
|
|
3612
|
+
// (avoids daemon query timeouts that occur when daemon is busy)
|
|
3613
|
+
let messages = [];
|
|
3614
|
+
if (storage) {
|
|
3615
|
+
const rows = await storage.getMessages({ limit: 100, order: 'desc' });
|
|
3616
|
+
messages = rows.map(r => ({ timestamp: new Date(r.ts).toISOString() }));
|
|
3617
|
+
}
|
|
3581
3618
|
// Get session data for lifecycle metrics
|
|
3582
3619
|
const sessions = storage?.getSessions
|
|
3583
3620
|
? await storage.getSessions({ limit: 100 })
|
|
@@ -3608,9 +3645,13 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
3608
3645
|
lastSeen: a.lastSeen ?? new Date().toISOString(),
|
|
3609
3646
|
}));
|
|
3610
3647
|
}
|
|
3611
|
-
// Get messages for throughput calculation
|
|
3612
|
-
|
|
3613
|
-
|
|
3648
|
+
// Get messages for throughput calculation - use storage directly for metrics
|
|
3649
|
+
// (avoids daemon query timeouts that occur when daemon is busy)
|
|
3650
|
+
let messages = [];
|
|
3651
|
+
if (storage) {
|
|
3652
|
+
const rows = await storage.getMessages({ limit: 100, order: 'desc' });
|
|
3653
|
+
messages = rows.map(r => ({ timestamp: new Date(r.ts).toISOString() }));
|
|
3654
|
+
}
|
|
3614
3655
|
// Get session data for lifecycle metrics
|
|
3615
3656
|
const sessions = storage?.getSessions
|
|
3616
3657
|
? await storage.getSessions({ limit: 100 })
|