Expand KOC LOOP MCP operations
This commit is contained in:
75
lib/mcp-export-token.ts
Normal file
75
lib/mcp-export-token.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { ensureSchema, getRawDb } from "./mvp-db";
|
||||
|
||||
export type McpExportKind = "recovery" | "resources";
|
||||
|
||||
type ExportTokenRow = {
|
||||
kind: McpExportKind;
|
||||
payload: string;
|
||||
expires_at: string;
|
||||
};
|
||||
|
||||
function sqliteTimestamp(date: Date) {
|
||||
return date.toISOString().replace("T", " ").slice(0, 19);
|
||||
}
|
||||
|
||||
async function digest(value: string) {
|
||||
const bytes = await crypto.subtle.digest(
|
||||
"SHA-256",
|
||||
new TextEncoder().encode(value),
|
||||
);
|
||||
return [...new Uint8Array(bytes)]
|
||||
.map((byte) => byte.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
}
|
||||
|
||||
export async function issueMcpExportToken(
|
||||
kind: McpExportKind,
|
||||
payload: Record<string, unknown>,
|
||||
ttlMinutes = 15,
|
||||
) {
|
||||
await ensureSchema();
|
||||
const db = getRawDb();
|
||||
const token = `${crypto.randomUUID().replaceAll("-", "")}${crypto
|
||||
.randomUUID()
|
||||
.replaceAll("-", "")}`;
|
||||
const expiresAt = new Date(
|
||||
Date.now() + Math.max(1, Math.min(60, ttlMinutes)) * 60_000,
|
||||
);
|
||||
await db.prepare("DELETE FROM mcp_export_tokens WHERE expires_at <= CURRENT_TIMESTAMP").run();
|
||||
await db
|
||||
.prepare(
|
||||
`INSERT INTO mcp_export_tokens (token_hash, kind, payload, expires_at)
|
||||
VALUES (?, ?, ?, ?)`,
|
||||
)
|
||||
.bind(await digest(token), kind, JSON.stringify(payload), sqliteTimestamp(expiresAt))
|
||||
.run();
|
||||
return { token, expiresAt: expiresAt.toISOString() };
|
||||
}
|
||||
|
||||
export async function consumeMcpExportToken(
|
||||
token: string,
|
||||
expectedKind: McpExportKind,
|
||||
) {
|
||||
if (!token || token.length < 32) return null;
|
||||
await ensureSchema();
|
||||
const db = getRawDb();
|
||||
const tokenHash = await digest(token);
|
||||
const row = await db
|
||||
.prepare(
|
||||
`SELECT kind, payload, expires_at
|
||||
FROM mcp_export_tokens
|
||||
WHERE token_hash = ? AND expires_at > CURRENT_TIMESTAMP`,
|
||||
)
|
||||
.bind(tokenHash)
|
||||
.first<ExportTokenRow>();
|
||||
if (!row || row.kind !== expectedKind) return null;
|
||||
await db
|
||||
.prepare("DELETE FROM mcp_export_tokens WHERE token_hash = ?")
|
||||
.bind(tokenHash)
|
||||
.run();
|
||||
try {
|
||||
return JSON.parse(row.payload) as Record<string, unknown>;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user