Integrate company-scoped status-card deletion

* commit '32044a63e138e7b6a38ec801878d0db65cce6bbe':
  fix: scope status-card deletion notifications to its company
This commit is contained in:
Dotta committed 2026-10-30 19:04:59 -05:00
commit 0afcc625e2
3 files changed
+42 -2

No files matched your search

@@ -144,6 +144,38 @@ const support = external ? { supported: true } : await getEmbeddedPostgresTestSu
expect(errors).toEqual([]);
});
it("keeps card deletion scoped to its company and a missing deletion quiet", async () => {
const removed = await card();
await card();
const ownCompany = companyId, ownAgent = agentId;
companyId = randomUUID(); agentId = randomUUID();
await db.insert(companies).values({ id: companyId, name: "Other", issuePrefix: `O${companyId.slice(0, 6)}` });
await db.insert(agents).values({ id: agentId, companyId, name: "Other summarizer", role: "general", status: "idle", adapterType: "process", adapterConfig: {} });
const other = await card();
companyId = ownCompany; agentId = ownAgent;
const factory = companySearch.companySearchService;
const searchedCompanies: string[] = [];
vi.spyOn(companySearch, "companySearchService").mockImplementation(owner => {
const search = factory(owner), actual = search.search;
search.search = async (...args) => { searchedCompanies.push(args[0]); return actual(...args); };
return search;
});
await start(); await quiet(); searchedCompanies.length = 0;
const cards = statusCardService(db);
expect(await cards.remove(removed.id)).toMatchObject({ id: removed.id, companyId: ownCompany });
await settled();
// Deleting a card only reconstructs deadlines; it is not an issue change
// that warrants re-running any unchanged reactive card's saved search.
expect(searchedCompanies).toEqual([]);
expect(await cards.getById(other.id)).toMatchObject({ nextEvalAt: null, generatingIssueId: null, pendingChangeCount: 0 });
expect(wakeup).not.toHaveBeenCalled();
searchedCompanies.length = 0;
expect(await cards.remove(removed.id)).toBeNull();
await quiet();
expect(searchedCompanies).toEqual([]);
expect(errors).toEqual([]);
});
it("coalesces one hundred committed source writes without delaying another company's saved deadline", async () => {
const reactive = await card();
const originalCompany = companyId, originalAgent = agentId;
+4 -2
View File
@@ -158,7 +158,7 @@ export function statusCardService(
const issuesSvc = () => deps.issuesSvc ?? issueService(db);
const searchSvc = companySearchService(db);
type Transaction = Parameters<Parameters<Db["transaction"]>[0]>[0];
function mutate<T>(companyId: string | undefined, write: (tx: Transaction) => Promise<T>) {
function mutate<T>(companyId: string, write: (tx: Transaction) => Promise<T>) {
return db.transaction(async tx => {
await notifyStatusCardEvaluation(tx, companyId);
return write(tx);
@@ -335,7 +335,9 @@ export function statusCardService(
}
async function remove(id: string) {
return mutate(undefined, tx => tx.delete(statusCards).where(eq(statusCards.id, id)).returning().then((rows) => rows[0] ?? null));
const card = await getById(id);
if (!card) return null;
return mutate(card.companyId, tx => tx.delete(statusCards).where(eq(statusCards.id, id)).returning().then((rows) => rows[0] ?? null));
}
async function listUpdates(cardId: string) {