Skip to content

Commit 96628ec

Browse files
committed
fix(release): address review feedback
1 parent 7e7a4b0 commit 96628ec

5 files changed

Lines changed: 149 additions & 12 deletions

File tree

apps/api/src/integration/cache-auth-bypass.test.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import "@databuddy/test/env";
22

3-
import { targetGroups } from "@databuddy/db/schema";
3+
import { flags, targetGroups } from "@databuddy/db/schema";
44
import { appRouter, type Context } from "@databuddy/rpc";
55
import {
66
addToOrganization,
@@ -50,6 +50,22 @@ async function seedTargetGroup(websiteId: string, createdBy: string) {
5050
});
5151
}
5252

53+
async function seedFlag(websiteId: string, createdBy: string) {
54+
await db()
55+
.insert(flags)
56+
.values({
57+
id: randomUUIDv7(),
58+
websiteId,
59+
key: "secret-rollout",
60+
name: "Secret Rollout",
61+
description: "Internal rollout definition",
62+
defaultValue: true,
63+
status: "active",
64+
rules: [{ field: "country", operator: "equals", value: "US" }],
65+
createdBy,
66+
});
67+
}
68+
5369
const annotationsParams = (websiteId: string) =>
5470
({
5571
websiteId,
@@ -145,6 +161,7 @@ describe("cache-bypass auth: target-groups.list", () => {
145161
describe("cache-bypass auth: flags.list", () => {
146162
iit("anon caller cannot read flags after authed prime", async () => {
147163
const { user, org, site } = await setupOwnedSite();
164+
await seedFlag(site.id, user.id);
148165

149166
await call(
150167
appRouter.flags.list,
@@ -160,6 +177,7 @@ describe("cache-bypass auth: flags.list", () => {
160177
iit("cross-org user is rejected after authed prime", async () => {
161178
const a = await setupOwnedSite();
162179
const b = await setupOwnedSite();
180+
await seedFlag(a.site.id, a.user.id);
163181

164182
await call(
165183
appRouter.flags.list,
@@ -176,13 +194,39 @@ describe("cache-bypass auth: flags.list", () => {
176194
});
177195

178196
iit("demo caller cannot read public-site flag definitions", async () => {
179-
const { site } = await setupOwnedSite({ isPublic: true });
197+
const { user, org, site } = await setupOwnedSite({ isPublic: true });
198+
await seedFlag(site.id, user.id);
199+
200+
const authed = await call(
201+
appRouter.flags.list,
202+
userContext(user, org.id)
203+
)({ websiteId: site.id });
204+
expect(authed).toHaveLength(1);
180205

181206
await expectCode(
182207
call(appRouter.flags.list, context())({ websiteId: site.id }),
183208
"UNAUTHORIZED"
184209
);
185210
});
211+
212+
iit("demo caller cannot read public-site flag definitions by key", async () => {
213+
const { user, org, site } = await setupOwnedSite({ isPublic: true });
214+
await seedFlag(site.id, user.id);
215+
216+
const authed = await call(
217+
appRouter.flags.getByKey,
218+
userContext(user, org.id)
219+
)({ websiteId: site.id, key: "secret-rollout" });
220+
expect(authed).toMatchObject({ key: "secret-rollout" });
221+
222+
await expectCode(
223+
call(appRouter.flags.getByKey, context())({
224+
websiteId: site.id,
225+
key: "secret-rollout",
226+
}),
227+
"UNAUTHORIZED"
228+
);
229+
});
186230
});
187231

188232
describe("cache-bypass auth: annotations.list", () => {

apps/dashboard/app/(main)/websites/[id]/goals/_components/goal-item.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ interface GoalItemProps {
2626
function GoalProgress({ rate }: { rate: number }) {
2727
const clampedRate = Math.max(0, Math.min(100, rate));
2828
return (
29-
<span className="block h-5 w-32 overflow-hidden rounded bg-muted lg:w-44">
29+
<div className="h-5 w-32 overflow-hidden rounded bg-muted lg:w-44">
3030
<div
3131
className="h-full rounded bg-chart-1 transition-[width]"
3232
style={{ width: `${clampedRate}%` }}
3333
/>
34-
</span>
34+
</div>
3535
);
3636
}
3737

apps/dashboard/app/(main)/websites/[id]/settings/general/page.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,35 @@ export default function GeneralSettingsPage() {
108108

109109
return { getByIdKey, listKey, previousList, previousWebsite };
110110
},
111-
onError: (_error, _variables, context) => {
111+
onError: (_error, variables, context) => {
112112
if (!context) {
113113
return;
114114
}
115-
queryClient.setQueryData(context.getByIdKey, context.previousWebsite);
116-
queryClient.setQueryData(context.listKey, context.previousList);
115+
const previousIsPublic =
116+
context.previousWebsite?.isPublic ??
117+
context.previousList?.websites.find(
118+
(website) => website.id === variables.id
119+
)?.isPublic;
120+
queryClient.setQueryData<Website>(context.getByIdKey, (current) => {
121+
if (!current) {
122+
return context.previousWebsite;
123+
}
124+
return previousIsPublic === undefined
125+
? current
126+
: { ...current, isPublic: previousIsPublic };
127+
});
128+
queryClient.setQueryData<WebsitesListData>(context.listKey, (current) =>
129+
current
130+
? {
131+
...current,
132+
websites: current.websites.map((website) =>
133+
website.id === variables.id && previousIsPublic !== undefined
134+
? { ...website, isPublic: previousIsPublic }
135+
: website
136+
),
137+
}
138+
: context.previousList
139+
);
117140
},
118141
onSuccess: (updatedWebsite: Website) => {
119142
updateWebsiteCache(queryClient, updatedWebsite);

apps/insights/src/delivery.test.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,76 @@ describe("Slack insight digest markdown", () => {
130130
expect(text).not.toContain("Delete funnel");
131131
});
132132

133+
it("filters code-heavy action labels before choosing the next action", () => {
134+
const blocks = buildBlocks(
135+
"Databuddy",
136+
"app.databuddy.cc",
137+
[
138+
{
139+
actions: [{ label: "Run document.execCommand('copy')" }],
140+
description: "Clipboard errors increased on onboarding.",
141+
id: "clipboard-action",
142+
severity: "warning",
143+
sentiment: "negative",
144+
suggestion: "Review the onboarding clipboard flow.",
145+
title: "Clipboard errors increased",
146+
type: "persistent_error_hotspot",
147+
},
148+
],
149+
[]
150+
);
151+
152+
const text = sectionText(blocks, 1);
153+
expect(text).toContain("Next: Review the onboarding clipboard flow.");
154+
expect(text).not.toContain("document.execCommand");
155+
});
156+
157+
it("keeps human-readable error handling suggestions", () => {
158+
const blocks = buildBlocks(
159+
"Databuddy",
160+
"app.databuddy.cc",
161+
[
162+
{
163+
actions: [],
164+
description: "Form submissions failed during a network blip.",
165+
id: "network-errors",
166+
severity: "warning",
167+
sentiment: "negative",
168+
suggestion:
169+
"Wrap the form submission in a try/catch block to handle network errors.",
170+
title: "Signup form errors increased",
171+
type: "error_spike",
172+
},
173+
],
174+
[]
175+
);
176+
177+
expect(sectionText(blocks, 1)).toContain(
178+
"Next: Wrap the form submission in a try/catch block"
179+
);
180+
});
181+
182+
it("handles legacy insight rows without type or sentiment fields", () => {
183+
const blocks = buildBlocks(
184+
"Databuddy",
185+
"app.databuddy.cc",
186+
[
187+
{
188+
description: "A historical insight row was missing newer metadata.",
189+
id: "legacy-insight",
190+
severity: "warning",
191+
suggestion: "Review this legacy insight.",
192+
title: "Legacy insight still renders",
193+
},
194+
],
195+
[]
196+
);
197+
198+
const text = sectionText(blocks, 1);
199+
expect(text).toContain("*Fix · Priority signal*");
200+
expect(text).toContain("Next: Review this legacy insight.");
201+
});
202+
133203
it("falls back to the domain when no website name exists", () => {
134204
const blocks = buildBlocks(
135205
null,

apps/insights/src/delivery.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ interface DigestInsight {
2323
description: string;
2424
id: string;
2525
impactSummary?: string | null;
26-
sentiment: string;
26+
sentiment?: string | null;
2727
severity: string;
2828
suggestion: string;
2929
title: string;
30-
type: string;
30+
type?: string | null;
3131
}
3232

3333
interface SlackBlock {
@@ -49,7 +49,7 @@ const IMPLEMENTATION_DETAIL_MARKERS = [
4949
"navigator.",
5050
"execcommand",
5151
"writetext",
52-
"try/catch",
52+
".catch(",
5353
] as const;
5454
const TRUNCATED_UUID_PATTERN = /\b[0-9a-f]{8}-[0-9a-f]{4}-\.\.\./gi;
5555

@@ -232,8 +232,8 @@ function visibleSuggestion(value: string): string | null {
232232

233233
function nextAction(insight: DigestInsight): string {
234234
const label = (insight.actions ?? [])
235-
.map((action) => action.label.trim())
236-
.find(Boolean);
235+
.map((action) => visibleSuggestion(action.label))
236+
.find((value): value is string => Boolean(value));
237237
return (
238238
label ??
239239
visibleSuggestion(insight.suggestion) ??

0 commit comments

Comments
 (0)