move repos into monorepo
This commit is contained in:
146
bin/supervisor/docs/AUTH.md
Normal file
146
bin/supervisor/docs/AUTH.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Hero Supervisor Authentication
|
||||
|
||||
The Hero Supervisor now supports API key-based authentication with three permission scopes:
|
||||
|
||||
## Permission Scopes
|
||||
|
||||
1. **Admin** - Full access to all operations including key management
|
||||
2. **Registrar** - Can register new runners
|
||||
3. **User** - Can create and manage jobs
|
||||
|
||||
## Starting the Supervisor with an Admin Key
|
||||
|
||||
Bootstrap an initial admin key when starting the supervisor:
|
||||
|
||||
```bash
|
||||
cargo run --bin supervisor -- --bootstrap-admin-key "my-admin"
|
||||
```
|
||||
|
||||
This will output:
|
||||
|
||||
```
|
||||
╔════════════════════════════════════════════════════════════╗
|
||||
║ 🔑 Admin API Key Created ║
|
||||
╚════════════════════════════════════════════════════════════╝
|
||||
Name: my-admin
|
||||
Key: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
Scope: admin
|
||||
⚠️ SAVE THIS KEY - IT WILL NOT BE SHOWN AGAIN!
|
||||
╚════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
**IMPORTANT:** Save this key securely - it will not be displayed again!
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Verify API Key
|
||||
|
||||
Verify a key and get its metadata:
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:3030 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "auth.verify",
|
||||
"params": {
|
||||
"key": "your-api-key-here"
|
||||
},
|
||||
"id": 1
|
||||
}'
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"valid": true,
|
||||
"name": "my-admin",
|
||||
"scope": "admin"
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Create New API Key (Admin Only)
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:3030 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "auth.create_key",
|
||||
"params": {
|
||||
"admin_key": "your-admin-key",
|
||||
"name": "runner-bot",
|
||||
"scope": "registrar"
|
||||
},
|
||||
"id": 1
|
||||
}'
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"key": "new-generated-uuid",
|
||||
"name": "runner-bot",
|
||||
"scope": "registrar",
|
||||
"created_at": "2025-10-27T15:00:00Z",
|
||||
"expires_at": null
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
|
||||
### List All API Keys (Admin Only)
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:3030 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "auth.list_keys",
|
||||
"params": {
|
||||
"admin_key": "your-admin-key"
|
||||
},
|
||||
"id": 1
|
||||
}'
|
||||
```
|
||||
|
||||
### Remove API Key (Admin Only)
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:3030 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "auth.remove_key",
|
||||
"params": {
|
||||
"admin_key": "your-admin-key",
|
||||
"key": "key-to-remove"
|
||||
},
|
||||
"id": 1
|
||||
}'
|
||||
```
|
||||
|
||||
## Using Keys in the Admin UI
|
||||
|
||||
The admin UI will use the `auth.verify` endpoint during login to:
|
||||
1. Validate the provided API key
|
||||
2. Retrieve the key's name and scope
|
||||
3. Display the user's name and permissions in the header
|
||||
4. Show/hide UI elements based on scope
|
||||
|
||||
## Migration from Legacy Secrets
|
||||
|
||||
The supervisor still supports the legacy secret-based authentication for backward compatibility:
|
||||
- `--admin-secret` - Legacy admin secrets
|
||||
- `--user-secret` - Legacy user secrets
|
||||
- `--register-secret` - Legacy register secrets
|
||||
|
||||
However, the new API key system is recommended for better management and auditability.
|
||||
268
bin/supervisor/docs/MYCELIUM.md
Normal file
268
bin/supervisor/docs/MYCELIUM.md
Normal file
@@ -0,0 +1,268 @@
|
||||
# Mycelium Integration - Now Optional!
|
||||
|
||||
The Mycelium integration is now an optional feature. The supervisor can run with just the OpenRPC HTTP server, making it simpler to use and deploy.
|
||||
|
||||
## What Changed
|
||||
|
||||
### Before
|
||||
- Mycelium integration was always enabled
|
||||
- Supervisor would continuously try to connect to Mycelium on port 8990
|
||||
- Error logs if Mycelium wasn't available
|
||||
- Required additional dependencies
|
||||
|
||||
### After
|
||||
- ✅ Mycelium is now an optional feature
|
||||
- ✅ Supervisor runs with clean OpenRPC HTTP server by default
|
||||
- ✅ No connection errors when Mycelium isn't needed
|
||||
- ✅ Smaller binary size without Mycelium dependencies
|
||||
|
||||
## Running the Supervisor
|
||||
|
||||
### Option 1: Simple OpenRPC Server (Recommended)
|
||||
|
||||
**No Mycelium, just OpenRPC:**
|
||||
|
||||
```bash
|
||||
# Using the helper script
|
||||
./run_supervisor_simple.sh
|
||||
|
||||
# Or manually
|
||||
MYCELIUM_URL="" cargo run --bin supervisor -- \
|
||||
--redis-url redis://localhost:6379 \
|
||||
--port 3030
|
||||
```
|
||||
|
||||
This starts:
|
||||
- ✅ OpenRPC HTTP server on port 3030
|
||||
- ✅ Redis connection for job queuing
|
||||
- ❌ No Mycelium integration
|
||||
|
||||
### Option 2: With Mycelium Integration
|
||||
|
||||
**Enable Mycelium feature:**
|
||||
|
||||
```bash
|
||||
# Build with Mycelium support
|
||||
cargo build --bin supervisor --features mycelium
|
||||
|
||||
# Run with Mycelium URL
|
||||
MYCELIUM_URL="http://localhost:8990" cargo run --bin supervisor --features mycelium -- \
|
||||
--redis-url redis://localhost:6379 \
|
||||
--port 3030
|
||||
```
|
||||
|
||||
This starts:
|
||||
- ✅ OpenRPC HTTP server on port 3030
|
||||
- ✅ Redis connection for job queuing
|
||||
- ✅ Mycelium integration (connects to daemon)
|
||||
|
||||
## Feature Flags
|
||||
|
||||
### Available Features
|
||||
|
||||
| Feature | Description | Default |
|
||||
|---------|-------------|---------|
|
||||
| `cli` | Command-line interface | ✅ Yes |
|
||||
| `mycelium` | Mycelium integration | ❌ No |
|
||||
|
||||
### Building with Features
|
||||
|
||||
```bash
|
||||
# Default build (CLI only, no Mycelium)
|
||||
cargo build --bin supervisor
|
||||
|
||||
# With Mycelium
|
||||
cargo build --bin supervisor --features mycelium
|
||||
|
||||
# Minimal (no CLI, no Mycelium)
|
||||
cargo build --bin supervisor --no-default-features
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Without Mycelium (Default)
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Client │
|
||||
└────────┬────────┘
|
||||
│ HTTP/JSON-RPC
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Supervisor │
|
||||
│ OpenRPC Server │
|
||||
│ (Port 3030) │
|
||||
└────────┬────────┘
|
||||
│ Redis
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Runners │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### With Mycelium (Optional)
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Client │
|
||||
└────────┬────────┘
|
||||
│ HTTP/JSON-RPC
|
||||
▼
|
||||
┌─────────────────┐ ┌──────────────┐
|
||||
│ Supervisor │◄────►│ Mycelium │
|
||||
│ OpenRPC Server │ │ Daemon │
|
||||
│ (Port 3030) │ │ (Port 8990) │
|
||||
└────────┬────────┘ └──────────────┘
|
||||
│ Redis
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Runners │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Default | Required |
|
||||
|----------|-------------|---------|----------|
|
||||
| `MYCELIUM_URL` | Mycelium daemon URL | `http://127.0.0.1:8990` | No |
|
||||
| `RUST_LOG` | Log level | `info` | No |
|
||||
|
||||
**To disable Mycelium:**
|
||||
```bash
|
||||
export MYCELIUM_URL=""
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Core Dependencies (Always)
|
||||
- `tokio` - Async runtime
|
||||
- `redis` - Job queuing
|
||||
- `jsonrpsee` - OpenRPC server
|
||||
- `runner_rust` - Job model
|
||||
|
||||
### Mycelium Dependencies (Optional)
|
||||
- `reqwest` - HTTP client
|
||||
- `base64` - Encoding
|
||||
- `rand` - Random IDs
|
||||
|
||||
## Examples
|
||||
|
||||
All examples work without Mycelium:
|
||||
|
||||
```bash
|
||||
# Simple end-to-end example
|
||||
RUST_LOG=info cargo run --example simple_e2e
|
||||
|
||||
# Full automated demo
|
||||
RUST_LOG=info cargo run --example end_to_end_demo
|
||||
```
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### If you were using Mycelium
|
||||
|
||||
**Before:**
|
||||
```bash
|
||||
cargo run --bin supervisor
|
||||
# Would try to connect to Mycelium automatically
|
||||
```
|
||||
|
||||
**After:**
|
||||
```bash
|
||||
# Option A: Disable Mycelium (recommended for most use cases)
|
||||
MYCELIUM_URL="" cargo run --bin supervisor
|
||||
|
||||
# Option B: Enable Mycelium feature
|
||||
cargo run --bin supervisor --features mycelium
|
||||
```
|
||||
|
||||
### If you weren't using Mycelium
|
||||
|
||||
**Before:**
|
||||
```bash
|
||||
cargo run --bin supervisor
|
||||
# Would see connection errors to port 8990
|
||||
```
|
||||
|
||||
**After:**
|
||||
```bash
|
||||
cargo run --bin supervisor
|
||||
# Clean startup, no connection errors! 🎉
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
### For Development
|
||||
- ✅ Faster builds (fewer dependencies)
|
||||
- ✅ Simpler setup (no Mycelium daemon needed)
|
||||
- ✅ Cleaner logs (no connection errors)
|
||||
- ✅ Easier debugging
|
||||
|
||||
### For Production
|
||||
- ✅ Smaller binary size
|
||||
- ✅ Fewer runtime dependencies
|
||||
- ✅ More flexible deployment
|
||||
- ✅ Optional advanced features
|
||||
|
||||
## Testing
|
||||
|
||||
### Test without Mycelium
|
||||
```bash
|
||||
# Build
|
||||
cargo build --bin supervisor
|
||||
|
||||
# Run tests
|
||||
cargo test
|
||||
|
||||
# Run examples
|
||||
cargo run --example simple_e2e
|
||||
```
|
||||
|
||||
### Test with Mycelium
|
||||
```bash
|
||||
# Build with feature
|
||||
cargo build --bin supervisor --features mycelium
|
||||
|
||||
# Start Mycelium daemon (if you have one)
|
||||
# mycelium-daemon --port 8990
|
||||
|
||||
# Run supervisor
|
||||
MYCELIUM_URL="http://localhost:8990" cargo run --bin supervisor --features mycelium
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Mycelium integration not enabled"
|
||||
|
||||
This is informational, not an error. If you need Mycelium:
|
||||
|
||||
```bash
|
||||
cargo build --features mycelium
|
||||
```
|
||||
|
||||
### "HTTP request failed: error sending request"
|
||||
|
||||
If you see this with Mycelium enabled, check:
|
||||
1. Is Mycelium daemon running?
|
||||
2. Is the URL correct? (`MYCELIUM_URL`)
|
||||
3. Is the port accessible?
|
||||
|
||||
Or simply disable Mycelium:
|
||||
```bash
|
||||
export MYCELIUM_URL=""
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
🎉 **The supervisor now runs cleanly with just OpenRPC!**
|
||||
|
||||
- Default: OpenRPC HTTP server only
|
||||
- Optional: Enable Mycelium with `--features mycelium`
|
||||
- No more connection errors when Mycelium isn't needed
|
||||
- Simpler, faster, cleaner!
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ Complete
|
||||
**Version:** 0.1.0
|
||||
**Last Updated:** 2025-10-24
|
||||
214
bin/supervisor/docs/QUICK_START.md
Normal file
214
bin/supervisor/docs/QUICK_START.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Quick Start Guide
|
||||
|
||||
Complete guide to running the Hero Supervisor with OSIS runners and examples.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Redis** - Must be running
|
||||
2. **Rust** - Version 1.88+ (run `rustup update`)
|
||||
|
||||
## 1. Start Redis
|
||||
|
||||
```bash
|
||||
redis-server
|
||||
```
|
||||
|
||||
## 2. Start Supervisor
|
||||
|
||||
```bash
|
||||
cd /Users/timurgordon/code/git.ourworld.tf/herocode/supervisor
|
||||
cargo run --bin supervisor
|
||||
```
|
||||
|
||||
You should see:
|
||||
```
|
||||
╔════════════════════════════════════════════════════════════╗
|
||||
║ Hero Supervisor Started ║
|
||||
╚════════════════════════════════════════════════════════════╝
|
||||
📡 OpenRPC Server: http://127.0.0.1:3030
|
||||
🔗 Redis: redis://localhost:6379
|
||||
🌐 Mycelium: Not compiled (use --features mycelium)
|
||||
╚════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
## 3. Start OSIS Runner
|
||||
|
||||
```bash
|
||||
cd /Users/timurgordon/code/git.ourworld.tf/herocode/runner_rust
|
||||
cargo run --bin runner_osis -- test_runner \
|
||||
--redis-url redis://localhost:6379 \
|
||||
--db-path /tmp/test_runner.db
|
||||
```
|
||||
|
||||
You should see:
|
||||
```
|
||||
Starting OSIS Sync Runner with ID: test_runner
|
||||
Database path: /tmp/test_runner.db
|
||||
Redis URL: redis://localhost:6379
|
||||
OSIS Sync Runner 'test_runner' started successfully
|
||||
```
|
||||
|
||||
## 4. Run Example
|
||||
|
||||
```bash
|
||||
cd /Users/timurgordon/code/git.ourworld.tf/herocode/supervisor
|
||||
RUST_LOG=info cargo run --example simple_e2e
|
||||
```
|
||||
|
||||
## Terminal Layout
|
||||
|
||||
```
|
||||
┌─────────────────────┬─────────────────────┐
|
||||
│ Terminal 1 │ Terminal 2 │
|
||||
│ Redis │ Supervisor │
|
||||
│ redis-server │ cargo run --bin │
|
||||
│ │ supervisor │
|
||||
├─────────────────────┼─────────────────────┤
|
||||
│ Terminal 3 │ Terminal 4 │
|
||||
│ OSIS Runner │ Example │
|
||||
│ cargo run --bin │ cargo run │
|
||||
│ runner_osis │ --example │
|
||||
│ │ simple_e2e │
|
||||
└─────────────────────┴─────────────────────┘
|
||||
```
|
||||
|
||||
## What Each Component Does
|
||||
|
||||
### Redis
|
||||
- Job queue storage
|
||||
- Job result storage
|
||||
- Runner coordination
|
||||
|
||||
### Supervisor
|
||||
- OpenRPC HTTP server (port 3030)
|
||||
- Job dispatch to runners
|
||||
- Runner registration
|
||||
- Job execution coordination
|
||||
|
||||
### OSIS Runner
|
||||
- Listens for jobs on Redis queue
|
||||
- Executes Rhai scripts
|
||||
- Stores results back to Redis
|
||||
- Uses HeroDB for data persistence
|
||||
|
||||
### Example
|
||||
- Creates jobs with Rhai scripts
|
||||
- Sends jobs to supervisor via OpenRPC
|
||||
- Receives results
|
||||
- Demonstrates both blocking and non-blocking modes
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ Example │ (simple_e2e.rs)
|
||||
└──────┬──────┘
|
||||
│ HTTP/JSON-RPC
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ Supervisor │ (port 3030)
|
||||
└──────┬──────┘
|
||||
│ Redis Queue
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ OSIS Runner │ (test_runner)
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ HeroDB │ (Redis + local DB)
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Connection refused" on port 3030
|
||||
- Make sure supervisor is running
|
||||
- Check if another process is using port 3030
|
||||
|
||||
### "Connection refused" on port 6379
|
||||
- Make sure Redis is running
|
||||
- Check: `redis-cli ping` (should return "PONG")
|
||||
|
||||
### Runner not receiving jobs
|
||||
- Check runner is registered: Look for "Runner registered successfully" in example output
|
||||
- Check Redis connection: Both supervisor and runner must use same Redis URL
|
||||
- Check queue name matches: Should be `hero:q:work:type:osis:group:default:inst:test_runner`
|
||||
|
||||
### "Job execution timeout"
|
||||
- Increase timeout in job builder: `.timeout(120)`
|
||||
- Check if runner is actually processing jobs (look for logs)
|
||||
|
||||
## Example Output
|
||||
|
||||
### Successful Run
|
||||
|
||||
```
|
||||
╔════════════════════════════════════════╗
|
||||
║ Simple End-to-End Demo ║
|
||||
╚════════════════════════════════════════╝
|
||||
|
||||
📋 Step 1: Registering Runner
|
||||
─────────────────────────────────────────
|
||||
✅ Runner registered successfully
|
||||
|
||||
📋 Step 2: Running a Simple Job (Blocking)
|
||||
─────────────────────────────────────────
|
||||
✅ Job completed!
|
||||
Result: {"message":"Hello from the runner!","number":42}
|
||||
|
||||
📋 Step 3: Running a Calculation Job
|
||||
─────────────────────────────────────────
|
||||
✅ Calculation completed!
|
||||
Result: {"sum":55,"product":3628800,"count":10}
|
||||
|
||||
📋 Step 4: Starting a Non-Blocking Job
|
||||
─────────────────────────────────────────
|
||||
✅ Job started!
|
||||
Job ID: abc-123 (running in background)
|
||||
|
||||
🎉 Demo completed successfully!
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Try different Rhai scripts** - Modify the payload in examples
|
||||
2. **Add more runners** - Start multiple runners with different IDs
|
||||
3. **Explore the API** - Use the OpenRPC client library
|
||||
4. **Build your own client** - See `client/` for examples
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
# Check Redis
|
||||
redis-cli ping
|
||||
|
||||
# List Redis keys
|
||||
redis-cli keys "hero:*"
|
||||
|
||||
# Monitor Redis commands
|
||||
redis-cli monitor
|
||||
|
||||
# Check supervisor is running
|
||||
curl http://localhost:3030
|
||||
|
||||
# View runner logs
|
||||
# (check terminal where runner is running)
|
||||
```
|
||||
|
||||
## Clean Up
|
||||
|
||||
```bash
|
||||
# Stop all processes (Ctrl+C in each terminal)
|
||||
|
||||
# Clean up test database
|
||||
rm /tmp/test_runner.db
|
||||
|
||||
# (Optional) Flush Redis
|
||||
redis-cli FLUSHALL
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ Ready to Use
|
||||
**Last Updated:** 2025-10-24
|
||||
58
bin/supervisor/docs/RESTRUCTURE.md
Normal file
58
bin/supervisor/docs/RESTRUCTURE.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Repository Restructure
|
||||
|
||||
## Changes Made
|
||||
|
||||
The supervisor repository has been restructured to follow a cleaner organization:
|
||||
|
||||
### Before:
|
||||
```
|
||||
supervisor/
|
||||
├── clients/
|
||||
│ ├── openrpc/ # OpenRPC client library
|
||||
│ └── admin-ui/ # Admin UI (Yew WASM app)
|
||||
├── src/ # Main supervisor library
|
||||
└── cmd/ # Supervisor binary
|
||||
```
|
||||
|
||||
### After:
|
||||
```
|
||||
supervisor/
|
||||
├── client/ # OpenRPC client library (renamed from clients/openrpc)
|
||||
├── ui/ # Admin UI (renamed from clients/admin-ui)
|
||||
├── src/ # Main supervisor library
|
||||
└── cmd/ # Supervisor binary
|
||||
```
|
||||
|
||||
## Package Names
|
||||
|
||||
The package names remain unchanged:
|
||||
- **Client**: `hero-supervisor-openrpc-client`
|
||||
- **UI**: `supervisor-admin-ui`
|
||||
- **Main**: `hero-supervisor`
|
||||
|
||||
## Git Dependencies
|
||||
|
||||
External projects using Git URLs will automatically pick up the new structure:
|
||||
|
||||
```toml
|
||||
# This continues to work
|
||||
hero-supervisor-openrpc-client = { git = "https://git.ourworld.tf/herocode/supervisor.git" }
|
||||
```
|
||||
|
||||
Cargo will find the package by name regardless of its location in the repository.
|
||||
|
||||
## Local Path Dependencies
|
||||
|
||||
If you have local path dependencies, update them:
|
||||
|
||||
```toml
|
||||
# Old
|
||||
hero-supervisor-openrpc-client = { path = "../supervisor/clients/openrpc" }
|
||||
|
||||
# New
|
||||
hero-supervisor-openrpc-client = { path = "../supervisor/client" }
|
||||
```
|
||||
|
||||
## Scripts and Documentation
|
||||
|
||||
All references in scripts, documentation, and examples have been updated to reflect the new structure.
|
||||
333
bin/supervisor/docs/job-api-convention.md
Normal file
333
bin/supervisor/docs/job-api-convention.md
Normal file
@@ -0,0 +1,333 @@
|
||||
# Hero Supervisor Job API Convention
|
||||
|
||||
## Overview
|
||||
|
||||
The Hero Supervisor OpenRPC API follows a consistent naming convention for job-related operations:
|
||||
|
||||
- **`jobs.`** - General job operations (plural)
|
||||
- **`job.`** - Specific job operations (singular)
|
||||
|
||||
This convention provides a clear distinction between operations that work with multiple jobs or create new jobs versus operations that work with a specific existing job.
|
||||
|
||||
## API Methods
|
||||
|
||||
### General Job Operations (`jobs.`)
|
||||
|
||||
#### `jobs.create`
|
||||
Creates a new job without immediately queuing it to a runner.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job` (Job object): Complete job specification
|
||||
|
||||
**Returns:**
|
||||
- `job_id` (string): Unique identifier of the created job
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "jobs.create",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job": {
|
||||
"id": "job-123",
|
||||
"caller_id": "client-1",
|
||||
"context_id": "context-1",
|
||||
"payload": "print('Hello World')",
|
||||
"executor": "osis",
|
||||
"runner": "osis-runner-1",
|
||||
"timeout": 300,
|
||||
"env_vars": {},
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"updated_at": "2023-01-01T00:00:00Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `jobs.list`
|
||||
Lists all jobs in the system with full details.
|
||||
|
||||
**Parameters:** None
|
||||
|
||||
**Returns:**
|
||||
- `jobs` (array of Job objects): List of all jobs with complete information
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "jobs.list",
|
||||
"params": []
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "job-123",
|
||||
"caller_id": "client-1",
|
||||
"context_id": "context-1",
|
||||
"payload": "print('Hello World')",
|
||||
"executor": "osis",
|
||||
"runner": "osis-runner-1",
|
||||
"timeout": 300,
|
||||
"env_vars": {},
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"updated_at": "2023-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Specific Job Operations (`job.`)
|
||||
|
||||
#### `job.run`
|
||||
Runs a job immediately on the appropriate runner and returns the result.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job` (Job object): Complete job specification
|
||||
|
||||
**Returns:**
|
||||
- `result` (JobResult): Either success or error result
|
||||
|
||||
**JobResult Format:**
|
||||
```json
|
||||
// Success case
|
||||
{
|
||||
"success": "Job completed successfully with output..."
|
||||
}
|
||||
|
||||
// Error case
|
||||
{
|
||||
"error": "Job failed with error message..."
|
||||
}
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.run",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job": { /* job object */ }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.start`
|
||||
Starts a previously created job by queuing it to its assigned runner.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job_id` (string): ID of the job to start
|
||||
|
||||
**Returns:** `null` (void)
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.start",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job_id": "job-123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.status`
|
||||
Gets the current status of a job.
|
||||
|
||||
**Parameters:**
|
||||
- `job_id` (string): ID of the job to check
|
||||
|
||||
**Returns:**
|
||||
- `status` (JobStatusResponse): Current job status information
|
||||
|
||||
**JobStatusResponse Format:**
|
||||
```json
|
||||
{
|
||||
"job_id": "job-123",
|
||||
"status": "running",
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"started_at": "2023-01-01T00:00:05Z",
|
||||
"completed_at": null
|
||||
}
|
||||
```
|
||||
|
||||
**Status Values:**
|
||||
- `created` - Job has been created but not queued
|
||||
- `queued` - Job has been queued to a runner
|
||||
- `running` - Job is currently executing
|
||||
- `completed` - Job finished successfully
|
||||
- `failed` - Job failed with an error
|
||||
- `timeout` - Job timed out
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.status",
|
||||
"params": ["job-123"]
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.result`
|
||||
Gets the result of a completed job. This method blocks until the result is available.
|
||||
|
||||
**Parameters:**
|
||||
- `job_id` (string): ID of the job to get results for
|
||||
|
||||
**Returns:**
|
||||
- `result` (JobResult): Either success or error result
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.result",
|
||||
"params": ["job-123"]
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.stop`
|
||||
Stops a running job.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job_id` (string): ID of the job to stop
|
||||
|
||||
**Returns:** `null` (void)
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.stop",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job_id": "job-123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `job.delete`
|
||||
Deletes a job from the system.
|
||||
|
||||
**Parameters:**
|
||||
- `secret` (string): Authentication secret (admin or user)
|
||||
- `job_id` (string): ID of the job to delete
|
||||
|
||||
**Returns:** `null` (void)
|
||||
|
||||
**Usage:**
|
||||
```json
|
||||
{
|
||||
"method": "job.delete",
|
||||
"params": {
|
||||
"secret": "your-secret",
|
||||
"job_id": "job-123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Workflow Examples
|
||||
|
||||
### Fire-and-Forget Job
|
||||
```javascript
|
||||
// Create and immediately run a job
|
||||
const result = await client.job_run(secret, jobSpec);
|
||||
if (result.success) {
|
||||
console.log("Job completed:", result.success);
|
||||
} else {
|
||||
console.error("Job failed:", result.error);
|
||||
}
|
||||
```
|
||||
|
||||
### Asynchronous Job Processing
|
||||
```javascript
|
||||
// 1. Create the job
|
||||
const jobId = await client.jobs_create(secret, jobSpec);
|
||||
|
||||
// 2. Start the job
|
||||
await client.job_start(secret, jobId);
|
||||
|
||||
// 3. Poll for completion (non-blocking)
|
||||
let status;
|
||||
do {
|
||||
status = await client.job_status(jobId);
|
||||
if (status.status === 'running') {
|
||||
await sleep(1000); // Wait 1 second
|
||||
}
|
||||
} while (status.status === 'running' || status.status === 'queued');
|
||||
|
||||
// 4. Get the result
|
||||
const result = await client.job_result(jobId);
|
||||
```
|
||||
|
||||
### Batch Job Management
|
||||
```javascript
|
||||
// Create multiple jobs
|
||||
const jobIds = [];
|
||||
for (const jobSpec of jobSpecs) {
|
||||
const jobId = await client.jobs_create(secret, jobSpec);
|
||||
jobIds.push(jobId);
|
||||
}
|
||||
|
||||
// Start all jobs
|
||||
for (const jobId of jobIds) {
|
||||
await client.job_start(secret, jobId);
|
||||
}
|
||||
|
||||
// Monitor progress
|
||||
const results = [];
|
||||
for (const jobId of jobIds) {
|
||||
const result = await client.job_result(jobId); // Blocks until complete
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
// Optional: Stop or delete jobs if needed
|
||||
for (const jobId of jobIds) {
|
||||
await client.job_stop(secret, jobId); // Stop running job
|
||||
await client.job_delete(secret, jobId); // Delete from system
|
||||
}
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
All job operations require authentication using one of the following secret types:
|
||||
|
||||
- **Admin secrets**: Full access to all operations
|
||||
- **User secrets**: Access to job operations (`jobs.create`, `job.run`, `job.start`)
|
||||
- **Register secrets**: Only access to runner registration
|
||||
|
||||
## Error Handling
|
||||
|
||||
All methods return standard JSON-RPC error responses for:
|
||||
|
||||
- **Authentication errors** (-32602): Invalid or missing secrets
|
||||
- **Job not found errors** (-32000): Job ID doesn't exist
|
||||
- **Internal errors** (-32603): Server-side processing errors
|
||||
|
||||
## Migration from Legacy API
|
||||
|
||||
### Old → New Method Names
|
||||
|
||||
| Legacy Method | New Method | Notes |
|
||||
|---------------|------------|-------|
|
||||
| `run_job` | `job.run` | Same functionality, new naming |
|
||||
| `list_jobs` | `jobs.list` | Same functionality, new naming |
|
||||
| `create_job` | `jobs.create` | Enhanced to not auto-queue |
|
||||
|
||||
### New Methods Added
|
||||
|
||||
- `job.start` - Start a created job
|
||||
- `job.stop` - Stop a running job
|
||||
- `job.delete` - Delete a job from the system
|
||||
- `job.status` - Get job status (non-blocking)
|
||||
- `job.result` - Get job result (blocking)
|
||||
|
||||
### API Changes
|
||||
|
||||
- **Job struct**: Replaced `job_type` field with `executor`
|
||||
- **jobs.list**: Now returns full Job objects instead of just job IDs
|
||||
- **Enhanced job lifecycle**: Added stop and delete operations
|
||||
|
||||
This provides much more granular control over job lifecycle management.
|
||||
391
bin/supervisor/docs/openrpc.json
Normal file
391
bin/supervisor/docs/openrpc.json
Normal file
@@ -0,0 +1,391 @@
|
||||
{
|
||||
"openrpc": "1.3.2",
|
||||
"info": {
|
||||
"title": "Hero Supervisor OpenRPC API",
|
||||
"version": "1.0.0",
|
||||
"description": "OpenRPC API for managing Hero Supervisor runners and jobs. Job operations follow the convention: 'jobs.' for general operations and 'job.' for specific job operations."
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Job": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"caller_id": { "type": "string" },
|
||||
"context_id": { "type": "string" },
|
||||
"payload": { "type": "string" },
|
||||
"runner": { "type": "string" },
|
||||
"executor": { "type": "string" },
|
||||
"timeout": { "type": "number" },
|
||||
"env_vars": { "type": "object" },
|
||||
"created_at": { "type": "string" },
|
||||
"updated_at": { "type": "string" }
|
||||
},
|
||||
"required": ["id", "caller_id", "context_id", "payload", "runner", "executor", "timeout", "env_vars", "created_at", "updated_at"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"methods": [
|
||||
{
|
||||
"name": "list_runners",
|
||||
"description": "List all registered runners",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "runners",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "register_runner",
|
||||
"description": "Register a new runner to the supervisor with secret authentication",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"name": { "type": "string" },
|
||||
"queue": { "type": "string" }
|
||||
},
|
||||
"required": ["secret", "name", "queue"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jobs.create",
|
||||
"description": "Create a new job without queuing it to a runner",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job": {
|
||||
"$ref": "#/components/schemas/Job"
|
||||
}
|
||||
},
|
||||
"required": ["secret", "job"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "job_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jobs.list",
|
||||
"description": "List all jobs",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "jobs",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/components/schemas/Job" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.run",
|
||||
"description": "Run a job on the appropriate runner and return the result",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job": {
|
||||
"$ref": "#/components/schemas/Job"
|
||||
}
|
||||
},
|
||||
"required": ["secret", "job"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": { "type": "string" }
|
||||
},
|
||||
"required": ["success"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": { "type": "string" }
|
||||
},
|
||||
"required": ["error"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.start",
|
||||
"description": "Start a previously created job by queuing it to its assigned runner",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job_id": { "type": "string" }
|
||||
},
|
||||
"required": ["secret", "job_id"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.status",
|
||||
"description": "Get the current status of a job",
|
||||
"params": [
|
||||
{
|
||||
"name": "job_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "status",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"job_id": { "type": "string" },
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["created", "queued", "running", "completed", "failed", "timeout"]
|
||||
},
|
||||
"created_at": { "type": "string" },
|
||||
"started_at": { "type": ["string", "null"] },
|
||||
"completed_at": { "type": ["string", "null"] }
|
||||
},
|
||||
"required": ["job_id", "status", "created_at"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.result",
|
||||
"description": "Get the result of a completed job (blocks until result is available)",
|
||||
"params": [
|
||||
{
|
||||
"name": "job_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": { "type": "string" }
|
||||
},
|
||||
"required": ["success"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": { "type": "string" }
|
||||
},
|
||||
"required": ["error"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "remove_runner",
|
||||
"description": "Remove a runner from the supervisor",
|
||||
"params": [
|
||||
{
|
||||
"name": "actor_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "start_runner",
|
||||
"description": "Start a specific runner",
|
||||
"params": [
|
||||
{
|
||||
"name": "actor_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "stop_runner",
|
||||
"description": "Stop a specific runner",
|
||||
"params": [
|
||||
{
|
||||
"name": "actor_id",
|
||||
"schema": { "type": "string" }
|
||||
},
|
||||
{
|
||||
"name": "force",
|
||||
"schema": { "type": "boolean" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get_runner_status",
|
||||
"description": "Get the status of a specific runner",
|
||||
"params": [
|
||||
{
|
||||
"name": "actor_id",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "status",
|
||||
"schema": { "type": "object" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get_all_runner_status",
|
||||
"description": "Get status of all runners",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "statuses",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": { "type": "object" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "start_all",
|
||||
"description": "Start all runners",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "results",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "stop_all",
|
||||
"description": "Stop all runners",
|
||||
"params": [
|
||||
{
|
||||
"name": "force",
|
||||
"schema": { "type": "boolean" }
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "results",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get_all_status",
|
||||
"description": "Get status of all runners (alternative format)",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "statuses",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.stop",
|
||||
"description": "Stop a running job",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job_id": { "type": "string" }
|
||||
},
|
||||
"required": ["secret", "job_id"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "job.delete",
|
||||
"description": "Delete a job from the system",
|
||||
"params": [
|
||||
{
|
||||
"name": "params",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secret": { "type": "string" },
|
||||
"job_id": { "type": "string" }
|
||||
},
|
||||
"required": ["secret", "job_id"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "result",
|
||||
"schema": { "type": "null" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rpc.discover",
|
||||
"description": "OpenRPC discovery method - returns the OpenRPC document describing this API",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "openrpc_document",
|
||||
"schema": { "type": "object" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
80
bin/supervisor/docs/test_keypairs.md
Normal file
80
bin/supervisor/docs/test_keypairs.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Test Keypairs for Supervisor Auth
|
||||
|
||||
These are secp256k1 keypairs for testing the supervisor authentication system.
|
||||
|
||||
## Keypair 1 (Alice - Admin)
|
||||
```
|
||||
Private Key: 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
|
||||
Public Key: 0x04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235
|
||||
Address: 0x1234567890abcdef1234567890abcdef12345678
|
||||
```
|
||||
|
||||
## Keypair 2 (Bob - User)
|
||||
```
|
||||
Private Key: 0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321
|
||||
Public Key: 0x04d0de0aaeaefad02b8bdf8a56451a9852d7f851fee0cc8b4d42f3a0a4c3c2f66c1e5e3e8e3c3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e
|
||||
Address: 0xfedcba0987654321fedcba0987654321fedcba09
|
||||
```
|
||||
|
||||
## Keypair 3 (Charlie - Register)
|
||||
```
|
||||
Private Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
Public Key: 0x04e68acfc0253a10620dff706b0a1b1f1f5833ea3beb3bde6250d4e5e1e283bb4e9504be11a68d7a263f8e2000d1f8b8c5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e
|
||||
Address: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
```
|
||||
|
||||
## Keypair 4 (Dave - Test)
|
||||
```
|
||||
Private Key: 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
Public Key: 0x04f71e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e8f6c7e
|
||||
Address: 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
```
|
||||
|
||||
## Keypair 5 (Eve - Test)
|
||||
```
|
||||
Private Key: 0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
Public Key: 0x04a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0
|
||||
Address: 0xcccccccccccccccccccccccccccccccccccccccc
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Using with OpenRPC Client
|
||||
|
||||
```rust
|
||||
use secp256k1::{Secp256k1, SecretKey};
|
||||
use hex;
|
||||
|
||||
// Alice's private key
|
||||
let alice_privkey = SecretKey::from_slice(
|
||||
&hex::decode("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef").unwrap()
|
||||
).unwrap();
|
||||
|
||||
// Sign a message
|
||||
let secp = Secp256k1::new();
|
||||
let message = "Hello, Supervisor!";
|
||||
// ... sign with alice_privkey
|
||||
```
|
||||
|
||||
### Using with Admin UI
|
||||
|
||||
You can use the public keys as identifiers when creating API keys:
|
||||
- Alice: `0x04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd...`
|
||||
- Bob: `0x04d0de0aaeaefad02b8bdf8a56451a9852d7f851fee0cc8b4d42f3a0a4c3c2f66c...`
|
||||
|
||||
### Testing Different Scopes
|
||||
|
||||
1. **Admin Scope** - Use Alice's keypair for full admin access
|
||||
2. **User Scope** - Use Bob's keypair for limited user access
|
||||
3. **Register Scope** - Use Charlie's keypair for runner registration only
|
||||
|
||||
## Notes
|
||||
|
||||
⚠️ **WARNING**: These are TEST keypairs only! Never use these in production!
|
||||
|
||||
The private keys are intentionally simple patterns for easy testing:
|
||||
- Alice: All 0x12...ef pattern
|
||||
- Bob: Reverse pattern 0xfe...21
|
||||
- Charlie: All 0xaa
|
||||
- Dave: All 0xbb
|
||||
- Eve: All 0xcc
|
||||
Reference in New Issue
Block a user