Initial commit: site monorepo with API, web, and infra.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
from urllib.parse import ParseResult, urlparse, urlunparse
|
||||
from uuid import uuid4
|
||||
|
||||
from app.core.crypto import generate_install_bundle
|
||||
|
||||
_API_ROOT = Path(__file__).resolve().parents[2]
|
||||
_INSTALL_SECRETS_ROOT = Path(os.getenv("COMPTON_INSTALL_SECRETS_DIR", str(_API_ROOT / "data" / "secrets")))
|
||||
INSTALL_SECRETS_DIR = _INSTALL_SECRETS_ROOT
|
||||
INSTALL_SECRETS_FILE = INSTALL_SECRETS_DIR / "install.env"
|
||||
INSTALL_SECRETS_META_FILE = INSTALL_SECRETS_DIR / "install.meta.json"
|
||||
REQUIRED_KEYS = (
|
||||
"POSTGRES_USER",
|
||||
"POSTGRES_PASSWORD",
|
||||
"POSTGRES_DB",
|
||||
"DATABASE_URL",
|
||||
"JWT_ACCESS_SECRET",
|
||||
"JWT_REFRESH_PEPPER",
|
||||
"S3_ACCESS_KEY",
|
||||
"S3_SECRET_KEY",
|
||||
"MINIO_ROOT_USER",
|
||||
"MINIO_ROOT_PASSWORD",
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class InstallSecretsStatus:
|
||||
initialized: bool
|
||||
locked: bool
|
||||
path: str
|
||||
created: bool
|
||||
|
||||
|
||||
def _parse_env_text(raw: str) -> dict[str, str]:
|
||||
values: dict[str, str] = {}
|
||||
for line in raw.splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
key, value = line.split("=", 1)
|
||||
values[key.strip()] = value.strip()
|
||||
return values
|
||||
|
||||
|
||||
def _render_env(values: dict[str, str]) -> str:
|
||||
ordered = [f"{key}={values[key]}" for key in sorted(values.keys())]
|
||||
return "\n".join(ordered) + "\n"
|
||||
|
||||
|
||||
def read_install_secrets() -> dict[str, str]:
|
||||
if not INSTALL_SECRETS_FILE.exists():
|
||||
return {}
|
||||
return _parse_env_text(INSTALL_SECRETS_FILE.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def _write_install_secrets(values: dict[str, str]) -> None:
|
||||
INSTALL_SECRETS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
INSTALL_SECRETS_FILE.write_text(_render_env(values), encoding="utf-8")
|
||||
|
||||
|
||||
def _write_meta() -> None:
|
||||
payload = (
|
||||
"{\n"
|
||||
f' "install_id": "{uuid4()}",\n'
|
||||
f' "locked_at": "{datetime.now(UTC).isoformat()}"\n'
|
||||
"}\n"
|
||||
)
|
||||
INSTALL_SECRETS_META_FILE.write_text(payload, encoding="utf-8")
|
||||
|
||||
|
||||
def _is_postgres_database_url(database_url: str) -> bool:
|
||||
scheme = urlparse(database_url).scheme.lower()
|
||||
return scheme.startswith("postgresql") or scheme.startswith("postgres+")
|
||||
|
||||
|
||||
def _adopt_from_environment() -> dict[str, str]:
|
||||
env_values = {key: os.getenv(key, "") for key in REQUIRED_KEYS if key != "DATABASE_URL"}
|
||||
db_url = os.getenv("DATABASE_URL", "")
|
||||
if db_url and _is_postgres_database_url(db_url):
|
||||
parsed = urlparse(db_url)
|
||||
if parsed.username:
|
||||
env_values["POSTGRES_USER"] = parsed.username
|
||||
if parsed.password:
|
||||
env_values["POSTGRES_PASSWORD"] = parsed.password
|
||||
if parsed.path and parsed.path != "/":
|
||||
env_values["POSTGRES_DB"] = parsed.path.lstrip("/")
|
||||
env_values["DATABASE_URL"] = db_url
|
||||
return {key: value for key, value in env_values.items() if value}
|
||||
|
||||
|
||||
def _sync_minio_s3_secrets(values: dict[str, str]) -> dict[str, str]:
|
||||
"""MinIO root credentials are the S3 access key pair — keep them aligned."""
|
||||
if (
|
||||
values.get("S3_ACCESS_KEY") == values.get("MINIO_ROOT_USER")
|
||||
and values.get("MINIO_ROOT_PASSWORD")
|
||||
and values.get("S3_SECRET_KEY") != values["MINIO_ROOT_PASSWORD"]
|
||||
):
|
||||
values = dict(values)
|
||||
values["S3_SECRET_KEY"] = values["MINIO_ROOT_PASSWORD"]
|
||||
return values
|
||||
|
||||
|
||||
def load_install_secrets_to_env() -> None:
|
||||
values = _sync_minio_s3_secrets(read_install_secrets())
|
||||
for key, value in values.items():
|
||||
os.environ[key] = value
|
||||
|
||||
|
||||
def ensure_install_secrets() -> InstallSecretsStatus:
|
||||
existing = read_install_secrets()
|
||||
if existing:
|
||||
db_url = existing.get("DATABASE_URL", "")
|
||||
if db_url and not _is_postgres_database_url(db_url):
|
||||
raise RuntimeError(
|
||||
"install.env DATABASE_URL must be PostgreSQL (got SQLite). "
|
||||
"Remove apps/api/data/secrets/install.env and run: python apps/api/scripts/bootstrap_install.py"
|
||||
)
|
||||
synced = _sync_minio_s3_secrets(existing)
|
||||
if synced != existing:
|
||||
synced["SECRETS_LOCKED"] = existing.get("SECRETS_LOCKED", "true")
|
||||
_write_install_secrets(synced)
|
||||
existing = synced
|
||||
load_install_secrets_to_env()
|
||||
return InstallSecretsStatus(True, existing.get("SECRETS_LOCKED", "false") == "true", str(INSTALL_SECRETS_FILE), False)
|
||||
|
||||
adopted = _adopt_from_environment()
|
||||
generated = generate_install_bundle()
|
||||
values = generated | adopted
|
||||
values["SECRETS_LOCKED"] = "true"
|
||||
_write_install_secrets(values)
|
||||
_write_meta()
|
||||
load_install_secrets_to_env()
|
||||
return InstallSecretsStatus(True, True, str(INSTALL_SECRETS_FILE), True)
|
||||
|
||||
|
||||
def masked_database_url(database_url: str) -> str:
|
||||
parsed = urlparse(database_url)
|
||||
if not parsed.username:
|
||||
return database_url
|
||||
password = "***" if parsed.password else ""
|
||||
credentials = f"{parsed.username}:{password}" if password else parsed.username
|
||||
host = parsed.hostname or ""
|
||||
if parsed.port:
|
||||
host = f"{host}:{parsed.port}"
|
||||
netloc = f"{credentials}@{host}"
|
||||
sanitized = ParseResult(
|
||||
scheme=parsed.scheme,
|
||||
netloc=netloc,
|
||||
path=parsed.path,
|
||||
params=parsed.params,
|
||||
query=parsed.query,
|
||||
fragment=parsed.fragment,
|
||||
)
|
||||
return urlunparse(sanitized)
|
||||
|
||||
|
||||
def install_secrets_payload() -> dict:
|
||||
values = read_install_secrets()
|
||||
db = urlparse(values.get("DATABASE_URL", ""))
|
||||
return {
|
||||
"initialized": bool(values),
|
||||
"locked": values.get("SECRETS_LOCKED") == "true",
|
||||
"secrets_path": str(INSTALL_SECRETS_FILE),
|
||||
"database": {
|
||||
"host": db.hostname,
|
||||
"port": db.port,
|
||||
"database": db.path.lstrip("/") if db.path else "",
|
||||
"user": db.username,
|
||||
"password_configured": bool(values.get("POSTGRES_PASSWORD")),
|
||||
},
|
||||
"connection_string_masked": masked_database_url(values.get("DATABASE_URL", "")),
|
||||
"secrets_status": {
|
||||
"jwt_access_secret": "configured" if bool(values.get("JWT_ACCESS_SECRET")) else "missing",
|
||||
"jwt_refresh_pepper": "configured" if bool(values.get("JWT_REFRESH_PEPPER")) else "missing",
|
||||
"postgres_password": "configured" if bool(values.get("POSTGRES_PASSWORD")) else "missing",
|
||||
"s3_secret_key": "configured" if bool(values.get("S3_SECRET_KEY")) else "missing",
|
||||
"password_bcrypt_salt": "per_user_in_db",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def reveal_install_secret(key: str) -> str:
|
||||
mapping = {
|
||||
"database_password": "POSTGRES_PASSWORD",
|
||||
"jwt_access_secret": "JWT_ACCESS_SECRET",
|
||||
"jwt_refresh_pepper": "JWT_REFRESH_PEPPER",
|
||||
"s3_secret_key": "S3_SECRET_KEY",
|
||||
}
|
||||
env_key = mapping.get(key)
|
||||
if not env_key:
|
||||
raise ValueError("UNSUPPORTED_SECRET_KEY")
|
||||
values = read_install_secrets()
|
||||
if env_key in values:
|
||||
return values[env_key]
|
||||
if env_key == "POSTGRES_PASSWORD":
|
||||
database_url = values.get("DATABASE_URL") or os.getenv("DATABASE_URL", "")
|
||||
parsed = urlparse(database_url)
|
||||
return parsed.password or ""
|
||||
return os.getenv(env_key, "")
|
||||
|
||||
Reference in New Issue
Block a user