// Standalone JS port of `lib/visibility.ts` for offline verification. // Mirrors the synchronous decision logic — DB call (assignments) is // faked as an array param. function scopeFor(user) { if (user.isPlatform) return "all"; if (user.roles.includes("owner")) return "org"; return "assigned"; } function listVisibleTenants(user, all, assignments = []) { const scope = scopeFor(user); if (scope === "all") return all; const orgScoped = all.filter( (t) => t.metadata.labels?.["pieced.ch/zitadel-org-id"] === user.orgId ); if (scope === "org") return orgScoped; const allowed = new Set(assignments); return orgScoped.filter((t) => allowed.has(t.metadata.name)); } function canUserSeeTenant(user, tenant, assignments = []) { const scope = scopeFor(user); if (scope === "all") return true; if (tenant.metadata.labels?.["pieced.ch/zitadel-org-id"] !== user.orgId) { return false; } if (scope === "org") return true; return assignments.includes(tenant.metadata.name); } function canSeeInflightRequests(user) { return scopeFor(user) !== "assigned"; } // --------------------------------------------------------------------------- // Test fixtures // --------------------------------------------------------------------------- const platformAdmin = { isPlatform: true, roles: ["platform_admin"], orgId: "platform-org", id: "u-admin" }; const owner = { isPlatform: false, roles: ["owner"], orgId: "org-acme", id: "u-owner" }; const userOnly = { isPlatform: false, roles: ["user"], orgId: "org-acme", id: "u-alice" }; const noRoles = { isPlatform: false, roles: [], orgId: "org-acme", id: "u-bob" }; const tenantA = { metadata: { name: "acme-prod-12345678", labels: { "pieced.ch/zitadel-org-id": "org-acme" } } }; const tenantB = { metadata: { name: "acme-dev-87654321", labels: { "pieced.ch/zitadel-org-id": "org-acme" } } }; const tenantC = { metadata: { name: "other-corp-aaaa", labels: { "pieced.ch/zitadel-org-id": "org-other" } } }; const allTenants = [tenantA, tenantB, tenantC]; // --------------------------------------------------------------------------- // listVisibleTenants // --------------------------------------------------------------------------- const listCases = [ { user: platformAdmin, assignments: [], expected: ["acme-prod-12345678", "acme-dev-87654321", "other-corp-aaaa"], note: "platform sees all" }, { user: owner, assignments: [], expected: ["acme-prod-12345678", "acme-dev-87654321"], note: "owner sees all org tenants" }, { user: owner, assignments: ["acme-prod-12345678"], expected: ["acme-prod-12345678", "acme-dev-87654321"], note: "owner ignores assignment table even if rows exist" }, { user: userOnly, assignments: [], expected: [], note: "user with no assignments sees nothing" }, { user: userOnly, assignments: ["acme-prod-12345678"], expected: ["acme-prod-12345678"], note: "user sees only assigned tenants" }, { user: userOnly, assignments: ["acme-prod-12345678", "acme-dev-87654321"], expected: ["acme-prod-12345678", "acme-dev-87654321"], note: "user sees multiple assigned tenants" }, { user: userOnly, assignments: ["other-corp-aaaa"], expected: [], note: "stale assignment to other-org tenant doesn't leak" }, { user: noRoles, assignments: [], expected: [], note: "no roles is treated as user-scope (empty)" }, ]; let pass = 0, fail = 0; console.log("--- listVisibleTenants ---"); for (const c of listCases) { const got = listVisibleTenants(c.user, allTenants, c.assignments).map((t) => t.metadata.name); const ok = JSON.stringify(got) === JSON.stringify(c.expected); console.log(`${ok ? "PASS" : "FAIL"} got=${JSON.stringify(got)} want=${JSON.stringify(c.expected)} [${c.note}]`); if (ok) pass++; else fail++; } // --------------------------------------------------------------------------- // canUserSeeTenant // --------------------------------------------------------------------------- console.log("\n--- canUserSeeTenant ---"); const seeCases = [ { user: platformAdmin, tenant: tenantA, assignments: [], expected: true, note: "platform sees same-cluster tenant" }, { user: platformAdmin, tenant: tenantC, assignments: [], expected: true, note: "platform sees other-org tenant" }, { user: owner, tenant: tenantA, assignments: [], expected: true, note: "owner sees own-org tenant" }, { user: owner, tenant: tenantC, assignments: [], expected: false, note: "owner does NOT see other-org tenant" }, { user: userOnly, tenant: tenantA, assignments: ["acme-prod-12345678"], expected: true, note: "user sees assigned tenant" }, { user: userOnly, tenant: tenantA, assignments: [], expected: false, note: "user does NOT see un-assigned own-org tenant" }, { user: userOnly, tenant: tenantC, assignments: ["other-corp-aaaa"], expected: false, note: "user does NOT see other-org tenant even with stale assignment" }, ]; for (const c of seeCases) { const got = canUserSeeTenant(c.user, c.tenant, c.assignments); const ok = got === c.expected; console.log(`${ok ? "PASS" : "FAIL"} got=${got} want=${c.expected} [${c.note}]`); if (ok) pass++; else fail++; } // --------------------------------------------------------------------------- // canSeeInflightRequests // --------------------------------------------------------------------------- console.log("\n--- canSeeInflightRequests ---"); const requestCases = [ { user: platformAdmin, expected: true, note: "platform sees in-flight" }, { user: owner, expected: true, note: "owner sees in-flight" }, { user: userOnly, expected: false, note: "user-role does NOT see in-flight" }, { user: noRoles, expected: false, note: "no-roles does NOT see in-flight" }, ]; for (const c of requestCases) { const got = canSeeInflightRequests(c.user); const ok = got === c.expected; console.log(`${ok ? "PASS" : "FAIL"} got=${got} want=${c.expected} [${c.note}]`); if (ok) pass++; else fail++; } console.log(`\n${pass} pass, ${fail} fail`); process.exit(fail === 0 ? 0 : 1);