// Versioned seed for the EA2-backed attendance roster. // // Creates the attendance_root anchor + 8 site flow docs (kind=value, // source_context=CANVAS_ATTENDANCE_SITE) + presentation edges linking // each site to the anchor. // // Idempotent: re-running reconciles each site by deterministic _key. const BASE = "https://demo.flow-master.ai"; const ANCHOR = "attendance_root"; const SOURCE_CTX = "CANVAS_ATTENDANCE_SITE"; const SITES = [ { key: "hq_london", label: "HQ · London", kind: "office", lat: 51.5074, lng: -0.1278, status: "checked_in", who: "Mariana Cole (CEO) — on-site", city: "London" }, { key: "store_204_manchester", label: "Store 204 · Manchester", kind: "store", lat: 53.4808, lng: -2.2426, status: "checked_in", who: "Manager Priya Sahota — opened 08:02", city: "Manchester" }, { key: "store_118_birmingham", label: "Store 118 · Birmingham", kind: "store", lat: 52.4862, lng: -1.8904, status: "late", who: "Manager Tom Reilly — late check-in 09:24", city: "Birmingham" }, { key: "store_052_edinburgh", label: "Store 052 · Edinburgh", kind: "store", lat: 55.9533, lng: -3.1883, status: "checked_in", who: "Manager Iona MacDonald — opened 07:58", city: "Edinburgh" }, { key: "office_berlin", label: "Office · Berlin", kind: "office", lat: 52.52, lng: 13.405, status: "checked_in", who: "Aisha Khan (HR Director) — remote-on", city: "Berlin" }, { key: "warehouse_rotterdam", label: "Warehouse · Rotterdam", kind: "warehouse", lat: 51.9244, lng: 4.4777, status: "checked_in", who: "Shift A — 24 staff on-floor", city: "Rotterdam" }, { key: "office_bangalore", label: "Office · Bangalore", kind: "office", lat: 12.9716, lng: 77.5946, status: "checked_in", who: "Rohan Patel (IT Director) — on-site", city: "Bangalore" }, { key: "store_088_cardiff", label: "Store 088 · Cardiff", kind: "store", lat: 51.4816, lng: -3.1791, status: "checked_out", who: "Manager Daniel Owens — closed 21:14 yesterday", city: "Cardiff" }, ]; function reqId(tag) { return `attendance-seed-${tag}-${Math.random().toString(36).slice(2, 10)}aaaaa`; } async function devLogin(email) { const r = await fetch(`${BASE}/api/v1/auth/dev-login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email }), }); if (!r.ok) throw new Error(`dev-login: ${r.status}`); return (await r.json()).access_token; } async function fetchEa2(token, method, path, body) { const init = { method, headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" } }; if (body !== undefined) init.body = JSON.stringify(body); const r = await fetch(`${BASE}${path}`, init); return { ok: r.ok, status: r.status, json: r.ok ? await r.json().catch(() => null) : null, text: r.ok ? null : await r.text().catch(() => "") }; } const token = await devLogin("hr-head@flow-master.ai"); console.log("[attendance] signed in"); const anchorHead = await fetchEa2(token, "GET", `/api/ea2/flow/${ANCHOR}`); if (!anchorHead.ok) { const r = await fetchEa2(token, "POST", "/api/ea2/apply-batch", { request_id: reqId("anchor"), ops: [{ op: "create", coll: "flow", data: { _key: ANCHOR, kind: "value", status: "published", name: ANCHOR, display_name: "Attendance · root", description: "Anchor doc for attendance sites", source_context: "CANVAS_ATTENDANCE_ROOT", }, }], }); if (!r.ok) throw new Error(`anchor create failed: ${r.status} ${r.text}`); console.log("[attendance] anchor created"); } else { console.log("[attendance] anchor exists"); } for (const s of SITES) { const existing = await fetchEa2(token, "GET", `/api/ea2/flow/${s.key}`); if (existing.ok) { console.log(` ${s.key}: exists`); continue; } const make = await fetchEa2(token, "POST", "/api/ea2/apply-batch", { request_id: reqId(s.key), ops: [ { op: "create", coll: "flow", data: { _key: s.key, kind: "value", status: "published", name: s.key, display_name: s.label, description: `${s.kind} site at ${s.city}`, source_context: SOURCE_CTX, config: { attendance: { kind: s.kind, lat: s.lat, lng: s.lng, status: s.status, who: s.who, city: s.city, label: s.label } }, }, }, { op: "create_edge", edge_coll: "defines", from: `flow/${ANCHOR}`, to: `flow/${s.key}`, role: "presentation" }, ], }); if (!make.ok) { console.log(` ${s.key}: create failed → ${make.status} ${make.text.slice(0, 200)}`); } else { console.log(` ${s.key}: created + linked`); } } console.log("\nattendance seed complete.");