Skip to content

feat(db): connection factory + env config + feature flags (Phase 2)#187

Merged
ajianaz merged 1 commit into
developfrom
feat/db-connection-factory-167
Jun 15, 2026
Merged

feat(db): connection factory + env config + feature flags (Phase 2)#187
ajianaz merged 1 commit into
developfrom
feat/db-connection-factory-167

Conversation

@ajianaz

@ajianaz ajianaz commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Phase 2 of the Multi-Backend Database epic (#171).

Adds a connection factory that detects the database URL scheme and instantiates the correct backend. Users select a backend via TRAPFALL_DATABASE_URL env var or --db flag.

Closes #167.

Changes

  • trapfall_db::open_database(url) — factory function detecting sqlite: / postgres: URL schemes
  • trapfall_db::normalise_url(url) — bare paths (e.g. trapfall.db) auto-prefixed with sqlite:
  • Cargo feature flags: default = ["sqlite"], optional postgres
    • sqlite module gated behind #[cfg(feature = "sqlite")]
    • Root sqlx dep trimmed to runtime-tokio; each crate opts-in its backend
  • TRAPFALL_DATABASE_URL env var support via clap env feature
    • --db changed from PathBuf to String (accepts URLs)
    • Fallback: --db flag → TRAPFALL_DATABASE_URL env → trapfall.db default
  • Docker: TRAPFALL_DATABASE_URL env var in docker-compose.yml
    • Dockerfile: cache trapfall-db/Cargo.toml in dependency stage
  • 9 factory tests: URL detection, feature flags, error messages, trait object sanity

Acceptance Criteria

Criteria Status
TRAPFALL_DATABASE_URL=sqlite:./trapfall.db works
postgres://... errors clearly if postgres feature not enabled
cargo build (default) = SQLite only
cargo build --features postgres = both backends compiled
Docker container starts with correct backend

Test Plan

  • cargo fmt --check — clean
  • cargo clippy --all-targets -- -D warnings — zero warnings
  • cargo test --workspace — 93 tests passed, 0 failed
  • cargo build --release -p trapfalld — binary builds
  • trapfall --help — shows database URL documentation
  • TRAPFALL_DATABASE_URL=sqlite:/tmp/test.db trapfall healthcheck — exit 0
  • trapfall --db /tmp/test.db healthcheck — exit 0 (bare path)
  • trapfall --db postgres://localhost/db healthcheck — clear error, exit 1

Roadmap

Phase Issue Status
1 — Trait abstraction #186 ✅ Merged
2 — Connection factory #167 This PR
3 — Postgres backend #168 Next (v0.1.0)
4 — Shared test suite #169 Next (v0.1.0)
5 — Migration tool #170 Next (v0.1.0)

…167)

- Add  factory in trapfall-db that detects URL scheme
  ( → SqliteBackend,  → PostgresBackend stub)
