Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
9.5 kB ยท 292 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293import { and, db, desc, eq } from "@openstatus/db";import { integration } from "@openstatus/db/src/schema";import { expect } from "@std/expect";import { afterAll, beforeAll, describe, test } from "@std/testing/bdd";
import { SEEDED_WORKSPACE_TEAM_ID } from "../../../test/fixtures";import { clearAuditLog, loadSeededWorkspace, makeApiKeyCtx, makeSlackCtx, readAuditLog, withTestTransaction,} from "../../../test/helpers";import type { ServiceContext } from "../../context";import { ForbiddenError } from "../../errors";import { installSlackAgent } from "../install-slack-agent";
const TEAM_ID = "T_FIXTURE";const SLACK_USER_ID = "U_FIXTURE";
let ctx: ServiceContext;
async function clearSlackAgentRows() { await db .delete(integration) .where( and( eq(integration.workspaceId, SEEDED_WORKSPACE_TEAM_ID), eq(integration.name, "slack-agent"), ), ) .catch(() => undefined);}
beforeAll(async () => { const team = await loadSeededWorkspace(SEEDED_WORKSPACE_TEAM_ID); ctx = makeSlackCtx(team, { teamId: TEAM_ID, slackUserId: SLACK_USER_ID }); // Wipe leftover slack-agent rows from prior aborted runs โ a stale // committed row would block fresh installs (one slack-agent per workspace). await clearSlackAgentRows(); await clearAuditLog(SEEDED_WORKSPACE_TEAM_ID);});
afterAll(async () => { await clearSlackAgentRows(); await clearAuditLog(SEEDED_WORKSPACE_TEAM_ID);});
const baseInput = { externalId: TEAM_ID, credential: { botToken: "xoxb-secret", botUserId: "B_BOT" }, data: { teamId: TEAM_ID, teamName: "Fixture Team", appId: "A_APP", scopes: "chat:write,channels:history", installedBy: SLACK_USER_ID, },};
describe("installSlackAgent", () => { test("first install inserts row and emits integration.create", async () => { await withTestTransaction(async (tx) => { const created = await installSlackAgent({ ctx: { ...ctx, db: tx }, input: baseInput, });
expect(created.name).toBe("slack-agent"); expect(created.workspaceId).toBe(SEEDED_WORKSPACE_TEAM_ID); expect(created.externalId).toBe(TEAM_ID);
const rows = await readAuditLog({ workspaceId: SEEDED_WORKSPACE_TEAM_ID, entityType: "integration", entityId: created.id, db: tx, }); expect(rows).toHaveLength(1); const [row] = rows; expect(row.action).toBe("integration.create"); expect(row.actorType).toBe("slack"); expect(row.before).toBeNull(); // Bot token must never appear in the snapshot. expect(JSON.stringify(row.after)).not.toContain("xoxb-secret"); expect((row.after as Record<string, unknown>).credential).toBeUndefined(); }); });
test("reinstall updates row and emits integration.update with credential diff", async () => { await withTestTransaction(async (tx) => { const ctxTx = { ...ctx, db: tx }; const created = await installSlackAgent({ ctx: ctxTx, input: baseInput }); await clearAuditLog(SEEDED_WORKSPACE_TEAM_ID, { db: tx });
const reinstalled = await installSlackAgent({ ctx: ctxTx, input: { ...baseInput, credential: { botToken: "xoxb-rotated", botUserId: "B_BOT" }, data: { ...baseInput.data, scopes: "chat:write" }, }, });
expect(reinstalled.id).toBe(created.id);
const rows = await readAuditLog({ workspaceId: SEEDED_WORKSPACE_TEAM_ID, entityType: "integration", entityId: created.id, db: tx, }); expect(rows).toHaveLength(1); const [row] = rows; expect(row.action).toBe("integration.update"); expect(row.changedFields).toContain("data"); expect(row.changedFields).toContain("credentialFingerprint"); expect(JSON.stringify(row.before)).not.toContain("xoxb-secret"); expect(JSON.stringify(row.after)).not.toContain("xoxb-rotated"); }); });
test("token-only rotation still emits an audit row via the fingerprint", async () => { await withTestTransaction(async (tx) => { const ctxTx = { ...ctx, db: tx }; const created = await installSlackAgent({ ctx: ctxTx, input: baseInput }); await clearAuditLog(SEEDED_WORKSPACE_TEAM_ID, { db: tx });
await installSlackAgent({ ctx: ctxTx, input: { ...baseInput, credential: { botToken: "xoxb-rotated", botUserId: "B_BOT" }, }, });
const rows = await readAuditLog({ workspaceId: SEEDED_WORKSPACE_TEAM_ID, entityType: "integration", entityId: created.id, db: tx, }); expect(rows).toHaveLength(1); expect(rows[0].action).toBe("integration.update"); expect(rows[0].changedFields).toEqual(["credentialFingerprint"]); }); });
test("identical reinstall is a no-op and does not emit an audit row", async () => { await withTestTransaction(async (tx) => { const ctxTx = { ...ctx, db: tx }; const created = await installSlackAgent({ ctx: ctxTx, input: baseInput }); await clearAuditLog(SEEDED_WORKSPACE_TEAM_ID, { db: tx });
await installSlackAgent({ ctx: ctxTx, input: baseInput });
const rows = await readAuditLog({ workspaceId: SEEDED_WORKSPACE_TEAM_ID, entityType: "integration", entityId: created.id, db: tx, }); expect(rows).toHaveLength(0); }); });
test("rejects empty bot token at the schema boundary", async () => { await withTestTransaction(async (tx) => { await expect( installSlackAgent({ ctx: { ...ctx, db: tx }, input: { ...baseInput, credential: { botToken: "", botUserId: "B" }, }, }), ).rejects.toThrow(); }); });
test("consolidates duplicate slack-agent rows in the same workspace", async () => { await withTestTransaction(async (tx) => { const ctxTx = { ...ctx, db: tx }; // Simulate legacy data: two `slack-agent` rows for the same workspace. // Insert directly to bypass the service guard. The DB has no // `UNIQUE (workspace_id, name)` index, so the service does the // consolidation in code. const [first] = await tx .insert(integration) .values({ name: "slack-agent", workspaceId: SEEDED_WORKSPACE_TEAM_ID, externalId: "T_OLD_1", credential: { botToken: "xoxb-old-1", botUserId: "B_OLD_1" }, data: { ...baseInput.data, teamId: "T_OLD_1" }, }) .returning(); const [second] = await tx .insert(integration) .values({ name: "slack-agent", workspaceId: SEEDED_WORKSPACE_TEAM_ID, externalId: "T_OLD_2", credential: { botToken: "xoxb-old-2", botUserId: "B_OLD_2" }, data: { ...baseInput.data, teamId: "T_OLD_2" }, }) .returning(); await clearAuditLog(SEEDED_WORKSPACE_TEAM_ID, { db: tx });
await installSlackAgent({ ctx: ctxTx, input: baseInput });
const remaining = await tx .select() .from(integration) .where( and( eq(integration.name, "slack-agent"), eq(integration.workspaceId, SEEDED_WORKSPACE_TEAM_ID), ), ) .orderBy(desc(integration.id)) .all(); expect(remaining).toHaveLength(1); expect(remaining[0].id).toBe(second.id);
const all = await readAuditLog({ workspaceId: SEEDED_WORKSPACE_TEAM_ID, entityType: "integration", db: tx, }); expect(all.find((r) => r.action === "integration.delete")?.entityId).toBe( String(first.id), ); const updateRow = all.find((r) => r.action === "integration.update"); expect(updateRow?.entityId).toBe(String(second.id)); // The deleted sibling's snapshot must carry the fingerprint, same // shape as create/update โ proves delete-path symmetry. const deleteRow = all.find((r) => r.action === "integration.delete"); expect( typeof (deleteRow?.before as Record<string, unknown> | null) ?.credentialFingerprint, ).toBe("string"); }); });
test("rejects read-only actor", async () => { await withTestTransaction(async (tx) => { const readOnlyCtx = { ...makeApiKeyCtx(ctx.workspace, { keyId: "k-read", userId: 1, scopes: ["read"], }), db: tx, }; await expect( installSlackAgent({ ctx: readOnlyCtx, input: baseInput }), ).rejects.toBeInstanceOf(ForbiddenError); }); });
test("propagates the openstatus userId from the slack actor", async () => { await withTestTransaction(async (tx) => { const ATTRIBUTED_USER_ID = 1; const attributedCtx: ServiceContext = { ...ctx, actor: { type: "slack", teamId: TEAM_ID, slackUserId: SLACK_USER_ID, userId: ATTRIBUTED_USER_ID, }, db: tx, };
const created = await installSlackAgent({ ctx: attributedCtx, input: baseInput, });
const rows = await readAuditLog({ workspaceId: SEEDED_WORKSPACE_TEAM_ID, entityType: "integration", entityId: created.id, db: tx, }); expect(rows).toHaveLength(1); expect(rows[0].actorUserId).toBe(ATTRIBUTED_USER_ID); }); });});