2.5 KiB
Backend Enum and String Compatibility Contract
Planet keeps finite, stable protocol states in backend/app/core/enums.py. Databases and APIs continue to store and return lowercase strings. Enums provide internal type safety, validation, and deduplication without requiring a migration to database enum types.
Selection Rules
A value should become an enum only when it is finite and stable, invalid outside the known set, and compared, sorted, or branched on by multiple modules. Typical examples are job states, AI Playground message roles and states, user roles, alert states, log levels, news importance, and Breaking states.
The following must remain configurable strings:
- news categories and tags;
- provider, model, datasource, collector, news source, and Feed identifiers;
- extensible incident and anomaly types; and
- user-authored and free-form text.
Boundary Conversion
Services should use StrEnum internally. Database writes and external responses use .value, preserving existing strings such as JobStatus.RUNNING.value == "running".
Use the compatibility parser when reading historical database values, JSON, or external input:
status = parse_enum(JobStatus, raw_status, JobStatus.FAILED)
Known historical strings normalize to enum members. Empty values use the explicit default. Unknown values emit a warning and safely fall back instead of breaking historical reads. Pydantic request fields may use enums directly so invalid protocol values return 422. Ordinary String and JSON database columns must not be converted to SQLAlchemy Enum.
Earth News Decisions
Earth news decisions live in backend/app/services/earth_news_classification.py:
- category answers what the story is and remains configurable;
- importance answers whether it has long-term value; and
- Breaking answers whether it must temporarily jump ahead.
Importance levels are fixed:
| Level | Score |
|---|---|
low |
0–34 |
medium |
35–59 |
high |
60–79 |
critical |
80–100 |
Breaking rules use the typed BreakingRule structure. Levels, scopes, sources, and TTLs are managed by the public classification module. earth_news.py remains responsible for fetching, parsing, orchestration, and serialization.
Regression Prevention
When adding or changing protocol states, check app/core/enums.py first and do not redefine duplicate Literal aliases, status sets, or normalization helpers in business modules. Add enum value and boundary contracts to tests/test_enum_contracts.py, and preserve API strings and database representation.