@vibes.diy/api-svc 13.1.12 → 13.1.14

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.
Files changed (45) hide show
  1. package/create-handler.js +2 -0
  2. package/create-handler.js.map +1 -1
  3. package/evento-handler-manifest.js +2 -0
  4. package/evento-handler-manifest.js.map +1 -1
  5. package/intern/attach-draft-handle.js +1 -0
  6. package/intern/attach-draft-handle.js.map +1 -1
  7. package/intern/backend-egress.d.ts +1 -0
  8. package/intern/backend-egress.js +24 -10
  9. package/intern/backend-egress.js.map +1 -1
  10. package/intern/components/vibe-page.js +29 -1
  11. package/intern/components/vibe-page.js.map +1 -1
  12. package/intern/draft-chat-store.d.ts +5 -0
  13. package/intern/draft-chat-store.js +1 -0
  14. package/intern/draft-chat-store.js.map +1 -1
  15. package/intern/egress-read-lane.js.map +1 -1
  16. package/intern/egress-request-log.d.ts +14 -0
  17. package/intern/egress-request-log.js +16 -0
  18. package/intern/egress-request-log.js.map +1 -0
  19. package/intern/ensure-app-metadata.js.map +1 -1
  20. package/intern/ensure-chat-id.d.ts +2 -1
  21. package/intern/ensure-chat-id.js +14 -1
  22. package/intern/ensure-chat-id.js.map +1 -1
  23. package/intern/pre-allocate.d.ts +5 -0
  24. package/intern/pre-allocate.js +8 -0
  25. package/intern/pre-allocate.js.map +1 -1
  26. package/intern/prompt-assembly.d.ts +1 -0
  27. package/intern/prompt-assembly.js +5 -2
  28. package/intern/prompt-assembly.js.map +1 -1
  29. package/intern/render-vibe.js +2 -0
  30. package/intern/render-vibe.js.map +1 -1
  31. package/intern/ssr-theme-css.d.ts +1 -0
  32. package/intern/ssr-theme-css.js +12 -0
  33. package/intern/ssr-theme-css.js.map +1 -1
  34. package/package.json +12 -11
  35. package/public/prompt-chat-section.js +1 -0
  36. package/public/prompt-chat-section.js.map +1 -1
  37. package/public/report-egress.d.ts +19 -0
  38. package/public/report-egress.js +168 -0
  39. package/public/report-egress.js.map +1 -0
  40. package/usage-report/egress-abuse-alert-util.d.ts +100 -0
  41. package/usage-report/egress-abuse-alert-util.js +246 -0
  42. package/usage-report/egress-abuse-alert-util.js.map +1 -0
  43. package/usage-report/egress-abuse-alert.d.ts +1 -0
  44. package/usage-report/egress-abuse-alert.js +94 -0
  45. package/usage-report/egress-abuse-alert.js.map +1 -0
