diff --git a/AGENTS.md b/AGENTS.md index cc04a80..0214009 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,7 @@ # Rune-Vault (rune-admin) Single-binary Go gRPC server (`runevault`) for FHE-encrypted organizational -memory. Built on `github.com/CryptoLabInc/envector-go-sdk`. The secret key +memory. Built on `github.com/CryptoLabInc/runespace-sdk`. The secret key never leaves this server. ## Setup diff --git a/CLAUDE.md b/CLAUDE.md index d562d4a..497f4a4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,7 +1,7 @@ # Rune-Vault (rune-admin) Single-binary Go gRPC server (`runevault`) for FHE-encrypted organizational -memory. Built on `github.com/CryptoLabInc/envector-go-sdk`. The secret key +memory. Built on `github.com/CryptoLabInc/runespace-sdk`. The secret key never leaves this server. ## Setup diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 40f82c3..25f7438 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -78,7 +78,7 @@ See [CLAUDE.md](CLAUDE.md#commands) (or [AGENTS.md](AGENTS.md#commands)) for the ``` vault/internal/ ├── tokens/ # Token store + role/rate-limit unit tests -├── crypto/ # HKDF + AES-CTR + envector-go-sdk wrappers +├── crypto/ # HKDF + AES-CTR + runespace-sdk wrappers ├── server/ # gRPC handlers, interceptors, audit, admin UDS, config ├── commands/ # CLI subcommands + admin client └── tests/ # E2E (build tag `e2e`): decrypt pipeline (fixture-based) + CLI smoke diff --git a/README.md b/README.md index 8300597..32426c1 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ For system architecture and data flow details, see [docs/ARCHITECTURE.md](docs/A ### For Administrators -1. **enVector Cloud account** at [https://envector.io](https://envector.io) — Cluster Endpoint and API Key +1. **Runespace account** at [https://runespace.example.com](https://runespace.example.com) — Cluster Endpoint and API Key 2. **Cloud provider account** (AWS, GCP, or OCI) — only needed for cloud deployment The [installer](#quick-start) auto-checks for the tools it needs (`terraform` and the relevant cloud CLI when targeting a CSP). @@ -33,8 +33,8 @@ The [installer](#quick-start) auto-checks for the tools it needs (`terraform` an Team members install [Rune](https://github.com/CryptoLabInc/rune) from Claude Marketplace and configure it with: - Vault Endpoint (provided by admin) - Vault Token (provided by admin) -- enVector Cluster Endpoint (provided by admin) -- enVector API Key (provided by admin) +- Runespace Cluster Endpoint (provided by admin) +- Runespace API Key (provided by admin) ## Quick Start @@ -54,7 +54,7 @@ curl -fsSL https://raw.githubusercontent.com/CryptoLabInc/rune-admin/main/instal | sudo bash -s -- --target aws # or gcp, oci ``` -The installer prompts for team name, enVector endpoint, and CSP-specific +The installer prompts for team name, Runespace endpoint, and CSP-specific inputs (region, GCP project ID, OCI compartment OCID). Use `--non-interactive` plus the `RUNEVAULT_*` env vars listed in [`install.sh`](install.sh) for CI. @@ -83,8 +83,8 @@ sudo runevault token issue --user alice --role member --expires 90d # Share via secure channel (1Password, Signal, etc.): # - Vault Endpoint # - Vault Token -# - enVector Cluster Endpoint -# - enVector API Key +# - Runespace Cluster Endpoint +# - Runespace API Key ``` Members of the `runevault` group can run the CLI without `sudo`. diff --git a/deployment/aws/cloud-init.yaml b/deployment/aws/cloud-init.yaml index 54bdacd..6fe10e8 100644 --- a/deployment/aws/cloud-init.yaml +++ b/deployment/aws/cloud-init.yaml @@ -6,8 +6,8 @@ write_files: - path: /etc/profile.d/runevault-installer-env.sh content: | export RUNEVAULT_TEAM_NAME='${team_name}' - export RUNEVAULT_ENVECTOR_ENDPOINT='${envector_endpoint}' - export RUNEVAULT_ENVECTOR_API_KEY='${envector_api_key}' + export RUNEVAULT_RUNESPACE_ENDPOINT='${runespace_endpoint}' + export RUNEVAULT_RUNESPACE_TOKEN='${runespace_token}' permissions: '0600' runcmd: diff --git a/deployment/aws/main.tf b/deployment/aws/main.tf index f9e3ef5..494a0f3 100644 --- a/deployment/aws/main.tf +++ b/deployment/aws/main.tf @@ -32,13 +32,13 @@ variable "tls_mode" { default = "self-signed" } -variable "envector_endpoint" { - description = "enVector Cloud endpoint" +variable "runespace_endpoint" { + description = "Runespace endpoint" type = string } -variable "envector_api_key" { - description = "enVector Cloud API key" +variable "runespace_token" { + description = "Runespace API key" type = string sensitive = true } @@ -197,8 +197,8 @@ resource "aws_instance" "vault" { user_data = templatefile("${path.module}/cloud-init.yaml", { team_name = var.team_name - envector_endpoint = var.envector_endpoint - envector_api_key = var.envector_api_key + runespace_endpoint = var.runespace_endpoint + runespace_token = var.runespace_token runevault_version = var.runevault_version }) diff --git a/deployment/gcp/main.tf b/deployment/gcp/main.tf index 3a5d9f0..f99b55c 100644 --- a/deployment/gcp/main.tf +++ b/deployment/gcp/main.tf @@ -47,13 +47,13 @@ variable "tls_mode" { default = "self-signed" } -variable "envector_endpoint" { - description = "enVector Cloud endpoint" +variable "runespace_endpoint" { + description = "Runespace endpoint" type = string } -variable "envector_api_key" { - description = "enVector Cloud API key" +variable "runespace_token" { + description = "Runespace API key" type = string sensitive = true } @@ -152,8 +152,8 @@ resource "google_compute_instance" "vault" { metadata_startup_script = templatefile("${path.module}/startup-script.sh", { team_name = var.team_name - envector_endpoint = var.envector_endpoint - envector_api_key = var.envector_api_key + runespace_endpoint = var.runespace_endpoint + runespace_token = var.runespace_token runevault_version = var.runevault_version }) diff --git a/deployment/gcp/startup-script.sh b/deployment/gcp/startup-script.sh index 217f7a6..5ae8638 100644 --- a/deployment/gcp/startup-script.sh +++ b/deployment/gcp/startup-script.sh @@ -10,8 +10,8 @@ done cat > /etc/profile.d/runevault-installer-env.sh <<'ENVFILE' export RUNEVAULT_TEAM_NAME='${team_name}' -export RUNEVAULT_ENVECTOR_ENDPOINT='${envector_endpoint}' -export RUNEVAULT_ENVECTOR_API_KEY='${envector_api_key}' +export RUNEVAULT_RUNESPACE_ENDPOINT='${runespace_endpoint}' +export RUNEVAULT_RUNESPACE_TOKEN='${runespace_token}' ENVFILE chmod 600 /etc/profile.d/runevault-installer-env.sh set -a; . /etc/profile.d/runevault-installer-env.sh; set +a diff --git a/deployment/oci/main.tf b/deployment/oci/main.tf index 39febaa..1930a3d 100644 --- a/deployment/oci/main.tf +++ b/deployment/oci/main.tf @@ -43,13 +43,13 @@ variable "tls_mode" { default = "self-signed" } -variable "envector_endpoint" { - description = "enVector Cloud endpoint" +variable "runespace_endpoint" { + description = "Runespace endpoint" type = string } -variable "envector_api_key" { - description = "enVector Cloud API key" +variable "runespace_token" { + description = "Runespace API key" type = string sensitive = true } @@ -164,8 +164,8 @@ resource "oci_core_instance" "vault_instance" { ssh_authorized_keys = var.public_key user_data = base64encode(templatefile("${path.module}/startup-script.sh", { team_name = var.team_name - envector_endpoint = var.envector_endpoint - envector_api_key = var.envector_api_key + runespace_endpoint = var.runespace_endpoint + runespace_token = var.runespace_token runevault_version = var.runevault_version })) } diff --git a/deployment/oci/startup-script.sh b/deployment/oci/startup-script.sh index 6ecfaea..bcc8262 100644 --- a/deployment/oci/startup-script.sh +++ b/deployment/oci/startup-script.sh @@ -13,8 +13,8 @@ done cat > /etc/profile.d/runevault-installer-env.sh <<'ENVFILE' export RUNEVAULT_TEAM_NAME='${team_name}' -export RUNEVAULT_ENVECTOR_ENDPOINT='${envector_endpoint}' -export RUNEVAULT_ENVECTOR_API_KEY='${envector_api_key}' +export RUNEVAULT_RUNESPACE_ENDPOINT='${runespace_endpoint}' +export RUNEVAULT_RUNESPACE_TOKEN='${runespace_token}' ENVFILE chmod 600 /etc/profile.d/runevault-installer-env.sh set -a; . /etc/profile.d/runevault-installer-env.sh; set +a diff --git a/docs-public/ARCHITECTURE.md b/docs-public/ARCHITECTURE.md index 355be82..677f4dd 100644 --- a/docs-public/ARCHITECTURE.md +++ b/docs-public/ARCHITECTURE.md @@ -7,7 +7,7 @@ Rune-Vault is the **infrastructure backbone** for team-shared FHE-encrypted orga ### Core Responsibilities 1. **Key Management**: Generate, store, and protect FHE keys (secret key isolation) -2. **Decryption Service**: Decrypt search results from enVector Cloud +2. **Decryption Service**: Decrypt search results from Runespace 3. **Authentication**: Validate team member access via tokens 4. **Access Control**: Per-user RBAC with role-based top_k limits, scope enforcement, and rate limiting 5. **Audit Logging**: Structured JSON logs for compliance and debugging @@ -29,7 +29,7 @@ Rune-Vault is the **infrastructure backbone** for team-shared FHE-encrypted orga │ MCP tool calls ▼ ┌────────────────────────────┐ - │ envector-mcp-server(s) │ ← Scalable + │ runespace-mcp-server(s) │ ← Scalable │ (Public Keys only) │ │ │ │ Tools: │ @@ -42,8 +42,8 @@ Rune-Vault is the **infrastructure backbone** for team-shared FHE-encrypted orga │ │ (called by remember) ▼ ▼ ┌──────────────────────┐ ┌────────────────────────────┐ - │ enVector Cloud(SaaS) │ │ Rune-Vault │ - │ https://envector.io │ │ (Your Infrastructure) │ + │ Runespace(SaaS) │ │ Rune-Vault │ + │ https://runespace.example.com │ │ (Your Infrastructure) │ │ │ │ │ │ - Encrypted vectors │ │ ┌──────────────────────┐ │ │ - Encrypted │ │ │ FHE Key Manager │ │ @@ -67,7 +67,7 @@ Rune-Vault is the **infrastructure backbone** for team-shared FHE-encrypted orga └────────────────────────────┘ ``` -**Key**: Agents never contact Vault directly. The envector-mcp-server's +**Key**: Agents never contact Vault directly. The runespace-mcp-server's `remember` tool orchestrates the Vault decryption call as part of its 3-step pipeline. Secret key never leaves Vault. @@ -92,7 +92,7 @@ Rune-Vault is the **infrastructure backbone** for team-shared FHE-encrypted orga **Runtime**: - Single-binary Go gRPC daemon (`runevault`) — no runtime dependencies beyond TLS -- gRPC server on port 50051 (used by envector-mcp-server) +- gRPC server on port 50051 (used by runespace-mcp-server) - gRPC health check via `grpc.health.v1` protocol - Admin Unix domain socket at `/opt/runevault/admin.sock` (mode 0600, vault-user owned) - Registered as a native systemd unit (`runevault.service`) on Linux or a launchd job (`com.cryptolabinc.runevault`) on macOS @@ -127,20 +127,20 @@ Defined in `proto/vault_service.proto` (`rune.vault.v1.VaultService`). **`GetPublicKey()`** - Returns: JSON bundle containing EncKey, EvalKey, index_name, key_id, agent_id, agent_dek (per-user derived encryption key) -- Used by: envector-mcp-server at startup +- Used by: runespace-mcp-server at startup - Auth: Required (validates token + scope check) **`DecryptScores()`** - Input: Result ciphertext from encrypted similarity search (base64-serialized) - Returns: Top-K typed `ScoreEntry` messages (shard_idx, row_idx, score) -- Used by: envector-mcp-server's `remember` pipeline (per search query) +- Used by: runespace-mcp-server's `remember` pipeline (per search query) - Auth: Required (validates token + scope check) - Policy: Per-role top_k limit (admin: 50, member: 10). Proto constraint: 1-300 range. **`DecryptMetadata()`** - Input: List of AES-encrypted metadata blobs. Each blob is JSON `{"a": "", "c": ""}`. - Returns: Decrypted metadata (JSON strings) -- Used by: envector-mcp-server's `remember` pipeline +- Used by: runespace-mcp-server's `remember` pipeline - Auth: Required (validates token + scope check) - Vault derives the agent's DEK via HKDF-SHA256 from team secret + agent_id. @@ -176,7 +176,7 @@ Custom roles can be created via `runevault role create`. 2. `/opt/runevault/configs/runevault.conf` 3. `./runevault.conf` (cwd, dev only) -Secret YAML fields (`tokens.team_secret`, `envector.api_key`) accept a sibling `*_file` key for KMS-backed deployments. +Secret YAML fields (`tokens.team_secret`, `runespace.token`) accept a sibling `*_file` key for KMS-backed deployments. ### 4. Admin Socket & CLI @@ -281,13 +281,13 @@ User: "What decisions did we make about database?" ▼ AI Agent (Claude/Gemini/Codex) │ - ├── 1. Call envector-mcp-server `remember` tool + ├── 1. Call runespace-mcp-server `remember` tool │ ▼ -envector-mcp-server (`remember` orchestration) +runespace-mcp-server (`remember` orchestration) │ ├── 2. Embed query (auto-embedded if text, or accepts vector/JSON) - ├── 3. Encrypted similarity scoring on enVector Cloud + ├── 3. Encrypted similarity scoring on Runespace │ → Returns result ciphertext (base64) │ ├── 4. Call Vault: DecryptScores(token, ciphertext, top_k) via gRPC @@ -301,9 +301,9 @@ Vault (gRPC — secret key holder) ├── 8. Return [{index: 42, score: 0.95}, ...] │ ▼ -envector-mcp-server (continued) +runespace-mcp-server (continued) │ - ├── 9. Retrieve metadata for top-k indices from enVector Cloud + ├── 9. Retrieve metadata for top-k indices from Runespace ├── 10. Return results to Agent │ ▼ @@ -311,7 +311,7 @@ AI Agent → User: "In Q2 2024, team chose PostgreSQL for JSON support..." ``` **Key**: The Agent never contacts Vault directly. The `remember` tool -in envector-mcp-server orchestrates the entire 3-step pipeline. +in runespace-mcp-server orchestrates the entire 3-step pipeline. Secret key never leaves Vault. **`search` vs `remember`**: The `search` tool is for the operator's own @@ -325,13 +325,13 @@ indiscriminately decrypting shared vectors. ### Threat Model **Assumptions**: -- enVector Cloud is **untrusted** (sees only ciphertext) +- Runespace is **untrusted** (sees only ciphertext) - Network is **untrusted** (TLS required) - Team members' laptops are **trusted** (Rune runs locally) - Vault VM is **trusted** (admin controls infrastructure) **Threats Mitigated**: -1. **Cloud Provider Breach**: enVector Cloud compromise → no plaintext leak (FHE) +1. **Cloud Provider Breach**: Runespace compromise → no plaintext leak (FHE) 2. **Network Eavesdropping**: MITM attacks → TLS encryption 3. **Unauthorized Access**: Non-team members → token authentication 4. **Key Theft**: secret key extraction → architectural isolation (no export API) @@ -413,7 +413,7 @@ Cloud Resources Created ``` Common Terraform variables across all CSPs: `team_name`, `tls_mode`, -`envector_endpoint`, `envector_api_key`, `runevault_version`, +`runespace_endpoint`, `runespace_token`, `runevault_version`, `public_key`, `region`. CSP-specific: `instance_type` (AWS), `project_id` / `zone` / `machine_type` (GCP), `oci_profile` / `compartment_id` (OCI). Output: `vault_public_ip`. @@ -489,7 +489,7 @@ When to scale: | `vault/internal/commands` | CLI subcommands (`daemon`, `token`, `role`, `status`, `logs`, `version`) and admin-socket client | | `vault/internal/server` | gRPC server, config loader, audit logger, admin UDS, `EnsureVault` startup hook, interceptors | | `vault/internal/tokens` | Per-user RBAC store: tokens, roles, validation, rate limiting, YAML persistence | -| `vault/internal/crypto` | FHE key management + HKDF/AES wrappers around `envector-go-sdk` | +| `vault/internal/crypto` | FHE key management + HKDF/AES wrappers around `runespace-sdk` | | `vault/internal/tests` | E2E tests gated by build tag `e2e` (decrypt pipeline + CLI smoke) | | `vault/pkg/vaultpb` | Generated gRPC stubs from `vault/proto/*.proto` | diff --git a/install.sh b/install.sh index 4833620..06de7a9 100755 --- a/install.sh +++ b/install.sh @@ -20,15 +20,15 @@ # # Non-interactive env vars (local install): # RUNEVAULT_TEAM_NAME keys.index_name (required) -# RUNEVAULT_ENVECTOR_ENDPOINT envector.endpoint (required) -# RUNEVAULT_ENVECTOR_API_KEY envector.api_key -# RUNEVAULT_ENVECTOR_API_KEY_FILE envector.api_key_file (alternative) +# RUNEVAULT_RUNESPACE_ENDPOINT runespace.endpoint (required) +# RUNEVAULT_RUNESPACE_TOKEN runespace.token +# RUNEVAULT_RUNESPACE_TOKEN_FILE runespace.token_file (alternative) # RUNEVAULT_TLS_CERT_PATH Path to existing TLS cert (skips auto-gen) # RUNEVAULT_TLS_KEY_PATH Path to existing TLS key (skips auto-gen) # # Non-interactive env vars (CSP install — operator workstation): -# RUNEVAULT_ENVECTOR_ENDPOINT enVector endpoint URL (required) -# RUNEVAULT_ENVECTOR_API_KEY enVector API key (required) +# RUNEVAULT_RUNESPACE_ENDPOINT Runespace endpoint URL (required) +# RUNEVAULT_RUNESPACE_TOKEN Runespace API key (required) # RUNEVAULT_TEAM_NAME Team name — used for resource naming and vault index (required) # RUNEVAULT_TARGET Pre-select target without interactive menu # RUNEVAULT_INSTALL_DIR Pre-set CSP install directory @@ -301,14 +301,14 @@ csp_prompt_config() { printf ' Cloud deployment configuration\n' printf '══════════════════════════════════════════════════════════\n' printf '\n' - printf ' Create your enVector cluster at https://envector.io\n' + printf ' Create your Runespace cluster at https://runespace.example.com\n' printf ' before proceeding. You will need the endpoint URL and\n' printf ' API key from the dashboard.\n' printf '\n' _prompt TEAM_NAME "Team name" "" - _prompt ENVECTOR_ENDPOINT "enVector endpoint" "" - _prompt ENVECTOR_API_KEY "enVector API key" "" + _prompt RUNESPACE_ENDPOINT "Runespace endpoint" "" + _prompt RUNESPACE_TOKEN "Runespace API key" "" case "$csp" in aws) _prompt CSP_REGION "AWS region" "us-east-1" ;; @@ -324,16 +324,16 @@ csp_prompt_config() { printf '\n' else TEAM_NAME="${RUNEVAULT_TEAM_NAME:-}" - ENVECTOR_ENDPOINT="${RUNEVAULT_ENVECTOR_ENDPOINT:-}" - ENVECTOR_API_KEY="${RUNEVAULT_ENVECTOR_API_KEY:-}" + RUNESPACE_ENDPOINT="${RUNEVAULT_RUNESPACE_ENDPOINT:-}" + RUNESPACE_TOKEN="${RUNEVAULT_RUNESPACE_TOKEN:-}" CSP_REGION="${RUNEVAULT_CSP_REGION:-}" GCP_PROJECT_ID="${RUNEVAULT_GCP_PROJECT_ID:-}" OCI_COMPARTMENT_ID="${RUNEVAULT_OCI_COMPARTMENT_ID:-}" local missing=() [[ -z "$TEAM_NAME" ]] && missing+=("RUNEVAULT_TEAM_NAME") - [[ -z "$ENVECTOR_ENDPOINT" ]] && missing+=("RUNEVAULT_ENVECTOR_ENDPOINT") - [[ -z "$ENVECTOR_API_KEY" ]] && missing+=("RUNEVAULT_ENVECTOR_API_KEY") + [[ -z "$RUNESPACE_ENDPOINT" ]] && missing+=("RUNEVAULT_RUNESPACE_ENDPOINT") + [[ -z "$RUNESPACE_TOKEN" ]] && missing+=("RUNEVAULT_RUNESPACE_TOKEN") [[ "$csp" = gcp && -z "$GCP_PROJECT_ID" ]] && missing+=("RUNEVAULT_GCP_PROJECT_ID") [[ "$csp" = oci && -z "$OCI_COMPARTMENT_ID" ]] && missing+=("RUNEVAULT_OCI_COMPARTMENT_ID") if [[ ${#missing[@]} -gt 0 ]]; then @@ -344,8 +344,8 @@ csp_prompt_config() { fi [[ -n "$TEAM_NAME" ]] || die "Team name is required." - [[ -n "$ENVECTOR_ENDPOINT" ]] || die "enVector endpoint is required." - [[ -n "$ENVECTOR_API_KEY" ]] || die "enVector API key is required." + [[ -n "$RUNESPACE_ENDPOINT" ]] || die "Runespace endpoint is required." + [[ -n "$RUNESPACE_TOKEN" ]] || die "Runespace API key is required." if [[ "$csp" = gcp ]]; then [[ -n "$GCP_PROJECT_ID" ]] || die "GCP project ID is required." fi @@ -430,8 +430,8 @@ csp_render_tfvars() { { printf 'team_name = "%s"\n' "$(escape_tf "${TEAM_NAME:-default}")" printf 'tls_mode = "self-signed"\n' - printf 'envector_endpoint = "%s"\n' "$(escape_tf "${ENVECTOR_ENDPOINT}")" - printf 'envector_api_key = "%s"\n' "$(escape_tf "${ENVECTOR_API_KEY}")" + printf 'runespace_endpoint = "%s"\n' "$(escape_tf "${RUNESPACE_ENDPOINT}")" + printf 'runespace_token = "%s"\n' "$(escape_tf "${RUNESPACE_TOKEN}")" printf 'runevault_version = "%s"\n' "$(escape_tf "${VERSION}")" printf 'public_key = "%s"\n' "$(escape_tf "${public_key}")" printf 'region = "%s"\n' "$(escape_tf "${CSP_REGION}")" @@ -1013,9 +1013,9 @@ collect_and_write_config() { info "Config already exists (use --force to overwrite): ${conf_file}" else local team_name="${RUNEVAULT_TEAM_NAME:-}" - local envector_endpoint="${RUNEVAULT_ENVECTOR_ENDPOINT:-}" - local envector_api_key="${RUNEVAULT_ENVECTOR_API_KEY:-}" - local envector_api_key_file="${RUNEVAULT_ENVECTOR_API_KEY_FILE:-}" + local runespace_endpoint="${RUNEVAULT_RUNESPACE_ENDPOINT:-}" + local runespace_token="${RUNEVAULT_RUNESPACE_TOKEN:-}" + local runespace_token_file="${RUNEVAULT_RUNESPACE_TOKEN_FILE:-}" local team_secret="${RUNEVAULT_TEAM_SECRET:-}" if [[ "$NON_INTERACTIVE" -eq 0 ]]; then @@ -1026,18 +1026,18 @@ collect_and_write_config() { printf '\n' [[ -z "$team_name" ]] \ && read -r -p "Team name (vault index identifier): " team_name - [[ -z "$envector_endpoint" ]] \ - && read -r -p "enVector endpoint URL: " envector_endpoint - if [[ -z "$envector_api_key" && -z "$envector_api_key_file" ]]; then - read -r -p "enVector API key: " envector_api_key + [[ -z "$runespace_endpoint" ]] \ + && read -r -p "Runespace endpoint URL: " runespace_endpoint + if [[ -z "$runespace_token" && -z "$runespace_token_file" ]]; then + read -r -p "Runespace API key: " runespace_token fi printf '\n' else local missing=() [[ -z "$team_name" ]] && missing+=("RUNEVAULT_TEAM_NAME") - [[ -z "$envector_endpoint" ]] && missing+=("RUNEVAULT_ENVECTOR_ENDPOINT") - [[ -z "$envector_api_key" && -z "$envector_api_key_file" ]] \ - && missing+=("RUNEVAULT_ENVECTOR_API_KEY or RUNEVAULT_ENVECTOR_API_KEY_FILE") + [[ -z "$runespace_endpoint" ]] && missing+=("RUNEVAULT_RUNESPACE_ENDPOINT") + [[ -z "$runespace_token" && -z "$runespace_token_file" ]] \ + && missing+=("RUNEVAULT_RUNESPACE_TOKEN or RUNEVAULT_RUNESPACE_TOKEN_FILE") if [[ ${#missing[@]} -gt 0 ]]; then printf 'ERROR: Missing required env vars for non-interactive install:\n' >&2 for v in "${missing[@]}"; do printf ' %s\n' "$v" >&2; done @@ -1050,15 +1050,15 @@ collect_and_write_config() { fi [[ -n "$team_name" ]] || die "team_name is required." - [[ -n "$envector_endpoint" ]] || die "envector_endpoint is required." - [[ -n "$envector_api_key" || -n "$envector_api_key_file" ]] \ - || die "enVector API key or key file is required." + [[ -n "$runespace_endpoint" ]] || die "runespace_endpoint is required." + [[ -n "$runespace_token" || -n "$runespace_token_file" ]] \ + || die "Runespace API key or key file is required." - local api_key_line - if [[ -n "$envector_api_key_file" ]]; then - api_key_line=" api_key_file: ${envector_api_key_file}" + local token_line + if [[ -n "$runespace_token_file" ]]; then + token_line=" token_file: ${runespace_token_file}" else - api_key_line=" api_key: ${envector_api_key}" + token_line=" token: ${runespace_token}" fi info "Writing ${conf_file}..." @@ -1079,9 +1079,9 @@ collect_and_write_config() { " index_name: ${team_name}" \ " embedding_dim: 1024" \ "" \ - "envector:" \ - " endpoint: ${envector_endpoint}" \ - "${api_key_line}" \ + "runespace:" \ + " endpoint: ${runespace_endpoint}" \ + "${token_line}" \ "" \ "tokens:" \ " team_secret: ${team_secret}" \ diff --git a/scripts/generate-test-fixtures.py b/scripts/generate-test-fixtures.py index d09ba69..7cbe409 100644 --- a/scripts/generate-test-fixtures.py +++ b/scripts/generate-test-fixtures.py @@ -7,7 +7,7 @@ to tests/fixtures/ for use in CI without cloud access. Usage: - ENVECTOR_ENDPOINT=... ENVECTOR_API_KEY=... python scripts/generate-test-fixtures.py + RUNESPACE_ENDPOINT=... RUNESPACE_TOKEN=... python scripts/generate-test-fixtures.py """ import base64 @@ -30,10 +30,10 @@ def main(): - endpoint = os.getenv("ENVECTOR_ENDPOINT") - api_key = os.getenv("ENVECTOR_API_KEY") - if not endpoint or not api_key: - print("Error: ENVECTOR_ENDPOINT and ENVECTOR_API_KEY must be set.") + endpoint = os.getenv("RUNESPACE_ENDPOINT") + token = os.getenv("RUNESPACE_TOKEN") + if not endpoint or not token: + print("Error: RUNESPACE_ENDPOINT and RUNESPACE_TOKEN must be set.") sys.exit(1) import pyenvector as ev @@ -68,7 +68,7 @@ def main(): dim=DIM, eval_mode="rmp", auto_key_setup=False, - access_token=api_key, + access_token=token, query_encryption="plain", ) try: @@ -90,7 +90,7 @@ def main(): dim=DIM, eval_mode="rmp", auto_key_setup=True, - access_token=api_key, + access_token=token, query_encryption="plain", ) print(" Connected with fresh keys.") diff --git a/scripts/install-dev.sh b/scripts/install-dev.sh index ef0d58a..c39a939 100755 --- a/scripts/install-dev.sh +++ b/scripts/install-dev.sh @@ -25,8 +25,8 @@ # over SSH after cloud-init finishes. # # Non-interactive env vars (CSP install — operator workstation): -# RUNEVAULT_ENVECTOR_ENDPOINT enVector endpoint URL (required) -# RUNEVAULT_ENVECTOR_API_KEY enVector API key (required) +# RUNEVAULT_RUNESPACE_ENDPOINT Runespace endpoint URL (required) +# RUNEVAULT_RUNESPACE_TOKEN Runespace API key (required) # RUNEVAULT_TEAM_NAME Team name (required) # RUNEVAULT_TARGET Pre-select target without interactive menu # RUNEVAULT_INSTALL_DIR Pre-set CSP install directory @@ -53,8 +53,8 @@ CSP_PUBLIC_IP="" # CSP config (populated by dev_csp_prompt_config) TEAM_NAME="" -ENVECTOR_ENDPOINT="" -ENVECTOR_API_KEY="" +RUNESPACE_ENDPOINT="" +RUNESPACE_TOKEN="" CSP_REGION="" GCP_PROJECT_ID="" OCI_COMPARTMENT_ID="" @@ -273,16 +273,16 @@ dev_local_prompt_config() { printf '\n' _prompt RUNEVAULT_TEAM_NAME "Team name" "devteam" - _prompt RUNEVAULT_ENVECTOR_ENDPOINT "enVector endpoint" "" - _prompt RUNEVAULT_ENVECTOR_API_KEY "enVector API key" "" + _prompt RUNEVAULT_RUNESPACE_ENDPOINT "Runespace endpoint" "" + _prompt RUNEVAULT_RUNESPACE_TOKEN "Runespace API key" "" printf '\n' - [[ -n "${RUNEVAULT_ENVECTOR_ENDPOINT:-}" ]] || die "enVector endpoint is required." - [[ -n "${RUNEVAULT_ENVECTOR_API_KEY:-}" ]] || die "enVector API key is required." + [[ -n "${RUNEVAULT_RUNESPACE_ENDPOINT:-}" ]] || die "Runespace endpoint is required." + [[ -n "${RUNEVAULT_RUNESPACE_TOKEN:-}" ]] || die "Runespace API key is required." else RUNEVAULT_TEAM_NAME="${RUNEVAULT_TEAM_NAME:-devteam}" - RUNEVAULT_ENVECTOR_ENDPOINT="${RUNEVAULT_ENVECTOR_ENDPOINT:-https://envector.example.com}" - RUNEVAULT_ENVECTOR_API_KEY="${RUNEVAULT_ENVECTOR_API_KEY:-dev-api-key-placeholder}" + RUNEVAULT_RUNESPACE_ENDPOINT="${RUNEVAULT_RUNESPACE_ENDPOINT:-https://runespace.example.com}" + RUNEVAULT_RUNESPACE_TOKEN="${RUNEVAULT_RUNESPACE_TOKEN:-dev-api-key-placeholder}" fi } @@ -293,8 +293,8 @@ dev_local_install() { export RUNEVAULT_LOCAL_BINARY="$LOCAL_BINARY_HOST" export RUNEVAULT_TEAM_NAME - export RUNEVAULT_ENVECTOR_ENDPOINT - export RUNEVAULT_ENVECTOR_API_KEY + export RUNEVAULT_RUNESPACE_ENDPOINT + export RUNEVAULT_RUNESPACE_TOKEN if [[ -n "$PREFIX" ]]; then export RUNEVAULT_INSTALL_PREFIX="$PREFIX" @@ -374,8 +374,8 @@ dev_csp_prompt_config() { printf '\n' _prompt TEAM_NAME "Team name" "devteam" - _prompt ENVECTOR_ENDPOINT "enVector endpoint" "" - _prompt ENVECTOR_API_KEY "enVector API key" "" + _prompt RUNESPACE_ENDPOINT "Runespace endpoint" "" + _prompt RUNESPACE_TOKEN "Runespace API key" "" case "$csp" in aws) _prompt CSP_REGION "AWS region" "us-east-1" ;; @@ -391,16 +391,16 @@ dev_csp_prompt_config() { printf '\n' else TEAM_NAME="${RUNEVAULT_TEAM_NAME:-}" - ENVECTOR_ENDPOINT="${RUNEVAULT_ENVECTOR_ENDPOINT:-}" - ENVECTOR_API_KEY="${RUNEVAULT_ENVECTOR_API_KEY:-}" + RUNESPACE_ENDPOINT="${RUNEVAULT_RUNESPACE_ENDPOINT:-}" + RUNESPACE_TOKEN="${RUNEVAULT_RUNESPACE_TOKEN:-}" CSP_REGION="${RUNEVAULT_CSP_REGION:-}" GCP_PROJECT_ID="${RUNEVAULT_GCP_PROJECT_ID:-}" OCI_COMPARTMENT_ID="${RUNEVAULT_OCI_COMPARTMENT_ID:-}" local missing=() [[ -z "$TEAM_NAME" ]] && missing+=("RUNEVAULT_TEAM_NAME") - [[ -z "$ENVECTOR_ENDPOINT" ]] && missing+=("RUNEVAULT_ENVECTOR_ENDPOINT") - [[ -z "$ENVECTOR_API_KEY" ]] && missing+=("RUNEVAULT_ENVECTOR_API_KEY") + [[ -z "$RUNESPACE_ENDPOINT" ]] && missing+=("RUNEVAULT_RUNESPACE_ENDPOINT") + [[ -z "$RUNESPACE_TOKEN" ]] && missing+=("RUNEVAULT_RUNESPACE_TOKEN") [[ "$csp" = gcp && -z "$GCP_PROJECT_ID" ]] && missing+=("RUNEVAULT_GCP_PROJECT_ID") [[ "$csp" = oci && -z "$OCI_COMPARTMENT_ID" ]] && missing+=("RUNEVAULT_OCI_COMPARTMENT_ID") if [[ ${#missing[@]} -gt 0 ]]; then @@ -411,8 +411,8 @@ dev_csp_prompt_config() { fi [[ -n "$TEAM_NAME" ]] || die "Team name is required." - [[ -n "$ENVECTOR_ENDPOINT" ]] || die "enVector endpoint is required." - [[ -n "$ENVECTOR_API_KEY" ]] || die "enVector API key is required." + [[ -n "$RUNESPACE_ENDPOINT" ]] || die "Runespace endpoint is required." + [[ -n "$RUNESPACE_TOKEN" ]] || die "Runespace API key is required." if [[ "$csp" = gcp ]]; then [[ -n "$GCP_PROJECT_ID" ]] || die "GCP project ID is required." fi @@ -489,8 +489,8 @@ dev_csp_render_tfvars() { { printf 'team_name = "%s"\n' "$(escape_tf "${TEAM_NAME:-default}")" printf 'tls_mode = "self-signed"\n' - printf 'envector_endpoint = "%s"\n' "$(escape_tf "${ENVECTOR_ENDPOINT}")" - printf 'envector_api_key = "%s"\n' "$(escape_tf "${ENVECTOR_API_KEY}")" + printf 'runespace_endpoint = "%s"\n' "$(escape_tf "${RUNESPACE_ENDPOINT}")" + printf 'runespace_token = "%s"\n' "$(escape_tf "${RUNESPACE_TOKEN}")" printf 'runevault_version = "dev"\n' printf 'public_key = "%s"\n' "$(escape_tf "${public_key}")" printf 'region = "%s"\n' "$(escape_tf "${CSP_REGION}")" @@ -584,14 +584,14 @@ dev_csp_upload_and_install() { info "Running install.sh on the VM..." local tn ee ek tn=$(escape_single "$TEAM_NAME") - ee=$(escape_single "$ENVECTOR_ENDPOINT") - ek=$(escape_single "$ENVECTOR_API_KEY") + ee=$(escape_single "$RUNESPACE_ENDPOINT") + ek=$(escape_single "$RUNESPACE_TOKEN") local remote_cmd remote_cmd="sudo \ RUNEVAULT_LOCAL_BINARY=/tmp/runevault-${TARGET_OS}-${TARGET_ARCH} \ RUNEVAULT_TEAM_NAME='${tn}' \ - RUNEVAULT_ENVECTOR_ENDPOINT='${ee}' \ - RUNEVAULT_ENVECTOR_API_KEY='${ek}' \ + RUNEVAULT_RUNESPACE_ENDPOINT='${ee}' \ + RUNEVAULT_RUNESPACE_TOKEN='${ek}' \ bash /tmp/install.sh --target local --non-interactive --version dev" # shellcheck disable=SC2086 diff --git a/tests/FIXTURES.md b/tests/FIXTURES.md index 7549fe1..2466d82 100644 --- a/tests/FIXTURES.md +++ b/tests/FIXTURES.md @@ -17,7 +17,7 @@ The CI workflow (`ci.yml`) always references one of these by name. A fixture upd ### Prerequisites -- enVector Cloud access (`ENVECTOR_ENDPOINT`, `ENVECTOR_API_KEY`) +- Runespace access (`RUNESPACE_ENDPOINT`, `RUNESPACE_TOKEN`) - GitHub repo admin access (to update Secrets) - `mise run setup` completed @@ -54,10 +54,10 @@ gh secret set FIXTURES_GPG_PASSPHRASE_ALT #### 4. Generate new fixtures ```bash -ENVECTOR_ENDPOINT=... ENVECTOR_API_KEY=... python scripts/generate-test-fixtures.py +RUNESPACE_ENDPOINT=... RUNESPACE_TOKEN=... python scripts/generate-test-fixtures.py ``` -This connects to enVector Cloud and writes plaintext fixtures to `tests/fixtures/`. +This connects to Runespace and writes plaintext fixtures to `tests/fixtures/`. #### 5. Encrypt fixtures with the new passphrase diff --git a/vault/internal/commands/daemon.go b/vault/internal/commands/daemon.go index 6aceff7..9e4e4e4 100644 --- a/vault/internal/commands/daemon.go +++ b/vault/internal/commands/daemon.go @@ -62,9 +62,9 @@ func runDaemonStart(ctx context.Context) error { // Open the full key set, dial runespace, and register the eval key. eng, err := crypto.OpenEngine(ctx, crypto.EngineParams{ Keys: keyParams, - Endpoint: cfg.Envector.Endpoint, - Token: cfg.Envector.APIKey, - Insecure: true, // integration test: runespace served plaintext on localhost + Endpoint: cfg.Runespace.Endpoint, + Token: cfg.Runespace.Token, + Insecure: cfg.Runespace.Insecure, // TLS by default; set runespace.insecure=true only for a localhost runespace }) if err != nil { return fmt.Errorf("daemon: open runespace engine: %w", err) diff --git a/vault/internal/crypto/metadata.go b/vault/internal/crypto/metadata.go index b7bb685..810c4f5 100644 --- a/vault/internal/crypto/metadata.go +++ b/vault/internal/crypto/metadata.go @@ -1,5 +1,5 @@ // Package crypto provides metadata key derivation, AES-256-CTR metadata -// encryption, and FHE key lifecycle wrappers around envector-go-sdk. +// encryption, and FHE key lifecycle wrappers around runespace-sdk. // // Wire format for metadata ciphertext: // diff --git a/vault/internal/server/config.go b/vault/internal/server/config.go index 8f0d036..966a0eb 100644 --- a/vault/internal/server/config.go +++ b/vault/internal/server/config.go @@ -27,11 +27,11 @@ const expectedSecretMode fs.FileMode = 0o640 // Config is the in-memory shape of runevault.conf. Field names follow the // YAML schema exactly so the loader can decode without an intermediate type. type Config struct { - Server ServerConfig `yaml:"server"` - Keys KeysConfig `yaml:"keys"` - Envector EnvectorConfig `yaml:"envector"` - Tokens TokensConfig `yaml:"tokens"` - Audit AuditConfig `yaml:"audit"` + Server ServerConfig `yaml:"server"` + Keys KeysConfig `yaml:"keys"` + Runespace RunespaceConfig `yaml:"runespace"` + Tokens TokensConfig `yaml:"tokens"` + Audit AuditConfig `yaml:"audit"` // Source records where this Config was loaded from (resolved absolute // path), populated by LoadConfig. Empty for in-memory test configs. @@ -65,14 +65,11 @@ type KeysConfig struct { EmbeddingDim int `yaml:"embedding_dim"` } -// EnvectorConfig accepts either an inline api_key or an api_key_file -// pointing at a 0600-mode file containing the same value. If both are -// set, api_key_file wins. Resolve() materialises the final string into -// APIKey and clears APIKeyFile. -type EnvectorConfig struct { - Endpoint string `yaml:"endpoint"` - APIKey string `yaml:"api_key"` - APIKeyFile string `yaml:"api_key_file"` +type RunespaceConfig struct { + Endpoint string `yaml:"endpoint"` + Token string `yaml:"token"` + TokenFile string `yaml:"token_file"` + Insecure bool `yaml:"insecure"` // default: false (true only for development; runespace on localhost) } type TokensConfig struct { @@ -150,13 +147,13 @@ func resolveConfigPath(override string) (path string, searched []string, err err // Returns an error if any referenced secret file has a permissive mode // (anything looser than 0o640). Idempotent. func (c *Config) Resolve() error { - if c.Envector.APIKeyFile != "" { - val, err := readSecretFile(c.Envector.APIKeyFile, "envector.api_key_file") + if c.Runespace.TokenFile != "" { + val, err := readSecretFile(c.Runespace.TokenFile, "runespace.token_file") if err != nil { return err } - c.Envector.APIKey = val - c.Envector.APIKeyFile = "" + c.Runespace.Token = val + c.Runespace.TokenFile = "" } if c.Tokens.TeamSecretFile != "" { val, err := readSecretFile(c.Tokens.TeamSecretFile, "tokens.team_secret_file") @@ -201,11 +198,11 @@ func checkSecretMode(path, label string) error { // admin endpoints that surface configuration to operators. func (c *Config) Redact() Config { out := *c - if out.Envector.APIKey != "" { - out.Envector.APIKey = "[REDACTED]" + if out.Runespace.Token != "" { + out.Runespace.Token = "[REDACTED]" } - if out.Envector.APIKeyFile != "" { - out.Envector.APIKeyFile = "[REDACTED]" + if out.Runespace.TokenFile != "" { + out.Runespace.TokenFile = "[REDACTED]" } if out.Tokens.TeamSecret != "" { out.Tokens.TeamSecret = "[REDACTED]" diff --git a/vault/internal/server/config_test.go b/vault/internal/server/config_test.go index 85d8f60..ae4ec1f 100644 --- a/vault/internal/server/config_test.go +++ b/vault/internal/server/config_test.go @@ -21,9 +21,9 @@ func minimalValidConfig(t *testing.T) string { keys: path: /tmp/vault-keys embedding_dim: 1024 -envector: +runespace: endpoint: https://example.com - api_key: inline-api-key + token: inline-api-key tokens: team_secret: inline-team-secret-deadbeef roles_file: /tmp/roles.yml @@ -103,16 +103,16 @@ func TestLoadConfigUnknownFieldsRejected(t *testing.T) { } } -func TestLoadConfigAPIKeyFileIndirection(t *testing.T) { +func TestLoadConfigTokenFileIndirection(t *testing.T) { dir := t.TempDir() - keyFile := filepath.Join(dir, "envector.key") + keyFile := filepath.Join(dir, "runespace.key") if err := os.WriteFile(keyFile, []byte("file-api-key\n"), 0o600); err != nil { t.Fatal(err) } body := strings.Replace( minimalValidConfig(t), - " api_key: inline-api-key", - " api_key_file: "+keyFile, + " token: inline-api-key", + " token_file: "+keyFile, 1, ) path := writeConfig(t, body) @@ -120,11 +120,11 @@ func TestLoadConfigAPIKeyFileIndirection(t *testing.T) { if err != nil { t.Fatal(err) } - if cfg.Envector.APIKey != "file-api-key" { - t.Errorf("api_key = %q, want file-api-key", cfg.Envector.APIKey) + if cfg.Runespace.Token != "file-api-key" { + t.Errorf("token = %q, want file-api-key", cfg.Runespace.Token) } - if cfg.Envector.APIKeyFile != "" { - t.Errorf("api_key_file should be cleared after Resolve, got %q", cfg.Envector.APIKeyFile) + if cfg.Runespace.TokenFile != "" { + t.Errorf("token_file should be cleared after Resolve, got %q", cfg.Runespace.TokenFile) } } @@ -205,15 +205,15 @@ func TestLoadConfigSecretFileMissing(t *testing.T) { func TestRedactMasksSecrets(t *testing.T) { cfg := &Config{ - Envector: EnvectorConfig{APIKey: "deadbeef", APIKeyFile: "/x"}, - Tokens: TokensConfig{TeamSecret: "supersecret", TeamSecretFile: "/y"}, + Runespace: RunespaceConfig{Token: "deadbeef", TokenFile: "/x"}, + Tokens: TokensConfig{TeamSecret: "supersecret", TeamSecretFile: "/y"}, } r := cfg.Redact() - if r.Envector.APIKey != "[REDACTED]" { - t.Errorf("api_key not redacted: %q", r.Envector.APIKey) + if r.Runespace.Token != "[REDACTED]" { + t.Errorf("token not redacted: %q", r.Runespace.Token) } - if r.Envector.APIKeyFile != "[REDACTED]" { - t.Errorf("api_key_file not redacted: %q", r.Envector.APIKeyFile) + if r.Runespace.TokenFile != "[REDACTED]" { + t.Errorf("token_file not redacted: %q", r.Runespace.TokenFile) } if r.Tokens.TeamSecret != "[REDACTED]" { t.Errorf("team_secret not redacted: %q", r.Tokens.TeamSecret) @@ -222,7 +222,7 @@ func TestRedactMasksSecrets(t *testing.T) { t.Errorf("team_secret_file not redacted: %q", r.Tokens.TeamSecretFile) } // Original must be untouched. - if cfg.Envector.APIKey != "deadbeef" { + if cfg.Runespace.Token != "deadbeef" { t.Errorf("Redact mutated original") } } diff --git a/vault/internal/server/testdata/runevault.conf.example b/vault/internal/server/testdata/runevault.conf.example index 70243e9..029a9e8 100644 --- a/vault/internal/server/testdata/runevault.conf.example +++ b/vault/internal/server/testdata/runevault.conf.example @@ -24,10 +24,10 @@ keys: index_name: my-team embedding_dim: 1024 -envector: - endpoint: https://envector.example.com - api_key: REPLACE_WITH_API_KEY - # Alternative: api_key_file: /run/secrets/envector_api_key +runespace: + endpoint: https://runespace.example.com + token: REPLACE_WITH_TOKEN + # Alternative: token_file: /run/secrets/runespace_token tokens: team_secret: REPLACE_WITH_RANDOM_HEX_32 diff --git a/vault/internal/tests/e2e_test.go b/vault/internal/tests/e2e_test.go index 33d3ddf..17921cf 100644 --- a/vault/internal/tests/e2e_test.go +++ b/vault/internal/tests/e2e_test.go @@ -41,9 +41,9 @@ func TestE2EDaemonLifecycle(t *testing.T) { keys: path: %[1]s/keys embedding_dim: 1024 -envector: +runespace: endpoint: "" - api_key: "" + token: "" tokens: team_secret: smoke-secret roles_file: %[1]s/roles.yml