@foundrynorth/flux-schema 1.12.0 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/schema.js CHANGED
@@ -2645,6 +2645,61 @@ export const fluxFulfillmentEventOutbox = pgTable("flux_fulfillment_event_outbox
2645
2645
  }));
2646
2646
  /** Relations for fulfillment event outbox (standalone — no foreign keys) */
2647
2647
  export const fluxFulfillmentEventOutboxRelations = relations(fluxFulfillmentEventOutbox, () => ({}));
2648
+ // ---------------------------------------------------------------------------
2649
+ // HubSpot Write-Back Queue
2650
+ // ---------------------------------------------------------------------------
2651
+ /**
2652
+ * Delivery status for HubSpot write-back queue entries.
2653
+ * Mirrors the fulfillment event outbox lifecycle.
2654
+ */
2655
+ export const fluxHubspotWritebackStatusEnum = pgEnum("flux_hubspot_writeback_status", ["pending", "delivered", "failed", "dead_letter"]);
2656
+ /**
2657
+ * Durable queue for HubSpot property write-backs.
2658
+ *
2659
+ * All computed state (health scores, confidence, completeness, SLA status) is
2660
+ * written back to HubSpot via fire-and-forget calls. When inline delivery fails
2661
+ * (API outage, rate limit, circuit breaker open), the write-back is enqueued
2662
+ * here for retry by the `/api/cron/hubspot-writeback-retry` cron job.
2663
+ *
2664
+ * Pattern modeled after `fluxFulfillmentEventOutbox`.
2665
+ */
2666
+ export const fluxHubspotWritebackQueue = pgTable("flux_hubspot_writeback_queue", {
2667
+ id: varchar("id")
2668
+ .primaryKey()
2669
+ .default(sql `gen_random_uuid()`),
2670
+ /** HubSpot object type: "company", "deal", or "ticket" */
2671
+ objectType: text("object_type").notNull(),
2672
+ /** HubSpot numeric object ID */
2673
+ hubspotObjectId: text("hubspot_object_id").notNull(),
2674
+ /** Properties to write as Record<string, string> */
2675
+ properties: jsonb("properties").notNull(),
2676
+ /** Source function that originated this write-back */
2677
+ source: text("source").notNull(),
2678
+ /** Delivery status lifecycle: pending → delivered | failed → dead_letter */
2679
+ status: fluxHubspotWritebackStatusEnum("status")
2680
+ .default("pending")
2681
+ .notNull(),
2682
+ /** Number of delivery attempts so far */
2683
+ attemptCount: integer("attempt_count").default(0).notNull(),
2684
+ /** When to next attempt delivery (exponential backoff) */
2685
+ nextAttemptAt: timestamp("next_attempt_at", { withTimezone: true })
2686
+ .defaultNow()
2687
+ .notNull(),
2688
+ /** Last error message from delivery attempt */
2689
+ lastError: text("last_error"),
2690
+ /** Idempotency key to prevent duplicate queue entries */
2691
+ idempotencyKey: text("idempotency_key").unique(),
2692
+ createdAt: timestamp("created_at", { withTimezone: true })
2693
+ .defaultNow()
2694
+ .notNull(),
2695
+ /** Timestamp of successful delivery */
2696
+ deliveredAt: timestamp("delivered_at", { withTimezone: true }),
2697
+ }, (table) => ({
2698
+ pendingIdx: index("flux_hubspot_writeback_pending_idx").on(table.status, table.nextAttemptAt),
2699
+ objectIdx: index("flux_hubspot_writeback_object_idx").on(table.objectType, table.hubspotObjectId),
2700
+ }));
2701
+ /** Relations for HubSpot write-back queue (standalone — no foreign keys) */
2702
+ export const fluxHubspotWritebackQueueRelations = relations(fluxHubspotWritebackQueue, () => ({}));
2648
2703
  // =============================================================================
2649
2704
  // PROGRAMMATIC SHELL — Enums
2650
2705
  // =============================================================================
@@ -3755,7 +3810,7 @@ export const fluxTapclicksLineItems = pgTable("flux_tapclicks_line_items", {
3755
3810
  rate: numeric("rate"),
3756
3811
  floorRate: numeric("floor_rate"),
3757
3812
  rateType: text("rate_type"),
3758
- impressions: integer("impressions"),
3813
+ impressions: numeric("impressions"),
3759
3814
  totalCost: numeric("total_cost"),
3760
3815
  creativeOptions: text("creative_options"),
3761
3816
  dfpLineItemId: text("dfp_line_item_id"),