@foundrynorth/flux-schema 1.19.11 → 1.20.0
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.d.ts +212 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +59 -0
- package/dist/schema.js.map +1 -1
- package/package.json +1 -1
package/dist/schema.js
CHANGED
|
@@ -168,6 +168,28 @@ export const fluxSecretsAuditActionEnum = pgEnum("flux_secrets_audit_action", [
|
|
|
168
168
|
"sync_failed",
|
|
169
169
|
]);
|
|
170
170
|
// =============================================================================
|
|
171
|
+
// MILESTONE NOTIFICATIONS (Real-time per-AM Slack DMs)
|
|
172
|
+
// =============================================================================
|
|
173
|
+
/**
|
|
174
|
+
* Milestone events that can trigger a per-user Slack DM. Owners on a ticket
|
|
175
|
+
* (account manager, account executive, strategist, fulfillment owner) receive
|
|
176
|
+
* these by default; non-owner subscribers must opt in per event type via
|
|
177
|
+
* `flux_users.notificationPreferences.milestones.subscriberOptIn`.
|
|
178
|
+
*/
|
|
179
|
+
export const MILESTONE_EVENT_TYPES = [
|
|
180
|
+
"ticket_created",
|
|
181
|
+
"creative_needed",
|
|
182
|
+
"creative_approved",
|
|
183
|
+
"ready_to_traffic",
|
|
184
|
+
"campaign_live",
|
|
185
|
+
"campaign_completed",
|
|
186
|
+
"campaign_paused",
|
|
187
|
+
"campaign_cancelled",
|
|
188
|
+
"change_required",
|
|
189
|
+
"sem_live",
|
|
190
|
+
"sem_failed",
|
|
191
|
+
];
|
|
192
|
+
// =============================================================================
|
|
171
193
|
// USERS (Extension table - references Clerk, not Forge users)
|
|
172
194
|
// =============================================================================
|
|
173
195
|
/**
|
|
@@ -459,6 +481,43 @@ export const fluxActivityItems = pgTable("flux_activity_items", {
|
|
|
459
481
|
projectOccurredIdx: index("flux_activity_items_project_occurred_idx").on(table.projectId, table.occurredAt),
|
|
460
482
|
}));
|
|
461
483
|
// =============================================================================
|
|
484
|
+
// MILESTONE NOTIFICATIONS (delivery ledger for per-AM Slack DMs)
|
|
485
|
+
// =============================================================================
|
|
486
|
+
/**
|
|
487
|
+
* Idempotency ledger for milestone Slack DMs. The dispatcher inserts one row
|
|
488
|
+
* per (user, source, event) before sending the DM; the unique index causes
|
|
489
|
+
* `ON CONFLICT DO NOTHING` to no-op on retries / re-syncs / webhook replays.
|
|
490
|
+
*
|
|
491
|
+
* Source rows:
|
|
492
|
+
* sourceType = "fulfillment_ticket" → sourceId = flux_fulfillment_tickets.id
|
|
493
|
+
* sourceType = "sem_campaign" → sourceId = flux_sem_campaigns.id
|
|
494
|
+
*
|
|
495
|
+
* `slackTs` captures the Slack message timestamp so future code can thread
|
|
496
|
+
* follow-up updates (e.g. edit the "campaign live" message when it completes).
|
|
497
|
+
*/
|
|
498
|
+
export const fluxMilestoneNotifications = pgTable("flux_milestone_notifications", {
|
|
499
|
+
id: varchar("id")
|
|
500
|
+
.primaryKey()
|
|
501
|
+
.default(sql `gen_random_uuid()`),
|
|
502
|
+
userId: varchar("user_id")
|
|
503
|
+
.references(() => fluxUsers.id, { onDelete: "cascade" })
|
|
504
|
+
.notNull(),
|
|
505
|
+
sourceType: varchar("source_type").notNull(),
|
|
506
|
+
sourceId: varchar("source_id").notNull(),
|
|
507
|
+
eventType: varchar("event_type").notNull(),
|
|
508
|
+
projectId: varchar("project_id").references(() => fluxProjects.id, {
|
|
509
|
+
onDelete: "set null",
|
|
510
|
+
}),
|
|
511
|
+
deliveredAt: timestamp("delivered_at").defaultNow().notNull(),
|
|
512
|
+
slackTs: varchar("slack_ts"),
|
|
513
|
+
metadata: jsonb("metadata").default({}).$type(),
|
|
514
|
+
}, (table) => ({
|
|
515
|
+
uniqueDelivery: uniqueIndex("flux_milestone_notifications_unique_idx").on(table.userId, table.sourceType, table.sourceId, table.eventType),
|
|
516
|
+
userIdx: index("flux_milestone_notifications_user_idx").on(table.userId),
|
|
517
|
+
projectIdx: index("flux_milestone_notifications_project_idx").on(table.projectId),
|
|
518
|
+
deliveredIdx: index("flux_milestone_notifications_delivered_idx").on(table.deliveredAt),
|
|
519
|
+
}));
|
|
520
|
+
// =============================================================================
|
|
462
521
|
// ALERT RULES
|
|
463
522
|
// =============================================================================
|
|
464
523
|
export const fluxAlertRules = pgTable("flux_alert_rules", {
|