// runtime/subsystems/integration/integration-audit.schema.ts
import {
  pgEnum,
  pgTable,
  uuid,
  text,
  jsonb,
  integer,
  boolean,
  timestamp,
  index,
  uniqueIndex
} from "drizzle-orm/pg-core";
var integrationRunDirectionEnum = pgEnum("integration_run_direction", [
  "inbound",
  "outbound"
]);
var integrationRunActionEnum = pgEnum("integration_run_action", [
  "poll",
  "cdc",
  "webhook",
  "manual",
  "writeback"
]);
var integrationRunStatusEnum = pgEnum("integration_run_status", [
  "running",
  "success",
  "no_changes",
  "failed"
]);
var integrationRunItemOperationEnum = pgEnum("integration_run_item_operation", [
  "created",
  "updated",
  "deleted",
  "noop"
]);
var integrationRunItemStatusEnum = pgEnum("integration_run_item_status", [
  "success",
  "failed",
  "skipped"
]);
var integrationSubscriptions = pgTable(
  "integration_subscriptions",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    connectionId: text("connection_id").notNull(),
    adapter: text("adapter").notNull(),
    domain: text("domain").notNull(),
    externalRef: text("external_ref"),
    enabled: boolean("enabled").notNull().default(true),
    /**
     * Per-subscription configuration bag. Strategies type it internally;
     * e.g. polling strategies stash `{ batchSize, highWatermark }` here.
     */
    config: jsonb("config").notNull().default({}).$type(),
    /**
     * Opaque cursor persisted by `ICursorStore.put()`. NULL until the first
     * successful run advances it.
     */
    cursor: jsonb("cursor").$type(),
    lastIntegrationAt: timestamp("last_integration_at", { withTimezone: true }),
    /** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
    tenantId: text("tenant_id"),
    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
  },
  (t) => ({
    /**
     * Composite uniqueness per the epic shape. `external_ref` is nullable;
     * Postgres treats NULLs as distinct in a UNIQUE constraint, which means
     * two rows with the same `(connection_id, adapter, domain)` and NULL
     * external_ref are allowed. That's intentional — a subscription with
     * NULL external_ref covers the full domain, and duplicates there would
     * be a consumer-layer modeling issue, not a schema concern.
     */
    uqIntegrationSubscriptionTuple: uniqueIndex("uq_integration_subscriptions_tuple").on(
      t.connectionId,
      t.adapter,
      t.domain,
      t.externalRef
    ),
    /** Scheduling query: list enabled subscriptions ordered by staleness. */
    idxIntegrationSubscriptionsEnabledLastIntegration: index(
      "idx_integration_subscriptions_enabled_last_integration"
    ).on(t.enabled, t.lastIntegrationAt)
  })
);
var integrationRuns = pgTable(
  "integration_runs",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    subscriptionId: uuid("subscription_id").notNull().references(() => integrationSubscriptions.id, { onDelete: "cascade" }),
    direction: integrationRunDirectionEnum("direction").notNull(),
    action: integrationRunActionEnum("action").notNull(),
    status: integrationRunStatusEnum("status").notNull().default("running"),
    recordsFound: integer("records_found").notNull().default(0),
    recordsProcessed: integer("records_processed").notNull().default(0),
    cursorBefore: jsonb("cursor_before").$type(),
    cursorAfter: jsonb("cursor_after").$type(),
    durationMs: integer("duration_ms"),
    error: text("error"),
    startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
    completedAt: timestamp("completed_at", { withTimezone: true }),
    /** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
    tenantId: text("tenant_id")
  },
  (t) => ({
    /** Timeline read: "most recent runs for this subscription". */
    idxIntegrationRunsSubscriptionStartedAt: index(
      "idx_integration_runs_subscription_started_at"
    ).on(t.subscriptionId, t.startedAt),
    /** Stale-run sweeper: "runs that started > N minutes ago and are still running". */
    idxIntegrationRunsStatusStartedAt: index("idx_integration_runs_status_started_at").on(
      t.status,
      t.startedAt
    )
  })
);
var integrationRunItems = pgTable(
  "integration_run_items",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    integrationRunId: uuid("integration_run_id").notNull().references(() => integrationRuns.id, { onDelete: "cascade" }),
    entityType: text("entity_type").notNull(),
    externalId: text("external_id").notNull(),
    localId: text("local_id"),
    operation: integrationRunItemOperationEnum("operation").notNull(),
    status: integrationRunItemStatusEnum("status").notNull(),
    /**
     * Structured per-field diff — ADR-0003 shape enforced by
     * `FieldDiffSchema.parse` at the recorder service layer.
     *
     * Shape: `{ [fieldName]: { from: unknown, to: unknown } }`.
     * Empty `{}` for `noop` items; `{ [field]: { from: null, to: <value> } }`
     * for created items; `{ [field]: { from: <value>, to: null } }` for
     * deleted items.
     */
    changedFields: jsonb("changed_fields").notNull().default({}).$type(),
    title: text("title"),
    error: text("error"),
    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
    /** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
    tenantId: text("tenant_id")
  },
  (t) => ({
    /** Ordered timeline within a run. */
    idxIntegrationRunItemsRunCreatedAt: index("idx_integration_run_items_run_created_at").on(
      t.integrationRunId,
      t.createdAt
    ),
    /** Per-record history: "every integration that touched opportunity/$extId". */
    idxIntegrationRunItemsEntityExternal: index(
      "idx_integration_run_items_entity_external"
    ).on(t.entityType, t.externalId)
  })
);

export {
  integrationRunDirectionEnum,
  integrationRunActionEnum,
  integrationRunStatusEnum,
  integrationRunItemOperationEnum,
  integrationRunItemStatusEnum,
  integrationSubscriptions,
  integrationRuns,
  integrationRunItems
};
//# sourceMappingURL=chunk-HNWZFNKP.js.map