breaking
CI / test (push) Successful in 9m56s

This commit is contained in:
Raven Scott
2026-07-10 20:36:11 -04:00
parent d6ce72af66
commit 0bb6ba1692
31 changed files with 10231 additions and 3772 deletions
+138 -8
View File
@@ -1,19 +1,128 @@
/**
* peardock P2P protocol constants.
* Shared by the HyperDHT server and Pear client.
*
* PROTOCOL_VERSION is negotiated via `handshake`. Bump when breaking RPC shapes.
*/
export const PROTOCOL = 'peardock/rpc'
export const PROTOCOL_VERSION = 1
export const PROTOCOL_VERSION = 2
/** Roles for capability ACL (Phase 2 skeleton; default admin until configured). */
export const Roles = Object.freeze({
viewer: 'viewer',
operator: 'operator',
admin: 'admin',
})
/** Minimum role required per method (default admin for unknown). */
export const MethodRoles = Object.freeze({
// viewer
handshake: Roles.viewer,
ping: Roles.viewer,
listContainers: Roles.viewer,
inspectContainer: Roles.viewer,
listImages: Roles.viewer,
inspectImage: Roles.viewer,
imageHistory: Roles.viewer,
listNetworks: Roles.viewer,
inspectNetwork: Roles.viewer,
listVolumes: Roles.viewer,
inspectVolume: Roles.viewer,
listStacks: Roles.viewer,
getSystemInfo: Roles.viewer,
getSystemDf: Roles.viewer,
getDockerEvents: Roles.viewer,
startLogs: Roles.viewer,
logs: Roles.viewer,
stopLogs: Roles.viewer,
containerTop: Roles.viewer,
containerStats: Roles.viewer,
// operator
startContainer: Roles.operator,
stopContainer: Roles.operator,
restartContainer: Roles.operator,
killContainer: Roles.operator,
pauseContainer: Roles.operator,
unpauseContainer: Roles.operator,
renameContainer: Roles.operator,
updateContainer: Roles.operator,
bulkContainerOperation: Roles.operator,
startTerminal: Roles.operator,
killTerminal: Roles.operator,
terminalInput: Roles.operator,
terminalResize: Roles.operator,
execContainer: Roles.operator,
execInput: Roles.operator,
dockerCommand: Roles.operator,
dockerTerminalResize: Roles.operator,
pullImage: Roles.operator,
tagImage: Roles.operator,
connectNetwork: Roles.operator,
disconnectNetwork: Roles.operator,
deployContainer: Roles.operator,
deployStack: Roles.operator,
stackPs: Roles.operator,
stackLogs: Roles.operator,
browseDirectory: Roles.operator,
waitContainer: Roles.operator,
// admin
removeContainer: Roles.admin,
commitContainer: Roles.admin,
exportContainer: Roles.admin,
archiveContainerGet: Roles.admin,
archiveContainerPut: Roles.admin,
duplicateContainer: Roles.admin,
pruneContainers: Roles.admin,
removeImage: Roles.admin,
buildImage: Roles.admin,
pruneImages: Roles.admin,
searchImages: Roles.viewer,
createNetwork: Roles.admin,
removeNetwork: Roles.admin,
pruneNetworks: Roles.admin,
createVolume: Roles.admin,
removeVolume: Roles.admin,
pruneVolumes: Roles.admin,
removeStack: Roles.admin,
stackPull: Roles.admin,
registryLogin: Roles.admin,
getAuthStatus: Roles.viewer,
})
const ROLE_RANK = {
[Roles.viewer]: 1,
[Roles.operator]: 2,
[Roles.admin]: 3,
}
/**
* @param {string} role
* @param {string} method
* @returns {boolean}
*/
export function roleAllows(role, method) {
const need = MethodRoles[method] || Roles.admin
const have = ROLE_RANK[role] || 0
const required = ROLE_RANK[need] || 99
return have >= required
}
/** Request/response RPC methods (client → server). */
export const Methods = Object.freeze({
// Session
handshake: 'handshake',
ping: 'ping',
// Containers
listContainers: 'listContainers',
inspectContainer: 'inspectContainer',
startContainer: 'startContainer',
stopContainer: 'stopContainer',
restartContainer: 'restartContainer',
killContainer: 'killContainer',
pauseContainer: 'pauseContainer',
unpauseContainer: 'unpauseContainer',
removeContainer: 'removeContainer',
@@ -25,6 +134,12 @@ export const Methods = Object.freeze({
deployContainer: 'deployContainer',
updateContainer: 'updateContainer',
bulkContainerOperation: 'bulkContainerOperation',
containerTop: 'containerTop',
containerStats: 'containerStats',
waitContainer: 'waitContainer',
archiveContainerGet: 'archiveContainerGet',
archiveContainerPut: 'archiveContainerPut',
pruneContainers: 'pruneContainers',
// Images
listImages: 'listImages',
@@ -33,6 +148,9 @@ export const Methods = Object.freeze({
inspectImage: 'inspectImage',
buildImage: 'buildImage',
tagImage: 'tagImage',
imageHistory: 'imageHistory',
pruneImages: 'pruneImages',
searchImages: 'searchImages',
// Networks
listNetworks: 'listNetworks',
@@ -41,25 +159,33 @@ export const Methods = Object.freeze({
inspectNetwork: 'inspectNetwork',
connectNetwork: 'connectNetwork',
disconnectNetwork: 'disconnectNetwork',
pruneNetworks: 'pruneNetworks',
// Volumes
listVolumes: 'listVolumes',
createVolume: 'createVolume',
removeVolume: 'removeVolume',
inspectVolume: 'inspectVolume',
pruneVolumes: 'pruneVolumes',
// Stacks / compose
deployStack: 'deployStack',
listStacks: 'listStacks',
removeStack: 'removeStack',
stackPs: 'stackPs',
stackLogs: 'stackLogs',
stackPull: 'stackPull',
// System / host
getSystemInfo: 'getSystemInfo',
getSystemDf: 'getSystemDf',
getDockerEvents: 'getDockerEvents',
browseDirectory: 'browseDirectory',
dockerCommand: 'dockerCommand',
registryLogin: 'registryLogin',
getAuthStatus: 'getAuthStatus',
// Terminal / streams (control plane)
// Terminal / streams
startTerminal: 'startTerminal',
killTerminal: 'killTerminal',
terminalInput: 'terminalInput',
@@ -68,18 +194,15 @@ export const Methods = Object.freeze({
stopLogs: 'stopLogs',
execInput: 'execInput',
dockerTerminalResize: 'dockerTerminalResize',
// Health
ping: 'ping',
})
/**
* Server → client push channels (registered as respond handlers on the client,
* fired with rpc.event on the server).
* Server → client push channels.
*/
export const Pushes = Object.freeze({
containers: 'push:containers',
volumes: 'push:volumes',
images: 'push:images',
allStats: 'push:allStats',
logs: 'push:logs',
terminalOutput: 'push:terminalOutput',
@@ -87,13 +210,17 @@ export const Pushes = Object.freeze({
execOutput: 'push:execOutput',
execErrorOutput: 'push:execErrorOutput',
dockerOutput: 'push:dockerOutput',
pullProgress: 'push:pullProgress',
buildProgress: 'push:buildProgress',
dockerEvent: 'push:dockerEvent',
error: 'push:error',
})
/** Map legacy response `type` field → push channel (for UI handlers). */
/** Map push channel → legacy UI type field. */
export const PushToType = Object.freeze({
[Pushes.containers]: 'containers',
[Pushes.volumes]: 'volumes',
[Pushes.images]: 'images',
[Pushes.allStats]: 'allStats',
[Pushes.logs]: 'logs',
[Pushes.terminalOutput]: 'terminalOutput',
@@ -101,5 +228,8 @@ export const PushToType = Object.freeze({
[Pushes.execOutput]: 'execOutput',
[Pushes.execErrorOutput]: 'execErrorOutput',
[Pushes.dockerOutput]: 'dockerOutput',
[Pushes.pullProgress]: 'pullProgress',
[Pushes.buildProgress]: 'buildProgress',
[Pushes.dockerEvent]: 'dockerEvent',
[Pushes.error]: 'error',
})