Skip to content

feat: add lifecycle states for config-only resources#2081

Merged
bjcoombs merged 14 commits intodevelopfrom
057-convergent-manifest-apply--10--lifecycle-states
Apr 1, 2026
Merged

feat: add lifecycle states for config-only resources#2081
bjcoombs merged 14 commits intodevelopfrom
057-convergent-manifest-apply--10--lifecycle-states

Conversation

@bjcoombs
Copy link
Copy Markdown
Collaborator

@bjcoombs bjcoombs commented Apr 1, 2026

Summary

  • Add ACTIVE/DEPRECATED lifecycle states to config-only resources: DataSource (market-information), ProviderConnection and InstructionRoute (operational-gateway)
  • Add DeprecateDataSource, DeprecateConnection, and DeprecateRoute gRPC RPCs
  • Add database migrations for status and deprecated_at columns with CHECK constraints

Details

Config-only resources (DataSource, ProviderConnection, InstructionRoute) previously had no lifecycle management. This PR adds proper ACTIVE/DEPRECATED states to enable deprecation instead of deletion, supporting PRD-057's convergent manifest apply semantics.

Design decisions:

  • Config-only resources go ACTIVE on creation (no DRAFT state)
  • Deprecation is idempotent (returns success if already DEPRECATED)
  • DataSource backward compatibility: existing is_active boolean derives from new status field
  • ProviderConnection: health_status (operational) remains separate from status (lifecycle)

Changes per service:

Market Information:

  • Proto: DataSourceStatus enum, status/deprecated_at fields, DeprecateDataSource RPC
  • Migration: status column with CHECK constraint on data_source table
  • Domain: DataSourceStatus type, Deprecate() method, builder methods
  • Persistence: Updated queries and mappers for status column
  • Service: DeprecateDataSource handler with error mapping

Operational Gateway:

  • Proto: ConnectionStatus/RouteStatus enums, DeprecateConnection/DeprecateRoute RPCs
  • Migration: status columns with CHECK constraints on provider_connections and instruction_routes
  • Domain: ConnectionStatus/RouteStatus types, Deprecate() methods
  • Persistence: Updated entities, repositories, and test DDL
  • Service: DeprecateConnection and DeprecateRoute handlers

Test plan

  • Operational-gateway persistence tests pass (verified locally)
  • Market-information tests pass
  • CI green across all checks
  • Proto generation matches committed .pb.go files

bjcoombs added 4 commits April 1, 2026 12:44
…tions

Add DataSourceStatus, ConnectionStatus, and RouteStatus enums with
ACTIVE/DEPRECATED states. Add DeprecateDataSource, DeprecateConnection,
and DeprecateRoute RPCs for config-only resource lifecycle management.
Add status (VARCHAR DEFAULT 'ACTIVE') and deprecated_at columns to
data_source, provider_connections, and instruction_routes tables with
CHECK constraints and tenant-scoped indexes.
Add ACTIVE/DEPRECATED status to DataSource domain model with Deprecate()
method, update persistence layer for status column, and add
DeprecateDataSource gRPC handler with idempotent deprecation semantics.
Add ACTIVE/DEPRECATED status to ProviderConnection and InstructionRoute
domain models with Deprecate() methods. Update persistence entities,
repositories, and gRPC handlers with DeprecateConnection and
DeprecateRoute endpoints. Update test DDL for new columns.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 1, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds deprecation lifecycle support across market-information and operational-gateway: new status enums and deprecated timestamps, proto RPCs for deprecation, domain deprecate methods/errors, repository deprecate operations, persistence schema/migrations, mappers, and service RPC handlers.

Changes

