Skip to content

feat: phase 1 bootstrap hardening (sqlite-first, migration, health)#32

Merged
wauputr4 merged 6 commits into
mainfrom
codex-phase-1-checkpoint
May 10, 2026
Merged

feat: phase 1 bootstrap hardening (sqlite-first, migration, health)#32
wauputr4 merged 6 commits into
mainfrom
codex-phase-1-checkpoint

Conversation

@wauputr4
Copy link
Copy Markdown
Contributor

@wauputr4 wauputr4 commented May 10, 2026

Summary

  • Stabilize workspace bootstrap for phase-1 milestone
  • Switch default env to sqlite-first local data path and unique default API port (18180)
  • Add SQL migration runner wiring with migration toggle via env
  • Normalize SQLite URL to resolve relative paths safely
  • Harden first migration and startup flow

Validation

  • cargo fmt --all --check
  • cargo check --workspace
  • cargo test --workspace
  • cargo clippy --workspace --all-targets -- -D warnings
  • Manual smoke check: GET /healthz and GET /readyz on 127.0.0.1:18180

Notes

  • Runtime sqlite artifacts now ignored in git via .gitignore
  • Added migration file at migrations/0001_initial.sql

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request transitions the storage layer to support both SQLite and PostgreSQL, establishing SQLite as the default for early development phases. Key changes include the introduction of a centralized storage management module, automated migration handling, and the addition of a readiness health check endpoint. Feedback highlights several improvement opportunities: enforcing referential integrity in the initial SQL migrations via foreign keys, expanding the readiness check to include Redis, and optimizing asynchronous performance by replacing blocking filesystem operations. Additionally, suggestions were made to refine configuration parsing for SQLite URLs and adjust logging levels for unmatched routes to reduce noise.

Comment thread migrations/0001_initial.sql
Comment thread crates/mizan-api/src/lib.rs Outdated
Comment thread crates/mizan-api/src/lib.rs Outdated
Comment thread crates/mizan-api/src/storage.rs Outdated
Comment thread crates/mizan-api/src/storage.rs Outdated
Comment thread crates/mizan-api/src/storage.rs Outdated
Comment thread crates/mizan-core/src/config.rs Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1520788a5f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mizan-api/src/lib.rs Outdated
dependencies,
};

Json(response)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Return 503 when readiness checks fail

readyz always returns Json<HealthResponse>, which Axum serializes with HTTP 200 even when database_ok is false and status is set to not_ready. In deployments that use /readyz for readiness probing, this will keep the instance in service while its database dependency is unavailable, so traffic can be routed to a node that has already declared itself unready in the payload.

Useful? React with 👍 / 👎.

Comment thread crates/mizan-api/src/storage.rs Outdated
install_default_drivers();

let pool = AnyPoolOptions::new()
.max_connections(10)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid multi-connection pools for SQLite in-memory URLs

This path accepts sqlite://:memory: (see the explicit :memory: handling) but still creates an AnyPool with max_connections(10). For SQLite in-memory databases, each connection gets its own isolated database, so migrations can run on one connection while later queries hit another and fail with missing schema/data. This causes nondeterministic failures whenever tests or local runs use an in-memory URL.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f14e835c55

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mizan-core/src/config.rs Outdated
Comment on lines +35 to +38
run_migrations: env::var("MIZAN_RUN_MIGRATIONS")
.unwrap_or_else(|_| "true".to_owned())
.parse()
.unwrap_or(true),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor explicit migration-disable values

MIZAN_RUN_MIGRATIONS is parsed with .parse().unwrap_or(true), so any non-lowercase-true/false value silently becomes true. In practice, operators commonly set values like FALSE or 0 to disable startup migrations; with this code, migrations still run and can execute DDL unexpectedly in environments where schema changes are managed separately.

Useful? React with 👍 / 👎.

Comment thread crates/mizan-api/src/storage.rs Outdated
Comment on lines +30 to +31
if !database_url.starts_with("sqlite://") {
return Ok(());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle sqlite: URLs in sqlite directory setup

The sqlite parent-directory bootstrap only runs for URLs starting with sqlite://, but SQLx also accepts sqlite: file URLs (for example sqlite:data/mizan.sqlite3?mode=rwc). With that valid format, this function returns early, no parent directory is created, and startup can fail with unable to open database file when the directory does not already exist.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 991de6945e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mizan-api/src/auth.rs
Comment thread crates/mizan-api/src/auth.rs Outdated
Copy link
Copy Markdown
Contributor Author

✅ PR review-feedback fixes completed and pushed in commit 895b3e6:

  • Config: hardened sqlite URL normalization for sqlite: and sqlite://, added configurable MIZAN_DB_MAX_CONNECTIONS, strict bool parsing for MIZAN_RUN_MIGRATIONS.
  • Storage: async sqlite dir bootstrap, in-memory sqlite uses single connection, supports legacy sqlite: URL prefix.
  • API: /readyz now includes Redis ping + returns 503 when not ready; unmatched route log lowered to warn!.
  • Auth: backend-aware SQL placeholder translation (? -> $n for Postgres), session token extraction supports Authorization: Bearer with fallback to x-session-token.
  • Migration: added FK constraints for relational columns.

Validation run: cargo test -p mizan-core, cargo test -p mizan-api, cargo check --workspace, cargo test --workspace.

I also resolved the two still-active review threads on this PR directly (initial migration FK and Postgres bind syntax).

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 895b3e6b69

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mizan-core/src/config.rs Outdated
Copy link
Copy Markdown
Contributor Author

Terupdate untuk review baru P2 file::memory:

  • Implemented in commit 4a53c5b.
  • Update normalize_sqlite_url agar :memory: dan file::memory: keduanya langsung return original URL (tanpa remap path).
  • Tambah regression test preserves_sqlite_memory_urls_during_normalization (cover sqlite:file::memory:?cache=shared dan sqlite://file::memory:?cache=shared).
  • Run: cargo test -p mizan-core (6 passed).
  • Thread PRRT_kwDOSYRKSs6A4EzJ sudah saya resolve.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a53c5b2df

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mizan-api/src/auth.rs Outdated
Comment thread crates/mizan-api/src/auth.rs Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32f928c96f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +350 to +351
let hashed = bcrypt::hash(password, bcrypt::DEFAULT_COST)
.map_err(|error| AppError::infrastructure(format!("password hash failed: {error}")))?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Offload password hashing from async request workers

create_user runs bcrypt::hash directly on the async executor thread, and this path is used by the public /auth/register endpoint. Under concurrent sign-up traffic (or abuse), these CPU-heavy hashes can occupy Tokio worker threads and increase latency for unrelated requests. This should be moved to spawn_blocking (as done for password verification) so expensive hashing does not block the runtime.

Useful? React with 👍 / 👎.

@wauputr4 wauputr4 merged commit 2453654 into main May 10, 2026
1 check passed
@wauputr4 wauputr4 deleted the codex-phase-1-checkpoint branch May 10, 2026 07:52
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