test(webui): fetch chat assets through the SSO public Host (#385)
This commit is contained in:
1 parent
484aef7e2a
commit
fbf8d61a4c
3 files changed
+11
-4
No files matched your search
@@ -5821,3 +5821,4 @@ Before: agents can read the library; supporting-path and push-credential depende
|
||||
2026-10-29T05:49:53Z | Codex Daybreak Blue xhigh implementation sub-agent | CORRECTION and Mos2255 #385 review repair R2 | The 03:27:31Z dependency/no-commit statements are historical: exact pinned `[email protected]` is now materialized through the ignored `node_modules` fixture with no install, and original preparation is committed at `9936a1be1a37fdb30ba53cf2f14b7897225c3e4a`. On that unchanged HEAD, uncommitted R2 source/tests/docs make Case 2 library preview read-only until #412, drop inherited non-SSO `--send` during release planning, and refuse duplicate service `--send`. Focused RED was 0/2, 0/1, 0/1; focused GREEN and selected T53/T55/T57/T58 fixture blocks pass. No root/native/live/full-suite/CI action, commit, push, PR/API, merge or frozen/live-pin change.
|
||||
2026-11-02T18:03:53Z | Claude Opus 5.5 implementation sub-agent (lead T3 c5c1e8ba) | #385 PR 1836 repair R3 on ab2bc23c7 | R2-F1: `scripts/stack-upgrade.sh` `read_args` now scans the serve argv after `--` and refuses `args-unreadable` before anything stops when the profile is library (no `--profile`, or the last one says library, as `case2-unit.sh` reads it) and `--send` is present; the message names the remediation, and the args file is never rewritten. `do_upgrade` and `do_rollback` both call `read_args` first, so rollback is covered; factory and tester paths are unchanged. RED on ab2bc23c7: new stack-upgrade case 0/1 (exit 2 rollback-failed, A4 and render-old failed, both units stopped), controls 1/1; GREEN 2/2. R2-I1: one component case runs the real `sso_for_target` then `send_for_target` on a legacy preview `--send` pointer, carried after `--sso` and before `--tester-socket`. R2-I2: TOOLS.md says a same-copy plain activate on a legacy pointer refuses already-active and needs `--no-send`. R2-I3: no code change; `uninstall`/`status` with `--send --send` exit 1, not 4, fail-closed either way. host-run-sheet section 7 gains the migration step. Whole files, one at a time: stack-upgrade 23/23 (69 s), stack-release 225/225 (608 s; a first run was cut by my 600 s background limit at 221 passing, its orphan fixture holder killed), case2-unit 48/48 (73 s). No root, systemd, container, network, push, PR or live action.
|
||||
2026-11-02T18:19:04Z | Claude Opus 5.5 implementation sub-agent (lead T3 c5c1e8ba) | #385 PR 1836 repair R4 on d0ddfa8de | R3-F1 fixed fail-closed, no migration: `scripts/stack-upgrade.sh` adds `legacy_console`, called right after `read_args` in `do_upgrade` and `do_rollback`. For the library profile (same default and last-wins rule as R3), an installed Console unit under the driver's UNIT_DIR whose ExecStart has a `--send` token after `serve` refuses new code `console-unit-legacy` (exit 3, nothing stopped). A missing unit is left to `read_old` (`units-unreadable`). The R3 args refusal stays. `case2-unit.sh`, factory, tester, stack-release.sh and OIDC/#412 untouched. Tests in stack-upgrade.test.mjs run the real base renderer (`git show 09a847eda` of case2-unit.sh and both templates) in the module fixture with fake getent/systemctl to make the legacy unit, prove the current case2-unit.sh refuses it, then drive upgrade and rollback with the real current renderer as A4's RENDER. Controls: read-only library unit, factory host, missing Console unit. RED on d0ddfa8de code 24/25 (the main case exits 2 rollback-failed, both units stopped), GREEN 25/25 (70.1 s). host-run-sheet section 7 now gives a read-only grep of the unit and says stop and report when it carries `--send`. TOOLS.md lists the code. No hash pins on changed files. stack-release.test.mjs and case2-unit.test.mjs read no changed file and were not rerun. One local commit, no push.
|
||||
2026-11-02T18:55:26Z | Claude Sonnet 5.5 implementation sub-agent (lead T3 c5c1e8ba) | #385 PR 1836 repair R5 on 484aef7e2 | Test-only fix; no product file changed. The asset test in packages/webui/tests/chat.test.mjs still fetched `http://127.0.0.1:PORT/chat.js` bare, but since 9936a1be1 its `setup()` runs `sso: auth.sso`, and `serve.mjs:726` answers any non-public Host with 403 `public Host required` (the lead found it in the landing gate on lead/q284-land). The server is right, the test was stale. The test now fetches chat.js and chat.css through `c.get` on the public Host with the signed-in session (new `asText` option on the test `http()` so an asset body is not JSON-parsed), asserts 200, the content type and a non-empty body, asserts the same asset on the loopback Host gets 403 `public Host required`, and adds one line pinning that an unauthenticated public-Host request gets 303 to `/auth/login?return=%2Fchat.js` (`serve.mjs` 736-739), so the asset is not public. RED on 484aef7e2 29/30 (403 !== 200 at chat.test.mjs:350), GREEN 30/30. Whole packages/webui run 495/495, 0 fail (65 s). A first whole run gave 487/8, all 8 in pinned-copy.test.mjs: `fixtureRepo` copies `git ls-files -co --exclude-standard`, and a symlink named `packages/webui/node_modules` is untracked and not ignored (`node_modules/` matches directories only), so cpSync refuses it. That is an artifact of the symlink; the rerun used a real ignored directory of links. Observation, not changed: in `c.get` the `host` option is overridden by `baseHeaders.host`, so the existing POST assertion passing `host: 127.0.0.1:PORT` sends the public Host and exercises the Origin fence. No hash pins on changed files. One local commit, no push.
|
||||
@@ -1883,3 +1883,4 @@ are never rewritten or removed; corrections are new entries.
|
||||
2026-10-29T05:49:53Z | Codex Daybreak Blue xhigh implementation sub-agent | Mos2255 #385 review repair R2 on work/vikunja-19-385-q284-complete at unchanged HEAD 9936a1be1a37fdb30ba53cf2f14b7897225c3e4a/base 09a847edaa25b609bac7728ff83f224708a29399 | Corrects the 03:27:31Z historical blocker: pinned oauth4webapi3.8.8 fixture is now present without install and original prep is committed. F1/F2/F3 repaired in uncommitted source/tests/docs; F4/F7 disclosed only, F6 append conflicts preserved. Three focused test files only: intentional RED captured, GREEN controls plus T53 12/12, T55 8/8, T57 13/13 and T58 11/11 pass. No root/native/live/full-suite/CI, commit/push/PR/API/merge, frozen packet or live-pin action.
|
||||
2026-11-02T18:03:53Z | Claude Opus 5.5 implementation sub-agent (lead T3 c5c1e8ba) | #385 PR 1836 repair R3 on work/vikunja-19-385-q284-complete at ab2bc23c7 | R2-F1 fixed: stack-upgrade refuses a library args file holding `--send` after `--` before any unit stops, for upgrade and rollback; R2-I1 component case and R2-I2 TOOLS.md precision added, R2-I3 noted. RED 0/1 then GREEN 2/2; stack-upgrade 23/23, stack-release 225/225, case2-unit 48/48. One local commit; no push, PR, Vikunja, Gitea or live action.
|
||||
2026-11-02T18:19:04Z | Claude Opus 5.5 implementation sub-agent (lead T3 c5c1e8ba) | #385 PR 1836 repair R4 on work/vikunja-19-385-q284-complete at d0ddfa8de | R3-F1 fixed: stack-upgrade refuses `console-unit-legacy` before any unit stops when a library host's installed Console unit runs serve with `--send`, for upgrade and rollback; host-run-sheet section 7 and TOOLS.md updated. RED 24/25 then GREEN 25/25 in stack-upgrade.test.mjs; other suites not rerun (no changed file read). One local commit; no push, PR, Vikunja, Gitea or live action.
|
||||
2026-11-02T18:55:26Z | Claude Sonnet 5.5 implementation sub-agent (lead T3 c5c1e8ba) | #385 PR 1836 repair R5 on work/vikunja-19-385-q284-complete at 484aef7e2 | chat.test.mjs asset test now fetches chat.js and chat.css on the SSO public Host with a signed-in session, pins 403 `public Host required` on the loopback Host and 303 to sign-in without a session; test-only, serve.mjs correct. RED 29/30, GREEN 30/30 in chat.test.mjs; whole packages/webui 495/495. One local commit; no push, PR, Vikunja, Gitea or live action.
|
||||
@@ -25,7 +25,7 @@ const posts = [
|
||||
[`/api/chat/threads/${T}/messages`, { body: ' hi\nthere ' }, 'thread.send', { thread: T, body: ' hi\nthere ', class: 'REQUEST' }, { id: M }],
|
||||
[`/api/chat/threads/${T}/open`, {}, 'thread.open', { thread: T }, { opened: T }],
|
||||
];
|
||||
function http(port, path, { method = 'GET', value, raw, extra = {}, host = preview.host, baseHeaders = headers } = {}) {
|
||||
function http(port, path, { method = 'GET', value, raw, asText = false, extra = {}, host = preview.host, baseHeaders = headers } = {}) {
|
||||
const data = raw ?? (value === undefined ? undefined : JSON.stringify(value));
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = request({ host: '127.0.0.1', port, method, path, headers: {
|
||||
@@ -33,7 +33,7 @@ function http(port, path, { method = 'GET', value, raw, extra = {}, host = previ
|
||||
} }, res => {
|
||||
let text = '';
|
||||
res.on('data', c => { text += c; });
|
||||
res.on('end', () => resolve({ status: res.statusCode, data: text ? JSON.parse(text) : null, cache: res.headers['cache-control'], headers: res.headers }));
|
||||
res.on('end', () => resolve({ status: res.statusCode, data: text ? (asText ? text : JSON.parse(text)) : null, cache: res.headers['cache-control'], headers: res.headers }));
|
||||
});
|
||||
req.on('error', reject); req.end(data);
|
||||
});
|
||||
@@ -345,11 +345,16 @@ test('configured Console process injects chat through its existing human transpo
|
||||
|
||||
test('chat assets, GET purity, method and unknown-route refusals are explicit', async t => {
|
||||
const c = await setup(t);
|
||||
// Under --sso the human listener answers only the public Host, and the page assets sit behind the session.
|
||||
for (const name of ['chat.js', 'chat.css']) {
|
||||
const result = await fetch(`http://127.0.0.1:${c.port}/${name}`);
|
||||
const result = await c.get(`/${name}`, { asText: true });
|
||||
assert.equal(result.status, 200);
|
||||
assert.match(result.headers.get('content-type'), name.endsWith('.js') ? /javascript/ : /css/);
|
||||
assert.match(result.headers['content-type'], name.endsWith('.js') ? /javascript/ : /css/);
|
||||
assert.ok(result.data.length > 0, name);
|
||||
const loopback = await c.get(`/${name}`, { extra: { host: `127.0.0.1:${c.port}` } });
|
||||
assert.equal(loopback.status, 403); assert.equal(loopback.data.error, 'public Host required');
|
||||
}
|
||||
assert.equal((await c.get('/chat.js', { extra: { cookie: '' } })).status, 303);
|
||||
assert.equal((await c.get(`/api/chat/threads/${T}/open`)).status, 404);
|
||||
assert.equal((await c.get('/api/chat/private')).status, 404);
|
||||
assert.equal((await c.get('/api/chat/projects', { method:'DELETE' })).status, 405);
|
||||
|
||||
Reference in new issue
Block a user