mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
feat: add namespace-based multi-user isolation
Implement namespace support across sessions, machines, and users for multi-user server deployments. Add access control with specific error reasons (namespace-missing, access-denied, not-found) and database schema updates with namespace columns and indexes.
This commit is contained in:
@@ -192,6 +192,13 @@ export class ApiMachineClient {
|
||||
this.machine.metadataVersion = obj.version
|
||||
throw new Error('Metadata version mismatch')
|
||||
}
|
||||
|
||||
if (obj.result === 'error') {
|
||||
const reason = typeof (obj as { reason?: unknown }).reason === 'string'
|
||||
? (obj as { reason?: string }).reason
|
||||
: 'unknown'
|
||||
throw new Error(`Machine metadata update failed (${reason})`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -241,6 +248,13 @@ export class ApiMachineClient {
|
||||
this.machine.daemonStateVersion = obj.version
|
||||
throw new Error('Daemon state version mismatch')
|
||||
}
|
||||
|
||||
if (obj.result === 'error') {
|
||||
const reason = typeof (obj as { reason?: unknown }).reason === 'string'
|
||||
? (obj as { reason?: string }).reason
|
||||
: 'unknown'
|
||||
throw new Error(`Machine state update failed (${reason})`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -322,6 +336,10 @@ export class ApiMachineClient {
|
||||
this.socket.on('connect_error', (error) => {
|
||||
logger.debug(`[API MACHINE] Connection error: ${error.message}`)
|
||||
})
|
||||
|
||||
this.socket.on('error', (payload) => {
|
||||
logger.debug('[API MACHINE] Socket error:', payload)
|
||||
})
|
||||
}
|
||||
|
||||
private startKeepAlive(): void {
|
||||
|
||||
@@ -121,6 +121,10 @@ export class ApiSessionClient extends EventEmitter {
|
||||
this.rpcHandlerManager.onSocketDisconnect()
|
||||
})
|
||||
|
||||
this.socket.on('error', (payload) => {
|
||||
logger.debug('[API] Socket error:', payload)
|
||||
})
|
||||
|
||||
const handleTerminalEvent = <T extends { sessionId: string }>(
|
||||
schema: ZodType<T>,
|
||||
handler: (payload: T) => void
|
||||
@@ -491,6 +495,13 @@ export class ApiSessionClient extends EventEmitter {
|
||||
this.metadataVersion = obj.version
|
||||
throw new Error('Metadata version mismatch')
|
||||
}
|
||||
|
||||
if (obj.result === 'error') {
|
||||
const reason = typeof (obj as { reason?: unknown }).reason === 'string'
|
||||
? (obj as { reason?: string }).reason
|
||||
: 'unknown'
|
||||
throw new Error(`Metadata update failed (${reason})`)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -543,6 +554,13 @@ export class ApiSessionClient extends EventEmitter {
|
||||
this.agentStateVersion = obj.version
|
||||
throw new Error('Agent state version mismatch')
|
||||
}
|
||||
|
||||
if (obj.result === 'error') {
|
||||
const reason = typeof (obj as { reason?: unknown }).reason === 'string'
|
||||
? (obj as { reason?: string }).reason
|
||||
: 'unknown'
|
||||
throw new Error(`Agent state update failed (${reason})`)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -325,6 +325,8 @@ export const MessageContentSchema = z.union([UserMessageSchema, AgentMessageSche
|
||||
|
||||
export type MessageContent = z.infer<typeof MessageContentSchema>
|
||||
|
||||
export type SocketErrorReason = 'namespace-missing' | 'access-denied' | 'not-found'
|
||||
|
||||
export interface ServerToClientEvents {
|
||||
update: (data: Update) => void
|
||||
'rpc-request': (data: { method: string; params: string }, callback: (response: string) => void) => void
|
||||
@@ -332,7 +334,7 @@ export interface ServerToClientEvents {
|
||||
'terminal:write': (data: TerminalWritePayload) => void
|
||||
'terminal:resize': (data: TerminalResizePayload) => void
|
||||
'terminal:close': (data: TerminalClosePayload) => void
|
||||
error: (data: { message: string }) => void
|
||||
error: (data: { message: string; code?: SocketErrorReason; scope?: 'session' | 'machine'; id?: string }) => void
|
||||
}
|
||||
|
||||
export interface ClientToServerEvents {
|
||||
@@ -348,6 +350,7 @@ export interface ClientToServerEvents {
|
||||
'session-end': (data: { sid: string; time: number }) => void
|
||||
'update-metadata': (data: { sid: string; expectedVersion: number; metadata: unknown }, cb: (answer: {
|
||||
result: 'error'
|
||||
reason?: SocketErrorReason
|
||||
} | {
|
||||
result: 'version-mismatch'
|
||||
version: number
|
||||
@@ -359,6 +362,7 @@ export interface ClientToServerEvents {
|
||||
}) => void) => void
|
||||
'update-state': (data: { sid: string; expectedVersion: number; agentState: unknown | null }, cb: (answer: {
|
||||
result: 'error'
|
||||
reason?: SocketErrorReason
|
||||
} | {
|
||||
result: 'version-mismatch'
|
||||
version: number
|
||||
@@ -371,6 +375,7 @@ export interface ClientToServerEvents {
|
||||
'machine-alive': (data: { machineId: string; time: number }) => void
|
||||
'machine-update-metadata': (data: { machineId: string; expectedVersion: number; metadata: unknown }, cb: (answer: {
|
||||
result: 'error'
|
||||
reason?: SocketErrorReason
|
||||
} | {
|
||||
result: 'version-mismatch'
|
||||
version: number
|
||||
@@ -382,6 +387,7 @@ export interface ClientToServerEvents {
|
||||
}) => void) => void
|
||||
'machine-update-state': (data: { machineId: string; expectedVersion: number; daemonState: unknown | null }, cb: (answer: {
|
||||
result: 'error'
|
||||
reason?: SocketErrorReason
|
||||
} | {
|
||||
result: 'version-mismatch'
|
||||
version: number
|
||||
|
||||
Reference in New Issue
Block a user