Files
planet/docs/technical/en/backend-enum-contracts.md
linkong 8c204717cd
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
release / images (push) Has been cancelled
ci / delivery (push) Has been cancelled
release: bump version to 0.70.0
2026-06-04 17:16:23 +08:00

2.5 KiB
Raw Blame History

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 034
medium 3559
high 6079
critical 80100

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.