@@ -0,0 +1,246 @@
1
+ const DISCORD_MARKUP_RE = /[\\`*_~|>#[\]()]/g;
2
+ export function sanitizeForDiscord(value) {
3
+ return value.replaceAll(DISCORD_MARKUP_RE, (c) => `\\${c}`);
4
+ }
5
+ export const DEFAULT_HOST_REQUESTS = 500;
6
+ export const DEFAULT_HOST_VIBES = 5;
7
+ export const DEFAULT_VIBE_HOSTS = 20;
8
+ export const DEFAULT_TRANSPORT_REQUESTS = 50;
9
+ export const DEFAULT_TRANSPORT_SHARE = 0.5;
10
+ export const DEFAULT_SUSPECT_EVENTS = 3;
11
+ export const TOP_N = 8;
12
+ export const DISCORD_DESCRIPTION_LIMIT = 4096;
13
+ const COLOR_TRIPPED = 15548997;
14
+ const COLOR_QUIET = 3447003;
15
+ const COLOR_DARK = 16776960;
16
+ export const EGRESS_ALERT_ENV_VARS = [
17
+ "NEON_DATABASE_URL",
18
+ "DISCORD_WEBHOOK_URL",
19
+ "EGRESS_ALERT_HOST_REQUESTS",
20
+ "EGRESS_ALERT_HOST_VIBES",
21
+ "EGRESS_ALERT_VIBE_HOSTS",
22
+ "EGRESS_ALERT_TRANSPORT_REQUESTS",
23
+ "EGRESS_ALERT_TRANSPORT_SHARE",
24
+ "EGRESS_ALERT_SUSPECT_EVENTS",
25
+ ];
26
+ function num(raw, fallback) {
27
+ if (raw === undefined || raw.trim() === "")
28
+ return fallback;
29
+ const parsed = Number(raw);
30
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
31
+ }
32
+ export function resolveThresholds(env) {
33
+ return {
34
+ hostRequests: num(env.EGRESS_ALERT_HOST_REQUESTS, DEFAULT_HOST_REQUESTS),
35
+ hostVibes: num(env.EGRESS_ALERT_HOST_VIBES, DEFAULT_HOST_VIBES),
36
+ vibeHosts: num(env.EGRESS_ALERT_VIBE_HOSTS, DEFAULT_VIBE_HOSTS),
37
+ transportRequests: num(env.EGRESS_ALERT_TRANSPORT_REQUESTS, DEFAULT_TRANSPORT_REQUESTS),
38
+ transportShare: num(env.EGRESS_ALERT_TRANSPORT_SHARE, DEFAULT_TRANSPORT_SHARE),
39
+ suspectEvents: num(env.EGRESS_ALERT_SUSPECT_EVENTS, DEFAULT_SUSPECT_EVENTS),
40
+ };
41
+ }
42
+ export const PG_UNDEFINED_TABLE = "42P01";
43
+ export function isUndefinedTableError(e) {
44
+ return typeof e === "object" && e !== null && e.code === PG_UNDEFINED_TABLE;
45
+ }
46
+ function vibeKey(ownerHandle, appSlug) {
47
+ return `${ownerHandle}/${appSlug}`;
48
+ }
49
+ export function vibeUrl(ownerHandle, appSlug) {
50
+ return `https://vibes.diy/vibe/${ownerHandle}/${appSlug}`;
51
+ }
52
+ function bump(m, k) {
53
+ m.set(k, (m.get(k) ?? 0) + 1);
54
+ }
55
+ function add(m, k, v) {
56
+ const s = m.get(k) ?? new Set();
57
+ s.add(v);
58
+ m.set(k, s);
59
+ }
60
+ export function summarizeEgress(events, suspects, thresholds) {
61
+ const perHost = new Map();
62
+ const perHostVibes = new Map();
63
+ const perHostTransportErrors = new Map();
64
+ const perVibe = new Map();
65
+ const perVibeHosts = new Map();
66
+ const allVibes = new Set();
67
+ let admitted = 0;
68
+ let denied = 0;
69
+ let transportErrors = 0;
70
+ for (const e of events) {
71
+ const reached = e.finalHost !== "" ? e.finalHost : e.host;
72
+ const vibe = vibeKey(e.ownerHandle, e.appSlug);
73
+ allVibes.add(vibe);
74
+ bump(perHost, reached);
75
+ add(perHostVibes, reached, vibe);
76
+ bump(perVibe, vibe);
77
+ add(perVibeHosts, vibe, e.host);
78
+ if (e.outcome === "admitted")
79
+ admitted += 1;
80
+ else if (e.outcome === "denied")
81
+ denied += 1;
82
+ else if (e.outcome === "transport-error") {
83
+ transportErrors += 1;
84
+ bump(perHostTransportErrors, reached);
85
+ }
86
+ }
87
+ const destinations = [...perHost.entries()]
88
+ .map(([host, requests]) => ({
89
+ host,
90
+ requests,
91
+ vibes: perHostVibes.get(host)?.size ?? 0,
92
+ transportErrors: perHostTransportErrors.get(host) ?? 0,
93
+ }))
94
+ .sort((a, b) => b.requests - a.requests || a.host.localeCompare(b.host));
95
+ const fanOut = [...perVibeHosts.entries()]
96
+ .map(([vibe, hosts]) => {
97
+ const [ownerHandle = "", appSlug = ""] = vibe.split("/");
98
+ return { ownerHandle, appSlug, requestedHosts: hosts.size, requests: perVibe.get(vibe) ?? 0 };
99
+ })
100
+ .sort((a, b) => b.requestedHosts - a.requestedHosts || b.requests - a.requests);
101
+ const transportErrorHosts = destinations
102
+ .filter((d) => d.transportErrors > 0)
103
+ .map((d) => ({ host: d.host, transportErrors: d.transportErrors, requests: d.requests, share: d.transportErrors / d.requests }))
104
+ .sort((a, b) => b.transportErrors - a.transportErrors || a.host.localeCompare(b.host));
105
+ const suspectHosts = new Map();
106
+ const suspectVibes = new Map();
107
+ const suspectReasons = new Map();
108
+ for (const s of suspects) {
109
+ bump(suspectHosts, s.host);
110
+ add(suspectVibes, s.host, vibeKey(s.ownerHandle, s.appSlug));
111
+ for (const r of s.reasons.split(",").map((t) => t.trim())) {
112
+ if (r !== "")
113
+ add(suspectReasons, s.host, r);
114
+ }
115
+ }
116
+ const suspectGroups = [...suspectHosts.entries()]
117
+ .map(([host, events2]) => ({
118
+ host,
119
+ events: events2,
120
+ vibes: suspectVibes.get(host)?.size ?? 0,
121
+ reasons: [...(suspectReasons.get(host) ?? new Set())].sort(),
122
+ }))
123
+ .sort((a, b) => b.events - a.events || a.host.localeCompare(b.host));
124
+ const tripped = [];
125
+ for (const d of destinations) {
126
+ if (d.requests >= thresholds.hostRequests || d.vibes >= thresholds.hostVibes) {
127
+ tripped.push(`Destination concentration — ${sanitizeForDiscord(d.host)} took ${d.requests} request${d.requests === 1 ? "" : "s"} from ${d.vibes} vibe${d.vibes === 1 ? "" : "s"}.`);
128
+ }
129
+ }
130
+ for (const f of fanOut) {
131
+ if (f.requestedHosts >= thresholds.vibeHosts) {
132
+ tripped.push(`Fan-out — ${sanitizeForDiscord(vibeKey(f.ownerHandle, f.appSlug))} asked for ${f.requestedHosts} distinct hosts in ${f.requests} request${f.requests === 1 ? "" : "s"}.`);
133
+ }
134
+ }
135
+ for (const t of transportErrorHosts) {
136
+ if (t.requests >= thresholds.transportRequests && t.share >= thresholds.transportShare) {
137
+ tripped.push(`Transport errors — ${Math.round(t.share * 100)}% of ${t.requests} requests to ${sanitizeForDiscord(t.host)} failed in transport.`);
138
+ }
139
+ }
140
+ for (const s of suspectGroups) {
141
+ if (s.events >= thresholds.suspectEvents) {
142
+ tripped.push(`Suspect responses — ${sanitizeForDiscord(s.host)} returned ${s.reasons.join("/")} to ${s.vibes} vibe${s.vibes === 1 ? "" : "s"} (${s.events} flagged).`);
143
+ }
144
+ }
145
+ return {
146
+ requests: events.length,
147
+ admitted,
148
+ denied,
149
+ transportErrors,
150
+ distinctHosts: perHost.size,
151
+ distinctVibes: allVibes.size,
152
+ suspectEvents: suspects.length,
153
+ destinations,
154
+ fanOut,
155
+ transportErrorHosts,
156
+ suspects: suspectGroups,
157
+ tripped,
158
+ };
159
+ }
160
+ function truncate(description) {
161
+ if (description.length <= DISCORD_DESCRIPTION_LIMIT)
162
+ return description;
163
+ const ellipsis = "\n…(truncated)";
164
+ return `${description.slice(0, DISCORD_DESCRIPTION_LIMIT - ellipsis.length)}${ellipsis}`;
165
+ }
166
+ function section(title, lines) {
167
+ return lines.length === 0 ? undefined : `**${title}**\n${lines.join("\n")}`;
168
+ }
169
+ export function buildMissingTablesEmbed(sinceHours) {
170
+ return {
171
+ content: `⚠️ Backend egress: the signal tables are missing`,
172
+ allowed_mentions: { parse: [] },
173
+ embeds: [
174
+ {
175
+ title: `Backend egress (last ${sinceHours}h)`,
176
+ description: [
177
+ `\`EgressEvents\` / \`EgressSuspectEvents\` do not exist in this database, so nothing could be read.`,
178
+ ``,
179
+ `Two readings, and this job cannot tell them apart:`,
180
+ `• **Expected** — the lane is merged but not deployed yet. The tables arrive with the next \`vibes-diy@p*\`; nothing to do but ship.`,
181
+ `• **A fault** — the tables were dropped, the deploy's schema push did not run, or this job is pointed at the wrong database. The egress abuse signals are unwatched until it is fixed.`,
182
+ ].join("\n"),
183
+ color: COLOR_DARK,
184
+ },
185
+ ],
186
+ };
187
+ }
188
+ export function buildEgressAlertEmbed(input) {
189
+ const { summary: s, sinceHours } = input;
190
+ if (s.requests === 0) {
191
+ return {
192
+ content: `🕳️ Backend egress: the telemetry chain reported nothing in ${sinceHours}h`,
193
+ allowed_mentions: { parse: [] },
194
+ embeds: [
195
+ {
196
+ title: `Backend egress (last ${sinceHours}h)`,
197
+ description: [
198
+ `No EgressEvents rows at all in the window.`,
199
+ ``,
200
+ `That is either a genuinely quiet window or a dead pipeline, and the database cannot tell them apart — the rows arrive over BackendDO console → Workers Trace Events Logpush → R2 → logpush-etl → Neon, and that transport has never been confirmed against a real R2 object. If backends did make outbound calls in this window, check the R2 objects before touching the reader.`,
201
+ ].join("\n"),
202
+ color: COLOR_DARK,
203
+ },
204
+ ],
205
+ };
206
+ }
207
+ const destinations = s.destinations
208
+ .slice(0, TOP_N)
209
+ .map((d) => ` ${sanitizeForDiscord(d.host)} — ${d.requests} req / ${d.vibes} vibe${d.vibes === 1 ? "" : "s"}`);
210
+ const fanOut = s.fanOut
211
+ .slice(0, TOP_N)
212
+ .map((f) => ` ${vibeUrl(f.ownerHandle, f.appSlug)} — ${f.requestedHosts} host${f.requestedHosts === 1 ? "" : "s"} / ${f.requests} req`);
213
+ const transport = s.transportErrorHosts
214
+ .slice(0, TOP_N)
215
+ .map((t) => ` ${sanitizeForDiscord(t.host)} — ${t.transportErrors} of ${t.requests} (${Math.round(t.share * 100)}%)`);
216
+ const suspects = s.suspects
217
+ .slice(0, TOP_N)
218
+ .map((g) => ` ${sanitizeForDiscord(g.host)} — ${g.events} flagged / ${g.vibes} vibe${g.vibes === 1 ? "" : "s"} · ${g.reasons.join(", ")}`);
219
+ const denominator = `${s.requests} request${s.requests === 1 ? "" : "s"} across ${s.distinctHosts} host${s.distinctHosts === 1 ? "" : "s"} from ${s.distinctVibes} vibe${s.distinctVibes === 1 ? "" : "s"} — ${s.admitted} admitted, ${s.denied} denied, ${s.transportErrors} transport errors.`;
220
+ const lead = s.tripped.length > 0 ? s.tripped.map((t) => `⚠️ ${t}`).join("\n") : `Nothing tripped a threshold. ${denominator}`;
221
+ const capNote = input.sampled
222
+ ? `\n\n_Read hit its row cap: these are the most recent events in the window, not all of them. Every count here is a floor._`
223
+ : "";
224
+ const blocks = [
225
+ s.tripped.length > 0 ? `${lead}\n\n${denominator}` : lead,
226
+ section("Top destinations (victim view)", destinations),
227
+ section("Fan-out — distinct hosts requested per vibe", fanOut),
228
+ section("Transport-error concentration", transport),
229
+ section(`Suspect responses (${s.suspectEvents} flagged)`, suspects),
230
+ `_Thresholds are provisional placeholders, to be recalibrated from measured traffic. This pass proposes; it never blocks a vibe or cools a host._`,
231
+ ].filter((b) => b !== undefined);
232
+ return {
233
+ content: s.tripped.length > 0
234
+ ? `🚨 Backend egress: ${s.tripped.length} signal${s.tripped.length === 1 ? "" : "s"} in the last ${sinceHours}h`
235
+ : `🛰️ Backend egress: ${s.requests} request${s.requests === 1 ? "" : "s"} in the last ${sinceHours}h`,
236
+ allowed_mentions: { parse: [] },
237
+ embeds: [
238
+ {
239
+ title: `Backend egress (last ${sinceHours}h)`,
240
+ description: truncate(blocks.join("\n\n") + capNote),
241
+ color: s.tripped.length > 0 ? COLOR_TRIPPED : COLOR_QUIET,
242
+ },
243
+ ],
244
+ };
245
+ }
246
+ //# sourceMappingURL=egress-abuse-alert-util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"egress-abuse-alert-util.js","sourceRoot":"","sources":["../../jsr/usage-report/egress-abuse-alert-util.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,94 @@
1
+ import { Pool } from "@neondatabase/serverless";
2
+ import { Result, exception2Result } from "@adviser/cement";
3
+ import { arg, flag, formatError, loadDevVars } from "./usage-report-util.js";
4
+ import { buildEgressAlertEmbed, buildMissingTablesEmbed, isUndefinedTableError, resolveThresholds, summarizeEgress, } from "./egress-abuse-alert-util.js";
5
+ const DEFAULT_SINCE_HOURS = 24;
6
+ const ROW_CAP = 50000;
7
+ function asString(v) {
8
+ return typeof v === "string" ? v : "";
9
+ }
10
+ async function postMissingTables(webhookUrl, dryRun, sinceHours) {
11
+ const body = buildMissingTablesEmbed(sinceHours);
12
+ if (dryRun) {
13
+ console.log(JSON.stringify(body, null, 2));
14
+ return Result.Ok(undefined);
15
+ }
16
+ return exception2Result(async () => {
17
+ const res = await fetch(webhookUrl, {
18
+ method: "POST",
19
+ headers: { "Content-Type": "application/json" },
20
+ body: JSON.stringify(body),
21
+ });
22
+ if (res.status !== 204)
23
+ throw new Error(`discord post returned ${res.status}`);
24
+ });
25
+ }
26
+ async function run() {
27
+ loadDevVars();
28
+ const sinceHours = Number(arg("--since-hours") ?? DEFAULT_SINCE_HOURS);
29
+ if (!Number.isFinite(sinceHours) || sinceHours <= 0) {
30
+ return Result.Err("usage: pnpm --dir vibes.diy/api/svc run egress-abuse-alert [--since-hours 24] [--dry-run]");
31
+ }
32
+ const connectionString = process.env["NEON_DATABASE_URL"];
33
+ if (connectionString === undefined)
34
+ return Result.Err("NEON_DATABASE_URL is required (prod Neon)");
35
+ const webhookUrl = process.env["DISCORD_WEBHOOK_URL"];
36
+ const thresholds = resolveThresholds({
37
+ EGRESS_ALERT_HOST_REQUESTS: process.env["EGRESS_ALERT_HOST_REQUESTS"],
38
+ EGRESS_ALERT_HOST_VIBES: process.env["EGRESS_ALERT_HOST_VIBES"],
39
+ EGRESS_ALERT_VIBE_HOSTS: process.env["EGRESS_ALERT_VIBE_HOSTS"],
40
+ EGRESS_ALERT_TRANSPORT_REQUESTS: process.env["EGRESS_ALERT_TRANSPORT_REQUESTS"],
41
+ EGRESS_ALERT_TRANSPORT_SHARE: process.env["EGRESS_ALERT_TRANSPORT_SHARE"],
42
+ EGRESS_ALERT_SUSPECT_EVENTS: process.env["EGRESS_ALERT_SUSPECT_EVENTS"],
43
+ });
44
+ const dryRun = flag("--dry-run") || webhookUrl === undefined || webhookUrl === "";
45
+ const sinceIso = new Date(Date.now() - sinceHours * 3600_000).toISOString();
46
+ const pool = new Pool({ connectionString });
47
+ const result = await exception2Result(async () => {
48
+ const eventsRes = await pool.query(`select outcome, host, "finalHost", "ownerHandle", "appSlug"
49
+ from "EgressEvents" where ts >= $1 order by ts desc limit ${ROW_CAP}`, [sinceIso]);
50
+ const events = eventsRes.rows.map((r) => ({
51
+ outcome: asString(r.outcome),
52
+ host: asString(r.host),
53
+ finalHost: asString(r.finalHost),
54
+ ownerHandle: asString(r.ownerHandle),
55
+ appSlug: asString(r.appSlug),
56
+ }));
57
+ const suspectRes = await pool.query(`select host, "ownerHandle", "appSlug", reasons
58
+ from "EgressSuspectEvents" where ts >= $1 order by ts desc limit ${ROW_CAP}`, [sinceIso]);
59
+ const suspects = suspectRes.rows.map((r) => ({
60
+ host: asString(r.host),
61
+ ownerHandle: asString(r.ownerHandle),
62
+ appSlug: asString(r.appSlug),
63
+ reasons: asString(r.reasons),
64
+ }));
65
+ const summary = summarizeEgress(events, suspects, thresholds);
66
+ const sampled = events.length === ROW_CAP || suspects.length === ROW_CAP;
67
+ const body = buildEgressAlertEmbed({ summary, sinceHours, sampled });
68
+ console.log(`[egress-abuse-alert] window=${sinceHours}h requests=${summary.requests} hosts=${summary.distinctHosts} vibes=${summary.distinctVibes} suspects=${summary.suspectEvents} signals=${summary.tripped.length} posted=${!dryRun}`);
69
+ if (dryRun) {
70
+ console.log(JSON.stringify(body, null, 2));
71
+ return;
72
+ }
73
+ const res = await fetch(webhookUrl, {
74
+ method: "POST",
75
+ headers: { "Content-Type": "application/json" },
76
+ body: JSON.stringify(body),
77
+ });
78
+ if (res.status !== 204)
79
+ throw new Error(`discord post returned ${res.status}`);
80
+ });
81
+ await pool.end();
82
+ if (result.isErr() && isUndefinedTableError(result.Err())) {
83
+ console.log("[egress-abuse-alert] EgressEvents/EgressSuspectEvents missing — reporting, not suppressing.");
84
+ return await postMissingTables(webhookUrl, dryRun, sinceHours);
85
+ }
86
+ return result;
87
+ }
88
+ run().then((result) => {
89
+ if (result.isErr()) {
90
+ console.error(formatError(result.Err()));
91
+ process.exitCode = 1;
92
+ }
93
+ });
94
+ //# sourceMappingURL=egress-abuse-alert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"egress-abuse-alert.js","sourceRoot":"","sources":["../../jsr/usage-report/egress-abuse-alert.ts"],"names":[],"mappings":"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"}