row 252: decide-browser placements (mos-1272): the hostile grant goes in with its INSERT since decisions is append-only, and page() loads about:blank first so a same-URL visit reloads

This commit is contained in:
jason.woltje committed 2026-10-23 10:17:33 -05:00
1 parent b316e0a556
commit 9e1601a201
1 file changed
+21 -2
+21 -2
View File
@@ -6,6 +6,7 @@
// through its reader session. Refresh timers fire after 150 ms. // through its reader session. Refresh timers fire after 150 ms.
import { test } from 'node:test'; import { test } from 'node:test';
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import { randomUUID } from 'node:crypto';
import { mkdtempSync, rmSync } from 'node:fs'; import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os'; import { tmpdir } from 'node:os';
import { join } from 'node:path'; import { join } from 'node:path';
@@ -46,12 +47,28 @@ const STUB = `(() => {
}; };
})();`; })();`;
// The open grant request, as host-fixtures' grantDecision writes it but with the hostile question.
// decisions is append-only (migration 3b), so the question goes in with the row, not by an UPDATE.
function hostileGrant(store, grant) {
const id = randomUUID(), at = '2026-10-21T00:00:00.000Z';
store.run(
'INSERT INTO decisions(id,at,business,raised_by_role,raised_by_run,class,action,route_to,question,options,recommendation,blocking) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)',
id, at, 'demo', 'chief', 'chief-run', 'gated', 'credential.mint', 'human', `Enroll web1? ${HOSTILE}`,
JSON.stringify([{ key: 'yes', text: 'Yes' }, { key: 'no', text: 'No' }]), 'yes', 0,
);
store.run(
"INSERT INTO events(id,at,business,kind,actor_role,actor_run,subject,body) VALUES(?,?,?,'action.allowed',?,?,?,?)",
randomUUID(), at, 'demo', 'chief', 'chief-run', id,
JSON.stringify({ decision: id, action: 'credential.mint', operation: 'decision.raise', approvalChoice: 'yes', grant }),
);
return id;
}
async function setup() { async function setup() {
const root = mkdtempSync(join(tmpdir(), 'webui-decide-browser-')); const root = mkdtempSync(join(tmpdir(), 'webui-decide-browser-'));
const store = new Store(root), b0 = new Broker({ store, businesses }); const store = new Store(root), b0 = new Broker({ store, businesses });
const grant = { method: 'host-enroll', host: 'web1', address: '192.0.2.10', port: 22, user: 'jarvis', sudo: true, fingerprints: [] }; const grant = { method: 'host-enroll', host: 'web1', address: '192.0.2.10', port: 22, user: 'jarvis', sudo: true, fingerprints: [] };
const open = grantDecision(store, { grant, close: null }); const open = hostileGrant(store, grant);
store.run('UPDATE decisions SET question=? WHERE id=?', `Enroll web1? ${HOSTILE}`, open);
const deploy = grantDecision(store, { action: 'deploy', grant, close: null }); const deploy = grantDecision(store, { action: 'deploy', grant, close: null });
const bare = grantDecision(store, { close: null }); const bare = grantDecision(store, { close: null });
const reader = b0.bindReader({ business: 'demo' }); const reader = b0.bindReader({ business: 'demo' });
@@ -67,6 +84,8 @@ async function setup() {
const queue = a => b.evaluate(`window.__answers.push(${JSON.stringify(a)}), true`); const queue = a => b.evaluate(`window.__answers.push(${JSON.stringify(a)}), true`);
const click = step => b.evaluate(`document.querySelector('#decide-section [data-decide="${step}"]').click(), true`); const click = step => b.evaluate(`document.querySelector('#decide-section [data-decide="${step}"]').click(), true`);
const page = async (query, id) => { const page = async (query, id) => {
// The same URL again is a same-document hash change, not a load, so load about:blank first (as editor-browser does).
await b.navigate('about:blank');
await b.navigate(`${base}?${query}#/inbox/${id}`); await b.navigate(`${base}?${query}#/inbox/${id}`);
await wait('document.querySelector("#bus-view h1")?.textContent.startsWith("Decision") && !document.querySelector("#bus-view [aria-busy]")'); await wait('document.querySelector("#bus-view h1")?.textContent.startsWith("Decision") && !document.querySelector("#bus-view [aria-busy]")');
// The config read redraws once it lands; a refresh tick after it settles the page. // The config read redraws once it lands; a refresh tick after it settles the page.