security: remove all hardcoded API keys, require from environment

This commit is contained in:
oib
2026-02-11 21:33:18 +01:00
parent b36e5a33ea
commit 15675390ac
46 changed files with 107 additions and 107 deletions

View File

@@ -2,9 +2,9 @@ APP_ENV=dev
APP_HOST=127.0.0.1
APP_PORT=8011
DATABASE_URL=sqlite:///./coordinator.db
CLIENT_API_KEYS=REDACTED_CLIENT_KEY,client_dev_key_2
MINER_API_KEYS=REDACTED_MINER_KEY,miner_dev_key_2
ADMIN_API_KEYS=REDACTED_ADMIN_KEY
CLIENT_API_KEYS=${CLIENT_API_KEY},client_dev_key_2
MINER_API_KEYS=${MINER_API_KEY},miner_dev_key_2
ADMIN_API_KEYS=${ADMIN_API_KEY}
HMAC_SECRET=change_me
ALLOW_ORIGINS=*
JOB_TTL_SECONDS=900

View File

@@ -11,9 +11,9 @@ class Settings(BaseSettings):
database_url: str = "sqlite:///./coordinator.db"
client_api_keys: List[str] = ["REDACTED_CLIENT_KEY"]
miner_api_keys: List[str] = ["REDACTED_MINER_KEY"]
admin_api_keys: List[str] = ["REDACTED_ADMIN_KEY"]
client_api_keys: List[str] = []
miner_api_keys: List[str] = []
admin_api_keys: List[str] = []
hmac_secret: Optional[str] = None
allow_origins: List[str] = ["*"]

View File

@@ -26,7 +26,7 @@ def test_receipt_endpoint_returns_signed_receipt(test_client: TestClient):
resp = test_client.post(
"/v1/miners/register",
json={"capabilities": {"price": 1}, "concurrency": 1},
headers={"X-Api-Key": "REDACTED_MINER_KEY"},
headers={"X-Api-Key": "${MINER_API_KEY}"},
)
assert resp.status_code == 200
@@ -37,7 +37,7 @@ def test_receipt_endpoint_returns_signed_receipt(test_client: TestClient):
resp = test_client.post(
"/v1/jobs",
json=job_payload,
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"},
headers={"X-Api-Key": "${CLIENT_API_KEY}"},
)
assert resp.status_code == 201
job_id = resp.json()["job_id"]
@@ -46,7 +46,7 @@ def test_receipt_endpoint_returns_signed_receipt(test_client: TestClient):
poll_resp = test_client.post(
"/v1/miners/poll",
json={"max_wait_seconds": 1},
headers={"X-Api-Key": "REDACTED_MINER_KEY"},
headers={"X-Api-Key": "${MINER_API_KEY}"},
)
assert poll_resp.status_code in (200, 204)
@@ -58,7 +58,7 @@ def test_receipt_endpoint_returns_signed_receipt(test_client: TestClient):
result_resp = test_client.post(
f"/v1/miners/{job_id}/result",
json=result_payload,
headers={"X-Api-Key": "REDACTED_MINER_KEY"},
headers={"X-Api-Key": "${MINER_API_KEY}"},
)
assert result_resp.status_code == 200
signed_receipt = result_resp.json()["receipt"]
@@ -67,7 +67,7 @@ def test_receipt_endpoint_returns_signed_receipt(test_client: TestClient):
# fetch receipt via client endpoint
receipt_resp = test_client.get(
f"/v1/jobs/{job_id}/receipt",
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"},
headers={"X-Api-Key": "${CLIENT_API_KEY}"},
)
assert receipt_resp.status_code == 200
payload = receipt_resp.json()

View File

