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
/dataas 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.tomlis 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, then404.
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 inapp.settings.Settings.The
globalkeyword must not be used; use dependency injection orfunctools.lru_cacheinstead.