@foundrynorth/compass-schema 1.0.13 → 1.0.15

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
@@ -852,6 +852,7 @@ export const plans = pgTable("plans", {
852
852
  // Partner association (null = legacy plans before partner system)
853
853
  partnerId: varchar("partner_id"),
854
854
  engagementId: varchar("engagement_id"), // FK → engagements.id (nullable for backward compatibility)
855
+ selectedOptionId: varchar("selected_option_id"), // FK → plan_options.id (nullable during migration)
855
856
  contractId: uuid("contract_id"), // FK → contracts.id (nullable — links to annual contract)
856
857
  // Workflow mode: determines which UI sections and features are available
857
858
  // 'research_backed' = full AnalyzeAndPlan flow (default, all existing plans)
@@ -1030,6 +1031,7 @@ export const proposals = pgTable("proposals", {
1030
1031
  engagementId: varchar("engagement_id"), // FK → engagements.id (nullable during transition)
1031
1032
  // Configuration references (which plan_configurations to include)
1032
1033
  configurationIds: jsonb("configuration_ids").$type(),
1034
+ optionIds: jsonb("option_ids").$type(),
1033
1035
  // Organization
1034
1036
  partnerId: varchar("partner_id"),
1035
1037
  // HubSpot links (direct — no plan required)
@@ -1105,6 +1107,155 @@ export const insertPlanConfigurationSchema = createInsertSchema(planConfiguratio
1105
1107
  createdAt: true,
1106
1108
  updatedAt: true,
1107
1109
  });
1110
+ // Canonical planning model enums
1111
+ export const planOptionSourceEnum = pgEnum("plan_option_source", [
1112
+ "strategist",
1113
+ "ai",
1114
+ "derived_snapshot",
1115
+ ]);
1116
+ export const planOptionKindEnum = pgEnum("plan_option_kind", [
1117
+ "base",
1118
+ "alternative",
1119
+ ]);
1120
+ export const planOptionStatusEnum = pgEnum("plan_option_status", [
1121
+ "draft",
1122
+ "recommended",
1123
+ "selected",
1124
+ "ordered",
1125
+ "archived",
1126
+ ]);
1127
+ export const researchRunStatusEnum = pgEnum("research_run_status", [
1128
+ "queued",
1129
+ "running",
1130
+ "completed",
1131
+ "failed",
1132
+ "cancelled",
1133
+ "reused",
1134
+ ]);
1135
+ // Canonical research snapshot store
1136
+ export const researchSnapshots = pgTable("research_snapshots", {
1137
+ id: varchar("id")
1138
+ .primaryKey()
1139
+ .default(sql `gen_random_uuid()`),
1140
+ engagementId: varchar("engagement_id").references(() => engagements.id, {
1141
+ onDelete: "set null",
1142
+ }),
1143
+ planId: varchar("plan_id")
1144
+ .notNull()
1145
+ .references(() => plans.id, { onDelete: "cascade" }),
1146
+ scopeType: text("scope_type").notNull(),
1147
+ scopeKey: text("scope_key").notNull(),
1148
+ sourceMode: text("source_mode").notNull(),
1149
+ snapshotVersion: integer("snapshot_version").notNull().default(1),
1150
+ prospectProfile: jsonb("prospect_profile").$type(),
1151
+ competitiveContext: jsonb("competitive_context").$type(),
1152
+ marketContext: jsonb("market_context").$type(),
1153
+ constraints: jsonb("constraints").$type(),
1154
+ fulfillmentContext: jsonb("fulfillment_context").$type(),
1155
+ brandContext: jsonb("brand_context").$type(),
1156
+ provenance: jsonb("provenance").$type().notNull(),
1157
+ freshUntil: timestamp("fresh_until"),
1158
+ reuseHash: text("reuse_hash"),
1159
+ triggerRunId: varchar("trigger_run_id"),
1160
+ costMeta: jsonb("cost_meta").$type(),
1161
+ createdAt: timestamp("created_at").notNull().defaultNow(),
1162
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
1163
+ }, (table) => [
1164
+ index("research_snapshots_plan_id_idx").on(table.planId),
1165
+ index("research_snapshots_plan_version_idx").on(table.planId, table.snapshotVersion),
1166
+ index("research_snapshots_scope_key_idx").on(table.scopeKey),
1167
+ index("research_snapshots_reuse_hash_idx").on(table.reuseHash),
1168
+ ]);
1169
+ export const insertResearchSnapshotSchema = createInsertSchema(researchSnapshots).omit({
1170
+ id: true,
1171
+ createdAt: true,
1172
+ updatedAt: true,
1173
+ });
1174
+ // Canonical actionable option store
1175
+ export const planOptions = pgTable("plan_options", {
1176
+ id: varchar("id")
1177
+ .primaryKey()
1178
+ .default(sql `gen_random_uuid()`),
1179
+ planId: varchar("plan_id")
1180
+ .notNull()
1181
+ .references(() => plans.id, { onDelete: "cascade" }),
1182
+ engagementId: varchar("engagement_id").references(() => engagements.id, {
1183
+ onDelete: "set null",
1184
+ }),
1185
+ legacyConfigurationId: varchar("legacy_configuration_id").references(() => planConfigurations.id, { onDelete: "set null" }),
1186
+ legacyTierKey: text("legacy_tier_key"),
1187
+ name: text("name").notNull(),
1188
+ label: text("label"),
1189
+ source: planOptionSourceEnum("source").notNull(),
1190
+ kind: planOptionKindEnum("kind").notNull(),
1191
+ status: planOptionStatusEnum("status").notNull().default("draft"),
1192
+ derivedFromOptionId: varchar("derived_from_option_id"),
1193
+ researchSnapshotId: varchar("research_snapshot_id").references(() => researchSnapshots.id, { onDelete: "set null" }),
1194
+ generationRunId: varchar("generation_run_id"),
1195
+ budgetTotal: integer("budget_total"),
1196
+ durationMonths: integer("duration_months"),
1197
+ allocations: jsonb("allocations")
1198
+ .$type()
1199
+ .notNull()
1200
+ .default(sql `'[]'::jsonb`),
1201
+ rationale: text("rationale"),
1202
+ assumptions: jsonb("assumptions").$type(),
1203
+ constraints: jsonb("constraints").$type(),
1204
+ fulfillmentNotes: text("fulfillment_notes"),
1205
+ generationContext: jsonb("generation_context").$type(),
1206
+ displayOrder: integer("display_order").notNull().default(0),
1207
+ createdBy: text("created_by"),
1208
+ createdAt: timestamp("created_at").notNull().defaultNow(),
1209
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
1210
+ }, (table) => [
1211
+ index("plan_options_plan_id_idx").on(table.planId),
1212
+ index("plan_options_plan_display_order_idx").on(table.planId, table.displayOrder),
1213
+ index("plan_options_engagement_id_idx").on(table.engagementId),
1214
+ index("plan_options_research_snapshot_id_idx").on(table.researchSnapshotId),
1215
+ uniqueIndex("plan_options_one_recommended_idx")
1216
+ .on(table.planId)
1217
+ .where(sql `${table.status} = 'recommended'::plan_option_status`),
1218
+ uniqueIndex("plan_options_one_selected_idx")
1219
+ .on(table.planId)
1220
+ .where(sql `${table.status} = 'selected'::plan_option_status`),
1221
+ ]);
1222
+ export const insertPlanOptionSchema = createInsertSchema(planOptions).omit({
1223
+ id: true,
1224
+ createdAt: true,
1225
+ updatedAt: true,
1226
+ });
1227
+ // Operational ledger for research runs and snapshot materialization
1228
+ export const researchRuns = pgTable("research_runs", {
1229
+ id: varchar("id")
1230
+ .primaryKey()
1231
+ .default(sql `gen_random_uuid()`),
1232
+ triggerRunId: varchar("trigger_run_id"),
1233
+ taskId: text("task_id").notNull(),
1234
+ engagementId: varchar("engagement_id").references(() => engagements.id, {
1235
+ onDelete: "set null",
1236
+ }),
1237
+ planId: varchar("plan_id").references(() => plans.id, {
1238
+ onDelete: "set null",
1239
+ }),
1240
+ researchSnapshotId: varchar("research_snapshot_id").references(() => researchSnapshots.id, { onDelete: "set null" }),
1241
+ status: researchRunStatusEnum("status").notNull().default("queued"),
1242
+ requestedBy: text("requested_by"),
1243
+ runReason: text("run_reason"),
1244
+ inputHash: text("input_hash"),
1245
+ costMeta: jsonb("cost_meta").$type(),
1246
+ startedAt: timestamp("started_at"),
1247
+ completedAt: timestamp("completed_at"),
1248
+ error: text("error"),
1249
+ createdAt: timestamp("created_at").notNull().defaultNow(),
1250
+ }, (table) => [
1251
+ index("research_runs_plan_id_idx").on(table.planId),
1252
+ index("research_runs_trigger_run_id_idx").on(table.triggerRunId),
1253
+ index("research_runs_task_status_idx").on(table.taskId, table.status),
1254
+ ]);
1255
+ export const insertResearchRunSchema = createInsertSchema(researchRuns).omit({
1256
+ id: true,
1257
+ createdAt: true,
1258
+ });
1108
1259
  // Jobs Table for async operations
1109
1260
  export const jobs = pgTable("jobs", {
1110
1261
  id: varchar("id")
@@ -3124,6 +3275,7 @@ export const mediaOrders = pgTable("media_orders", {
3124
3275
  planId: varchar("plan_id"), // FK → plans.id (nullable — can exist without a plan)
3125
3276
  engagementId: varchar("engagement_id"), // FK → engagements.id (nullable during transition)
3126
3277
  configurationId: varchar("configuration_id"), // FK → plan_configurations.id (named product mix)
3278
+ optionId: varchar("option_id"), // FK → plan_options.id (canonical selected option)
3127
3279
  contractId: uuid("contract_id"), // FK → contracts.id (nullable — links to annual contract)
3128
3280
  partnerId: varchar("partner_id"),
3129
3281
  hubspotDealId: text("hubspot_deal_id"),
@@ -5804,4 +5956,13 @@ export const compassEventOutbox = pgTable("compass_event_outbox", {
5804
5956
  index("compass_event_outbox_pending_idx").on(table.deliveryStatus, table.nextAttemptAt),
5805
5957
  index("compass_event_outbox_event_type_idx").on(table.eventType),
5806
5958
  ]);
5959
+ // ─── Creative Deliveries (Prism webhook idempotency) ────────────────────────
5960
+ export const creativeDeliveries = pgTable("creative_deliveries", {
5961
+ id: serial("id").primaryKey(),
5962
+ packageId: varchar("package_id", { length: 255 }).notNull().unique(),
5963
+ compassCampaignId: varchar("compass_campaign_id", { length: 255 }).notNull(),
5964
+ status: varchar("status", { length: 50 }).notNull(),
5965
+ assetCount: integer("asset_count").notNull().default(0),
5966
+ receivedAt: timestamp("received_at").defaultNow().notNull(),
5967
+ });
5807
5968
  //# sourceMappingURL=schema.js.map