Research-Stack/4-Infrastructure/infra/credential_server.py
Brandon Schneider c5b6a31a8b feat: add RDS probe tool, credential server, and Notion/Linear ingestion pipeline
New infrastructure components:
- rds_probe: Rust database inspection tool with IAM auth
- credential_server.py: REST credential provider server
- credential_provider.py: credential resolution chain
- ene_rds_fractal_fold.py / ene_rds_wiki_layer.py: RDS-backed ENE layers
- import_dumps_to_rds.py / export_linear_from_rds.py: ingestion pipeline
- recover_credential_server.sh: deployment script (sanitized)

Sanitize hardcoded secrets across codebase:
- Strip API keys from recover_credential_server.sh → env var lookups
- Replace hardcoded Wolfram appid (HYJE3R3R63) → env var in 5 scripts
- Strip fallback key values from config/index.js
- Add .claude/ and optimized_basis_v3.bin to .gitignore

Ingested 2,685 records into RDS: 2,421 Linear issues + 264 wiki pages
2026-05-18 00:31:44 -05:00

319 lines
12 KiB
Python

"""Credential server — REST + OpenAPI access point for API keys.
Reads credentials from credential_provider (env vars + config file + RDS)
and serves them via HTTP so no script needs direct env var access.
Usage:
# Standalone
python3 credential_server.py [--port 8444] [--bind 0.0.0.0]
# Via existing embedded surface (if RS_CREDENTIAL_SERVER_PORT is set)
"""
from __future__ import annotations
import json
import os
import re
import sys
import urllib.request
import urllib.parse
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from typing import Any
from credential_provider import (
credential_status,
provider_manifest,
resolve_credential,
_rds_connect,
_cred_server_url
)
VERSION = "0.4"
OPENAPI_VERSION = "3.0.3"
OPENAPI_SPEC: dict[str, Any] = {
"openapi": OPENAPI_VERSION,
"info": {
"title": "Research Stack Credential Provider",
"description": "Central API key access point for all stack services. "
"Set keys once on the microVM, consume from anywhere.",
"version": VERSION,
},
"servers": [
{"url": "http://localhost:8444", "description": "Local / Tailnet default"},
],
"paths": {
"/": {
"get": {
"summary": "Service root",
"responses": {"200": {"description": "Service info + links"}},
}
},
"/health": {
"get": {
"summary": "Health check",
"responses": {"200": {"description": "OK"}},
}
},
"/openapi.json": {
"get": {
"summary": "OpenAPI 3.0 specification",
"responses": {"200": {"description": "This document"}},
}
},
"/credentials": {
"get": {
"summary": "List all available credential providers",
"responses": {
"200": {
"description": "Provider manifest",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"providers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"description": {"type": "string"},
"available": {"type": "boolean"},
},
},
}
},
}
}
},
}
},
}
},
"/credentials/{provider}": {
"get": {
"summary": "Resolve a specific provider credential",
"parameters": [
{
"name": "provider",
"in": "path",
"required": True,
"schema": {"type": "string"},
"description": "Provider name (deepseek, bedrock, etc.)",
}
],
"responses": {
"200": {"description": "Credential value"},
"404": {"description": "Provider not found"},
},
}
},
"/status": {
"get": {
"summary": "Credential provider status",
"responses": {"200": {"description": "Backend info + counts"}},
}
},
},
}
SERVICE_INFO: dict[str, Any] = {
"service": "credential-provider",
"version": VERSION,
"docs": "/openapi.json",
"credentials": "/credentials",
"status": "/status",
"health": "/health",
}
class CredentialHTTPHandler(BaseHTTPRequestHandler):
def log_message(self, fmt, *args):
sys.stderr.write(f"[credential-server] {args[0]} {args[1]} {args[2]}\n")
def _send_json(self, data: Any, status: int = 200):
body = json.dumps(data, sort_keys=True, indent=2).encode("utf-8") + b"\n"
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
self.wfile.write(body)
def _send_error(self, status: int, message: str):
self._send_json({"ok": False, "error": message}, status)
def do_GET(self):
path = self.path.rstrip("/") or "/"
if path in ("/", "/api"):
return self._send_json(SERVICE_INFO)
if path in ("/health", "/api/health"):
return self._send_json({"status": "ok", "version": VERSION})
if path == "/openapi.json":
return self._send_json(OPENAPI_SPEC)
if path in ("/status", "/api/status"):
return self._send_json(credential_status())
if path == "/credentials" or path == "/api/credentials":
return self._send_json(provider_manifest())
m = re.match(r"^(?:/api)?/credentials/([a-zA-Z0-9_-]+)$", path)
if m:
provider = m.group(1).lower()
cred = resolve_credential(provider)
if cred is None:
return self._send_error(404, f"provider '{provider}' not found")
return self._send_json({
"ok": True,
"provider": cred.provider,
"key": cred.value,
"key_name": cred.key_name,
})
return self._send_error(404, f"not found: {path}")
def do_POST(self):
path = self.path.rstrip("/") or "/"
if path in ("/api/webhooks/linear", "/webhooks/linear"):
# Read raw body
content_length = int(self.headers.get("Content-Length", 0))
raw_body = self.rfile.read(content_length)
# Node identification logic: proxy or process
node_id = os.environ.get("RS_SURFACE_NODE_ID", "")
if node_id != "MicroVM-Racknerd":
# Act as Proxy: Forward POST request to the central microVM
target_url = f"{_cred_server_url}/api/webhooks/linear"
req = urllib.request.Request(target_url, data=raw_body, method="POST")
for k, v in self.headers.items():
if k.lower() in ("content-type", "linear-signature"):
req.add_header(k, v)
try:
with urllib.request.urlopen(req, timeout=10) as resp:
resp_data = json.loads(resp.read().decode("utf-8"))
return self._send_json(resp_data, resp.status)
except urllib.error.HTTPError as e:
try:
err_data = json.loads(e.read().decode("utf-8"))
return self._send_json(err_data, e.code)
except Exception:
return self._send_error(e.code, f"Forwarding failed: {e}")
except Exception as e:
return self._send_error(500, f"Forwarding connection error: {e}")
# Act as Server: Process Linear webhook body and upsert into Aurora RDS ENE packages table
try:
data = json.loads(raw_body.decode("utf-8"))
except Exception as e:
return self._send_error(400, f"Invalid JSON payload: {e}")
action = data.get("action")
issue_data = data.get("data", {})
payload_type = data.get("type")
if payload_type != "Issue":
return self._send_json({"ok": True, "message": f"Ignored non-Issue payload: {payload_type}"})
identifier = issue_data.get("identifier")
if not identifier:
return self._send_error(400, "Missing issue identifier")
pkg_id = f"linear/{identifier}"
if action == "remove":
try:
conn = _rds_connect()
cur = conn.cursor()
cur.execute("DELETE FROM ene.packages WHERE pkg = %s", (pkg_id,))
conn.commit()
conn.close()
return self._send_json({"ok": True, "action": "delete", "pkg": pkg_id})
except Exception as e:
return self._send_error(500, f"Database delete error: {e}")
# Extract title and description
title = issue_data.get("title", "")
description = issue_data.get("description", "")
full_text = f"{title}\n\n{description}" if description else title
url = issue_data.get("url", "")
# Extract labels
labels_data = issue_data.get("labels", [])
labels_list = []
if isinstance(labels_data, list):
for l in labels_data:
if isinstance(l, dict):
labels_list.append(l.get("name"))
elif isinstance(l, str):
labels_list.append(l)
tags_json = json.dumps(labels_list)
import datetime
now_iso = datetime.datetime.now(datetime.timezone.utc).isoformat()
try:
conn = _rds_connect()
cur = conn.cursor()
cur.execute("""
INSERT INTO ene.packages (
pkg, version, domain, tier, archetype,
tags, description, source, indexed_utc
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
ON CONFLICT (pkg) DO UPDATE SET
description = EXCLUDED.description,
tags = EXCLUDED.tags,
source = EXCLUDED.source,
indexed_utc = EXCLUDED.indexed_utc
""", (
pkg_id,
"1.0.0",
"LINEAR",
"INTENT",
"issue",
tags_json,
full_text,
url,
now_iso
))
conn.commit()
conn.close()
return self._send_json({"ok": True, "action": action, "pkg": pkg_id})
except Exception as e:
return self._send_error(500, f"Database upsert error: {e}")
return self._send_error(404, f"not found: {path}")
do_HEAD = do_GET
def main():
import argparse
parser = argparse.ArgumentParser(description="Research Stack Credential Server")
parser.add_argument("--port", type=int, default=int(os.environ.get("RS_CREDENTIAL_PORT", "8444")))
parser.add_argument("--bind", default=os.environ.get("RS_CREDENTIAL_BIND", "0.0.0.0"))
args = parser.parse_args()
server = ThreadingHTTPServer((args.bind, args.port), CredentialHTTPHandler)
print(f"[credential-server] listening on {args.bind}:{args.port}", flush=True)
print(f"[credential-server] OpenAPI spec at http://{args.bind}:{args.port}/openapi.json", flush=True)
try:
server.serve_forever()
except KeyboardInterrupt:
print("\n[credential-server] shutting down", flush=True)
server.server_close()
if __name__ == "__main__":
main()