- Add  helper: bare paths auto-prefixed with
- Add Cargo feature flags: , optional
- Gate  module behind
- Read  env var via clap NVM_INC=/Users/ajianaz/.nvm/versions/node/v24.16.0/include/node
MANPATH=/Users/ajianaz/.nvm/versions/node/v24.16.0/share/man::/usr/share/man:/usr/local/share/man:/Applications/Ghostty.app/Contents/Resources/ghostty/../man:
GHOSTTY_RESOURCES_DIR=/Applications/Ghostty.app/Contents/Resources/ghostty
ZLE_RPROMPT_INDENT=0
TERM_PROGRAM=ghostty
NVM_CD_FLAGS=-q
POSH_SHELL=zsh
SHELL=/bin/zsh
TERM=xterm-256color
HOMEBREW_REPOSITORY=/opt/homebrew
TMPDIR=/var/folders/2p/cq1s63ns5ws25clfnxx1mv240000gn/T/
CONDA_PROMPT_MODIFIER=false
TERM_PROGRAM_VERSION=1.3.1
FPATH=/opt/homebrew/share/zsh/site-functions:/usr/local/share/zsh/site-functions:/usr/share/zsh/site-functions:/usr/share/zsh/5.9/functions:/Users/ajianaz/.orbstack/shell/completions/zsh
PI_CODING_AGENT=true
POWERLINE_COMMAND=oh-my-posh
ZAI_API_KEY=7bcf7223da584f608232b592bf493de1.k0ooxDcGZTWoHGX7
NVM_DIR=/Users/ajianaz/.nvm
POSH_SESSION_ID=6ac4ee50-10d7-4c1b-8b1c-e3f79bf41ccf
USER=ajianaz
COMMAND_MODE=unix2003
CHROME_EXECUTABLE=/Applications/Brave Browser.app/Contents/MacOS/Brave Browser
SSH_AUTH_SOCK=/var/run/com.apple.launchd.rxcSj5frzD/Listeners
PYENV_VIRTUALENV_DISABLE_PROMPT=1
__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0
VIRTUAL_ENV_DISABLE_PROMPT=1
PATH=/Users/ajianaz/.pi/agent/bin:/Users/ajianaz/bin:/Users/ajianaz/.local/bin:/Users/ajianaz/.antigravity/antigravity/bin:/Users/ajianaz/.bun/bin:/Users/ajianaz/.nvm/versions/node/v24.16.0/bin:/opt/homebrew/opt/python@3.12/libexec/bin:/opt/homebrew/bin:/Users/ajianaz/.pub-cache/bin:/Users/ajianaz/.npm-global/bin:/opt/homebrew/opt/openjdk@17/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/pkg/env/global/bin:/usr/local/co.palokaj.battery:/Library/Apple/usr/bin:/usr/local/go/bin:/Users/ajianaz/.cargo/bin:/Applications/Ghostty.app/Contents/MacOS:/Users/ajianaz/.orbstack/bin:/Users/ajianaz/Ngoding/flutter/bin:/usr/local/mysql/bin/mysql:/usr/local/bin:/usr/local/go/bin:/opt/homebrew/share/android-platform-tools
_=/usr/bin/env
LaunchInstanceID=39327689-4F43-4DB9-9891-BE35FF3D4A24
GHOSTTY_SHELL_FEATURES=cursor:blink,path,title
__CFBundleIdentifier=com.mitchellh.ghostty
PWD=/Users/ajianaz/Ngoding/project-latest/trapfall
JAVA_HOME=/opt/homebrew/opt/openjdk@17
FIRECRAWL_API_KEY=test
POSH_SHELL_VERSION=5.9
LANG=en_US.UTF-8
XPC_FLAGS=0x0
FIRECRAWL_API_URL=https://firecrawl.ajianaz.dev
XPC_SERVICE_NAME=0
HOME=/Users/ajianaz
SHLVL=2
OSTYPE=darwin25.0
TERMINFO=/Applications/Ghostty.app/Contents/Resources/terminfo
HOMEBREW_PREFIX=/opt/homebrew
PYTHONPATH=/Users/ajianaz/Ngoding/project-latest/Auto-Claude:
LOGNAME=ajianaz
XDG_DATA_DIRS=/usr/local/share:/usr/share:/Applications/Ghostty.app/Contents/Resources/ghostty/..
GHOSTTY_BIN_DIR=/Applications/Ghostty.app/Contents/MacOS
BUN_INSTALL=/Users/ajianaz/.bun
NVM_BIN=/Users/ajianaz/.nvm/versions/node/v24.16.0/bin
INFOPATH=/opt/homebrew/share/info:
HOMEBREW_CELLAR=/opt/homebrew/Cellar
OSLogRateLimit=64
SECURITYSESSIONID=186b7
COLORTERM=truecolor (falls back to )
- Change  from PathBuf to String (accepts URLs)
- Docker: support  env var in docker-compose
- Dockerfile: cache trapfall-db Cargo.toml in dependency stage
- Root sqlx dep trimmed to  only; crates opt-in backends
- Add clap NVM_INC=/Users/ajianaz/.nvm/versions/node/v24.16.0/include/node
MANPATH=/Users/ajianaz/.nvm/versions/node/v24.16.0/share/man::/usr/share/man:/usr/local/share/man:/Applications/Ghostty.app/Contents/Resources/ghostty/../man:
GHOSTTY_RESOURCES_DIR=/Applications/Ghostty.app/Contents/Resources/ghostty
ZLE_RPROMPT_INDENT=0
TERM_PROGRAM=ghostty
NVM_CD_FLAGS=-q
POSH_SHELL=zsh
SHELL=/bin/zsh
TERM=xterm-256color
HOMEBREW_REPOSITORY=/opt/homebrew
TMPDIR=/var/folders/2p/cq1s63ns5ws25clfnxx1mv240000gn/T/
CONDA_PROMPT_MODIFIER=false
TERM_PROGRAM_VERSION=1.3.1
FPATH=/opt/homebrew/share/zsh/site-functions:/usr/local/share/zsh/site-functions:/usr/share/zsh/site-functions:/usr/share/zsh/5.9/functions:/Users/ajianaz/.orbstack/shell/completions/zsh
PI_CODING_AGENT=true
POWERLINE_COMMAND=oh-my-posh
ZAI_API_KEY=7bcf7223da584f608232b592bf493de1.k0ooxDcGZTWoHGX7
NVM_DIR=/Users/ajianaz/.nvm
POSH_SESSION_ID=6ac4ee50-10d7-4c1b-8b1c-e3f79bf41ccf
USER=ajianaz
COMMAND_MODE=unix2003
CHROME_EXECUTABLE=/Applications/Brave Browser.app/Contents/MacOS/Brave Browser
SSH_AUTH_SOCK=/var/run/com.apple.launchd.rxcSj5frzD/Listeners
PYENV_VIRTUALENV_DISABLE_PROMPT=1
__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0
VIRTUAL_ENV_DISABLE_PROMPT=1
PATH=/Users/ajianaz/.pi/agent/bin:/Users/ajianaz/bin:/Users/ajianaz/.local/bin:/Users/ajianaz/.antigravity/antigravity/bin:/Users/ajianaz/.bun/bin:/Users/ajianaz/.nvm/versions/node/v24.16.0/bin:/opt/homebrew/opt/python@3.12/libexec/bin:/opt/homebrew/bin:/Users/ajianaz/.pub-cache/bin:/Users/ajianaz/.npm-global/bin:/opt/homebrew/opt/openjdk@17/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/pkg/env/global/bin:/usr/local/co.palokaj.battery:/Library/Apple/usr/bin:/usr/local/go/bin:/Users/ajianaz/.cargo/bin:/Applications/Ghostty.app/Contents/MacOS:/Users/ajianaz/.orbstack/bin:/Users/ajianaz/Ngoding/flutter/bin:/usr/local/mysql/bin/mysql:/usr/local/bin:/usr/local/go/bin:/opt/homebrew/share/android-platform-tools
_=/usr/bin/env
LaunchInstanceID=39327689-4F43-4DB9-9891-BE35FF3D4A24
GHOSTTY_SHELL_FEATURES=cursor:blink,path,title
__CFBundleIdentifier=com.mitchellh.ghostty
PWD=/Users/ajianaz/Ngoding/project-latest/trapfall
JAVA_HOME=/opt/homebrew/opt/openjdk@17
FIRECRAWL_API_KEY=test
POSH_SHELL_VERSION=5.9
LANG=en_US.UTF-8
XPC_FLAGS=0x0
FIRECRAWL_API_URL=https://firecrawl.ajianaz.dev
XPC_SERVICE_NAME=0
HOME=/Users/ajianaz
SHLVL=2
OSTYPE=darwin25.0
TERMINFO=/Applications/Ghostty.app/Contents/Resources/terminfo
HOMEBREW_PREFIX=/opt/homebrew
PYTHONPATH=/Users/ajianaz/Ngoding/project-latest/Auto-Claude:
LOGNAME=ajianaz
XDG_DATA_DIRS=/usr/local/share:/usr/share:/Applications/Ghostty.app/Contents/Resources/ghostty/..
GHOSTTY_BIN_DIR=/Applications/Ghostty.app/Contents/MacOS
BUN_INSTALL=/Users/ajianaz/.bun
NVM_BIN=/Users/ajianaz/.nvm/versions/node/v24.16.0/bin
INFOPATH=/opt/homebrew/share/info:
HOMEBREW_CELLAR=/opt/homebrew/Cellar
OSLogRateLimit=64
SECURITYSESSIONID=186b7
COLORTERM=truecolor feature to workspace dependencies
- Add 9 factory tests covering URL detection, feature flags, error messages
- Update CHANGELOG with [Unreleased] section

Acceptance criteria (#167):
✅  works (default)
✅  panics with clear message if  feature not enabled
✅  (default) = SQLite only
✅  = both backends compiled
✅ Docker container starts with correct backend via env var

Closes #167
@ajianaz ajianaz merged commit 01a2a49 into develop Jun 15, 2026
10 checks passed
@ajianaz ajianaz deleted the feat/db-connection-factory-167 branch June 15, 2026 16:01
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.

feat(db): connection factory + env config + feature flags (Phase 2)

1 participant