feat: fail closed before domain runtime entry

This commit is contained in:
冰朔 2026-08-10 01:23:52 +08:00
commit 0990e96c0e
6 changed files with 160 additions and 8 deletions

View file

@ -18,6 +18,7 @@ import path from 'path';
import { spawn, ChildProcess } from 'child_process';
import fs from 'fs';
import { importKnowledgeFolder } from './folder-import.js';
import { evaluateDomainAccess } from '../../guanghu-knowledge-base/server/domain-access.js';
// ─── 配置 ───
@ -565,6 +566,25 @@ ipcMain.handle('server:session', async (_event, requestedNodeId?: string) => {
return { authenticated: false, nodeId };
}
});
ipcMain.handle('server:domain-access', async (_event, domainId = 'DOM-FIFTH-0001') => {
const stored = applyStoredServerAuth();
let accountVerified = false;
if (stored) {
try {
const { response } = await forgejoRequest(stored.nodeId, '/api/v1/user', {}, { token: stored.token });
accountVerified = response.ok;
} catch {
accountVerified = false;
}
}
// Forgejo identity is only the first proof. A signed manifest, scoped capability and
// matching online receipt must arrive from the lighthouse/domain before runtime entry.
return evaluateDomainAccess({
accountVerified,
domainId: String(domainId),
nodeId: stored?.nodeId || defaultPersonalServerId() || '',
});
});
ipcMain.handle('server:login', async (_event, input: { nodeId: string; username: string; password: string }) => {
const username = String(input.username || '').trim();
const password = String(input.password || '');

View file

@ -31,6 +31,7 @@ contextBridge.exposeInMainWorld('hololake', {
list: () => ipcRenderer.invoke('server:list'),
connect: (nodeId: string) => ipcRenderer.invoke('server:connect', nodeId),
domainRegistry: () => ipcRenderer.invoke('server:domain-registry'),
domainAccess: (domainId: string) => ipcRenderer.invoke('server:domain-access', domainId),
session: (nodeId?: string) => ipcRenderer.invoke('server:session', nodeId),
login: (input: { nodeId: string; username: string; password: string }) =>
ipcRenderer.invoke('server:login', input),