@@ -812,7 +812,7 @@
// Display demo offers
displayGPUOffers([{
id: '1',
provider: 'REDACTED_MINER_KEY',
provider: '${MINER_API_KEY}',
capacity: 1,
price: 50,
attributes: {

View File

@@ -13,7 +13,7 @@ class Settings(BaseSettings):
debug: bool = Field(default=False)
coordinator_base_url: str = Field(default="http://localhost:8011", alias="COORDINATOR_BASE_URL")
coordinator_api_key: str = Field(default="REDACTED_CLIENT_KEY", alias="COORDINATOR_API_KEY")
coordinator_api_key: str = Field(default="${CLIENT_API_KEY}", alias="COORDINATOR_API_KEY")
rest_prefix: str = Field(default="/v1", alias="REST_PREFIX")
ledger_db_path: Path = Field(default=Path("./data/wallet_ledger.db"), alias="LEDGER_DB_PATH")

View File

@@ -105,8 +105,8 @@ python3 client.py --url http://localhost:8000 --api-key your_key submit inferenc
```
Default credentials:
- Client API Key: `REDACTED_CLIENT_KEY`
- Miner API Key: `REDACTED_MINER_KEY`
- Client API Key: `${CLIENT_API_KEY}`
- Miner API Key: `${MINER_API_KEY}`
## Examples

View File

@@ -12,7 +12,7 @@ from typing import Optional
# Configuration
DEFAULT_COORDINATOR = "http://127.0.0.1:18000"
DEFAULT_API_KEY = "REDACTED_CLIENT_KEY"
DEFAULT_API_KEY = "${CLIENT_API_KEY}"
class AITBCClient:
def __init__(self, coordinator_url: str, api_key: str):

View File

@@ -13,7 +13,7 @@ from typing import Optional
# Configuration
DEFAULT_COORDINATOR = "http://localhost:8001"
DEFAULT_API_KEY = "REDACTED_MINER_KEY"
DEFAULT_API_KEY = "${MINER_API_KEY}"
DEFAULT_MINER_ID = "cli-miner"
class AITBCMiner:

View File

@@ -11,7 +11,7 @@ import sys
# Configuration
DEFAULT_COORDINATOR = "http://localhost:8001"
DEFAULT_API_KEY = "REDACTED_MINER_KEY"
DEFAULT_API_KEY = "${MINER_API_KEY}"
DEFAULT_MINER_ID = "localhost-gpu-miner"
def test_miner_registration(coordinator_url):
@@ -72,7 +72,7 @@ def test_job_processing(coordinator_url):
f"{coordinator_url}/v1/jobs",
headers={
"Content-Type": "application/json",
"X-Api-Key": "REDACTED_CLIENT_KEY"
"X-Api-Key": "${CLIENT_API_KEY}"
},
json={
"payload": {

View File

@@ -19,7 +19,7 @@ import httpx
# Configuration
DEFAULT_COORDINATOR = "http://127.0.0.1:18000"
DEFAULT_BLOCKCHAIN = "http://127.0.0.1:19000"
DEFAULT_API_KEY = "REDACTED_CLIENT_KEY"
DEFAULT_API_KEY = "${CLIENT_API_KEY}"
DEFAULT_PROMPT = "What is the capital of France?"
DEFAULT_MODEL = "llama3.2:latest"
DEFAULT_TIMEOUT = 180
@@ -150,7 +150,7 @@ def main() -> int:
# Check miner registration
print("\n📋 Checking miner registration...")
with httpx.Client() as client:
miner_info = get_miner_info(client, args.coordinator_url, "REDACTED_ADMIN_KEY")
miner_info = get_miner_info(client, args.coordinator_url, "${ADMIN_API_KEY}")
if miner_info:
print(f"✅ Found registered miner: {miner_info.get('miner_id')}")
print(f" Status: {miner_info.get('status')}")

View File

@@ -12,7 +12,7 @@ from typing import Optional
import httpx
DEFAULT_COORDINATOR = "http://127.0.0.1:18000"
DEFAULT_API_KEY = "REDACTED_CLIENT_KEY"
DEFAULT_API_KEY = "${CLIENT_API_KEY}"
DEFAULT_PROMPT = "hello"
DEFAULT_TIMEOUT = 180
POLL_INTERVAL = 3

View File

@@ -17,8 +17,8 @@ All AITBC API endpoints require authentication using API keys.
### Testing/Development
For integration tests and development, these test keys are available:
- `REDACTED_CLIENT_KEY` - For client API access
- `REDACTED_MINER_KEY` - For miner registration
- `${CLIENT_API_KEY}` - For client API access
- `${MINER_API_KEY}` - For miner registration
- `test-tenant` - Default tenant ID for testing
## Using API Keys

View File

@@ -271,7 +271,7 @@ This document tracks components that have been successfully deployed and are ope
- Result submission now returns 200 OK instead of 500 Internal Server Error
-**Miner Configuration Fix**
- Updated miner ID from `host-gpu-miner` to `REDACTED_MINER_KEY` for proper job assignment
- Updated miner ID from `host-gpu-miner` to `${MINER_API_KEY}` for proper job assignment
- Added explicit flush logging handler for better systemd journal visibility
- Enhanced systemd unit with unbuffered logging environment variables

View File

@@ -25,7 +25,7 @@ This document illustrates the complete flow of a job submission through the CLI
1. Bash script (`aitbc-cli.sh`) parses arguments
2. Sets environment variables:
- `AITBC_URL=http://127.0.0.1:18000`
- `CLIENT_KEY=REDACTED_CLIENT_KEY`
- `CLIENT_KEY=${CLIENT_API_KEY}`
3. Calls Python client: `python3 cli/client.py --url $AITBC_URL --api-key $CLIENT_KEY submit inference --prompt "..."`
### 2. Python Client Processing
@@ -40,7 +40,7 @@ This document illustrates the complete flow of a job submission through the CLI
"type": "inference",
"prompt": "What is machine learning?",
"model": "llama3.2:latest",
"client_key": "REDACTED_CLIENT_KEY",
"client_key": "${CLIENT_API_KEY}",
"timestamp": "2025-01-29T14:50:00Z"
}
```
@@ -52,7 +52,7 @@ This document illustrates the complete flow of a job submission through the CLI
POST /v1/jobs
Host: 127.0.0.1:18000
Content-Type: application/json
X-Api-Key: REDACTED_CLIENT_KEY
X-Api-Key: ${CLIENT_API_KEY}
{
"type": "inference",
@@ -84,7 +84,7 @@ X-Api-Key: REDACTED_CLIENT_KEY
{
"type": "submit_job",
"job_id": "job_123456",
"client": "REDACTED_CLIENT_KEY",
"client": "${CLIENT_API_KEY}",
"payload_hash": "abc123...",
"reward": "100aitbc"
}
@@ -110,14 +110,14 @@ X-Api-Key: REDACTED_CLIENT_KEY
2. Miner selection algorithm runs:
- Check available miners
- Select based on stake, reputation, capacity
3. Selected miner: `REDACTED_MINER_KEY`
3. Selected miner: `${MINER_API_KEY}`
**Coordinator → Miner Daemon (Port 18001):**
```http
POST /v1/jobs/assign
Host: 127.0.0.1:18001
Content-Type: application/json
X-Api-Key: REDACTED_ADMIN_KEY
X-Api-Key: ${ADMIN_API_KEY}
{
"job_id": "job_123456",
@@ -183,7 +183,7 @@ Content-Type: application/json
POST /v1/jobs/job_123456/complete
Host: 127.0.0.1:18000
Content-Type: application/json
X-Miner-Key: REDACTED_MINER_KEY
X-Miner-Key: ${MINER_API_KEY}
{
"job_id": "job_123456",
@@ -210,8 +210,8 @@ X-Miner-Key: REDACTED_MINER_KEY
{
"receipt_id": "receipt_789",
"job_id": "job_123456",
"client": "REDACTED_CLIENT_KEY",
"miner": "REDACTED_MINER_KEY",
"client": "${CLIENT_API_KEY}",
"miner": "${MINER_API_KEY}",
"amount_paid": "0.25aitbc",
"result_hash": "hash_of_result",
"block_height": 12345,
@@ -244,7 +244,7 @@ X-Miner-Key: REDACTED_MINER_KEY
```http
GET /v1/jobs/job_123456
Host: 127.0.0.1:18000
X-Api-Key: REDACTED_CLIENT_KEY
X-Api-Key: ${CLIENT_API_KEY}
```
**Response:**

View File

@@ -117,7 +117,7 @@ incus exec aitbc -- systemctl reload nginx
```bash
# Check each service
curl -k https://aitbc.bubuit.net/api/health
curl -k https://aitbc.bubuit.net/admin/stats -H "X-Api-Key: REDACTED_ADMIN_KEY"
curl -k https://aitbc.bubuit.net/admin/stats -H "X-Api-Key: ${ADMIN_API_KEY}"
curl -k https://aitbc.bubuit.net/rpc/head
```

View File

@@ -69,7 +69,7 @@ These instructions cover the newly scaffolded services. Install dependencies usi
python - <<'PY'
from aitbc_sdk import CoordinatorReceiptClient, verify_receipt
client = CoordinatorReceiptClient("http://localhost:8011", "REDACTED_CLIENT_KEY")
client = CoordinatorReceiptClient("http://localhost:8011", "${CLIENT_API_KEY}")
receipt = client.fetch_latest("<job_id>")
verification = verify_receipt(receipt)
print("miner signature valid:", verification.miner_signature.valid)

View File

@@ -74,9 +74,9 @@ DATABASE_URL=sqlite:///./coordinator.db
# or: DATABASE_URL=postgresql://user:pass@localhost:5432/aitbc
# Auth
CLIENT_API_KEYS=REDACTED_CLIENT_KEY,client_dev_key_2
MINER_API_KEYS=REDACTED_MINER_KEY,miner_dev_key_2
ADMIN_API_KEYS=REDACTED_ADMIN_KEY
CLIENT_API_KEYS=${CLIENT_API_KEY},client_dev_key_2
MINER_API_KEYS=${MINER_API_KEY},miner_dev_key_2
ADMIN_API_KEYS=${ADMIN_API_KEY}
# Security
HMAC_SECRET=change_me
@@ -349,7 +349,7 @@ def match_next_job(miner):
**Client creates a job**
```bash
curl -sX POST http://127.0.0.1:8011/v1/jobs \
-H 'X-Api-Key: REDACTED_CLIENT_KEY' \
-H 'X-Api-Key: ${CLIENT_API_KEY}' \
-H 'Idempotency-Key: 7d4a...' \
-H 'Content-Type: application/json' \
-d '{
@@ -361,12 +361,12 @@ curl -sX POST http://127.0.0.1:8011/v1/jobs \
**Miner registers + polls**
```bash
curl -sX POST http://127.0.0.1:8011/v1/miners/register \
-H 'X-Api-Key: REDACTED_MINER_KEY' \
-H 'X-Api-Key: ${MINER_API_KEY}' \
-H 'Content-Type: application/json' \
-d '{"capabilities":{"gpu":"RTX4060Ti","cuda":"12.3","vram_gb":16},"concurrency":2,"region":"eu-central"}'
curl -i -sX POST http://127.0.0.1:8011/v1/miners/poll \
-H 'X-Api-Key: REDACTED_MINER_KEY' \
-H 'X-Api-Key: ${MINER_API_KEY}' \
-H 'Content-Type: application/json' \
-d '{"max_wait_seconds":10}'
```
@@ -374,7 +374,7 @@ curl -i -sX POST http://127.0.0.1:8011/v1/miners/poll \
**Miner submits result**
```bash
curl -sX POST http://127.0.0.1:8011/v1/miners/<JOB_ID>/result \
-H 'X-Api-Key: REDACTED_MINER_KEY' \
-H 'X-Api-Key: ${MINER_API_KEY}' \
-H 'Content-Type: application/json' \
-d '{"result":{"sum":5},"metrics":{"latency_ms":42}}'
```
@@ -382,7 +382,7 @@ curl -sX POST http://127.0.0.1:8011/v1/miners/<JOB_ID>/result \
**Client fetches result**
```bash
curl -s http://127.0.0.1:8011/v1/jobs/<JOB_ID>/result \
-H 'X-Api-Key: REDACTED_CLIENT_KEY'
-H 'X-Api-Key: ${CLIENT_API_KEY}'
```
---

View File

@@ -11,7 +11,7 @@
- ✅ Deployed real GPU miner on host with NVIDIA RTX 4060 Ti (16GB)
- ✅ Integrated Ollama for LLM inference across 13+ models
- ✅ Configured systemd service (`aitbc-host-gpu-miner.service`)
- ✅ Fixed miner ID configuration (REDACTED_MINER_KEY)
- ✅ Fixed miner ID configuration (${MINER_API_KEY})
- ✅ Enhanced logging with flush handlers for systemd journal visibility
- ✅ Verified end-to-end workflow: job polling → Ollama inference → result submission → receipt generation
@@ -24,7 +24,7 @@
### Integration Points
- Coordinator API: http://127.0.0.1:18000 (via Incus proxy)
- Miner ID: REDACTED_MINER_KEY
- Miner ID: ${MINER_API_KEY}
- Heartbeat interval: 15 seconds
- Job polling: 3-second intervals
- Result submission: JSON with metrics and execution details

View File

@@ -98,7 +98,7 @@ CREATE TABLE job_payments (
### 1. Client Creates Job
```bash
curl -X POST http://localhost:18000/v1/jobs \
-H "X-Api-Key: REDACTED_CLIENT_KEY" \
-H "X-Api-Key: ${CLIENT_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"payload": {
@@ -124,7 +124,7 @@ curl -X POST http://localhost:18000/v1/jobs \
### 3. Job Completion & Payment Release
```bash
curl -X POST http://localhost:18000/v1/payments/pay456/release \
-H "X-Api-Key: REDACTED_CLIENT_KEY" \
-H "X-Api-Key: ${CLIENT_API_KEY}" \
-d '{"job_id": "abc123", "reason": "Job completed"}'
```

View File

@@ -22,7 +22,7 @@
### 4. Missing API Keys
- **Problem**: Some requests were missing the required `X-Api-Key` header
- **Solution**: Added `X-Api-Key: REDACTED_CLIENT_KEY` to all requests
- **Solution**: Added `X-Api-Key: ${CLIENT_API_KEY}` to all requests
### 5. Non-existent Endpoints
- **Problem**: Tests were calling endpoints that don't exist (e.g., `/v1/jobs/{id}/complete`)

View File

@@ -112,9 +112,9 @@ python -m pytest -m integration
### Authentication Issues?
- Use correct API keys:
- Client: `REDACTED_CLIENT_KEY`
- Miner: `REDACTED_MINER_KEY`
- Admin: `REDACTED_ADMIN_KEY`
- Client: `${CLIENT_API_KEY}`
- Miner: `${MINER_API_KEY}`
- Admin: `${ADMIN_API_KEY}`
## 📝 Next Steps

View File

@@ -390,7 +390,7 @@ This roadmap aggregates high-priority tasks derived from the bootstrap specifica
- ✅ Validate receipt payload structure and signature generation
- **Miner Configuration & Optimization**
- ✅ Fix miner ID mismatch (host-gpu-miner → REDACTED_MINER_KEY)
- ✅ Fix miner ID mismatch (host-gpu-miner → ${MINER_API_KEY})
- ✅ Enhance logging with explicit flush handlers for systemd journal
- ✅ Configure unbuffered Python logging environment variables
- ✅ Create systemd service unit with proper environment configuration

View File

@@ -9,7 +9,7 @@ from datetime import datetime
# Configuration - using the SSH tunnel to remote server
COORDINATOR_URL = "http://localhost:8001"
CLIENT_API_KEY = "REDACTED_CLIENT_KEY"
CLIENT_API_KEY = "${CLIENT_API_KEY}"
def create_job():
"""Create a job on the remote coordinator"""

View File

@@ -15,7 +15,7 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'cli'))
class AITBCClient:
def __init__(self):
self.coordinator_url = "http://localhost:8001"
self.api_key = "REDACTED_CLIENT_KEY"
self.api_key = "${CLIENT_API_KEY}"
def submit_job(self, prompt, model="llama3.2:latest", wait_for_result=True):
"""Submit a job and optionally wait for result"""

View File

@@ -107,7 +107,7 @@ def get_job_result(job_id: str) -> Optional[dict]:
with httpx.Client() as client:
response = client.get(
f"{DEFAULT_COORDINATOR}/v1/jobs/{job_id}/result",
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"},
headers={"X-Api-Key": "${CLIENT_API_KEY}"},
timeout=10,
)
if response.status_code == 200:

View File

@@ -70,7 +70,7 @@ Miners earn 150% of the cost (50% markup).
```python
from client_plugin import OllamaClient
client = OllamaClient("http://localhost:8001", "REDACTED_CLIENT_KEY")
client = OllamaClient("http://localhost:8001", "${CLIENT_API_KEY}")
job_id = client.submit_generation(
model="llama3.2:latest",

View File

@@ -190,7 +190,7 @@ def main():
parser = argparse.ArgumentParser(description="AITBC Ollama Client")
parser.add_argument("--url", default="http://localhost:8001", help="Coordinator URL")
parser.add_argument("--api-key", default="REDACTED_CLIENT_KEY", help="API key")
parser.add_argument("--api-key", default="${CLIENT_API_KEY}", help="API key")
subparsers = parser.add_subparsers(dest="command", help="Commands")

View File

@@ -30,7 +30,7 @@ def main():
print(f"✅ Ollama running with {len(models)} models")
# Create client
client = OllamaClient("http://localhost:8001", "REDACTED_CLIENT_KEY")
client = OllamaClient("http://localhost:8001", "${CLIENT_API_KEY}")
# Submit a few different jobs
jobs = []

View File

@@ -264,7 +264,7 @@ if __name__ == "__main__":
import sys
coordinator_url = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8001"
api_key = sys.argv[2] if len(sys.argv) > 2 else "REDACTED_MINER_KEY"
api_key = sys.argv[2] if len(sys.argv) > 2 else "${MINER_API_KEY}"
miner_id = sys.argv[3] if len(sys.argv) > 3 else "ollama-miner"
# Create and run miner

View File

@@ -68,7 +68,7 @@ def test_client_miner_flow():
print("\n🔄 Testing Client-Miner Flow...")
# Create client
client = OllamaClient("http://localhost:8001", "REDACTED_CLIENT_KEY")
client = OllamaClient("http://localhost:8001", "${CLIENT_API_KEY}")
# Submit a job
print("1. Submitting inference job...")
@@ -89,7 +89,7 @@ def test_client_miner_flow():
miner_cmd = [
"python3", "miner_plugin.py",
"http://localhost:8001",
"REDACTED_MINER_KEY",
"${MINER_API_KEY}",
"ollama-miner-test"
]

View File

@@ -5,9 +5,9 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CLI_PY="$ROOT_DIR/cli/client.py"
AITBC_URL="${AITBC_URL:-http://127.0.0.1:18000}"
CLIENT_KEY="${CLIENT_KEY:-REDACTED_CLIENT_KEY}"
ADMIN_KEY="${ADMIN_KEY:-REDACTED_ADMIN_KEY}"
MINER_KEY="${MINER_KEY:-REDACTED_MINER_KEY}"
CLIENT_KEY="${CLIENT_KEY:?Set CLIENT_KEY env var}"
ADMIN_KEY="${ADMIN_KEY:?Set ADMIN_KEY env var}"
MINER_KEY="${MINER_KEY:?Set MINER_KEY env var}"
usage() {
cat <<'EOF'
@@ -28,9 +28,9 @@ Usage:
Environment overrides:
AITBC_URL (default: http://127.0.0.1:18000)
CLIENT_KEY (default: REDACTED_CLIENT_KEY)
ADMIN_KEY (default: REDACTED_ADMIN_KEY)
MINER_KEY (default: REDACTED_MINER_KEY)
CLIENT_KEY (required)
ADMIN_KEY (required)
MINER_KEY (required)
EOF
}

View File

@@ -8,7 +8,7 @@ import json
# Configuration
COORDINATOR_URL = "http://localhost:8001"
MINER_API_KEY = "REDACTED_MINER_KEY"
MINER_API_KEY = "${MINER_API_KEY}"
MINER_ID = "localhost-gpu-miner"
def assign_proposer_to_latest_block():

View File

@@ -217,7 +217,7 @@ ssh $SERVER "systemctl status aitbc-blockchain --no-pager -l | head -10"
print_status "Testing endpoints..."
ssh $SERVER "curl -s http://127.0.0.1:8000/v1/health | head -c 100"
echo ""
ssh $SERVER "curl -s http://127.0.0.1:8000/v1/admin/stats -H 'X-Api-Key: REDACTED_ADMIN_KEY' | head -c 100"
ssh $SERVER "curl -s http://127.0.0.1:8000/v1/admin/stats -H 'X-Api-Key: ${ADMIN_API_KEY}' | head -c 100"
echo ""
echo ""

View File

@@ -14,8 +14,8 @@ from datetime import datetime
# Configuration
COORDINATOR_URL = "http://127.0.0.1:18000"
MINER_ID = "REDACTED_MINER_KEY"
AUTH_TOKEN = "REDACTED_MINER_KEY"
MINER_ID = "${MINER_API_KEY}"
AUTH_TOKEN = "${MINER_API_KEY}"
HEARTBEAT_INTERVAL = 15
MAX_RETRIES = 10
RETRY_DELAY = 30

View File

@@ -124,7 +124,7 @@ def test_endpoints():
for name, url in endpoints:
try:
if "admin" in url:
response = requests.get(url, headers={"X-Api-Key": "REDACTED_ADMIN_KEY"}, timeout=2)
response = requests.get(url, headers={"X-Api-Key": "${ADMIN_API_KEY}"}, timeout=2)
else:
response = requests.get(url, timeout=2)
print(f" {name}: ✅ {response.status_code}")

View File

@@ -10,7 +10,7 @@ from datetime import datetime
# Configuration
COORDINATOR_URL = "http://localhost:8001"
MINER_API_KEY = "REDACTED_MINER_KEY"
MINER_API_KEY = "${MINER_API_KEY}"
MINER_ID = "localhost-gpu-miner"
def poll_and_accept_job():

View File

@@ -52,7 +52,7 @@ echo "API Health:"
curl -s http://127.0.0.1:8000/v1/health | head -c 100
echo -e "\n\nAdmin Stats:"
curl -s http://127.0.0.1:8000/v1/admin/stats -H "X-Api-Key: REDACTED_ADMIN_KEY" | head -c 100
curl -s http://127.0.0.1:8000/v1/admin/stats -H "X-Api-Key: ${ADMIN_API_KEY}" | head -c 100
echo -e "\n\nMarketplace Offers:"
curl -s http://127.0.0.1:8000/v1/marketplace/offers | head -c 100

View File

@@ -77,7 +77,7 @@ else
fi
echo -n "Admin API: "
if curl -s http://127.0.0.1:8000/v1/admin/stats -H "X-Api-Key: REDACTED_ADMIN_KEY" > /dev/null; then
if curl -s http://127.0.0.1:8000/v1/admin/stats -H "X-Api-Key: ${ADMIN_API_KEY}" > /dev/null; then
echo "✅ OK"
else
echo "❌ Failed"

View File

@@ -56,7 +56,7 @@ def main():
print(" • Professional, production-ready interface")
print("\n💡 Note: Most transactions show:")
print(" • From: REDACTED_CLIENT_KEY")
print(" • From: ${CLIENT_API_KEY}")
print(" • To: null (not assigned to miner yet)")
print(" • Value: 0 (cost shown when completed)")
print(" • Status: Queued/Running/Expired")

View File

@@ -8,7 +8,7 @@ import json
# Configuration
COORDINATOR_URL = "http://127.0.0.1:8000/v1"
CLIENT_KEY = "test_client_key_123"
MINER_KEY = "REDACTED_MINER_KEY"
MINER_KEY = "${MINER_API_KEY}"
async def register_client():
"""Register a test client"""

View File

@@ -18,7 +18,7 @@ logger = logging.getLogger(__name__)
# Configuration
COORDINATOR_URL = "https://aitbc.bubuit.net/api"
CLIENT_KEY = "test_client_key_123"
MINER_KEY = "REDACTED_MINER_KEY"
MINER_KEY = "${MINER_API_KEY}"
class PaymentIntegrationTest:
def __init__(self):

View File

@@ -17,8 +17,8 @@ logger = logging.getLogger(__name__)
# Configuration - Using localhost as we're testing from the server
COORDINATOR_URL = "http://127.0.0.1:8000/v1"
CLIENT_KEY = "REDACTED_CLIENT_KEY"
MINER_KEY = "REDACTED_MINER_KEY"
CLIENT_KEY = "${CLIENT_API_KEY}"
MINER_KEY = "${MINER_API_KEY}"
class PaymentIntegrationTest:
def __init__(self):

View File

@@ -35,7 +35,7 @@ class TestJobToBlockchainWorkflow:
"/v1/jobs",
json=job_data,
headers={
"X-Api-Key": "REDACTED_CLIENT_KEY", # Valid API key from config
"X-Api-Key": "${CLIENT_API_KEY}", # Valid API key from config
"X-Tenant-ID": "test-tenant"
}
)
@@ -46,7 +46,7 @@ class TestJobToBlockchainWorkflow:
# 2. Get job status
response = coordinator_client.get(
f"/v1/jobs/{job_id}",
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"}
headers={"X-Api-Key": "${CLIENT_API_KEY}"}
)
assert response.status_code == 200
assert response.json()["job_id"] == job_id # Fixed: use job_id
@@ -54,7 +54,7 @@ class TestJobToBlockchainWorkflow:
# 3. Test that we can get receipts (even if empty)
response = coordinator_client.get(
f"/v1/jobs/{job_id}/receipts",
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"}
headers={"X-Api-Key": "${CLIENT_API_KEY}"}
)
assert response.status_code == 200
receipts = response.json()
@@ -74,7 +74,7 @@ class TestJobToBlockchainWorkflow:
response = coordinator_client.post(
"/v1/jobs",
json={"payload": {"job_type": "test", "parameters": {}}, "ttl_seconds": 900},
headers={"X-Api-Key": "REDACTED_CLIENT_KEY", "X-Tenant-ID": "tenant-a"}
headers={"X-Api-Key": "${CLIENT_API_KEY}", "X-Tenant-ID": "tenant-a"}
)
tenant_a_jobs.append(response.json()["job_id"]) # Fixed: use job_id
@@ -83,7 +83,7 @@ class TestJobToBlockchainWorkflow:
response = coordinator_client.post(
"/v1/jobs",
json={"payload": {"job_type": "test", "parameters": {}}, "ttl_seconds": 900},
headers={"X-Api-Key": "REDACTED_CLIENT_KEY", "X-Tenant-ID": "tenant-b"}
headers={"X-Api-Key": "${CLIENT_API_KEY}", "X-Tenant-ID": "tenant-b"}
)
tenant_b_jobs.append(response.json()["job_id"]) # Fixed: use job_id
@@ -91,7 +91,7 @@ class TestJobToBlockchainWorkflow:
# Try to access other tenant's job (currently returns 200, not 404)
response = coordinator_client.get(
f"/v1/jobs/{tenant_b_jobs[0]}",
headers={"X-Api-Key": "REDACTED_CLIENT_KEY", "X-Tenant-ID": "tenant-a"}
headers={"X-Api-Key": "${CLIENT_API_KEY}", "X-Tenant-ID": "tenant-a"}
)
# The API doesn't enforce tenant isolation yet
assert response.status_code in [200, 404] # Accept either for now
@@ -122,7 +122,7 @@ class TestWalletToCoordinatorIntegration:
"/v1/jobs",
json=job_data,
headers={
"X-Api-Key": "REDACTED_CLIENT_KEY",
"X-Api-Key": "${CLIENT_API_KEY}",
"X-Tenant-ID": "test-tenant"
}
)
@@ -137,7 +137,7 @@ class TestWalletToCoordinatorIntegration:
# Get payment details
response = coordinator_client.get(
f"/v1/jobs/{job_id}/payment",
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"}
headers={"X-Api-Key": "${CLIENT_API_KEY}"}
)
assert response.status_code == 200
payment = response.json()
@@ -155,7 +155,7 @@ class TestWalletToCoordinatorIntegration:
"job_id": job_id,
"reason": "Job completed successfully"
},
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"}
headers={"X-Api-Key": "${CLIENT_API_KEY}"}
)
# Note: This might fail if wallet daemon is not running
# That's OK for this test
@@ -253,7 +253,7 @@ class TestMarketplaceIntegration:
response = coordinator_client.post(
"/v1/jobs",
json=job_data,
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"}
headers={"X-Api-Key": "${CLIENT_API_KEY}"}
)
assert response.status_code == 201
job = response.json()
@@ -285,7 +285,7 @@ class TestSecurityIntegration:
"/v1/jobs",
json=job_data,
headers={
"X-Api-Key": "REDACTED_CLIENT_KEY",
"X-Api-Key": "${CLIENT_API_KEY}",
"X-Tenant-ID": "secure-tenant"
}
)
@@ -300,7 +300,7 @@ class TestSecurityIntegration:
# Test that we can retrieve the job securely
response = coordinator_client.get(
f"/v1/jobs/{job_id}",
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"}
headers={"X-Api-Key": "${CLIENT_API_KEY}"}
)
assert response.status_code == 200
retrieved_job = response.json()

View File

@@ -58,7 +58,7 @@ def test_job_endpoint_structure():
response = client.post(
"/v1/jobs",
json={},
headers={"X-Api-Key": "REDACTED_CLIENT_KEY"}
headers={"X-Api-Key": "${CLIENT_API_KEY}"}
)
# Should get validation error, not auth or not found
assert response.status_code in [400, 422], f"Expected validation error, got {response.status_code}"
@@ -84,7 +84,7 @@ def test_miner_endpoint_structure():
response = client.post(
"/v1/miners/register",
json={},
headers={"X-Api-Key": "REDACTED_MINER_KEY"}
headers={"X-Api-Key": "${MINER_API_KEY}"}
)
# Should get validation error, not auth or not found
assert response.status_code in [400, 422], f"Expected validation error, got {response.status_code}"

View File

@@ -174,7 +174,7 @@
<script>
const API_BASE = '/api';
const ADMIN_API_KEY = 'REDACTED_ADMIN_KEY';
const ADMIN_API_KEY = '${ADMIN_API_KEY}';
const headers = { 'X-Api-Key': ADMIN_API_KEY };
// Initialize

View File

@@ -357,7 +357,7 @@
<li>Sets environment variables:
<ul>
<li><span class="inline-code">AITBC_URL=http://127.0.0.1:18000</span></li>
<li><span class="inline-code">CLIENT_KEY=REDACTED_CLIENT_KEY</span></li>
<li><span class="inline-code">CLIENT_KEY=${CLIENT_API_KEY}</span></li>
</ul>
</li>
<li>Calls Python client: <span class="inline-code">python3 cli/client.py --url $AITBC_URL --api-key $CLIENT_KEY submit inference --prompt "..."</span></li>
@@ -374,7 +374,7 @@
"type": "inference",
"prompt": "What is machine learning?",
"model": "llama3.2:latest",
"client_key": "REDACTED_CLIENT_KEY",
"client_key": "${CLIENT_API_KEY}",
"timestamp": "2025-01-29T14:50:00Z"
}</code></pre>
</li>
@@ -386,7 +386,7 @@
<pre><code>POST /v1/jobs
Host: 127.0.0.1:18000
Content-Type: application/json
X-Api-Key: REDACTED_CLIENT_KEY
X-Api-Key: ${CLIENT_API_KEY}
{
"type": "inference",
@@ -418,7 +418,7 @@ X-Api-Key: REDACTED_CLIENT_KEY
<pre><code>{
"type": "submit_job",
"job_id": "job_123456",
"client": "REDACTED_CLIENT_KEY",
"client": "${CLIENT_API_KEY}",
"payload_hash": "abc123...",
"reward": "100aitbc"
}</code></pre>
@@ -445,7 +445,7 @@ X-Api-Key: REDACTED_CLIENT_KEY
<li>Select based on stake, reputation, capacity</li>
</ul>
</li>
<li>Selected miner: <span class="inline-code">REDACTED_MINER_KEY</span></li>
<li>Selected miner: <span class="inline-code">${MINER_API_KEY}</span></li>
</ol>
<div class="http-request">
@@ -453,7 +453,7 @@ X-Api-Key: REDACTED_CLIENT_KEY
<pre><code>POST /v1/jobs/assign
Host: 127.0.0.1:18001
Content-Type: application/json
X-Api-Key: REDACTED_ADMIN_KEY
X-Api-Key: ${ADMIN_API_KEY}
{
"job_id": "job_123456",
@@ -518,7 +518,7 @@ Content-Type: application/json
<pre><code>POST /v1/jobs/job_123456/complete
Host: 127.0.0.1:18000
Content-Type: application/json
X-Miner-Key: REDACTED_MINER_KEY
X-Miner-Key: ${MINER_API_KEY}
{
"job_id": "job_123456",
@@ -544,8 +544,8 @@ X-Miner-Key: REDACTED_MINER_KEY
<pre><code>{
"receipt_id": "receipt_789",
"job_id": "job_123456",
"client": "REDACTED_CLIENT_KEY",
"miner": "REDACTED_MINER_KEY",
"client": "${CLIENT_API_KEY}",
"miner": "${MINER_API_KEY}",
"amount_paid": "0.25aitbc",
"result_hash": "hash_of_result",
"block_height": 12345,
@@ -573,7 +573,7 @@ X-Miner-Key: REDACTED_MINER_KEY
<h4>HTTP Request:</h4>
<pre><code>GET /v1/jobs/job_123456
Host: 127.0.0.1:18000
X-Api-Key: REDACTED_CLIENT_KEY</code></pre>
X-Api-Key: ${CLIENT_API_KEY}</code></pre>
<h4>Response:</h4>
<pre><code>{