Skip to content

[Audit] ETL hardcodes manager_id but API-created SQLite managers table uses id #1302

Description

@stranske

Why

The SQLite manager-id convention is inconsistent between the API (which has a dialect resolver) and the ETL flows (which hardcode manager_id), so ETL breaks on any SQLite database bootstrapped by the API.

  • api/managers.py:136 creates the SQLite table as managers(id INTEGER PRIMARY KEY, ...), and api/managers.py:33 _manager_id_column(conn) correctly returns "id" for SQLite / "manager_id" for Postgres.
  • ETL readers do NOT use that resolver — they hardcode manager_id: etl/news_flow.py:71 (SELECT manager_id, name, aliases FROM managers), etl/daily_diff_flow.py:138, diff_holdings.py:70, etl/activism_flow.py:124.

Failure mode: on a SQLite DB created via the manager API (the documented local/dev path), ETL flows fail with sqlite3.OperationalError: no such column: manager_id. Prod Postgres is unaffected (its column IS manager_id per schema.sql), and CI can miss it when fixtures create a different schema than the app itself creates.

Scope

Make ETL manager-id access dialect-correct so the SQLite-bootstrapped path works end-to-end.

Non-Goals

  • Do NOT change the Postgres schema (manager_id stays canonical there).
  • Do NOT duplicate the resolver — reuse the existing _manager_id_column logic.

Tasks

  • Export/reuse a shared manager-id column resolver and apply it in etl/news_flow.py:71, etl/daily_diff_flow.py:138, diff_holdings.py:70, etl/activism_flow.py:124 (and any other hardcoded manager_id reader of the managers table). Alternatively, standardize the SQLite managers schema on manager_id.

Acceptance Criteria

  • New test (currently failing): in a fresh SQLite DB, create a manager via the API path (_ensure_manager_table() + insert), then call an ETL reader (e.g. _fetch_all_manager_ids(conn) / match_entities); current code raises no such column: manager_id, fixed code returns the inserted manager id.
  • Deliberate-break demonstration: reverting ETL to hardcoded manager_id fails the new test; restoring the resolver passes.

Implementation Notes

Audit baseline: main @ e5764a5 on 2026-06-28. Source-verified: API SQLite create at managers.py:136, resolver at managers.py:33, hardcoded ETL reads at the listed lines. Prod-Postgres path is unaffected; this is a SQLite/local-path wiring fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

agents:formattedIssue has been formatted to AGENT_ISSUE_TEMPLATEbugSomething isn't workingpriority:normalNormal-priority weekly repo-review worktestingTests or coverage work

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions