// Sage, 2026-10-09: task round trip for the mosaic-stack bots on tasks.mosaicstack.dev, then cleanup as the owner. // Prints statuses and ids only. Usage: node roundtrip.mjs SECRETS_DIR PROJECT_ID FOREIGN_TASK_ID import { readFileSync } from "node:fs"; const [S, P, FOREIGN] = process.argv.slice(2); const BASE = "https://tasks.mosaicstack.dev/api/v2"; const rd = (f) => readFileSync(`${S}/${f}`, "utf8").trim(); async function call(method, path, tok, body) { const headers = { Authorization: `Bearer ${tok}`, "Content-Type": "application/json" }; const r = await fetch(BASE + path, { method, headers, body: body === undefined ? undefined : JSON.stringify(body) }); let j = null; try { j = await r.json(); } catch {} return { s: r.status, j }; } const login = await fetch(BASE + "/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: "mosaic-stack-owner", password: rd("vikunja-owner.password") }) }); const owner = (await login.json()).token; const pm = rd("pm-vikunja.token"); const made = await call("POST", `/projects/${P}/tasks`, pm, { title: "probe: delete me (sage 2026-10-09)" }); console.log("pm create", made.s, made.j?.id, "bucket", made.j?.bucket_id); const T = made.j?.id; for (const r of ["cto", "coder", "reviewer"]) { const tok = rd(`${r}-vikunja.token`); const read = await call("GET", `/tasks/${T}`, tok); const cmt = await call("POST", `/tasks/${T}/comments`, tok, { comment: `probe comment from ${r}` }); const foreign = await call("GET", `/tasks/${FOREIGN}`, tok); const del = await call("DELETE", `/tasks/${T}`, tok); console.log(r, `read=${read.s}`, `comment=${cmt.s}`, `foreignTask=${foreign.s}`, `delete=${del.s}`); } const sync = rd("sync-vikunja.token"); const sread = await call("GET", `/tasks/${T}`, sync); const swrite = await call("POST", `/tasks/${T}/comments`, sync, { comment: "sync should not write" }); const sforeign = await call("GET", `/tasks/${FOREIGN}`, sync); console.log("sync", `read=${sread.s}`, `comment=${swrite.s}`, `foreignTask=${sforeign.s}`); const pforeign = await call("GET", `/tasks/${FOREIGN}`, pm); console.log("pm", `foreignTask=${pforeign.s}`); const gone = await call("DELETE", `/tasks/${T}`, owner); console.log("owner cleanup delete", gone.s);