16 KiB
DoGaMa project state
Read this compact operational baseline before starting a milestone. Open detailed domain documents only when the current work affects them.
Baseline
- Current reference: post-v0.1.1 release-gate correction based on tagged baseline
88a45c7. - Source-facing HTML templates, CSS and browser JavaScript are structurally formatted for maintainability; the primary assets are exposed as
app.css,theme.cssandapp.jswith simple development-friendly cache headers. - SQLite is initialized directly from one embedded current schema and can be reopened safely after first initialization. Development databases from earlier revisions are intentionally unsupported until versioned production migrations are introduced.
- Roadmap milestones 1-10 are implemented; this is the V1 feature baseline.
Architecture
- Go main application: HTTP API, embedded server-rendered UI, authentication/authorization, SQLite, workflows, backups and WASM runtime.
- Private restricted Go agent: sole Docker-socket owner; authenticated typed API; registered-instance and plan-digest binding; no generic Docker proxy.
- Integrations: capability-scoped WebAssembly adapters only. Palworld REST is the reference module.
- Data: SQLite plus canonical allowed server, import and backup roots. Persistent game data lives outside containers.
- Contracts: declarative YAML templates and module manifests validated against JSON Schemas; released snapshots are immutable.
Implemented capabilities
- Bootstrap administrator with required email and persisted language preference, local authentication, secure sessions and CSRF protection.
- Validated embedded catalog, deterministic deployment previews and instance registry.
- Restricted instance create/inspect/start/stop/restart/delete and reconciliation.
- Per-instance memberships, overrides and installation requests with backend authorization.
- Backup scheduling/retention, safe imports, export and restore with safety backups.
- Sandboxed WASM runtime and normalized module API with Palworld reference adapter.
- Game-container configuration: global and per-instance labels, safe label variables, derived instance slug, immutable Docker-user selection, tracked/pinned image tags, immediate or deferred container recreation, and public game-logo/artwork routes.
- Administration stores persistent game-container UID/GID defaults (1000:1000) with decimal uint32 validation. Managed templates use them as Docker
User;user_mode: imageis authoritative and omits DockerUser. Templates can map the values to declared runtime environment variables; V Rising usesPUID/PGIDwhile retaining its root entrypoint and capabilities. - Controlled digest-aware game updates with confirmation, policy-driven pre-update backups, readiness verification, mod warnings and automatic container-plan rollback.
- Redacted configuration history retained to the latest 10 revisions, with pinned-template revalidation and immediate or deferred rollback.
- Declarative Steam Workshop item configuration with numeric-ID validation, stable ordering and backend
mods.manageenforcement. - Encrypted write-only SMTP, generic HTTPS webhook, Discord and Gotify channels with event filters, queued test delivery, bounded retry and redacted terminal errors; SMTP event email is filtered by persistent personal preferences and instance access.
- SSRF-resistant HTTPS webhook delivery with redirect/address revalidation, event IDs, timestamps and optional HMAC-SHA256 signatures.
- Compact allow-listed audit events for authentication and significant mutations, administrator filtering, bounded manual purge, daily retention and maximum-count enforcement.
- Responsive server-rendered application shell with synthwave-derived design tokens, permission-aware navigation, the official DoGaMa wordmark in the sidebar, searchable real instance cards, lifecycle summaries, server-only recent Audit activity and resilient agent/database/storage/backup/audit status on the Dashboard.
- The responsive shell exposes a keyboard-accessible mobile navigation toggle on every authenticated SSR page; all recent-administrator form mutations return an explicit CSRF denial when request verification fails.
- Dedicated administrator Audit and Settings pages; notification channels, audit retention/purge and game-container labels retain their existing backend contracts outside the Dashboard.
- Audit uses server-side filtering and 50-event pagination; timestamps remain UTC in SQLite and are rendered in the Compose
TZIANA timezone with an invalid-zone fallback to UTC. Instance audit events retain a minimal game/name/slug snapshot so history stays readable after instance deletion. - Separate personal account settings and administrator user management, including email/password preferences, active-state session revocation, protected global roles, per-instance memberships and permission overrides.
- Restrictive browser headers and bounded public HTTP headers.
- Hardened read-only two-service Compose, capability dropping, private agent networking and distinct minimal OCI image targets.
- Linux black-box bootstrap/authentication E2E coverage plus a documented disposable-Docker V1 release verification matrix.
- Deterministic Linux
amd64/arm64archives with embedded build identity, SPDX module SBOM and SHA-256 checksums. - Minimal production Compose containing only
dogamaandagent;docker compose up -dis the complete first-start workflow with no initializer, setup command, host UID/GID preparation or user-managed internal secrets. compose-dev.ymlis a local-only overlay for the production Compose: it builds the two local image targets and adds Caddy 2.10.2 withtls internalathttps://dogama.lan. Caddy PKI and configuration are isolated in development named volumes; production imposes no reverse proxy.- Service-owned persistent secrets: the agent atomically creates and validates its mode-
0640shared token in the internalagent_authvolume; the application mounts only that secret directory read-only and independently creates and validates its mode-0600master key below the application data path. The application tolerates concurrent first start by waiting up to 60 seconds for the token and authenticated agent health. - The agent token is exactly 32 opaque random bytes. Readers preserve terminal carriage-return and newline byte values instead of treating the secret as text.
- Two service networks: an administrator-named application/reverse-proxy network plus a private Compose control network. The agent safely ensures the fixed
DOGAMA_GAMES_NETWORKexists and applies it to every game-container create or replacement; it is not caller-selectable through the lifecycle API. - Portable fresh bind-mount startup uses root identities inside the read-only, capability-free container namespaces and a private process umask. No recursive ownership change is performed; game-container UID/GID is controlled by Administration only for managed templates.
- Gitea CI for pull requests and
main, plus tag-only multi-architecture image publication and Gitea Release creation.
Durable decisions
- Editable Docker labels apply only to game-server instance containers.
- Labels on the DoGaMa application container remain Compose configuration and are never read, copied or edited by DoGaMa.
- Merge order is global labels, then instance labels; instance values win. Internal technical labels are applied last and cannot be overridden.
dogama.*andio.dogama.*are reserved label namespaces.- Label values support only the explicit allowlist in
internal/instance/container_config.go; unknown variables are errors, not arbitrary templates. {{game.icon_url}}is the public icon for the game.{{instance.slug}}remains supported.- Template game artwork contains separate required local
logoand horizontalimageassets; template validation rejects missing files. Deployment previews expose distinct logo and artwork URLs while retainingicon_urlas a compatible logo alias. Palworld template1.1.0is the first snapshot with this contract. - Embedded catalog validation is collection-based: every discovered template is schema- and cross-field-validated, including referenced assets, declared template-local integration modules and ports/configuration. A module bundle lives at
<template>/module/, is declared bymodule.path, is path-confined and is retained with the selected snapshot; no game-specific internal registry exists. Template asset contents are not SHA-256-pinned, allowing administrator-maintained local assets while preserving required-path validation. A templateversionidentifies a DoGaMa snapshot, whereascontainer.tagselects the game-server image; the official Palworld template follows Pocketpair'slatesttag for new deployments and ordinary pulls. - Instance slugs are derived from the display name, not canonical IDs. Accents are normalized to ASCII; whitespace,
/, punctuation and special characters become safe hyphen separators; repeated and edge hyphens are removed. - Docker user mode is fixed at creation to the administrator's managed game-container UID/GID or image-defined user. Image-defined templates cannot be overridden. Never perform automatic recursive ownership changes.
- A pinned image tag is an explicit mutable tag, not an immutable digest. Tracked mode follows the template's declared default tag.
- Replacement-requiring changes use the generic
container_config_pendingdesired-versus-applied state. Replacements preserve bind-mounted data and prior running/stopped intent. - The main app never gains Docker-socket access; the agent remains deny-by-default and independently validates privileged plan fields.
- Update candidates are explicit
tag@sha256:digestreferences. Mutable tags alone are rejected; automatic updates remain disabled. - Mod configuration is data-only. Provider commands, scripts and arbitrary download URLs are forbidden.
- The application generates and retains its 32-byte master key outside SQLite; the agent never receives it. Ciphertext is authenticated AES-GCM and secrets are never returned by list APIs.
agent_stateandagent_authremain durable security state: the former stores the MAC-protected instance-to-container registry and the latter stores its shared authentication key. Losing either must never trigger automatic adoption.- The canonical public deployment has exactly two services. Setup sidecars, init containers, host bootstrap scripts and user-managed internal secrets require an explicit architectural decision.
compose.yamlis the canonical minimal production Compose definition;compose-dev.ymlis its intentionally small local HTTPS/testing overlay. Documentation references the canonical files instead of duplicating either configuration.DOGAMA_NETWORKnames the application-facing network.DOGAMA_GAMES_NETWORKnames the single agent-approved network for all created and recreated game containers; API input cannot override either bootstrap boundary.- DoGaMa services never recursively change ownership of application, game-server or backup roots.
- Notification delivery attempts are capped at five with exponential minute-scale backoff and never determine the originating operation result.
- Audit retention defaults to 30 days and 10,000 entries; zero explicitly selects unlimited retention/count within documented bounds.
- At least one active global administrator is always retained; deactivation revokes that user's sessions atomically.
- The local template directory (
/var/lib/dogama/templates, under the application data bind mount) is the catalog source of truth for administrator-owned customizations. Bundled templates are copied only when their destination files are absent; after every local scan, the current bundled immutable snapshots are synchronized into SQLite and selected for new deployments while older snapshots remain available for existing instances, audit and diagnostics. - Administrators can persist bounded HTTP(S) template-repository definitions for future use. They are configuration only: remote retrieval, authentication, synchronization and automatic updates are deliberately unavailable, and Catalog Scan remains local-only.
- V Rising is the first template-scoped TCP RCON module. Its manifest currently declares only verified connectivity/status; command operations are not advertised until validated end-to-end against a real server. Go/WASI reactor modules use
-buildmode=c-sharedand initialize through_initialize; the V Rising success path uses concrete results to avoid Go 1.26 WASI reactor nil-interface traps. Wazero is pinned at v1.12.0. - Module TCP access is instance-scoped and template-bound: the guest supplies no destination, only bounded bytes; the host pins the instance network address and declared integration port, enforces deadlines and response limits, and rejects arbitrary/unsafe destinations.
Known limitations and debt
- Scheduled backup outcomes and repeated authentication blocks are audited/logged, but broader scheduler-origin notification coverage remains intentionally limited to events emitted by implemented workflows.
- The Dashboard links to an SSR instance detail page through opaque registry IDs. It uses existing lifecycle and backup services for CSRF-protected actions and a validated sandboxed WASM facade for declared live server info, metrics, player lists, banned-player lists and permitted player/announcement actions. Unban uses a fresh adapter
list_bansresult when available; otherwise, it accepts a bounded manual game identifier for the module to validate. Update availability is limited to immutable candidates explicitly approved in a template; games without one remain safely unknown and no registry browsing is performed. - Template configuration targets are applied during deployment: container environment and argv are included in the signed agent plan; INI changes are applied atomically after an optional restore and before start. Instance secrets are encrypted outside preview JSON.
- Linux is the deployment target. Native Windows execution of the full Go suite is blocked by Unix
Statfscode; use Linux/WSL/CI for complete execution. - The two DoGaMa services run as root inside their container namespaces for bind-mount portability. Risk is bounded with read-only image filesystems, all capabilities dropped,
no-new-privileges, no Docker socket in the main application and a private typed agent API; rootless Docker and user-namespace remapping remain host-level deployment choices. - In-place migration of a successfully initialized v0.1.0 data directory has not been validated because that release wrote the application key under a different container identity. Preserve all stores and test a copied deployment rather than assuming compatibility.
staticcheck,golangci-lintand Python specification dependencies may not be installed on every development host; report missing tooling rather than silently skipping or installing it.
Validation and CI
.gitea/workflows/ci.ymlvalidates pull requests andmain;.gitea/workflows/release.ymlpublishes only tagged SemVer releases after the same required gate.- Normal completion gate for Go changes is the validation set in
AGENTS.mdon Linux. - Specification validation is
python tools/validate_spec.pywithtools/requirements-validation.txtavailable. - Start with package/file-specific tests, then run global tests, build, race detection, vet, static analysis and schema validation as applicable.
Next known work
-
No V1 milestone remains. Do not begin V1.x or V2 work without an explicit accepted scope.
-
Update this file after every merged milestone or durable architectural change; keep it compact and remove stale statements.
-
Web access and i18n are stored in the initial SQLite schema. HTTP defaults to working session/CSRF cookies without Secure and without HSTS; HTTPS enforcement is explicit.
-
Lifecycle failures retain a bounded diagnostic record separate from Audit. The restricted agent captures Docker inspection state (including exit/OOM/timestamps/health) and a bounded log tail after a failed start; the application persists this record under the operation ID and writes a stable
DGM-*error category. Existing SQLite stores receive the additive diagnostic table at open time. -
Approved template helper assets are immutable mode
0555, so an image-defined non-root user can execute a bind-mounted entrypoint while retaining no write access.