Major additions: - marketplace/: Agent template registry with FTS5 search, ratings, versioning - observability/: Prometheus metrics, distributed tracing, structured logging - ledger/migrations/: Database migration scripts for multi-tenant support - tests/governance/: 15 new test files for phases 6-12 (295 total tests) - bin/validate-phases: Full 12-phase validation script New features: - Multi-tenant support with tenant isolation and quota enforcement - Agent marketplace with semantic versioning and search - Observability with metrics, tracing, and log correlation - Tier-1 agent bootstrap scripts Updated components: - ledger/api.py: Extended API for tenants, marketplace, observability - ledger/schema.sql: Added tenant, project, marketplace tables - testing/framework.ts: Enhanced test framework - checkpoint/checkpoint.py: Improved checkpoint management Archived: - External integrations (Slack/GitHub/PagerDuty) moved to .archive/ - Old checkpoint files cleaned up Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
10 KiB
10 KiB
Production Credentials Setup Guide
How to configure external integration credentials for Slack, GitHub, and PagerDuty.
Overview
The Agent Governance System uses HashiCorp Vault for secure credential storage. Each integration has a dedicated secret path with specific required keys. The system also supports environment variable overrides for development and CI environments.
Prerequisites
- Vault server running at
https://127.0.0.1:8200(orVAULT_ADDR) - Vault root token or appropriate access policy
- Admin access to Slack, GitHub, and PagerDuty accounts
Credential Priority
The secrets manager loads credentials in this order:
- Environment variables (highest priority)
- Vault secrets (production)
- Mock values (testing only, when
INTEGRATION_DRY_RUN=true)
Slack Integration
Vault Path
secret/data/integrations/slack
Required Keys
| Key | Description | Format |
|---|---|---|
slack_bot_token |
Bot User OAuth Token | xoxb-... |
slack_webhook_url |
Incoming Webhook URL | https://hooks.slack.com/services/... |
How to Obtain
Bot Token
- Go to api.slack.com/apps
- Create a new app or select existing
- Navigate to OAuth & Permissions
- Under Bot Token Scopes, add:
chat:write- Send messageschat:write.public- Send to public channelsfiles:write- Upload files (optional)
- Click Install to Workspace
- Copy the Bot User OAuth Token (
xoxb-...)
Webhook URL
- In your Slack app, go to Incoming Webhooks
- Enable incoming webhooks
- Click Add New Webhook to Workspace
- Select the target channel
- Copy the Webhook URL
Store in Vault
# Set Vault address and token
export VAULT_ADDR="https://127.0.0.1:8200"
export VAULT_TOKEN=$(cat /opt/vault/init-keys.json | python3 -c "import sys,json; print(json.load(sys.stdin)['root_token'])")
# Store Slack credentials
vault kv put secret/integrations/slack \
slack_bot_token="xoxb-YOUR-BOT-TOKEN" \
slack_webhook_url="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" \
configured=true
# Or using curl (if vault CLI not available)
curl -sk -X POST \
-H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"slack_bot_token": "xoxb-YOUR-BOT-TOKEN",
"slack_webhook_url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
"configured": true
}
}' \
"$VAULT_ADDR/v1/secret/data/integrations/slack"
Environment Variable Override
export SLACK_BOT_TOKEN="xoxb-YOUR-BOT-TOKEN"
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
Verify Configuration
# Test with Python
python3 -c "
from integrations.slack import SlackIntegration
slack = SlackIntegration()
print(f'Enabled: {slack.enabled}')
print(f'Connection test: {slack.test_connection()}')
"
GitHub Integration
Vault Path
secret/data/integrations/github
Required Keys
| Key | Description | Format |
|---|---|---|
github_token |
Personal Access Token or App Token | ghp_... or ghs_... |
github_webhook_secret |
Webhook signature secret | Random string |
How to Obtain
Personal Access Token (Classic)
- Go to github.com/settings/tokens
- Click Generate new token (classic)
- Select scopes:
repo- Full repository accesswrite:org- Organization webhooks (if needed)admin:repo_hook- Manage webhooks
- Click Generate token
- Copy the token immediately (shown only once)
Fine-Grained Personal Access Token (Recommended)
- Go to github.com/settings/tokens?type=beta
- Click Generate new token
- Set token name and expiration
- Select Repository access (specific repos or all)
- Under Permissions, enable:
- Contents: Read and write
- Pull requests: Read and write
- Commit statuses: Read and write
- Webhooks: Read and write
- Click Generate token
Webhook Secret
- Generate a random secret:
openssl rand -hex 32 - When creating GitHub webhooks, use this secret for signature verification
Store in Vault
# Generate webhook secret
WEBHOOK_SECRET=$(openssl rand -hex 32)
# Store GitHub credentials
vault kv put secret/integrations/github \
github_token="ghp_YOUR-PERSONAL-ACCESS-TOKEN" \
github_webhook_secret="$WEBHOOK_SECRET" \
configured=true
# Or using curl
curl -sk -X POST \
-H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"data\": {
\"github_token\": \"ghp_YOUR-PERSONAL-ACCESS-TOKEN\",
\"github_webhook_secret\": \"$WEBHOOK_SECRET\",
\"configured\": true
}
}" \
"$VAULT_ADDR/v1/secret/data/integrations/github"
Environment Variable Override
export GITHUB_TOKEN="ghp_YOUR-PERSONAL-ACCESS-TOKEN"
export GITHUB_WEBHOOK_SECRET="your-webhook-secret"
Verify Configuration
python3 -c "
from integrations.github import GitHubIntegration
gh = GitHubIntegration()
print(f'Enabled: {gh.enabled}')
print(f'Connection test: {gh.test_connection()}')
"
PagerDuty Integration
Vault Path
secret/data/integrations/pagerduty
Required Keys
| Key | Description | Format |
|---|---|---|
pagerduty_routing_key |
Events API v2 Integration Key | 32-char hex string |
pagerduty_api_token |
REST API Token (optional) | 20-char string |
pagerduty_service_id |
Service ID (optional) | P... format |
How to Obtain
Routing Key (Events API v2) - Required
- Log into app.pagerduty.com
- Go to Services > Select your service
- Click Integrations tab
- Click Add Integration
- Select Events API v2
- Copy the Integration Key (this is your routing key)
REST API Token (Optional)
- Go to Configuration > API Access
- Click Create New API Key
- Enter a description (e.g., "Agent Governance")
- Choose Read/Write access
- Copy the generated token
Service ID (Optional)
- Go to Services > Select your service
- The Service ID is in the URL:
app.pagerduty.com/services/PXXXXXX - Or find it under Settings > Service ID
Store in Vault
# Store PagerDuty credentials
vault kv put secret/integrations/pagerduty \
pagerduty_routing_key="YOUR-32-CHAR-ROUTING-KEY" \
pagerduty_api_token="YOUR-API-TOKEN" \
pagerduty_service_id="PXXXXXXX" \
configured=true
# Or using curl
curl -sk -X POST \
-H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"pagerduty_routing_key": "YOUR-32-CHAR-ROUTING-KEY",
"pagerduty_api_token": "YOUR-API-TOKEN",
"pagerduty_service_id": "PXXXXXXX",
"configured": true
}
}' \
"$VAULT_ADDR/v1/secret/data/integrations/pagerduty"
Environment Variable Override
export PAGERDUTY_ROUTING_KEY="your-32-char-routing-key"
export PAGERDUTY_API_TOKEN="your-api-token"
export PAGERDUTY_SERVICE_ID="PXXXXXXX"
Verify Configuration
python3 -c "
from integrations.pagerduty import PagerDutyIntegration
pd = PagerDutyIntegration()
print(f'Enabled: {pd.enabled}')
print(f'Connection test: {pd.test_connection()}')
"
Runtime Environment Variables
The following environment variables control integration behavior:
| Variable | Description | Default |
|---|---|---|
VAULT_ADDR |
Vault server address | https://127.0.0.1:8200 |
VAULT_TOKEN |
Vault authentication token | Read from /opt/vault/init-keys.json |
USE_VAULT |
Enable Vault secret loading | true |
INTEGRATION_DRY_RUN |
Prevent actual API calls (testing) | false |
TESTING |
Enable mock mode for all secrets | false |
Production Configuration
# /etc/environment or systemd unit file
VAULT_ADDR=https://vault.internal:8200
USE_VAULT=true
INTEGRATION_DRY_RUN=false
Development Configuration
# .env or shell profile
export SLACK_BOT_TOKEN="xoxb-dev-token"
export GITHUB_TOKEN="ghp_dev-token"
export PAGERDUTY_ROUTING_KEY="dev-routing-key"
export INTEGRATION_DRY_RUN=true
Verification Script
Run this script to verify all integrations are properly configured:
#!/bin/bash
# verify-integrations.sh
cd /opt/agent-governance
echo "=== Integration Credential Verification ==="
echo ""
python3 << 'EOF'
import os
import sys
sys.path.insert(0, "/opt/agent-governance/integrations")
from common.secrets import SecretsManager
secrets = SecretsManager()
integrations = ["slack", "github", "pagerduty"]
for name in integrations:
result = secrets.validate_integration(name)
status = "READY" if result["ready"] else "MISSING KEYS"
print(f"\n[{name.upper()}] {status}")
if result["configured"]:
print(f" Configured: {', '.join(result['configured'])}")
if result["missing"]:
print(f" Missing: {', '.join(result['missing'])}")
if result["mock_mode"]:
print(f" (Running in mock mode)")
print("\n" + "=" * 45)
EOF
Troubleshooting
"No credentials found"
- Check Vault is accessible:
curl -sk $VAULT_ADDR/v1/sys/health - Verify token is valid:
vault token lookup - Check secret path exists:
vault kv get secret/integrations/slack
"Connection test failed"
- Verify credentials are correct (not placeholder values)
- Check network connectivity to external services
- Enable dry-run mode to test without making real API calls:
INTEGRATION_DRY_RUN=true python3 -c "..."
"Rate limit exceeded"
- The integration base class handles rate limiting (60 req/min default)
- Check
_request_timesin the integration instance - Wait 60 seconds and retry
Security Best Practices
- Never commit credentials to version control
- Rotate tokens regularly (GitHub: 90 days, PagerDuty: annually)
- Use least privilege - only request scopes you need
- Enable Vault audit logging for credential access tracking
- Use environment variables only in development; production should use Vault
- Monitor for credential leaks with GitHub secret scanning
Related Documentation
Last updated: 2026-01-24