Cohort / File(s) Summary
Protobufs
api/proto/meridian/market_information/v1/market_information.proto, api/proto/meridian/operational_gateway/v1/operational_gateway.proto
Added enums (DataSourceStatus, ConnectionStatus, RouteStatus), added status and deprecated_at fields on relevant messages, and added deprecation RPCs (DeprecateDataSource, DeprecateConnection, DeprecateRoute) with request/response types and HTTP mappings.
Market Information — Domain & Service
services/market-information/domain/data_source.go, services/market-information/domain/repository.go, services/market-information/service/source_service.go
Introduced DataSourceStatus type/constants, added status/deprecatedAt fields and getters to DataSource, added builder setters and sentinel errors, extended repository interface with Deprecate, implemented Server.DeprecateDataSource, and added domain→proto status/deprecated_at conversions.
Market Information — Persistence & Migration
services/market-information/adapters/persistence/entities.go, .../mappers.go, .../source_repository.go, .../testhelpers/schema.sql, services/market-information/migrations/20260401000001_add_data_source_status.sql
Entity struct gains Status and DeprecatedAt; mappers updated including parseDataSourceStatus; upsert/select queries and scans include status/deprecated_at; added transactional SourceRepository.Deprecate; migration and test schema add columns, constraint, and index.
Operational Gateway — Domain & Service
services/operational-gateway/domain/provider_connection.go, services/operational-gateway/domain/instruction_route.go, services/operational-gateway/service/grpc_connection_service.go, services/operational-gateway/service/route_server.go
Added ConnectionStatus/RouteStatus types/constants and sentinel errors; added Status/DeprecatedAt fields and idempotent Deprecate() methods on domain types; added gRPC handlers DeprecateConnection and DeprecateRoute, persistence and mapping updates.
Operational Gateway — Persistence & Migration
services/operational-gateway/adapters/persistence/connection_entity.go, .../route_entity.go, .../mappers.go, .../connection_repository.go, .../route_repository.go, services/operational-gateway/migrations/20260401000001_add_connection_route_status.sql, services/operational-gateway/adapters/persistence/setup_test.go
Added Status/DeprecatedAt fields with GORM tags; upsert DO UPDATE updated to include status/deprecated_at; mappers roundtrip new fields; migration and test schema add columns, constraints, and indexes.
GRPC Mappers & Proto Conversions
services/operational-gateway/service/grpc_mappers.go, services/market-information/service/source_service.go
Added conversion helpers mapping domain statuses to proto enums and populated proto Status, DeprecatedAt, and timestamp fields in response messages.
Tests / Mocks / Linting
services/market-information/domain/repository_test.go, services/event-router/adapters/mds/market_data_publisher_test.go, tests/architecture/naming_test.go
Extended mock implementations with Deprecate/DeprecateDataSource stubs, added Deprecate to repository mock, and allowed Deprecate verb in naming test allowlist.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as gRPC Service
    participant Domain
    participant Repo
    participant DB

    Client->>API: Deprecate*Request(identifier)
    API->>Repo: FindBy...(identifier)
    Repo->>DB: SELECT ... WHERE identifier=?
    DB-->>Repo: row (status=ACTIVE)
    Repo-->>API: entity -> domain

    API->>Domain: call Deprecate()
    Domain-->>API: success / ErrNotActive

    API->>Repo: Deprecate(identifier) (txn)
    Repo->>DB: UPDATE ... SET status='DEPRECATED', deprecated_at=NOW() WHERE ... AND status='ACTIVE'
    DB-->>Repo: result (rows affected)
    Repo-->>API: success

    API->>Repo: FindBy...(identifier)
    Repo->>DB: SELECT ...
    DB-->>Repo: row (status=DEPRECATED)
    Repo-->>API: updated entity/domain

    API-->>Client: Deprecate*Response(updated resource proto)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add lifecycle states for config-only resources' directly and specifically captures the main change: adding ACTIVE/DEPRECATED lifecycle states (status management) to config-only resources.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the lifecycle state additions, design decisions, per-service changes, and test plan that align with the file modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 057-convergent-manifest-apply--10--lifecycle-states

Comment @coderabbitai help to get the list of available commands and usage tips.

Update generated TypeScript protobuf files for new lifecycle status
enums and deprecation RPCs added to market-information and
operational-gateway protos.
claude[bot]
claude Bot previously requested changes Apr 1, 2026
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

See summary comment for full review. 2 critical inline findings.

