Merge branch 'clickhouse-sync-session-replays' into clickhouse-sync-project-api-keys

This commit is contained in:
BilalG1 2026-03-16 17:26:53 -07:00 committed by GitHub
commit 52f2f28bbf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 100 additions and 42 deletions

View File

@ -358,14 +358,19 @@ CREATE TABLE IF NOT EXISTS analytics_internal.email_outboxes (
created_with LowCardinality(String),
email_draft_id Nullable(String),
email_programmatic_call_template_id Nullable(String),
theme_id Nullable(String),
is_high_priority UInt8,
rendered_is_transactional Nullable(UInt8),
rendered_subject Nullable(String),
rendered_notification_category_id Nullable(String),
started_rendering_at Nullable(DateTime64(3, 'UTC')),
finished_rendering_at Nullable(DateTime64(3, 'UTC')),
render_error Nullable(String),
scheduled_at DateTime64(3, 'UTC'),
created_at DateTime64(3, 'UTC'),
started_sending_at Nullable(DateTime64(3, 'UTC')),
finished_sending_at Nullable(DateTime64(3, 'UTC')),
server_error Nullable(String),
sent_at Nullable(DateTime64(3, 'UTC')),
delivered_at Nullable(DateTime64(3, 'UTC')),
opened_at Nullable(DateTime64(3, 'UTC')),
@ -373,8 +378,10 @@ CREATE TABLE IF NOT EXISTS analytics_internal.email_outboxes (
unsubscribed_at Nullable(DateTime64(3, 'UTC')),
marked_as_spam_at Nullable(DateTime64(3, 'UTC')),
bounced_at Nullable(DateTime64(3, 'UTC')),
delivery_delayed_at Nullable(DateTime64(3, 'UTC')),
can_have_delivery_info Nullable(UInt8),
skipped_reason LowCardinality(Nullable(String)),
skipped_details Nullable(String),
send_retries Int32,
is_paused UInt8,
sync_sequence_id Int64,
@ -399,14 +406,19 @@ SELECT
created_with,
email_draft_id,
email_programmatic_call_template_id,
theme_id,
is_high_priority,
rendered_is_transactional,
rendered_subject,
rendered_notification_category_id,
started_rendering_at,
finished_rendering_at,
render_error,
scheduled_at,
created_at,
started_sending_at,
finished_sending_at,
server_error,
sent_at,
delivered_at,
opened_at,
@ -414,8 +426,10 @@ SELECT
unsubscribed_at,
marked_as_spam_at,
bounced_at,
delivery_delayed_at,
can_have_delivery_info,
skipped_reason,
skipped_details,
send_retries,
is_paused
FROM analytics_internal.email_outboxes

View File

@ -566,6 +566,7 @@ const CLICKHOUSE_COLUMN_NORMALIZERS: Record<string, Record<string, 'json' | 'boo
is_high_priority: 'boolean',
rendered_is_transactional: 'nullable_boolean',
can_have_delivery_info: 'nullable_boolean',
skipped_details: 'json',
is_paused: 'boolean',
sync_is_deleted: 'boolean',
},

View File

@ -114,6 +114,8 @@ describe("AI Query Endpoint - Validation", () => {
});
it("rejects invalid tool names", async ({ expect }) => {
// Deterministic non-AI check: this payload is schema-valid, then rejected by
// route-level tool-name validation before any model/provider call.
const response = await niceBackendFetch("/api/v1/ai/query/generate", {
method: "POST",
accessType: "admin",
@ -196,23 +198,6 @@ describe("AI Query Endpoint - Validation", () => {
expect(response.body).toMatchObject({ code: "SCHEMA_ERROR", error: expect.stringContaining("messages") });
});
it("accepts valid request body with all required fields", async ({ expect }) => {
// This will forward to production, so we just verify it doesn't fail validation
const response = await niceBackendFetch("/api/v1/ai/query/generate", {
method: "POST",
accessType: "admin",
body: {
quality: "dumb",
speed: "fast",
tools: [],
systemPrompt: "command-center-ask-ai",
messages: [{ role: "user", content: "test" }],
},
});
expect(response.body).not.toMatchObject({ code: "SCHEMA_ERROR" });
}, 10000); // 60 seconds for AI API call
});
describeWithAi("AI Query Endpoint - Authentication", () => {

View File

@ -348,7 +348,9 @@ describe("Stack CLI", () => {
// --- init command tests ---
it("init create writes stack.config.ts with selected apps", async ({ expect }) => {
// TODO: Re-enable these create-mode tests once init mode handling is finalized.
// We keep these skipped (instead of todo) so the test logic remains visible and easy to re-enable.
it.skip("init create writes stack.config.ts with selected apps", async ({ expect }) => {
const initDir = path.join(tmpDir, "init-create");
fs.mkdirSync(initDir, { recursive: true });
@ -367,7 +369,7 @@ describe("Stack CLI", () => {
expect(parsed.apps.installed.teams).toEqual({ enabled: true });
});
it("init create with single app", async ({ expect }) => {
it.skip("init create with single app", async ({ expect }) => {
const initDir = path.join(tmpDir, "init-create-single");
fs.mkdirSync(initDir, { recursive: true });
@ -450,7 +452,7 @@ describe("Stack CLI", () => {
expect(stderr).toContain("not found");
});
it("init outputs setup instructions", async ({ expect }) => {
it.skip("init outputs setup instructions", async ({ expect }) => {
const initDir = path.join(tmpDir, "init-instructions");
fs.mkdirSync(initDir, { recursive: true });

View File

@ -844,14 +844,19 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"created_with" text NOT NULL,
"email_draft_id" text,
"email_programmatic_call_template_id" text,
"theme_id" text,
"is_high_priority" boolean NOT NULL DEFAULT false,
"rendered_is_transactional" boolean,
"rendered_subject" text,
"rendered_notification_category_id" text,
"started_rendering_at" timestamp without time zone,
"finished_rendering_at" timestamp without time zone,
"render_error" text,
"scheduled_at" timestamp without time zone NOT NULL,
"created_at" timestamp without time zone NOT NULL,
"started_sending_at" timestamp without time zone,
"finished_sending_at" timestamp without time zone,
"server_error" text,
"sent_at" timestamp without time zone,
"delivered_at" timestamp without time zone,
"opened_at" timestamp without time zone,
@ -859,8 +864,10 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"unsubscribed_at" timestamp without time zone,
"marked_as_spam_at" timestamp without time zone,
"bounced_at" timestamp without time zone,
"delivery_delayed_at" timestamp without time zone,
"can_have_delivery_info" boolean,
"skipped_reason" text,
"skipped_details" jsonb,
"send_retries" integer NOT NULL DEFAULT 0,
"is_paused" boolean NOT NULL DEFAULT false
);
@ -883,14 +890,19 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
created_with LowCardinality(String),
email_draft_id Nullable(String),
email_programmatic_call_template_id Nullable(String),
theme_id Nullable(String),
is_high_priority UInt8,
rendered_is_transactional Nullable(UInt8),
rendered_subject Nullable(String),
rendered_notification_category_id Nullable(String),
started_rendering_at Nullable(DateTime64(3, 'UTC')),
finished_rendering_at Nullable(DateTime64(3, 'UTC')),
render_error Nullable(String),
scheduled_at DateTime64(3, 'UTC'),
created_at DateTime64(3, 'UTC'),
started_sending_at Nullable(DateTime64(3, 'UTC')),
finished_sending_at Nullable(DateTime64(3, 'UTC')),
server_error Nullable(String),
sent_at Nullable(DateTime64(3, 'UTC')),
delivered_at Nullable(DateTime64(3, 'UTC')),
opened_at Nullable(DateTime64(3, 'UTC')),
@ -898,8 +910,10 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
unsubscribed_at Nullable(DateTime64(3, 'UTC')),
marked_as_spam_at Nullable(DateTime64(3, 'UTC')),
bounced_at Nullable(DateTime64(3, 'UTC')),
delivery_delayed_at Nullable(DateTime64(3, 'UTC')),
can_have_delivery_info Nullable(UInt8),
skipped_reason LowCardinality(Nullable(String)),
skipped_details Nullable(String),
send_retries Int32,
is_paused UInt8,
sync_sequence_id Int64,
@ -922,14 +936,19 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"EmailOutbox"."createdWith"::text AS "created_with",
"EmailOutbox"."emailDraftId" AS "email_draft_id",
"EmailOutbox"."emailProgrammaticCallTemplateId" AS "email_programmatic_call_template_id",
"EmailOutbox"."themeId" AS "theme_id",
"EmailOutbox"."isHighPriority" AS "is_high_priority",
"EmailOutbox"."renderedIsTransactional" AS "rendered_is_transactional",
"EmailOutbox"."renderedSubject" AS "rendered_subject",
"EmailOutbox"."renderedNotificationCategoryId" AS "rendered_notification_category_id",
"EmailOutbox"."startedRenderingAt" AS "started_rendering_at",
"EmailOutbox"."finishedRenderingAt" AS "finished_rendering_at",
"EmailOutbox"."renderErrorExternalMessage" AS "render_error",
"EmailOutbox"."scheduledAt" AS "scheduled_at",
"EmailOutbox"."createdAt" AS "created_at",
"EmailOutbox"."startedSendingAt" AS "started_sending_at",
"EmailOutbox"."finishedSendingAt" AS "finished_sending_at",
"EmailOutbox"."sendServerErrorExternalMessage" AS "server_error",
"EmailOutbox"."sentAt" AS "sent_at",
"EmailOutbox"."deliveredAt" AS "delivered_at",
"EmailOutbox"."openedAt" AS "opened_at",
@ -937,8 +956,10 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"EmailOutbox"."unsubscribedAt" AS "unsubscribed_at",
"EmailOutbox"."markedAsSpamAt" AS "marked_as_spam_at",
"EmailOutbox"."bouncedAt" AS "bounced_at",
"EmailOutbox"."deliveryDelayedAt" AS "delivery_delayed_at",
"EmailOutbox"."canHaveDeliveryInfo" AS "can_have_delivery_info",
"EmailOutbox"."skippedReason"::text AS "skipped_reason",
"EmailOutbox"."skippedDetails" AS "skipped_details",
"EmailOutbox"."sendRetries" AS "send_retries",
"EmailOutbox"."isPaused" AS "is_paused",
"EmailOutbox"."sequenceId" AS "sync_sequence_id",
@ -961,14 +982,19 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"EmailOutbox"."createdWith"::text AS "created_with",
"EmailOutbox"."emailDraftId" AS "email_draft_id",
"EmailOutbox"."emailProgrammaticCallTemplateId" AS "email_programmatic_call_template_id",
"EmailOutbox"."themeId" AS "theme_id",
"EmailOutbox"."isHighPriority" AS "is_high_priority",
"EmailOutbox"."renderedIsTransactional" AS "rendered_is_transactional",
"EmailOutbox"."renderedSubject" AS "rendered_subject",
"EmailOutbox"."renderedNotificationCategoryId" AS "rendered_notification_category_id",
"EmailOutbox"."startedRenderingAt" AS "started_rendering_at",
"EmailOutbox"."finishedRenderingAt" AS "finished_rendering_at",
"EmailOutbox"."renderErrorExternalMessage" AS "render_error",
"EmailOutbox"."scheduledAt" AS "scheduled_at",
"EmailOutbox"."createdAt" AS "created_at",
"EmailOutbox"."startedSendingAt" AS "started_sending_at",
"EmailOutbox"."finishedSendingAt" AS "finished_sending_at",
"EmailOutbox"."sendServerErrorExternalMessage" AS "server_error",
"EmailOutbox"."sentAt" AS "sent_at",
"EmailOutbox"."deliveredAt" AS "delivered_at",
"EmailOutbox"."openedAt" AS "opened_at",
@ -976,8 +1002,10 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"EmailOutbox"."unsubscribedAt" AS "unsubscribed_at",
"EmailOutbox"."markedAsSpamAt" AS "marked_as_spam_at",
"EmailOutbox"."bouncedAt" AS "bounced_at",
"EmailOutbox"."deliveryDelayedAt" AS "delivery_delayed_at",
"EmailOutbox"."canHaveDeliveryInfo" AS "can_have_delivery_info",
"EmailOutbox"."skippedReason"::text AS "skipped_reason",
"EmailOutbox"."skippedDetails" AS "skipped_details",
"EmailOutbox"."sendRetries" AS "send_retries",
"EmailOutbox"."isPaused" AS "is_paused",
"EmailOutbox"."sequenceId" AS "sequence_id",
@ -1000,28 +1028,35 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
$4::text AS "created_with",
$5::text AS "email_draft_id",
$6::text AS "email_programmatic_call_template_id",
$7::boolean AS "is_high_priority",
$8::boolean AS "rendered_is_transactional",
$9::text AS "rendered_subject",
$10::text AS "rendered_notification_category_id",
$11::timestamp without time zone AS "scheduled_at",
$12::timestamp without time zone AS "created_at",
$13::timestamp without time zone AS "started_sending_at",
$14::timestamp without time zone AS "finished_sending_at",
$15::timestamp without time zone AS "sent_at",
$16::timestamp without time zone AS "delivered_at",
$17::timestamp without time zone AS "opened_at",
$18::timestamp without time zone AS "clicked_at",
$19::timestamp without time zone AS "unsubscribed_at",
$20::timestamp without time zone AS "marked_as_spam_at",
$21::timestamp without time zone AS "bounced_at",
$22::boolean AS "can_have_delivery_info",
$23::text AS "skipped_reason",
$24::integer AS "send_retries",
$25::boolean AS "is_paused",
$26::bigint AS "sequence_id",
$27::boolean AS "is_deleted",
$28::text AS "mapping_name"
$7::text AS "theme_id",
$8::boolean AS "is_high_priority",
$9::boolean AS "rendered_is_transactional",
$10::text AS "rendered_subject",
$11::text AS "rendered_notification_category_id",
$12::timestamp without time zone AS "started_rendering_at",
$13::timestamp without time zone AS "finished_rendering_at",
$14::text AS "render_error",
$15::timestamp without time zone AS "scheduled_at",
$16::timestamp without time zone AS "created_at",
$17::timestamp without time zone AS "started_sending_at",
$18::timestamp without time zone AS "finished_sending_at",
$19::text AS "server_error",
$20::timestamp without time zone AS "sent_at",
$21::timestamp without time zone AS "delivered_at",
$22::timestamp without time zone AS "opened_at",
$23::timestamp without time zone AS "clicked_at",
$24::timestamp without time zone AS "unsubscribed_at",
$25::timestamp without time zone AS "marked_as_spam_at",
$26::timestamp without time zone AS "bounced_at",
$27::timestamp without time zone AS "delivery_delayed_at",
$28::boolean AS "can_have_delivery_info",
$29::text AS "skipped_reason",
$30::jsonb AS "skipped_details",
$31::integer AS "send_retries",
$32::boolean AS "is_paused",
$33::bigint AS "sequence_id",
$34::boolean AS "is_deleted",
$35::text AS "mapping_name"
),
deleted AS (
DELETE FROM "email_outboxes" eo
@ -1037,14 +1072,19 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"created_with",
"email_draft_id",
"email_programmatic_call_template_id",
"theme_id",
"is_high_priority",
"rendered_is_transactional",
"rendered_subject",
"rendered_notification_category_id",
"started_rendering_at",
"finished_rendering_at",
"render_error",
"scheduled_at",
"created_at",
"started_sending_at",
"finished_sending_at",
"server_error",
"sent_at",
"delivered_at",
"opened_at",
@ -1052,8 +1092,10 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"unsubscribed_at",
"marked_as_spam_at",
"bounced_at",
"delivery_delayed_at",
"can_have_delivery_info",
"skipped_reason",
"skipped_details",
"send_retries",
"is_paused"
)
@ -1064,14 +1106,19 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
p."created_with",
p."email_draft_id",
p."email_programmatic_call_template_id",
p."theme_id",
p."is_high_priority",
p."rendered_is_transactional",
p."rendered_subject",
p."rendered_notification_category_id",
p."started_rendering_at",
p."finished_rendering_at",
p."render_error",
p."scheduled_at",
p."created_at",
p."started_sending_at",
p."finished_sending_at",
p."server_error",
p."sent_at",
p."delivered_at",
p."opened_at",
@ -1079,8 +1126,10 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
p."unsubscribed_at",
p."marked_as_spam_at",
p."bounced_at",
p."delivery_delayed_at",
p."can_have_delivery_info",
p."skipped_reason",
p."skipped_details",
p."send_retries",
p."is_paused"
FROM params p
@ -1091,14 +1140,19 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"created_with" = EXCLUDED."created_with",
"email_draft_id" = EXCLUDED."email_draft_id",
"email_programmatic_call_template_id" = EXCLUDED."email_programmatic_call_template_id",
"theme_id" = EXCLUDED."theme_id",
"is_high_priority" = EXCLUDED."is_high_priority",
"rendered_is_transactional" = EXCLUDED."rendered_is_transactional",
"rendered_subject" = EXCLUDED."rendered_subject",
"rendered_notification_category_id" = EXCLUDED."rendered_notification_category_id",
"started_rendering_at" = EXCLUDED."started_rendering_at",
"finished_rendering_at" = EXCLUDED."finished_rendering_at",
"render_error" = EXCLUDED."render_error",
"scheduled_at" = EXCLUDED."scheduled_at",
"created_at" = EXCLUDED."created_at",
"started_sending_at" = EXCLUDED."started_sending_at",
"finished_sending_at" = EXCLUDED."finished_sending_at",
"server_error" = EXCLUDED."server_error",
"sent_at" = EXCLUDED."sent_at",
"delivered_at" = EXCLUDED."delivered_at",
"opened_at" = EXCLUDED."opened_at",
@ -1106,8 +1160,10 @@ export const DEFAULT_DB_SYNC_MAPPINGS = {
"unsubscribed_at" = EXCLUDED."unsubscribed_at",
"marked_as_spam_at" = EXCLUDED."marked_as_spam_at",
"bounced_at" = EXCLUDED."bounced_at",
"delivery_delayed_at" = EXCLUDED."delivery_delayed_at",
"can_have_delivery_info" = EXCLUDED."can_have_delivery_info",
"skipped_reason" = EXCLUDED."skipped_reason",
"skipped_details" = EXCLUDED."skipped_details",
"send_retries" = EXCLUDED."send_retries",
"is_paused" = EXCLUDED."is_paused"
RETURNING 1