Files
stack/agents/sage/work/vikunja-setup/roundtrip.mjs
T
jason.woltjeandClaude Opus 5.5 a6382f7bdf docs(slice1): tasks.mosaicstack.dev on Vikunja 2.7.0, runbook sections 2-3 by Sage (row 35, #1517, lead decision 75)
Jason asked for tasks.mosaicstack.dev operational with agents configured in it.
Sage backed it up, tested the restore, pinned 2.7.0 (infra PR #325) and ran
sections 2 and 3 through the API: owner id 4, svc-mosaic-stack id 5, project 32,
bots 6-10, scoped tokens to 2027-01-07. Probes pass. Scope is Mosaic Stack only
(Mos relaying Jason, his Q9 open). OIDC has been broken since a 2026-04-27
NetworkPolicy; infra PR #326 is with ops-01. BUILD-LOG also records the cert
renewal fix and the last-applied annotation slip.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 17:49:40 -05:00

36 lines
2.2 KiB
JavaScript

// 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);