Commit graph

3 commits

Author SHA1 Message Date
07288a01d7 feat(db): add Alembic migrations (#6)
All checks were successful
CI / typecheck (push) Successful in 51s
CI / Secret scan (gitleaks) (push) Successful in 32s
CI / lint (push) Successful in 47s
CI / Security audit (bandit) (push) Successful in 35s
CI / test (push) Successful in 1m20s
2026-07-03 02:22:33 +02:00
a7c30b12cd chore(lint): auto-fix 253 of 283 ruff issues (F401, I001, E402, RUF100, UP037, SIM105)
Some checks failed
CI / lint (push) Failing after 2s
CI / typecheck (push) Failing after 2s
CI / test (push) Failing after 2s
CI / Secret scan (gitleaks) (push) Failing after 1s
CI / Security audit (bandit) (push) Failing after 2s
Mass ruff auto-fix:
  - ruff check --fix: 109 issues fixed (F401 unused imports,
    I001 unsorted imports, UP037 quoted annotations, SIM105
    suppressible exception, RUF100 unused-noqa)
  - ruff check --fix --unsafe-fixes: 22 additional issues
  - ruff format: 70 files reformatted
  - Manual pass: fix 16 misplaced import httpx lines
  - Manual pass: fix remaining E402 (import-after-docstring)

Result: 283 errors -> 30 errors.

The remaining 30 are real issues that need manual review:
  5 F401 unused-import (likely auto-generated stubs)
  5 F821 undefined-name (real bugs in code that references
    redis/pydantic/LLMRegistry without imports)
  3 BLE001 (the compliance LLM fallback is intentional; the
    other two are real)
  3 RUF012 mutable-class-default
  3 SIM105, 3 SIM117, 2 E722, 2 E741
  1 B007, 1 B025, 1 E402, 1 RUF200 (pyproject.toml issue)

Tests: 436/437 pass (1 pre-existing SSE sandbox failure).
format check + import sort: now clean.
make ci: still gated on the 30 remaining real issues.
Follow-up: triage the 30 issues file-by-file.
2026-07-02 21:51:25 +02:00
469cce04aa feat(db): SQLAlchemy foundation with 24 models + JSON importer
Replaces the 12 ad-hoc JSON file stores (quality, intel, monitors,
sessions, accounts, agency, etc.) with a single SQLAlchemy-backed
database. The new foundation gives us:
  - Concurrency safety (SQLite WAL mode, file locks via SQLAlchemy)
  - Transactions (rollback on error)
  - Querying (WHERE, JOIN, ORDER BY, LIMIT)
  - Relationships (ForeignKey on monitor_id, agency_id, etc.)
  - Multi-tenant ready (everything indexed by id)

Engine:
  - Default: SQLite at $PRY_DATA_DIR/pry.db (zero-config)
  - Production: set PRY_DATABASE_URL=postgresql://... (no code change)
  - Foreign keys enabled for SQLite (off by default)

Models (24):
  quality_checks, review_items, intel_snapshots, costing_entries,
  freshness_snapshots, structure_snapshots, seo_snapshots, monitors,
  monitor_runs, accounts, browser_sessions, reports, training_datasets,
  pipelines, pipeline_runs, gdpr_requests, agencies, agency_clients,
  referral_clicks, actors, actor_runs, llm_usage, webhooks, x402_receipts

Each model maps to a former JSON store. Most have an _id field with
unique constraint so re-importing the same data is safe. The legacy
"id" and "name" fields are renamed to "<scope>_id" / "<scope>_name"
to avoid reserved LogRecord field name collisions.

JSON importer (import_json_stores):
  One-shot function that reads the existing JSON files in $PRY_DATA_DIR
  and writes them to the SQL tables. Returns a {store: count} dict.
  Idempotent: re-running with the same data is safe.

Public API:
  - get_engine()         - lazy engine creation
  - get_session()        - new Session (caller manages)
  - session_scope()      - context manager: commit/rollback
  - import_json_stores() - the one-shot importer
  - db_health()          - dict for /health endpoint
  - _has_sqlalchemy, get_db - backward-compat aliases

pyproject.toml: added sqlalchemy>=2.0.0 and aiosqlite>=0.19.0

Tests: 7/7 in tests/test_db.py pass:
  - Engine creates DB file
  - All 24 tables created
  - session_scope commits on success
  - session_scope rolls back on error
  - import_json_stores reads existing JSON
  - db_health returns dict
  - Models have unique indexes on _id columns

Test suite: 436/437 pass (1 pre-existing SSE subprocess failure in
this sandbox; unrelated).

Follow-up:
  - Migrate the actual module code to use the SQL tables instead of
    JSON files. Each module (quality.py, intelligence.py, monitors.py,
    etc.) needs a SQL-backed replacement. Estimated 4-6 hours.
  - Add Alembic for schema migrations instead of create_all().
  - Add Postgres-specific tuning when PRY_DATABASE_URL is set.
2026-07-02 21:10:46 +02:00