BusinessException (and its subclass LeauditException) had no
FastAPI exception handler, so they escaped as unhandled 500s
even when carrying the correct status code (e.g. 403). Add a
handler that renders the status code and message as a proper
JSON response.
- DB: add region column to leaudit_rule_sets + leaudit_rule_type_bindings
- DB: change UNIQUE constraint from (rule_type) to (rule_type, region)
- Config: add APP_REGION to app.toml + AppSettings + __init__.pyi
- AuditServiceImpl: filter bindings by APP_REGION
- RuleServiceImpl: ListBindings/CreateBinding use APP_REGION
- Seed script: accept --region arg, tag rules by region
- OssPathUtils: BuildRuleYamlKey already accepts Region parameter
Each region can now have its own independent copy of the same rule_type,
stored in separate OSS paths and DB rows, keyed by region.
17-table PostgreSQL schema with full Chinese column comments,
FastAPI project structure (admin/common/modules),
DSL rule files, and schema migration scripts.