Skip to content

Latest commit

 

History

History
64 lines (43 loc) · 3.23 KB

File metadata and controls

64 lines (43 loc) · 3.23 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

SyncServer is a FastAPI/Uvicorn HTTP+WebSocket server for synchronizing Minecraft schematics across game servers. Clients are grouped into named pools (e.g. practice, build-team); each pool has its own isolated schematic storage, WebSocket broadcast channel, and backup stream.

Running

pip install -r requirements.txt
python app.py

No build step. No test suite. Configuration is read from conf.txt (copy from conf.txt.example), or from $SCHEMSYNC_CONF.

Configuration

conf.txt (key=value, inline # comments stripped):

Key Default Env override
host 0.0.0.0 SCHEMSYNC_HOST
port 8756 SCHEMSYNC_PORT
api_key change-me-in-production SCHEMSYNC_API_KEY
data_dir data (relative to app.py) SCHEMSYNC_DATA
backup_hours 12.0 SCHEMSYNC_BACKUP_HOURS

Architecture

The entire application lives in app.py — one file, no packages.

Startup flow: load_settings() → create SCHEMATICS_ROOT/BACKUPS_ROOT → register FastAPI routes → launch backup_loop() via @app.on_event("startup").

Pool model: All /v1/ endpoints are prefixed with /{pool}. Pools are auto-created on first authenticated use (pool_schematics_dir() calls mkdir(exist_ok=True)). Pool names are validated by _POOL_RE = r"^[A-Za-z0-9_-]{1,64}$" — reject anything else with 400.

Storage layout:

data/schematics/<pool>/...   ← schematic files
data/backups/<pool>/...      ← zip backups

Auth: Single master api_key. HTTP endpoints use X-API-Key header via the require_api_key FastAPI dependency. WebSocket uses ?token= query param. Pool creation is implicitly gated — no unauthenticated request reaches pool-touching code.

WebSocket broadcast: _ws_pools: dict[str, set[WebSocket]] — one set per pool. _broadcast(pool, msg) fans out to that pool's set and silently prunes dead connections. broadcast_schematic(pool, path) and broadcast_repo_resync(pool) are the two public helpers.

Path security: safe_relative_path() rejects .. and leading /. pool_schematics_dir() / pool_backups_dir() resolve and create the per-pool directory.

File mtime preservation: Upload accepts X-Client-Mtime-Ms (ms since epoch) → os.utime. Download returns X-Mtime-Ms header.

Backup loop: Sleeps first, then iterates every directory under SCHEMATICS_ROOT, zipping each pool independently to data/backups/<pool>/schematics-YYYYMMDD-HHMMSS.zip. Minimum 1 h enforced.

API Endpoints

Method Path Notes
GET /health Returns config path + list of existing pools; no auth
GET /v1/{pool}/list JSON array of {path, mtime_ms, size}
GET /v1/{pool}/file/{path} File download; X-Mtime-Ms response header
POST /v1/{pool}/upload Multipart: path field + file field
POST /v1/{pool}/notify/repo-resync Broadcasts repo_resync to pool
POST /v1/{pool}/hook/plugin JSON body {path}, broadcasts schematic_updated to pool
WS /v1/{pool}/ws ?token=<api_key>; scoped to pool