Comment thread services/market-information/adapters/persistence/source_repository.go Outdated
@claude
Copy link
Copy Markdown

claude Bot commented Apr 1, 2026

Claude Code Review

Commit: `c3eaa1d` | CI: running (all checks pending except migration checksums: pass)

Summary

Well-structured PR adding ACTIVE/DEPRECATED lifecycle states to three config-only resources across market-information and operational-gateway services. The operational-gateway implementation is clean — GORM-based persistence correctly includes both `status` and `deprecated_at` in entity mappings and upsert clauses. Domain models with idempotent `Deprecate()` methods are well-designed.

However, the market-information service has two correctness bugs in the persistence/service layers that will cause production failures after migration. These were flagged in the previous review and remain unresolved.

Risk Assessment

Area Level Detail
Blast radius High UpdateDataSource breaks for all callers after migration
Rollback Safe Migration adds columns with defaults; can be reverted
Scale Low No new queries without indexes; deprecation is rare
Cross-system Low No cross-service contracts changed
Migration Risky CockroachDB-safe DDL, but CHECK constraint interacts badly with existing UpdateDataSource handler

Findings

Severity Location Description Status
Critical `source_repository.go:49` `deprecated_at` missing from INSERT column list but referenced in ON CONFLICT as `EXCLUDED.deprecated_at` — upserts silently null out deprecation timestamps Open
Critical `source_service.go:89-105` + migration `:8` `UpdateDataSource` builder omits `WithStatus()` and `WithDeprecatedAt()` — zero-value status `""` violates CHECK constraint, breaking every update call post-migration Open

Bot Review Notes

CodeRabbit on `market_information.proto:466` — Valid minor concern. Proto doc says "Returns FAILED_PRECONDITION if data source is not in ACTIVE status" but the repo `Deprecate()` method returns success (nil) when already DEPRECATED. The idempotent behavior is correct; the proto doc just needs to say "Returns FAILED_PRECONDITION if data source is not in ACTIVE or DEPRECATED status" or explicitly document idempotency.

CodeRabbit on `setup_test.go:103` and `:158` — Valid minor concern. Test DDL for `provider_connections` and `instruction_routes` omits the `CHECK (status IN ('ACTIVE', 'DEPRECATED'))` constraints present in production migrations. Tests won't catch invalid status values at the DB layer. Worth adding for parity but not a blocker.

CodeRabbit on `schema.sql:21` — Marginal. Missing `idx_data_source_status` index in test schema. Indexes don't affect correctness in tests. Not actionable.

Questions for the Author

  1. `source_service.go:89` — The `UpdateDataSource` builder copies `IsActive` from the existing source but does not copy `Status` or `DeprecatedAt`. Was this intentional, or should these be preserved like other existing fields?

coderabbitai[bot]
coderabbitai Bot previously requested changes Apr 1, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
services/market-information/adapters/persistence/source_repository.go (2)

37-67: ⚠️ Potential issue | 🟠 Major

deprecated_at never reaches the database in Save.

DataSourceToEntity now carries entity.DeprecatedAt, but this upsert never inserts or binds that column. Any later Save of a deprecated source will drop its timestamp back to NULL, so the new field is not round-trippable.

💾 Include `deprecated_at` in the upsert payload
 		query := `
 			INSERT INTO data_source (
-				id, code, name, description, trust_level, status,
-				created_at, created_by, updated_at, updated_by, version
+				id, code, name, description, trust_level, status, deprecated_at,
+				created_at, created_by, updated_at, updated_by, version
 			) VALUES (
-				$1, $2, $3, $4, $5, $6,
-				$7, $8, $9, $10, 1
+				$1, $2, $3, $4, $5, $6, $7,
+				$8, $9, $10, $11, 1
 			)
 			ON CONFLICT (code) DO UPDATE SET
 				name = EXCLUDED.name,
 				description = EXCLUDED.description,
 				trust_level = EXCLUDED.trust_level,
@@
 		_, err := tx.Exec(ctx, query,
 			entity.ID,
 			entity.Code,
 			entity.Name,
 			entity.Description,
 			entity.TrustLevel,
 			entity.Status,
+			entity.DeprecatedAt,
 			entity.CreatedAt,
 			userID,
 			entity.UpdatedAt,
 			userID,
 		)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/market-information/adapters/persistence/source_repository.go` around
