PR Pipeline — Authorize → Validate → Review → Merge / auth (push) Failing after 1s
PR Pipeline — Authorize → Validate → Review → Merge / validate (push) Has been skipped
PR Pipeline — Authorize → Validate → Review → Merge / lint (push) Has been skipped
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (push) Has been skipped
PR Pipeline — Authorize → Validate → Review → Merge / gate (push) Has been skipped
145 lines
5.1 KiB
Markdown
145 lines
5.1 KiB
Markdown
---
|
|
kind: enforcement
|
|
name: hermes-key-enforcement
|
|
version: 1.0.0
|
|
description: >
|
|
Enforces standardized API key configuration across all Hermes agents. Harness/LiteLLM
|
|
providers MUST use api_key_env indirection. External providers (DeepSeek, OpenAI,
|
|
Anthropic) may use hardcoded keys. Single source of truth: /etc/environment on each
|
|
agent host. Designed to make key rotation a one-step operation.
|
|
author: Abiba (pi agent)
|
|
---
|
|
|
|
# Hermes Key Enforcement Contract
|
|
|
|
## Rule (One Sentence)
|
|
|
|
**Any `api_key` pointing to a Syslog-hosted LiteLLM/harness provider MUST be replaced with `api_key_env: LITELLM_API_KEY` — hardcoded harness keys are forbidden.**
|
|
|
|
## Scope
|
|
|
|
Applies to all Hermes agent configs across all hosts. Covers these config sections:
|
|
- `model.api_key`
|
|
- `custom_providers[].api_key` (when `name` contains `harness` or `litellm`)
|
|
- `auxiliary.*.api_key` (when `provider` is `harness` or contains `litellm`)
|
|
- `delegation.api_key` (when `provider` is `harness` or contains `litellm`)
|
|
- `compression.api_key` (when `provider` is `harness` or contains `litellm`)
|
|
- `fallback_providers[].api_key` (when provider is harness)
|
|
|
|
## Exemptions
|
|
|
|
External providers are **explicitly exempt** and may use hardcoded keys:
|
|
- DeepSeek (`api.deepseek.com`)
|
|
- OpenAI (`api.openai.com`)
|
|
- Anthropic (`api.anthropic.com`)
|
|
- OpenRouter
|
|
- Any provider whose base_url does NOT match `192.168.68.116` or `litellm.sysloggh.net`
|
|
|
|
## Standard Pattern
|
|
|
|
```yaml
|
|
# ✅ CORRECT — all harness/litellm providers
|
|
model:
|
|
provider: harness # or custom:litellm.sysloggh.net
|
|
base_url: http://192.168.68.116/v1
|
|
api_key_env: LITELLM_API_KEY # ← indirection
|
|
|
|
custom_providers:
|
|
- name: harness
|
|
base_url: http://192.168.68.116/v1
|
|
api_key_env: LITELLM_API_KEY # ← indirection
|
|
|
|
auxiliary:
|
|
compression:
|
|
provider: harness
|
|
api_key_env: LITELLM_API_KEY # ← indirection
|
|
|
|
# ✅ ALSO CORRECT — external providers
|
|
fallback_providers:
|
|
- provider: deepseek
|
|
base_url: https://api.deepseek.com
|
|
api_key: sk-b7d9... # ← hardcoded OK (external)
|
|
api_key_env: DEEPSEEK_API_KEY # ← also OK if set in /etc/environment
|
|
```
|
|
|
|
```yaml
|
|
# ❌ FORBIDDEN — hardcoded harness/litellm key
|
|
model:
|
|
provider: harness
|
|
api_key: sk-Flc62smlegyMEaSo1ka8JA # ← RULE VIOLATION
|
|
```
|
|
|
|
## Detection Query
|
|
|
|
Run on any Hermes host to detect violations:
|
|
|
|
```bash
|
|
grep -n 'api_key: sk-' /root/.hermes/config.yaml \
|
|
| grep -v 'deepseek\|b7d9\|openai\|anthropic\|DEEPSEEK'
|
|
```
|
|
|
|
If any output — violation. Fix immediately.
|
|
|
|
## Rotation Procedure
|
|
|
|
With this standard enforced, key rotation is one step:
|
|
|
|
```bash
|
|
# 1. Generate new key in LiteLLM
|
|
# 2. Update /etc/environment on agent host
|
|
ssh root@<host> "sed -i 's/LITELLM_API_KEY=.*/LITELLM_API_KEY=sk-NEW_KEY/' /etc/environment"
|
|
# 3. Restart agent gateway
|
|
ssh root@<host> "pkill -f 'hermes_cli.main gateway run'; sleep 2; nohup ... &"
|
|
# 4. Verify
|
|
curl -s -H "Authorization: Bearer sk-NEW_KEY" http://192.168.68.116/v1/models
|
|
```
|
|
|
|
**Done.** No config file changes needed. The agent picks up the new key on restart.
|
|
|
|
## Key Longevity Policy (2026-07-04)
|
|
|
|
**Keys are permanent and use bare agent name aliases.**
|
|
|
|
- **Duration**: `null` — keys never expire. This is enforced by `default_key_generate_params` in `litellm_config.yaml`.
|
|
- **Alias convention**: bare agent name only (e.g., `tanko`, `mumuni`, `koby`, `koonimo`). No dates, no versions. The alias IS the identity.
|
|
- **Rotation triggers**: compromise, personnel departure, or quarterly security hygiene. NOT calendar-driven.
|
|
- **Max budget**: $100 per key (config default).
|
|
|
|
```yaml
|
|
# In litellm_config.yaml — ensures all future keys inherit these defaults:
|
|
litellm_settings:
|
|
default_key_generate_params:
|
|
models: ["syslog-auto", "qwen3.6-27B-code", "gemma-4-12b"]
|
|
duration: null # ← permanent
|
|
max_budget: 100
|
|
metadata:
|
|
purpose: "agent-inference"
|
|
```
|
|
|
|
## Verified Agents (2026-07-04 final)
|
|
|
|
| Agent | CT | Status | api_key_env entries | Hardcoded harness | Last Verified |
|
|
|-------|-----|--------|---------------------|-------------------|---------------|
|
|
| Tanko | 112 | ✅ Compliant (key: tanko) | 4 | 0 | 22:45 EDT |
|
|
| Mumuni | 114 | ✅ Compliant | 8 | 0 | 19:14 EDT |
|
|
| Koby | 111 | ✅ Compliant | 14 | 0 | 19:14 EDT |
|
|
| Koonimo | 113 | ✅ Compliant | 7 | 0 | 19:14 EDT |
|
|
| Abiba | 100 | ✅ N/A (pi native) | — | — | 19:14 EDT |
|
|
| Kagenz0 | 105 | ❌ DOWN | — | — | 19:14 EDT |
|
|
|
|
## Violation Response
|
|
|
|
1. **Detect** — run detection query above
|
|
2. **Fix** — replace `api_key: sk-...` with `api_key_env: LITELLM_API_KEY` in all harness/litellm sections
|
|
3. **Verify** — `grep -c "api_key_env" config.yaml` should increase, hardcoded harness keys should be 0
|
|
4. **Restart** — gateway must restart to pick up env var
|
|
5. **Confirm** — test key against LiteLLM: `curl -H "Authorization: Bearer $KEY" .../v1/models` → 200
|
|
6. **Update** — bump the verified table above
|
|
|
|
## Related Contracts
|
|
|
|
- `hermes-config-template.prose.md` — full configuration template
|
|
- `litellm-health.prose.md` — LiteLLM stack health verification
|
|
- `zulip-platform-verification.prose.md` — cross-platform agent verification
|
|
# CI test — Node.js installed on runner
|