Skip to main content

Permission taxonomy codegen

What this page is

The Rust-authored permission vocabulary that the Python backend consumes via generated code, and the pipeline that keeps the two in sync. The architecture document treats permissions as typed enums; this page is how the typing crosses language boundaries without drift.

Why it exists this way

ADR 006 records the decision. Briefly: the SOC has a small, fixed set of (resource, action) pairs that gate every privileged API call. Hand-maintaining the Python copy of a Rust enum is the classic source of bugs nobody catches until a permission check fails in production. A codegen step from one source of truth removes the drift.

The Rust crate aurora-schema owns the resource and action enums; the Python mirror lives at packages/backend/aurorasoc/core/permission_taxonomy.py, generated by the script at tools/scripts/codegen/permission_taxonomy_from_rust.py.

How it works

The script parses crates/aurora-schema/src/permission.rs, emits a Python StrEnum per Rust enum, and writes a RESOURCE_ACTION_PAIRS frozenset that the FastAPI dependency require_permission reads at import time. CI catches drift by running the codegen and refusing to merge if the working tree diff is non-empty after the run.

The build prompt's rule about typed enums means a code change that introduces a new permission must:

  1. Add the variant in aurora-schema.
  2. Re-run the codegen.
  3. Commit both files in the same atomic commit.

The Python side never carries a magic string for a permission; require_permission(Resource.ALERT, Action.ACKNOWLEDGE) is the only shape allowed.

What goes wrong

  • Codegen ran against an old aurora-schema (forgot to rebuild). CI catches the drift via a follow-up step that re-runs the generator and verifies the working tree is clean. The scripted equivalent locally is just permission-codegen-check.
  • A permission lands in Rust but the Python check has not been updated to call require_permission on the new pair. The permission exists in the generated file but is unenforced; this is what the Phase 7 follow-up item "flatten legacy string permission matrix" is about (deferred until Phase 7 stabilises).