Copy architecture docs, ADRs, storage domain specs, research, reviews, and 56 storage architecture tasks from the alkhub_ts monorepo. Adapt for standalone @alkdev/hub repo structure (src/ not packages/hub/). Sanitize all sensitive information: - Replace private IPs (10.0.0.1) with localhost defaults - Remove internal server hostnames (dev1, ns528096) - Replace /workspace/ private paths with npm package references - Remove hardcoded credentials from examples - Rewrite infrastructure.md without private network details Add Deno project scaffolding: deno.json (pinned deps), .gitignore, AGENTS.md, entry point. Migrate existing code stubs (crypto, config types, logger) with updated import paths.
39 lines
3.2 KiB
Markdown
39 lines
3.2 KiB
Markdown
# ADR-008: Secrets encrypted at rest with key versioning
|
|
|
|
- **Status**: Accepted (revised 2026-04-23)
|
|
- **Date**: 2026-04-19
|
|
- **Revised**: 2026-04-23
|
|
- **Deciders**: alkdev
|
|
|
|
## Context
|
|
|
|
API keys, passwords, OAuth tokens, and SSH keys for external services must be stored securely. The crypto.ts utility from ade-v0 (AES-256-GCM + PBKDF2 with key version support) is battle-tested.
|
|
|
|
The original decision specified reading the encryption key from an environment variable (`HUB_ENCRYPTION_KEY`). This is a security concern: environment variables are readable via `/proc/PID/environ` by any process with the same UID on the host, and are visible in `docker inspect`. In a multi-container Docker environment, this is a real attack surface.
|
|
|
|
## Decision
|
|
|
|
Copy crypto.ts to packages/core/utils/crypto.ts. Store encrypted secrets in client_secrets.value as EncryptedData { keyVersion, salt, iv, data }.
|
|
|
|
**Two-layer key model** (revised from original):
|
|
|
|
1. **Master key** — Provisioned via Docker secret (`/run/secrets/hub_master_key`). tmpfs-backed, never on container filesystem, not visible in `/proc/environ`. Used only to decrypt the config file's encrypted fields. Rarely rotated (requires redeploying the Docker secret).
|
|
|
|
2. **Data encryption keys** — Stored in the config file's `encryptionKeys` field (itself encrypted with the master key). Multi-key format: `v1:base64,v2:base64` — the first key is "current" (used for new encryptions), all keys are available for decryption (enables rotation). Generated via `crypto.generateEncryptionKey()`. Rotated by updating the config file and re-encrypting `client_secrets` rows — no Docker secret change needed.
|
|
|
|
Key versioning supports rotation — bump keyVersion, re-encrypt on next access. The rotation protocol is defined in storage/services.md.
|
|
|
|
**No environment variables for secrets or important configuration.** This is a hard rule. Non-sensitive convenience vars (e.g., `ALKHUB_CONFIG_PATH`) are acceptable. Nothing that would be damaging if exposed via `/proc` may be in an env var.
|
|
|
|
Full config system specification: [docs/architecture/hub-config.md](../docs/architecture/hub-config.md).
|
|
Startup sequence: [docs/architecture/hub-startup.md](../docs/architecture/hub-startup.md).
|
|
|
|
## Consequences
|
|
|
|
Encryption keys must be available at runtime. If lost, all secrets unrecoverable. Standard for symmetric encryption.
|
|
|
|
**Positive**: Key versioning enables rotation without downtime. Proven crypto implementation. Docker secrets eliminate the `/proc/environ` leak vector. Two-layer keys allow independent rotation schedules (master key rarely, data keys as needed). Config file with encrypted fields is safe to version-control (ciphertext only).
|
|
|
|
**Negative**: Encryption key loss means total data loss (same as before). Two keys to manage instead of one. Slightly more complex deployment (mount config file + secret, rather than just setting env vars). Config file must be prepared with the `alkhub-config` CLI tool before deployment.
|
|
|
|
**Mitigated by**: Storing master key in Docker secrets (not DB, not env), supporting key rotation so compromised keys can be cycled, `alkhub-config` tool automating config file preparation, infrastructure.md documenting the Docker deployment pattern. |