forked from snxraven/p2ns
Update docs
This commit is contained in:
@@ -144,8 +144,8 @@ Access `https://p2ns.admin` for real-time management:
|
|||||||
| **Interfaces** | Domain-to-IP mappings |
|
| **Interfaces** | Domain-to-IP mappings |
|
||||||
| **Backups** | Create/restore backups |
|
| **Backups** | Create/restore backups |
|
||||||
| **Diagnostics** | DNS lookup, ping, traceroute, connection tests |
|
| **Diagnostics** | DNS lookup, ping, traceroute, connection tests |
|
||||||
| **Stats** | Real-time metrics, health status |
|
| **Stats** | Live metrics (`subscribe-stats`), Core RPC invite diagnostics, Plugin RPC protocol stats |
|
||||||
| **Logs** | Live system logs |
|
| **Logs** | Tail split log files (core, proxy, HTTP proxy, DNS, plugins, Holesail) with filter |
|
||||||
| **Settings** | Environment config, subnet management |
|
| **Settings** | Environment config, subnet management |
|
||||||
| **Plugins** | Start/stop plugins, view logs, configure settings |
|
| **Plugins** | Start/stop plugins, view logs, configure settings |
|
||||||
|
|
||||||
@@ -207,6 +207,8 @@ Configure via `.env` (copy from `default.env`):
|
|||||||
| `STORAGE_DIR` | `./my-storage` | Corestore data directory |
|
| `STORAGE_DIR` | `./my-storage` | Corestore data directory |
|
||||||
| `CERTS_DIR` | `./certs` | Certificate storage |
|
| `CERTS_DIR` | `./certs` | Certificate storage |
|
||||||
| `LOG_LEVEL` | `0` | 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR |
|
| `LOG_LEVEL` | `0` | 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR |
|
||||||
|
| `LOG_DIR` | `./logs` | Split log files (core, proxy, http-proxy, dns, plugins, holesail) |
|
||||||
|
| `LOG_BUFFER_LINES` | `2000` | In-memory tail size per log channel (admin Logs tab) |
|
||||||
| `TOPIC_SEED` | `p2ns-dns` | Hyperswarm topic seed |
|
| `TOPIC_SEED` | `p2ns-dns` | Hyperswarm topic seed |
|
||||||
|
|
||||||
### File Paths
|
### File Paths
|
||||||
@@ -308,7 +310,7 @@ Example multi-subnet config:
|
|||||||
- **[REST API](docs/RESTAPI.md)** - Complete API documentation
|
- **[REST API](docs/RESTAPI.md)** - Complete API documentation
|
||||||
- **[Consensus](docs/CONSENSUS.md)** - Domain voting and resolution
|
- **[Consensus](docs/CONSENSUS.md)** - Domain voting and resolution
|
||||||
- **[HyperDB](docs/plugins/HYPERDB.md)** - Database operations
|
- **[HyperDB](docs/plugins/HYPERDB.md)** - Database operations
|
||||||
- **[Plugin Channels](docs/plugins/PLUGIN_CHANNELS.md)** - P2P communication
|
- **[Plugin RPC](docs/plugins/PLUGIN_CHANNELS.md)** - protomux-rpc peer protocols
|
||||||
- **[Hyperdrive](docs/plugins/HYPERDRIVE.md)** - Distributed file system
|
- **[Hyperdrive](docs/plugins/HYPERDRIVE.md)** - Distributed file system
|
||||||
- **[Proxy Server](proxy-server/README.md)** - Standalone proxy configuration
|
- **[Proxy Server](proxy-server/README.md)** - Standalone proxy configuration
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,12 @@ ENABLE_HYPERCORE_STATS=true
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Logging
|
# Logging
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
# 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR
|
||||||
LOG_LEVEL=1
|
LOG_LEVEL=1
|
||||||
|
# Split log files directory (core.log, proxy.log, http-proxy.log, dns.log, plugins.log, holesail.log)
|
||||||
|
# LOG_DIR=./logs
|
||||||
|
# In-memory tail lines per channel for admin /api/logs and WebSocket tail
|
||||||
|
# LOG_BUFFER_LINES=2000
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Backup Configuration
|
# Backup Configuration
|
||||||
|
|||||||
+12
-13
@@ -46,21 +46,19 @@ Supports two removal modes:
|
|||||||
|
|
||||||
## Infrastructure Modules
|
## Infrastructure Modules
|
||||||
|
|
||||||
### `infrastructure/logger.js`
|
### `infrastructure/logger.js` + `infrastructure/log-files.js`
|
||||||
Leveled logging system with prefixes:
|
Leveled logging with component prefixes, routed to split files under `logs/` via `log-files.js`:
|
||||||
- `logDebug(prefix, message)` - DEBUG level (0)
|
- `logDebug` / `logInfo` / `logWarn` / `logError`
|
||||||
- `logInfo(prefix, message)` - INFO level (1)
|
- **core** → console + `core.log`; **Internal Proxy**, **HTTP Proxy**, **DNS**, **Plugins**, **Holesail** → dedicated files (no console)
|
||||||
- `logWarn(prefix, message)` - WARN level (2)
|
|
||||||
- `logError(prefix, message)` - ERROR level (3)
|
|
||||||
|
|
||||||
Logs are broadcast to WebSocket clients for real-time admin interface updates.
|
Admin log tail uses `log-websocket.js` (`subscribe-log`, `file-log`, `log-snapshot`). Plugin logs use separate `plugin-log` WebSocket messages and `app.log` per plugin.
|
||||||
|
|
||||||
### `infrastructure/state.js`
|
### `infrastructure/state.js`
|
||||||
Global state management including:
|
Global state management including:
|
||||||
- Domain-to-IP mappings
|
- Domain-to-IP mappings
|
||||||
- Holesail connections
|
- Holesail connections
|
||||||
- TLS/HTTP servers
|
- TLS/HTTP servers
|
||||||
- Peer channels and metrics
|
- Swarm peer channels (`peerChannels`), plugin RPC state (`pluginChannels`), and metrics
|
||||||
- Version preferences
|
- Version preferences
|
||||||
- DNS pass instance
|
- DNS pass instance
|
||||||
|
|
||||||
@@ -313,10 +311,10 @@ Hyperdrive file system management:
|
|||||||
- Replication
|
- Replication
|
||||||
|
|
||||||
### `plugins/channel-manager.js`
|
### `plugins/channel-manager.js`
|
||||||
Protomux channel management:
|
Plugin protomux-rpc management:
|
||||||
- Channel creation
|
- `registerPluginProtocol` — per-plugin RPC muxes and method handlers
|
||||||
- Message routing
|
- Request/event routing via `channel-rpc.js` and `plugin-rpc-contract.js`
|
||||||
- Peer tracking
|
- Peer RPC session tracking in `state.pluginChannels`
|
||||||
|
|
||||||
### `plugins/replication-manager.js`
|
### `plugins/replication-manager.js`
|
||||||
Database replication over Hyperswarm:
|
Database replication over Hyperswarm:
|
||||||
@@ -439,7 +437,8 @@ module.exports = {
|
|||||||
httpServers: new Map(), // domain -> HTTP server
|
httpServers: new Map(), // domain -> HTTP server
|
||||||
|
|
||||||
// Peer management
|
// Peer management
|
||||||
peerChannels: new Map(), // peerId -> channel
|
peerChannels: new Map(), // peerId -> { conn, mux } (swarm); plugin RPC state is in pluginChannels
|
||||||
|
pluginChannels: new Map(), // pluginDomain -> protocol -> { peerChannels: Map(peerId -> { rpc, ... }) }
|
||||||
peerMetrics: new Map(), // peerId -> metrics
|
peerMetrics: new Map(), // peerId -> metrics
|
||||||
peerHistory: new Map(), // peerId -> history
|
peerHistory: new Map(), // peerId -> history
|
||||||
blockedPeers: new Set(), // blocked peer IDs
|
blockedPeers: new Set(), // blocked peer IDs
|
||||||
|
|||||||
+26
-10
@@ -513,19 +513,35 @@ curl -k "https://p2ns.admin/api/stats/historical?minutes=1440"
|
|||||||
### JavaScript Stats Monitoring
|
### JavaScript Stats Monitoring
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
async function getStats() {
|
// One-shot HTTP load (admin UI uses this once on tab open)
|
||||||
|
async function getStatsOnce() {
|
||||||
const response = await fetch('https://p2ns.admin/api/stats');
|
const response = await fetch('https://p2ns.admin/api/stats');
|
||||||
const stats = await response.json();
|
return response.json();
|
||||||
|
|
||||||
console.log('Total requests:', stats.requests?.total);
|
|
||||||
console.log('Success rate:', stats.requests?.successRate);
|
|
||||||
console.log('Holesail connections:', stats.holesailChildren?.length);
|
|
||||||
|
|
||||||
return stats;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get stats every 10 seconds
|
// Live updates via WebSocket (preferred)
|
||||||
setInterval(getStats, 10000);
|
const ws = new WebSocket('wss://p2ns.admin/ws');
|
||||||
|
ws.onopen = () => ws.send(JSON.stringify({ type: 'subscribe-stats' }));
|
||||||
|
ws.onmessage = (ev) => {
|
||||||
|
const msg = JSON.parse(ev.data);
|
||||||
|
if (msg.type === 'stats-snapshot') {
|
||||||
|
console.log('Core RPC:', msg.stats?.core?.summary);
|
||||||
|
console.log('Plugin RPC protocols:', msg.stats?.pluginRpc?.totalProtocols);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tail logs over WebSocket
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const ws = new WebSocket('wss://p2ns.admin/ws');
|
||||||
|
ws.onopen = () => {
|
||||||
|
ws.send(JSON.stringify({ type: 'subscribe-log', channel: 'dns', lines: 500 }));
|
||||||
|
};
|
||||||
|
ws.onmessage = (ev) => {
|
||||||
|
const msg = JSON.parse(ev.data);
|
||||||
|
if (msg.type === 'file-log' && msg.channel === 'dns') console.log(msg.message);
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## Consensus Examples
|
## Consensus Examples
|
||||||
|
|||||||
+8
-2
@@ -79,6 +79,12 @@ A distributed ledger built on Hyperbee used for storing domain claims and votes.
|
|||||||
### Corestore
|
### Corestore
|
||||||
Storage management for multiple Hypercores. Handles persistence, caching, and lifecycle of cores. P2NS uses Corestore to manage storage for Autopass, HyperDB, and Hyperdrive instances.
|
Storage management for multiple Hypercores. Handles persistence, caching, and lifecycle of cores. P2NS uses Corestore to manage storage for Autopass, HyperDB, and Hyperdrive instances.
|
||||||
|
|
||||||
|
### Plugin RPC
|
||||||
|
The only peer-to-peer transport for plugin protocols. Each plugin registers named JSON methods on `{pluginDomain}-{protocol}-rpc`. Distinct from legacy protomux message channels (removed). See [plugins/PLUGIN_CHANNELS.md](plugins/PLUGIN_CHANNELS.md).
|
||||||
|
|
||||||
|
### Core request RPC
|
||||||
|
Control-plane RPC on `p2ns.core-request-rpc` for invites (`invite.request`, `invite.deliver`, `invite.ack`, …) and consensus events. Joiner lifecycle uses `registerPluginProtocol` for the `request` protocol (RPC open triggers invite flow).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Holesail
|
## Holesail
|
||||||
@@ -129,8 +135,8 @@ A self-contained module that extends P2NS functionality. Plugins are stored in `
|
|||||||
### Plugin SDK
|
### Plugin SDK
|
||||||
The API provided to plugins for accessing P2NS functionality. Includes modules for state access, DNS operations, domain management, Holesail control, peer management, and more. See [plugins/PLUGIN_SDK.md](plugins/PLUGIN_SDK.md).
|
The API provided to plugins for accessing P2NS functionality. Includes modules for state access, DNS operations, domain management, Holesail control, peer management, and more. See [plugins/PLUGIN_SDK.md](plugins/PLUGIN_SDK.md).
|
||||||
|
|
||||||
### Protomux Channels
|
### Split logging
|
||||||
P2P communication channels for plugins using the Protomux protocol. Enables plugins to send messages directly between peers without going through HTTP. See [plugins/PLUGIN_CHANNELS.md](plugins/PLUGIN_CHANNELS.md).
|
Core and subsystem logs are written to separate files under `LOG_DIR` (default `./logs/`): `core.log`, `proxy.log`, `http-proxy.log`, `dns.log`, `plugins.log`, `holesail.log`. The admin **Logs** tab tails these via `subscribe-log` / `file-log`. Plugin `sdk.log` output goes to `plugins.log` and per-plugin `app.log`.
|
||||||
|
|
||||||
### Admin Panel Actions
|
### Admin Panel Actions
|
||||||
Custom operations that plugins can register to appear in the admin interface. Actions are async functions that can be triggered from the Plugins tab. Registered via `sdk.admin.registerAction()`.
|
Custom operations that plugins can register to appear in the admin interface. Actions are async functions that can be triggered from the Plugins tab. Registered via `sdk.admin.registerAction()`.
|
||||||
|
|||||||
+39
-21
@@ -76,7 +76,7 @@ P2NS provides a comprehensive set of features for decentralized networking:
|
|||||||
- **Circuit Breaker Pattern**: Automatic failure detection and recovery with exponential backoff retry logic.
|
- **Circuit Breaker Pattern**: Automatic failure detection and recovery with exponential backoff retry logic.
|
||||||
- **Rate Limiting**: Built-in rate limiting for API endpoints to prevent abuse and ensure system stability.
|
- **Rate Limiting**: Built-in rate limiting for API endpoints to prevent abuse and ensure system stability.
|
||||||
- **Enhanced Error Handling**: Comprehensive error handling with retry logic, graceful degradation, and detailed error reporting.
|
- **Enhanced Error Handling**: Comprehensive error handling with retry logic, graceful degradation, and detailed error reporting.
|
||||||
- **Logging**: Leveled logging (DEBUG, INFO, WARN, ERROR) with prefixes for debugging.
|
- **Logging**: Split log files under `logs/` (core, proxy, HTTP proxy, DNS, plugins, Holesail) with live tail in the admin **Logs** tab.
|
||||||
- **Graceful Shutdown**: Cleans up connections, channels, virtual interfaces, and child processes on exit.
|
- **Graceful Shutdown**: Cleans up connections, channels, virtual interfaces, and child processes on exit.
|
||||||
|
|
||||||
## Architecture Overview
|
## Architecture Overview
|
||||||
@@ -86,7 +86,7 @@ P2NS is a modular Node.js application with the following components:
|
|||||||
- **Core Components**:
|
- **Core Components**:
|
||||||
- **Corestore & Autopass** (`core.js`): Manages decentralized storage and secure writer additions. Stores claims (`claim:domain:claimant`) and votes (`vote:domain:claimant:voter`).
|
- **Corestore & Autopass** (`core.js`): Manages decentralized storage and secure writer additions. Stores claims (`claim:domain:claimant`) and votes (`vote:domain:claimant:voter`).
|
||||||
- **Hyperswarm** (`swarm.js`): Handles peer discovery using a fixed topic (`sha256('p2ns-dns')`).
|
- **Hyperswarm** (`swarm.js`): Handles peer discovery using a fixed topic (`sha256('p2ns-dns')`).
|
||||||
- **Protomux** (`p2ns.js`): Multiplexes channels for invites and requests.
|
- **Protomux / protomux-rpc** (`p2ns.js`, `includes/core/core-rpc.js`): Core invite and consensus on `p2ns.core-request-rpc`; plugin traffic via per-protocol RPC muxes (see [plugins/PLUGIN_CHANNELS.md](plugins/PLUGIN_CHANNELS.md)).
|
||||||
|
|
||||||
- **DNS Handling** (`dns.js`):
|
- **DNS Handling** (`dns.js`):
|
||||||
- UDP server on port 53 for P2P and public DNS resolution.
|
- UDP server on port 53 for P2P and public DNS resolution.
|
||||||
@@ -423,9 +423,9 @@ P2NS tracks peer connections, metrics, and history to provide visibility into th
|
|||||||
|
|
||||||
When peers connect via Hyperswarm:
|
When peers connect via Hyperswarm:
|
||||||
1. **Connection Established**: Peer connection is detected and tracked
|
1. **Connection Established**: Peer connection is detected and tracked
|
||||||
2. **Channel Setup**: Protomux channels are created for communication
|
2. **RPC Setup**: Core `p2ns.core-request-rpc` and plugin RPC muxes attach to the connection
|
||||||
3. **Replication**: Corestore replication begins automatically
|
3. **Replication**: Corestore replication begins automatically
|
||||||
4. **Invite Exchange**: Peers exchange invites if needed
|
4. **Invite Exchange**: Joiners receive Autopass invite wire via `invite.deliver` RPC when needed
|
||||||
5. **Metrics Tracking**: Connection metrics are recorded (duration, timestamps)
|
5. **Metrics Tracking**: Connection metrics are recorded (duration, timestamps)
|
||||||
6. **Disconnection**: On disconnect, metrics are finalized and stored in history
|
6. **Disconnection**: On disconnect, metrics are finalized and stored in history
|
||||||
|
|
||||||
@@ -768,11 +768,32 @@ After installation, verify the certificate is trusted by accessing `https://p2ns
|
|||||||
|
|
||||||
## Logging and Debugging
|
## Logging and Debugging
|
||||||
|
|
||||||
Logs are prefixed (e.g., `[Main]`, `[DNS]`) and leveled (DEBUG=0, INFO=1, WARN=2, ERROR=3). Set `LOG_LEVEL` in `.env`. Logs are displayed in the admin interface and console.
|
Logging uses leveled, prefixed messages (`[Main]`, `[DNS]`, `[Internal Proxy]`, `[HTTP Proxy]`, etc.). Set `LOG_LEVEL` in `.env` (0=DEBUG … 3=ERROR).
|
||||||
|
|
||||||
Example:
|
### Log files (`logs/`)
|
||||||
|
|
||||||
|
| File | Prefix / source | Console |
|
||||||
|
|------|-----------------|--------|
|
||||||
|
| `core.log` | Most subsystems (Swarm, Admin, Main, …) | Yes |
|
||||||
|
| `proxy.log` | `[Internal Proxy]` HTTPS plugin proxy | No |
|
||||||
|
| `http-proxy.log` | `[HTTP Proxy]` HTTP→HTTPS redirect server | No |
|
||||||
|
| `dns.log` | `[DNS]` | No |
|
||||||
|
| `plugins.log` | `Plugin:*`, PluginSDK, PluginChannels | No |
|
||||||
|
| `holesail.log` | `[Holesail]` | No |
|
||||||
|
|
||||||
|
Override directory with `LOG_DIR`. In-memory tail size per channel: `LOG_BUFFER_LINES` (default `2000`).
|
||||||
|
|
||||||
|
### Admin Logs tab
|
||||||
|
|
||||||
|
- Choose a log file from the dropdown.
|
||||||
|
- **Filter** lines (debounced substring or `/regex/flags`).
|
||||||
|
- Live tail via WebSocket (`subscribe-log` / `file-log` messages), not the legacy console stream.
|
||||||
|
|
||||||
|
Plugin `sdk.log.*` messages still appear in per-plugin terminals (`plugin-log` WebSocket) and `plugin-sites/{domain}/app.log`.
|
||||||
|
|
||||||
|
Example core line:
|
||||||
```
|
```
|
||||||
[INFO Main] Starting main function...
|
2026-05-28T12:00:00.000Z [INFO] [Main] Starting main function...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration Options
|
## Configuration Options
|
||||||
@@ -802,6 +823,8 @@ Configure via `.env` (copy from `default.env`):
|
|||||||
- **INTERNAL_PROXY_TIMEOUT_MS**: Timeout for internal HTTP proxy upstream requests to local Holesail endpoints (default: `12000` ms). Prevents long hangs during tunnel failures.
|
- **INTERNAL_PROXY_TIMEOUT_MS**: Timeout for internal HTTP proxy upstream requests to local Holesail endpoints (default: `12000` ms). Prevents long hangs during tunnel failures.
|
||||||
- **PORT_CHECK_TIMEOUT**: Port check timeout in seconds (default: `2` seconds).
|
- **PORT_CHECK_TIMEOUT**: Port check timeout in seconds (default: `2` seconds).
|
||||||
- **LOG_LEVEL**: Logging level (0-3, default: `0`).
|
- **LOG_LEVEL**: Logging level (0-3, default: `0`).
|
||||||
|
- **LOG_DIR**: Directory for split log files (default: `./logs`).
|
||||||
|
- **LOG_BUFFER_LINES**: In-memory tail lines per log channel for admin API/WS (default: `2000`).
|
||||||
- **Internal Domains**: Automatically discovered from `plugin-sites/{domain}/config.json` files. `p2ns.admin` is always internal.
|
- **Internal Domains**: Automatically discovered from `plugin-sites/{domain}/config.json` files. `p2ns.admin` is always internal.
|
||||||
- **DNS_PORT**: DNS server port (default: `53`).
|
- **DNS_PORT**: DNS server port (default: `53`).
|
||||||
- **HTTPS_PORT**: HTTPS proxy port (default: `443`).
|
- **HTTPS_PORT**: HTTPS proxy port (default: `443`).
|
||||||
@@ -917,7 +940,7 @@ The resource validation system runs at configurable intervals (default: 5 minute
|
|||||||
|
|
||||||
- **Holesail Connections**: Detects and removes stale Holesail server/client connections
|
- **Holesail Connections**: Detects and removes stale Holesail server/client connections
|
||||||
- **TLS/HTTP Servers**: Identifies and closes inactive TLS and HTTP server instances
|
- **TLS/HTTP Servers**: Identifies and closes inactive TLS and HTTP server instances
|
||||||
- **Peer Channels**: Validates Protomux channels and removes closed or stale channels
|
- **Plugin RPC**: Validates protomux-rpc plugin protocols and recreates stale peer RPC sessions
|
||||||
- **Timeout Handles**: Cleans up orphaned timeout handles that are no longer needed
|
- **Timeout Handles**: Cleans up orphaned timeout handles that are no longer needed
|
||||||
- **State Maps**: Ensures state maps (`holesails`, `tlsServers`, `httpServers`, `holesailClientTimeouts`) are consistent
|
- **State Maps**: Ensures state maps (`holesails`, `tlsServers`, `httpServers`, `holesailClientTimeouts`) are consistent
|
||||||
|
|
||||||
@@ -925,7 +948,7 @@ The resource validation system runs at configurable intervals (default: 5 minute
|
|||||||
|
|
||||||
1. **Holesail Servers/Clients**: Checks if processes are still running and connections are active
|
1. **Holesail Servers/Clients**: Checks if processes are still running and connections are active
|
||||||
2. **TLS/HTTP Servers**: Verifies servers are still listening and haven't been closed unexpectedly
|
2. **TLS/HTTP Servers**: Verifies servers are still listening and haven't been closed unexpectedly
|
||||||
3. **Peer Channels**: Validates that channels are still open and connected
|
3. **Plugin RPC**: Validates plugin RPC sessions and recreates closed muxes when peers are still connected
|
||||||
4. **Timeouts**: Removes timeout handles for connections that no longer exist
|
4. **Timeouts**: Removes timeout handles for connections that no longer exist
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
@@ -955,14 +978,9 @@ P2NS collects comprehensive system metrics for monitoring and troubleshooting.
|
|||||||
|
|
||||||
### Metrics Endpoints
|
### Metrics Endpoints
|
||||||
|
|
||||||
- **Current Stats**: `GET /api/stats` - Real-time system metrics including:
|
- **Current Stats**: `GET /api/stats` - One-shot snapshot (used for initial Stats tab load).
|
||||||
- Request statistics (total, success rate, average response time)
|
- **Historical Data**: `GET /api/stats/historical?minutes=N` - Historical metrics (1-1440 minutes).
|
||||||
- Holesail server/client status and resource usage
|
- **Live updates**: Admin Stats tab subscribes over WebSocket with `subscribe-stats` and receives `stats-snapshot` payloads (includes `stats`, `historical`, `health`, `status`, **Core** RPC invite diagnostics, and **Plugin RPC** protocol stats). `update-stats` notifies subscribers only; it does not replace the snapshot stream.
|
||||||
- P2P domain connections
|
|
||||||
- Process metrics (CPU, memory)
|
|
||||||
- Peer connection metrics
|
|
||||||
|
|
||||||
- **Historical Data**: `GET /api/stats/historical?minutes=N` - Historical metrics for the specified time range (1-1440 minutes).
|
|
||||||
|
|
||||||
### Metrics Configuration
|
### Metrics Configuration
|
||||||
|
|
||||||
@@ -972,7 +990,7 @@ Configure metrics behavior via environment variables:
|
|||||||
- `METRICS_AGGREGATION_INTERVAL`: Aggregation frequency
|
- `METRICS_AGGREGATION_INTERVAL`: Aggregation frequency
|
||||||
- `METRICS_MAX_BUFFER_SIZE`: Maximum samples to buffer
|
- `METRICS_MAX_BUFFER_SIZE`: Maximum samples to buffer
|
||||||
|
|
||||||
View metrics in the admin interface "Stats" tab with interactive charts and real-time updates.
|
View metrics in the admin **Stats** tab (charts + **Core** / **Plugin RPC** sections). Open the **Diagnostics** tab or `GET /api/diagnostics/invites` for detailed invite RPC diagnostics.
|
||||||
|
|
||||||
## Subnet Configuration
|
## Subnet Configuration
|
||||||
|
|
||||||
@@ -1064,10 +1082,10 @@ For more detailed information on specific topics, see:
|
|||||||
- **[Plugin SDK Reference](docs/plugins/PLUGIN_SDK.md)**: Comprehensive API reference for plugin development
|
- **[Plugin SDK Reference](docs/plugins/PLUGIN_SDK.md)**: Comprehensive API reference for plugin development
|
||||||
- **[REST API Documentation](docs/RESTAPI.md)**: Complete API endpoint reference including plugin management endpoints
|
- **[REST API Documentation](docs/RESTAPI.md)**: Complete API endpoint reference including plugin management endpoints
|
||||||
- **[HyperDB Integration](docs/plugins/HYPERDB.md)**: Database operations for plugins
|
- **[HyperDB Integration](docs/plugins/HYPERDB.md)**: Database operations for plugins
|
||||||
- **[Plugin Channels](docs/plugins/PLUGIN_CHANNELS.md)**: P2P communication via Protomux channels
|
- **[Plugin RPC](docs/plugins/PLUGIN_CHANNELS.md)**: Plugin peer protocols via protomux-rpc
|
||||||
- **[Hyperdrive Integration](docs/plugins/HYPERDRIVE.md)**: Distributed file system for plugins
|
- **[Hyperdrive Integration](docs/plugins/HYPERDRIVE.md)**: Distributed file system for plugins
|
||||||
- **[Proxy Server Documentation](proxy-server/README.md)**: Standalone proxy server configuration and usage
|
- **[Proxy Server Documentation](proxy-server/README.md)**: Standalone proxy server configuration and usage
|
||||||
- **[Test Scripts](test-scripts/README.md)**: Smoke validation scripts for `p2ns.admin` and `peer.paste`
|
- **[Test Scripts](test-scripts/README.md)**: Smoke tests and `npm run test:plugin-rpc` for plugin RPC contract
|
||||||
- **[Architecture RFCs](docs/rfcs/README.md)**: Design proposals for consensus, discovery, packaging, and admin security
|
- **[Architecture RFCs](docs/rfcs/README.md)**: Design proposals for consensus, discovery, packaging, and admin security
|
||||||
|
|
||||||
### Holepunch-Native Defaults
|
### Holepunch-Native Defaults
|
||||||
@@ -1075,7 +1093,7 @@ For more detailed information on specific topics, see:
|
|||||||
The following modernization features are enabled by default:
|
The following modernization features are enabled by default:
|
||||||
|
|
||||||
- Shared Corestore namespaces for plugin databases (`USE_SHARED_CORESTORE_NAMESPACES=true`)
|
- Shared Corestore namespaces for plugin databases (`USE_SHARED_CORESTORE_NAMESPACES=true`)
|
||||||
- Protomux RPC channel attachment (`ENABLE_PROTOMUX_RPC=true`)
|
- Plugin protomux-rpc (`ENABLE_PROTOMUX_RPC=true`; RPC-only plugin protocols — see [PLUGIN_CHANNELS.md](plugins/PLUGIN_CHANNELS.md))
|
||||||
- Hypercore/Corestore stats collection in `/api/stats` (`ENABLE_HYPERCORE_STATS=true`)
|
- Hypercore/Corestore stats collection in `/api/stats` (`ENABLE_HYPERCORE_STATS=true`)
|
||||||
|
|
||||||
Each can be explicitly disabled by setting its flag to `false`.
|
Each can be explicitly disabled by setting its flag to `false`.
|
||||||
|
|||||||
+104
-92
@@ -8,28 +8,32 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
## WebSocket Endpoint
|
## WebSocket Endpoint
|
||||||
- **URL**: `wss://p2ns.admin/ws`
|
- **URL**: `wss://p2ns.admin/ws`
|
||||||
- **Description**: Establishes a WebSocket connection for real-time updates from the server.
|
- **Description**: Establishes a WebSocket connection for real-time updates from the server.
|
||||||
- **Message Types**:
|
- **Client → server messages**:
|
||||||
- `log`: System logs with `level` (info, error) and `message`.
|
- `subscribe-stats` / `unsubscribe-stats` / `request-stats-snapshot` — Stats tab live data.
|
||||||
- `holesail-log`: Holesail server/client logs with `id`, `level`, and `message`.
|
- `subscribe-log` — `{ "type": "subscribe-log", "channel": "core", "lines": 1000 }` (channels: `core`, `proxy`, `httpProxy`, `dns`, `plugins`, `holesail`).
|
||||||
- `update-database`: Triggers refresh of domains and entries.
|
- `unsubscribe-log` — Stop log tail.
|
||||||
- `update-peers`: Triggers refresh of peers.
|
- `request-domains` — Refresh domains list (server replies with `domains-list`).
|
||||||
- `update-certs`: Triggers refresh of certificates.
|
|
||||||
- `update-interfaces`: Triggers refresh of virtual interfaces.
|
- **Server → client messages**:
|
||||||
- `update-local-dns`: Triggers refresh of local DNS and conflict selector.
|
- `stats-snapshot` — Full stats page payload (`stats`, `historical`, `health`, `status`, `minutes`). Includes `stats.core` (invite RPC diagnostics) and `stats.pluginRpc` / `stats.peerChannels` (plugin RPC metrics).
|
||||||
- `update-holesail`: Triggers refresh of Holesail servers.
|
- `update-stats` — Notifies stats subscribers to apply their latest snapshot (does not embed metrics itself).
|
||||||
- `update-holesail-clients`: Triggers refresh of Holesail clients.
|
- `update-health` — Health payload for Diagnostics tab subscribers.
|
||||||
- `update-settings`: Triggers refresh of settings and subnets.
|
- `file-log` — `{ "type": "file-log", "channel": "dns", "level": "info", "message": "<line>" }` (live log tail).
|
||||||
- `update-stats`: Triggers refresh of stats tab.
|
- `log-snapshot` — Initial tail after `subscribe-log`: `{ "type": "log-snapshot", "channel": "core", "lines": ["..."] }`.
|
||||||
- `update-plugins`: Triggers refresh of plugins tab.
|
- `log` — **Legacy**; may still map to core. Prefer `file-log` + `subscribe-log`.
|
||||||
- `update-plugin-settings`: Triggers refresh of plugin settings.
|
- `holesail-log` — Holesail child process logs (`id`, `level`, `message`).
|
||||||
- `plugin-log`: Plugin log messages with `domain` (string), `level` (string: debug/info/warn/error), `component` (string), and `message` (string).
|
- `plugin-log` — Per-plugin logs (`domain`, `level`, `component`, `message`).
|
||||||
- `system-reset`: Signals a system reset, requiring a client reload.
|
- `domains-list` — Resolved domains array.
|
||||||
- **Example**:
|
- `update-database`, `update-peers`, `update-certs`, `update-interfaces`, `update-local-dns`, `update-holesail`, `update-holesail-clients`, `update-settings`, `update-plugins`, `update-plugin-settings` — Tab refresh hints.
|
||||||
|
- `system-reset` — Client should reload.
|
||||||
|
|
||||||
|
- **Example (`file-log`)**:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "log",
|
"type": "file-log",
|
||||||
|
"channel": "core",
|
||||||
"level": "info",
|
"level": "info",
|
||||||
"message": "Starting main function..."
|
"message": "2026-05-28T12:00:00.000Z [INFO] [Main] Starting..."
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -724,7 +728,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
{"id":"abc123"}
|
{"id":"abc123"}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 29. POST /api/holesail-delete
|
### 33. POST /api/holesail-delete
|
||||||
- **Description**: Deletes a Holesail server by ID and removes it from `holesail_servers.json`.
|
- **Description**: Deletes a Holesail server by ID and removes it from `holesail_servers.json`.
|
||||||
- **Request Body**: JSON with `id` (string).
|
- **Request Body**: JSON with `id` (string).
|
||||||
- **Response**: Plain text `OK` on success, error message on failure.
|
- **Response**: Plain text `OK` on success, error message on failure.
|
||||||
@@ -743,7 +747,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
OK
|
OK
|
||||||
```
|
```
|
||||||
|
|
||||||
### 30. POST /api/holesail-restart
|
### 34. POST /api/holesail-restart
|
||||||
- **Description**: Restarts a Holesail server by ID, optionally reassigning its domain. Persists to `holesail_servers.json`.
|
- **Description**: Restarts a Holesail server by ID, optionally reassigning its domain. Persists to `holesail_servers.json`.
|
||||||
- **Request Body**: JSON with `id` (string).
|
- **Request Body**: JSON with `id` (string).
|
||||||
- **Response**: Plain text `OK` on success, error message on failure.
|
- **Response**: Plain text `OK` on success, error message on failure.
|
||||||
@@ -762,7 +766,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
OK
|
OK
|
||||||
```
|
```
|
||||||
|
|
||||||
### 31. POST /api/holesail-client-create
|
### 35. POST /api/holesail-client-create
|
||||||
- **Description**: Creates a new Holesail client for a domain and port. Persists to `holesail_clients.json`. If `serviceName` is provided, the client ID will be `domain_servicename`; otherwise, a generated ID is used. The client is also added to the domain's claim record `clients` array.
|
- **Description**: Creates a new Holesail client for a domain and port. Persists to `holesail_clients.json`. If `serviceName` is provided, the client ID will be `domain_servicename`; otherwise, a generated ID is used. The client is also added to the domain's claim record `clients` array.
|
||||||
- **Request Body**: JSON with:
|
- **Request Body**: JSON with:
|
||||||
- `domain` (string, required): Domain name (must be owned by local writer)
|
- `domain` (string, required): Domain name (must be owned by local writer)
|
||||||
@@ -787,7 +791,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
{"id":"example.tld_web"}
|
{"id":"example.tld_web"}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 32. POST /api/holesail-client-delete
|
### 36. POST /api/holesail-client-delete
|
||||||
- **Description**: Deletes a Holesail client by ID, closing connections and removing it from `holesail_clients.json`.
|
- **Description**: Deletes a Holesail client by ID, closing connections and removing it from `holesail_clients.json`.
|
||||||
- **Request Body**: JSON with `id` (string).
|
- **Request Body**: JSON with `id` (string).
|
||||||
- **Response**: Plain text `OK` on success, error message on failure.
|
- **Response**: Plain text `OK` on success, error message on failure.
|
||||||
@@ -806,7 +810,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
OK
|
OK
|
||||||
```
|
```
|
||||||
|
|
||||||
### 33. POST /api/holesail-client-restart
|
### 37. POST /api/holesail-client-restart
|
||||||
- **Description**: Restarts a Holesail client by ID, ensuring the port is free and connections are closed.
|
- **Description**: Restarts a Holesail client by ID, ensuring the port is free and connections are closed.
|
||||||
- **Request Body**: JSON with `id` (string).
|
- **Request Body**: JSON with `id` (string).
|
||||||
- **Response**: Plain text `OK` on success, error message on failure.
|
- **Response**: Plain text `OK` on success, error message on failure.
|
||||||
@@ -825,7 +829,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
OK
|
OK
|
||||||
```
|
```
|
||||||
|
|
||||||
### 34. POST /api/update-settings
|
### 38. POST /api/update-settings
|
||||||
- **Description**: Updates environment settings (whitelisted variables) and persists them to `.env`. Note: `SUBNETS` can be updated here, but it's recommended to use `/api/subnets` for subnet management. `SUBNET_BASE` and `INITIAL_IP_INDEX` are deprecated in favor of the subnet configurator.
|
- **Description**: Updates environment settings (whitelisted variables) and persists them to `.env`. Note: `SUBNETS` can be updated here, but it's recommended to use `/api/subnets` for subnet management. `SUBNET_BASE` and `INITIAL_IP_INDEX` are deprecated in favor of the subnet configurator.
|
||||||
- **Request Body**: JSON with `settings` (object mapping whitelisted keys to values). For `SUBNETS`, provide a JSON array string.
|
- **Request Body**: JSON with `settings` (object mapping whitelisted keys to values). For `SUBNETS`, provide a JSON array string.
|
||||||
- **Response**: JSON object with `message` (string), `restartRequired` (boolean), and optionally `restartRequiredSettings` (array of strings).
|
- **Response**: JSON object with `message` (string), `restartRequired` (boolean), and optionally `restartRequiredSettings` (array of strings).
|
||||||
@@ -848,7 +852,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 35. GET /api/network-interfaces
|
### 39. GET /api/network-interfaces
|
||||||
- **Description**: Retrieves a list of available network interfaces on the system. Used by the admin interface to populate the Subnet Interface Name dropdown setting.
|
- **Description**: Retrieves a list of available network interfaces on the system. Used by the admin interface to populate the Subnet Interface Name dropdown setting.
|
||||||
- **Response**: JSON object with `interfaces` (array of interface objects). Each interface object contains:
|
- **Response**: JSON object with `interfaces` (array of interface objects). Each interface object contains:
|
||||||
- `value` (string): Interface name (e.g., "lo0", "lo", "eth0")
|
- `value` (string): Interface name (e.g., "lo0", "lo", "eth0")
|
||||||
@@ -872,7 +876,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
```
|
```
|
||||||
- **Note**: Interfaces are sorted with loopback interfaces (lo, lo0) and OS-specific defaults (lo0 on macOS, lo on Linux, Loopback Pseudo-Interface 1 on Windows) prioritized first.
|
- **Note**: Interfaces are sorted with loopback interfaces (lo, lo0) and OS-specific defaults (lo0 on macOS, lo on Linux, Loopback Pseudo-Interface 1 on Windows) prioritized first.
|
||||||
|
|
||||||
### 36. GET /api/subnets
|
### 40. GET /api/subnets
|
||||||
- **Description**: Retrieves all configured subnets with capacity information. Returns default subnet from `SUBNET_BASE` if no subnets are configured.
|
- **Description**: Retrieves all configured subnets with capacity information. Returns default subnet from `SUBNET_BASE` if no subnets are configured.
|
||||||
- **Response**: JSON object with `subnets` (array of subnet objects). Each subnet object contains:
|
- **Response**: JSON object with `subnets` (array of subnet objects). Each subnet object contains:
|
||||||
- `base` (string): Network base IP address (e.g., "192.168.3.0")
|
- `base` (string): Network base IP address (e.g., "192.168.3.0")
|
||||||
@@ -918,7 +922,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 36. POST /api/subnets
|
### 41. POST /api/subnets
|
||||||
- **Description**: Updates subnet configuration. Replaces all existing subnets with the provided array. Changes require a system restart to fully take effect.
|
- **Description**: Updates subnet configuration. Replaces all existing subnets with the provided array. Changes require a system restart to fully take effect.
|
||||||
- **Request Body**: JSON object with `subnets` (array of subnet objects). Each subnet object must contain:
|
- **Request Body**: JSON object with `subnets` (array of subnet objects). Each subnet object must contain:
|
||||||
- `base` (string, required): Network base IP address (e.g., "192.168.3.0")
|
- `base` (string, required): Network base IP address (e.g., "192.168.3.0")
|
||||||
@@ -950,7 +954,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
- `startIndex` must be between 1 and 254 (or up to subnet size - 2)
|
- `startIndex` must be between 1 and 254 (or up to subnet size - 2)
|
||||||
- Subnets must not overlap with each other
|
- Subnets must not overlap with each other
|
||||||
|
|
||||||
### 37. GET /api/health
|
### 42. GET /api/health
|
||||||
- **Description**: Health check endpoint supporting liveness and readiness probes.
|
- **Description**: Health check endpoint supporting liveness and readiness probes.
|
||||||
- **Query Parameters**:
|
- **Query Parameters**:
|
||||||
- `probe`: Type of health probe (`liveness` or `readiness`, default: `liveness`).
|
- `probe`: Type of health probe (`liveness` or `readiness`, default: `liveness`).
|
||||||
@@ -981,13 +985,14 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 38. GET /api/stats
|
### 43. GET /api/stats
|
||||||
- **Description**: Retrieves real-time system metrics including request statistics, Holesail connections, process metrics, and peer information.
|
- **Description**: Retrieves a one-shot system metrics snapshot (same data shape as `stats-snapshot` over WebSocket). The admin UI loads this once, then uses `subscribe-stats` for live updates.
|
||||||
- **Response**: JSON object with comprehensive metrics including:
|
- **Response**: JSON object including:
|
||||||
- Request statistics (total, success rate, average response time, failed requests)
|
- Request statistics (total, success rate, average response time, failed requests)
|
||||||
- Holesail children (servers, clients, P2P domain connections) with status, PID, uptime, CPU/memory usage
|
- Holesail children (servers, clients, P2P domain connections) with status, PID, uptime, CPU/memory usage
|
||||||
- Process metrics
|
- `core` — Core control-plane / invite RPC diagnostics (`diagnoseInviteIssues`)
|
||||||
- Peer connection metrics
|
- `pluginRpc` and `peerChannels` — Per-plugin protomux-rpc protocol stats (`transport: 'rpc'`, methods, `rpcOpen` counts)
|
||||||
|
- HyperDB / Hyperdrive sections when available
|
||||||
- **Status Codes**:
|
- **Status Codes**:
|
||||||
- `200`: Success.
|
- `200`: Success.
|
||||||
- `500`: Failed to fetch stats.
|
- `500`: Failed to fetch stats.
|
||||||
@@ -1019,7 +1024,26 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 39. GET /api/stats/historical
|
### 44. GET /api/logs
|
||||||
|
- **Description**: Lists available split log channels written under `LOG_DIR` (default `./logs/`).
|
||||||
|
- **Response**: `{ "channels": [ { "id": "core", "label": "Core", "file": "core.log" }, ... ] }`
|
||||||
|
- **Status Codes**: `200`, `500`
|
||||||
|
- **Example**:
|
||||||
|
```bash
|
||||||
|
curl -k https://p2ns.admin/api/logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 45. GET /api/logs/:channel
|
||||||
|
- **Description**: Returns the tail of a log file (in-memory buffer with file fallback).
|
||||||
|
- **Path**: `channel` — `core`, `proxy`, `httpProxy`, `dns`, `plugins`, or `holesail`
|
||||||
|
- **Query**: `lines` — max lines (default `500`, max `5000`)
|
||||||
|
- **Response**: `{ "channel": "dns", "lines": ["..."] }`
|
||||||
|
- **Example**:
|
||||||
|
```bash
|
||||||
|
curl -k "https://p2ns.admin/api/logs/dns?lines=200"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 46. GET /api/stats/historical
|
||||||
- **Description**: Retrieves historical metrics data for a specified time range.
|
- **Description**: Retrieves historical metrics data for a specified time range.
|
||||||
- **Query Parameters**:
|
- **Query Parameters**:
|
||||||
- `minutes`: Time range in minutes (1-1440, default: 60).
|
- `minutes`: Time range in minutes (1-1440, default: 60).
|
||||||
@@ -1033,7 +1057,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
"https://p2ns.admin/api/stats/historical?minutes=1440"
|
"https://p2ns.admin/api/stats/historical?minutes=1440"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 40. GET /api/backups
|
### 47. GET /api/backups
|
||||||
- **Description**: Lists all available backups with metadata including name, timestamp, size, and file count.
|
- **Description**: Lists all available backups with metadata including name, timestamp, size, and file count.
|
||||||
- **Response**: JSON array of backup objects with `name`, `timestamp`, `size`, `sizeFormatted`, and `fileCount`.
|
- **Response**: JSON array of backup objects with `name`, `timestamp`, `size`, `sizeFormatted`, and `fileCount`.
|
||||||
- **Status Codes**:
|
- **Status Codes**:
|
||||||
@@ -1056,7 +1080,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 41. POST /api/backups/create
|
### 48. POST /api/backups/create
|
||||||
- **Description**: Creates a manual backup of configuration files, certificates, and cache data. Automatic cleanup of old backups is performed before creation.
|
- **Description**: Creates a manual backup of configuration files, certificates, and cache data. Automatic cleanup of old backups is performed before creation.
|
||||||
- **Request Body**: None.
|
- **Request Body**: None.
|
||||||
- **Response**: JSON object with `success` (boolean) and `path` (string, backup file path).
|
- **Response**: JSON object with `success` (boolean) and `path` (string, backup file path).
|
||||||
@@ -1075,7 +1099,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 42. POST /api/backups/restore
|
### 49. POST /api/backups/restore
|
||||||
- **Description**: Restores system configuration from a backup. Replaces current configuration files and certificates.
|
- **Description**: Restores system configuration from a backup. Replaces current configuration files and certificates.
|
||||||
- **Request Body**: JSON with `backupName` (string, backup name to restore).
|
- **Request Body**: JSON with `backupName` (string, backup name to restore).
|
||||||
- **Response**: JSON object with `success` (boolean) and `message` (string).
|
- **Response**: JSON object with `success` (boolean) and `message` (string).
|
||||||
@@ -1097,7 +1121,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 43. DELETE /api/backups/:id
|
### 50. DELETE /api/backups/:id
|
||||||
- **Description**: Deletes a backup by name. Supports both directory and tar.gz formats.
|
- **Description**: Deletes a backup by name. Supports both directory and tar.gz formats.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `id`: Backup name (e.g., `backup-20240101-000000` or `backup-20240101-000000.tar.gz`).
|
- `id`: Backup name (e.g., `backup-20240101-000000` or `backup-20240101-000000.tar.gz`).
|
||||||
@@ -1112,7 +1136,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
https://p2ns.admin/api/backups/backup-20240101-000000
|
https://p2ns.admin/api/backups/backup-20240101-000000
|
||||||
```
|
```
|
||||||
|
|
||||||
### 44. GET /api/backups/:id/metadata
|
### 51. GET /api/backups/:id/metadata
|
||||||
- **Description**: Retrieves detailed metadata for a backup including file list, sizes, and timestamps.
|
- **Description**: Retrieves detailed metadata for a backup including file list, sizes, and timestamps.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `id`: Backup name.
|
- `id`: Backup name.
|
||||||
@@ -1127,7 +1151,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
https://p2ns.admin/api/backups/backup-20240101-000000/metadata
|
https://p2ns.admin/api/backups/backup-20240101-000000/metadata
|
||||||
```
|
```
|
||||||
|
|
||||||
### 45. POST /api/diagnostics/dns-lookup
|
### 52. POST /api/diagnostics/dns-lookup
|
||||||
- **Description**: Performs DNS lookup for a domain with specified record type.
|
- **Description**: Performs DNS lookup for a domain with specified record type.
|
||||||
- **Request Body**: JSON with `domain` (string, required) and `type` (string, optional, default: `A`). Supported types: A, AAAA, MX, TXT, NS, CNAME, SRV, PTR, SOA.
|
- **Request Body**: JSON with `domain` (string, required) and `type` (string, optional, default: `A`). Supported types: A, AAAA, MX, TXT, NS, CNAME, SRV, PTR, SOA.
|
||||||
- **Response**: JSON object with `success` (boolean), `domain`, `type`, `results` (array), and `responseTime` (number).
|
- **Response**: JSON object with `success` (boolean), `domain`, `type`, `results` (array), and `responseTime` (number).
|
||||||
@@ -1152,7 +1176,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 46. POST /api/diagnostics/ping
|
### 53. POST /api/diagnostics/ping
|
||||||
- **Description**: Tests network connectivity using ping. Supports both streaming and non-streaming modes.
|
- **Description**: Tests network connectivity using ping. Supports both streaming and non-streaming modes.
|
||||||
- **Request Body**: JSON with `target` (string, required), `count` (number, optional, default: 4), and `stream` (boolean, optional, default: false).
|
- **Request Body**: JSON with `target` (string, required), `count` (number, optional, default: 4), and `stream` (boolean, optional, default: false).
|
||||||
- **Response**:
|
- **Response**:
|
||||||
@@ -1177,7 +1201,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
https://p2ns.admin/api/diagnostics/ping
|
https://p2ns.admin/api/diagnostics/ping
|
||||||
```
|
```
|
||||||
|
|
||||||
### 47. POST /api/diagnostics/traceroute
|
### 54. POST /api/diagnostics/traceroute
|
||||||
- **Description**: Traces network path to a target. Supports both streaming and non-streaming modes.
|
- **Description**: Traces network path to a target. Supports both streaming and non-streaming modes.
|
||||||
- **Request Body**: JSON with `target` (string, required) and `stream` (boolean, optional, default: false).
|
- **Request Body**: JSON with `target` (string, required) and `stream` (boolean, optional, default: false).
|
||||||
- **Response**:
|
- **Response**:
|
||||||
@@ -1195,7 +1219,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
https://p2ns.admin/api/diagnostics/traceroute
|
https://p2ns.admin/api/diagnostics/traceroute
|
||||||
```
|
```
|
||||||
|
|
||||||
### 48. POST /api/diagnostics/connection-test
|
### 55. POST /api/diagnostics/connection-test
|
||||||
- **Description**: Tests TCP connectivity to a domain and port combination.
|
- **Description**: Tests TCP connectivity to a domain and port combination.
|
||||||
- **Request Body**: JSON with `domain` (string, required) and `port` (number, required).
|
- **Request Body**: JSON with `domain` (string, required) and `port` (number, required).
|
||||||
- **Response**: JSON object with `success` (boolean), `domain`, `ip` (resolved IP), `port`, `latency` (if successful), `error` (if failed), and `responseTime`.
|
- **Response**: JSON object with `success` (boolean), `domain`, `ip` (resolved IP), `port`, `latency` (if successful), `error` (if failed), and `responseTime`.
|
||||||
@@ -1221,37 +1245,25 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 49. GET /api/diagnostics/bandwidth
|
### 56. GET /api/diagnostics/bandwidth
|
||||||
- **Description**: Retrieves network interface information and configuration. Note: Real-time bandwidth statistics require system-specific tools and are not available via Node.js.
|
- **Description**: Network interface information and configuration. Real-time throughput stats are not available via Node.js; response is interface layout only.
|
||||||
- **Response**: JSON object with `interfaces` (object mapping interface names to configuration), `note` (string), and `responseTime`.
|
- **Response**: JSON with `interfaces`, optional `note`, `responseTime`.
|
||||||
- **Status Codes**:
|
- **Status Codes**: `200`, `500`
|
||||||
- `200`: Success.
|
|
||||||
- `500`: Server error.
|
|
||||||
- **Example**:
|
- **Example**:
|
||||||
```bash
|
```bash
|
||||||
curl -X GET \
|
curl -k https://p2ns.admin/api/diagnostics/bandwidth
|
||||||
https://p2ns.admin/api/diagnostics/bandwidth
|
|
||||||
```
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"interfaces": {
|
|
||||||
"eth0": {
|
|
||||||
"name": "eth0",
|
|
||||||
"addresses": [
|
|
||||||
{
|
|
||||||
"address": "192.168.1.100",
|
|
||||||
"netmask": "255.255.255.0",
|
|
||||||
"family": "IPv4"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"note": "Bandwidth statistics require system-specific tools. Interface information only.",
|
|
||||||
"responseTime": 5
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 50. GET /<tab>
|
### 57. GET /api/diagnostics/invites
|
||||||
|
- **Description**: Core invite / control-plane diagnostics over `p2ns.core-request-rpc` (`invite.request`, `invite.deliver`, `invite.ack`, `core.status`). Used by the Stats **Core** section and Invite Diagnostics UI.
|
||||||
|
- **Response**: JSON with `summary` (dnsPass, rpcOpen, requestChannelOpen, failed peers, …), `peers`, `recommendations`, `connectionIssues`, etc.
|
||||||
|
- **Status Codes**: `200`, `503` (still initializing), `500`
|
||||||
|
- **Example**:
|
||||||
|
```bash
|
||||||
|
curl -k https://p2ns.admin/api/diagnostics/invites
|
||||||
|
```
|
||||||
|
|
||||||
|
### 58. GET /<tab>
|
||||||
- **Description**: Redirects to the admin panel with the specified tab (e.g., `/domains`, `/host`, `/local-dns`) open.
|
- **Description**: Redirects to the admin panel with the specified tab (e.g., `/domains`, `/host`, `/local-dns`) open.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `tab`: One of `domains`, `host`, `local-dns`, `entries`, `peers`, `certs`, `interfaces`, `logs`, `settings`.
|
- `tab`: One of `domains`, `host`, `local-dns`, `entries`, `peers`, `certs`, `interfaces`, `logs`, `settings`.
|
||||||
@@ -1265,7 +1277,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
https://p2ns.admin/domains
|
https://p2ns.admin/domains
|
||||||
```
|
```
|
||||||
|
|
||||||
### 38. GET /favicon.ico
|
### 59. GET /favicon.ico
|
||||||
- **Description**: Returns a 404 response (favicon not implemented).
|
- **Description**: Returns a 404 response (favicon not implemented).
|
||||||
- **Response**: Plain text `Not Found`.
|
- **Response**: Plain text `Not Found`.
|
||||||
- **Status Codes**:
|
- **Status Codes**:
|
||||||
@@ -1281,7 +1293,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
|
|
||||||
## Consensus Endpoints
|
## Consensus Endpoints
|
||||||
|
|
||||||
### 51. GET /api/consensus/:domain
|
### 60. GET /api/consensus/:domain
|
||||||
- **Description**: Retrieves the consensus state for a specific domain, including vote counts, quorum status, and resolution information.
|
- **Description**: Retrieves the consensus state for a specific domain, including vote counts, quorum status, and resolution information.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `domain`: The domain name (e.g., `example.tld`).
|
- `domain`: The domain name (e.g., `example.tld`).
|
||||||
@@ -1320,7 +1332,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 52. GET /api/consensus/metrics
|
### 61. GET /api/consensus/metrics
|
||||||
- **Description**: Retrieves overall consensus metrics including resolution statistics, quorum failures, ties, and validation failures.
|
- **Description**: Retrieves overall consensus metrics including resolution statistics, quorum failures, ties, and validation failures.
|
||||||
- **Response**: JSON object with:
|
- **Response**: JSON object with:
|
||||||
- `resolutions` (number): Total number of successful domain resolutions.
|
- `resolutions` (number): Total number of successful domain resolutions.
|
||||||
@@ -1361,7 +1373,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 53. POST /api/consensus/recalculate
|
### 62. POST /api/consensus/recalculate
|
||||||
- **Description**: Forces a consensus recalculation for all domains. Invalidates the consensus cache and triggers auto-voting checks.
|
- **Description**: Forces a consensus recalculation for all domains. Invalidates the consensus cache and triggers auto-voting checks.
|
||||||
- **Request Body**: None.
|
- **Request Body**: None.
|
||||||
- **Response**: JSON object with `success` (boolean) and `message` (string).
|
- **Response**: JSON object with `success` (boolean) and `message` (string).
|
||||||
@@ -1381,7 +1393,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 54. POST /api/consensus/recalculate/:domain
|
### 63. POST /api/consensus/recalculate/:domain
|
||||||
- **Description**: Forces a consensus recalculation for a specific domain. Invalidates the consensus cache for that domain and triggers auto-voting.
|
- **Description**: Forces a consensus recalculation for a specific domain. Invalidates the consensus cache for that domain and triggers auto-voting.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `domain`: The domain name (e.g., `example.tld`).
|
- `domain`: The domain name (e.g., `example.tld`).
|
||||||
@@ -1405,7 +1417,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
|
|
||||||
## Service Subscription Endpoints
|
## Service Subscription Endpoints
|
||||||
|
|
||||||
### 55. GET /api/domain-services
|
### 64. GET /api/domain-services
|
||||||
- **Description**: Retrieves all services configured for a specific domain from its claim record.
|
- **Description**: Retrieves all services configured for a specific domain from its claim record.
|
||||||
- **Query Parameters**:
|
- **Query Parameters**:
|
||||||
- `domain` (string, required): The domain name to query services for.
|
- `domain` (string, required): The domain name to query services for.
|
||||||
@@ -1440,7 +1452,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 56. GET /api/service-subscriptions
|
### 65. GET /api/service-subscriptions
|
||||||
- **Description**: Lists all service subscriptions configured on this node.
|
- **Description**: Lists all service subscriptions configured on this node.
|
||||||
- **Response**: JSON array of subscription objects, each containing:
|
- **Response**: JSON array of subscription objects, each containing:
|
||||||
- `domain` (string): Domain name
|
- `domain` (string): Domain name
|
||||||
@@ -1468,7 +1480,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 57. GET /api/subscribe-all-domains
|
### 66. GET /api/subscribe-all-domains
|
||||||
- **Description**: Lists all domains for which "subscribe all" is enabled. When enabled, the system automatically subscribes to all services for that domain, including newly added services.
|
- **Description**: Lists all domains for which "subscribe all" is enabled. When enabled, the system automatically subscribes to all services for that domain, including newly added services.
|
||||||
- **Response**: JSON array of domain names (strings).
|
- **Response**: JSON array of domain names (strings).
|
||||||
- **Status Codes**:
|
- **Status Codes**:
|
||||||
@@ -1483,7 +1495,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
["example.tld", "another.tld"]
|
["example.tld", "another.tld"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 58. POST /api/service-subscribe
|
### 67. POST /api/service-subscribe
|
||||||
- **Description**: Subscribes to a specific service from a domain. Creates a Holesail client automatically with ID `domain_servicename` and persists the subscription to `subscriptions.json`.
|
- **Description**: Subscribes to a specific service from a domain. Creates a Holesail client automatically with ID `domain_servicename` and persists the subscription to `subscriptions.json`.
|
||||||
- **Request Body**: JSON with:
|
- **Request Body**: JSON with:
|
||||||
- `domain` (string, required): Domain name
|
- `domain` (string, required): Domain name
|
||||||
@@ -1509,7 +1521,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
{"success": true}
|
{"success": true}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 59. POST /api/service-unsubscribe
|
### 68. POST /api/service-unsubscribe
|
||||||
- **Description**: Unsubscribes from a specific service. Deletes the associated Holesail client and removes the subscription from `subscriptions.json`.
|
- **Description**: Unsubscribes from a specific service. Deletes the associated Holesail client and removes the subscription from `subscriptions.json`.
|
||||||
- **Request Body**: JSON with:
|
- **Request Body**: JSON with:
|
||||||
- `domain` (string, required): Domain name
|
- `domain` (string, required): Domain name
|
||||||
@@ -1532,7 +1544,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
{"success": true}
|
{"success": true}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 60. POST /api/subscribe-all
|
### 69. POST /api/subscribe-all
|
||||||
- **Description**: Enables "subscribe all" for a domain. This automatically subscribes to all current services for that domain and will automatically subscribe to any new services added in the future. Creates Holesail clients for all existing services.
|
- **Description**: Enables "subscribe all" for a domain. This automatically subscribes to all current services for that domain and will automatically subscribe to any new services added in the future. Creates Holesail clients for all existing services.
|
||||||
- **Request Body**: JSON with:
|
- **Request Body**: JSON with:
|
||||||
- `domain` (string, required): Domain name
|
- `domain` (string, required): Domain name
|
||||||
@@ -1553,7 +1565,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
{"success": true}
|
{"success": true}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 61. POST /api/unsubscribe-all
|
### 70. POST /api/unsubscribe-all
|
||||||
- **Description**: Disables "subscribe all" for a domain and unsubscribes from all services for that domain. Deletes all associated Holesail clients.
|
- **Description**: Disables "subscribe all" for a domain and unsubscribes from all services for that domain. Deletes all associated Holesail clients.
|
||||||
- **Request Body**: JSON with:
|
- **Request Body**: JSON with:
|
||||||
- `domain` (string, required): Domain name
|
- `domain` (string, required): Domain name
|
||||||
@@ -1578,7 +1590,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
|
|
||||||
**Note:** For detailed information about the plugin system, see [plugins/README.md](plugins/README.md) and [plugins/PLUGIN_SDK.md](plugins/PLUGIN_SDK.md).
|
**Note:** For detailed information about the plugin system, see [plugins/README.md](plugins/README.md) and [plugins/PLUGIN_SDK.md](plugins/PLUGIN_SDK.md).
|
||||||
|
|
||||||
### 62. GET /api/plugins
|
### 71. GET /api/plugins
|
||||||
- **Description**: Lists all plugins with their information, status, actions, and settings. Includes both loaded and stopped plugins.
|
- **Description**: Lists all plugins with their information, status, actions, and settings. Includes both loaded and stopped plugins.
|
||||||
- **Response**: JSON object with `plugins` (array of plugin objects). Each plugin object contains:
|
- **Response**: JSON object with `plugins` (array of plugin objects). Each plugin object contains:
|
||||||
- `domain` (string): Plugin domain name
|
- `domain` (string): Plugin domain name
|
||||||
@@ -1639,7 +1651,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 63. GET /api/plugins/:domain
|
### 72. GET /api/plugins/:domain
|
||||||
- **Description**: Retrieves detailed information for a specific plugin.
|
- **Description**: Retrieves detailed information for a specific plugin.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
||||||
@@ -1654,7 +1666,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
https://p2ns.admin/api/plugins/example.plugin
|
https://p2ns.admin/api/plugins/example.plugin
|
||||||
```
|
```
|
||||||
|
|
||||||
### 64. POST /api/plugins/:domain/start
|
### 73. POST /api/plugins/:domain/start
|
||||||
- **Description**: Starts a stopped plugin. Loads the plugin handler and initializes resources.
|
- **Description**: Starts a stopped plugin. Loads the plugin handler and initializes resources.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
||||||
@@ -1678,7 +1690,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 65. POST /api/plugins/:domain/stop
|
### 74. POST /api/plugins/:domain/stop
|
||||||
- **Description**: Stops a running plugin. Unloads the plugin handler and cleans up resources.
|
- **Description**: Stops a running plugin. Unloads the plugin handler and cleans up resources.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
||||||
@@ -1702,7 +1714,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 66. POST /api/plugins/:domain/reload
|
### 75. POST /api/plugins/:domain/reload
|
||||||
- **Description**: Reloads a plugin. Stops the plugin, clears the module cache, and starts it again. Useful for applying code changes without restarting P2NS.
|
- **Description**: Reloads a plugin. Stops the plugin, clears the module cache, and starts it again. Useful for applying code changes without restarting P2NS.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
||||||
@@ -1726,7 +1738,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 67. POST /api/plugins/:domain/actions/:actionName
|
### 76. POST /api/plugins/:domain/actions/:actionName
|
||||||
- **Description**: Executes a registered plugin action. The action handler is called with the provided parameters.
|
- **Description**: Executes a registered plugin action. The action handler is called with the provided parameters.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
||||||
@@ -1756,7 +1768,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 68. POST /api/plugins/:domain/settings
|
### 77. POST /api/plugins/:domain/settings
|
||||||
- **Description**: Updates plugin settings. Saves settings to `cache/plugin-settings/{domain}.json` and persists them across plugin restarts.
|
- **Description**: Updates plugin settings. Saves settings to `cache/plugin-settings/{domain}.json` and persists them across plugin restarts.
|
||||||
- **Path Parameters**:
|
- **Path Parameters**:
|
||||||
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
- `domain`: The plugin domain name (e.g., `example.plugin`).
|
||||||
@@ -1781,7 +1793,7 @@ The P2NS (Peer-to-Peer Name System) admin backend API, hosted at `https://p2ns.a
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 69. GET /api/token
|
### 78. GET /api/token
|
||||||
- **Description**: Generates a signed Ed25519 authentication token for plugin authentication. Available to all plugins globally.
|
- **Description**: Generates a signed Ed25519 authentication token for plugin authentication. Available to all plugins globally.
|
||||||
- **Request Headers**: None required.
|
- **Request Headers**: None required.
|
||||||
- **Response**: JSON object with `token` (string), `expiresAt` (number), and `peerId` (string).
|
- **Response**: JSON object with `token` (string), `expiresAt` (number), and `peerId` (string).
|
||||||
@@ -1879,4 +1891,4 @@ See [plugins/PLUGIN_SDK.md](plugins/PLUGIN_SDK.md#authentication-and-authorizati
|
|||||||
- Use tools like `curl` or Postman to test endpoints.
|
- Use tools like `curl` or Postman to test endpoints.
|
||||||
- Verify WebSocket updates using a WebSocket client (e.g., `wscat`).
|
- Verify WebSocket updates using a WebSocket client (e.g., `wscat`).
|
||||||
- Test DNS record creation with various types (e.g., SRV, SOA) and check `local_dns.json`.
|
- Test DNS record creation with various types (e.g., SRV, SOA) and check `local_dns.json`.
|
||||||
- Monitor logs via WebSocket or the admin interface for errors.
|
- Monitor logs in the admin **Logs** tab (`subscribe-log` per channel) or `GET /api/logs/:channel`; plugin logs use `plugin-log` WebSocket messages.
|
||||||
+8
-8
@@ -126,7 +126,7 @@ The application layer enables rich functionality through plugins:
|
|||||||
- **Internal domains**: Plugins register domains (e.g., "peer.directory") that resolve to localhost
|
- **Internal domains**: Plugins register domains (e.g., "peer.directory") that resolve to localhost
|
||||||
- **HyperDB**: Distributed databases with automatic P2P replication
|
- **HyperDB**: Distributed databases with automatic P2P replication
|
||||||
- **Hyperdrive**: Distributed file systems for content hosting
|
- **Hyperdrive**: Distributed file systems for content hosting
|
||||||
- **Protomux channels**: Custom protocols for real-time peer communication
|
- **Plugin RPC (protomux-rpc)**: Named JSON methods for real-time peer communication between plugins
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -276,16 +276,16 @@ For file storage, plugins use Hyperdrive:
|
|||||||
- **Version history**: Full history of changes preserved
|
- **Version history**: Full history of changes preserved
|
||||||
- **Streaming support**: Large files can be streamed without full download
|
- **Streaming support**: Large files can be streamed without full download
|
||||||
|
|
||||||
### 6.4 Protomux Channels: Custom Protocols
|
### 6.4 Plugin RPC: Custom Protocols
|
||||||
|
|
||||||
For real-time communication, plugins register Protomux channels:
|
For real-time communication, plugins register protomux-rpc protocols via `sdk.channels`:
|
||||||
|
|
||||||
- **Protocol multiplexing**: Multiple protocols share a single connection
|
- **Protocol multiplexing**: Multiple RPC muxes share a single Hyperswarm connection
|
||||||
- **Typed messages**: JSON, string, or binary encoding
|
- **Named methods**: JSON request/response and fire-and-forget events (e.g. `chat.message`, `profile.updated`)
|
||||||
- **Bidirectional**: Both peers can send and receive
|
- **Bidirectional**: `request`, `event`, and `broadcast` between peers
|
||||||
- **Auto-reconnection**: Channels re-establish when peers reconnect
|
- **Auto-reconnection**: RPC sessions are recreated when peers reconnect (see admin **Plugin RPC** stats)
|
||||||
|
|
||||||
This enables chat applications, real-time collaboration, gaming, and any protocol requiring low-latency peer communication.
|
This enables chat, collaboration, live profile sync, and other low-latency peer protocols without HTTP. See [plugins/PLUGIN_CHANNELS.md](plugins/PLUGIN_CHANNELS.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+65
-396
@@ -22,8 +22,9 @@ Upgrade **all nodes and plugins together**. Mixed old (message channel + RPC) an
|
|||||||
| `broadcast('x', data)` | `broadcast('x', 'my.event', data)` |
|
| `broadcast('x', data)` | `broadcast('x', 'my.event', data)` |
|
||||||
| `channels.rpc.register` | `channels.register` with `methods` |
|
| `channels.rpc.register` | `channels.register` with `methods` |
|
||||||
| `send('x', peer, data)` | `event('x', peer, 'message', data)` or a named method |
|
| `send('x', peer, data)` | `event('x', peer, 'message', data)` or a named method |
|
||||||
|
| `closeChannel('x')` | `unregister('x')` |
|
||||||
|
|
||||||
## Basic Usage
|
## Basic usage
|
||||||
|
|
||||||
> **Note:** The SDK is available via `require('../../includes/plugins/sdk')` from `plugin-sites/`.
|
> **Note:** The SDK is available via `require('../../includes/plugins/sdk')` from `plugin-sites/`.
|
||||||
|
|
||||||
@@ -35,12 +36,14 @@ const sdk = require('../../includes/plugins/sdk');
|
|||||||
sdk.channels.register('chat', {
|
sdk.channels.register('chat', {
|
||||||
methods: {
|
methods: {
|
||||||
'chat.message': async (data, { peerId }) => {
|
'chat.message': async (data, { peerId }) => {
|
||||||
console.log(`Received from ${peerId}:`, data);
|
sdk.log.debug('chat', `From ${peerId}: ${JSON.stringify(data)}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
},
|
||||||
|
'chat.ping': async (_value, { peerId }) => ({ pong: true, peerId })
|
||||||
},
|
},
|
||||||
onPeerOpen: (peerId) => console.log(`Peer ${peerId} RPC ready`),
|
onPeerOpen: (peerId) => sdk.log.debug('chat', `RPC ready: ${peerId}`),
|
||||||
onPeerClose: (peerId) => console.log(`Peer ${peerId} disconnected`)
|
onPeerClose: (peerId) => sdk.log.debug('chat', `RPC closed: ${peerId}`),
|
||||||
|
autoReconnect: true
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -57,432 +60,98 @@ const sentCount = sdk.channels.broadcast('chat', 'chat.message', {
|
|||||||
|
|
||||||
Use `sdk.channels.isRpcReady('chat', peerId)` before sending if the peer just connected.
|
Use `sdk.channels.isRpcReady('chat', peerId)` before sending if the peer just connected.
|
||||||
|
|
||||||
### Getting Channel Information
|
### Protocol information
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Get channel info
|
const info = sdk.channels.getProtocol('chat'); // alias: getChannel()
|
||||||
const channelInfo = sdk.channels.getChannel('chat');
|
const protocols = sdk.channels.listProtocols(); // alias: listChannels()
|
||||||
|
|
||||||
// List all channels for this plugin
|
|
||||||
const channels = sdk.channels.listChannels();
|
|
||||||
|
|
||||||
// Get connected peers for a channel
|
|
||||||
const peers = sdk.channels.getConnectedPeers('chat');
|
const peers = sdk.channels.getConnectedPeers('chat');
|
||||||
|
const ready = sdk.channels.isRpcReady('chat', peerId);
|
||||||
// Check if a peer is connected
|
|
||||||
const isConnected = sdk.channels.isPeerConnected('chat', peerId);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Encoding Types
|
`getProtocol()` returns RPC-centric state: `transport: 'rpc'`, `peerChannels` map with `rpc` handles per peer (no legacy message `channel` object).
|
||||||
|
|
||||||
### JSON Encoding
|
## Register options
|
||||||
|
|
||||||
Best for structured data:
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `methods` | Map of method name → `async (value, { peerId, pluginDomain, protocol }) => result` |
|
||||||
|
| `onPeerOpen` | Called when RPC is open for a peer |
|
||||||
|
| `onPeerClose` | Called when RPC closes for a peer |
|
||||||
|
| `autoReconnect` | Recreate RPC when peer reconnects (default: `true`) |
|
||||||
|
|
||||||
```javascript
|
Method names must not start with `__p2ns.` (reserved for keepalive).
|
||||||
sdk.channels.createChannel('data', {
|
|
||||||
encoding: 'json',
|
|
||||||
onMessage: (data, peerId) => {
|
|
||||||
// data is automatically parsed as JSON
|
|
||||||
console.log(data.type, data.payload);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send JSON data
|
## Complete example: chat plugin
|
||||||
sdk.channels.send('data', peerId, {
|
|
||||||
type: 'update',
|
|
||||||
payload: { value: 42 }
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### String Encoding
|
|
||||||
|
|
||||||
Best for text messages:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
sdk.channels.createChannel('text', {
|
|
||||||
encoding: 'string',
|
|
||||||
onMessage: (data, peerId) => {
|
|
||||||
// data is a string
|
|
||||||
console.log(`Message: ${data}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send string
|
|
||||||
sdk.channels.send('text', peerId, 'Hello, world!');
|
|
||||||
```
|
|
||||||
|
|
||||||
### Binary Encoding
|
|
||||||
|
|
||||||
Best for binary data (files, images, etc.):
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
sdk.channels.createChannel('binary', {
|
|
||||||
encoding: 'binary',
|
|
||||||
onMessage: (data, peerId) => {
|
|
||||||
// data is a Buffer
|
|
||||||
console.log(`Received ${data.length} bytes`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send binary data
|
|
||||||
const buffer = Buffer.from('Hello', 'utf8');
|
|
||||||
sdk.channels.send('binary', peerId, buffer);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom Encoding
|
|
||||||
|
|
||||||
Use compact-encoding directly:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const c = require('compact-encoding');
|
|
||||||
|
|
||||||
// Create custom encoding
|
|
||||||
const customEncoding = {
|
|
||||||
encode: (state, value) => {
|
|
||||||
// Custom encode logic
|
|
||||||
},
|
|
||||||
decode: (state) => {
|
|
||||||
// Custom decode logic
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sdk.channels.createChannel('custom', {
|
|
||||||
encoding: customEncoding,
|
|
||||||
onMessage: (data, peerId) => {
|
|
||||||
// Handle custom encoded data
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Channel Options
|
|
||||||
|
|
||||||
### `encoding`
|
|
||||||
|
|
||||||
- **Type**: `string | Object`
|
|
||||||
- **Default**: `'string'`
|
|
||||||
- **Options**: `'json'`, `'string'`, `'binary'`, or custom encoding object
|
|
||||||
|
|
||||||
### `onMessage`
|
|
||||||
|
|
||||||
- **Type**: `Function(data, peerId, peer)`
|
|
||||||
- **Required**: No
|
|
||||||
- **Description**: Callback called when a message is received
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
onMessage: (data, peerId, peer) => {
|
|
||||||
// data: Decoded message data
|
|
||||||
// peerId: String peer ID
|
|
||||||
// peer: Peer object from protomux
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `onOpen`
|
|
||||||
|
|
||||||
- **Type**: `Function(peerId, channel)`
|
|
||||||
- **Required**: No
|
|
||||||
- **Description**: Callback called when a peer connects to the channel
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
onOpen: (peerId, channel) => {
|
|
||||||
// peerId: String peer ID
|
|
||||||
// channel: Protomux channel object
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `onClose`
|
|
||||||
|
|
||||||
- **Type**: `Function(peerId, channel)`
|
|
||||||
- **Required**: No
|
|
||||||
- **Description**: Callback called when a peer disconnects from the channel
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
onClose: (peerId, channel) => {
|
|
||||||
// peerId: String peer ID
|
|
||||||
// channel: Protomux channel object
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `autoReconnect`
|
|
||||||
|
|
||||||
- **Type**: `boolean`
|
|
||||||
- **Default**: `true`
|
|
||||||
- **Description**: Automatically recreate channels when peers reconnect
|
|
||||||
|
|
||||||
## Complete Example: Chat Plugin
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const sdk = require('../../includes/plugins/sdk');
|
const sdk = require('../../includes/plugins/sdk');
|
||||||
|
|
||||||
const messages = new Map(); // Store messages per peer
|
|
||||||
|
|
||||||
async function onInit() {
|
async function onInit() {
|
||||||
// Create chat channel
|
sdk.channels.register('chat', {
|
||||||
sdk.channels.createChannel('chat', {
|
methods: {
|
||||||
encoding: 'json',
|
'chat.message': async (data, { peerId }) => {
|
||||||
onMessage: (data, peerId) => {
|
sdk.websocket.broadcast({ type: 'chat', from: peerId, ...data });
|
||||||
if (data.type === 'message' && data.text) {
|
return null;
|
||||||
// Store message
|
|
||||||
if (!messages.has(peerId)) {
|
|
||||||
messages.set(peerId, []);
|
|
||||||
}
|
|
||||||
messages.get(peerId).push({
|
|
||||||
timestamp: Date.now(),
|
|
||||||
peerId,
|
|
||||||
text: data.text,
|
|
||||||
direction: 'incoming'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpen: (peerId) => {
|
onPeerOpen: (peerId) => {
|
||||||
sdk.log.info('chat', `Peer ${peerId} connected`);
|
sdk.channels.event('chat', peerId, 'chat.sync', { since: Date.now() });
|
||||||
},
|
|
||||||
onClose: (peerId) => {
|
|
||||||
sdk.log.info('chat', `Peer ${peerId} disconnected`);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMessage(peerId, text) {
|
|
||||||
// Send message
|
|
||||||
sdk.channels.send('chat', peerId, {
|
|
||||||
type: 'message',
|
|
||||||
text: text,
|
|
||||||
timestamp: Date.now()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Store locally
|
|
||||||
if (!messages.has(peerId)) {
|
|
||||||
messages.set(peerId, []);
|
|
||||||
}
|
|
||||||
messages.get(peerId).push({
|
|
||||||
timestamp: Date.now(),
|
|
||||||
peerId,
|
|
||||||
text,
|
|
||||||
direction: 'outgoing'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handler(req, res) {
|
|
||||||
const { path, query } = sdk.router.parseRequest(req);
|
|
||||||
|
|
||||||
if (path === 'api/send' && req.method === 'POST') {
|
|
||||||
// Handle send message API
|
|
||||||
let body = '';
|
|
||||||
req.on('data', chunk => { body += chunk.toString(); });
|
|
||||||
req.on('end', () => {
|
|
||||||
const { peerId, message } = JSON.parse(body);
|
|
||||||
sendMessage(peerId, message);
|
|
||||||
sdk.router.json(res, { success: true });
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Let static files handle other routes
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { handler, onInit };
|
|
||||||
```
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
### 1. Initialize Channels in `onInit`
|
|
||||||
|
|
||||||
Always create channels in the `onInit` hook to ensure they're ready when peers connect:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
async function onInit() {
|
|
||||||
sdk.channels.createChannel('my-channel', { /* ... */ });
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Handle Errors Gracefully
|
|
||||||
|
|
||||||
Always wrap channel operations in try-catch:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
try {
|
|
||||||
sdk.channels.send('chat', peerId, message);
|
|
||||||
} catch (err) {
|
|
||||||
sdk.log.error('my-plugin', `Failed to send: ${err.message}`);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Clean Up on Shutdown
|
|
||||||
|
|
||||||
Channels are automatically cleaned up, but you can clean up local state:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
async function onShutdown() {
|
async function onShutdown() {
|
||||||
// Channels are cleaned up automatically
|
sdk.channels.unregister('chat');
|
||||||
// Clean up local state
|
|
||||||
messages.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { handler, onInit, onShutdown };
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Use Appropriate Encoding
|
## Best practices
|
||||||
|
|
||||||
- Use `'json'` for structured data
|
1. **Register in `onInit`** so RPC is ready before peers attach.
|
||||||
- Use `'string'` for simple text
|
2. **Use explicit method names** (`domain.action`) instead of opaque blobs.
|
||||||
- Use `'binary'` for files or raw data
|
3. **Check `isRpcReady`** before `request` on freshly connected peers.
|
||||||
- Use custom encoding for specialized needs
|
4. **Unregister in `onShutdown`** to release handlers and peer state.
|
||||||
|
5. **Return JSON-serializable values** from request handlers; use `null` for fire-and-forget handlers.
|
||||||
|
|
||||||
### 5. Check Peer Connection
|
## Protocol naming
|
||||||
|
|
||||||
Before sending, check if peer is connected:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
if (sdk.channels.isPeerConnected('chat', peerId)) {
|
|
||||||
sdk.channels.send('chat', peerId, message);
|
|
||||||
} else {
|
|
||||||
sdk.log.warn('chat', `Peer ${peerId} not connected`);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Handle Reconnections
|
|
||||||
|
|
||||||
Channels automatically reconnect, but you may want to resend state:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
onOpen: (peerId) => {
|
|
||||||
// Send current state to newly connected peer
|
|
||||||
sdk.channels.send('chat', peerId, {
|
|
||||||
type: 'state',
|
|
||||||
data: getCurrentState()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Protocol Naming
|
|
||||||
|
|
||||||
Channels are automatically scoped to your plugin domain:
|
|
||||||
|
|
||||||
- Plugin domain: `peer.chat`
|
- Plugin domain: `peer.chat`
|
||||||
- Protocol: `chat`
|
- Protocol: `chat`
|
||||||
- Full protocol: `peer.chat-chat`
|
- Wire mux: `peer.chat-chat-rpc`
|
||||||
|
|
||||||
This prevents conflicts between plugins. You don't need to worry about the full protocol name - just use your protocol name in the SDK.
|
Use the short protocol name in the SDK; the manager adds the domain and `-rpc` suffix.
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
1. **Peer Must Be Connected**: You can only send to peers that are currently connected via Hyperswarm
|
|
||||||
2. **No Guaranteed Delivery**: Messages are sent over the network without delivery guarantees
|
|
||||||
3. **No Ordering Guarantees**: Messages may arrive out of order
|
|
||||||
4. **Size Limits**: Very large messages may be split or fail
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Channel Not Created
|
| Issue | Checks |
|
||||||
|
|-------|--------|
|
||||||
|
| RPC not registered | `PLUGIN_DOMAIN` set; `register()` in `onInit`; no reserved method names |
|
||||||
|
| Peer not receiving | Both nodes upgraded; `isRpcReady`; method name matches on both sides |
|
||||||
|
| `request` hangs | RPC open timeout; peer disconnected; handler throws |
|
||||||
|
|
||||||
- Check that `PLUGIN_DOMAIN` is set (should be automatic)
|
## API reference
|
||||||
- Verify channel creation in `onInit` hook
|
|
||||||
- Check logs for errors
|
|
||||||
|
|
||||||
### Messages Not Received
|
| Method | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `register(protocol, config)` | Register RPC protocol and handlers |
|
||||||
|
| `unregister(protocol)` | Tear down protocol |
|
||||||
|
| `request(protocol, peerId, method, value?, timeoutMs?)` | Request/response |
|
||||||
|
| `event(protocol, peerId, method, value?)` | Fire-and-forget |
|
||||||
|
| `broadcast(protocol, method, value)` | Fan-out event to all peers with open RPC |
|
||||||
|
| `getProtocol(protocol)` | Protocol + per-peer RPC state |
|
||||||
|
| `listProtocols()` | Registered protocol names |
|
||||||
|
| `getConnectedPeers(protocol)` | Peer IDs with attached RPC state |
|
||||||
|
| `isRpcReady(protocol, peerId)` | Whether RPC mux is open |
|
||||||
|
| `getPeerRpc(protocol, peerId)` | Underlying ProtomuxRPC instance |
|
||||||
|
|
||||||
- Verify peer is connected: `sdk.channels.isPeerConnected('protocol', peerId)`
|
Deprecated shims (`createChannel`, `send`, `sendAsync`, nested `channels.rpc`) may still exist but should not be used in new code.
|
||||||
- Check encoding matches between sender and receiver
|
|
||||||
- Verify `onMessage` handler is set correctly
|
|
||||||
|
|
||||||
### Channel Not Reconnecting
|
## See also
|
||||||
|
|
||||||
- Ensure `autoReconnect: true` (default)
|
|
||||||
- Check that peer is actually reconnecting
|
|
||||||
- Verify channel wasn't manually closed
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### `sdk.channels.createChannel(protocol, options)`
|
|
||||||
|
|
||||||
Create a new channel.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `protocol` (string): Protocol name
|
|
||||||
- `options` (object): Channel options
|
|
||||||
|
|
||||||
**Returns:** `boolean` - Direct `message.send(data)` result (`false` means send was not accepted)
|
|
||||||
|
|
||||||
### `sdk.channels.getChannel(protocol)`
|
|
||||||
|
|
||||||
Get channel information.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `protocol` (string): Protocol name
|
|
||||||
|
|
||||||
**Returns:** `Object | null` - Channel info or null
|
|
||||||
|
|
||||||
### `sdk.channels.listChannels()`
|
|
||||||
|
|
||||||
List all channels for this plugin.
|
|
||||||
|
|
||||||
**Returns:** `Array<string>` - Array of protocol names
|
|
||||||
|
|
||||||
### `sdk.channels.closeChannel(protocol)`
|
|
||||||
|
|
||||||
Close a channel.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `protocol` (string): Protocol name
|
|
||||||
|
|
||||||
**Returns:** `boolean` - Success status
|
|
||||||
|
|
||||||
### `sdk.channels.send(protocol, peerId, data)`
|
|
||||||
|
|
||||||
Send data to a specific peer.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `protocol` (string): Protocol name
|
|
||||||
- `peerId` (string): Target peer ID
|
|
||||||
- `data` (any): Data to send
|
|
||||||
|
|
||||||
**Returns:** `boolean` - Success status
|
|
||||||
|
|
||||||
### `sdk.channels.sendAsync(protocol, peerId, data, waitTimeout)`
|
|
||||||
|
|
||||||
Send data to a specific peer (async version that waits for bidirectional channel opening).
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `protocol` (string): Protocol name
|
|
||||||
- `peerId` (string): Target peer ID
|
|
||||||
- `data` (any): Data to send
|
|
||||||
- `waitTimeout` (number): Timeout to wait for channel to open in milliseconds (default: 5000)
|
|
||||||
|
|
||||||
**Returns:** `Promise<boolean>` - Direct `message.send(data)` result after waiting for `fullyOpened()`
|
|
||||||
|
|
||||||
**Note:** This method waits for the channel to be fully opened before sending, which is useful when you need to ensure the channel is ready. The regular `send()` method returns immediately and may fail if the channel isn't open yet or if backpressure prevents sending.
|
|
||||||
|
|
||||||
### `sdk.channels.broadcast(protocol, data)`
|
|
||||||
|
|
||||||
Broadcast data to all connected peers.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `protocol` (string): Protocol name
|
|
||||||
- `data` (any): Data to broadcast
|
|
||||||
|
|
||||||
**Returns:** `number` - Number of peers message was sent to
|
|
||||||
|
|
||||||
### `sdk.channels.getConnectedPeers(protocol)`
|
|
||||||
|
|
||||||
Get list of connected peers for a channel.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `protocol` (string): Protocol name
|
|
||||||
|
|
||||||
**Returns:** `Array<string>` - Array of peer IDs
|
|
||||||
|
|
||||||
### `sdk.channels.isPeerConnected(protocol, peerId)`
|
|
||||||
|
|
||||||
Check if a peer is connected to a channel.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `protocol` (string): Protocol name
|
|
||||||
- `peerId` (string): Peer ID
|
|
||||||
|
|
||||||
**Returns:** `boolean` - True if connected
|
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
- [Plugin System Documentation](README.md) - Complete plugin system guide
|
|
||||||
- [Plugin SDK Reference](PLUGIN_SDK.md) - Full SDK documentation
|
|
||||||
- [Example Plugin](../../plugin-sites/example.plugin/index.js) - Basic plugin example
|
|
||||||
|
|
||||||
|
- [Plugin SDK](PLUGIN_SDK.md)
|
||||||
|
- [Plugin system](README.md)
|
||||||
|
- [example.plugin](../../plugin-sites/example.plugin/index.js)
|
||||||
|
- [global.profile](../../plugin-sites/global.profile/index.js) — `profile.update` broadcast pattern
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ The P2NS Plugin SDK provides comprehensive access to P2NS system functionality.
|
|||||||
- [Plugin Information](#plugin-information)
|
- [Plugin Information](#plugin-information)
|
||||||
- [Security and Validation](#security-and-validation)
|
- [Security and Validation](#security-and-validation)
|
||||||
- [Authentication and Authorization](#authentication-and-authorization)
|
- [Authentication and Authorization](#authentication-and-authorization)
|
||||||
- [Protomux Channels](#protomux-channels)
|
- [Plugin RPC (protomux-rpc)](#plugin-rpc-protomux-rpc)
|
||||||
- [Database Operations (HyperDB)](#database-operations-hyperdb)
|
- [Database Operations (HyperDB)](#database-operations-hyperdb)
|
||||||
- [Hyperdrive Operations](#hyperdrive-operations)
|
- [Hyperdrive Operations](#hyperdrive-operations)
|
||||||
- [Admin Panel Registration](#admin-panel-registration)
|
- [Admin Panel Registration](#admin-panel-registration)
|
||||||
@@ -62,7 +62,7 @@ const ipMap = sdk.state.domainToIPMap;
|
|||||||
// Get all active Holesail connections (returns a new Map)
|
// Get all active Holesail connections (returns a new Map)
|
||||||
const holesails = sdk.state.holesails;
|
const holesails = sdk.state.holesails;
|
||||||
|
|
||||||
// Get peer channels (returns a new Map)
|
// Get swarm peer channels (returns a new Map; not plugin RPC — use sdk.channels for plugin protocols)
|
||||||
const peerChannels = sdk.state.peerChannels;
|
const peerChannels = sdk.state.peerChannels;
|
||||||
|
|
||||||
// Get peer metrics (returns a new Map)
|
// Get peer metrics (returns a new Map)
|
||||||
@@ -159,7 +159,7 @@ sdk.log.error('component', 'Error message');
|
|||||||
await sdk.log.close();
|
await sdk.log.close();
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** Plugin logs are automatically broadcast to the admin interface and displayed in real-time in the plugin's log terminal. Logs are also written to `app.log` in the plugin directory.
|
**Note:** Plugin logs go to `logs/plugins.log` on the host, `plugin-log` WebSocket messages (per-plugin terminal in the admin UI), and `app.log` in the plugin directory. They are not mixed into the core log stream.
|
||||||
|
|
||||||
## Core Operations
|
## Core Operations
|
||||||
|
|
||||||
@@ -2436,7 +2436,7 @@ module.exports = {
|
|||||||
- [PLUGINS.md](PLUGINS.md) - Plugin system overview
|
- [PLUGINS.md](PLUGINS.md) - Plugin system overview
|
||||||
- [RESTAPI.md](RESTAPI.md) - Plugin management API endpoints
|
- [RESTAPI.md](RESTAPI.md) - Plugin management API endpoints
|
||||||
- [plugins/HYPERDB.md](plugins/HYPERDB.md) - HyperDB database integration
|
- [plugins/HYPERDB.md](plugins/HYPERDB.md) - HyperDB database integration
|
||||||
- [plugins/PLUGIN_CHANNELS.md](plugins/PLUGIN_CHANNELS.md) - P2P communication channels
|
- [plugins/PLUGIN_CHANNELS.md](plugins/PLUGIN_CHANNELS.md) - Plugin protomux-rpc protocols
|
||||||
- [plugins/HYPERDRIVE.md](plugins/HYPERDRIVE.md) - Hyperdrive distributed file system
|
- [plugins/HYPERDRIVE.md](plugins/HYPERDRIVE.md) - Hyperdrive distributed file system
|
||||||
- [plugins/README.md](plugins/README.md) - Plugin system documentation (detailed)
|
- [plugins/README.md](plugins/README.md) - Plugin system documentation (detailed)
|
||||||
- [README.md](../README.md) - Main P2NS documentation
|
- [README.md](../README.md) - Main P2NS documentation
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ This directory contains comprehensive documentation for the P2NS plugin system:
|
|||||||
### SDK Features
|
### SDK Features
|
||||||
- **[HYPERDB.md](HYPERDB.md)** - HyperDB database integration for plugins
|
- **[HYPERDB.md](HYPERDB.md)** - HyperDB database integration for plugins
|
||||||
- **[HYPERDRIVE.md](HYPERDRIVE.md)** - Hyperdrive distributed file system for plugins
|
- **[HYPERDRIVE.md](HYPERDRIVE.md)** - Hyperdrive distributed file system for plugins
|
||||||
- **[PLUGIN_CHANNELS.md](PLUGIN_CHANNELS.md)** - P2P communication channels via Protomux
|
- **[PLUGIN_CHANNELS.md](PLUGIN_CHANNELS.md)** - Plugin peer protocols via protomux-rpc
|
||||||
|
|
||||||
### Example Plugins
|
### Example Plugins
|
||||||
- **[example.plugin.md](example.plugin.md)** - Example Plugin template documentation
|
- **[example.plugin.md](example.plugin.md)** - Example Plugin template documentation
|
||||||
@@ -225,7 +225,7 @@ const ip = sdk.state.getIPForDomain('example.tld');
|
|||||||
// Get all active Holesail connections
|
// Get all active Holesail connections
|
||||||
const holesails = sdk.state.holesails;
|
const holesails = sdk.state.holesails;
|
||||||
|
|
||||||
// Get peer channels
|
// Get swarm peer channels (plugin P2P uses sdk.channels, not this map)
|
||||||
const peerChannels = sdk.state.peerChannels;
|
const peerChannels = sdk.state.peerChannels;
|
||||||
|
|
||||||
// Get peer metrics
|
// Get peer metrics
|
||||||
@@ -279,7 +279,7 @@ sdk.log.warn('my-plugin', 'Warning message');
|
|||||||
sdk.log.error('my-plugin', 'Error message');
|
sdk.log.error('my-plugin', 'Error message');
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** Plugin logs are automatically broadcast to the admin interface and displayed in real-time in the plugin's log terminal. Logs are also written to `app.log` in the plugin directory.
|
**Note:** Plugin logs are written to `logs/plugins.log`, broadcast as `plugin-log` WebSocket messages (per-plugin terminal in admin), and appended to `plugin-sites/{domain}/app.log`.
|
||||||
|
|
||||||
### Core Operations
|
### Core Operations
|
||||||
|
|
||||||
@@ -945,7 +945,7 @@ The SDK provides comprehensive access to all P2NS functionality:
|
|||||||
- **`sdk.router`** - HTTP request parsing and response helpers
|
- **`sdk.router`** - HTTP request parsing and response helpers
|
||||||
- **`sdk.admin`** - Admin panel registration (actions, settings)
|
- **`sdk.admin`** - Admin panel registration (actions, settings)
|
||||||
- **`sdk.db`** - HyperDB database operations (see [HYPERDB.md](HYPERDB.md))
|
- **`sdk.db`** - HyperDB database operations (see [HYPERDB.md](HYPERDB.md))
|
||||||
- **`sdk.channels`** - P2P communication channels (see [PLUGIN_CHANNELS.md](PLUGIN_CHANNELS.md))
|
- **`sdk.channels`** - Plugin protomux-rpc protocols (see [PLUGIN_CHANNELS.md](PLUGIN_CHANNELS.md))
|
||||||
- **`sdk.drives`** - Hyperdrive distributed file system (see [HYPERDRIVE.md](HYPERDRIVE.md))
|
- **`sdk.drives`** - Hyperdrive distributed file system (see [HYPERDRIVE.md](HYPERDRIVE.md))
|
||||||
|
|
||||||
### Admin Panel Registration
|
### Admin Panel Registration
|
||||||
@@ -1030,7 +1030,7 @@ async handler(req, res) {
|
|||||||
## Best Practices
|
## Best Practices
|
||||||
|
|
||||||
1. **Error Handling**: Always wrap async operations in try-catch blocks
|
1. **Error Handling**: Always wrap async operations in try-catch blocks
|
||||||
2. **Logging**: Use the SDK logging functions instead of console.log (logs appear in admin interface)
|
2. **Logging**: Use `sdk.log` instead of `console.log` (admin Plugins tab + `logs/plugins.log` and per-plugin `app.log`)
|
||||||
3. **Resource Cleanup**: Implement `onShutdown()` to clean up resources
|
3. **Resource Cleanup**: Implement `onShutdown()` to clean up resources
|
||||||
4. **Security**: Validate and sanitize user input using `sdk.security`
|
4. **Security**: Validate and sanitize user input using `sdk.security`
|
||||||
5. **Performance**: Cache expensive operations when possible
|
5. **Performance**: Cache expensive operations when possible
|
||||||
@@ -1059,10 +1059,10 @@ Plugins can be managed via the admin interface at `https://p2ns.admin` in the Pl
|
|||||||
- **Static**: Plugin only serves static files (no handler)
|
- **Static**: Plugin only serves static files (no handler)
|
||||||
|
|
||||||
**Logs:**
|
**Logs:**
|
||||||
- Plugin logs are displayed in real-time in the plugin's log terminal
|
- Plugin logs appear in the Plugins tab terminal and in `logs/plugins.log` (all plugins) plus `plugin-sites/{domain}/app.log`
|
||||||
- Logs are automatically captured from `sdk.log` calls
|
- Logs are captured from `sdk.log` calls only (not `console.log`)
|
||||||
- Logs are also written to `app.log` in the plugin directory
|
|
||||||
- Log terminals are hidden by default and appear when you start/stop/restart a plugin
|
- Log terminals are hidden by default and appear when you start/stop/restart a plugin
|
||||||
|
- System-wide split logs (core, proxy, HTTP proxy, DNS, Holesail) are in the admin **Logs** tab — see [README_LONGFORM.md](../README_LONGFORM.md#logging-and-debugging)
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ async function handleLogsRoutes(req, res) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const match = urlPath.match(/^\/api\/logs\/([a-z]+)$/);
|
const match = urlPath.match(/^\/api\/logs\/([a-zA-Z]+)$/);
|
||||||
if (method === 'GET' && match) {
|
if (method === 'GET' && match) {
|
||||||
const channelId = match[1];
|
const channelId = match[1];
|
||||||
const channels = listLogChannels();
|
const channels = listLogChannels();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
- **[HyperDB Integration](../docs/plugins/HYPERDB.md)** - Database operations
|
- **[HyperDB Integration](../docs/plugins/HYPERDB.md)** - Database operations
|
||||||
- **[Hyperdrive Integration](../docs/plugins/HYPERDRIVE.md)** - Distributed file system
|
- **[Hyperdrive Integration](../docs/plugins/HYPERDRIVE.md)** - Distributed file system
|
||||||
- **[Plugin Channels](../docs/plugins/PLUGIN_CHANNELS.md)** - P2P communication
|
- **[Plugin RPC](../docs/plugins/PLUGIN_CHANNELS.md)** - protomux-rpc peer protocols
|
||||||
|
|
||||||
## Example Plugins
|
## Example Plugins
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ The plugin supports the following standard profile fields:
|
|||||||
- `profile-update`: Broadcast when a profile is created or updated
|
- `profile-update`: Broadcast when a profile is created or updated
|
||||||
- `profile-deleted`: Broadcast when a profile is deleted
|
- `profile-deleted`: Broadcast when a profile is deleted
|
||||||
- `replication-status`: Periodic updates about replication status
|
- `replication-status`: Periodic updates about replication status
|
||||||
- **P2P Channels**: Uses P2NS channels to broadcast profile updates across the network
|
- **Plugin RPC**: Uses `sdk.channels` to broadcast profile updates to peers (`profile-updates` protocol)
|
||||||
|
|
||||||
## Web Interface
|
## Web Interface
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ These scripts validate core HTTP surfaces on a running P2NS instance.
|
|||||||
- `npm run test:admin` checks `p2ns.admin` health/status/stats endpoints.
|
- `npm run test:admin` checks `p2ns.admin` health/status/stats endpoints.
|
||||||
- `npm run test:peer-paste` checks `peer.paste` health/stats/OpenAPI endpoints.
|
- `npm run test:peer-paste` checks `peer.paste` health/stats/OpenAPI endpoints.
|
||||||
- `npm run test:plugins` checks `peer.directory`, `global.profile`, and `file.drop` API endpoints.
|
- `npm run test:plugins` checks `peer.directory`, `global.profile`, and `file.drop` API endpoints.
|
||||||
- `npm test` runs all smoke scripts in sequence.
|
- `npm run test:plugin-rpc` runs `plugin-channel-rpc.test.js` (offline contract tests for protomux-rpc plugin channels; no running node required).
|
||||||
|
- `npm test` runs admin, peer-paste, and plugins smoke scripts in sequence (does not include `test:plugin-rpc`).
|
||||||
|
|
||||||
## Custom target URL
|
## Custom target URL
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user