2026-06-12 01:58:46 +02:00
|
|
|
# retoor <retoor@molodetz.nl>
|
|
|
|
|
|
2026-06-14 02:16:22 +02:00
|
|
|
import time
|
2026-05-10 09:08:12 +02:00
|
|
|
from pathlib import Path
|
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
from os import environ
|
|
|
|
|
|
|
|
|
|
load_dotenv()
|
|
|
|
|
|
|
|
|
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
|
|
|
STATIC_DIR = BASE_DIR / "devplacepy" / "static"
|
|
|
|
|
TEMPLATES_DIR = BASE_DIR / "devplacepy" / "templates"
|
chore: consolidate runtime data layout under single `data/` root directory
Migrate all runtime artifacts (database, uploads, VAPID keys, locks, bot state, container workspaces, zip staging) from scattered locations (`var/`, `devplacepy/static/uploads/`) into a unified `data/` directory. Update `config.py` as single source of truth with `DATA_PATHS` registry and `ensure_data_dirs()`, add `devplace migrate-data` CLI command with CRC verification and idempotent relocation, adjust `.dockerignore`, `.env.example`, `.gitignore`, `Dockerfile`, `Makefile`, `README.md`, `AGENTS.md`, `CLAUDE.md`, and all import paths in `attachments.py` to reference `config.UPLOADS_DIR`/`ATTACHMENTS_DIR` instead of computing from `STATIC_DIR`.
2026-06-13 21:06:43 +02:00
|
|
|
|
|
|
|
|
# Single source of truth for every runtime/user-generated artifact. Everything the
|
|
|
|
|
# app creates or modifies at runtime lives under DATA_DIR, never inside the package
|
|
|
|
|
# and never served via /static. Overridable by DEVPLACE_DATA_DIR (point at a volume
|
|
|
|
|
# in production). Each path below is derived from DATA_DIR; no other module computes
|
|
|
|
|
# a runtime path from scratch.
|
|
|
|
|
DATA_DIR = Path(environ.get("DEVPLACE_DATA_DIR", str(BASE_DIR / "data")))
|
|
|
|
|
UPLOADS_DIR = DATA_DIR / "uploads"
|
|
|
|
|
ATTACHMENTS_DIR = UPLOADS_DIR / "attachments"
|
|
|
|
|
PROJECT_FILES_DIR = UPLOADS_DIR / "project_files"
|
|
|
|
|
CONTAINER_WORKSPACES_DIR = DATA_DIR / "container_workspaces"
|
|
|
|
|
ZIPS_DIR = DATA_DIR / "zips"
|
|
|
|
|
ZIP_STAGING_DIR = DATA_DIR / "zip_staging"
|
|
|
|
|
FORK_STAGING_DIR = DATA_DIR / "fork_staging"
|
2026-06-14 02:16:22 +02:00
|
|
|
SEO_REPORTS_DIR = DATA_DIR / "seo_reports"
|
chore: consolidate runtime data layout under single `data/` root directory
Migrate all runtime artifacts (database, uploads, VAPID keys, locks, bot state, container workspaces, zip staging) from scattered locations (`var/`, `devplacepy/static/uploads/`) into a unified `data/` directory. Update `config.py` as single source of truth with `DATA_PATHS` registry and `ensure_data_dirs()`, add `devplace migrate-data` CLI command with CRC verification and idempotent relocation, adjust `.dockerignore`, `.env.example`, `.gitignore`, `Dockerfile`, `Makefile`, `README.md`, `AGENTS.md`, `CLAUDE.md`, and all import paths in `attachments.py` to reference `config.UPLOADS_DIR`/`ATTACHMENTS_DIR` instead of computing from `STATIC_DIR`.
2026-06-13 21:06:43 +02:00
|
|
|
KEYS_DIR = DATA_DIR / "keys"
|
|
|
|
|
BOT_DIR = DATA_DIR / "bot"
|
|
|
|
|
LOCKS_DIR = DATA_DIR / "locks"
|
|
|
|
|
|
|
|
|
|
DEVII_TASKS_DB = DATA_DIR / "devii_tasks.db"
|
|
|
|
|
DEVII_LESSONS_DB = DATA_DIR / "devii_lessons.db"
|
|
|
|
|
|
2026-06-09 18:48:08 +02:00
|
|
|
DATABASE_URL = environ.get(
|
chore: consolidate runtime data layout under single `data/` root directory
Migrate all runtime artifacts (database, uploads, VAPID keys, locks, bot state, container workspaces, zip staging) from scattered locations (`var/`, `devplacepy/static/uploads/`) into a unified `data/` directory. Update `config.py` as single source of truth with `DATA_PATHS` registry and `ensure_data_dirs()`, add `devplace migrate-data` CLI command with CRC verification and idempotent relocation, adjust `.dockerignore`, `.env.example`, `.gitignore`, `Dockerfile`, `Makefile`, `README.md`, `AGENTS.md`, `CLAUDE.md`, and all import paths in `attachments.py` to reference `config.UPLOADS_DIR`/`ATTACHMENTS_DIR` instead of computing from `STATIC_DIR`.
2026-06-13 21:06:43 +02:00
|
|
|
"DEVPLACE_DATABASE_URL", f"sqlite:///{DATA_DIR / 'devplace.db'}"
|
2026-06-09 18:48:08 +02:00
|
|
|
)
|
2026-05-10 09:08:12 +02:00
|
|
|
SECRET_KEY = environ.get("SECRET_KEY", "devplace-secret-key-change-in-production")
|
2026-06-06 16:31:42 +02:00
|
|
|
SECONDS_PER_DAY = 86400
|
|
|
|
|
SESSION_MAX_AGE = SECONDS_PER_DAY * 7
|
|
|
|
|
SESSION_MAX_AGE_REMEMBER = SECONDS_PER_DAY * 30
|
2026-05-10 09:08:12 +02:00
|
|
|
PORT = 10500
|
2026-05-23 03:21:55 +02:00
|
|
|
SITE_URL = environ.get("DEVPLACE_SITE_URL", "").rstrip("/")
|
2026-05-23 10:03:27 +02:00
|
|
|
|
2026-06-14 02:16:22 +02:00
|
|
|
# Cache-busting version stamped onto every app-owned static URL. Computed once at
|
|
|
|
|
# process start, so a restart/deploy changes it and busts every browser cache while
|
|
|
|
|
# assets stay heavily cached (immutable, 1 year) between deploys. Set
|
|
|
|
|
# DEVPLACE_STATIC_VERSION at launch so multiple prod workers share one value.
|
|
|
|
|
STATIC_VERSION = environ.get("DEVPLACE_STATIC_VERSION") or str(int(time.time()))
|
|
|
|
|
|
2026-06-09 18:48:08 +02:00
|
|
|
INTERNAL_BASE_URL = environ.get(
|
|
|
|
|
"DEVPLACE_INTERNAL_BASE_URL", f"http://localhost:{PORT}"
|
|
|
|
|
).rstrip("/")
|
feat: add api key auth, devii agent, openai gateway, and admin service management
This commit introduces a comprehensive set of new features including API key authentication with CLI management commands (get, reset, backfill), a Devii agentic assistant with WebSocket terminal and session bootstrap, an OpenAI-compatible LLM gateway service, and an admin service management panel. It also adds Playwright browser automation for bot support, configures internal gateway URLs, refactors content editing/deletion to support JSON API responses, and updates documentation across AGENTS.md, README.md, and the developer docs site.
2026-06-08 17:38:33 +02:00
|
|
|
INTERNAL_GATEWAY_URL = f"{INTERNAL_BASE_URL}/openai/v1/chat/completions"
|
|
|
|
|
INTERNAL_MODEL = "molodetz"
|
2026-06-14 03:06:18 +02:00
|
|
|
INTERNAL_EMBED_MODEL = "molodetz~embed"
|
feat: add api key auth, devii agent, openai gateway, and admin service management
This commit introduces a comprehensive set of new features including API key authentication with CLI management commands (get, reset, backfill), a Devii agentic assistant with WebSocket terminal and session bootstrap, an OpenAI-compatible LLM gateway service, and an admin service management panel. It also adds Playwright browser automation for bot support, configures internal gateway URLs, refactors content editing/deletion to support JSON API responses, and updates documentation across AGENTS.md, README.md, and the developer docs site.
2026-06-08 17:38:33 +02:00
|
|
|
|
chore: consolidate runtime data layout under single `data/` root directory
Migrate all runtime artifacts (database, uploads, VAPID keys, locks, bot state, container workspaces, zip staging) from scattered locations (`var/`, `devplacepy/static/uploads/`) into a unified `data/` directory. Update `config.py` as single source of truth with `DATA_PATHS` registry and `ensure_data_dirs()`, add `devplace migrate-data` CLI command with CRC verification and idempotent relocation, adjust `.dockerignore`, `.env.example`, `.gitignore`, `Dockerfile`, `Makefile`, `README.md`, `AGENTS.md`, `CLAUDE.md`, and all import paths in `attachments.py` to reference `config.UPLOADS_DIR`/`ATTACHMENTS_DIR` instead of computing from `STATIC_DIR`.
2026-06-13 21:06:43 +02:00
|
|
|
SERVICE_LOCK_FILE = LOCKS_DIR / "devplace-services.lock"
|
|
|
|
|
INIT_LOCK_FILE = LOCKS_DIR / "devplace-init.lock"
|
2026-06-02 23:17:51 +02:00
|
|
|
|
2026-06-09 16:06:02 +02:00
|
|
|
# Every container instance runs this one prebuilt image (built once via `make ppy`).
|
|
|
|
|
CONTAINER_IMAGE = environ.get("DEVPLACE_CONTAINER_IMAGE", "ppy:latest")
|
2026-06-10 09:11:56 +02:00
|
|
|
# Override host the /p/<slug> ingress proxy dials, with the published host port,
|
|
|
|
|
# instead of the container's own bridge IP. Set this only for topologies where
|
|
|
|
|
# the app cannot route to the container network directly (containerized app via
|
|
|
|
|
# docker socket: use host.docker.internal). Left empty, the proxy connects
|
|
|
|
|
# straight to the container IP and container port, which avoids the host
|
|
|
|
|
# port-publishing layer (docker-proxy / iptables DNAT / loopback) entirely.
|
|
|
|
|
CONTAINER_PROXY_HOST = environ.get("DEVPLACE_CONTAINER_PROXY_HOST", "").strip()
|
2026-06-09 06:41:27 +02:00
|
|
|
|
chore: consolidate runtime data layout under single `data/` root directory
Migrate all runtime artifacts (database, uploads, VAPID keys, locks, bot state, container workspaces, zip staging) from scattered locations (`var/`, `devplacepy/static/uploads/`) into a unified `data/` directory. Update `config.py` as single source of truth with `DATA_PATHS` registry and `ensure_data_dirs()`, add `devplace migrate-data` CLI command with CRC verification and idempotent relocation, adjust `.dockerignore`, `.env.example`, `.gitignore`, `Dockerfile`, `Makefile`, `README.md`, `AGENTS.md`, `CLAUDE.md`, and all import paths in `attachments.py` to reference `config.UPLOADS_DIR`/`ATTACHMENTS_DIR` instead of computing from `STATIC_DIR`.
2026-06-13 21:06:43 +02:00
|
|
|
VAPID_PRIVATE_KEY_FILE = KEYS_DIR / "notification-private.pem"
|
|
|
|
|
VAPID_PRIVATE_KEY_PKCS8_FILE = KEYS_DIR / "notification-private.pkcs8.pem"
|
|
|
|
|
VAPID_PUBLIC_KEY_FILE = KEYS_DIR / "notification-public.pem"
|
2026-05-23 10:03:27 +02:00
|
|
|
VAPID_SUB = environ.get("DEVPLACE_VAPID_SUB", "mailto:retoor@molodetz.nl")
|
chore: consolidate runtime data layout under single `data/` root directory
Migrate all runtime artifacts (database, uploads, VAPID keys, locks, bot state, container workspaces, zip staging) from scattered locations (`var/`, `devplacepy/static/uploads/`) into a unified `data/` directory. Update `config.py` as single source of truth with `DATA_PATHS` registry and `ensure_data_dirs()`, add `devplace migrate-data` CLI command with CRC verification and idempotent relocation, adjust `.dockerignore`, `.env.example`, `.gitignore`, `Dockerfile`, `Makefile`, `README.md`, `AGENTS.md`, `CLAUDE.md`, and all import paths in `attachments.py` to reference `config.UPLOADS_DIR`/`ATTACHMENTS_DIR` instead of computing from `STATIC_DIR`.
2026-06-13 21:06:43 +02:00
|
|
|
|
|
|
|
|
# Documented registry of every runtime directory. ensure_data_dirs() creates them
|
|
|
|
|
# all at startup so the tree always exists before the DB, keys, locks, uploads, and
|
|
|
|
|
# job staging are written.
|
|
|
|
|
DATA_PATHS: dict[str, Path] = {
|
|
|
|
|
"data": DATA_DIR,
|
|
|
|
|
"uploads": UPLOADS_DIR,
|
|
|
|
|
"attachments": ATTACHMENTS_DIR,
|
|
|
|
|
"project_files": PROJECT_FILES_DIR,
|
|
|
|
|
"container_workspaces": CONTAINER_WORKSPACES_DIR,
|
|
|
|
|
"zips": ZIPS_DIR,
|
|
|
|
|
"zip_staging": ZIP_STAGING_DIR,
|
|
|
|
|
"fork_staging": FORK_STAGING_DIR,
|
2026-06-14 02:16:22 +02:00
|
|
|
"seo_reports": SEO_REPORTS_DIR,
|
chore: consolidate runtime data layout under single `data/` root directory
Migrate all runtime artifacts (database, uploads, VAPID keys, locks, bot state, container workspaces, zip staging) from scattered locations (`var/`, `devplacepy/static/uploads/`) into a unified `data/` directory. Update `config.py` as single source of truth with `DATA_PATHS` registry and `ensure_data_dirs()`, add `devplace migrate-data` CLI command with CRC verification and idempotent relocation, adjust `.dockerignore`, `.env.example`, `.gitignore`, `Dockerfile`, `Makefile`, `README.md`, `AGENTS.md`, `CLAUDE.md`, and all import paths in `attachments.py` to reference `config.UPLOADS_DIR`/`ATTACHMENTS_DIR` instead of computing from `STATIC_DIR`.
2026-06-13 21:06:43 +02:00
|
|
|
"keys": KEYS_DIR,
|
|
|
|
|
"bot": BOT_DIR,
|
|
|
|
|
"locks": LOCKS_DIR,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def ensure_data_dirs() -> None:
|
|
|
|
|
for path in DATA_PATHS.values():
|
|
|
|
|
path.mkdir(parents=True, exist_ok=True)
|