ldrouter 1.11.12 → 1.11.15
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/app.js
CHANGED
|
@@ -82,6 +82,9 @@ export async function buildApp(opts = {}) {
|
|
|
82
82
|
registerAdminIpGate(app);
|
|
83
83
|
// Operational routes (always available)
|
|
84
84
|
await registerHealthRoutes(app);
|
|
85
|
+
// Debug logging for request lifecycle (before routes)
|
|
86
|
+
const { registerDebugHook } = await import('./logging/debug.js');
|
|
87
|
+
registerDebugHook(app);
|
|
85
88
|
// Admin + gateway routes MUST be registered BEFORE static files to avoid
|
|
86
89
|
// 404s falling through to SPA index.html or static assets being served instead
|
|
87
90
|
await registerAdminRoutes(app);
|
|
@@ -37,12 +37,21 @@ export function authenticateGatewayKey(req) {
|
|
|
37
37
|
candidate = anthropic;
|
|
38
38
|
if (!candidate)
|
|
39
39
|
return null;
|
|
40
|
+
// DEBUG: Log what we're trying to authenticate
|
|
41
|
+
console.log(`🔑 API KEY AUTH - Candidate extracted: ${candidate.slice(0, 8)}...${candidate.slice(-4)}`);
|
|
40
42
|
// Custom keys are stored verbatim (no prefix requirement); auto-generated
|
|
41
43
|
// keys start with ld-, but authentication must accept any stored secret.
|
|
42
44
|
const digest = sha256Hex(candidate);
|
|
45
|
+
console.log(`🔑 API KEY AUTH - SHA256 Digest: ${digest.slice(0, 16)}...`);
|
|
43
46
|
const db = getDb();
|
|
47
|
+
// DEBUG: Check total keys in database
|
|
48
|
+
const allKeys = db.select().from(schema.apiKeys).all();
|
|
49
|
+
console.log(`📊 TOTAL KEYS IN DB: ${allKeys.length}`);
|
|
50
|
+
console.log(`📋 ALL KEYS:`, allKeys.map(k => ({ id: k.id.slice(0, 8), name: k.name, keyPrefix: k.keyPrefix, digestPreview: k.keyDigest?.slice(0, 16) + '...' })));
|
|
44
51
|
const row = db.select().from(schema.apiKeys).where(eq(schema.apiKeys.keyDigest, digest)).get();
|
|
52
|
+
console.log(`❓ QUERY RESULT: Found match? ${!!row}`);
|
|
45
53
|
if (!row) {
|
|
54
|
+
console.error(`❌ INVALID API KEY - No matching digest found for: ${digest.slice(0, 32)}...`);
|
|
46
55
|
throw new GatewayError('authentication_error', 'Invalid API key', { status: 401 });
|
|
47
56
|
}
|
|
48
57
|
return {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Debug logging utilities for request lifecycle tracking
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
const DEBUG_LOG_DIR = '/data';
|
|
5
|
+
const DEBUG_LOG_FILE = path.join(DEBUG_LOG_DIR, 'ldrouter-debug.log');
|
|
6
|
+
// Ensure log file exists
|
|
7
|
+
if (!fs.existsSync(DEBUG_LOG_FILE)) {
|
|
8
|
+
try {
|
|
9
|
+
fs.writeFileSync(DEBUG_LOG_FILE, '');
|
|
10
|
+
}
|
|
11
|
+
catch (_err) {
|
|
12
|
+
// Silent fail - don't break the application
|
|
13
|
+
console.error('Failed to create debug log:', _err);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function appendDebugLog(entry) {
|
|
17
|
+
const logLine = JSON.stringify(entry) + '\n';
|
|
18
|
+
try {
|
|
19
|
+
fs.appendFileSync(DEBUG_LOG_FILE, logLine);
|
|
20
|
+
}
|
|
21
|
+
catch (_err) {
|
|
22
|
+
// Silent fail - don't break the application
|
|
23
|
+
console.error('Failed to write debug log:', _err);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function registerDebugHook(app) {
|
|
27
|
+
// Log every request entering the system
|
|
28
|
+
app.addHook('onRequest', async (req, _reply) => {
|
|
29
|
+
const entry = {
|
|
30
|
+
timestamp: new Date().toISOString(),
|
|
31
|
+
level: 'DEBUG',
|
|
32
|
+
requestId: req.id,
|
|
33
|
+
url: req.url,
|
|
34
|
+
method: req.method,
|
|
35
|
+
phase: 'REQUEST_ENTERED',
|
|
36
|
+
details: {
|
|
37
|
+
headers: {
|
|
38
|
+
authorization: req.headers.authorization ? '[REDACTED]' : undefined,
|
|
39
|
+
'content-type': req.headers['content-type'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
appendDebugLog(entry);
|
|
44
|
+
});
|
|
45
|
+
// Log before route handler execution
|
|
46
|
+
app.addHook('preHandler', async (req, _reply) => {
|
|
47
|
+
const entry = {
|
|
48
|
+
timestamp: new Date().toISOString(),
|
|
49
|
+
level: 'DEBUG',
|
|
50
|
+
requestId: req.id,
|
|
51
|
+
url: req.url,
|
|
52
|
+
method: req.method,
|
|
53
|
+
phase: 'ROUTE_MATCHED',
|
|
54
|
+
details: {},
|
|
55
|
+
};
|
|
56
|
+
appendDebugLog(entry);
|
|
57
|
+
});
|
|
58
|
+
// Log response completion with status code and content type
|
|
59
|
+
app.addHook('onResponse', async (_req, _reply) => {
|
|
60
|
+
// Note: We'll capture this in the onRequest handler instead for simpler logging
|
|
61
|
+
});
|
|
62
|
+
}
|
|
@@ -112,6 +112,10 @@ export async function registerApiKeyRoutes(app) {
|
|
|
112
112
|
throw new GatewayError('invalid_request_error', `An API key with this exact secret already exists ("${existing.name}"). Choose a different key value.`, { status: 409 });
|
|
113
113
|
}
|
|
114
114
|
const enc = encryptSecret(secret);
|
|
115
|
+
// DEBUG: Log what we're about to insert
|
|
116
|
+
console.log(`📝 CREATE API KEY - Name: ${body.name}, Prefix: ${keyPrefix}`);
|
|
117
|
+
console.log(`📝 CREATE API KEY - Secret (full): ${secret}`);
|
|
118
|
+
console.log(`📝 CREATE API KEY - Digest: ${keyDigest}`);
|
|
115
119
|
db.insert(schema.apiKeys).values({
|
|
116
120
|
id,
|
|
117
121
|
name: body.name,
|
|
@@ -131,6 +135,12 @@ export async function registerApiKeyRoutes(app) {
|
|
|
131
135
|
maxOutputTokensPerRequest: body.maxOutputTokensPerRequest ?? null,
|
|
132
136
|
cacheOverrideEnabled: body.cacheOverrideEnabled ?? null,
|
|
133
137
|
}).run();
|
|
138
|
+
// DEBUG: Verify it was actually inserted
|
|
139
|
+
const verify = db.select().from(schema.apiKeys).where(eq(schema.apiKeys.id, id)).get();
|
|
140
|
+
console.log(`✅ INSERT VERIFICATION: ${verify ? 'SUCCESS' : 'FAILED'} - Key exists in DB? ${!!verify}`);
|
|
141
|
+
if (!verify) {
|
|
142
|
+
console.error('❌ DATABASE INSERT FAILED - Key should exist but query returned null');
|
|
143
|
+
}
|
|
134
144
|
if (body.permissions) {
|
|
135
145
|
for (const p of body.permissions) {
|
|
136
146
|
db.insert(schema.apiKeyModelPermissions).values({ id: uuid(), apiKeyId: id, targetKind: p.targetKind, targetId: p.targetId }).run();
|