Skip to content

[Chore] Migrate runtime DB to penguin-dal (SQLAlchemy/Alembic = schema authority)#80

Open
PenguinzTech wants to merge 2 commits into
feature/backend-basefrom
chore/penguin-dal-migration
Open

[Chore] Migrate runtime DB to penguin-dal (SQLAlchemy/Alembic = schema authority)#80
PenguinzTech wants to merge 2 commits into
feature/backend-basefrom
chore/penguin-dal-migration

Conversation

@PenguinzTech

@PenguinzTech PenguinzTech commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Migrates all runtime DB access from raw PyDAL to penguin-dal (SQLAlchemy-backed), with SQLAlchemy models + Alembic as the sole schema authority — per backend-database.md. Removes ~570 lines of raw CREATE TABLE/define_table; the event reserved-word class of bug disappears (identifiers are quoted).

Result

671 passed, 0 failed, coverage 90.60% on the flask-backend suite.

What was broken (and fixed here)

The initial mechanical migration compiled but shipped 246 failing tests. penguin-dal 0.1.0 (only PyPI release) lacks much PyDAL-compatible surface. Fixes:

app/penguin_db.py compat layer (each shim flagged TODO to upstream into penguin-dal):

  • executesql binds positional params via exec_driver_sql (SQLAlchemy text() is named-params only)
  • FieldProxy comparisons unwrap a FieldProxy operand → real column==column join predicates (fixes ~20 RBAC/tenant/team joins with no changes to auth queries)
  • TableProxy.ALL → underlying Table (restores db.t.ALL join-selects)
  • Copy Python-side column default=/onupdate= from db_schema onto reflected tables (reflection only captures DDL, not ORM defaults) — fixes revoked=False/timestamps
  • Dispose the pool after attaching the SQLite FK pragma → ON DELETE CASCADE works

Call-site fixes (unshimmable idioms): bare-table db(db.t)db(db.t.id>0); PyDAL nested joined-row m["table"]["col"] → flat m["col"]; async_db.count accepts a bare table.

Root cause of ~200 403s: _ensure_default_roles branched on Config.DB_TYPE (frozen at import to default "postgresql"), running Postgres SQL against SQLite → no roles seeded → admin had zero scopes. Now a dialect-agnostic native check-then-insert. conftest sets DB_TYPE=sqlite at import + uses a per-test temp-file DB (in-memory SQLite is penguin-dal-incompatible).

Hygiene: removed committed app_db.db + gitignored it; fixed stale test_config :memory: assertion.

Follow-ups (pre-existing, not introduced here)

  • Alembic chain head (is_bot) lags db_schema.py (18 tables incl shortener) — regenerate so Alembic truly reproduces the full schema.
  • oidc.py: jwks_uri fetched but unused (F841) — possible JWKS-validation gap, worth investigating separately.

🤖 Generated with Claude Code

Summary by Sourcery

Migrate the Flask backend’s runtime database layer from raw PyDAL to penguin-dal backed by SQLAlchemy models and Alembic, making the SQLAlchemy schema the single source of truth and ensuring dialect-agnostic behavior across Postgres and SQLite.

Bug Fixes:

  • Fix default role seeding to be dialect-agnostic and truly idempotent, avoiding Postgres-specific SQL against SQLite and restoring admin scopes in tests.
  • Ensure ON DELETE CASCADE and other SQLite foreign key behaviors by attaching the appropriate PRAGMA on the SQLAlchemy engine and disposing the initial pool.
  • Restore Python-side column defaults (e.g., revoked flags and timestamps) by copying ORM default/onupdate metadata onto reflected tables so inserts no longer write NULLs.
  • Correct async and synchronous query patterns that relied on bare-table or nested-row PyDAL idioms to work correctly under penguin-dal’s query model.

