From 30629ffe1f3eff0a76d3cd4e2217569567bbef5f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Oct 2026 13:13:31 +0000 Subject: [PATCH] fix(dogfood): the criteria-less legacy sharing-rule row carries the organization the admin acts in The case "a criteria-less rule already IN the table shares nothing and loses its grants" wrote its legacy row at the driver seam with no organization_id. Since the organization-less readers of sharing rules retired (ADR-0131 D1/D8, 7cacad5348), no admin read resolves such a row, so POST /sharing/rules/srule_3896_legacy/evaluate answered 404 before the criteria guard the case pins was reached. The row now carries the admin's active organization, read off the admin's own session: the shape a pre-gate row has once the organization-ownership ceremony attributes it (ADR-0131 D10). Every assertion is unchanged: evaluate answers below 300, matches 0 records, and materialises no grant. Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6 Co-authored-by: Claude --- ...haring-rule-criteria-required.dogfood.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/qa/dogfood/test/sharing-rule-criteria-required.dogfood.test.ts b/packages/qa/dogfood/test/sharing-rule-criteria-required.dogfood.test.ts index 6ec135ef64f..c22aa9f438f 100644 --- a/packages/qa/dogfood/test/sharing-rule-criteria-required.dogfood.test.ts +++ b/packages/qa/dogfood/test/sharing-rule-criteria-required.dogfood.test.ts @@ -134,6 +134,21 @@ describe('#3896 — a sharing rule POSTed without criteria is rejected, never ma // defense-in-depth the flip bought. A true legacy row predates all of it: // write it at the DRIVER seam, the same level a pre-gate deployment's // storage actually holds it. + // + // The row carries the organization the admin acts in. That is the shape a + // pre-gate row has once the organization-ownership upgrade ceremony has + // attributed it (ADR-0131 D10), and the only shape a certified deployment + // holds. A row with no organization is one no admin read resolves any more + // (ADR-0131 D1/D8: the caller's own organization only), so `evaluate` + // would answer 404 before the criteria guard this case pins is reached. + // The organization is read off the admin's own session, the field the + // request context of the `evaluate` call below is resolved from. + const me = await stack.apiAs(admin, 'GET', '/auth/get-session'); + expect(me.status, 'get-session answers for the admin').toBe(200); + const organizationId = ((await me.json()) as { session?: { activeOrganizationId?: string | null } }) + .session?.activeOrganizationId; + expect(organizationId, 'the admin acts in an organization').toMatch(/^\S+$/); + const id = 'srule_3896_legacy'; const driver = (ql as any).getDriverForObject('sys_sharing_rule'); expect(driver, 'sys_sharing_rule driver must be resolvable').toBeTruthy(); @@ -147,6 +162,7 @@ describe('#3896 — a sharing rule POSTed without criteria is rejected, never ma recipient_id: 'sales_rep', access_level: 'read', active: true, + organization_id: organizationId, }); const res = await stack.apiAs(admin, 'POST', `${RULES}/${id}/evaluate`, {});