keiro-migrations (empty) → 0.2.0.0
raw patch · 318 files changed
+7353/−0 lines, 318 filesdep +aesondep +asyncdep +attoparsec
Dependencies added: aeson, async, attoparsec, base, bytestring, codd, codd-extras, containers, contravariant-extras, directory, ephemeral-pg, file-embed, filepath, generic-lens, hasql, hasql-pool, hspec, keiro-migrations, kiroku-store, kiroku-store-migrations, lens, optparse-applicative, pg-migrate, pg-migrate-cli, pg-migrate-embed, pg-migrate-import-codd, pg-migrate-test-support, template-haskell, temporary, text, time, vector
Files
- CHANGELOG.md +112/−0
- README.md +100/−0
- app/Main.hs +48/−0
- app/WriteExpectedSchema.hs +13/−0
- expected-schema/v18/db-settings +8/−0
- expected-schema/v18/roles/keiro +12/−0
- expected-schema/v18/schemas/keiro/objrep +11/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/awakeable_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/completed_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/created_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/owner_workflow_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/owner_workflow_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/payload +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/status +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/updated_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_awakeable_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_created_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_owner_workflow_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_owner_workflow_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_status_chk +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_status_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_updated_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_owner_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_pending_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_awakeables/objrep +32/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/attempt_count +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/attributes +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/causation_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/completed_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/content_type +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/correlation_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/dedupe_key +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/destination +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/event_type +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/failed_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_offset +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_partition +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_topic +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/last_error +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/message_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/occurred_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/payload_bytes +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/received_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_fingerprint +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_registry +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_subject +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_version +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_version_ref +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source_event_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source_global_position +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/status +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/traceparent +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/tracestate +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_attempt_count_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_content_type_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_dedupe_key_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_payload_bytes_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_received_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_source_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_status_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_backlog_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_completed_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_inbox/objrep +54/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/attempt_count +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/attributes +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/causation_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/content_type +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/correlation_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/created_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/destination +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/event_type +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/last_error +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/message_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/message_key +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/next_attempt_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/occurred_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/outbox_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/payload_bytes +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/published_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_fingerprint +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_registry +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_subject +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_version +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_version_ref +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source_event_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source_global_position +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/status +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/traceparent +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/tracestate +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/updated_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_attempt_count_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_content_type_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_created_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_destination_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_event_type_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_message_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_next_attempt_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_occurred_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_outbox_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_payload_bytes_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_schema_version_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_source_message_id_key +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_source_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_status_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_updated_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_claim_order_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_head_of_line_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_pending_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_sent_gc_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_source_message_id_key +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_source_order_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_outbox/objrep +53/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/applied_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/event_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/projection_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_applied_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_event_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_projection_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/indexes/keiro_projection_dedup_applied_at_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/indexes/keiro_projection_dedup_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/objrep +27/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/last_built_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/shape_hash +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/status +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/updated_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/version +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_shape_hash_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_status_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_updated_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_version_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/indexes/keiro_read_models_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_read_models/objrep +30/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/created_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/regfile_shape_hash +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/state +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/state_codec_version +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/stream_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/stream_version +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/updated_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_created_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_regfile_shape_hash_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_state_codec_version_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_state_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_stream_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_stream_version_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_updated_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/indexes/keiro_snapshots_compat_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/indexes/keiro_snapshots_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_snapshots/objrep +31/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/bucket +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/heartbeat_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/lease_expires_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/owner_worker_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/shard_count +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/subscription_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/updated_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_bucket_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_bucket_range_chk +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_count_chk +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_shard_count_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_subscription_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_updated_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_lease_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_owner_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/objrep +31/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/attempts +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/correlation_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/created_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/fire_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/fired_event_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/last_error +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/payload +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/process_manager_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/status +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/timer_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/updated_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_attempts_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_correlation_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_created_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_fire_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_payload_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_process_manager_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_status_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_timer_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_updated_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/indexes/keiro_timers_due_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/indexes/keiro_timers_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_timers/objrep +35/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/await_step +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/child_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/child_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/completed_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/created_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/parent_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/parent_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/result +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/status +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/updated_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_await_step_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_child_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_child_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_created_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_parent_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_parent_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_status_chk +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_status_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_updated_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_parent_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_running_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/objrep +34/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/generation +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/recorded_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/result +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/step_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/workflow_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/workflow_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_generation_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_recorded_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_result_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_step_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_workflow_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_workflow_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/indexes/keiro_workflow_steps_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/indexes/keiro_workflow_steps_workflow_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/objrep +30/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/attempts +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/completed_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/created_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/generation +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/last_error +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/lease_expires_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/leased_by +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/next_attempt_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/status +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/updated_at +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/wake_after +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/workflow_id +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/workflow_name +13/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_attempts_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_created_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_generation_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_pkey +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_status_chk +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_status_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_updated_at_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_workflow_id_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_workflow_name_not_null +16/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_active_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_gc_idx +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_pkey +21/−0
- expected-schema/v18/schemas/keiro/tables/keiro_workflows/objrep +37/−0
- keiro-migrations.cabal +439/−0
- migrations.lock +16/−0
- migrations/0001-keiro-bootstrap.sql +44/−0
- migrations/0002-keiro-outbox.sql +39/−0
- migrations/0003-keiro-inbox.sql +39/−0
- migrations/0004-keiro-timer-recovery.sql +8/−0
- migrations/0005-keiro-workflow-steps.sql +21/−0
- migrations/0006-keiro-awakeables.sql +33/−0
- migrations/0007-keiro-workflow-children.sql +39/−0
- migrations/0008-keiro-workflow-generation.sql +25/−0
- migrations/0009-keiro-subscription-shards.sql +38/−0
- migrations/0010-keiro-messaging-crash-recovery.sql +21/−0
- migrations/0011-keiro-workflows-instances.sql +76/−0
- migrations/0012-keiro-workflow-gc-index.sql +3/−0
- migrations/0013-keiro-workflows-wake-after.sql +3/−0
- migrations/0014-keiro-projection-dedup.sql +9/−0
- migrations/0015-keiro-outbox-claim-order-index.sql +6/−0
- migrations/0016-keiro-inbox-drop-received-idx.sql +4/−0
- migrations/0017-schema-management-comment.sql +2/−0
- migrations/0018.sql +28/−0
- migrations/manifest +18/−0
- sql-migrations/2026-05-17-13-58-15-keiro-bootstrap.sql +44/−0
- sql-migrations/2026-05-19-12-55-02-keiro-outbox.sql +39/−0
- sql-migrations/2026-05-19-13-05-23-keiro-inbox.sql +39/−0
- sql-migrations/2026-06-03-05-14-28-keiro-timer-recovery.sql +8/−0
- sql-migrations/2026-06-03-16-10-05-keiro-workflow-steps.sql +21/−0
- sql-migrations/2026-06-03-18-19-41-keiro-awakeables.sql +33/−0
- sql-migrations/2026-06-03-19-49-23-keiro-workflow-children.sql +39/−0
- sql-migrations/2026-06-04-02-12-28-keiro-workflow-generation.sql +25/−0
- sql-migrations/2026-06-04-03-53-34-keiro-subscription-shards.sql +38/−0
- sql-migrations/2026-06-15-13-22-31-keiro-messaging-crash-recovery.sql +21/−0
- sql-migrations/2026-06-15-15-07-25-keiro-workflows-instances.sql +76/−0
- sql-migrations/2026-06-15-17-53-48-keiro-workflow-gc-index.sql +3/−0
- sql-migrations/2026-06-15-18-01-33-keiro-workflows-wake-after.sql +3/−0
- sql-migrations/2026-06-15-21-49-37-keiro-projection-dedup.sql +9/−0
- sql-migrations/2026-07-02-00-15-48-keiro-outbox-claim-order-index.sql +6/−0
- sql-migrations/2026-07-02-00-58-54-keiro-inbox-drop-received-idx.sql +4/−0
- src/Keiro/Migrations.hs +31/−0
- src/Keiro/Migrations/ExpectedSchema.hs +19/−0
- src/Keiro/Migrations/History/Codd.hs +127/−0
- src/Keiro/Migrations/Internal/Definition.hs +27/−0
- src/Keiro/Migrations/Internal/EmbedFile.hs +19/−0
- src/Keiro/Migrations/LegacyCodd.hs +118/−0
- src/Keiro/Migrations/New.hs +51/−0
- test-legacy/Main.hs +689/−0
- test/Main.hs +426/−0
+ CHANGELOG.md view
@@ -0,0 +1,112 @@+# Changelog++All notable changes to `keiro-migrations` are recorded here. The format follows+[Keep a Changelog](https://keepachangelog.com/), and the package follows the+[Haskell Package Versioning Policy](https://pvp.haskell.org/).++## [Unreleased]++_No unreleased changes._++## 0.2.0.0 — 2026-07-13++### Added++- Appended `0018`, creating `keiro.keiro_dead_letters`. It durably records+ process-manager and router dispatches that reached a target stream and were+ rejected. These rows are distinct from `kiroku.dead_letters`: the source+ subscription event is successfully handled and checkpointed only after every+ rejected dispatch has been recorded. The `keiro` package reads and replays them+ through `Keiro.DeadLetter`.+- Appended `0017-schema-management-comment`, an observable non-destructive+ native-runner canary. The combined-history fixture proves Kiroku `0008`+ completes before Keiro `0017`, then strict verification and reruns succeed.++### Breaking Changes++- Replaced the public Codd runner surface with native `pg-migrate` APIs.+ `keiroMigrations` now returns the `keiro` `MigrationComponent`, and+ `frameworkMigrationPlan` composes concrete Kiroku and Keiro components in+ dependency order. The standard `keiro-migrate` CLI now uses the `pgmigrate`+ ledger.+- Renamed the sixteen embedded migrations to stable component-local identifiers+ under `migrations/manifest` while preserving every legacy SQL payload byte.+ Timestamped filenames and `migrations.lock` remain import evidence only.+- **Keiro's framework tables moved out of the `kiroku` schema into a new,+ dedicated `keiro` PostgreSQL schema that Keiro creates and owns.** The+ bootstrap migration now issues `CREATE SCHEMA IF NOT EXISTS keiro`, and every+ migration creates its objects schema-qualified as `keiro.<table>` with **no**+ `SET search_path` pin and no explanatory comment. The `keiro-migrate new`+ scaffolder emits that qualified, comment-free template.+- The codd expected-schema drift gate is now scoped to the `keiro` namespace+ (`CODD_SCHEMAS=keiro`), contains only `keiro_*` objects, and is **portable**:+ the captured database role and owner are a deterministic pinned `keiro`+ identity rather than the local operating-system user, so+ `cabal test keiro-migrations-test` passes on any machine and in CI.+- Read-model and projection tables now support a **configurable schema**: an+ application declares the schema its read-model/projection tables live in (a+ `schema` field on `ReadModel` plus the `Keiro.Connection` helpers), instead of+ implicitly inheriting the store connection's `search_path`. This is+ Haskell-level configuration only — no new database column and no new migration.++### Upgrade++- Added atomic Codd history import for the shared Kiroku/Keiro ledger. Both+ components' exact payload maps, manifests, and 23 mappings are validated in+ one adapter call; strict verification succeeds without replaying target SQL.+- Moved Codd expected-schema, remediation, and ledger-fixup behavior behind the+ manual `legacy-codd-tools` flag. The normal library, executable, and shared+ test fixture no longer depend on `codd`, `codd-extras`, `file-embed`, or+ `postgresql-simple` for migration execution.+- Added integrity gates for shipped migrations: `migrations.lock`,+ `keiro-migrate lock`, embed-parity checks, body linting, combined+ Kiroku+Keiro ledger timestamp uniqueness, a codd v5 ledger canary, and+ regression tests for both the ledger realignment fixup and the alpha+ remediation runbook.+- Hardened the apply path: unknown `keiro-migrate` arguments now exit 2 with+ usage, `up` is an explicit apply synonym, `KEIRO_MIGRATE_NO_CHECK=false`+ remains checked, schema drift under the checked path exits nonzero, embedded+ migrations force codd's single-try retry policy, and concurrent applies+ serialize with the shared Kiroku advisory lock.+- Added operator tooling: `keiro-migrate verify` strict-checks a live database+ against the expected-schema snapshot embedded in the binary,+ `keiro-migrate status` reports applied and pending combined-ledger entries,+ and `Keiro.Migrations.missingMigrations` lets applications fail fast at+ startup when Kiroku or Keiro framework migrations have not been applied.+- Added `docs/user/migration-ownership.md`, the canonical guide for+ framework-owned vs application-owned migrations, combined-ledger composition,+ application migration guards, runtime grants, and operator checks.+- A database first migrated by `0.1.0.0` has its `keiro_*` tables in `kiroku`. It+ requires a **one-time remediation** before running these migrations: follow+ [Upgrading To The Keiro Schema](../docs/user/upgrading-to-the-keiro-schema.md),+ which wraps the tested script+ `keiro-migrations/remediation/2026-07-05-relocate-keiro-tables-to-keiro-schema.sql`.+ The script relocates the tables (`ALTER TABLE ... SET SCHEMA keiro`) in one+ transaction and needs no codd-ledger change (migration filenames are unchanged,+ so codd re-runs nothing). Fresh and ephemeral databases need no remediation.++### Recommended Version Bump++- The next release is **`0.2.0.0`**. This is a breaking change; the package+ follows the Haskell PVP, where the leading `A.B` components form the "major"+ version and must increment on any breaking change, so `0.1` → `0.2` is the+ minimal PVP-correct major bump for a pre-1.0 package.++## 0.1.0.0 — 2026-07-05++Initial Hackage release.++### New Features++- Added embedded codd migrations and the `keiro-migrate` executable for Keiro+ schema installation and upgrades.+- Added framework schema for read models, snapshots, timers, outbox, inbox,+ subscriptions, projections, durable workflows, workflow children, awakeables,+ workflow instances, recovery indexes, and maintenance helpers.+- Added expected-schema drift checks and a local-development no-check migration+ runner.++### Bug Fixes++- Aligned with kiroku schema dependencies and added messaging crash-recovery+ schema updates.
+ README.md view
@@ -0,0 +1,100 @@+# Keiro database migrations++`keiro-migrations` exports a native `pg-migrate` component named `keiro`. The+component owns sixteen embedded SQL migrations and declares one dependency,+`kiroku`. Applications compose Kiroku first and Keiro second; Keiro never embeds+or copies Kiroku's SQL.++```haskell+import Keiro.Migrations (frameworkMigrationPlan, keiroMigrations)+import Kiroku.Store.Migrations qualified as Kiroku++plan = do+ kiroku <- Kiroku.kirokuMigrations+ keiro <- keiroMigrations+ frameworkMigrationPlan kiroku keiro+```++The `keiro-migrate` executable builds that plan and exposes the standard+`pg-migrate` commands. Set `DATABASE_URL` or pass the connection option shown by+the command help:++```bash+cabal run keiro-migrate -- plan+cabal run keiro-migrate -- status+cabal run keiro-migrate -- verify+cabal run keiro-migrate -- up+```++`status` and `verify` are read-only. `up` serializes concurrent callers with the+`pg-migrate` advisory lock, applies all Kiroku migrations before Keiro, and+reports already-applied migrations without replaying them.++## Authoring native migrations++The ordered manifest is `keiro-migrations/migrations/manifest`. Migration names+are stable component-local identifiers such as `0016-keiro-inbox-drop-received-idx`;+the timestamped files under `sql-migrations/` and `migrations.lock` remain+immutable legacy evidence for old Codd databases.++Create new work through the standard CLI and review the manifest append together+with the new SQL file:++```bash+cabal run keiro-migrate -- new \+ --manifest keiro-migrations/migrations/manifest \+ --description "add order summary"+cabal run keiro-migrate -- check keiro-migrations/migrations/manifest+```++Never edit a migration that has shipped. Add a new forward migration for every+schema correction.++## Importing the shared Codd ledger++`Keiro.Migrations.History.Codd` combines Kiroku's seven mappings with Keiro's+sixteen mappings. `frameworkCoddSourceConfig` selects both histories from the+shared `codd.sql_migrations` or legacy `codd_schema.sql_migrations` ledger,+checks the original SHA-256 manifests and payload bytes, and produces one atomic+history import:++```haskell+config <-+ either (fail . show) pure $+ frameworkCoddSourceConfig provider True reason Confirmed++result <-+ importCoddHistory+ defaultImportOptions+ config+ provider+ plan+ frameworkCoddHistoryMappings+```++Run the import while legacy migration writers are quiescent, then run strict+`verify`. A partial row, missing payload, changed manifest, or unexpected row in+strict mode fails before either target component is imported.++Databases first migrated by `keiro-migrations 0.1.0.0` may have `keiro_*`+tables under `kiroku`. Follow+[Upgrading To The Keiro Schema](../docs/user/upgrading-to-the-keiro-schema.md)+before importing their history.++## Legacy transition tools++Codd expected-schema snapshots, remediation drills, and sentinel-ledger fixup+tests remain available only through the manual `legacy-codd-tools` flag. They do+not enter the normal library, executable, or test-support dependency closure:++```bash+cabal test -flegacy-codd-tools \+ keiro-migrations:keiro-migrations-legacy-test+cabal run -flegacy-codd-tools keiro-write-expected-schema+```++The normal migration suite is:++```bash+cabal test keiro-migrations:keiro-migrations-test+```
+ app/Main.hs view
@@ -0,0 +1,48 @@+module Main (main) where++import Data.Aeson qualified as Aeson+import Data.ByteString.Lazy.Char8 qualified as LazyByteString+import Data.Text qualified as Text+import Data.Text.IO qualified as Text.IO+import Database.PostgreSQL.Migrate (defaultRunOptions)+import Database.PostgreSQL.Migrate.CLI+import Hasql.Connection.Settings qualified as Settings+import Keiro.Migrations (frameworkMigrationPlan, keiroMigrations)+import Kiroku.Store.Migrations qualified as Kiroku+import Options.Applicative+import System.Environment (lookupEnv)+import System.Exit qualified as Exit++main :: IO ()+main = do+ kiroku <- either (fail . show) pure Kiroku.kirokuMigrations+ keiro <- either (fail . show) pure keiroMigrations+ plan <- either (fail . show) pure (frameworkMigrationPlan kiroku keiro)+ command <-+ execParser+ ( info+ (migrationCommandParser plan <**> helper)+ (fullDesc <> progDesc "Manage the Kiroku and Keiro migration components")+ )+ defaultDatabaseUrl <- lookupEnv "DATABASE_URL"+ let defaultSettings =+ Settings.connectionString (Text.pack (maybe "" id defaultDatabaseUrl))+ environment = cliEnvironment defaultSettings plan defaultRunOptions+ outcome <- runMigrationCommand environment command+ case commandOutputFormat command of+ TextOutput -> Text.IO.putStrLn (renderMigrationCommandText outcome)+ JsonOutput -> LazyByteString.putStrLn (Aeson.encode (renderMigrationCommandJson outcome))+ Exit.exitWith+ (case exitClass outcome of ExitSuccess -> Exit.ExitSuccess; _ -> Exit.ExitFailure 1)++commandOutputFormat :: MigrationCommand -> OutputFormat+commandOutputFormat command =+ case command of+ Plan PlanOptions{output = OutputOptions format} -> format+ List ListOptions{output = OutputOptions format} -> format+ Check CheckOptions{output = OutputOptions format} -> format+ Status StatusOptions{output = OutputOptions format} -> format+ Verify VerifyOptions{output = OutputOptions format} -> format+ Up UpOptions{output = OutputOptions format} -> format+ Repair RepairOptions{output = OutputOptions format} -> format+ New NewOptions{output = OutputOptions format} -> format
+ app/WriteExpectedSchema.hs view
@@ -0,0 +1,13 @@+module Main (+ main,+)+where++import Codd.Extras.WriteSchema (writeExpectedSchemaMain)+import Data.Time (secondsToDiffTime)+import Keiro.Migrations.LegacyCodd (runAllKeiroMigrationsNoCheck)++main :: IO ()+main =+ writeExpectedSchemaMain "keiro" ["keiro"] "keiro-migrations/expected-schema" $ \settings ->+ runAllKeiroMigrationsNoCheck settings (secondsToDiffTime 5)
+ expected-schema/v18/db-settings view
@@ -0,0 +1,8 @@+{+ "collate": "c",+ "ctype": "c",+ "encoding": "utf8",+ "owner": "keiro",+ "public_privileges": "[[\"cT\", \"keiro\"]]",+ "settings": null+}
+ expected-schema/v18/roles/keiro view
@@ -0,0 +1,12 @@+{+ "bypassrls": true,+ "canlogin": true,+ "config": null,+ "createdb": true,+ "createrole": true,+ "db_privileges": "[[\"cCT\", \"keiro\"]]",+ "inherit": true,+ "membership": [],+ "replication": true,+ "superuser": true+}
+ expected-schema/v18/schemas/keiro/objrep view
@@ -0,0 +1,11 @@+{+ "owner": "keiro",+ "privileges": {+ "keiro": [+ [+ "CU",+ "keiro"+ ]+ ]+ }+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/awakeable_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/completed_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/created_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/owner_workflow_id view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/owner_workflow_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/payload view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "jsonb"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/status view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": "'pending'::text",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/updated_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_awakeable_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL awakeable_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_created_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL created_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_owner_workflow_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL owner_workflow_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_owner_workflow_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL owner_workflow_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (awakeable_id)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_awakeables_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_status_chk view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "CHECK (status = ANY (ARRAY['pending'::text, 'completed'::text, 'cancelled'::text]))",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "c",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_status_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL status",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_updated_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL updated_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_owner_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_awakeables_owner_idx ON keiro.keiro_awakeables USING btree (owner_workflow_name, owner_workflow_id)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_pending_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_awakeables_pending_idx ON keiro.keiro_awakeables USING btree (status) WHERE (status = 'pending'::text)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_awakeables_pkey ON keiro.keiro_awakeables USING btree (awakeable_id)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/objrep view
@@ -0,0 +1,32 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "awakeable_id",+ "owner_workflow_name",+ "owner_workflow_id",+ "status",+ "payload",+ "created_at",+ "updated_at",+ "completed_at"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_awakeables",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/attempt_count view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "0",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/attributes view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "jsonb"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/causation_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/completed_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/content_type view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/correlation_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/dedupe_key view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/destination view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/event_type view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/failed_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_offset view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_partition view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_topic view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/last_error view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/message_id view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/occurred_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/payload_bytes view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bytea"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/received_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_fingerprint view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_registry view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_subject view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_version view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_version_ref view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source_event_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source_global_position view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/status view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": "'processing'::text",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/traceparent view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/tracestate view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_attempt_count_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL attempt_count",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_content_type_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL content_type",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_dedupe_key_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL dedupe_key",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_payload_bytes_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL payload_bytes",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (source, dedupe_key)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_inbox_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_received_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL received_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_source_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL source",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_status_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL status",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_backlog_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_inbox_backlog_idx ON keiro.keiro_inbox USING btree (status) WHERE (status = ANY (ARRAY['processing'::text, 'failed'::text]))",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_completed_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_inbox_completed_idx ON keiro.keiro_inbox USING btree (completed_at) WHERE (status = 'completed'::text)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_inbox_pkey ON keiro.keiro_inbox USING btree (source, dedupe_key)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/objrep view
@@ -0,0 +1,54 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "source",+ "dedupe_key",+ "message_id",+ "source_event_id",+ "source_global_position",+ "destination",+ "event_type",+ "schema_version",+ "content_type",+ "schema_registry",+ "schema_subject",+ "schema_version_ref",+ "schema_id",+ "schema_fingerprint",+ "causation_id",+ "correlation_id",+ "traceparent",+ "tracestate",+ "kafka_topic",+ "kafka_partition",+ "kafka_offset",+ "payload_bytes",+ "attributes",+ "occurred_at",+ "status",+ "received_at",+ "completed_at",+ "failed_at",+ "last_error",+ "attempt_count"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_inbox",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/attempt_count view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "0",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/attributes view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "jsonb"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/causation_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/content_type view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/correlation_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/created_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/destination view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/event_type view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/last_error view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/message_id view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/message_key view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/next_attempt_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/occurred_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/outbox_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/payload_bytes view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bytea"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/published_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_fingerprint view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_registry view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_subject view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_version view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_version_ref view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source_event_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source_global_position view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/status view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": "'pending'::text",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/traceparent view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/tracestate view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/updated_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_attempt_count_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL attempt_count",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_content_type_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL content_type",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_created_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL created_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_destination_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL destination",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_event_type_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL event_type",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_message_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL message_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_next_attempt_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL next_attempt_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_occurred_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL occurred_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_outbox_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL outbox_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_payload_bytes_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL payload_bytes",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (outbox_id)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_outbox_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_schema_version_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL schema_version",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_source_message_id_key view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "UNIQUE (source, message_id)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_outbox_source_message_id_key",+ "type": "u",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_source_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL source",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_status_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL status",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_updated_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL updated_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_claim_order_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_outbox_claim_order_idx ON keiro.keiro_outbox USING btree (created_at, outbox_id) WHERE (status = ANY (ARRAY['pending'::text, 'failed'::text]))",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_head_of_line_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_outbox_head_of_line_idx ON keiro.keiro_outbox USING btree (source, message_key, created_at) WHERE ((status <> ALL (ARRAY['sent'::text, 'dead'::text])) AND (message_key IS NOT NULL))",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_pending_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_outbox_pending_idx ON keiro.keiro_outbox USING btree (status, next_attempt_at, created_at)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_outbox_pkey ON keiro.keiro_outbox USING btree (outbox_id)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_sent_gc_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_outbox_sent_gc_idx ON keiro.keiro_outbox USING btree (published_at) WHERE (status = 'sent'::text)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_source_message_id_key view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_outbox_source_message_id_key ON keiro.keiro_outbox USING btree (source, message_id)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_source_order_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_outbox_source_order_idx ON keiro.keiro_outbox USING btree (source, created_at, outbox_id) WHERE (status <> ALL (ARRAY['sent'::text, 'dead'::text]))",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/objrep view
@@ -0,0 +1,53 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "outbox_id",+ "message_id",+ "source",+ "destination",+ "message_key",+ "event_type",+ "schema_version",+ "content_type",+ "schema_registry",+ "schema_subject",+ "schema_version_ref",+ "schema_id",+ "schema_fingerprint",+ "source_event_id",+ "source_global_position",+ "causation_id",+ "correlation_id",+ "traceparent",+ "tracestate",+ "payload_bytes",+ "attributes",+ "occurred_at",+ "status",+ "attempt_count",+ "next_attempt_at",+ "last_error",+ "published_at",+ "created_at",+ "updated_at"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_outbox",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/applied_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/event_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/projection_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_applied_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL applied_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_event_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL event_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (projection_name, event_id)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_projection_dedup_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_projection_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL projection_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/indexes/keiro_projection_dedup_applied_at_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_projection_dedup_applied_at_idx ON keiro.keiro_projection_dedup USING btree (applied_at)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/indexes/keiro_projection_dedup_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_projection_dedup_pkey ON keiro.keiro_projection_dedup USING btree (projection_name, event_id)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/objrep view
@@ -0,0 +1,27 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "projection_name",+ "event_id",+ "applied_at"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_projection_dedup",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/last_built_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/shape_hash view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/status view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/updated_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/version view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (name)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_read_models_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_shape_hash_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL shape_hash",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_status_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL status",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_updated_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL updated_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_version_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL version",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/indexes/keiro_read_models_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_read_models_pkey ON keiro.keiro_read_models USING btree (name)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/objrep view
@@ -0,0 +1,30 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "name",+ "version",+ "shape_hash",+ "last_built_at",+ "status",+ "updated_at"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_read_models",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/created_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/regfile_shape_hash view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/state view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "jsonb"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/state_codec_version view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/stream_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/stream_version view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/updated_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_created_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL created_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (stream_id)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_snapshots_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_regfile_shape_hash_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL regfile_shape_hash",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_state_codec_version_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL state_codec_version",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_state_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL state",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_stream_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL stream_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_stream_version_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL stream_version",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_updated_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL updated_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/indexes/keiro_snapshots_compat_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_snapshots_compat_idx ON keiro.keiro_snapshots USING btree (stream_id, state_codec_version, regfile_shape_hash, stream_version DESC)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/indexes/keiro_snapshots_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_snapshots_pkey ON keiro.keiro_snapshots USING btree (stream_id)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/objrep view
@@ -0,0 +1,31 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "stream_id",+ "stream_version",+ "state",+ "state_codec_version",+ "regfile_shape_hash",+ "created_at",+ "updated_at"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_snapshots",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/bucket view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "integer"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/heartbeat_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/lease_expires_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/owner_worker_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/shard_count view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "integer"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/subscription_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/updated_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_bucket_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL bucket",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_bucket_range_chk view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "CHECK (bucket >= 0 AND bucket < shard_count)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "c",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_count_chk view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "CHECK (shard_count >= 1)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "c",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (subscription_name, bucket)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_subscription_shards_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_shard_count_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL shard_count",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_subscription_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL subscription_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_updated_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL updated_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_lease_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_subscription_shards_lease_idx ON keiro.keiro_subscription_shards USING btree (subscription_name, lease_expires_at)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_owner_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_subscription_shards_owner_idx ON keiro.keiro_subscription_shards USING btree (subscription_name, owner_worker_id)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_subscription_shards_pkey ON keiro.keiro_subscription_shards USING btree (subscription_name, bucket)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/objrep view
@@ -0,0 +1,31 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "subscription_name",+ "bucket",+ "shard_count",+ "owner_worker_id",+ "lease_expires_at",+ "heartbeat_at",+ "updated_at"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_subscription_shards",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/attempts view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "0",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "bigint"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/correlation_id view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/created_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/fire_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/fired_event_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/last_error view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/payload view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "jsonb"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/process_manager_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/status view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": "'scheduled'::text",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/timer_id view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "uuid"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/updated_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_attempts_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL attempts",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_correlation_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL correlation_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_created_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL created_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_fire_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL fire_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_payload_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL payload",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (timer_id)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_timers_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_process_manager_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL process_manager_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_status_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL status",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_timer_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL timer_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_updated_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL updated_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/indexes/keiro_timers_due_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_timers_due_idx ON keiro.keiro_timers USING btree (status, fire_at, process_manager_name) WHERE (status = ANY (ARRAY['scheduled'::text, 'firing'::text]))",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/indexes/keiro_timers_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_timers_pkey ON keiro.keiro_timers USING btree (timer_id)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_timers/objrep view
@@ -0,0 +1,35 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "timer_id",+ "process_manager_name",+ "correlation_id",+ "fire_at",+ "payload",+ "status",+ "attempts",+ "fired_event_id",+ "created_at",+ "updated_at",+ "last_error"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_timers",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/await_step view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/child_id view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/child_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/completed_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/created_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/parent_id view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/parent_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/result view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "jsonb"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/status view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": "'running'::text",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/updated_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_await_step_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL await_step",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_child_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL child_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_child_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL child_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_created_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL created_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_parent_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL parent_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_parent_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL parent_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (child_id, child_name)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_workflow_children_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_status_chk view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "CHECK (status = ANY (ARRAY['running'::text, 'completed'::text, 'cancelled'::text, 'failed'::text]))",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "c",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_status_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL status",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_updated_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL updated_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_parent_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_workflow_children_parent_idx ON keiro.keiro_workflow_children USING btree (parent_id, parent_name)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_workflow_children_pkey ON keiro.keiro_workflow_children USING btree (child_id, child_name)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_running_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_workflow_children_running_idx ON keiro.keiro_workflow_children USING btree (status) WHERE (status = 'running'::text)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/objrep view
@@ -0,0 +1,34 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "child_id",+ "child_name",+ "parent_id",+ "parent_name",+ "await_step",+ "status",+ "result",+ "created_at",+ "updated_at",+ "completed_at"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_workflow_children",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/generation view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "0",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "integer"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/recorded_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/result view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "jsonb"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/step_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/workflow_id view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/workflow_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_generation_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL generation",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (workflow_id, workflow_name, generation, step_name)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_workflow_steps_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_recorded_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL recorded_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_result_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL result",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_step_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL step_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_workflow_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL workflow_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_workflow_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL workflow_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/indexes/keiro_workflow_steps_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_workflow_steps_pkey ON keiro.keiro_workflow_steps USING btree (workflow_id, workflow_name, generation, step_name)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/indexes/keiro_workflow_steps_workflow_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_workflow_steps_workflow_idx ON keiro.keiro_workflow_steps USING btree (workflow_id, workflow_name, generation)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/objrep view
@@ -0,0 +1,30 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "workflow_id",+ "workflow_name",+ "step_name",+ "result",+ "recorded_at",+ "generation"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_workflow_steps",+ "shared": false+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/attempts view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "0",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "integer"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/completed_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/created_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/generation view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "0",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "integer"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/last_error view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/lease_expires_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/leased_by view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/next_attempt_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/status view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": "'running'::text",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/updated_at view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": "now()",+ "generated": "",+ "hasdefault": true,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/wake_after view
@@ -0,0 +1,13 @@+{+ "collation": null,+ "collation_nsp": null,+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": false,+ "privileges": null,+ "type": "timestamp with time zone"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/workflow_id view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/workflow_name view
@@ -0,0 +1,13 @@+{+ "collation": "default",+ "collation_nsp": "pg_catalog",+ "default": null,+ "generated": "",+ "hasdefault": false,+ "identity": "",+ "inhcount": 0,+ "local": true,+ "notnull": true,+ "privileges": null,+ "type": "text"+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_attempts_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL attempts",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_created_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL created_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_generation_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL generation",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_pkey view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "PRIMARY KEY (workflow_id, workflow_name)",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": true,+ "parent_constraint": null,+ "supporting_index": "keiro_workflows_pkey",+ "type": "p",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_status_chk view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "CHECK (status = ANY (ARRAY['running'::text, 'suspended'::text, 'completed'::text, 'cancelled'::text, 'failed'::text]))",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "c",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_status_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL status",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_updated_at_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL updated_at",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_workflow_id_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL workflow_id",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_workflow_name_not_null view
@@ -0,0 +1,16 @@+{+ "deferrable": false,+ "deferred": false,+ "definition": "NOT NULL workflow_name",+ "fk_deltype": " ",+ "fk_matchtype": " ",+ "fk_ref_table": null,+ "fk_updtype": " ",+ "inhcount": 0,+ "local": true,+ "noinherit": false,+ "parent_constraint": null,+ "supporting_index": null,+ "type": "n",+ "validated": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_active_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_workflows_active_idx ON keiro.keiro_workflows USING btree (status) WHERE (status = ANY (ARRAY['running'::text, 'suspended'::text]))",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_gc_idx view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE INDEX keiro_workflows_gc_idx ON keiro.keiro_workflows USING btree (status, completed_at)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": false,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": false,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_pkey view
@@ -0,0 +1,21 @@+{+ "accessmethod": "btree",+ "amoptions": null,+ "compositetype": null,+ "definition": "CREATE UNIQUE INDEX keiro_workflows_pkey ON keiro.keiro_workflows USING btree (workflow_id, workflow_name)",+ "exclusion": false,+ "forcerowsecurity": false,+ "immediate": true,+ "kind": "i",+ "nullsnotdistinct": false,+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "primary": true,+ "replident": "n",+ "rowsecurity": false,+ "rowtype": null,+ "shared": false,+ "unique": true,+ "valid": true+}
+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/objrep view
@@ -0,0 +1,37 @@+{+ "accessmethod": "heap",+ "amoptions": null,+ "columns_in_order": [+ "workflow_id",+ "workflow_name",+ "generation",+ "status",+ "attempts",+ "last_error",+ "next_attempt_at",+ "leased_by",+ "lease_expires_at",+ "created_at",+ "updated_at",+ "completed_at",+ "wake_after"+ ],+ "compositetype": null,+ "forcerowsecurity": false,+ "kind": "r",+ "owner": "keiro",+ "partition": false,+ "persistence": "p",+ "privileges": {+ "keiro": [+ [+ "damxrtDw",+ "keiro"+ ]+ ]+ },+ "replident": "d",+ "rowsecurity": false,+ "rowtype": "keiro_workflows",+ "shared": false+}
+ keiro-migrations.cabal view
@@ -0,0 +1,439 @@+cabal-version: 3.0+name: keiro-migrations+version: 0.2.0.0+synopsis: Schema migrations for keiro+description:+ Embedded PostgreSQL schema migrations and a migration runner for the Keiro+ event-sourcing framework.++license: BSD-3-Clause+author: Nadeem Bitar+maintainer: nadeem@gmail.com+copyright: 2026 Nadeem Bitar+category: Database+build-type: Simple+tested-with: GHC >=9.12 && <9.13+extra-doc-files:+ CHANGELOG.md+ README.md++extra-source-files:+ expected-schema/v18/db-settings+ expected-schema/v18/roles/keiro+ expected-schema/v18/schemas/keiro/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/awakeable_id+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/completed_at+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/created_at+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/owner_workflow_id+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/owner_workflow_name+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/payload+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/status+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/cols/updated_at+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_awakeable_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_created_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_owner_workflow_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_owner_workflow_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_status_chk+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_status_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/constraints/keiro_awakeables_updated_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_owner_idx+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_pending_idx+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/indexes/keiro_awakeables_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_awakeables/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/attempt_count+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/attributes+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/causation_id+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/completed_at+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/content_type+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/correlation_id+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/dedupe_key+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/destination+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/event_type+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/failed_at+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_offset+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_partition+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/kafka_topic+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/last_error+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/message_id+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/occurred_at+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/payload_bytes+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/received_at+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_fingerprint+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_id+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_registry+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_subject+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_version+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/schema_version_ref+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source_event_id+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/source_global_position+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/status+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/traceparent+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/cols/tracestate+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_attempt_count_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_content_type_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_dedupe_key_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_payload_bytes_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_received_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_source_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/constraints/keiro_inbox_status_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_backlog_idx+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_completed_idx+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/indexes/keiro_inbox_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_inbox/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/attempt_count+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/attributes+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/causation_id+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/content_type+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/correlation_id+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/created_at+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/destination+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/event_type+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/last_error+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/message_id+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/message_key+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/next_attempt_at+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/occurred_at+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/outbox_id+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/payload_bytes+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/published_at+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_fingerprint+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_id+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_registry+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_subject+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_version+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/schema_version_ref+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source_event_id+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/source_global_position+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/status+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/traceparent+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/tracestate+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/cols/updated_at+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_attempt_count_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_content_type_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_created_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_destination_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_event_type_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_message_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_next_attempt_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_occurred_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_outbox_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_payload_bytes_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_schema_version_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_source_message_id_key+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_source_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_status_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/constraints/keiro_outbox_updated_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_claim_order_idx+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_head_of_line_idx+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_pending_idx+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_sent_gc_idx+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_source_message_id_key+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/indexes/keiro_outbox_source_order_idx+ expected-schema/v18/schemas/keiro/tables/keiro_outbox/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/applied_at+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/event_id+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/cols/projection_name+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_applied_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_event_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/constraints/keiro_projection_dedup_projection_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/indexes/keiro_projection_dedup_applied_at_idx+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/indexes/keiro_projection_dedup_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_projection_dedup/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/last_built_at+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/name+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/shape_hash+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/status+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/updated_at+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/cols/version+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_shape_hash_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_status_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_updated_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/constraints/keiro_read_models_version_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/indexes/keiro_read_models_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_read_models/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/created_at+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/regfile_shape_hash+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/state+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/state_codec_version+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/stream_id+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/stream_version+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/cols/updated_at+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_created_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_regfile_shape_hash_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_state_codec_version_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_state_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_stream_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_stream_version_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/constraints/keiro_snapshots_updated_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/indexes/keiro_snapshots_compat_idx+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/indexes/keiro_snapshots_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_snapshots/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/bucket+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/heartbeat_at+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/lease_expires_at+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/owner_worker_id+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/shard_count+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/subscription_name+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/cols/updated_at+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_bucket_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_bucket_range_chk+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_count_chk+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_shard_count_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_subscription_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/constraints/keiro_subscription_shards_updated_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_lease_idx+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_owner_idx+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/indexes/keiro_subscription_shards_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_subscription_shards/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/attempts+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/correlation_id+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/created_at+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/fire_at+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/fired_event_id+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/last_error+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/payload+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/process_manager_name+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/status+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/timer_id+ expected-schema/v18/schemas/keiro/tables/keiro_timers/cols/updated_at+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_attempts_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_correlation_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_created_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_fire_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_payload_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_process_manager_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_status_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_timer_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/constraints/keiro_timers_updated_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_timers/indexes/keiro_timers_due_idx+ expected-schema/v18/schemas/keiro/tables/keiro_timers/indexes/keiro_timers_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_timers/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/await_step+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/child_id+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/child_name+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/completed_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/created_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/parent_id+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/parent_name+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/result+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/status+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/cols/updated_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_await_step_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_child_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_child_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_created_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_parent_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_parent_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_status_chk+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_status_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/constraints/keiro_workflow_children_updated_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_parent_idx+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/indexes/keiro_workflow_children_running_idx+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_children/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/generation+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/recorded_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/result+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/step_name+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/workflow_id+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/cols/workflow_name+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_generation_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_recorded_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_result_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_step_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_workflow_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/constraints/keiro_workflow_steps_workflow_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/indexes/keiro_workflow_steps_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/indexes/keiro_workflow_steps_workflow_idx+ expected-schema/v18/schemas/keiro/tables/keiro_workflow_steps/objrep+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/attempts+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/completed_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/created_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/generation+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/last_error+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/lease_expires_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/leased_by+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/next_attempt_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/status+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/updated_at+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/wake_after+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/workflow_id+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/cols/workflow_name+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_attempts_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_created_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_generation_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_status_chk+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_status_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_updated_at_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_workflow_id_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/constraints/keiro_workflows_workflow_name_not_null+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_active_idx+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_gc_idx+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/indexes/keiro_workflows_pkey+ expected-schema/v18/schemas/keiro/tables/keiro_workflows/objrep+ migrations/*.sql+ migrations/manifest+ migrations.lock+ sql-migrations/*.sql++source-repository head+ type: git+ location: https://github.com/shinzui/keiro.git++flag legacy-codd-tools+ description:+ Build transitional Codd expected-schema, remediation, and ledger-fixup+ targets. The normal pg-migrate closure excludes these dependencies.++ default: False+ manual: True++common common+ default-language: GHC2024+ default-extensions:+ DeriveAnyClass+ DuplicateRecordFields+ MultilineStrings+ OverloadedLabels+ OverloadedStrings++library+ import: common+ exposed-modules:+ Keiro.Migrations+ Keiro.Migrations.History.Codd++ other-modules:+ Keiro.Migrations.Internal.Definition+ Keiro.Migrations.Internal.EmbedFile++ hs-source-dirs: src+ build-depends:+ , base >=4.18 && <5+ , bytestring >=0.11 && <0.13+ , containers >=0.6 && <0.8+ , kiroku-store-migrations ^>=0.2.0.0+ , pg-migrate ^>=1.0.0.0+ , pg-migrate-embed ^>=1.0.0.0+ , pg-migrate-import-codd ^>=1.0.0.0+ , template-haskell >=2.20 && <2.24+ , text >=2.0 && <2.2++ if flag(legacy-codd-tools)+ exposed-modules:+ Keiro.Migrations.ExpectedSchema+ Keiro.Migrations.LegacyCodd+ Keiro.Migrations.New++ build-depends:+ , codd >=0.1.8 && <0.2+ , codd-extras >=0.1 && <0.2+ , directory >=1.3+ , file-embed >=0.0.15 && <0.0.17+ , filepath >=1.4 && <1.6+ , time >=1.12 && <1.15++executable keiro-migrate+ import: common+ main-is: Main.hs+ hs-source-dirs: app+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ , aeson >=2.1 && <2.3+ , base >=4.18 && <5+ , bytestring >=0.11 && <0.13+ , hasql >=1.10 && <1.11+ , keiro-migrations+ , kiroku-store-migrations ^>=0.2.0.0+ , optparse-applicative >=0.17 && <0.20+ , pg-migrate ^>=1.0.0.0+ , pg-migrate-cli ^>=1.0.0.0+ , text >=2.0 && <2.2++executable keiro-write-expected-schema+ import: common+ main-is: WriteExpectedSchema.hs+ hs-source-dirs: app+ ghc-options: -threaded -rtsopts -with-rtsopts=-N++ if !flag(legacy-codd-tools)+ buildable: False++ build-depends:+ , base+ , codd-extras:ephemeral >=0.1 && <0.2+ , keiro-migrations+ , time++test-suite keiro-migrations-test+ import: common+ type: exitcode-stdio-1.0+ main-is: Main.hs+ hs-source-dirs: test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ , async+ , base >=4.18 && <5+ , bytestring >=0.11 && <0.13+ , containers >=0.6 && <0.8+ , directory >=1.3+ , ephemeral-pg >=0.2 && <0.3+ , filepath >=1.4 && <1.6+ , hasql >=1.10 && <1.11+ , hspec >=2.10 && <2.12+ , keiro-migrations+ , kiroku-store-migrations ^>=0.2.0.0+ , pg-migrate ^>=1.0.0.0+ , pg-migrate-import-codd ^>=1.0.0.0+ , pg-migrate-test-support ^>=1.0.0.0+ , text >=2.0 && <2.2++test-suite keiro-migrations-legacy-test+ import: common+ type: exitcode-stdio-1.0+ main-is: Main.hs+ hs-source-dirs: test-legacy+ ghc-options: -threaded -rtsopts -with-rtsopts=-N++ if !flag(legacy-codd-tools)+ buildable: False++ build-depends:+ , aeson+ , async+ , attoparsec+ , base >=4.18 && <5+ , codd+ , codd-extras+ , containers+ , contravariant-extras+ , directory+ , ephemeral-pg >=0.2+ , filepath+ , generic-lens >=2.2+ , hasql >=1.10+ , hasql-pool >=1.2+ , hspec >=2.10+ , keiro-migrations+ , kiroku-store >=0.3 && <0.4+ , kiroku-store-migrations ^>=0.2.0.0+ , lens >=5.2+ , temporary+ , text >=2.0+ , time >=1.12+ , vector >=0.13
+ migrations.lock view
@@ -0,0 +1,16 @@+1d15faa7cfb474455c3a1193b454ce493d49589b0f9f62b0b8beff65a00f6403 2026-05-17-13-58-15-keiro-bootstrap.sql+4c9c645e7ac9ebc9228638a89580613bd0058444e20047486d4bd7696b9ddb0a 2026-05-19-12-55-02-keiro-outbox.sql+71aabbfd93e66b324691ca856ca73245d62d84d984ca162e1388726127daa5e5 2026-05-19-13-05-23-keiro-inbox.sql+42f1bbd4fb23b27b2be434f25b559b2e17870f1d8c6efbcf2ae6a702c6136f98 2026-06-03-05-14-28-keiro-timer-recovery.sql+e967d41342cddc8cfe8381e5f562603dbc9a10e61232458e24c5cb291cfe9047 2026-06-03-16-10-05-keiro-workflow-steps.sql+3b20ba3981ae718cfbb9ed68318131a50ca5ad715b459868b79ac1f4c138fc5c 2026-06-03-18-19-41-keiro-awakeables.sql+975c0e6480fa01f2af1e2c45a4396e2588af4560c9803b55e8b574ea2e69b5b2 2026-06-03-19-49-23-keiro-workflow-children.sql+f05e8254de4c328f9319db4db8b9a78d6fba552c245acf0e24c6c450d8d71559 2026-06-04-02-12-28-keiro-workflow-generation.sql+1a93b4fdad24624b168a0aeeb12c659c59764660cc11fa564e77aa4b32a54fca 2026-06-04-03-53-34-keiro-subscription-shards.sql+49a963745a637c8e0248b5b958a719ccc772dbd02ca77cf706fee5de8d8d1a85 2026-06-15-13-22-31-keiro-messaging-crash-recovery.sql+7c329c9f439d2bab927debf5dc8b96acb438b4e240ef16292723398ddf005fea 2026-06-15-15-07-25-keiro-workflows-instances.sql+77c394334c64ff0631eb1c831f60629123ae255f1be7fb1716748b6ff9d0b701 2026-06-15-17-53-48-keiro-workflow-gc-index.sql+a2ea08ce3debec078e89490403241d9fd4e5d4ff3ea64b2c01ab236fb2dda313 2026-06-15-18-01-33-keiro-workflows-wake-after.sql+ed5bef75d195df0335b86d36256fd4f1dab30cb1eab4e05f0a321bf8d989503a 2026-06-15-21-49-37-keiro-projection-dedup.sql+fd65320576b06e8d30a8308ac790be463c09906e74d81a6fd535e7745ef943c5 2026-07-02-00-15-48-keiro-outbox-claim-order-index.sql+50b169c9bc98e7ab6845c74b105d13990af3cdb2e587445fd869e942c28df81d 2026-07-02-00-58-54-keiro-inbox-drop-received-idx.sql
+ migrations/0001-keiro-bootstrap.sql view
@@ -0,0 +1,44 @@+-- Keiro framework bootstrap migration (codd).+--+-- Keiro owns the dedicated `keiro` schema. codd applies this file in its own+-- session, so the schema is created here and every object is written fully+-- qualified as keiro.<name> — no session search-path pin is used anywhere.+CREATE SCHEMA IF NOT EXISTS keiro;++CREATE TABLE IF NOT EXISTS keiro.keiro_snapshots (+ stream_id BIGINT PRIMARY KEY,+ stream_version BIGINT NOT NULL,+ state JSONB NOT NULL,+ state_codec_version BIGINT NOT NULL,+ regfile_shape_hash TEXT NOT NULL,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()+);++CREATE INDEX IF NOT EXISTS keiro_snapshots_compat_idx+ ON keiro.keiro_snapshots (stream_id, state_codec_version, regfile_shape_hash, stream_version DESC);++CREATE TABLE IF NOT EXISTS keiro.keiro_read_models (+ name TEXT PRIMARY KEY,+ version BIGINT NOT NULL,+ shape_hash TEXT NOT NULL,+ last_built_at TIMESTAMPTZ,+ status TEXT NOT NULL,+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()+);++CREATE TABLE IF NOT EXISTS keiro.keiro_timers (+ timer_id UUID PRIMARY KEY,+ process_manager_name TEXT NOT NULL,+ correlation_id TEXT NOT NULL,+ fire_at TIMESTAMPTZ NOT NULL,+ payload JSONB NOT NULL,+ status TEXT NOT NULL DEFAULT 'scheduled',+ attempts BIGINT NOT NULL DEFAULT 0,+ fired_event_id UUID,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()+);++CREATE INDEX IF NOT EXISTS keiro_timers_due_idx+ ON keiro.keiro_timers (status, fire_at, process_manager_name);
+ migrations/0002-keiro-outbox.sql view
@@ -0,0 +1,39 @@+CREATE TABLE IF NOT EXISTS keiro.keiro_outbox (+ outbox_id UUID PRIMARY KEY,+ message_id TEXT NOT NULL,+ source TEXT NOT NULL,+ destination TEXT NOT NULL,+ message_key TEXT,+ event_type TEXT NOT NULL,+ schema_version BIGINT NOT NULL,+ content_type TEXT NOT NULL,+ schema_registry TEXT,+ schema_subject TEXT,+ schema_version_ref BIGINT,+ schema_id BIGINT,+ schema_fingerprint TEXT,+ source_event_id UUID,+ source_global_position BIGINT,+ causation_id UUID,+ correlation_id UUID,+ traceparent TEXT,+ tracestate TEXT,+ payload_bytes BYTEA NOT NULL,+ attributes JSONB,+ occurred_at TIMESTAMPTZ NOT NULL,+ status TEXT NOT NULL DEFAULT 'pending',+ attempt_count BIGINT NOT NULL DEFAULT 0,+ next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ last_error TEXT,+ published_at TIMESTAMPTZ,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ UNIQUE (source, message_id)+);++CREATE INDEX IF NOT EXISTS keiro_outbox_pending_idx+ ON keiro.keiro_outbox (status, next_attempt_at, created_at);++CREATE INDEX IF NOT EXISTS keiro_outbox_head_of_line_idx+ ON keiro.keiro_outbox (source, message_key, created_at)+ WHERE status NOT IN ('sent', 'dead') AND message_key IS NOT NULL;
+ migrations/0003-keiro-inbox.sql view
@@ -0,0 +1,39 @@+CREATE TABLE IF NOT EXISTS keiro.keiro_inbox (+ source TEXT NOT NULL,+ dedupe_key TEXT NOT NULL,+ message_id TEXT,+ source_event_id UUID,+ source_global_position BIGINT,+ destination TEXT,+ event_type TEXT,+ schema_version BIGINT,+ content_type TEXT NOT NULL,+ schema_registry TEXT,+ schema_subject TEXT,+ schema_version_ref BIGINT,+ schema_id BIGINT,+ schema_fingerprint TEXT,+ causation_id UUID,+ correlation_id UUID,+ traceparent TEXT,+ tracestate TEXT,+ kafka_topic TEXT,+ kafka_partition BIGINT,+ kafka_offset BIGINT,+ payload_bytes BYTEA NOT NULL,+ attributes JSONB,+ occurred_at TIMESTAMPTZ,+ status TEXT NOT NULL DEFAULT 'processing',+ received_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ completed_at TIMESTAMPTZ,+ failed_at TIMESTAMPTZ,+ last_error TEXT,+ PRIMARY KEY (source, dedupe_key)+);++CREATE INDEX IF NOT EXISTS keiro_inbox_received_idx+ ON keiro.keiro_inbox (received_at);++CREATE INDEX IF NOT EXISTS keiro_inbox_completed_idx+ ON keiro.keiro_inbox (completed_at)+ WHERE status = 'completed';
+ migrations/0004-keiro-timer-recovery.sql view
@@ -0,0 +1,8 @@+ALTER TABLE keiro.keiro_timers+ ADD COLUMN IF NOT EXISTS last_error TEXT;++DROP INDEX IF EXISTS keiro.keiro_timers_due_idx;++CREATE INDEX IF NOT EXISTS keiro_timers_due_idx+ ON keiro.keiro_timers (status, fire_at, process_manager_name)+ WHERE status IN ('scheduled', 'firing');
+ migrations/0005-keiro-workflow-steps.sql view
@@ -0,0 +1,21 @@+-- The fast-lookup index of journaled workflow steps. The journal stream+-- (wf:<name>-<id>) is the source of truth for replay; this table is a derived+-- view kept in sync inside the same transaction as each journal append. It+-- lets the runtime hot path and the EP-42 resume worker look up a step (or+-- discover unfinished workflows) without rescanning the journal stream.+--+-- The reserved step name '__workflow_completed__' is written when a workflow+-- finishes (see Keiro.Workflow.Types.completedStepName); its absence is how+-- findUnfinishedWorkflowIds distinguishes an in-flight workflow from a+-- completed one.+CREATE TABLE IF NOT EXISTS keiro.keiro_workflow_steps (+ workflow_id text NOT NULL,+ workflow_name text NOT NULL,+ step_name text NOT NULL,+ result jsonb NOT NULL,+ recorded_at timestamptz NOT NULL DEFAULT now(),+ PRIMARY KEY (workflow_id, step_name)+);++CREATE INDEX IF NOT EXISTS keiro_workflow_steps_workflow_idx+ ON keiro.keiro_workflow_steps (workflow_id);
+ migrations/0006-keiro-awakeables.sql view
@@ -0,0 +1,33 @@+-- The keiro_awakeables table: durable promises an external system resolves.+--+-- A workflow's `awakeable` allocates a deterministic id, inserts a 'pending'+-- row here, and suspends; an external caller later runs `signalAwakeable`,+-- which flips the row to 'completed' (storing the payload) and appends a+-- StepRecorded "awk:<uuid>" to the owning workflow's journal so the next+-- runWorkflow takes the awaitStep hit path. `cancelAwakeable` flips a still+-- 'pending' row to 'cancelled'; a subsequent run then throws.+--+-- The journal stream (wf:<name>-<id>) remains the source of truth for replay;+-- this table is the external-completion handshake plus operator-visible state+-- (a stuck 'pending' row is a workflow waiting on a callback that never came).+CREATE TABLE IF NOT EXISTS keiro.keiro_awakeables (+ awakeable_id UUID PRIMARY KEY,+ owner_workflow_name TEXT NOT NULL,+ owner_workflow_id TEXT NOT NULL,+ status TEXT NOT NULL DEFAULT 'pending',+ payload JSONB,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ completed_at TIMESTAMPTZ,+ CONSTRAINT keiro_awakeables_status_chk+ CHECK (status IN ('pending', 'completed', 'cancelled'))+);++-- Gauge support (EP-44 keiro.workflow.awakeables.pending) and operator triage.+CREATE INDEX IF NOT EXISTS keiro_awakeables_pending_idx+ ON keiro.keiro_awakeables (status)+ WHERE status = 'pending';++-- Find all awakeables owned by one workflow instance (operator repair, EP-42/EP-43).+CREATE INDEX IF NOT EXISTS keiro_awakeables_owner_idx+ ON keiro.keiro_awakeables (owner_workflow_name, owner_workflow_id);
+ migrations/0007-keiro-workflow-children.sql view
@@ -0,0 +1,39 @@+-- The keiro_workflow_children table: durable parent->child workflow links.+--+-- A parent workflow's `spawnChild` records the child in the parent's journal+-- as a StepRecorded "child:<childId>" (so a replay short-circuits the spawn)+-- and inserts a 'running' row here linking the child's (id, name) back to the+-- parent's (id, name) plus the parent-journal step the parent awaits+-- ("child:<childId>:result"). When the child completes, `childCompletionHook`+-- flips the row to 'completed' (storing the child's result) and appends that+-- await step to the parent's journal so the parent's `awaitChild` resolves.+-- `cancelChild` flips a still-'running' row to 'cancelled' and writes a+-- WorkflowCancelled marker to the child's journal so the child stops.+--+-- The journal streams (wf:<name>-<id>) remain the source of truth for replay;+-- this table is the parent<->child relation plus operator-visible state and+-- the discovery seed that lets the resume worker drive a zero-step child.+CREATE TABLE IF NOT EXISTS keiro.keiro_workflow_children (+ child_id TEXT NOT NULL,+ child_name TEXT NOT NULL,+ parent_id TEXT NOT NULL,+ parent_name TEXT NOT NULL,+ await_step TEXT NOT NULL, -- "child:<childId>:result" in the parent journal+ status TEXT NOT NULL DEFAULT 'running',+ result JSONB,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ completed_at TIMESTAMPTZ,+ PRIMARY KEY (child_id, child_name),+ CONSTRAINT keiro_workflow_children_status_chk+ CHECK (status IN ('running', 'completed', 'cancelled'))+);++-- List all children of one parent (operator inspection, awaitChild arm re-assertion).+CREATE INDEX IF NOT EXISTS keiro_workflow_children_parent_idx+ ON keiro.keiro_workflow_children (parent_id, parent_name);++-- Discovery for the resume worker: children still running (zero-step children too).+CREATE INDEX IF NOT EXISTS keiro_workflow_children_running_idx+ ON keiro.keiro_workflow_children (status)+ WHERE status = 'running';
+ migrations/0008-keiro-workflow-generation.sql view
@@ -0,0 +1,25 @@+-- Continue-as-new (EP-48) rotates a long-running workflow onto a fresh journal+-- *generation* so its history stays bounded. The logical identity+-- (workflow_id, workflow_name) is stable; the generation discriminates the+-- physical journal stream wf:<name>-<id>#<gen>. Generation 0 is the pre-rotation+-- default, so every existing row and every never-rotating workflow is unaffected.+ALTER TABLE keiro.keiro_workflow_steps+ ADD COLUMN IF NOT EXISTS generation integer NOT NULL DEFAULT 0;++-- Fold the generation (and workflow_name) into the key so two generations of the+-- same logical workflow do not collide on a reserved step name (e.g. the terminal+-- markers). Adding columns to the key is a strict relaxation: no existing row can+-- violate the wider key. The as-shipped key is (workflow_id, step_name) — plan 47+-- (which would have keyed on (workflow_id, workflow_name, step_name)) has NOT landed,+-- so this migration re-keys with workflow_name AND generation in one step, doing both+-- jobs at once. The base table's primary-key constraint is named+-- keiro_workflow_steps_pkey (Postgres default <table>_pkey).+ALTER TABLE keiro.keiro_workflow_steps DROP CONSTRAINT keiro_workflow_steps_pkey;+ALTER TABLE keiro.keiro_workflow_steps+ ADD PRIMARY KEY (workflow_id, workflow_name, generation, step_name);++-- Support the current-generation lookup (MAX(generation) per id+name). Replaces the+-- old (workflow_id)-only lookup index.+DROP INDEX IF EXISTS keiro.keiro_workflow_steps_workflow_idx;+CREATE INDEX IF NOT EXISTS keiro_workflow_steps_workflow_idx+ ON keiro.keiro_workflow_steps (workflow_id, workflow_name, generation);
+ migrations/0009-keiro-subscription-shards.sql view
@@ -0,0 +1,38 @@+-- The keiro_subscription_shards table: cooperative ownership of category+-- subscription buckets (EP-51).+--+-- A "bucket" is a kiroku consumer-group member index in [0, shard_count): the+-- stream key (originating stream_id) hashes to one bucket via+-- (((hashtextextended(stream_id::text, 0) % shard_count) + shard_count) % shard_count)+-- exactly as kiroku's readCategoryForwardConsumerGroupStmt does. This table does+-- NOT re-hash anything; it records WHO owns each bucket right now, as a renewable+-- lease. A live worker renews lease_expires_at on a heartbeat; a dead worker stops+-- renewing, its lease expires, and another worker re-claims the bucket (failover).+--+-- One row per (subscription_name, bucket). owner_worker_id NULL means unowned+-- (free to claim). The journal/checkpoints stay in kiroku's `subscriptions` table+-- keyed (subscription_name, consumer_group_member); this table only governs+-- assignment, never event position.+CREATE TABLE IF NOT EXISTS keiro.keiro_subscription_shards (+ subscription_name TEXT NOT NULL,+ bucket INT NOT NULL, -- kiroku consumer-group member index+ shard_count INT NOT NULL, -- N; fixed per subscription_name+ owner_worker_id UUID, -- NULL = unowned / claimable+ lease_expires_at TIMESTAMPTZ, -- NULL when unowned+ heartbeat_at TIMESTAMPTZ, -- last renewal (observability)+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ PRIMARY KEY (subscription_name, bucket),+ CONSTRAINT keiro_subscription_shards_bucket_range_chk+ CHECK (bucket >= 0 AND bucket < shard_count),+ CONSTRAINT keiro_subscription_shards_count_chk+ CHECK (shard_count >= 1)+);++-- Fast lookup of an owner's currently-held buckets (renew path) and of+-- claimable buckets (claim path filters on lease_expires_at).+CREATE INDEX IF NOT EXISTS keiro_subscription_shards_owner_idx+ ON keiro.keiro_subscription_shards (subscription_name, owner_worker_id);++-- Find expired/unowned buckets cheaply during a claim sweep.+CREATE INDEX IF NOT EXISTS keiro_subscription_shards_lease_idx+ ON keiro.keiro_subscription_shards (subscription_name, lease_expires_at);
+ migrations/0010-keiro-messaging-crash-recovery.sql view
@@ -0,0 +1,21 @@+-- messaging crash recovery++-- H5: per-message failure accounting for the inbox poison-message path.+ALTER TABLE keiro.keiro_inbox+ ADD COLUMN IF NOT EXISTS attempt_count BIGINT NOT NULL DEFAULT 0;++-- H3: lets the backlog gauge count rows without a sequential scan.+CREATE INDEX IF NOT EXISTS keiro_inbox_backlog_idx+ ON keiro.keiro_inbox (status)+ WHERE status IN ('processing', 'failed');++-- H4: lets garbageCollectSent find expired sent rows without a sequential scan.+CREATE INDEX IF NOT EXISTS keiro_outbox_sent_gc_idx+ ON keiro.keiro_outbox (published_at)+ WHERE status = 'sent';++-- L8: supports the PerSourceStream head-of-line predicate (any key, including+-- NULL); the existing keiro_outbox_head_of_line_idx excludes NULL keys.+CREATE INDEX IF NOT EXISTS keiro_outbox_source_order_idx+ ON keiro.keiro_outbox (source, created_at, outbox_id)+ WHERE status NOT IN ('sent', 'dead');
+ migrations/0011-keiro-workflows-instances.sql view
@@ -0,0 +1,76 @@+-- Workflow instance state used by the resume worker and by later discovery /+-- pruning work. The journal remains the source of truth; this table is a+-- transactional summary maintained beside journal-index writes.+CREATE TABLE IF NOT EXISTS keiro.keiro_workflows (+ workflow_id TEXT NOT NULL,+ workflow_name TEXT NOT NULL,+ generation INTEGER NOT NULL DEFAULT 0,+ status TEXT NOT NULL DEFAULT 'running',+ attempts INTEGER NOT NULL DEFAULT 0,+ last_error TEXT,+ next_attempt_at TIMESTAMPTZ,+ leased_by TEXT,+ lease_expires_at TIMESTAMPTZ,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ completed_at TIMESTAMPTZ,+ PRIMARY KEY (workflow_id, workflow_name),+ CONSTRAINT keiro_workflows_status_chk+ CHECK (status IN ('running', 'suspended', 'completed', 'cancelled', 'failed'))+);++CREATE INDEX IF NOT EXISTS keiro_workflows_active_idx+ ON keiro.keiro_workflows (status)+ WHERE status IN ('running', 'suspended');++WITH current_gen AS (+ SELECT workflow_id, workflow_name, MAX(generation) AS generation+ FROM keiro.keiro_workflow_steps+ GROUP BY workflow_id, workflow_name+),+terminal AS (+ SELECT+ cg.workflow_id,+ cg.workflow_name,+ cg.generation,+ CASE+ WHEN EXISTS (+ SELECT 1 FROM keiro.keiro_workflow_steps s+ WHERE s.workflow_id = cg.workflow_id+ AND s.workflow_name = cg.workflow_name+ AND s.generation = cg.generation+ AND s.step_name = '__workflow_completed__'+ ) THEN 'completed'+ WHEN EXISTS (+ SELECT 1 FROM keiro.keiro_workflow_steps s+ WHERE s.workflow_id = cg.workflow_id+ AND s.workflow_name = cg.workflow_name+ AND s.generation = cg.generation+ AND s.step_name = '__workflow_cancelled__'+ ) THEN 'cancelled'+ WHEN EXISTS (+ SELECT 1 FROM keiro.keiro_workflow_steps s+ WHERE s.workflow_id = cg.workflow_id+ AND s.workflow_name = cg.workflow_name+ AND s.generation = cg.generation+ AND s.step_name = '__workflow_failed__'+ ) THEN 'failed'+ ELSE 'running'+ END AS status+ FROM current_gen cg+)+INSERT INTO keiro.keiro_workflows (workflow_id, workflow_name, generation, status, completed_at)+SELECT workflow_id, workflow_name, generation, status,+ CASE WHEN status IN ('completed', 'cancelled', 'failed') THEN now() ELSE NULL END+FROM terminal+ON CONFLICT (workflow_id, workflow_name) DO NOTHING;++INSERT INTO keiro.keiro_workflows (workflow_id, workflow_name, generation, status)+SELECT child_id, child_name, 0, 'running'+FROM keiro.keiro_workflow_children+WHERE status = 'running'+ON CONFLICT (workflow_id, workflow_name) DO NOTHING;++ALTER TABLE keiro.keiro_workflow_children DROP CONSTRAINT IF EXISTS keiro_workflow_children_status_chk;+ALTER TABLE keiro.keiro_workflow_children ADD CONSTRAINT keiro_workflow_children_status_chk+ CHECK (status IN ('running', 'completed', 'cancelled', 'failed'));
+ migrations/0012-keiro-workflow-gc-index.sql view
@@ -0,0 +1,3 @@+-- GC eligibility scan: terminal instances ordered by terminal age.+CREATE INDEX IF NOT EXISTS keiro_workflows_gc_idx+ ON keiro.keiro_workflows (status, completed_at);
+ migrations/0013-keiro-workflows-wake-after.sql view
@@ -0,0 +1,3 @@+-- Self-expiring resume hint for workflows parked only on a sleep timer.+ALTER TABLE keiro.keiro_workflows+ ADD COLUMN IF NOT EXISTS wake_after TIMESTAMPTZ;
+ migrations/0014-keiro-projection-dedup.sql view
@@ -0,0 +1,9 @@+CREATE TABLE IF NOT EXISTS keiro.keiro_projection_dedup (+ projection_name TEXT NOT NULL,+ event_id UUID NOT NULL,+ applied_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ PRIMARY KEY (projection_name, event_id)+);++CREATE INDEX IF NOT EXISTS keiro_projection_dedup_applied_at_idx+ ON keiro.keiro_projection_dedup (applied_at);
+ migrations/0015-keiro-outbox-claim-order-index.sql view
@@ -0,0 +1,6 @@+-- Serves the outbox claim query's candidate scan: ordered walk by+-- (created_at, outbox_id) over claimable rows, stopping at the batch limit.+-- next_attempt_at is a residual filter, usually already satisfied for pending rows.+CREATE INDEX IF NOT EXISTS keiro_outbox_claim_order_idx+ ON keiro.keiro_outbox (created_at, outbox_id)+ WHERE status IN ('pending', 'failed');
+ migrations/0016-keiro-inbox-drop-received-idx.sql view
@@ -0,0 +1,4 @@+-- keiro_inbox_received_idx served only the listInbox test helper's ordering+-- but was maintained on every consumed message. Retention GC uses+-- keiro_inbox_completed_idx; the backlog gauge uses keiro_inbox_backlog_idx.+DROP INDEX IF EXISTS keiro.keiro_inbox_received_idx;
+ migrations/0017-schema-management-comment.sql view
@@ -0,0 +1,2 @@+COMMENT ON SCHEMA keiro IS+ 'Managed by pg-migrate component keiro through 0017-schema-management-comment';
+ migrations/0018.sql view
@@ -0,0 +1,28 @@+-- keiro dead letters++-- Durable records for process-manager and router dispatches that reached a+-- target stream but were rejected. These rows are distinct from+-- kiroku.dead_letters: the source subscription event is successfully handled+-- and checkpointed after every rejected dispatch has been recorded here.+CREATE TABLE IF NOT EXISTS keiro.keiro_dead_letters (+ dead_letter_id BIGSERIAL PRIMARY KEY,+ dispatcher_kind TEXT NOT NULL,+ dispatcher_name TEXT NOT NULL,+ correlation_id TEXT NOT NULL,+ source_event_id UUID NOT NULL,+ source_global_position BIGINT NOT NULL,+ emit_index INT NOT NULL,+ target_stream_name TEXT NOT NULL,+ error_class TEXT NOT NULL,+ error_detail TEXT NOT NULL,+ attempt_count INT NOT NULL,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ CONSTRAINT keiro_dead_letters_dispatcher_kind_chk+ CHECK (dispatcher_kind IN ('process-manager', 'router')),+ CONSTRAINT keiro_dead_letters_attempt_count_chk+ CHECK (attempt_count >= 1),+ UNIQUE (dispatcher_name, source_event_id, emit_index)+);++CREATE INDEX IF NOT EXISTS keiro_dead_letters_dispatcher_created_at_idx+ ON keiro.keiro_dead_letters (dispatcher_name, created_at DESC);
+ migrations/manifest view
@@ -0,0 +1,18 @@+0001-keiro-bootstrap.sql+0002-keiro-outbox.sql+0003-keiro-inbox.sql+0004-keiro-timer-recovery.sql+0005-keiro-workflow-steps.sql+0006-keiro-awakeables.sql+0007-keiro-workflow-children.sql+0008-keiro-workflow-generation.sql+0009-keiro-subscription-shards.sql+0010-keiro-messaging-crash-recovery.sql+0011-keiro-workflows-instances.sql+0012-keiro-workflow-gc-index.sql+0013-keiro-workflows-wake-after.sql+0014-keiro-projection-dedup.sql+0015-keiro-outbox-claim-order-index.sql+0016-keiro-inbox-drop-received-idx.sql+0017-schema-management-comment.sql+0018.sql
+ sql-migrations/2026-05-17-13-58-15-keiro-bootstrap.sql view
@@ -0,0 +1,44 @@+-- Keiro framework bootstrap migration (codd).+--+-- Keiro owns the dedicated `keiro` schema. codd applies this file in its own+-- session, so the schema is created here and every object is written fully+-- qualified as keiro.<name> — no session search-path pin is used anywhere.+CREATE SCHEMA IF NOT EXISTS keiro;++CREATE TABLE IF NOT EXISTS keiro.keiro_snapshots (+ stream_id BIGINT PRIMARY KEY,+ stream_version BIGINT NOT NULL,+ state JSONB NOT NULL,+ state_codec_version BIGINT NOT NULL,+ regfile_shape_hash TEXT NOT NULL,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()+);++CREATE INDEX IF NOT EXISTS keiro_snapshots_compat_idx+ ON keiro.keiro_snapshots (stream_id, state_codec_version, regfile_shape_hash, stream_version DESC);++CREATE TABLE IF NOT EXISTS keiro.keiro_read_models (+ name TEXT PRIMARY KEY,+ version BIGINT NOT NULL,+ shape_hash TEXT NOT NULL,+ last_built_at TIMESTAMPTZ,+ status TEXT NOT NULL,+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()+);++CREATE TABLE IF NOT EXISTS keiro.keiro_timers (+ timer_id UUID PRIMARY KEY,+ process_manager_name TEXT NOT NULL,+ correlation_id TEXT NOT NULL,+ fire_at TIMESTAMPTZ NOT NULL,+ payload JSONB NOT NULL,+ status TEXT NOT NULL DEFAULT 'scheduled',+ attempts BIGINT NOT NULL DEFAULT 0,+ fired_event_id UUID,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()+);++CREATE INDEX IF NOT EXISTS keiro_timers_due_idx+ ON keiro.keiro_timers (status, fire_at, process_manager_name);
+ sql-migrations/2026-05-19-12-55-02-keiro-outbox.sql view
@@ -0,0 +1,39 @@+CREATE TABLE IF NOT EXISTS keiro.keiro_outbox (+ outbox_id UUID PRIMARY KEY,+ message_id TEXT NOT NULL,+ source TEXT NOT NULL,+ destination TEXT NOT NULL,+ message_key TEXT,+ event_type TEXT NOT NULL,+ schema_version BIGINT NOT NULL,+ content_type TEXT NOT NULL,+ schema_registry TEXT,+ schema_subject TEXT,+ schema_version_ref BIGINT,+ schema_id BIGINT,+ schema_fingerprint TEXT,+ source_event_id UUID,+ source_global_position BIGINT,+ causation_id UUID,+ correlation_id UUID,+ traceparent TEXT,+ tracestate TEXT,+ payload_bytes BYTEA NOT NULL,+ attributes JSONB,+ occurred_at TIMESTAMPTZ NOT NULL,+ status TEXT NOT NULL DEFAULT 'pending',+ attempt_count BIGINT NOT NULL DEFAULT 0,+ next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ last_error TEXT,+ published_at TIMESTAMPTZ,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ UNIQUE (source, message_id)+);++CREATE INDEX IF NOT EXISTS keiro_outbox_pending_idx+ ON keiro.keiro_outbox (status, next_attempt_at, created_at);++CREATE INDEX IF NOT EXISTS keiro_outbox_head_of_line_idx+ ON keiro.keiro_outbox (source, message_key, created_at)+ WHERE status NOT IN ('sent', 'dead') AND message_key IS NOT NULL;
+ sql-migrations/2026-05-19-13-05-23-keiro-inbox.sql view
@@ -0,0 +1,39 @@+CREATE TABLE IF NOT EXISTS keiro.keiro_inbox (+ source TEXT NOT NULL,+ dedupe_key TEXT NOT NULL,+ message_id TEXT,+ source_event_id UUID,+ source_global_position BIGINT,+ destination TEXT,+ event_type TEXT,+ schema_version BIGINT,+ content_type TEXT NOT NULL,+ schema_registry TEXT,+ schema_subject TEXT,+ schema_version_ref BIGINT,+ schema_id BIGINT,+ schema_fingerprint TEXT,+ causation_id UUID,+ correlation_id UUID,+ traceparent TEXT,+ tracestate TEXT,+ kafka_topic TEXT,+ kafka_partition BIGINT,+ kafka_offset BIGINT,+ payload_bytes BYTEA NOT NULL,+ attributes JSONB,+ occurred_at TIMESTAMPTZ,+ status TEXT NOT NULL DEFAULT 'processing',+ received_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ completed_at TIMESTAMPTZ,+ failed_at TIMESTAMPTZ,+ last_error TEXT,+ PRIMARY KEY (source, dedupe_key)+);++CREATE INDEX IF NOT EXISTS keiro_inbox_received_idx+ ON keiro.keiro_inbox (received_at);++CREATE INDEX IF NOT EXISTS keiro_inbox_completed_idx+ ON keiro.keiro_inbox (completed_at)+ WHERE status = 'completed';
+ sql-migrations/2026-06-03-05-14-28-keiro-timer-recovery.sql view
@@ -0,0 +1,8 @@+ALTER TABLE keiro.keiro_timers+ ADD COLUMN IF NOT EXISTS last_error TEXT;++DROP INDEX IF EXISTS keiro.keiro_timers_due_idx;++CREATE INDEX IF NOT EXISTS keiro_timers_due_idx+ ON keiro.keiro_timers (status, fire_at, process_manager_name)+ WHERE status IN ('scheduled', 'firing');
+ sql-migrations/2026-06-03-16-10-05-keiro-workflow-steps.sql view
@@ -0,0 +1,21 @@+-- The fast-lookup index of journaled workflow steps. The journal stream+-- (wf:<name>-<id>) is the source of truth for replay; this table is a derived+-- view kept in sync inside the same transaction as each journal append. It+-- lets the runtime hot path and the EP-42 resume worker look up a step (or+-- discover unfinished workflows) without rescanning the journal stream.+--+-- The reserved step name '__workflow_completed__' is written when a workflow+-- finishes (see Keiro.Workflow.Types.completedStepName); its absence is how+-- findUnfinishedWorkflowIds distinguishes an in-flight workflow from a+-- completed one.+CREATE TABLE IF NOT EXISTS keiro.keiro_workflow_steps (+ workflow_id text NOT NULL,+ workflow_name text NOT NULL,+ step_name text NOT NULL,+ result jsonb NOT NULL,+ recorded_at timestamptz NOT NULL DEFAULT now(),+ PRIMARY KEY (workflow_id, step_name)+);++CREATE INDEX IF NOT EXISTS keiro_workflow_steps_workflow_idx+ ON keiro.keiro_workflow_steps (workflow_id);
+ sql-migrations/2026-06-03-18-19-41-keiro-awakeables.sql view
@@ -0,0 +1,33 @@+-- The keiro_awakeables table: durable promises an external system resolves.+--+-- A workflow's `awakeable` allocates a deterministic id, inserts a 'pending'+-- row here, and suspends; an external caller later runs `signalAwakeable`,+-- which flips the row to 'completed' (storing the payload) and appends a+-- StepRecorded "awk:<uuid>" to the owning workflow's journal so the next+-- runWorkflow takes the awaitStep hit path. `cancelAwakeable` flips a still+-- 'pending' row to 'cancelled'; a subsequent run then throws.+--+-- The journal stream (wf:<name>-<id>) remains the source of truth for replay;+-- this table is the external-completion handshake plus operator-visible state+-- (a stuck 'pending' row is a workflow waiting on a callback that never came).+CREATE TABLE IF NOT EXISTS keiro.keiro_awakeables (+ awakeable_id UUID PRIMARY KEY,+ owner_workflow_name TEXT NOT NULL,+ owner_workflow_id TEXT NOT NULL,+ status TEXT NOT NULL DEFAULT 'pending',+ payload JSONB,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ completed_at TIMESTAMPTZ,+ CONSTRAINT keiro_awakeables_status_chk+ CHECK (status IN ('pending', 'completed', 'cancelled'))+);++-- Gauge support (EP-44 keiro.workflow.awakeables.pending) and operator triage.+CREATE INDEX IF NOT EXISTS keiro_awakeables_pending_idx+ ON keiro.keiro_awakeables (status)+ WHERE status = 'pending';++-- Find all awakeables owned by one workflow instance (operator repair, EP-42/EP-43).+CREATE INDEX IF NOT EXISTS keiro_awakeables_owner_idx+ ON keiro.keiro_awakeables (owner_workflow_name, owner_workflow_id);
+ sql-migrations/2026-06-03-19-49-23-keiro-workflow-children.sql view
@@ -0,0 +1,39 @@+-- The keiro_workflow_children table: durable parent->child workflow links.+--+-- A parent workflow's `spawnChild` records the child in the parent's journal+-- as a StepRecorded "child:<childId>" (so a replay short-circuits the spawn)+-- and inserts a 'running' row here linking the child's (id, name) back to the+-- parent's (id, name) plus the parent-journal step the parent awaits+-- ("child:<childId>:result"). When the child completes, `childCompletionHook`+-- flips the row to 'completed' (storing the child's result) and appends that+-- await step to the parent's journal so the parent's `awaitChild` resolves.+-- `cancelChild` flips a still-'running' row to 'cancelled' and writes a+-- WorkflowCancelled marker to the child's journal so the child stops.+--+-- The journal streams (wf:<name>-<id>) remain the source of truth for replay;+-- this table is the parent<->child relation plus operator-visible state and+-- the discovery seed that lets the resume worker drive a zero-step child.+CREATE TABLE IF NOT EXISTS keiro.keiro_workflow_children (+ child_id TEXT NOT NULL,+ child_name TEXT NOT NULL,+ parent_id TEXT NOT NULL,+ parent_name TEXT NOT NULL,+ await_step TEXT NOT NULL, -- "child:<childId>:result" in the parent journal+ status TEXT NOT NULL DEFAULT 'running',+ result JSONB,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ completed_at TIMESTAMPTZ,+ PRIMARY KEY (child_id, child_name),+ CONSTRAINT keiro_workflow_children_status_chk+ CHECK (status IN ('running', 'completed', 'cancelled'))+);++-- List all children of one parent (operator inspection, awaitChild arm re-assertion).+CREATE INDEX IF NOT EXISTS keiro_workflow_children_parent_idx+ ON keiro.keiro_workflow_children (parent_id, parent_name);++-- Discovery for the resume worker: children still running (zero-step children too).+CREATE INDEX IF NOT EXISTS keiro_workflow_children_running_idx+ ON keiro.keiro_workflow_children (status)+ WHERE status = 'running';
+ sql-migrations/2026-06-04-02-12-28-keiro-workflow-generation.sql view
@@ -0,0 +1,25 @@+-- Continue-as-new (EP-48) rotates a long-running workflow onto a fresh journal+-- *generation* so its history stays bounded. The logical identity+-- (workflow_id, workflow_name) is stable; the generation discriminates the+-- physical journal stream wf:<name>-<id>#<gen>. Generation 0 is the pre-rotation+-- default, so every existing row and every never-rotating workflow is unaffected.+ALTER TABLE keiro.keiro_workflow_steps+ ADD COLUMN IF NOT EXISTS generation integer NOT NULL DEFAULT 0;++-- Fold the generation (and workflow_name) into the key so two generations of the+-- same logical workflow do not collide on a reserved step name (e.g. the terminal+-- markers). Adding columns to the key is a strict relaxation: no existing row can+-- violate the wider key. The as-shipped key is (workflow_id, step_name) — plan 47+-- (which would have keyed on (workflow_id, workflow_name, step_name)) has NOT landed,+-- so this migration re-keys with workflow_name AND generation in one step, doing both+-- jobs at once. The base table's primary-key constraint is named+-- keiro_workflow_steps_pkey (Postgres default <table>_pkey).+ALTER TABLE keiro.keiro_workflow_steps DROP CONSTRAINT keiro_workflow_steps_pkey;+ALTER TABLE keiro.keiro_workflow_steps+ ADD PRIMARY KEY (workflow_id, workflow_name, generation, step_name);++-- Support the current-generation lookup (MAX(generation) per id+name). Replaces the+-- old (workflow_id)-only lookup index.+DROP INDEX IF EXISTS keiro.keiro_workflow_steps_workflow_idx;+CREATE INDEX IF NOT EXISTS keiro_workflow_steps_workflow_idx+ ON keiro.keiro_workflow_steps (workflow_id, workflow_name, generation);
+ sql-migrations/2026-06-04-03-53-34-keiro-subscription-shards.sql view
@@ -0,0 +1,38 @@+-- The keiro_subscription_shards table: cooperative ownership of category+-- subscription buckets (EP-51).+--+-- A "bucket" is a kiroku consumer-group member index in [0, shard_count): the+-- stream key (originating stream_id) hashes to one bucket via+-- (((hashtextextended(stream_id::text, 0) % shard_count) + shard_count) % shard_count)+-- exactly as kiroku's readCategoryForwardConsumerGroupStmt does. This table does+-- NOT re-hash anything; it records WHO owns each bucket right now, as a renewable+-- lease. A live worker renews lease_expires_at on a heartbeat; a dead worker stops+-- renewing, its lease expires, and another worker re-claims the bucket (failover).+--+-- One row per (subscription_name, bucket). owner_worker_id NULL means unowned+-- (free to claim). The journal/checkpoints stay in kiroku's `subscriptions` table+-- keyed (subscription_name, consumer_group_member); this table only governs+-- assignment, never event position.+CREATE TABLE IF NOT EXISTS keiro.keiro_subscription_shards (+ subscription_name TEXT NOT NULL,+ bucket INT NOT NULL, -- kiroku consumer-group member index+ shard_count INT NOT NULL, -- N; fixed per subscription_name+ owner_worker_id UUID, -- NULL = unowned / claimable+ lease_expires_at TIMESTAMPTZ, -- NULL when unowned+ heartbeat_at TIMESTAMPTZ, -- last renewal (observability)+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ PRIMARY KEY (subscription_name, bucket),+ CONSTRAINT keiro_subscription_shards_bucket_range_chk+ CHECK (bucket >= 0 AND bucket < shard_count),+ CONSTRAINT keiro_subscription_shards_count_chk+ CHECK (shard_count >= 1)+);++-- Fast lookup of an owner's currently-held buckets (renew path) and of+-- claimable buckets (claim path filters on lease_expires_at).+CREATE INDEX IF NOT EXISTS keiro_subscription_shards_owner_idx+ ON keiro.keiro_subscription_shards (subscription_name, owner_worker_id);++-- Find expired/unowned buckets cheaply during a claim sweep.+CREATE INDEX IF NOT EXISTS keiro_subscription_shards_lease_idx+ ON keiro.keiro_subscription_shards (subscription_name, lease_expires_at);
+ sql-migrations/2026-06-15-13-22-31-keiro-messaging-crash-recovery.sql view
@@ -0,0 +1,21 @@+-- messaging crash recovery++-- H5: per-message failure accounting for the inbox poison-message path.+ALTER TABLE keiro.keiro_inbox+ ADD COLUMN IF NOT EXISTS attempt_count BIGINT NOT NULL DEFAULT 0;++-- H3: lets the backlog gauge count rows without a sequential scan.+CREATE INDEX IF NOT EXISTS keiro_inbox_backlog_idx+ ON keiro.keiro_inbox (status)+ WHERE status IN ('processing', 'failed');++-- H4: lets garbageCollectSent find expired sent rows without a sequential scan.+CREATE INDEX IF NOT EXISTS keiro_outbox_sent_gc_idx+ ON keiro.keiro_outbox (published_at)+ WHERE status = 'sent';++-- L8: supports the PerSourceStream head-of-line predicate (any key, including+-- NULL); the existing keiro_outbox_head_of_line_idx excludes NULL keys.+CREATE INDEX IF NOT EXISTS keiro_outbox_source_order_idx+ ON keiro.keiro_outbox (source, created_at, outbox_id)+ WHERE status NOT IN ('sent', 'dead');
+ sql-migrations/2026-06-15-15-07-25-keiro-workflows-instances.sql view
@@ -0,0 +1,76 @@+-- Workflow instance state used by the resume worker and by later discovery /+-- pruning work. The journal remains the source of truth; this table is a+-- transactional summary maintained beside journal-index writes.+CREATE TABLE IF NOT EXISTS keiro.keiro_workflows (+ workflow_id TEXT NOT NULL,+ workflow_name TEXT NOT NULL,+ generation INTEGER NOT NULL DEFAULT 0,+ status TEXT NOT NULL DEFAULT 'running',+ attempts INTEGER NOT NULL DEFAULT 0,+ last_error TEXT,+ next_attempt_at TIMESTAMPTZ,+ leased_by TEXT,+ lease_expires_at TIMESTAMPTZ,+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ completed_at TIMESTAMPTZ,+ PRIMARY KEY (workflow_id, workflow_name),+ CONSTRAINT keiro_workflows_status_chk+ CHECK (status IN ('running', 'suspended', 'completed', 'cancelled', 'failed'))+);++CREATE INDEX IF NOT EXISTS keiro_workflows_active_idx+ ON keiro.keiro_workflows (status)+ WHERE status IN ('running', 'suspended');++WITH current_gen AS (+ SELECT workflow_id, workflow_name, MAX(generation) AS generation+ FROM keiro.keiro_workflow_steps+ GROUP BY workflow_id, workflow_name+),+terminal AS (+ SELECT+ cg.workflow_id,+ cg.workflow_name,+ cg.generation,+ CASE+ WHEN EXISTS (+ SELECT 1 FROM keiro.keiro_workflow_steps s+ WHERE s.workflow_id = cg.workflow_id+ AND s.workflow_name = cg.workflow_name+ AND s.generation = cg.generation+ AND s.step_name = '__workflow_completed__'+ ) THEN 'completed'+ WHEN EXISTS (+ SELECT 1 FROM keiro.keiro_workflow_steps s+ WHERE s.workflow_id = cg.workflow_id+ AND s.workflow_name = cg.workflow_name+ AND s.generation = cg.generation+ AND s.step_name = '__workflow_cancelled__'+ ) THEN 'cancelled'+ WHEN EXISTS (+ SELECT 1 FROM keiro.keiro_workflow_steps s+ WHERE s.workflow_id = cg.workflow_id+ AND s.workflow_name = cg.workflow_name+ AND s.generation = cg.generation+ AND s.step_name = '__workflow_failed__'+ ) THEN 'failed'+ ELSE 'running'+ END AS status+ FROM current_gen cg+)+INSERT INTO keiro.keiro_workflows (workflow_id, workflow_name, generation, status, completed_at)+SELECT workflow_id, workflow_name, generation, status,+ CASE WHEN status IN ('completed', 'cancelled', 'failed') THEN now() ELSE NULL END+FROM terminal+ON CONFLICT (workflow_id, workflow_name) DO NOTHING;++INSERT INTO keiro.keiro_workflows (workflow_id, workflow_name, generation, status)+SELECT child_id, child_name, 0, 'running'+FROM keiro.keiro_workflow_children+WHERE status = 'running'+ON CONFLICT (workflow_id, workflow_name) DO NOTHING;++ALTER TABLE keiro.keiro_workflow_children DROP CONSTRAINT IF EXISTS keiro_workflow_children_status_chk;+ALTER TABLE keiro.keiro_workflow_children ADD CONSTRAINT keiro_workflow_children_status_chk+ CHECK (status IN ('running', 'completed', 'cancelled', 'failed'));
+ sql-migrations/2026-06-15-17-53-48-keiro-workflow-gc-index.sql view
@@ -0,0 +1,3 @@+-- GC eligibility scan: terminal instances ordered by terminal age.+CREATE INDEX IF NOT EXISTS keiro_workflows_gc_idx+ ON keiro.keiro_workflows (status, completed_at);
+ sql-migrations/2026-06-15-18-01-33-keiro-workflows-wake-after.sql view
@@ -0,0 +1,3 @@+-- Self-expiring resume hint for workflows parked only on a sleep timer.+ALTER TABLE keiro.keiro_workflows+ ADD COLUMN IF NOT EXISTS wake_after TIMESTAMPTZ;
+ sql-migrations/2026-06-15-21-49-37-keiro-projection-dedup.sql view
@@ -0,0 +1,9 @@+CREATE TABLE IF NOT EXISTS keiro.keiro_projection_dedup (+ projection_name TEXT NOT NULL,+ event_id UUID NOT NULL,+ applied_at TIMESTAMPTZ NOT NULL DEFAULT now(),+ PRIMARY KEY (projection_name, event_id)+);++CREATE INDEX IF NOT EXISTS keiro_projection_dedup_applied_at_idx+ ON keiro.keiro_projection_dedup (applied_at);
+ sql-migrations/2026-07-02-00-15-48-keiro-outbox-claim-order-index.sql view
@@ -0,0 +1,6 @@+-- Serves the outbox claim query's candidate scan: ordered walk by+-- (created_at, outbox_id) over claimable rows, stopping at the batch limit.+-- next_attempt_at is a residual filter, usually already satisfied for pending rows.+CREATE INDEX IF NOT EXISTS keiro_outbox_claim_order_idx+ ON keiro.keiro_outbox (created_at, outbox_id)+ WHERE status IN ('pending', 'failed');
+ sql-migrations/2026-07-02-00-58-54-keiro-inbox-drop-received-idx.sql view
@@ -0,0 +1,4 @@+-- keiro_inbox_received_idx served only the listInbox test helper's ordering+-- but was maintained on every consumed message. Retention GC uses+-- keiro_inbox_completed_idx; the backlog gauge uses keiro_inbox_backlog_idx.+DROP INDEX IF EXISTS keiro.keiro_inbox_received_idx;
+ src/Keiro/Migrations.hs view
@@ -0,0 +1,31 @@+module Keiro.Migrations (+ DefinitionError,+ MigrationComponent,+ MigrationPlan,+ PlanError,+ frameworkMigrationPlan,+ keiroMigrations,+) where++import Data.List.NonEmpty (NonEmpty (..))+import Database.PostgreSQL.Migrate (+ DefinitionError,+ MigrationComponent,+ MigrationPlan,+ PlanError,+ migrationPlan,+ )+import Keiro.Migrations.Internal.Definition (keiroMigrations)++{- | Compose the concrete Kiroku and Keiro components in dependency order.++The first argument must be Kiroku's component and the second must be Keiro's.+The native planner validates both identity and ordering, so swapped or unrelated+components fail with a structured 'PlanError'.+-}+frameworkMigrationPlan ::+ MigrationComponent ->+ MigrationComponent ->+ Either PlanError MigrationPlan+frameworkMigrationPlan kiroku keiro =+ migrationPlan (kiroku :| [keiro])
+ src/Keiro/Migrations/ExpectedSchema.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE TemplateHaskell #-}++module Keiro.Migrations.ExpectedSchema (+ expectedSchemaFiles,+ withMaterializedExpectedSchema,+) where++import Codd.Extras.ExpectedSchema qualified as ExpectedSchema+import Data.ByteString (ByteString)+import Data.FileEmbed (embedDir)++-- Embedded expected schema (touch this comment after regenerating expected-schema+-- so Template Haskell refreshes the executable snapshot).+expectedSchemaFiles :: [(FilePath, ByteString)]+expectedSchemaFiles = $(embedDir "expected-schema")++withMaterializedExpectedSchema :: (FilePath -> IO a) -> IO a+withMaterializedExpectedSchema action =+ ExpectedSchema.withMaterializedExpectedSchema "keiro-expected-schema" expectedSchemaFiles action
+ src/Keiro/Migrations/History/Codd.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE TemplateHaskell #-}++module Keiro.Migrations.History.Codd (+ frameworkCoddHistoryMappings,+ frameworkCoddSourceConfig,+ keiroCoddHistoryMappings,+ keiroCoddManifestText,+ keiroCoddSourcePayloads,+ keiroLegacyMigrationNames,+) where++import Data.Bifunctor (first)+import Data.ByteString (ByteString)+import Data.Foldable (toList)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Map.Strict qualified as Map+import Data.Text (Text)+import Database.PostgreSQL.Migrate (+ Confirmation,+ ConnectionProvider,+ EvidenceRequirement (Evidence),+ HistoryMapping,+ PayloadRelation (SamePayload),+ historyMapping,+ migrationId,+ )+import Database.PostgreSQL.Migrate.History.Codd (+ CoddDefinitionError,+ CoddSourceConfig,+ coddEvidenceKey,+ coddSourceConfig,+ parseCoddManifest,+ )+import Keiro.Migrations.Internal.Definition (embeddedMigrationEntries)+import Keiro.Migrations.Internal.EmbedFile (embedTextFile)+import Kiroku.Store.Migrations.History.Codd qualified as Kiroku++keiroLegacyMigrationNames :: NonEmpty FilePath+keiroLegacyMigrationNames =+ "2026-05-17-13-58-15-keiro-bootstrap.sql"+ :| [ "2026-05-19-12-55-02-keiro-outbox.sql"+ , "2026-05-19-13-05-23-keiro-inbox.sql"+ , "2026-06-03-05-14-28-keiro-timer-recovery.sql"+ , "2026-06-03-16-10-05-keiro-workflow-steps.sql"+ , "2026-06-03-18-19-41-keiro-awakeables.sql"+ , "2026-06-03-19-49-23-keiro-workflow-children.sql"+ , "2026-06-04-02-12-28-keiro-workflow-generation.sql"+ , "2026-06-04-03-53-34-keiro-subscription-shards.sql"+ , "2026-06-15-13-22-31-keiro-messaging-crash-recovery.sql"+ , "2026-06-15-15-07-25-keiro-workflows-instances.sql"+ , "2026-06-15-17-53-48-keiro-workflow-gc-index.sql"+ , "2026-06-15-18-01-33-keiro-workflows-wake-after.sql"+ , "2026-06-15-21-49-37-keiro-projection-dedup.sql"+ , "2026-07-02-00-15-48-keiro-outbox-claim-order-index.sql"+ , "2026-07-02-00-58-54-keiro-inbox-drop-received-idx.sql"+ ]++keiroCoddHistoryMappings :: NonEmpty HistoryMapping+keiroCoddHistoryMappings =+ zipWithNonEmpty mapping keiroLegacyMigrationNames nativeMigrationNames+ where+ mapping sourceFilename targetName =+ historyMapping+ (definitionInvariant (migrationId "keiro" targetName))+ (Evidence sourceKey)+ (SamePayload sourceKey)+ where+ sourceKey = definitionInvariant (first show (coddEvidenceKey sourceFilename))++frameworkCoddHistoryMappings :: NonEmpty HistoryMapping+frameworkCoddHistoryMappings =+ Kiroku.kirokuCoddHistoryMappings <> keiroCoddHistoryMappings++frameworkCoddSourceConfig ::+ ConnectionProvider ->+ Bool ->+ Text ->+ Confirmation ->+ Either CoddDefinitionError CoddSourceConfig+frameworkCoddSourceConfig sourceProvider strictSource reason confirmation =+ coddSourceConfig+ sourceProvider+ (Kiroku.kirokuLegacyMigrationNames <> keiroLegacyMigrationNames)+ strictSource+ (Kiroku.kirokuCoddSourcePayloads <> keiroCoddSourcePayloads)+ (Just combinedManifest)+ reason+ confirmation+ where+ combinedManifest =+ definitionInvariant+ (parseCoddManifest (Kiroku.kirokuCoddManifestText <> keiroCoddManifestText))++nativeMigrationNames :: NonEmpty Text+nativeMigrationNames =+ "0001-keiro-bootstrap"+ :| [ "0002-keiro-outbox"+ , "0003-keiro-inbox"+ , "0004-keiro-timer-recovery"+ , "0005-keiro-workflow-steps"+ , "0006-keiro-awakeables"+ , "0007-keiro-workflow-children"+ , "0008-keiro-workflow-generation"+ , "0009-keiro-subscription-shards"+ , "0010-keiro-messaging-crash-recovery"+ , "0011-keiro-workflows-instances"+ , "0012-keiro-workflow-gc-index"+ , "0013-keiro-workflows-wake-after"+ , "0014-keiro-projection-dedup"+ , "0015-keiro-outbox-claim-order-index"+ , "0016-keiro-inbox-drop-received-idx"+ ]++keiroCoddSourcePayloads :: Map.Map FilePath ByteString+keiroCoddSourcePayloads =+ Map.fromList+ (zip (toList keiroLegacyMigrationNames) (snd <$> toList embeddedMigrationEntries))++keiroCoddManifestText :: Text+keiroCoddManifestText = $(embedTextFile "migrations.lock")++zipWithNonEmpty :: (a -> b -> c) -> NonEmpty a -> NonEmpty b -> NonEmpty c+zipWithNonEmpty combine (firstA :| restA) (firstB :| restB) =+ combine firstA firstB :| zipWith combine restA restB++definitionInvariant :: (Show error) => Either error value -> value+definitionInvariant = either (error . ("invalid checked-in Keiro migration definition: " <>) . show) id
+ src/Keiro/Migrations/Internal/Definition.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE TemplateHaskell #-}++module Keiro.Migrations.Internal.Definition (+ embeddedMigrationEntries,+ keiroMigrations,+) where++import Data.ByteString (ByteString)+import Data.List.NonEmpty (NonEmpty)+import Data.Set qualified as Set+import Database.PostgreSQL.Migrate (+ DefinitionError,+ MigrationComponent,+ migrationComponentFromEmbeddedSql,+ )+import Database.PostgreSQL.Migrate.Embed (embedMigrationManifest)++embeddedMigrationEntries :: NonEmpty (FilePath, ByteString)+embeddedMigrationEntries =+ $(embedMigrationManifest "migrations/manifest")++keiroMigrations :: Either DefinitionError MigrationComponent+keiroMigrations =+ migrationComponentFromEmbeddedSql+ "keiro"+ (Set.singleton "kiroku")+ embeddedMigrationEntries
+ src/Keiro/Migrations/Internal/EmbedFile.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE TemplateHaskell #-}++module Keiro.Migrations.Internal.EmbedFile (embedTextFile) where++import Data.ByteString qualified as ByteString+import Data.Text qualified as Text+import Data.Text.Encoding qualified as Text.Encoding+import Language.Haskell.TH (Exp (..), Lit (..), Q)+import Language.Haskell.TH.Syntax qualified as TH++embedTextFile :: FilePath -> Q Exp+embedTextFile inputPath = do+ path <- TH.makeRelativeToProject inputPath+ TH.addDependentFile path+ bytes <- TH.runIO (ByteString.readFile path)+ case Text.Encoding.decodeUtf8' bytes of+ Left decodeError -> fail ("invalid UTF-8 in " <> path <> ": " <> show decodeError)+ Right contents ->+ pure (AppE (VarE 'Text.pack) (LitE (StringL (Text.unpack contents))))
+ src/Keiro/Migrations/LegacyCodd.hs view
@@ -0,0 +1,118 @@+{-# LANGUAGE TemplateHaskell #-}++{- | Transitional Codd-only tools retained for expected-schema snapshots,+remediation drills, and historical ledger fixups.++Normal migration execution uses 'Keiro.Migrations' and does not build this+module unless the @legacy-codd-tools@ Cabal flag is enabled.+-}+module Keiro.Migrations.LegacyCodd (+ LedgerSchema (..),+ MigrationStatus (..),+ VerifyOutcome (..),+ embeddedMigrationNames,+ embeddedMigrationSources,+ kirokuEmbeddedMigrationNames,+ migrationStatus,+ missingMigrations,+ runAllKeiroMigrations,+ runAllKeiroMigrationsNoCheck,+ runKirokuMigrationsNoCheck,+ verifySchema,+) where++import Codd (ApplyResult, CoddSettings (..), VerifySchemas)+import Codd.Extras.Ledger (LedgerSchema (..), MigrationStatus (..), VerifyOutcome (..))+import Codd.Extras.MigrationSet (MigrationSet)+import Codd.Extras.MigrationSet qualified as MigrationSet+import Control.Monad (void)+import Data.ByteString (ByteString)+import Data.FileEmbed (embedDir)+import Data.Foldable (toList)+import Data.Map.Strict qualified as Map+import Data.Time (DiffTime)+import Keiro.Migrations.ExpectedSchema (expectedSchemaFiles)+import Keiro.Migrations.History.Codd (keiroLegacyMigrationNames)+import Kiroku.Store.Migrations.History.Codd qualified as Kiroku++runAllKeiroMigrations :: CoddSettings -> DiffTime -> VerifySchemas -> IO ApplyResult+runAllKeiroMigrations settings connectTimeout verifySchemas =+ MigrationSet.applyMigrationSets settings connectTimeout verifySchemas frameworkMigrationSets++runAllKeiroMigrationsNoCheck :: CoddSettings -> DiffTime -> IO ()+runAllKeiroMigrationsNoCheck settings connectTimeout =+ void $ MigrationSet.applyMigrationSetsNoCheck settings connectTimeout frameworkMigrationSets++runKirokuMigrationsNoCheck :: CoddSettings -> DiffTime -> IO ()+runKirokuMigrationsNoCheck settings connectTimeout =+ void $ MigrationSet.applyMigrationSetNoCheck settings connectTimeout kirokuMigrationSet++verifySchema :: CoddSettings -> DiffTime -> IO VerifyOutcome+verifySchema =+ MigrationSet.verifyExpectedSchema+ expectedLedgerNames+ MigrationSet.ExpectedSchema+ { MigrationSet.label = "keiro-expected-schema"+ , MigrationSet.files = expectedSchemaFiles+ }++missingMigrations :: CoddSettings -> DiffTime -> IO [FilePath]+missingMigrations settings connectTimeout =+ MigrationSet.missingMigrationsForNames expectedLedgerNames (migsConnString settings) connectTimeout++migrationStatus :: CoddSettings -> DiffTime -> IO MigrationStatus+migrationStatus settings connectTimeout =+ MigrationSet.migrationStatusForNames expectedLedgerNames (migsConnString settings) connectTimeout++frameworkMigrationSets :: [MigrationSet]+frameworkMigrationSets =+ [ kirokuMigrationSet+ , keiroMigrationSet+ ]++kirokuMigrationSet :: MigrationSet+kirokuMigrationSet =+ MigrationSet.MigrationSet+ { MigrationSet.label = "Kiroku legacy evidence"+ , MigrationSet.files = sourceFiles Kiroku.kirokuLegacyMigrationNames Kiroku.kirokuCoddSourcePayloads+ }++keiroMigrationSet :: MigrationSet+keiroMigrationSet =+ MigrationSet.MigrationSet+ { MigrationSet.label = "Keiro legacy evidence"+ , MigrationSet.files = embeddedMigrationFiles+ }++sourceFiles ::+ (Foldable collection) =>+ collection FilePath ->+ Map.Map FilePath ByteString ->+ [(FilePath, ByteString)]+sourceFiles names payloads =+ [ (name, requirePayload name)+ | name <- toList names+ ]+ where+ requirePayload name =+ case Map.lookup name payloads of+ Just payload -> payload+ Nothing -> error ("missing checked-in legacy payload for " <> name)++embeddedMigrationFiles :: [(FilePath, ByteString)]+embeddedMigrationFiles = $(embedDir "sql-migrations")++embeddedMigrationSources :: [(FilePath, ByteString)]+embeddedMigrationSources = embeddedMigrationFiles++embeddedMigrationNames :: [FilePath]+embeddedMigrationNames =+ MigrationSet.migrationNames keiroMigrationSet++kirokuEmbeddedMigrationNames :: [FilePath]+kirokuEmbeddedMigrationNames =+ MigrationSet.migrationNames kirokuMigrationSet++expectedLedgerNames :: [FilePath]+expectedLedgerNames =+ MigrationSet.migrationNamesForSets frameworkMigrationSets
+ src/Keiro/Migrations/New.hs view
@@ -0,0 +1,51 @@+{- | Generate a new timestamped Keiro migration skeleton.++The embedded migrations are ordered by their @YYYY-MM-DD-HH-MM-SS-slug.sql@+file names (lexicographic order == chronological order because every field is+fixed-width and zero-padded). 'newMigrationFile' stamps the /real/ current UTC+time, so two migrations authored at different moments can never collide and+always sort in authoring order -- no hand-assigned slots to coordinate.+-}+module Keiro.Migrations.New (+ newMigrationFile,+ defaultMigrationsDir,+ migrationFileName,+ migrationSlug,+ migrationTemplate,+) where++import Codd.Extras.New qualified as New+import Data.Time (UTCTime)++defaultMigrationsDir :: FilePath+defaultMigrationsDir = New.defaultMigrationsDir++newMigrationFile :: FilePath -> String -> IO FilePath+newMigrationFile = New.newMigrationFile migrationFileConfig++migrationFileName :: UTCTime -> String -> FilePath+migrationFileName = New.migrationFileName migrationFileConfig++migrationSlug :: String -> String+migrationSlug = New.migrationSlug (Just "keiro")++migrationTemplate :: String -> String+migrationTemplate description =+ unlines+ [ "-- " <> description+ , "--"+ , "-- Create objects fully qualified in the keiro schema (no session path pin)."+ , "-- Example:"+ , "-- CREATE TABLE IF NOT EXISTS keiro.keiro_example ("+ , "-- id UUID PRIMARY KEY"+ , "-- );"+ , ""+ , "-- TODO: write the migration body. Prefer idempotent DDL (IF NOT EXISTS)."+ ]++migrationFileConfig :: New.MigrationFileConfig+migrationFileConfig =+ New.MigrationFileConfig+ { New.migrationSlugPrefix = Just "keiro"+ , New.migrationTemplate = migrationTemplate+ }
+ test-legacy/Main.hs view
@@ -0,0 +1,689 @@+module Main (+ main,+)+where++import Codd (ApplyResult (..), CoddSettings (..), VerifySchemas (LaxCheck, StrictCheck))+import Codd.Extras.Guards+import Codd.Parsing (connStringParser)+import Codd.Types (ConnectionString, SchemaAlgo (..), SchemaSelection (..), SqlSchema (..), TxnIsolationLvl (..), singleTryPolicy)+import Contravariant.Extras (contrazip3)+import Control.Concurrent.Async (concurrently)+import Control.Exception (finally)+import Control.Monad (filterM)+import Data.Attoparsec.Text (endOfInput, parseOnly)+import Data.Int (Int32)+import Data.List (isSuffixOf, sort)+import Data.Text (Text)+import Data.Text qualified as T+import Data.Text.IO qualified as TIO+import Data.Time (UTCTime (..), fromGregorian, secondsToDiffTime)+import EphemeralPg qualified as Pg+import Hasql.Connection.Settings qualified as Conn+import Hasql.Decoders qualified as D+import Hasql.Encoders qualified as E+import Hasql.Pool qualified as Pool+import Hasql.Pool.Config qualified as Pool.Config+import Hasql.Session qualified as Session+import Hasql.Statement (Statement, preparable)+import Keiro.Migrations.LegacyCodd (+ MigrationStatus (..),+ VerifyOutcome (..),+ embeddedMigrationNames,+ embeddedMigrationSources,+ kirokuEmbeddedMigrationNames,+ migrationStatus,+ missingMigrations,+ runAllKeiroMigrations,+ runAllKeiroMigrationsNoCheck,+ runKirokuMigrationsNoCheck,+ verifySchema,+ )+import Keiro.Migrations.New (migrationFileName, migrationSlug, newMigrationFile)+import System.Directory (doesDirectoryExist, doesFileExist, listDirectory)+import System.FilePath (takeFileName)+import System.IO.Temp (withSystemTempDirectory)+import Test.Hspec++{- | Pin the ephemeral PostgreSQL superuser to the fixed name @keiro@ so the+captured snapshot identity (roles, database owner, per-object owners) is+deterministic across machines and CI rather than the local OS username. This is+the portability fix for the strict drift gate.+-}+keiroPgConfig :: Pg.Config+keiroPgConfig = Pg.defaultConfig{Pg.user = "keiro"}++{- | Start a cached ephemeral server whose PostgreSQL superuser is the fixed+name @keiro@. Mirrors 'Pg.withCached' but pins the user; 'Pg.withCachedConfig'+is not exported, so we use 'Pg.startCached' + 'finally'.+-}+withKeiroPg :: (Pg.Database -> IO a) -> IO (Either Pg.StartError a)+withKeiroPg action = do+ started <- Pg.startCached keiroPgConfig Pg.defaultCacheConfig+ case started of+ Left err -> pure (Left err)+ Right db -> Right <$> (action db `finally` Pg.stop db)++main :: IO ()+main =+ hspec $ do+ migrationFileNameSpec+ migrationIntegritySpec+ scaffolderSpec+ migrationUpgradeSpec+ describe "Keiro codd migrations" $ do+ it "applies Kiroku and Keiro migrations to a fresh database and is repeatable" $ do+ result <- withKeiroPg $ \db -> do+ let connStr = Pg.connectionString db+ coddSettings = testCoddSettings connStr "keiro-migrations/expected-schema"++ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ assertTablesExist connStr "kiroku" kirokuTables+ assertTablesExist connStr "keiro" keiroTables+ assertTablesAbsent connStr "kiroku" keiroTables+ assertTablesAbsent connStr "public" keiroTables+ assertTablesAbsent connStr "public" kirokuTables++ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ assertTablesExist connStr "kiroku" kirokuTables+ assertTablesExist connStr "keiro" keiroTables+ assertTablesAbsent connStr "kiroku" keiroTables+ assertTablesAbsent connStr "public" keiroTables+ assertColumnExists connStr "keiro" "keiro_timers" "last_error"++ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++ it "matches the checked-in expected schema" $ do+ expectedSchemaDir <- findExpectedSchemaDir+ result <- withKeiroPg $ \db -> do+ let coddSettings = testCoddSettings (Pg.connectionString db) expectedSchemaDir+ runAllKeiroMigrations coddSettings (secondsToDiffTime 5) StrictCheck++ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right (SchemasMatch _) -> pure ()+ Right SchemasNotVerified -> expectationFailure "StrictCheck did not verify schemas"+ Right (SchemasDiffer _) -> expectationFailure "StrictCheck returned a schema mismatch without throwing"++ it "reports schema drift under LaxCheck" $ do+ expectedSchemaDir <- findExpectedSchemaDir+ result <- withKeiroPg $ \db -> do+ let connStr = Pg.connectionString db+ coddSettings = testCoddSettings connStr expectedSchemaDir+ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ runDb+ connStr+ "drift drill"+ (Session.script "ALTER TABLE keiro.keiro_timers ALTER COLUMN last_error SET NOT NULL;")+ runAllKeiroMigrations coddSettings (secondsToDiffTime 5) LaxCheck++ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right (SchemasDiffer _) -> pure ()+ Right SchemasNotVerified -> expectationFailure "LaxCheck did not verify schemas"+ Right (SchemasMatch _) -> expectationFailure "LaxCheck did not report schema drift"++{- | Guard against the recurring mistake of hand-assigning rounded, sentinel+migration timestamps (e.g. @2026-05-17-00-00-00-...@, @...-01-00-00-...@).+Migrations must be created with @keiro-migrate new@ ("Keiro.Migrations.New"),+which stamps the real current UTC time to the second, so filenames sort in true+authoring order and never collide in codd's timestamp-keyed ledger.+-}+migrationFileNameSpec :: Spec+migrationFileNameSpec =+ describe "migration file names" $ do+ it "carry real UTC authoring timestamps, not hand-assigned sentinels" $ do+ files <- migrationFiles+ files `shouldNotBe` []+ sentinelViolations files `shouldHaveNoViolations` "sentinel timestamp violations"++ it "have unique, strictly increasing timestamps" $ do+ files <- migrationFiles+ duplicateTimestampViolations files `shouldHaveNoViolations` "duplicate timestamp violations"++migrationIntegritySpec :: Spec+migrationIntegritySpec =+ describe "migration integrity guards" $ do+ it "embeds exactly the checked-in sql-migrations directory" $ do+ diskNames <- sort <$> migrationFiles+ embeddedMigrationNames `shouldBe` diskNames++ it "matches the checked-in SHA-256 manifest" $ do+ manifestPath <- findLockfile+ parsed <- parseChecksumManifest <$> TIO.readFile manifestPath+ case parsed of+ Left err -> expectationFailure (T.unpack err)+ Right manifest ->+ checksumViolations manifest embeddedMigrationSources+ `shouldHaveNoViolations` "checksum manifest violations"++ it "keeps future migration bodies schema-qualified and codd-safe" $ do+ lintViolations+ LintConfig+ { requiredQualifier = "keiro."+ , exemptFiles = []+ }+ embeddedMigrationSources+ `shouldHaveNoViolations` "migration body lint violations"++ it "keeps timestamps unique across the combined Kiroku and Keiro ledger" $ do+ duplicateTimestampViolations expectedLedgerNames+ `shouldHaveNoViolations` "combined-ledger duplicate timestamp violations"++ it "records every embedded Kiroku and Keiro migration in the codd v5 ledger" $ do+ result <- withKeiroPg $ \db -> do+ let connStr = Pg.connectionString db+ coddSettings = testCoddSettings connStr "keiro-migrations/expected-schema"+ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ schema <- detectLedgerSchema connStr+ schema `shouldBe` "codd"+ names <- ledgerNames connStr schema+ names `shouldBe` map T.pack expectedLedgerNames+ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++ it "serializes concurrent combined applies with the shared advisory lock" $ do+ result <- withKeiroPg $ \db -> do+ let connStr = Pg.connectionString db+ coddSettings = testCoddSettings connStr "keiro-migrations/expected-schema"+ concurrently+ (runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5))+ (runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5))+ schema <- detectLedgerSchema connStr+ names <- ledgerNames connStr schema+ names `shouldBe` map T.pack expectedLedgerNames+ count <- ledgerRowCount connStr schema+ count `shouldBe` fromIntegral (length expectedLedgerNames)+ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++ it "reports every embedded migration as pending on an empty database" $ do+ result <- withKeiroPg $ \db -> do+ let coddSettings = testCoddSettings (Pg.connectionString db) "keiro-migrations/expected-schema"+ verifySchema coddSettings (secondsToDiffTime 5) `shouldReturn` VerifyPending expectedLedgerNames+ status <- migrationStatus coddSettings (secondsToDiffTime 5)+ statusApplied status `shouldBe` []+ statusPending status `shouldBe` expectedLedgerNames+ missingMigrations coddSettings (secondsToDiffTime 5) `shouldReturn` expectedLedgerNames+ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++ it "reports only Keiro migrations as pending after Kiroku-only apply" $ do+ result <- withKeiroPg $ \db -> do+ let coddSettings = testCoddSettings (Pg.connectionString db) "keiro-migrations/expected-schema"+ runKirokuMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ verifySchema coddSettings (secondsToDiffTime 5) `shouldReturn` VerifyPending embeddedMigrationNames+ status <- migrationStatus coddSettings (secondsToDiffTime 5)+ map fst (statusApplied status) `shouldBe` kirokuEmbeddedMigrationNames+ statusPending status `shouldBe` embeddedMigrationNames+ missingMigrations coddSettings (secondsToDiffTime 5) `shouldReturn` embeddedMigrationNames+ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++ it "verifies the embedded Keiro expected schema after combined apply" $ do+ result <- withKeiroPg $ \db -> do+ let coddSettings = testCoddSettings (Pg.connectionString db) "keiro-migrations/expected-schema"+ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ verifySchema coddSettings (secondsToDiffTime 5) `shouldReturn` VerifySucceeded+ status <- migrationStatus coddSettings (secondsToDiffTime 5)+ map fst (statusApplied status) `shouldBe` expectedLedgerNames+ statusPending status `shouldBe` []+ missingMigrations coddSettings (secondsToDiffTime 5) `shouldReturn` []+ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++ it "reports Keiro schema drift without applying migrations" $ do+ result <- withKeiroPg $ \db -> do+ let connStr = Pg.connectionString db+ coddSettings = testCoddSettings connStr "keiro-migrations/expected-schema"+ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ beforeCount <- ledgerRowCount connStr "codd"+ runDb connStr "verify drift mutation" (Session.script "CREATE TABLE keiro.verify_drift (id int);")+ verifySchema coddSettings (secondsToDiffTime 5) `shouldReturn` VerifyFailed+ afterCount <- ledgerRowCount connStr "codd"+ afterCount `shouldBe` beforeCount+ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++ it "realigns historical sentinel ledger rows before a repeat migrate" $ do+ fixupPath <- findLedgerFixup+ fixupScript <- TIO.readFile fixupPath+ result <- withKeiroPg $ \db -> do+ let connStr = Pg.connectionString db+ coddSettings = testCoddSettings connStr "keiro-migrations/expected-schema"+ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ schema <- detectLedgerSchema connStr+ rewindKeiroLedgerToSentinelNames connStr schema+ sentinelNames <- ledgerNames connStr schema+ sentinelNames `shouldSatisfy` any (`elem` map oldLedgerName keiroLedgerRemaps)+ runDb connStr "keiro ledger fixup script" (Session.script fixupScript)+ fixedNames <- ledgerNames connStr schema+ fixedNames `shouldBe` map T.pack expectedLedgerNames+ beforeCount <- ledgerRowCount connStr schema+ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ afterCount <- ledgerRowCount connStr schema+ afterCount `shouldBe` beforeCount+ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++{- | Prove the scaffolder (`Keiro.Migrations.New`) is the producer that satisfies+the reactive filename guard. The deterministic check proves the slug convention;+the temp-dir check proves the live writer creates a schema-qualified template.+-}+scaffolderSpec :: Spec+scaffolderSpec =+ describe "migration scaffolder" $ do+ it "stamps a real, non-sentinel UTC timestamp and a keiro-prefixed slug" $ do+ let sampled = UTCTime (fromGregorian 2026 7 5) (secondsToDiffTime (19 * 3600 + 9 * 60 + 18))+ name = migrationFileName sampled "Add widget index"+ takeFileName name `shouldBe` name+ isTimestampShaped (take timestampWidth name) `shouldBe` True+ handAssignedTimestamp name `shouldBe` False+ migrationSlug "Add widget index" `shouldBe` "keiro-add-widget-index"++ it "writes a well-named file into a temp dir with a qualified template" $+ withSystemTempDirectory "keiro-scaffolder" $ \dir -> do+ path <- newMigrationFile dir "add widget index"+ let base = takeFileName path+ isTimestampShaped (take timestampWidth base) `shouldBe` True+ length base `shouldSatisfy` (> timestampWidth)+ body <- TIO.readFile path+ (".sql" `isSuffixOf` path) `shouldBe` True+ ("keiro.keiro_example" `T.isInfixOf` body) `shouldBe` True+ ("search_path" `T.isInfixOf` body) `shouldBe` False++migrationUpgradeSpec :: Spec+migrationUpgradeSpec =+ describe "keiro migration upgrade artifacts" $ do+ it "remediates a 0.1.0.0-style kiroku-schema layout without losing rows" $ do+ remediationPath <- findRemediationScript+ remediationScript <- TIO.readFile remediationPath+ expectedSchemaDir <- findExpectedSchemaDir+ result <- withKeiroPg $ \db -> do+ let connStr = Pg.connectionString db+ coddSettings = testCoddSettings connStr expectedSchemaDir+ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ schema <- detectLedgerSchema connStr+ moveKeiroTablesBackToKiroku connStr+ seedRemediationRows connStr+ runDb connStr "keiro schema remediation script" (Session.script remediationScript)++ assertTablesExist connStr "keiro" keiroTables+ assertTablesAbsent connStr "kiroku" keiroTables+ assertSnapshotRowSurvived connStr+ assertTimerRowSurvived connStr++ beforeCount <- ledgerRowCount connStr schema+ runAllKeiroMigrationsNoCheck coddSettings (secondsToDiffTime 5)+ afterCount <- ledgerRowCount connStr schema+ afterCount `shouldBe` beforeCount++ strictResult <- runAllKeiroMigrations coddSettings (secondsToDiffTime 5) StrictCheck+ case strictResult of+ SchemasMatch _ -> pure ()+ SchemasNotVerified -> expectationFailure "StrictCheck did not verify remediated schemas"+ SchemasDiffer _ -> expectationFailure "StrictCheck returned a schema mismatch after remediation"++ runDb connStr "idempotent keiro schema remediation script" (Session.script remediationScript)+ assertTablesExist connStr "keiro" keiroTables+ assertTablesAbsent connStr "kiroku" keiroTables+ assertSnapshotRowSurvived connStr+ assertTimerRowSurvived connStr+ case result of+ Left err -> expectationFailure ("Failed to start ephemeral PostgreSQL: " <> show err)+ Right () -> pure ()++-- | The migration @.sql@ files, wherever the suite is run from.+migrationFiles :: IO [FilePath]+migrationFiles = do+ dir <- findMigrationsDir+ filter (".sql" `isSuffixOf`) <$> listDirectory dir++findMigrationsDir :: IO FilePath+findMigrationsDir = do+ let candidates = ["keiro-migrations/sql-migrations", "sql-migrations"]+ existing <- filterM doesDirectoryExist candidates+ case existing of+ dir : _ -> pure dir+ [] ->+ expectationFailure "Could not find keiro-migrations/sql-migrations"+ >> pure "keiro-migrations/sql-migrations"++findExpectedSchemaDir :: IO FilePath+findExpectedSchemaDir = do+ let candidates =+ [ "keiro-migrations/expected-schema"+ , "expected-schema"+ ]+ existing <- filterM doesDirectoryExist candidates+ case existing of+ dir : _ -> pure dir+ [] ->+ expectationFailure "Could not find keiro-migrations/expected-schema"+ >> pure "keiro-migrations/expected-schema"++findLockfile :: IO FilePath+findLockfile = findExistingFile ["keiro-migrations/migrations.lock", "migrations.lock"]++findLedgerFixup :: IO FilePath+findLedgerFixup =+ findExistingFile+ [ "keiro-migrations/ledger-fixups/2026-07-05-realign-keiro-migration-timestamps.sql"+ , "ledger-fixups/2026-07-05-realign-keiro-migration-timestamps.sql"+ ]++findRemediationScript :: IO FilePath+findRemediationScript =+ findExistingFile+ [ "keiro-migrations/remediation/2026-07-05-relocate-keiro-tables-to-keiro-schema.sql"+ , "remediation/2026-07-05-relocate-keiro-tables-to-keiro-schema.sql"+ ]++findExistingFile :: [FilePath] -> IO FilePath+findExistingFile candidates = do+ existing <- filterM doesFileExist candidates+ case existing of+ path : _ -> pure path+ [] -> expectationFailure ("Could not find any of: " <> show candidates) >> pure fallback+ where+ fallback =+ case candidates of+ path : _ -> path+ [] -> "."++expectedLedgerNames :: [FilePath]+expectedLedgerNames = sort (kirokuEmbeddedMigrationNames <> embeddedMigrationNames)++-- | Kiroku's own event-store tables, which remain in the kiroku schema.+kirokuTables :: [Text]+kirokuTables =+ [ "events"+ , "stream_events"+ , "streams"+ , "subscriptions"+ ]++-- | Keiro's framework tables, which live in the dedicated keiro schema.+keiroTables :: [Text]+keiroTables =+ [ "keiro_awakeables"+ , "keiro_inbox"+ , "keiro_outbox"+ , "keiro_projection_dedup"+ , "keiro_read_models"+ , "keiro_snapshots"+ , "keiro_subscription_shards"+ , "keiro_timers"+ , "keiro_workflow_children"+ , "keiro_workflow_steps"+ , "keiro_workflows"+ ]++testCoddSettings :: Text -> FilePath -> CoddSettings+testCoddSettings connStr expectedSchemaDir =+ CoddSettings+ { migsConnString = parseConnString connStr+ , sqlMigrations = []+ , onDiskReps = Left expectedSchemaDir+ , namespacesToCheck = IncludeSchemas [SqlSchema "keiro"]+ , extraRolesToCheck = []+ , retryPolicy = singleTryPolicy+ , txnIsolationLvl = DbDefault+ , schemaAlgoOpts = SchemaAlgo False False False+ }++parseConnString :: Text -> ConnectionString+parseConnString connStr =+ case parseOnly (connStringParser <* endOfInput) connStr of+ Left err -> error ("Could not parse ephemeral PostgreSQL connection string for codd: " <> err)+ Right parsed -> parsed++shouldHaveNoViolations :: [Text] -> String -> Expectation+shouldHaveNoViolations [] _ = pure ()+shouldHaveNoViolations violations label =+ expectationFailure (label <> ":\n" <> T.unpack (T.unlines violations))++runDb :: Text -> String -> Session.Session a -> IO a+runDb connStr label session = do+ pool <- Pool.acquire poolConfig+ result <- Pool.use pool session+ Pool.release pool+ case result of+ Left err -> expectationFailure (label <> " failed: " <> show err) >> fail label+ Right value -> pure value+ where+ poolConfig =+ Pool.Config.settings+ [ Pool.Config.staticConnectionSettings (Conn.connectionString connStr)+ , Pool.Config.size 1+ ]++detectLedgerSchema :: Text -> IO Text+detectLedgerSchema connStr = do+ (hasCodd, hasCoddSchema) <- runDb connStr "ledger schema detection" (Session.statement () ledgerSchemaStmt)+ case (hasCodd, hasCoddSchema) of+ (True, False) -> pure "codd"+ (False, True) -> pure "codd_schema"+ (False, False) -> expectationFailure "codd ledger table was not found" >> pure "codd"+ (True, True) -> expectationFailure "both codd and codd_schema ledger tables exist" >> pure "codd"++ledgerSchemaStmt :: Statement () (Bool, Bool)+ledgerSchemaStmt =+ preparable+ "SELECT to_regclass('codd.sql_migrations') IS NOT NULL, to_regclass('codd_schema.sql_migrations') IS NOT NULL"+ E.noParams+ (D.singleRow ((,) <$> D.column (D.nonNullable D.bool) <*> D.column (D.nonNullable D.bool)))++ledgerNames :: Text -> Text -> IO [Text]+ledgerNames connStr "codd" = runDb connStr "codd ledger names" (Session.statement () ledgerNamesCoddStmt)+ledgerNames connStr "codd_schema" = runDb connStr "codd_schema ledger names" (Session.statement () ledgerNamesCoddSchemaStmt)+ledgerNames _ schema = expectationFailure ("unknown ledger schema " <> T.unpack schema) >> pure []++ledgerNamesCoddStmt :: Statement () [Text]+ledgerNamesCoddStmt =+ preparable+ "SELECT name::text FROM codd.sql_migrations ORDER BY name"+ E.noParams+ (D.rowList (D.column (D.nonNullable D.text)))++ledgerNamesCoddSchemaStmt :: Statement () [Text]+ledgerNamesCoddSchemaStmt =+ preparable+ "SELECT name::text FROM codd_schema.sql_migrations ORDER BY name"+ E.noParams+ (D.rowList (D.column (D.nonNullable D.text)))++ledgerRowCount :: Text -> Text -> IO Int32+ledgerRowCount connStr "codd" = runDb connStr "codd ledger row count" (Session.statement () ledgerCountCoddStmt)+ledgerRowCount connStr "codd_schema" = runDb connStr "codd_schema ledger row count" (Session.statement () ledgerCountCoddSchemaStmt)+ledgerRowCount _ schema = expectationFailure ("unknown ledger schema " <> T.unpack schema) >> pure 0++ledgerCountCoddStmt :: Statement () Int32+ledgerCountCoddStmt =+ preparable+ "SELECT count(*)::int FROM codd.sql_migrations"+ E.noParams+ (D.singleRow (D.column (D.nonNullable D.int4)))++ledgerCountCoddSchemaStmt :: Statement () Int32+ledgerCountCoddSchemaStmt =+ preparable+ "SELECT count(*)::int FROM codd_schema.sql_migrations"+ E.noParams+ (D.singleRow (D.column (D.nonNullable D.int4)))++data KeiroLedgerRemap = KeiroLedgerRemap+ { newLedgerName :: Text+ , oldLedgerName :: Text+ , oldLedgerTimestamp :: Text+ }+ deriving stock (Eq, Show)++keiroLedgerRemaps :: [KeiroLedgerRemap]+keiroLedgerRemaps =+ [ KeiroLedgerRemap "2026-05-17-13-58-15-keiro-bootstrap.sql" "2026-05-17-00-00-00-keiro-bootstrap.sql" "2026-05-17 00:00:00+00"+ , KeiroLedgerRemap "2026-05-19-12-55-02-keiro-outbox.sql" "2026-05-17-01-00-00-keiro-outbox.sql" "2026-05-17 01:00:00+00"+ , KeiroLedgerRemap "2026-05-19-13-05-23-keiro-inbox.sql" "2026-05-17-02-00-00-keiro-inbox.sql" "2026-05-17 02:00:00+00"+ , KeiroLedgerRemap "2026-06-03-05-14-28-keiro-timer-recovery.sql" "2026-05-17-03-00-00-keiro-timer-recovery.sql" "2026-05-17 03:00:00+00"+ , KeiroLedgerRemap "2026-06-03-16-10-05-keiro-workflow-steps.sql" "2026-06-03-00-00-00-keiro-workflow-steps.sql" "2026-06-03 00:00:00+00"+ , KeiroLedgerRemap "2026-06-03-18-19-41-keiro-awakeables.sql" "2026-06-03-01-00-00-keiro-awakeables.sql" "2026-06-03 01:00:00+00"+ , KeiroLedgerRemap "2026-06-03-19-49-23-keiro-workflow-children.sql" "2026-06-03-02-00-00-keiro-workflow-children.sql" "2026-06-03 02:00:00+00"+ , KeiroLedgerRemap "2026-06-04-02-12-28-keiro-workflow-generation.sql" "2026-06-05-00-00-00-keiro-workflow-generation.sql" "2026-06-05 00:00:00+00"+ , KeiroLedgerRemap "2026-06-04-03-53-34-keiro-subscription-shards.sql" "2026-06-05-01-00-00-keiro-subscription-shards.sql" "2026-06-05 01:00:00+00"+ , KeiroLedgerRemap "2026-06-15-15-07-25-keiro-workflows-instances.sql" "2026-06-11-00-00-04-keiro-workflows-instances.sql" "2026-06-11 00:00:04+00"+ , KeiroLedgerRemap "2026-06-15-17-53-48-keiro-workflow-gc-index.sql" "2026-06-15-22-10-00-keiro-workflow-gc-index.sql" "2026-06-15 22:10:00+00"+ , KeiroLedgerRemap "2026-06-15-18-01-33-keiro-workflows-wake-after.sql" "2026-06-15-22-20-00-keiro-workflows-wake-after.sql" "2026-06-15 22:20:00+00"+ , KeiroLedgerRemap "2026-07-02-00-15-48-keiro-outbox-claim-order-index.sql" "2026-07-02-00-12-00-keiro-outbox-claim-order-index.sql" "2026-07-02 00:12:00+00"+ , KeiroLedgerRemap "2026-07-02-00-58-54-keiro-inbox-drop-received-idx.sql" "2026-07-02-00-55-00-keiro-inbox-drop-received-idx.sql" "2026-07-02 00:55:00+00"+ ]++rewindKeiroLedgerToSentinelNames :: Text -> Text -> IO ()+rewindKeiroLedgerToSentinelNames connStr schema =+ runDb connStr "keiro ledger rewind to sentinel names" (Session.script script)+ where+ qname = schema <> ".sql_migrations"+ -- Kept in sync with ledger-fixups/2026-07-05-realign-keiro-migration-timestamps.sql.+ script =+ T.unlines+ [ "UPDATE " <> qname <> " SET name = '" <> oldName <> "', migration_timestamp = '" <> oldTimestamp <> "' WHERE name = '" <> newName <> "';"+ | KeiroLedgerRemap newName oldName oldTimestamp <- keiroLedgerRemaps+ ]++moveKeiroTablesBackToKiroku :: Text -> IO ()+moveKeiroTablesBackToKiroku connStr =+ runDb connStr "move keiro tables back to kiroku schema" (Session.script script)+ where+ tableArray = T.intercalate ", " ["'" <> table <> "'" | table <- keiroTables]+ script =+ T.unlines+ [ "DO $$"+ , "DECLARE"+ , " t text;"+ , " tables text[] := ARRAY[" <> tableArray <> "];"+ , "BEGIN"+ , " FOREACH t IN ARRAY tables LOOP"+ , " IF to_regclass('keiro.' || t) IS NOT NULL THEN"+ , " EXECUTE format('ALTER TABLE keiro.%I SET SCHEMA kiroku', t);"+ , " END IF;"+ , " END LOOP;"+ , "END"+ , "$$;"+ , "DROP SCHEMA IF EXISTS keiro;"+ ]++seedRemediationRows :: Text -> IO ()+seedRemediationRows connStr =+ runDb connStr "seed 0.1.0.0-layout keiro rows" (Session.script script)+ where+ script =+ """+ INSERT INTO kiroku.keiro_snapshots+ (stream_id, stream_version, state, state_codec_version, regfile_shape_hash)+ VALUES+ (4242, 7, '{"ok": true}'::jsonb, 3, 'shape-abc');++ INSERT INTO kiroku.keiro_timers+ (timer_id, process_manager_name, correlation_id, fire_at, payload, status)+ VALUES+ ('00000000-0000-4000-8000-000000000001', 'remediation-test', 'corr-1',+ '2026-07-06 00:00:00+00', '{"wake": true}'::jsonb, 'scheduled');+ """++assertSnapshotRowSurvived :: Text -> IO ()+assertSnapshotRowSurvived connStr = do+ present <- runDb connStr "snapshot survival query" (Session.statement () snapshotSurvivedStmt)+ present `shouldBe` True++snapshotSurvivedStmt :: Statement () Bool+snapshotSurvivedStmt =+ preparable+ """+ SELECT EXISTS (+ SELECT 1+ FROM keiro.keiro_snapshots+ WHERE stream_id = 4242+ AND stream_version = 7+ AND state = '{"ok": true}'::jsonb+ AND state_codec_version = 3+ AND regfile_shape_hash = 'shape-abc'+ )+ """+ E.noParams+ (D.singleRow (D.column (D.nonNullable D.bool)))++assertTimerRowSurvived :: Text -> IO ()+assertTimerRowSurvived connStr = do+ present <- runDb connStr "timer survival query" (Session.statement () timerSurvivedStmt)+ present `shouldBe` True++timerSurvivedStmt :: Statement () Bool+timerSurvivedStmt =+ preparable+ """+ SELECT EXISTS (+ SELECT 1+ FROM keiro.keiro_timers+ WHERE timer_id = '00000000-0000-4000-8000-000000000001'+ AND process_manager_name = 'remediation-test'+ AND correlation_id = 'corr-1'+ AND payload = '{"wake": true}'::jsonb+ AND status = 'scheduled'+ )+ """+ E.noParams+ (D.singleRow (D.column (D.nonNullable D.bool)))++assertTablesExist :: Text -> Text -> [Text] -> IO ()+assertTablesExist connStr schema tables = do+ actualTables <- runDb connStr "table verification query" (Session.statement schema schemaTablesStmt)+ let missing = filter (`notElem` actualTables) tables+ missing `shouldBe` []++assertTablesAbsent :: Text -> Text -> [Text] -> IO ()+assertTablesAbsent connStr schema tables = do+ actualTables <- runDb connStr "table verification query" (Session.statement schema schemaTablesStmt)+ let present = filter (`elem` actualTables) tables+ present `shouldBe` []++assertColumnExists :: Text -> Text -> Text -> Text -> IO ()+assertColumnExists connStr schema table column = do+ present <- runDb connStr "column verification query" (Session.statement (schema, table, column) columnExistsStmt)+ present `shouldBe` True++columnExistsStmt :: Statement (Text, Text, Text) Bool+columnExistsStmt =+ preparable+ """+ SELECT EXISTS (+ SELECT 1 FROM information_schema.columns+ WHERE table_schema = $1 AND table_name = $2 AND column_name = $3+ )+ """+ ( contrazip3+ (E.param (E.nonNullable E.text))+ (E.param (E.nonNullable E.text))+ (E.param (E.nonNullable E.text))+ )+ (D.singleRow (D.column (D.nonNullable D.bool)))++schemaTablesStmt :: Statement Text [Text]+schemaTablesStmt =+ preparable+ """+ SELECT table_name::text+ FROM information_schema.tables+ WHERE table_schema = $1+ AND table_type = 'BASE TABLE'+ ORDER BY table_name+ """+ (E.param (E.nonNullable E.text))+ (D.rowList (D.column (D.nonNullable D.text)))
+ test/Main.hs view
@@ -0,0 +1,426 @@+{-# LANGUAGE MultilineStrings #-}++module Main (main) where++import Control.Concurrent.Async (concurrently)+import Control.Exception (finally)+import Control.Monad (forM_)+import Data.ByteString (ByteString)+import Data.ByteString qualified as ByteString+import Data.Either (isLeft)+import Data.Foldable (toList)+import Data.Int (Int64)+import Data.List (sort)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Map.Strict qualified as Map+import Data.Set qualified as Set+import Data.Text (Text)+import Data.Text qualified as Text+import Data.Text.Encoding qualified as Text.Encoding+import Data.Text.IO qualified as Text.IO+import Database.PostgreSQL.Migrate+import Database.PostgreSQL.Migrate.History.Codd+import Database.PostgreSQL.Migrate.Internal (+ ComponentDescription (..),+ PlanDescription (..),+ componentNameText,+ migrationChecksumBytes,+ planDescription,+ )+import Database.PostgreSQL.Migrate.Test (withMigratedDatabase)+import EphemeralPg qualified as Pg+import Hasql.Connection qualified as Connection+import Hasql.Connection.Settings qualified as Settings+import Hasql.Decoders qualified as Decoders+import Hasql.Encoders qualified as Encoders+import Hasql.Session qualified as Session+import Hasql.Statement (Statement)+import Hasql.Statement qualified as Statement+import Keiro.Migrations+import Keiro.Migrations.History.Codd+import Kiroku.Store.Migrations qualified as Kiroku+import Kiroku.Store.Migrations.History.Codd qualified as Kiroku.Codd+import Numeric qualified+import System.Directory (doesDirectoryExist, doesFileExist)+import System.FilePath ((</>))+import Test.Hspec++main :: IO ()+main = hspec $ do+ describe "native Keiro migration definition" $ do+ it "tracks eighteen native files in manifest order" $ do+ directory <- findMigrationsDirectory+ manifest <- Text.lines <$> Text.IO.readFile (directory </> "manifest")+ manifest `shouldBe` Text.pack <$> nativeMigrationFiles++ it "preserves every legacy payload byte recorded by migrations.lock" $ do+ directory <- findMigrationsDirectory+ lockPath <- findLockfile+ lockEntries <- parseLockfile <$> Text.IO.readFile lockPath+ forM_ (zip (toList keiroLegacyMigrationNames) nativeMigrationFiles) $ \(legacyName, nativeName) -> do+ bytes <- ByteString.readFile (directory </> nativeName)+ lookup legacyName lockEntries `shouldBe` Just (checksumText bytes)++ it "builds component keiro with dependency kiroku and eighteen migrations" $ do+ plan <- requirePlan+ let PlanDescription components = planDescription plan+ case toList components of+ [ ComponentDescription{name = kirokuName, dependencies = kirokuDependencies, migrations = kirokuEntries}+ , ComponentDescription{name = keiroName, dependencies = keiroDependencies, migrations = keiroEntries}+ ] -> do+ componentNameText kirokuName `shouldBe` "kiroku"+ kirokuDependencies `shouldBe` mempty+ length kirokuEntries `shouldBe` 8+ componentNameText keiroName `shouldBe` "keiro"+ dependencyName <- requireRight (componentName "kiroku")+ keiroDependencies `shouldBe` Set.singleton dependencyName+ length keiroEntries `shouldBe` 18+ actual -> expectationFailure ("unexpected plan description: " <> show actual)+ validateHistoryMappingTargets plan frameworkCoddHistoryMappings `shouldBe` Right ()++ it "rejects missing and reversed Kiroku dependencies" $ do+ kiroku <- requireRight Kiroku.kirokuMigrations+ keiro <- requireRight keiroMigrations+ migrationPlan (keiro :| []) `shouldSatisfy` isLeft+ frameworkMigrationPlan keiro kiroku `shouldSatisfy` isLeft++ describe "fresh native databases" $ do+ it "applies Kiroku then Keiro, verifies strictly, and is repeatable" $ do+ plan <- requirePlan+ result <- withMigratedDatabase plan $ \connection -> do+ assertSchema connection+ let provider = providerFor connection+ rerun <- runMigrationPlanWith defaultRunOptions provider plan >>= requireRight+ reportOutcomes rerun `shouldBe` replicate 26 AlreadyApplied+ verified <- verifyMigrationPlanWith defaultRunOptions provider plan >>= requireRight+ case verified of+ VerificationReport verificationIssues applied pending unknown -> do+ verificationIssues `shouldBe` []+ length applied `shouldBe` 26+ pending `shouldBe` []+ unknown `shouldBe` []+ either (expectationFailure . show) pure result++ it "serializes concurrent composed applies" $ do+ plan <- requirePlan+ withKeiroPg $ \database -> do+ let settings = Pg.connectionSettings database+ (first, second) <-+ concurrently+ (runMigrationPlan defaultRunOptions settings plan >>= requireRight)+ (runMigrationPlan defaultRunOptions settings plan >>= requireRight)+ sort [reportOutcomes first, reportOutcomes second]+ `shouldBe` sort [replicate 26 AppliedNow, replicate 26 AlreadyApplied]++ describe "combined Codd history import" $ do+ it "imports a shared Codd V5 ledger atomically without replaying target SQL" $+ importFixture "codd"++ it "imports the legacy codd_schema ledger shape" $+ importFixture "codd_schema"++ it "rejects one partial source row before creating the target ledger" $ do+ plan <- requirePlan+ withKeiroPg $ \database -> do+ let settings = Pg.connectionSettings database+ provider = connectionProviderFromSettings settings+ withConnection settings $ \connection -> do+ applyLegacyPayloads connection+ installCoddLedger connection "codd" True False+ config <-+ requireRight+ (frameworkCoddSourceConfig provider True "partial fixture must fail" Confirmed)+ imported <-+ importCoddHistory defaultImportOptions config provider plan frameworkCoddHistoryMappings+ imported `shouldSatisfy` \case+ Left CoddPartialMigration{} -> True+ _ -> False+ withConnection settings $ \connection -> do+ targetExists <- useSession connection (Session.statement "pgmigrate" schemaExistsStatement)+ targetExists `shouldBe` False++ it "rejects unselected shared-ledger rows in strict mode" $ do+ plan <- requirePlan+ withKeiroPg $ \database -> do+ let settings = Pg.connectionSettings database+ provider = connectionProviderFromSettings settings+ withConnection settings $ \connection -> do+ applyLegacyPayloads connection+ installCoddLedger connection "codd" False True+ config <-+ requireRight+ (frameworkCoddSourceConfig provider True "strict source fixture" Confirmed)+ imported <-+ importCoddHistory defaultImportOptions config provider plan frameworkCoddHistoryMappings+ imported `shouldSatisfy` \case+ Left CoddStrictSourceHasUnselected{} -> True+ _ -> False++importFixture :: Text -> Expectation+importFixture sourceSchema = do+ plan <- requirePlan+ withKeiroPg $ \database -> do+ let settings = Pg.connectionSettings database+ provider = connectionProviderFromSettings settings+ withConnection settings $ \connection -> do+ applyLegacyPayloads connection+ installCoddLedger connection sourceSchema False False+ config <-+ requireRight+ (frameworkCoddSourceConfig provider True "verified Keiro shared-ledger cutover" Confirmed)+ first <-+ importCoddHistory defaultImportOptions config provider plan frameworkCoddHistoryMappings+ >>= requireRight+ importOutcomes first `shouldBe` replicate 23 Imported+ kirokuCanaryId <- requireRight (migrationId "kiroku" "0008-schema-management-comment")+ keiroCanaryId <- requireRight (migrationId "keiro" "0017-schema-management-comment")+ keiroDeadLettersId <- requireRight (migrationId "keiro" "0018")+ verifiedBeforeCanaries <- verifyMigrationPlan defaultRunOptions settings plan >>= requireRight+ case verifiedBeforeCanaries of+ VerificationReport verificationIssues _ _ _ ->+ verificationIssues+ `shouldBe` [ PendingMigration kirokuCanaryId+ , PendingMigration keiroCanaryId+ , PendingMigration keiroDeadLettersId+ ]+ up <- runMigrationPlan defaultRunOptions settings plan >>= requireRight+ reportOutcomes up+ `shouldBe` replicate 7 AlreadyApplied+ <> [AppliedNow]+ <> replicate 16 AlreadyApplied+ <> [AppliedNow, AppliedNow]+ verifiedAfterCanaries <- verifyMigrationPlan defaultRunOptions settings plan >>= requireRight+ case verifiedAfterCanaries of+ VerificationReport verificationIssues _ _ _ -> verificationIssues `shouldBe` []+ rerun <- runMigrationPlan defaultRunOptions settings plan >>= requireRight+ reportOutcomes rerun `shouldBe` replicate 26 AlreadyApplied+ second <-+ importCoddHistory defaultImportOptions config provider plan frameworkCoddHistoryMappings+ >>= requireRight+ importOutcomes second `shouldBe` replicate 23 AlreadyImported+ withConnection settings $ \connection -> do+ assertSchema connection+ sourceRows <- useSession connection (Session.statement () (sourceRowCountStatement sourceSchema))+ sourceRows `shouldBe` 23+ facts <- useSession connection (Session.statement () importFactsStatement)+ facts `shouldBe` (26, 23, True)++nativeMigrationFiles :: [FilePath]+nativeMigrationFiles =+ [ "0001-keiro-bootstrap.sql"+ , "0002-keiro-outbox.sql"+ , "0003-keiro-inbox.sql"+ , "0004-keiro-timer-recovery.sql"+ , "0005-keiro-workflow-steps.sql"+ , "0006-keiro-awakeables.sql"+ , "0007-keiro-workflow-children.sql"+ , "0008-keiro-workflow-generation.sql"+ , "0009-keiro-subscription-shards.sql"+ , "0010-keiro-messaging-crash-recovery.sql"+ , "0011-keiro-workflows-instances.sql"+ , "0012-keiro-workflow-gc-index.sql"+ , "0013-keiro-workflows-wake-after.sql"+ , "0014-keiro-projection-dedup.sql"+ , "0015-keiro-outbox-claim-order-index.sql"+ , "0016-keiro-inbox-drop-received-idx.sql"+ , "0017-schema-management-comment.sql"+ , "0018.sql"+ ]++findMigrationsDirectory :: IO FilePath+findMigrationsDirectory =+ findDirectory ["keiro-migrations/migrations", "migrations"]++findLockfile :: IO FilePath+findLockfile =+ findFile ["keiro-migrations/migrations.lock", "migrations.lock"]++findDirectory :: [FilePath] -> IO FilePath+findDirectory candidates = do+ existing <- filterM doesDirectoryExist candidates+ case existing of+ directory : _ -> pure directory+ [] -> expectationFailure ("could not find directory: " <> show candidates) >> pure "."++findFile :: [FilePath] -> IO FilePath+findFile candidates = do+ existing <- filterM doesFileExist candidates+ case existing of+ path : _ -> pure path+ [] -> expectationFailure ("could not find file: " <> show candidates) >> pure "."++filterM :: (value -> IO Bool) -> [value] -> IO [value]+filterM predicate = foldr step (pure [])+ where+ step value remaining = do+ matches <- predicate value+ values <- remaining+ pure (if matches then value : values else values)++parseLockfile :: Text -> [(FilePath, Text)]+parseLockfile contents =+ [ (Text.unpack filename, checksum)+ | line <- Text.lines contents+ , [checksum, filename] <- [Text.words line]+ ]++checksumText :: ByteString -> Text+checksumText =+ Text.pack+ . concatMap renderByte+ . ByteString.unpack+ . migrationChecksumBytes+ . migrationFingerprint+ where+ renderByte byte =+ case Numeric.showHex byte "" of+ [digit] -> ['0', digit]+ digits -> digits++requirePlan :: IO MigrationPlan+requirePlan = do+ kiroku <- requireRight Kiroku.kirokuMigrations+ keiro <- requireRight keiroMigrations+ requireRight (frameworkMigrationPlan kiroku keiro)++requireRight :: (Show error) => Either error value -> IO value+requireRight = either failure pure++failure :: (Show value) => value -> IO result+failure value = expectationFailure (show value) >> fail (show value)++providerFor :: Connection.Connection -> ConnectionProvider+providerFor connection = connectionProvider (\action -> Right <$> action connection)++reportOutcomes :: MigrationReport -> [MigrationOutcome]+reportOutcomes MigrationReport{results} = outcome <$> toList results++importOutcomes :: HistoryImportReport -> [HistoryImportOutcome]+importOutcomes HistoryImportReport{importResults} = importOutcome <$> toList importResults++keiroPgConfig :: Pg.Config+keiroPgConfig = Pg.defaultConfig{Pg.user = "keiro"}++withKeiroPg :: (Pg.Database -> IO ()) -> IO ()+withKeiroPg action = do+ started <- Pg.startCached keiroPgConfig Pg.defaultCacheConfig+ case started of+ Left startError -> expectationFailure (show startError)+ Right database -> action database `finally` Pg.stop database++withConnection :: Settings.Settings -> (Connection.Connection -> IO value) -> IO value+withConnection settings action = do+ acquired <- Connection.acquire settings+ connection <- requireRight acquired+ action connection `finally` Connection.release connection++useSession :: Connection.Connection -> Session.Session value -> IO value+useSession connection session =+ Connection.use connection session >>= requireRight++assertSchema :: Connection.Connection -> Expectation+assertSchema connection = do+ healthy <- useSession connection (Session.statement () schemaFactsStatement)+ healthy `shouldBe` True++schemaFactsStatement :: Statement () Bool+schemaFactsStatement =+ Statement.preparable+ """+ SELECT bool_and(ok)+ FROM (VALUES+ (to_regnamespace('kiroku') IS NOT NULL),+ (to_regclass('kiroku.events') IS NOT NULL),+ (to_regnamespace('keiro') IS NOT NULL),+ (to_regclass('keiro.keiro_inbox') IS NOT NULL),+ (to_regclass('keiro.keiro_outbox') IS NOT NULL),+ (to_regclass('keiro.keiro_timers') IS NOT NULL),+ (to_regclass('keiro.keiro_workflows') IS NOT NULL),+ (obj_description(to_regnamespace('kiroku'), 'pg_namespace') = 'Managed by pg-migrate component kiroku through 0008-schema-management-comment'),+ (obj_description(to_regnamespace('keiro'), 'pg_namespace') = 'Managed by pg-migrate component keiro through 0017-schema-management-comment')+ ) AS checks(ok)+ """+ Encoders.noParams+ (Decoders.singleRow (Decoders.column (Decoders.nonNullable Decoders.bool)))++applyLegacyPayloads :: Connection.Connection -> IO ()+applyLegacyPayloads connection = do+ apply Kiroku.Codd.kirokuLegacyMigrationNames Kiroku.Codd.kirokuCoddSourcePayloads+ apply keiroLegacyMigrationNames keiroCoddSourcePayloads+ where+ apply names payloads =+ forM_ names $ \name ->+ case Map.lookup name payloads of+ Nothing -> failure ("missing source payload " <> name)+ Just bytes -> useSession connection (Session.script (Text.Encoding.decodeUtf8 bytes))++installCoddLedger :: Connection.Connection -> Text -> Bool -> Bool -> IO ()+installCoddLedger connection sourceSchema partial includeExtra =+ useSession connection (Session.script (coddFixtureSql sourceSchema partial includeExtra))++coddFixtureSql :: Text -> Bool -> Bool -> Text+coddFixtureSql sourceSchema partial includeExtra =+ Text.unlines+ [ "CREATE SCHEMA " <> sourceSchema <> ";"+ , "CREATE TABLE " <> sourceSchema <> ".sql_migrations ("+ , " id serial NOT NULL, migration_timestamp timestamptz NOT NULL,"+ , " applied_at timestamptz, name text NOT NULL, application_duration interval,"+ , " num_applied_statements int, no_txn_failed_at timestamptz, txnid bigint, connid int"+ , ");"+ , "INSERT INTO " <> sourceSchema <> ".sql_migrations"+ , " (migration_timestamp, applied_at, name, application_duration, num_applied_statements, no_txn_failed_at, txnid, connid) VALUES"+ , Text.intercalate ",\n" (zipWith renderRow [1 :: Int ..] filenames) <> ";"+ ]+ where+ selected = toList Kiroku.Codd.kirokuLegacyMigrationNames <> toList keiroLegacyMigrationNames+ filenames = selected <> ["application-owned-extra.sql" | includeExtra]+ renderRow index filename =+ "('2026-01-01 00:00:00+00'::timestamptz + interval '"+ <> Text.pack (show index)+ <> " seconds', "+ <> appliedAt index+ <> ", '"+ <> Text.pack filename+ <> "', interval '1 second', 1, "+ <> failureAt index+ <> ", 1, 1)"+ appliedAt index+ | partial && index == 11 = "NULL"+ | otherwise = "'2026-01-01 00:01:00+00'::timestamptz + interval '" <> Text.pack (show index) <> " seconds'"+ failureAt index+ | partial && index == 11 = "'2026-01-01 00:02:00+00'::timestamptz"+ | otherwise = "NULL"++schemaExistsStatement :: Statement Text Bool+schemaExistsStatement =+ Statement.preparable+ "SELECT to_regnamespace($1) IS NOT NULL"+ (Encoders.param (Encoders.nonNullable Encoders.text))+ (Decoders.singleRow (Decoders.column (Decoders.nonNullable Decoders.bool)))++sourceRowCountStatement :: Text -> Statement () Int64+sourceRowCountStatement sourceSchema =+ Statement.unpreparable+ ("SELECT count(*) FROM " <> sourceSchema <> ".sql_migrations")+ Encoders.noParams+ (Decoders.singleRow (Decoders.column (Decoders.nonNullable Decoders.int8)))++importFactsStatement :: Statement () (Int64, Int64, Bool)+importFactsStatement =+ Statement.preparable+ """+ SELECT+ (SELECT count(*) FROM pgmigrate.migrations),+ (SELECT count(*) FROM pgmigrate.history_imports),+ (SELECT bool_and(source_evidence #>> '{satisfying_evidence,0,details,adapter}' = 'codd') FROM pgmigrate.history_imports)+ """+ Encoders.noParams+ ( Decoders.singleRow+ ( (,,)+ <$> column Decoders.int8+ <*> column Decoders.int8+ <*> column Decoders.bool+ )+ )+ where+ column = Decoders.column . Decoders.nonNullable