Enhancements:

  • Introduce a penguin-dal based PenguinDB wrapper that reflects the SQLAlchemy schema, patches field and table proxies for PyDAL-style ergonomics, and enforces SQLite foreign key constraints.
  • Replace manual CREATE TABLE / define_table usage in models with initialization via SQLAlchemy URIs and penguin-dal, relying on db_schema.py for table definitions.
  • Update async DB helpers, Flask-Security datastore, and RBAC/teams/roles/tenants/OIDC/user code paths to use penguin-dal semantics, including explicit id-based queries and flatter join result shapes.
  • Adjust configuration and testing setup to use SQLAlchemy-style URIs and per-test file-based SQLite databases instead of :memory:, preserving test isolation under penguin-dal.
  • Add SQLAlchemy and penguin-dal as explicit backend dependencies and update requirements metadata accordingly.

Build:

  • Add penguin-dal and SQLAlchemy to requirements, adjust dependency comments, and update the uv pip compile invocation comment formatting.

Tests:

  • Modify test configuration and fixtures to assert only the SQLite dialect, inject per-test temporary DB files, and clean up those databases after each test run.
  • Update RBAC unit tests and other DB-interacting tests to align with penguin-dal’s requirement for explicit query conditions (e.g., id > 0) when selecting rows.

Chores:

  • Remove the committed SQLite database file from the repository and add it to .gitignore to prevent future accidental commits.

PenguinzTech and others added 2 commits July 17, 2026 20:57
…my/Alembic sole schema authority

