# Invariants These rules are mandatory and derive from `contract.md`. ## Scope Invariants - Do not implement features explicitly excluded by the contract. - Keep the service split: FastAPI API service and nginx static/reverse-proxy service in separate containers. - Keep one long-running process per container. - Keep `/data` as the only authoritative persistent data source. - Do not add a database, ORM, or background workers. ## Layering Invariants - API handlers own HTTP concerns only. - Business logic and filesystem writes belong in backend services. - API handlers must not perform direct filesystem operations. - All filesystem operations must go through the storage abstraction. - Version resolution must always go through `resolve_version(...)`. ## Data and Immutability Invariants - Storage path model must follow the locale-aware contract layout. - Version+locale artifacts are immutable once created. - Writes must be atomic; no partial version visibility. - `metadata.toml` is system-generated and not trusted from uploaded archives. - Refs in `refs/` are symlinks and must be written atomically. ## Locale Invariants - Locale is mandatory for uploads and resolution. - Locale format is two lowercase letters. - Fallback order is fixed: requested locale, then `en`, then any available locale, then `404`. ## Security Invariants - Authentication is stateless JWT validation via JWKS. - Write operations require valid JWT and namespace ACL write permission. - Public read behavior is controlled only by namespace ACL. - Upload ZIP validation must reject traversal and symlink entries. - Upload validation must enforce extracted size and file-count limits. - Uploaded documentation must contain top-level `index.html`. ## Concurrency Invariants - Concurrent uploads to different projects must be supported. - Concurrent uploads to same project for different versions/locales must be supported. - Two uploads must never create the same version+locale artifact. ## Code Quality Invariants - Every test function must have a docstring starting with "Ensure…". - Every source file must have a module-level docstring. - Every function must have a docstring. - All environment variables must use the `DOCROOT_` prefix and be declared in `app.settings.Settings`. - The `global` keyword must not be used; use dependency injection or `functools.lru_cache` instead.