These fields from v_event_session_w_file_count were lost during the v1/v2 -> v3 migration. Added to Event_Session_Base model and to searchable_fields in the event_session object definition. Fields are only available via the alt view (v_event_session_w_file_count). To search: use ?view=alt on the nested search endpoint. To retrieve: use ?inc_file_count=true on the GET endpoint. Also: - Updated ARCH__V3_DEVELOPMENT_STANDARDS.md: expanded Field Evolution Checklist with alt-view field rules, Docker restart requirement, and documented the ?view= parameter as a live (not proposed) feature. - Updated TODO__Agents.md: marked migration gap audit as complete. - Added regression test to test_e2e_v3_search_engine.py.
5.2 KiB
Aether V3 Development Standards & Strategy
This document serves as the master guide for the Aether API V3. It combines core architectural principles with the finalized infrastructure standards established in January 2026.
1. Core Principles
id_randomPrimary:id_random(URL-safe string) is the only identifier exposed to clients. Internal integeridis a private implementation detail.- Singular naming: All object types and prefixes use singular form (e.g.,
journal, notjournals). - Inheritance: All models must inherit from
CoreObjectto ensure consistent base fields. - Separation of Concerns: Business logic lives in
app/methods/, CRUD helpers inapp/lib_sql_crud.py, and routing inapp/routers/.
2. Infrastructure Standards
Finalized Jan 15, 2026, to ensure boot stability.
Application Entry Point (app/main.py)
- Registry Pattern: All routers are registered via
app/routers/registry.py. - Lifespan Management: All startup tasks (logging setup, DB bootstrap, engine refresh) MUST reside within the
@contextlib.asynccontextmanagerlifespan. - No Top-Level Logic: No SQL queries or heavy initialization should execute at the module level.
Database Layering
lib_sql_core.py: The foundational "Source of Truth" for the SQLAlchemy engine and globaldbconnection.lib_sql_crud.py: High-level logic forsql_insert,sql_select, etc.db_sql.py: A backward-compatible facade. code should import from here.
Logging
- Explicit Setup:
setup_logging(settings)must be called during the lifespan startup. lib_log_v3.py: New home for logging configuration and thelogger_resetdecorator.
3. V3 CRUD Strategy
URL Structure
- Top-Level:
/v3/crud/{obj_type}/ - Nested:
/v3/crud/{parent_type}/{parent_id_random}/{obj_type}/(Enforces parent ownership).
Search API
- POST Based: Complex filtering is handled via
POST /searchwith a JSON body containingand,or, andnotlogic. - Hybrid Filtering: (Proposed) Query parameters should append simple standard filters (e.g.,
?enabled=true) to the complex body logic.
Field Evolution Checklist
When a table or view gains, loses, or renames fields, keep the API contract and search registry in sync:
- Update the Pydantic model in
app/models/first so CRUD serialization matches the new shape. - Update the SQL view or table projection so
GETandSEARCHresponses actually return the field. - Update
searchable_fieldsinapp/object_definitions/only for fields that should be searchable. - Add write-only, virtual, or view-only fields to
fields_to_exclude_from_dbwhen they must not be persisted. - Run the schema/search E2E tests that cover the object type before handing the change off.
- Restart the Docker API containers (
docker compose restart ae_api) — Python file changes inside containers are not picked up until restart.
For archive_content, the public field set now includes external_id and code, and future additions should follow the same order of operations.
Alt-view fields (fields only in tbl_alt)
Some objects have a richer alternate SQL view (tbl_alt) that adds JOINed/computed columns absent from the default view (tbl_default). For example, event_session uses v_event_session_w_file_count as its alt view (triggered by ?view=alt on search, or ?inc_file_count=true on GET).
- Fields from
tbl_altmust still be declared in the Pydantic model and insearchable_fields— Pydantic strips undeclared fields, and the search whitelist rejects unknown field names regardless of the view. - When adding such a field, add a comment noting which view provides it (e.g.,
# from v_event_session_w_file_count). - Searching by an alt-view field on the default endpoint returns
400 Unknown column— this is correct behaviour. Clients must pass?view=altto use those fields in a search. - Known alt-view fields restored May 2026:
event_presentation_li_qry_str,event_presenter_li_qry_str(event_session);account_name,account_code, and related convenience fields (site_domain).
Response Views (?view= parameter)
- The nested search router (
api_crud_v3_nested.py) already supports?view=<key>to switch between registered views.view=defaultusestbl_default;view=altusestbl_alt; additional named views can be added to the object registry astbl_<name>/mdl_<name>. - Flat search (
api_crud_v3.py) does not yet support?view=— it always usestbl_default.
4. Stability Rules
- Baby Step Testing: Restart Docker and verify root health after every modular change.
- Avoid Shadowing: Never name a module part of the
app.package the same as a common instance variable (e.g., avoidapp.middlewarepackage if you useapp = FastAPI()). - Deferred Imports: Use
from app.db_sql import ...inside functions in library modules to prevent circular dependency traps. - Model changes require container restart: Editing Python files on the host does not hot-reload inside Docker. Always run
docker compose restart ae_apiafter model or object-definition changes, then re-run E2E tests.