- Migrate runtime DB layer to penguin-dal (SQLAlchemy-backed, PyDAL ergonomics)
- Remove raw PyDAL schema creation; rely on SQLAlchemy + Alembic for all DDL
- Update config.py to generate SQLAlchemy URIs (sqlite:///, postgresql://, mysql+pymysql://)
- Rewrite models.py init_db() to call create_dal() with pool_size from app config
- Remove _create_tables_if_needed() entirely (schema authority now SQLAlchemy only)
- Delete all db.define_table() calls; tables reflect from SQLAlchemy metadata
- Update seed logic (_ensure_default_roles, _ensure_default_tenant, _seed_default_admin) for penguin-dal
- Fix async_db.py select() to work with penguin-dal Query API (no table.ALL)
- Update datastore.py and async_db.py type hints (remove pydal imports, use Any)
- Fix conftest.py: per-test temp file DB instead of :memory: (penguin-dal pool_size incompatibility)
- Update requirements.in: replace pydal==20260313.1 with penguin-dal==0.1.0, add sqlalchemy==2.0.31

Test DB isolation: each pytest creates unique temp file, SQLAlchemy create_all is idempotent,
tests run in parallel safely. Seed logic idempotent (check-then-insert for roles/tenant).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ixes

The mechanical migration (prev commit) shipped broken: 246 failing tests
that were dismissed as "not blocking". penguin-dal 0.1.0 (the only PyPI
release) lacks much of the PyDAL-compatible surface the codebase relies on.
Fixed every gap and the underlying seed bug so the base suite is green
(671 passed, 90.6% coverage).

penguin_db.py compat layer (each shim TODO-flagged to upstream into penguin-dal):
- executesql: bind positional params via exec_driver_sql (DBAPI paramstyle),
  since SQLAlchemy text() only supports named params — un-breaks role seed +
  click counter.
- FieldProxy comparisons unwrap a FieldProxy operand to its column, so
  column==column builds a real join predicate (SQLAlchemy auto-adds the table
  to FROM) — fixes ~20 implicit-join sites in RBAC/tenant/team with no changes
  to the security-critical auth queries.
- TableProxy.ALL -> underlying Table, restoring db.t.ALL join-selects.
- Copy Python-side column defaults (default=/onupdate=) from db_schema onto the
  reflected tables so inserts apply them (e.g. revoked=False, created_at) —
  reflection only captures DDL, not ORM defaults. Fixes the refresh-token path.
- Dispose the pool after attaching the SQLite FK pragma listener, so every
  connection enforces foreign_keys=ON — fixes ON DELETE CASCADE.

Call-site fixes for idioms that can't be shimmed:
- bare-table db(db.t) -> db(db.t.id > 0) (models/oidc/roles/tenants/teams).
- PyDAL nested joined-row access m["table"]["col"] -> flat m["col"]
  (penguin-dal returns a flat row) in teams/users/roles.
- async_db.count accepts a bare table (count-all).

Root cause of the ~200 "403 Access denied": _ensure_default_roles branched on
Config.DB_TYPE, a class attribute frozen at import time to the default
"postgresql", so it ran Postgres %s SQL against SQLite and silently seeded no
roles -> admin resolved zero scopes. Replaced with a dialect-agnostic native
check-then-insert (IntegrityError = concurrent-worker race). conftest now sets
DB_TYPE=sqlite at import (was moved into the fixture, too late) and uses a
per-test temp-file DB (in-memory SQLite is incompatible with penguin-dal).

Also: drop committed app_db.db (stray SQLite file) + gitignore it; fix stale
test_config :memory: assertion; _get_primary_role type hint DAL -> PenguinDB.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Reviewer's Guide

Migrates the Flask backend runtime database layer from raw PyDAL and handcrafted DDL to penguin-dal (SQLAlchemy-backed) with SQLAlchemy models and Alembic as the sole schema authority, adding a PenguinDB compat layer, updating DB configuration and async wrappers, fixing PyDAL-only idioms at call sites, and adjusting the test setup to use file-based SQLite per test.

File-Level Changes

Change Details Files
Replace PyDAL-based runtime DB initialization and hand-written DDL with penguin-dal backed by SQLAlchemy schema metadata.
  • Rewrite init_db to construct a SQLAlchemy-style URI from Quart app config and create the DAL via create_dal instead of pydal.DAL and _create_tables_if_needed
  • Remove all raw CREATE TABLE / define_table logic and rely on db_schema/Alembic as schema authority
  • Change role/tenant/admin seeding helpers to use PenguinDB, dialect-agnostic checks, and IntegrityError handling instead of Config.DB_TYPE-specific SQL.
  • Update callers to use explicit always-true queries (e.g., db.auth_user.id>0) where penguin-dal disallows bare-table queries, and update pagination counts accordingly.
services/flask-backend/app/models.py
Introduce penguin-dal compat layer (PenguinDB) and schema bootstrap that mirrors PyDAL ergonomics while using SQLAlchemy under the hood.
  • Add PenguinDB subclass of penguin_dal.DB providing rollback no-op and PyDAL-like executesql that supports positional and named parameters via SQLAlchemy engine
  • Patch FieldProxy comparison operators to support column-to-column comparisons (joins) and handle None correctly, and add TableProxy.ALL alias to underlying SA table to support existing select patterns
  • Add create_schema to create tables idempotently from db_schema.Base metadata, enable SQLite foreign key enforcement via SQLAlchemy events, and propagate Python-side defaults/onupdate from db_schema onto reflected tables
  • Implement create_dal to perform create_all, reflect metadata, attach FK pragma, dispose the initial pool, and return a configured PenguinDB instance.
services/flask-backend/app/penguin_db.py
Adapt async DB wrapper and Flask-Security datastore to operate on penguin-dal instead of PyDAL, preserving public interfaces.
  • Remove strict DAL typing in async_db.AsyncDAL/AsyncDBContext to accept Any, and adjust select/count helpers to build required query conditions (id>0) and handle table vs query inputs under penguin-dal semantics
  • Update async count/select-first to avoid implicit table queries and to pass through fields/kwargs appropriately
  • Loosen datastore type hints to Any and keep PyDALUser/PyDALRole/PyDALUserDatastore semantics while clarifying they now wrap penguin-dal rows/tables.
  • Ensure no explicit PyDAL imports remain in async_db.py and datastore.py except via penguin-dal abstractions.
services/flask-backend/app/async_db.py
services/flask-backend/app/datastore.py
Switch configuration and tests to SQLAlchemy-style URIs and per-test file-based SQLite databases compatible with penguin-dal.
  • Change Config.get_db_uri to emit SQLAlchemy URIs (dialect+driver) instead of PyDAL URIs, including sqlite file handling and absolute path support
  • Update TestingConfig.DB_NAME from ':memory:' to a default file path and refine tests to assert only dialect (DB_TYPE) and truthy DB_NAME rather than a fixed memory name
  • Modify tests conftest app fixture to set DB_TYPE=sqlite at import time, create a unique temp SQLite file per test, override TestingConfig.DB_NAME accordingly, and clean up files afterward.
  • Clarify comments around penguin-dal incompatibility with in-memory SQLite pools.
services/flask-backend/app/config.py
services/flask-backend/tests/conftest.py
services/flask-backend/tests/test_config.py
Update application call sites using PyDAL-specific idioms to penguin-dal-compatible query shapes and flattened join results.
  • Replace bare-table queries like db(db.teams) and db(db.auth_role) with explicit predicates db.teams.id>0 or db.auth_role.id>0 in teams, roles, tenants, oidc, and RBAC tests.
  • Adjust handling of joined rows from nested m['table']['col'] access to flattened m['col'] access for team members and role assignments returned by penguin-dal joins.
  • Fix async_db.AsyncDAL.count and call sites that passed tables directly so that they construct appropriate queries before counting.
services/flask-backend/app/teams.py
services/flask-backend/app/roles.py
services/flask-backend/app/users.py
services/flask-backend/app/oidc.py
services/flask-backend/app/tenants.py
services/flask-backend/tests/test_rbac_unit.py
Align dependencies and repo hygiene with the new DB stack.
  • Add penguin-dal and sqlalchemy to requirements.in/requirements.txt and adjust pydal usage to only come via penguin-utils, updating comments accordingly.
  • Update the uv pip compile command comment in requirements.txt to the new flag ordering.
  • Remove the committed SQLite DB file and add it to .gitignore so runtime/test DBs are not tracked.
services/flask-backend/requirements.in
services/flask-backend/requirements.txt
.gitignore

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedpypi/​penguin-dal@​0.1.010010010010070
Addedpypi/​sqlalchemy@​2.0.3197100100100100

View full report

@socket-security

Copy link
Copy Markdown

Caution

Review the following alerts detected in dependencies.

According to your organization's Security Policy, you must resolve all "Block" alerts before proceeding. It is recommended to resolve "Warn" alerts too. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block High
Obfuscated code: pypi sqlalchemy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: pypi sqlalchemy

Location: Package overview

From: services/flask-backend/requirements.txtpypi/sqlalchemy@2.0.31

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/sqlalchemy@2.0.31. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In init_db you rebuild the SQLAlchemy URI from app config rather than reusing Config.get_db_uri, which now contains similar mapping logic; consider centralizing URI construction to avoid future drift between the two code paths.
  • The monkeypatches in penguin_db.py (_patch_tableproxy_all and _patch_fieldproxy_column_ops) hardwire behavior into penguin-dal 0.1.0; it would be safer to feature-detect or gate these by version to avoid subtle breakage when the library is upgraded.
  • The heuristics in AsyncDAL.select and AsyncDAL.count that synthesize id > 0 when a bare table is passed can hide misuse of the API; it might be clearer to require explicit query conditions and fail fast when a table is passed directly instead of guessing an always-true predicate.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `init_db` you rebuild the SQLAlchemy URI from app config rather than reusing `Config.get_db_uri`, which now contains similar mapping logic; consider centralizing URI construction to avoid future drift between the two code paths.
- The monkeypatches in `penguin_db.py` (`_patch_tableproxy_all` and `_patch_fieldproxy_column_ops`) hardwire behavior into penguin-dal 0.1.0; it would be safer to feature-detect or gate these by version to avoid subtle breakage when the library is upgraded.
- The heuristics in `AsyncDAL.select` and `AsyncDAL.count` that synthesize `id > 0` when a bare table is passed can hide misuse of the API; it might be clearer to require explicit query conditions and fail fast when a table is passed directly instead of guessing an always-true predicate.

## Individual Comments

### Comment 1
<location path="services/flask-backend/app/models.py" line_range="45-54" />
<code_context>
+    # Build SQLAlchemy URI from app config
</code_context>
<issue_to_address>
**suggestion:** Avoid duplicating DB URI construction logic already present in Config.get_db_uri.

init_db now re-implements DB URI construction (type mappings, SQLite handling, pool_size) instead of delegating to Config.get_db_uri, which is already SQLAlchemy-compatible. This duplication creates two sources of truth and a risk of divergence if one is updated without the other. Please centralize URI construction via Config.get_db_uri and read pool_size consistently from app.config/Config so the rules stay in one place.

Suggested implementation:

```python
    # Build SQLAlchemy URI and pool configuration via centralized Config logic
    db_uri = Config.get_db_uri(app.config)
    pool_size = app.config.get("DB_POOL_SIZE", getattr(Config, "DB_POOL_SIZE", 10))

```

1. Ensure `Config` is imported in this module from the correct location (for example, `from app.config import Config` or your project’s equivalent). If it is already imported, no further change is needed.
2. If `Config.get_db_uri` returns additional metadata (such as pool size) instead of only the URI, adjust the assignment accordingly, e.g. `db_uri, pool_size = Config.get_db_uri(app.config)` and remove the separate `pool_size` line.
3. Remove any now-unused variables or mappings (such as `type_map` and the individual `db_*` variables) elsewhere in `init_db` or this module if they were referenced after this block, since `Config.get_db_uri` should encapsulate that logic.
4. Where the SQLAlchemy engine/session is created later in this function, make sure it uses `db_uri` (from `Config.get_db_uri`) and `pool_size` from this new logic, instead of any older URI-building or pool-size configuration.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +45 to +54
# Build SQLAlchemy URI from app config
db_type = app.config.get("DB_TYPE", "postgres")
db_host = app.config.get("DB_HOST", "localhost")
db_port = app.config.get("DB_PORT", "5432")
db_name = app.config.get("DB_NAME", "app_db")
db_user = app.config.get("DB_USER", "app_user")
db_pass = app.config.get("DB_PASS", "app_pass")
pool_size = app.config.get("DB_POOL_SIZE", 10)

# Map common aliases to SQLAlchemy format

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Avoid duplicating DB URI construction logic already present in Config.get_db_uri.

init_db now re-implements DB URI construction (type mappings, SQLite handling, pool_size) instead of delegating to Config.get_db_uri, which is already SQLAlchemy-compatible. This duplication creates two sources of truth and a risk of divergence if one is updated without the other. Please centralize URI construction via Config.get_db_uri and read pool_size consistently from app.config/Config so the rules stay in one place.

Suggested implementation:

    # Build SQLAlchemy URI and pool configuration via centralized Config logic
    db_uri = Config.get_db_uri(app.config)
    pool_size = app.config.get("DB_POOL_SIZE", getattr(Config, "DB_POOL_SIZE", 10))
  1. Ensure Config is imported in this module from the correct location (for example, from app.config import Config or your project’s equivalent). If it is already imported, no further change is needed.
  2. If Config.get_db_uri returns additional metadata (such as pool size) instead of only the URI, adjust the assignment accordingly, e.g. db_uri, pool_size = Config.get_db_uri(app.config) and remove the separate pool_size line.
  3. Remove any now-unused variables or mappings (such as type_map and the individual db_* variables) elsewhere in init_db or this module if they were referenced after this block, since Config.get_db_uri should encapsulate that logic.
  4. Where the SQLAlchemy engine/session is created later in this function, make sure it uses db_uri (from Config.get_db_uri) and pool_size from this new logic, instead of any older URI-building or pool-size configuration.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant