Skip to content

[SECURITY] Database security - connection pool, atomic transactions, health monitor - closes #54#83

Merged
sjackson0109 merged 10 commits into
sjackson0109:mainfrom
Ibrahim-3d:feat/54-database-security-transactions
May 24, 2026
Merged

[SECURITY] Database security - connection pool, atomic transactions, health monitor - closes #54#83
sjackson0109 merged 10 commits into
sjackson0109:mainfrom
Ibrahim-3d:feat/54-database-security-transactions

Conversation

@Ibrahim-3d

Copy link
Copy Markdown
Collaborator

Summary

Creates pt_database_manager.py — standalone database security layer that complements the existing OrderManagementDB/SQLAlchemy stack without modifying it.

Changes

  • New: app/pt_database_manager.py
  • New: app/test_database_manager.py — 28 tests

Key components

Component Purpose
DatabaseConnectionPool Thread-local connections; serializes creation to prevent concurrent WAL pragma lock
atomic_transaction() Context manager with BEGIN IMMEDIATE + exponential-backoff retry on SQLITE_BUSY
InputSanitizer Null-byte stripping, SQL keyword detection, identifier validation
DatabaseHealthMonitor Background daemon running PRAGMA integrity_check on schedule with corrupt callback

Usage

from pt_database_manager import DatabaseConnectionPool, atomic_transaction, DatabaseHealthMonitor

pool = DatabaseConnectionPool("order_management.db")
conn = pool.get_connection()

with atomic_transaction(conn) as c:
    c.execute("INSERT INTO orders VALUES (?, ?)", (order_id, symbol))
    c.execute("UPDATE balances SET amount = amount - ? WHERE user = ?", (amount, user))

monitor = DatabaseHealthMonitor("order_management.db", on_corrupt=emergency_stop)
monitor.start()

Test plan

  • 28 unit tests pass
  • Thread isolation for connections verified
  • WAL mode applied (no concurrent lock conflict)
  • Atomic rollback on exception verified
  • SQL injection detection tested

Closes #54

Copilot AI review requested due to automatic review settings May 17, 2026 20:46
@Ibrahim-3d Ibrahim-3d requested a review from sjackson0109 as a code owner May 17, 2026 20:46

Copilot AI 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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new SQLite-focused database utility module (connection pooling, atomic transactions w/ retry, sanitization, and health monitoring) plus unit tests to validate core behaviors.

Changes:

  • Introduces pt_database_manager.py with connection pooling, atomic_transaction, input sanitization, and a background integrity-check monitor.
  • Adds test_database_manager.py covering connection pool behavior, transaction commit/rollback, sanitizer behavior, and health monitor lifecycle.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 11 comments.

File Description
app/pt_database_manager.py Implements SQLite connection pool, atomic transaction context manager with retry/backoff, input sanitization, and periodic integrity health monitoring.
app/test_database_manager.py Adds unit tests for the new database manager components.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/test_database_manager.py Outdated
Comment thread app/test_database_manager.py Outdated
Comment thread app/pt_database_manager.py
Comment thread app/pt_database_manager.py Outdated
Comment thread app/pt_database_manager.py
Comment thread app/pt_database_manager.py
Comment thread app/pt_database_manager.py
Comment thread app/pt_database_manager.py Outdated
Comment thread app/pt_database_manager.py Outdated
Comment thread app/test_database_manager.py Outdated
@sjackson0109 sjackson0109 self-assigned this May 17, 2026
@sjackson0109 sjackson0109 added high-priority security component-security Security components component-architecture System architecture and design components labels May 17, 2026
sjackson0109
sjackson0109 previously approved these changes May 17, 2026

@sjackson0109 sjackson0109 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

A logical set of changes. Appreciate your efforts here, Ibrahim.

@sjackson0109

Copy link
Copy Markdown
Owner

@Ibrahim-3d Brilliant effort. Can you review the copilot comments/suggestions here - #83 (review)
For each entry, please either directly resolve, or provide appropriate comments to support a debate of ignoring/skipping etc. if you feel you have resolved, please explain how in your resolve comment.

@Ibrahim-3d

Ibrahim-3d commented May 18, 2026

Copy link
Copy Markdown
Collaborator Author

All 11 Copilot review comments addressed in the fix commit. Inline replies posted directly on each thread. All threads resolved.

Note: Threads are resolved and collapsed. To view any thread, open the Files changed tab and click "Show resolved" or the collapsed thread indicator.

# File Topic Status
1 test_database_manager.py unittest.mock import inside __main__ guard - not visible to pytest Resolved
2 test_database_manager.py Test asserts broad Exception instead of TransactionError Resolved
3 pt_database_manager.py Non-contention OperationalError wrapped as TransactionError - wrong semantics Resolved
4 pt_database_manager.py Duplicate of #3 - different line Resolved
5 pt_database_manager.py Duplicate of #3 - different line Resolved
6 pt_database_manager.py Connection leak in check_health if integrity_check raises Resolved
7 pt_database_manager.py Duplicate of #6 - different line Resolved
8 pt_database_manager.py %d format truncates float check_interval in log output Resolved
9 pt_database_manager.py Duplicate of #8 - different line Resolved
10 pt_database_manager.py Docstring claims "deadlock detection" - inaccurate for SQLite Resolved
11 test_database_manager.py Tests never close pool connections - blocks temp dir cleanup on Windows Resolved

@Ibrahim-3d

Copy link
Copy Markdown
Collaborator Author

Local CI Simulation Results

Ran all workflow steps locally against this branch prior to owner approval. Results:

Code Quality & Testing

Check Tool Result
Code formatting black --check ✅ Pass — 0 files need reformatting
Import ordering isort --check ✅ Pass
Linting (hard errors) flake8 --select=E9,F63,F7,F82 ✅ Pass — 0 syntax/undefined-name errors
Linting (extended) flake8 --exit-zero ✅ Pass — 0 warnings in new files
Unit tests pytest ✅ All tests pass (see table below)

Unit Test Results

File Tests Result
test_circuit_breaker.py 20 ✅ All pass
test_credentials_rotation.py 30 ✅ All pass
test_error_handler.py 22 ✅ All pass
test_backup_validation.py 35 ✅ All pass
test_database_manager.py 29 ✅ All pass
test_security_logger.py 25 ✅ All pass

CI/CD Pipeline

Workflow Status Reason
Code Quality & Testing ⏳ Awaiting owner approval Fork PR — first-time contributor gate
PowerTrader AI+ CI/CD ⏳ Awaiting owner approval Fork PR — first-time contributor gate
Project Management ⏳ Awaiting owner approval Fork PR — first-time contributor gate

All three workflows are queued with action_required status. This is GitHub's security gate for PRs from fork contributors. Once approved by @sjackson0109, they will execute against the same code that was verified locally above.

@sjackson0109

Copy link
Copy Markdown
Owner

Would welcome your thoughts @Ibrahim-3d - Gould I permit the code quality ci pipelines to run automatically?

…ealth monitor

pt_database_manager.py:
- DatabaseConnectionPool with thread-local connections and serialized creation
  (prevents SQLITE_LOCKED during concurrent PRAGMA journal_mode=WAL setup)
- atomic_transaction() context manager with exponential-backoff retry on SQLITE_BUSY
- InputSanitizer with SQL injection heuristics and identifier validation
- DatabaseHealthMonitor daemon thread with PRAGMA integrity_check and corrupt callback

- 28 unit tests, all passing
…ion safety

- atomic_transaction re-raises original sqlite3.OperationalError for non-contention
  errors; only wraps as TransactionError when retry limit exceeded on busy/locked
- check_health uses try/finally to close connection even when integrity_check raises
- Log interval format changed from %d to %s (float-safe)
- Module docstring updated: remove "deadlock detection" claim (SQLite uses locking,
  not deadlocks); describe retry-on-contention behavior accurately
- Tests: unittest.mock imported at module level (not inside __main__ guard)
- Tests: test_non_contention_error propagates sqlite3.OperationalError (not TransactionError)
- Tests: test_contention_retries uses real write lock + TransactionError assertion
- Tests: tearDown closes thread-local connections before rmtree (prevents Windows lock)
- Tests: threading.Barrier ensures concurrent thread test reliability
Copilot AI review requested due to automatic review settings May 18, 2026 18:39
@Ibrahim-3d Ibrahim-3d force-pushed the feat/54-database-security-transactions branch from 2cbb859 to d6b5d59 Compare May 18, 2026 18:39

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.

Comment thread app/pt_database_manager.py
Comment thread app/pt_database_manager.py Outdated
Comment thread app/pt_database_manager.py
Comment thread app/pt_database_manager.py Outdated
Comment thread app/pt_database_manager.py
Comment thread app/pt_database_manager.py Outdated
Comment thread app/test_database_manager.py
Comment thread app/pt_database_manager.py
@sjackson0109

Copy link
Copy Markdown
Owner

@Ibrahim-3d loiks like all CI pipelines passed. Please can you review copilot’s comments here #83 (review)

- atomic_transaction: add COMMIT contention retry loop so SQLITE_BUSY
  on COMMIT triggers backoff-retry up to max_retries, not silent failure
- check_same_thread: change False->True; thread-local pool guarantees
  single-thread access, letting SQLite enforce this as a safety net
- check_sql_injection: replace substring match with word-boundary regex
  for alphabetic keywords to eliminate false positives on values like
  "dropbox", "selection", "truncate_me"; punctuation tokens (-- ;) still
  use exact substring match
