Files
peardata/shared/protocol.js
T
Raven Scott 4b5b78892f
CI / test (push) Successful in 2m45s
Release rolling / release (push) Successful in 11m36s
FIX: QVAC Updates
2026-07-30 15:23:43 -04:00

174 lines
4.3 KiB
JavaScript

/**
* PearData P2P protocol — control plane + metric streaming.
*
* PROTOCOL_VERSION is negotiated via `handshake`. Bump on breaking RPC shapes.
* Additive methods may land without a bump when clients tolerate unknown methods.
*
* Planes:
* - Control/metadata: handshake, info, ACL, invites, jobs, alerts config
* - Metrics query: contexts, charts, historical data (hot path)
* - Push streams: live samples, anomalies, health events
*/
export const PROTOCOL = 'peardata/rpc'
export const PROTOCOL_VERSION = 1
export const APP_NAME = 'peardata'
export const APP_VERSION = '0.1.0'
/** Roles for capability ACL. Secure default peer role is viewer. */
export const Roles = Object.freeze({
viewer: 'viewer',
operator: 'operator',
admin: 'admin',
})
const ROLE_RANK = {
[Roles.viewer]: 1,
[Roles.operator]: 2,
[Roles.admin]: 3,
}
/**
* @param {string} role
* @param {string} required
*/
export function roleAllows(role, required) {
const have = ROLE_RANK[role] || 0
const need = ROLE_RANK[required] || ROLE_RANK[Roles.admin]
return have >= need
}
/**
* Minimum role required per method (default admin for unknown).
*/
export const MethodRoles = Object.freeze({
// session
handshake: Roles.viewer,
ping: Roles.viewer,
getServerInfo: Roles.viewer,
getAuthStatus: Roles.viewer,
setDisplayName: Roles.viewer,
// agent / node metadata
getNodeInfo: Roles.viewer,
getHealth: Roles.viewer,
// metrics discovery + query
listContexts: Roles.viewer,
getContext: Roles.viewer,
listCharts: Roles.viewer,
getChart: Roles.viewer,
queryData: Roles.viewer,
getAllMetrics: Roles.viewer,
getWeights: Roles.viewer,
// AI / QVAC tool-friendly composites (viewer read)
getHostSnapshot: Roles.viewer,
searchCharts: Roles.viewer,
summarizeChart: Roles.viewer,
investigateHost: Roles.viewer,
hotMetrics: Roles.viewer,
relatedCharts: Roles.viewer,
compareChartWindows: Roles.viewer,
summarizeCharts: Roles.viewer,
// live subscription control
subscribeMetrics: Roles.viewer,
unsubscribeMetrics: Roles.viewer,
subscribeAnomalies: Roles.viewer,
unsubscribeAnomalies: Roles.viewer,
// anomalies + alerts (read)
listAnomalies: Roles.viewer,
listAlerts: Roles.viewer,
getAlert: Roles.viewer,
/** Anomaly source: viewer; audit/journal enforced admin inside handler */
queryLogs: Roles.viewer,
/** Live process table (Linux /proc) */
listProcesses: Roles.viewer,
// alerts / thresholds (write)
setAlertConfig: Roles.operator,
ackAlert: Roles.operator,
silenceAlert: Roles.operator,
// jobs (on-demand collection / maintenance)
listJobs: Roles.viewer,
runJob: Roles.operator,
cancelJob: Roles.operator,
// HyperDB peer links / db info
getDbInfo: Roles.viewer,
listPeerLinks: Roles.viewer,
linkPeer: Roles.admin,
unlinkPeer: Roles.admin,
// Data Manager — retention + storage
getStorageInfo: Roles.viewer,
getRetentionConfig: Roles.viewer,
setRetentionConfig: Roles.admin,
pruneHistory: Roles.admin,
// parent / fleet aggregation
getFleetHealth: Roles.viewer,
listChildPeers: Roles.viewer,
// admin / fleet
mintInvite: Roles.admin,
listPeers: Roles.admin,
revokePeer: Roles.admin,
exportSnapshot: Roles.admin,
})
/**
* String method names for typed client calls.
*/
export const Methods = Object.freeze(
Object.fromEntries(Object.keys(MethodRoles).map((k) => [k, k]))
)
/**
* Server → client push event names (protomux-rpc events).
*/
export const Pushes = Object.freeze({
metrics: 'push:metrics',
anomaly: 'push:anomaly',
alert: 'push:alert',
health: 'push:health',
job: 'push:job',
system: 'push:system',
})
/**
* Map push channel → UI event type.
*/
export const PushToType = Object.freeze({
[Pushes.metrics]: 'metrics',
[Pushes.anomaly]: 'anomaly',
[Pushes.alert]: 'alert',
[Pushes.health]: 'health',
[Pushes.job]: 'job',
[Pushes.system]: 'system',
})
/** Methods treated as hot-path (skip heavy audit / schema). */
export const HotMethods = Object.freeze(
new Set([
Methods.ping,
Methods.queryData,
Methods.subscribeMetrics,
Methods.unsubscribeMetrics,
Methods.getAllMetrics,
Methods.listProcesses,
Methods.getHostSnapshot,
Methods.searchCharts,
Methods.summarizeChart,
Methods.investigateHost,
Methods.hotMetrics,
Methods.relatedCharts,
Methods.compareChartWindows,
Methods.summarizeCharts,
])
)