/// // // Issue #16 — Lock down API rules now that authentication is real. // // Before Azure login the app had no real auth, so every collection rule was // "" (public). With mandatory Entra OIDC login, every legitimate caller is // authenticated, so we require `@request.auth.id != ""` on all non-system, // non-`team_members` collections. // // This intentionally does NOT delete or restructure any data — it only changes // access rules. The knowledge base, generated tests and micro-learnings stay // exactly as they are; they simply become unreadable to anonymous callers. // // `team_members` is configured by its own migration (1781000000) and skipped // here. System collections (`_superusers`, `_mfas`, `_otps`, …) are skipped. // // NOTE (follow-up): for least-privilege we could further restrict write/delete // on the knowledge-authoring collections (topics, relations, content, sources, // question_bank, curriculum_versions) to `@request.auth.role = "admin"`. That // is deferred because micro_learnings / theme_sessions are written by regular // users (generate-then-cache) and the full matrix needs runtime verification. // The trust boundary today is: perimeter Azure gate + authenticated employees. const AUTHED = '@request.auth.id != ""'; migrate((app) => { const collections = app.findAllCollections(); for (const c of collections) { if (c.system) continue; if (c.name === "team_members") continue; c.viewRule = AUTHED; c.listRule = AUTHED; // View collections only support list/view rules. if (c.type !== "view") { c.createRule = AUTHED; c.updateRule = AUTHED; c.deleteRule = AUTHED; } app.save(c); } }, (app) => { // Down: restore fully public rules (the pre-Azure baseline). const collections = app.findAllCollections(); for (const c of collections) { if (c.system) continue; if (c.name === "team_members") continue; c.viewRule = ""; c.listRule = ""; if (c.type !== "view") { c.createRule = ""; c.updateRule = ""; c.deleteRule = ""; } app.save(c); } });