# Protocol Wire contract for PearData P2P RPC. Source of truth: `shared/protocol.js`, `shared/schema.js`, `shared/metrics.js`. ## Identity | Constant | Value | |----------|-------| | Protocol id | `peardata/rpc` | | Protocol version | `1` | | Invite prefix | `pd1.` | | Default role | `viewer` | Bump `PROTOCOL_VERSION` on breaking argument/result shapes. ## Roles | Role | Rank | Typical access | |------|------|----------------| | `viewer` | 1 | Read metrics, subscribe, list alerts | | `operator` | 2 | Ack/silence alerts, run jobs, set alert config | | `admin` | 3 | Mint invites, revoke peers, export snapshot | Auth modes at handshake: public key (viewer), capability token / `pd1.` invite, admin seed proof, allowlist. ## Methods ### Session | Method | Role | Notes | |--------|------|-------| | `handshake` | viewer | Negotiate version + elevate role | | `ping` | viewer | Hot | | `getServerInfo` | viewer | Agent metadata | | `getAuthStatus` | viewer | Peer role / auth mode | | `setDisplayName` | viewer | Label for audit / UI | ### Node | Method | Role | Result | |--------|------|--------| | `getNodeInfo` | viewer | Hostname, CPUs, charts, sample interval | | `getHealth` | viewer | `{ status, score, checks }` | ### Metrics discovery & query | Method | Role | Args | Result | |--------|------|------|--------| | `listContexts` | viewer | — | Context catalog | | `getContext` | viewer | `{ id }` | Charts in context | | `listCharts` | viewer | — | agent-style chart map | | `getChart` | viewer | `{ id }` | Chart summary | | `queryData` | viewer | `{ chart, after, before, points, group, tier }` | Time series | | `getWeights` | viewer | see below | Metric Correlations / alert weights | | `queryLogs` | viewer* | see below | Anomaly / audit / journal lines | | `listProcesses` | viewer | sort / filter / q / limit | Live Linux `/proc` process table | | `getAllMetrics` | viewer | `{ format: json\|prometheus\|shell }` | Latest export | \* `queryLogs` method role is viewer so anomaly search works for all dialers; **audit** and **journal** sources require **admin** inside the handler. `after` / `before`: absolute unix seconds, or relative (negative = relative to `before`/`now`), agent-style. #### `getWeights` Scores charts for [Metric Correlations](../user-guide/metric-correlations.md) (or legacy alert weights when no highlight window). | Arg | Notes | |-----|--------| | `method` | `volume` \| `ks2` \| `anomaly-rate` \| `value` \| `alerts` | | `after` / `before` | Highlight window | | `baseline_after` / `baseline_before` | Optional baseline (default 4× preceding highlight) | | `points`, `time_group`, `contexts`, `charts`, `dimensions`, `limit`, `timeout` | Same as REST | REST parity: `GET /api/v*/weights`. Engine: `server/services/weights.js`. #### `queryLogs` | Arg | Notes | |-----|--------| | `source` | `journal` (default) \| `anomaly` \| `audit` — desktop prefers journal for admins | | `q` | Case-insensitive substring | | `since` / `until` | Absolute ms/sec or relative (`-1h`) | | `priority` / `unit` | Journal filters | | `limit` / `cursor` | Cap (≤2000) + pagination offset | Journal is **enabled by default** on Linux (`PEARDATA_JOURNAL=0` to disable). Installer grants `systemd-journal` to the agent user. REST: `GET /api/v*/logs`. Engine: `server/services/logs.js`. UI: [user-guide/logs.md](../user-guide/logs.md). #### `listProcesses` | Arg | Notes | |-----|--------| | `sort` | `cpu` (default) \| `rss` \| `pid` \| `name` \| `io` \| `threads` \| `age` \| `fds` \| `state` | | `order` | `desc` (default) \| `asc` | | `filter` | `all` \| `running` \| `sleeping` \| `zombie` \| `stopped` \| `highcpu` \| `highmem` \| `hasio` \| `kernel` \| `user` | | `q` | Substring over pid / name / cmdline / user / cgroup | | `limit` / `offset` | Cap ≤2000 | | `pid` | Optional — return one process with detail fields (fds, exe, cwd, …) | Linux `/proc` only. Rates need two samples (~450ms cache). REST: `GET /api/v*/processes`. UI: [user-guide/processes.md](../user-guide/processes.md). ### Live subscriptions | Method | Role | Args | |--------|------|------| | `subscribeMetrics` | viewer | `{ charts: string[]\|['*'], intervalMs }` | | `unsubscribeMetrics` | viewer | — | | `subscribeAnomalies` | viewer | — | | `unsubscribeAnomalies` | viewer | — | ### Anomalies & alerts | Method | Role | Notes | |--------|------|-------| | `listAnomalies` | viewer | Recent events | | `listAlerts` / `getAlert` | viewer | State + config | | `setAlertConfig` | operator | Upsert threshold | | `ackAlert` | operator | Clear until next breach | | `silenceAlert` | operator | Disable temporarily | ### AI / QVAC tool composites Lean read-only helpers for the desktop QVAC tab (and scripts). See [QVAC.md](./QVAC.md). | Method | Role | Args | Notes | |--------|------|------|-------| | `getHostSnapshot` | viewer | — | Health, KPIs, recent anomalies/alerts, catalog + storage summary | | `searchCharts` | viewer | `{ q?, limit? }` | Catalog free-text search (`limit` 1–100) | | `summarizeChart` | viewer | `{ chart, after?, points?, group? }` | min/avg/max/last per dim for a window | REST mirrors: `GET /api/v3/ai/snapshot`, `/api/v3/ai/charts`, `/api/v3/ai/chart/:id/summary`. ### Jobs | Method | Role | Known jobs | |--------|------|------------| | `listJobs` | viewer | — | | `runJob` | operator | `collectOnce`, `snapshot`, `gcBuffers` (prune) | | `cancelJob` | operator | By job id | ### Data Manager (retention / storage) | Method | Role | Notes | |--------|------|-------| | `getStorageInfo` | viewer | Disk usage, memory rings, warm sample stats, effective retention | | `getRetentionConfig` | viewer | Current policy (`retention.json`; default warm age **3 months**, **1 GiB** disk budget) | | `setRetentionConfig` | admin | Update hot/warm rings, age rotate, disk budget, auto-prune | | `pruneHistory` | admin | `{ dryRun?, beforeMs?, gc? }` — delete warm points + physical reclaim (`clearUnlinked` + `compact`). Returns `bytesBefore` / `bytesAfter` / `bytesFreed`. | UI: [user-guide/settings.md](../user-guide/settings.md) → **Data**. Job alias: `runJob({ name: 'gcBuffers' })` runs the same prune path. ### HyperDB / peer links | Method | Role | Notes | |--------|------|-------| | `getDbInfo` | viewer | DB + discovery keys, swarm flag, remotes | | `listPeerLinks` | viewer | Linked peers from HyperDB | | `linkPeer` | admin | Upsert link; open remote bee + optional swarm join | | `unlinkPeer` | admin | Remove link | | `getFleetHealth` | viewer | Parent rollup (when `PEARDATA_PARENT=1`) | | `listChildPeers` | viewer | Dialed child agents | See [STORAGE-HYPERDB.md](./STORAGE-HYPERDB.md). ### Admin | Method | Role | |--------|------| | `mintInvite` | admin | | `listPeers` | admin | | `revokePeer` | admin | | `exportSnapshot` | admin | ## Pushes (server → client) | Event | Payload | |-------|---------| | `push:metrics` | `{ samples: MetricSample[] }` | | `push:anomaly` | `AnomalyEvent` | | `push:alert` | Alert transition | | `push:health` | `HealthSnapshot` | | `push:job` | `JobRecord` | | `push:system` | Generic notices | ## Errors Handlers throw `Error` with `.code`: | Code | Meaning | |------|---------| | `PERMISSION_DENIED` | Role too low | | `RATE_LIMIT_EXCEEDED` | RPM exceeded | | `INVALID_ARGS` | Schema failure | | `NOT_CONNECTED` | Client-side | | `CAPABILITY_*` | Invite/token issues | ## Versioning policy 1. Additive methods/fields: no version bump if old clients ignore unknowns. 2. Rename/remove/change meaning: bump `PROTOCOL_VERSION`; reject or compat-negotiate in handshake. 3. REST API versions (`v1`/`v2`/`v3`) are independent of RPC version but share the store. ## Example session ```text client → handshake { clientName, clientVersion, capability? } server → { role, protocolVersion, auth } client → subscribeMetrics { charts: ['*'], intervalMs: 1000 } server → push:metrics { samples: [...] } # ~1 Hz client → queryData { chart: 'system.cpu', after: -300, points: 300 } ```