- stop(): check is_alive() after join timeout and log warning if thread
  did not terminate within 5s
- tests: close victim connection in contention test to prevent handle
  leak; add test_commit_contention_retries; add
  test_check_sql_injection_no_false_positives;
  add test_check_sql_injection_punctuation_tokens
@Ibrahim-3d

Copy link
Copy Markdown
Collaborator Author

Manual Testing Guide — PR #83: Database Security (Connection Pool, Atomic Transactions, Health Monitor)

Prerequisites

git fetch fork && git checkout feat/54-database-security-transactions
cd app

1. Run unit tests

python -m pytest test_database_manager.py -v

Expected: All 29 tests pass, including new test_commit_contention_retries, test_check_sql_injection_no_false_positives.

2. Smoke test — atomic transaction commit + rollback

python -c "
import sqlite3, tempfile, os
from pt_database_manager import DatabaseConnectionPool, atomic_transaction

with tempfile.TemporaryDirectory() as d:
    db = os.path.join(d, 'test.db')
    pool = DatabaseConnectionPool(db)
    conn = pool.get_connection()
    conn.execute('CREATE TABLE t (id INTEGER PRIMARY KEY, val TEXT)')
    # Commit path
    with atomic_transaction(conn) as c:
        c.execute(\"INSERT INTO t VALUES (1, 'hello')\")
    row = conn.execute('SELECT val FROM t WHERE id=1').fetchone()
    print('commit ok:', row[0])
    # Rollback path
    try:
        with atomic_transaction(conn) as c:
            c.execute(\"INSERT INTO t VALUES (2, 'will rollback')\")
            raise ValueError('forced')
    except ValueError:
        pass
    row2 = conn.execute('SELECT * FROM t WHERE id=2').fetchone()
    assert row2 is None, 'rollback failed'
    print('rollback ok')
    pool.close_thread_connection()
"

3. Verify SQL injection heuristic — no false positives (key change)

python -c "
from pt_database_manager import InputSanitizer
safe = ['dropbox', 'selection', 'truncate_me', 'executor', 'BTC-USD', 'user@email.com']
for v in safe:
    hit = InputSanitizer.check_sql_injection(v)
    print(f'  {v!r}: {\"FALSE POSITIVE\" if hit else \"ok\"}')
# Real injections must still be detected
injections = [\"DROP TABLE users\", \"1' UNION SELECT--\", \"val; DELETE\"]
for v in injections:
    hit = InputSanitizer.check_sql_injection(v)
    print(f'  {v!r}: {\"detected\" if hit else \"MISSED\"}')
"

Expected: all safe values show ok, all injections show detected.

4. Health monitor start/stop

python -c "
import tempfile, os, sqlite3, time
from pt_database_manager import DatabaseConnectionPool, DatabaseHealthMonitor

with tempfile.TemporaryDirectory() as d:
    db = os.path.join(d, 'health.db')
    sqlite3.connect(db).execute('CREATE TABLE x (id INTEGER)')
    mon = DatabaseHealthMonitor(db, check_interval=1)
    mon.start()
    print('running:', mon._thread.is_alive())
    time.sleep(0.2)
    mon.stop()
    print('stopped:', not mon._thread.is_alive())
    print('last_check_ok:', mon._last_check_ok)
"

Rollback

git checkout main -- app/pt_database_manager.py app/test_database_manager.py

Copilot AI review requested due to automatic review settings May 19, 2026 12:32

Copilot AI 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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@Ibrahim-3d

Copy link
Copy Markdown
Collaborator Author

/gemini review

Copilot AI 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.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

Comment thread app/pt_database_manager.py Outdated
Comment thread app/pt_database_manager.py Outdated
Comment thread app/security_audit.jsonl Outdated
Comment thread app/pt_database_manager.py
@sjackson0109

Copy link
Copy Markdown
Owner

@Ibrahim-3d
Unfortunately a few unit-tests seem to fail: https://github.com/sjackson0109/PowerTraderAI/actions/runs/26190881394/job/77058668525?pr=83

And the review (copilot) brings a small number of high risk items to the table:
#83 (review)

mind having a look?

- pt_database_manager: replace literal backspace char in _SQL_KEYWORD_RE
  with proper \b word boundaries (raw string was missing escape, compiled
  to \x08 instead of regex boundary, breaking all SQL keyword detection)
- pt_database_manager: build _SQL_KEYWORD_RE from _SQL_KEYWORDS_WORD set
  to eliminate duplicate keyword list and prevent drift
- pt_database_manager: restrict atomic_transaction retry detection to
  "database is busy" / "database is locked" only; "cannot start ..."
  no longer triggers retry (was matching nested-transaction config errors)
- test_database_manager: rewrite test_commit_contention_retries with a
  transparent connection wrapper; sqlite3.Connection.execute became
  read-only in Python 3.12 and could no longer be patch.object'd
- gitignore: add security_audit.jsonl and rotated variants so runtime
  audit logs never get committed accidentally
@Ibrahim-3d

Copy link
Copy Markdown
Collaborator Author

@sjackson0109 round-3 done — addressed in 84a36e3:

# File Issue Fix
1 pt_database_manager.py _SQL_KEYWORD_RE had literal \x08 (backspace) instead of \b — SQL keyword detection silently broken Raw string + re.IGNORECASE; pattern now \b(?:alter|create|delete|drop|exec|execute|insert|select|truncate|union|update)\b
2 pt_database_manager.py atomic_transaction retry detection matched "cannot start" (catches nested-tx config errors) Match only "database is busy" / "database is locked"
3 pt_database_manager.py _SQL_KEYWORDS_WORD unused — duplicate of regex source Regex now built from _SQL_KEYWORDS_WORD (single source of truth)
4 .gitignore + repo app/security_audit.jsonl runtime artifact in source tree Removed locally + added explicit patterns to .gitignore

Also fixed CI: Python 3.12 made sqlite3.Connection.execute read-only so patch.object(self.conn, "execute", ...) in test_commit_contention_retries failed with AttributeError. Rewrote with a transparent wrapper class — passes on 3.10/3.11/3.12 now.

32 unit tests pass locally. Threads resolved.

Copilot AI review requested due to automatic review settings May 21, 2026 13:57
@Ibrahim-3d Ibrahim-3d force-pushed the feat/54-database-security-transactions branch from 84a36e3 to c1b140a Compare May 21, 2026 13:57

Copilot AI 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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

Comment thread app/pt_database_manager.py
Comment thread app/pt_database_manager.py Outdated
@sjackson0109

Copy link
Copy Markdown
Owner

@Ibrahim-3d sorry there are two more from copilot’s review.

You should be able to tag copilot to ‘restart the review’.

@Ibrahim-3d

Ibrahim-3d commented May 23, 2026

Copy link
Copy Markdown
Collaborator Author

@sjackson0109 quick one - on the Copilot restart-review thing you mentioned earlier, idk why Your triggers work, mine don't. I have Copilot Pro on my account but tagging @copilot review on a PR doesn't kick off a review for me. Just tried on #80 / #81 / #82 / #92 and nothing happens. Could you check the Copilot Code Review access settings on this repo (probably under Settings -> Code & automation -> Code review) and confirm whether collaborators can request it, or whether it's tied to your account only? If you can share the exact method you use to restart a review I can copy that approach.

…ilability)

Two Copilot review threads:

1) atomic_transaction docstring overstated retry scope. The retry loop
   only re-runs BEGIN IMMEDIATE / COMMIT contention. Exceptions raised
   inside the with block (including busy/locked) are rolled back and
   re-raised unchanged - they cannot be retried because @contextmanager
   generators can only yield once. Clarified in docstring under a new
   'Retry scope' section so callers know to wrap body statements in
   their own retry loop if they need contention retry there.

2) DatabaseHealthMonitor.on_corrupt fired for any check_health failure,
   including missing file or transient sqlite IO errors. This could
   trigger emergency-stop on non-corruption conditions. Added new
   IntegrityStatus enum (OK / CORRUPT / UNAVAILABLE) and
   check_integrity() method on the pool. Monitor now only fires
   on_corrupt for true CORRUPT result; UNAVAILABLE routes to a new
   optional on_unavailable callback so callers can alert / retry rather
   than emergency-stop. Old check_health() / check_now() kept as
   back-compat boolean shims.

Tests: 4 new cases covering UNAVAILABLE classification, on_corrupt
guard against missing-file, OK classification, last_status exposure.
36 total pass.
Copilot AI review requested due to automatic review settings May 23, 2026 14:16

Copilot AI 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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@sjackson0109

Copy link
Copy Markdown
Owner

@sjackson0109 quick one - on the Copilot restart-review thing you mentioned earlier, idk why Your triggers work, mine don't. I have Copilot Pro on my account but tagging @copilot review on a PR doesn't kick off a review for me. Just tried on #80 / #81 / #82 / #92 and nothing happens. Could you check the Copilot Code Review access settings on this repo (probably under Settings -> Code & automation -> Code review) and confirm whether collaborators can request it, or whether it's tied to your account only? If you can share the exact method you use to restart a review I can copy that approach.

can we chat offline about this. Discord?

@sjackson0109 sjackson0109 merged commit f095da1 into sjackson0109:main May 24, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component-architecture System architecture and design components component-security Security components high-priority security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SECURITY] Implement database security and transaction management

3 participants