lines 37 - 67, The upsert in Save (in source_repository.go) omits
entity.DeprecatedAt from the INSERT payload so deprecated_at never gets
persisted; update the SQL INSERT column list and VALUES placeholders to include
deprecated_at, and add entity.DeprecatedAt to the tx.Exec argument list
(adjusting parameter order to match the new placeholder index) so
DataSourceToEntity's DeprecatedAt is persisted and round-trips correctly (the ON
CONFLICT already assigns deprecated_at = EXCLUDED.deprecated_at).

233-249: ⚠️ Potential issue | 🟠 Major

Honor activeOnly in both list queries.

api/proto/meridian/market_information/v1/market_information.proto says active_only should return only active data sources, but these queries still filter only deleted_at. After this change, List(..., true, ...) will keep returning status='DEPRECATED' rows.

📋 Thread `activeOnly` into the SQL builder
-func (r *SourceRepository) List(ctx context.Context, _ bool, pageSize int, pageToken string) ([]domain.DataSource, string, error) {
+func (r *SourceRepository) List(ctx context.Context, activeOnly bool, pageSize int, pageToken string) ([]domain.DataSource, string, error) {
@@
-		query, args := buildSourceListQuery(cursorTime, cursorID, pageSize)
+		query, args := buildSourceListQuery(activeOnly, cursorTime, cursorID, pageSize)
@@
-func buildSourceListQuery(cursorTime time.Time, cursorID uuid.UUID, pageSize int) (string, []interface{}) {
+func buildSourceListQuery(activeOnly bool, cursorTime time.Time, cursorID uuid.UUID, pageSize int) (string, []interface{}) {
+	whereClause := "WHERE deleted_at IS NULL"
+	if activeOnly {
+		whereClause += " AND status = 'ACTIVE'"
+	}
+
 	if cursorTime.IsZero() {
 		return `
 			SELECT id, code, name, description, trust_level, status, created_at, updated_at, deprecated_at, version
 			FROM data_source
-			WHERE deleted_at IS NULL
+			` + whereClause + `
 			ORDER BY date_trunc('second', created_at) DESC, id DESC
 			LIMIT $1`, []interface{}{pageSize + 1}
 	}
 
 	return `
 		SELECT id, code, name, description, trust_level, status, created_at, updated_at, deprecated_at, version
 		FROM data_source
-		WHERE deleted_at IS NULL
+		` + whereClause + `
 			AND (
 				date_trunc('second', created_at) < $1
 				OR (date_trunc('second', created_at) = $1 AND id < $2)
 			)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/market-information/adapters/persistence/source_repository.go` around
lines 233 - 249, The list SQL currently only filters deleted_at but ignores the
activeOnly flag; update the two query branches in source_repository.go (the
no-cursor and cursor-returning queries built by the list function) to add "AND
status = 'ACTIVE'" when the activeOnly boolean is true, thread activeOnly into
the SQL builder so the WHERE clause is conditionally extended, and adjust the
parameter list/order (and the $n positional placeholders) to include no extra
params for the simple branch or to include activeOnly only if used; ensure the
queries still use cursorTime, cursorID, and pageSize + 1 variables (and update
$1/$2/$3 indices accordingly) when building the cursor query.
services/market-information/adapters/persistence/mappers.go (1)

113-130: ⚠️ Potential issue | 🔴 Critical

Status is now required, but existing builder call sites still omit it.

DataSourceToEntity now always persists s.Status(). In services/market-information/service/source_service.go, the builders starting at Line 83 and Line 143 still never call WithStatus(...). That makes UpdateDataSource write status="" and hit chk_data_source_status, and DeactivateDataSource now returns DATA_SOURCE_STATUS_UNSPECIFIED.

🔧 Preserve lifecycle fields when rebuilding a source
 builder := domain.NewDataSourceBuilder().
 	WithID(existing.ID()).
 	WithCode(existing.Code()).
 	WithSourceType(existing.SourceType()).
 	WithIsActive(existing.IsActive()).
+	WithStatus(existing.Status()).
 	WithCreatedAt(existing.CreatedAt()).
 	WithUpdatedAt(time.Now())

+if existing.DeprecatedAt() != nil {
+	builder.WithDeprecatedAt(existing.DeprecatedAt())
+}

Apply the same preservation in DeactivateDataSource.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/market-information/adapters/persistence/mappers.go` around lines 113
- 130, The DataSourceToEntity mapper now always writes s.Status(), but the
builder usages in services/market-information/service/source_service.go (used by
UpdateDataSource and DeactivateDataSource) don’t set Status, so updates write an
empty status and validations fail; fix the builders to preserve lifecycle fields
when rebuilding sources by passing the existing entity's status into the builder
(call WithStatus(existing.Status()) or the domain object's Status()) and also
preserve other lifecycle fields the mapper expects (Description, DeprecatedAt,
CreatedAt, UpdatedAt, Version) when constructing the new domain/DataSource
before calling DataSourceToEntity; apply the same preservation logic in
DeactivateDataSource so it sets Status (and DeprecatedAt) correctly instead of
leaving it unspecified.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/proto/meridian/market_information/v1/market_information.proto`:
- Around line 457-466: Update the DeprecateDataSource RPC comment to document
idempotency: state that calling DeprecateDataSource transitions a data source
from ACTIVE to DEPRECATED, returns NOT_FOUND if missing, and is idempotent — it
returns success when the source is already DEPRECATED (instead of
FAILED_PRECONDITION); only return FAILED_PRECONDITION for statuses that are
neither ACTIVE nor DEPRECATED. Reference the RPC name DeprecateDataSource in the
proto and the persistence behavior in
services/market-information/adapters/persistence/source_repository.go so
generated OpenAPI/SDK docs reflect the actual behavior.

In `@services/market-information/domain/repository.go`:
- Around line 170-174: The mockSourceRepository needs to implement the new
Deprecate(ctx context.Context, code string) error method to satisfy the
SourceRepository interface; add a Deprecate method on mockSourceRepository with
the same signature, returning nil or the appropriate test error (e.g.,
ErrDataSourceNotFound / ErrDataSourceNotActive) based on the mock's configured
state so existing compile-time assertions and tests continue to pass; ensure the
method uses the mock's existing fields/behaviors (the same patterns as other
mock methods like Create/Update) so tests can simulate success and failure
cases.

In `@services/operational-gateway/adapters/persistence/setup_test.go`:
- Around line 157-158: The test DDL for the instruction_routes table is missing
the CHECK constraint on the status column; update the test schema in
setup_test.go so the instruction_routes definition includes the same constraint
as production (e.g., status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' CHECK (status
IN ('ACTIVE','DEPRECATED'))), ensuring the status column and its default remain
unchanged but add the CHECK clause to enforce valid values during tests.
- Around line 102-103: Test DDL for table provider_connections is missing the
CHECK constraint on the status column; update the DDL in setup_test.go where
provider_connections is defined to add the same constraint as production (e.g.,
"CHECK (status IN ('ACTIVE','DEPRECATED'))") on the status VARCHAR(20) NOT NULL
DEFAULT 'ACTIVE' column so tests enforce the same valid values as the migration.

---

Outside diff comments:
In `@services/market-information/adapters/persistence/mappers.go`:
- Around line 113-130: The DataSourceToEntity mapper now always writes
s.Status(), but the builder usages in
services/market-information/service/source_service.go (used by UpdateDataSource
and DeactivateDataSource) don’t set Status, so updates write an empty status and
validations fail; fix the builders to preserve lifecycle fields when rebuilding
sources by passing the existing entity's status into the builder (call
WithStatus(existing.Status()) or the domain object's Status()) and also preserve
other lifecycle fields the mapper expects (Description, DeprecatedAt, CreatedAt,
UpdatedAt, Version) when constructing the new domain/DataSource before calling
DataSourceToEntity; apply the same preservation logic in DeactivateDataSource so
it sets Status (and DeprecatedAt) correctly instead of leaving it unspecified.

In `@services/market-information/adapters/persistence/source_repository.go`:
- Around line 37-67: The upsert in Save (in source_repository.go) omits
entity.DeprecatedAt from the INSERT payload so deprecated_at never gets
persisted; update the SQL INSERT column list and VALUES placeholders to include
deprecated_at, and add entity.DeprecatedAt to the tx.Exec argument list
(adjusting parameter order to match the new placeholder index) so
DataSourceToEntity's DeprecatedAt is persisted and round-trips correctly (the ON
CONFLICT already assigns deprecated_at = EXCLUDED.deprecated_at).
- Around line 233-249: The list SQL currently only filters deleted_at but
ignores the activeOnly flag; update the two query branches in
source_repository.go (the no-cursor and cursor-returning queries built by the
list function) to add "AND status = 'ACTIVE'" when the activeOnly boolean is
true, thread activeOnly into the SQL builder so the WHERE clause is
conditionally extended, and adjust the parameter list/order (and the $n
positional placeholders) to include no extra params for the simple branch or to
include activeOnly only if used; ensure the queries still use cursorTime,
cursorID, and pageSize + 1 variables (and update $1/$2/$3 indices accordingly)
when building the cursor query.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f496463d-2978-4a2c-9d8a-b294ac2ddfbc

📥 Commits

Reviewing files that changed from the base of the PR and between 3e7dd8e and d550297.

⛔ Files ignored due to path filters (8)
  • api/proto/meridian/market_information/v1/market_information.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • api/proto/meridian/market_information/v1/market_information_grpc.pb.go is excluded by !**/*.pb.go, !**/*.pb.go, !**/*_grpc.pb.go
  • api/proto/meridian/operational_gateway/v1/operational_gateway.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • api/proto/meridian/operational_gateway/v1/operational_gateway_grpc.pb.go is excluded by !**/*.pb.go, !**/*.pb.go, !**/*_grpc.pb.go
  • frontend/src/api/gen/meridian/market_information/v1/market_information_pb.ts is excluded by !**/gen/**
  • frontend/src/api/gen/meridian/operational_gateway/v1/operational_gateway_pb.ts is excluded by !**/gen/**
  • services/market-information/migrations/atlas.sum is excluded by !**/*.sum
  • services/operational-gateway/migrations/atlas.sum is excluded by !**/*.sum
📒 Files selected for processing (21)
  • api/proto/meridian/market_information/v1/market_information.proto
  • api/proto/meridian/operational_gateway/v1/operational_gateway.proto
  • services/market-information/adapters/persistence/entities.go
  • services/market-information/adapters/persistence/mappers.go
  • services/market-information/adapters/persistence/source_repository.go
  • services/market-information/domain/data_source.go
  • services/market-information/domain/repository.go
  • services/market-information/migrations/20260401000001_add_data_source_status.sql
  • services/market-information/service/source_service.go
  • services/operational-gateway/adapters/persistence/connection_entity.go
  • services/operational-gateway/adapters/persistence/connection_repository.go
  • services/operational-gateway/adapters/persistence/mappers.go
  • services/operational-gateway/adapters/persistence/route_entity.go
  • services/operational-gateway/adapters/persistence/route_repository.go
  • services/operational-gateway/adapters/persistence/setup_test.go
  • services/operational-gateway/domain/instruction_route.go
  • services/operational-gateway/domain/provider_connection.go
  • services/operational-gateway/migrations/20260401000001_add_connection_route_status.sql
  • services/operational-gateway/service/grpc_connection_service.go
  • services/operational-gateway/service/grpc_mappers.go
  • services/operational-gateway/service/route_server.go

Comment thread api/proto/meridian/market_information/v1/market_information.proto
Comment thread services/market-information/domain/repository.go
Comment thread services/operational-gateway/adapters/persistence/setup_test.go
Comment thread services/operational-gateway/adapters/persistence/setup_test.go
The mock did not implement the new Deprecate interface method, causing
golangci-lint typecheck failures.
claude[bot]
claude Bot previously requested changes Apr 1, 2026
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Two critical correctness bugs remain unresolved from previous review. See summary comment for full details.

The generated MarketInformationServiceClient interface gained the new
DeprecateDataSource RPC method, requiring mock implementations to match.
claude[bot]
claude Bot previously requested changes Apr 1, 2026
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Two correctness bugs in market-information persistence. See summary comment.

Replace string literals with domain type constants in parseDataSetStatus
and parseDataSourceStatus to avoid repeated string occurrences.
claude[bot]
claude Bot previously requested changes Apr 1, 2026
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Two critical correctness bugs in market-information persistence. See summary comment.

bjcoombs added 2 commits April 1, 2026 13:55
Lifecycle deprecation is a standard operation for config-only resources,
alongside Create/Find/Update/Delete.
The market-information test helper schema.sql was missing the new
lifecycle columns, causing integration test failures.
coderabbitai[bot]
coderabbitai Bot previously requested changes Apr 1, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@services/market-information/adapters/persistence/testhelpers/schema.sql`:
- Around line 16-21: The test schema is missing the index for data_source.status
causing drift; add the same index as production by creating
idx_data_source_status on the data_source table for the status column (match the
index name used in migrations: idx_data_source_status) so the test DDL mirrors
services/market-information/migrations/20260401000001_add_data_source_status.sql;
update the schema definition near the data_source CREATE TABLE block to include
the index creation for status.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 366f457d-abb7-4881-91c9-83f24fe28809

📥 Commits

Reviewing files that changed from the base of the PR and between 581b39b and 484502e.

📒 Files selected for processing (2)
  • services/market-information/adapters/persistence/testhelpers/schema.sql
  • tests/architecture/naming_test.go

claude[bot]
claude Bot previously requested changes Apr 1, 2026
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Two critical bugs must be fixed. See summary comment for full details.

The createSchemaDataSourceTable function for multi-tenant test schemas
was missing the new columns, causing column mismatch when copying data
sources from the public schema via SELECT *.
claude[bot]
claude Bot previously requested changes Apr 1, 2026
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Two critical correctness bugs remain in market-information:

  1. source_repository.go:51 - deprecated_at missing from INSERT (see inline)
  2. source_service.go:89-105 (not in diff) - UpdateDataSource builder omits WithStatus() and WithDeprecatedAt(). Zero-value DataSourceStatus is empty string, violating the new CHECK constraint. Every UpdateDataSource call will fail post-migration. Fix: add WithStatus(existing.Status()) and WithDeprecatedAt(existing.DeprecatedAt()) to the builder chain.

See summary comment for full details including bot thread assessments.

bjcoombs added 2 commits April 1, 2026 15:02
Critical fixes:
- Add deprecated_at to INSERT column list in Save (was missing, causing
  EXCLUDED.deprecated_at to always be NULL)
- Preserve status and deprecated_at in UpdateDataSource and
  DeactivateDataSource builders (zero-value status violated CHECK constraint)
- Add CHECK constraints to operational-gateway test DDL for parity
- Add idx_data_source_status to test schema to match production
- Update proto comment to document idempotent deprecation behavior
Use WithDeprecatedAt directly in builder chain instead of conditional
block, reducing function size below 60-line threshold.
@bjcoombs bjcoombs dismissed stale reviews from claude[bot] and coderabbitai[bot] April 1, 2026 15:20

Stale bot review - all findings addressed

@bjcoombs bjcoombs dismissed stale reviews from claude[bot], claude[bot], claude[bot], coderabbitai[bot], claude[bot], and claude[bot] April 1, 2026 15:20

Stale bot review - all findings addressed

@bjcoombs bjcoombs merged commit 96aeaaf into develop Apr 1, 2026
39 of 45 checks passed
@bjcoombs bjcoombs deleted the 057-convergent-manifest-apply--10--lifecycle-states branch April 1, 2026 15:20
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