fix(db): remove hardcoded Postgres epoch expressions from query SQL - #542
Conversation
Login failed on SQLite when the RBAC role lookup ran "ura.expires_at > extract(epoch from current_timestamp)::bigint". Migrations and seeding both passed first, because this dialect leak lives in query code rather than in the schema, so it only surfaced when that path executed. Adds Kind.NowEpoch, plus dbdialect.NowEpochFromBun and a NowEpoch method on the connection for call sites that hold one, and routes all 20 live occurrences through them. Model default: tags are left alone: bun only emits those for zero values and BeforeAppendModel sets the fields first, so they never reach the database. TestNoHardcodedEpochExpression now fails if the expression reappears in query SQL. Writing it immediately found six occurrences a grep had missed, which is the point of having it. Three files are genuinely Postgres-only rather than sloppy, and opt out with a dialect:postgres-only marker: the session diagnostics repository reads pg_stat_activity and pg_blocking_pids, and the reporting compiler and A/R analytics bucket dates with date_trunc. The diagnostics repository now gates on a new CapSessionDiagnostic capability and returns 501 on SQLite; the two date bucketing sites are recorded in docs/databases.md as an outstanding gap. Also documents the rest of the known runtime surface, ILIKE and the numeric casts, so the next contributor does not have to find it one failing request at a time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FXYnxBszfwkNUeeAcVSSNf
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
trenova | b054248 | Aug 12 2026, 04:34 PM |
📝 WalkthroughWalkthroughThe change centralizes dialect-specific epoch SQL, adds PostgreSQL session-diagnostic capability checks, replaces hardcoded epoch expressions, documents SQLite conversion details, and applies formatting-only updates. ChangesDatabase dialect portability
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Repository
participant DatabaseConnection
participant Dialect
Repository->>DatabaseConnection: request NowEpoch()
DatabaseConnection->>Dialect: resolve configured database kind
Dialect-->>DatabaseConnection: return dialect-specific epoch SQL
DatabaseConnection-->>Repository: return timestamp expression
Repository->>DatabaseConnection: execute query with epoch expression
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
services/tms/pkg/dbdialect/dbdialect.go (1)
62-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover
CapSessionDiagnosticin the dialect tests.The shown
TestNowEpochtest checks only SQL output. Add assertions thatdbdialect.Postgres.Supports(db...CapSessionDiagnostic)is true anddbdialect.SQLite.Supports(db...CapSessionDiagnostic)is false. This protects the new SQLite session-diagnostic gate.Also applies to: 77-77
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@services/tms/pkg/dbdialect/dbdialect.go` at line 62, Extend the existing TestNowEpoch dialect test to assert capability support for CapSessionDiagnostic: Postgres.Supports must be true and SQLite.Supports must be false. Keep the existing SQL-output assertions unchanged and use the current dbdialect capability-testing conventions.services/tms/internal/infrastructure/postgres/connection.go (1)
404-404: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRemove the added Go comments in infrastructure/postgres code.
Both changes violate the repository path rule that forbids comments in Go code.
services/tms/internal/infrastructure/postgres/connection.go#L404-L404: remove the newNowEpochcomment.services/tms/internal/infrastructure/postgres/repositories/databasesessionrepository/databasesession.go#L1-L2: remove the PostgreSQL-only comment; it also uses the incorrect identifierCapSessionDiagnostics.As per coding guidelines,
services/tms/internal/infrastructure/postgres/**/*.gomust not add comments to Go code.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@services/tms/internal/infrastructure/postgres/connection.go` at line 404, Remove the added NowEpoch comment in services/tms/internal/infrastructure/postgres/connection.go at lines 404-404. Also remove the PostgreSQL-only comment referencing CapSessionDiagnostics in services/tms/internal/infrastructure/postgres/repositories/databasesessionrepository/databasesession.go at lines 1-2; no replacement comments are needed.Source: Coding guidelines
services/tms/internal/infrastructure/postgres/repositories/edimessagerepository/edimessage.go (1)
293-293: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse generated Bun column helpers for all changed repository column references.
These changed repository statements continue to embed column names as string literals. Replace each field reference with its generated helper while retaining the dialect-aware epoch expression.
services/tms/internal/infrastructure/postgres/repositories/edimessagerepository/edimessage.go#L293-L293: use the generated EDI messageUpdatedAthelper.services/tms/internal/infrastructure/postgres/repositories/edimessagerepository/edimessage.go#L630-L630: use the generated EDI messageUpdatedAthelper.services/tms/internal/infrastructure/postgres/repositories/emailrepository/email.go#L295-L295: use the generated profile-assignmentUpdatedAthelper.services/tms/internal/infrastructure/postgres/repositories/invoiceadjustmentrepository/invoiceadjustment.go#L594-L594: use the generated batch-itemUpdatedAthelper.services/tms/internal/infrastructure/postgres/repositories/journalpostingrepository/journalposting.go#L349-L349: use the generated GL-accountUpdatedAthelper.services/tms/internal/infrastructure/postgres/repositories/rbacrepository/rbac.go#L170-L170: use the generated user-role-assignment expiration helper and preserve theuraalias.services/tms/internal/infrastructure/postgres/repositories/shipmentimportchatrepository/shipmentimportchat.go#L158-L158: use the generated conversationUpdatedAthelper.services/tms/internal/infrastructure/postgres/repositories/tableconfigurationrepository/tableconfiguration.go#L412-L412: use the generated table-configurationUpdatedAthelper.services/tms/internal/infrastructure/postgres/repositories/tableconfigurationrepository/tableconfiguration.go#L444-L444: use the generated table-configurationUpdatedAthelper.As per coding guidelines, repository code must use generated column helpers from
services/tms/pkg/buncolgen/and must not hand-write column references. Based on learnings, this rule also applies to these repository paths.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@services/tms/internal/infrastructure/postgres/repositories/edimessagerepository/edimessage.go` at line 293, Replace every hand-written changed repository column reference with the corresponding generated helper from services/tms/pkg/buncolgen/, while preserving each dialect-aware r.db.NowEpoch() expression. Update EDI message UpdatedAt at services/tms/internal/infrastructure/postgres/repositories/edimessagerepository/edimessage.go:293-293 and :630-630; profile-assignment UpdatedAt at services/tms/internal/infrastructure/postgres/repositories/emailrepository/email.go:295-295; batch-item UpdatedAt at services/tms/internal/infrastructure/postgres/repositories/invoiceadjustmentrepository/invoiceadjustment.go:594-594; GL-account UpdatedAt at services/tms/internal/infrastructure/postgres/repositories/journalpostingrepository/journalposting.go:349-349; user-role-assignment expiration at services/tms/internal/infrastructure/postgres/repositories/rbacrepository/rbac.go:170-170 while preserving the ura alias; conversation UpdatedAt at services/tms/internal/infrastructure/postgres/repositories/shipmentimportchatrepository/shipmentimportchat.go:158-158; and table-configuration UpdatedAt at services/tms/internal/infrastructure/postgres/repositories/tableconfigurationrepository/tableconfiguration.go:412-412 and :444-444.Sources: Coding guidelines, Learnings
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/databases.md`:
- Line 86: Correct the `ALTER TABLE ... DROP COLUMN` description to state that
the converter emits the statement after removing blocking indexes when no index
or constraint still references the column; when a reference remains, it should
omit the statement.
In `@services/tms/pkg/dbdialect/dbdialect.go`:
- Around line 121-123: Remove the added NowEpoch documentation comment in
services/tms/pkg/dbdialect/dbdialect.go (lines 121-123), and remove the
dialect:postgres-only annotations in
services/tms/internal/core/services/reporting/compiler/outputs.go (line 1) and
services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.go
(line 1); no other changes are needed.
In `@services/tms/pkg/dbdialect/nowepoch_test.go`:
- Around line 50-53: Update the marker handling in the nowepoch test so
PostgreSQL-only files are exempted only when they are explicitly approved or
contain a capability guard such as dbdialect.RequireFromBun(...,
dbdialect.CapSessionDiagnostic); otherwise continue validating the file instead
of returning nil. Preserve the existing marker behavior for approved guarded
files.
---
Nitpick comments:
In `@services/tms/internal/infrastructure/postgres/connection.go`:
- Line 404: Remove the added NowEpoch comment in
services/tms/internal/infrastructure/postgres/connection.go at lines 404-404.
Also remove the PostgreSQL-only comment referencing CapSessionDiagnostics in
services/tms/internal/infrastructure/postgres/repositories/databasesessionrepository/databasesession.go
at lines 1-2; no replacement comments are needed.
In
`@services/tms/internal/infrastructure/postgres/repositories/edimessagerepository/edimessage.go`:
- Line 293: Replace every hand-written changed repository column reference with
the corresponding generated helper from services/tms/pkg/buncolgen/, while
preserving each dialect-aware r.db.NowEpoch() expression. Update EDI message
UpdatedAt at
services/tms/internal/infrastructure/postgres/repositories/edimessagerepository/edimessage.go:293-293
and :630-630; profile-assignment UpdatedAt at
services/tms/internal/infrastructure/postgres/repositories/emailrepository/email.go:295-295;
batch-item UpdatedAt at
services/tms/internal/infrastructure/postgres/repositories/invoiceadjustmentrepository/invoiceadjustment.go:594-594;
GL-account UpdatedAt at
services/tms/internal/infrastructure/postgres/repositories/journalpostingrepository/journalposting.go:349-349;
user-role-assignment expiration at
services/tms/internal/infrastructure/postgres/repositories/rbacrepository/rbac.go:170-170
while preserving the ura alias; conversation UpdatedAt at
services/tms/internal/infrastructure/postgres/repositories/shipmentimportchatrepository/shipmentimportchat.go:158-158;
and table-configuration UpdatedAt at
services/tms/internal/infrastructure/postgres/repositories/tableconfigurationrepository/tableconfiguration.go:412-412
and :444-444.
In `@services/tms/pkg/dbdialect/dbdialect.go`:
- Line 62: Extend the existing TestNowEpoch dialect test to assert capability
support for CapSessionDiagnostic: Postgres.Supports must be true and
SQLite.Supports must be false. Keep the existing SQL-output assertions unchanged
and use the current dbdialect capability-testing conventions.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: e26f5824-e655-4a77-a5e6-0b89bf99ac50
📒 Files selected for processing (28)
docs/databases.mdservices/tms/internal/core/services/ediservice/service.goservices/tms/internal/core/services/hosprojection/project_test.goservices/tms/internal/core/services/reporting/compiler/outputs.goservices/tms/internal/infrastructure/database/seeds/development/12_driverpay_ledger.goservices/tms/internal/infrastructure/pdfrender/gotenberg/client_live_test.goservices/tms/internal/infrastructure/postgres/connection.goservices/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.goservices/tms/internal/infrastructure/postgres/repositories/databasesessionrepository/databasesession.goservices/tms/internal/infrastructure/postgres/repositories/documentparsingrulerepository/documentparsingrule.goservices/tms/internal/infrastructure/postgres/repositories/driverpayrepository/assignment.goservices/tms/internal/infrastructure/postgres/repositories/driverpayrepository/payprofile.goservices/tms/internal/infrastructure/postgres/repositories/driversettlementrepository/batch.goservices/tms/internal/infrastructure/postgres/repositories/edimappingprofilerepository/edimappingprofiler.goservices/tms/internal/infrastructure/postgres/repositories/edimessagerepository/edimessage.goservices/tms/internal/infrastructure/postgres/repositories/editenderchangerepository/editenderchange.goservices/tms/internal/infrastructure/postgres/repositories/editenderrecipientrepository/editenderrecipient.goservices/tms/internal/infrastructure/postgres/repositories/editransferrepository/editransfer.goservices/tms/internal/infrastructure/postgres/repositories/emailrepository/email.goservices/tms/internal/infrastructure/postgres/repositories/invoiceadjustmentrepository/invoiceadjustment.goservices/tms/internal/infrastructure/postgres/repositories/journalpostingrepository/journalposting.goservices/tms/internal/infrastructure/postgres/repositories/rbacrepository/rbac.goservices/tms/internal/infrastructure/postgres/repositories/shipmentimportchatrepository/shipmentimportchat.goservices/tms/internal/infrastructure/postgres/repositories/tableconfigurationrepository/tableconfiguration.goservices/tms/internal/infrastructure/reporting/render/render_test.goservices/tms/pkg/dbdialect/bun.goservices/tms/pkg/dbdialect/dbdialect.goservices/tms/pkg/dbdialect/nowepoch_test.go
💤 Files with no reviewable changes (1)
- services/tms/internal/infrastructure/reporting/render/render_test.go
| | `ALTER TABLE ... ADD CONSTRAINT` | SQLite cannot add constraints after creation | | ||
| | `ALTER TABLE ... ALTER COLUMN` | SQLite cannot alter column definitions | | ||
| | `ALTER TABLE ... DROP COLUMN` | rejected whenever an index or `CHECK` still references the column | | ||
| | `ALTER TABLE ... DROP COLUMN` | only when an index or constraint still pins the column; otherwise it is emitted, dropping blocking indexes first | |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Correct the DROP COLUMN condition.
Line 86 says the statement is emitted only when an index or constraint still references the column, then says it is emitted otherwise. This reverses the documented behavior. State that the converter emits the statement after removing blocking indexes when no index or constraint still references the column; otherwise it drops the statement.
Proposed wording
-| `ALTER TABLE ... DROP COLUMN` | only when an index or constraint still pins the column; otherwise it is emitted, dropping blocking indexes first |
+| `ALTER TABLE ... DROP COLUMN` | emitted after dropping blocking indexes when no index or constraint still references the column; otherwise the statement is dropped |This follows the stated converter behavior in the line-range change details.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | `ALTER TABLE ... DROP COLUMN` | only when an index or constraint still pins the column; otherwise it is emitted, dropping blocking indexes first | | |
| | `ALTER TABLE ... DROP COLUMN` | emitted after dropping blocking indexes when no index or constraint still references the column; otherwise the statement is dropped | |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/databases.md` at line 86, Correct the `ALTER TABLE ... DROP COLUMN`
description to state that the converter emits the statement after removing
blocking indexes when no index or constraint still references the column; when a
reference remains, it should omit the statement.
| // NowEpoch returns the SQL expression for the current Unix timestamp as an | ||
| // integer. PostgreSQL has no portable spelling of this and SQLite has no | ||
| // extract(), so query builders must ask for it rather than hardcoding either. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- repository guidance ---'
for f in CLAUDE.md AGENTS.md; do
if [ -f "$f" ]; then
echo "### $f"
cat "$f"
fi
done
printf '%s\n' '--- target files and line ranges ---'
for f in \
services/tms/pkg/dbdialect/dbdialect.go \
services/tms/internal/core/services/reporting/compiler/outputs.go \
services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.go
do
echo "### $f"
wc -l "$f"
case "$f" in
*/dbdialect.go) sed -n '108,132p' "$f" ;;
*/outputs.go) sed -n '1,20p' "$f" ;;
*/analytics.go) sed -n '1,20p' "$f" ;;
esac
done
printf '%s\n' '--- targeted diff ---'
git diff --unified=8 -- \
services/tms/pkg/dbdialect/dbdialect.go \
services/tms/internal/core/services/reporting/compiler/outputs.go \
services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.goRepository: emoss08/Trenova
Length of output: 19164
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- repository state ---'
git status --short
git rev-parse --show-toplevel
git log -2 --oneline --decorate
printf '%s\n' '--- target-file change in HEAD versus its parent ---'
git diff --stat HEAD^ HEAD -- \
services/tms/pkg/dbdialect/dbdialect.go \
services/tms/internal/core/services/reporting/compiler/outputs.go \
services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.go
git diff --unified=12 HEAD^ HEAD -- \
services/tms/pkg/dbdialect/dbdialect.go \
services/tms/internal/core/services/reporting/compiler/outputs.go \
services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.go
printf '%s\n' '--- commits that introduced the exact comments ---'
git log --all --oneline -S'NowEpoch returns the SQL expression for the current Unix timestamp' -- services/tms/pkg/dbdialect/dbdialect.go
git log --all --oneline -S'dialect:postgres-only — report date bucketing compiles to date_trunc.' -- services/tms/internal/core/services/reporting/compiler/outputs.go
git log --all --oneline -S'dialect:postgres-only — collections analytics bucket dates with date_trunc.' -- services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.goRepository: emoss08/Trenova
Length of output: 4977
Remove or relocate the three added Go comments.
services/tms/pkg/dbdialect/dbdialect.go: remove theNowEpochdocumentation comment.services/tms/internal/core/services/reporting/compiler/outputs.go: remove thedialect:postgres-onlyannotation.services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.go: remove thedialect:postgres-onlyannotation.
📍 Affects 3 files
services/tms/pkg/dbdialect/dbdialect.go#L121-L123(this comment)services/tms/internal/core/services/reporting/compiler/outputs.go#L1-L1services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.go#L1-L1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@services/tms/pkg/dbdialect/dbdialect.go` around lines 121 - 123, Remove the
added NowEpoch documentation comment in services/tms/pkg/dbdialect/dbdialect.go
(lines 121-123), and remove the dialect:postgres-only annotations in
services/tms/internal/core/services/reporting/compiler/outputs.go (line 1) and
services/tms/internal/infrastructure/postgres/repositories/accountsreceivablerepository/analytics.go
(line 1); no other changes are needed.
Source: Coding guidelines
| // Files that are deliberately Postgres-only opt out with a marker. | ||
| // They must gate themselves on a capability instead. | ||
| if strings.Contains(string(contents), postgresOnlyMarker) { | ||
| return nil |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the PostgreSQL-only exemption enforce its capability check.
The marker check skips the entire file. It does not verify dbdialect.RequireFromBun(..., dbdialect.CapSessionDiagnostic) or another capability guard. A future file can add the marker and hardcode PostgreSQL SQL while this test still passes. Restrict the exemption to approved files or validate the guard before returning.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@services/tms/pkg/dbdialect/nowepoch_test.go` around lines 50 - 53, Update the
marker handling in the nowepoch test so PostgreSQL-only files are exempted only
when they are explicitly approved or contain a capability guard such as
dbdialect.RequireFromBun(..., dbdialect.CapSessionDiagnostic); otherwise
continue validating the file instead of returning nil. Preserve the existing
marker behavior for approved guarded files.
Description
Login failed on SQLite. The RBAC role lookup runs:
which SQLite rejects with
near "from": syntax error.Migrations and seeding both passed beforehand, because this dialect leak lives in query code rather than in the schema. It only surfaces when that code path executes, which is a different failure class from everything fixed so far and the reason it appeared at login rather than at startup.
Related Issue or Discussion
Follow-up to #540. Same SQLite development-support effort.
Type of Change
Scope
pkg/dbdialect— addsKind.NowEpoch(), returningextract(epoch from current_timestamp)::biginton PostgreSQL andunixepoch()on SQLite, plusNowEpochFromBun()for call sites holding only abun.IDBor a transaction.(*postgres.Connection).NowEpoch()is the convenience for repositories.20 live call sites across 16 repository, service and seed files now use those helpers instead of the literal expression.
The roughly 398
default:tags in domain models are deliberately not touched. bun only emits a default for a zero value, andBeforeAppendModelsetscreated_at/updated_atbefore every insert, so those never reach the database.TestNoHardcodedEpochExpressionfails the build if the expression reappears in query SQL. Worth noting that writing it immediately found six occurrences a grep had already missed — different casing and multi-line forms — which is the argument for having it rather than trusting a search.Three files are genuinely Postgres-only rather than careless, and opt out with a
dialect:postgres-onlymarker near the package clause:databasesessionrepositoryreadspg_stat_activityandpg_blocking_pids. It now gates on a newCapSessionDiagnosticcapability and returns 501 on SQLite.date_trunc. Left as-is and recorded as an outstanding gap; astrftimeequivalent is real work and did not belong in a login fix.docs/databases.mdgains a section on dialect leaks in query code, and a table of the remaining runtime surface —ILIKEin 17 files, roughly 109 numeric and jsonb casts, and thedate_truncbucketing — so the next contributor is not left discovering it one failing request at a time. Two stale figures are corrected while there: the converter now emits 1518 statements rather than 1471, andnumericmaps toREAL, notNUMERIC.Validation
cd services/tms && task test— passescd services/tms && task lint— not run. golangci-lint does not start here: built against Go 1.25 while the module targets 1.26. Changed files were formatted withgithub.com/golangci/golinesv0.15.0, the fork golangci-lint v2.12.2 embeds, which is what CI checks.cd client && pnpm build— no client changescd client && pnpm lint— no client changesgo build ./...— cleango test ./pkg/dbdialect/ ./pkg/dberror/ ./internal/infrastructure/database/seeder/— passes, including the full SQLite seed runDeployment Notes
No migrations, config or env changes.
PostgreSQL generates identical SQL:
Kind.NowEpoch()returns exactly the expression that was previously hardcoded. The only behavioural change on PostgreSQL is that database session diagnostics now pass through a capability check, which PostgreSQL always satisfies.Checklist
AGENTS.md,CLAUDE.md, and existing repository patterns.Generated by Claude Code
Summary by CodeRabbit
New Features
DROP COLUMNoperations.Bug Fixes
REALvalues where appropriate.Documentation