Commit Graph
85 Commits
Author SHA1 Message Date
jason.woltje 1e1357cb6e feat(console): answer every eligible decision option (#1839) 2026-11-03 17:25:24 -06:00
jason.woltje 38cfa72335 feat(row 333): count dropped proxy usage batches and show them in the Console (Vikunja #778)
The usage queue read drains the proxy. A batch that is then not written (the
client or the bus refuses its shape, an ambiguous key owner, a failed write) is
lost, and the Console showed proxy totals with no sign of it. The reader now
counts these per enabled business since the bus started, the proxy view returns
the count as droppedBatches, and the Console proxy section says so above 0.
A read that failed before the proxy answered or that it refused drained nothing
and is not counted. Telemetry only; no quota reads it. The log line stays
proxy-usage-read-failed.
2026-11-02 20:08:50 -06:00
jason.woltje 3692fca522 fix(row333 R3): per-key quota follows the agent's key lineage across rotation and re-issue (#1831)
Ruling 1: model records keep a bounded previous list (64 ids, oldest dropped)
of ids that left by rotation, grace expiry or re-issue; a fire removes the
record. A tokens.keys leaf matches and counts every id in the lineage that
holds it. Lineage ids are unique host-wide. An orphaned leaf limits nothing,
logs one value-free line when it becomes orphaned, and the Console usage
view lists it.
Ruling 2: an agent with no model key under a key quota refuses
key-quota-no-model-key, passed through the broker, launcher and stop reason.
Ruling 3: covered by the lineage; no mayLaunch change.
Ruling 4: the usage module receives a frozen { readUsageQueue } only.
Ruling 5: every telemetry fixture wait races a 5 s real-timer deadline.
2026-11-02 17:54:07 -06:00
jason.woltje c0c291cda2 merge: join row 333 P5 quotas onto landed row 332 (#1831)
Joins row 333 R2 head 0ef269da9 (base 09a847eda: R1 503b91e56, overlay
2627321f6, docs c012b2e0a and ddb3e961f, R2 fixtures 12eba4b59 and
0ef269da9) onto refactor with row 332 landed at 5df0e9d6f. Run with the
union attributes for BUILD-LOG.md and docs/SESSIONS.md. Two files
conflicted; no other path did.

packages/business/src/launch.mjs, import block: 332 changed the errors
import to `{ BusinessError, refuse }` for the proxy route refusals; 333
added `isDailyModelQuota` from plugins/src/model-quota.mjs for the daily
model leaves under limits.tokens.keys. Kept both: the model-quota import
and the `{ BusinessError, refuse }` import. The rest of launch.mjs merged
without conflict (332's checkModels route handling and checkAccount
credential "proxy"; 333's checkTokenLimits keys block).

packages/plugins/README.md, end of file: 332 appended "Per-session proxy
context (P3)" and 333 appended "Proxy usage telemetry (row333 / P5)" at
the same spot. Kept both sections, P3 first, one blank line between.

The resolved files match the earlier 332 R1 join resolution
(join-resolution.patch) line for line apart from hunk offsets.
2026-11-02 16:33:47 -06:00
jason.woltje 8eb37bed32 row 173 (#1671): a Seen click that waited out a Board read posts what its button said, read from data-intent before the wait; a fresh row that already holds it (another viewer's mark) posts nothing and announces 'already seen' or 'already waiting'; board-held test covers both; BUILD.md design and mutant plan; no runs yet (sage-2799)
(cherry picked from commit 02b50ddf35)
(cherry picked from commit d95be10ec4)
2026-11-02 14:40:12 -06:00
jason.woltje 9936a1be1a fix(webui): require verified OIDC for human writes (#385) 2026-10-29 00:19:02 -05:00
jason.woltje 503b91e561 feat: add optional proxy usage and human model-key quotas (row333) 2026-10-26 17:55:26 -05:00
jason.woltje 362893d043 feat: integrate reviewed proxy page and managed model keys
Source-candidate: poe d9a564e6d20f5f0fd75ce45b12cbbf8bb4c9d568\nSource-candidate: magica38ba5762b06716db1dee00d0afec162656488f5c\nValidated321whole-file phase plus whole bus1349/model-proxy100/webui490; final gate tooling checks pending, not landed.
2026-10-26 12:04:21 -05:00
jason.woltje c0bf87b789 Untested: row 288 library writes, notices, revert and human saves (#1793) 2026-10-25 00:08:18 -05:00
Herb c68a29fed8 build: regenerate editor bundle for inert wikilinks 2026-10-24 22:50:44 -05:00
jason.woltje abc11152a0 Row 266: add Console room timeline and member completion 2026-10-24 12:11:42 -05:00
jason.woltje 360f9a331b row225: prevent checked notice forgery and report definite revert refusals 2026-10-24 10:12:34 -05:00
jason.woltje 35fbdcad01 Untested full gate: row 225 fixes verified by targeted RED-GREEN and library suite 2026-10-24 10:12:33 -05:00
jason.woltje de17e8bc30 morgana: row 225 handoff to fethry (mos-1501), UNTESTED: renderReply, chat replies/cites/notice/Revert/status line, library status and revert routes, channel-proof re-pin of webui bus.mjs 2026-10-24 10:12:24 -05:00
jason.woltje 4a4bef6c13 feat(webui): shared threads and per-grant viewer read-only (193d) 2026-10-23 23:22:19 -05:00
jason.woltje 7e59ba8b3d feat(business): allow businesses without a tracker (#1820) 2026-10-23 18:43:08 -05:00
jason.woltje 712a084124 row 239 (#1745) b1: the fire's and the delete's revoke runs inside writer.write under the lock, after the revision check and the validations; an error after it carries revoked and the bus names it revision-conflict-revoked or outcome-unknown-revoked, with CLI, Console (OPEN, duckworth-0165 C1) and fire-notice texts; the mark sits in a catch around withLock (C2); tests T1-T6, channel-proof re-pins transport.mjs and webui bus.mjs; BUILD.md with mutants M1-M3g and the gate plan; untested, waits for a CLEAR (sage-2792) 2026-10-23 17:00:42 -05:00
jason.woltje 24672fd9d6 row 252: Console inbox Approve and Deny for grant requests, human-only through a console owner proof, confirmation then resolve, via console with human.input before the executor (#1753, Webby N1-N5); tests not yet run 2026-10-23 12:25:39 -05:00
jason.woltje 0ea3db297b row 272: fix session fixture authority and initial chat render 2026-10-23 08:53:07 -05:00
jason.woltje f859d06d20 row 272: preserve granted-user default chat on denied session catalog 2026-10-23 08:53:07 -05:00
jason.woltje 70651f45d8 row 272: retain session recovery state on invalid selection 2026-10-23 08:53:07 -05:00
jason.woltje 490f45f024 row 272: preserve untested session CLI and Console draft (sage-3145) 2026-10-23 08:53:07 -05:00
jason.woltje bb031ec840 launchpad: row 301 (#1808): R6-N4, user-bus.mjs folded into bus.mjs beside humanCall, unchanged; channel-proof re-pin held for Mos's go; unrun 2026-10-23 07:26:44 -05:00
Rocko 049214486b wip: publish unverified row 219 inspection candidate
Preserve the draft for inspection under sage-3113. Tests and mutants have not run. Old-test adaptations approved in mos-1316 and mos-1317 are recorded in OLD-TEST-CHANGES.md.
2026-10-23 05:37:43 -05:00
jason.woltje 26f93fa746 launchpad: row 294 sage-3157, owner-transport exception written out, userOptionsFor, G9 pins no user value, M10/M11 (unrun, #1800) 2026-10-23 01:37:03 -05:00
jason.woltje 52d2a16109 launchpad: row 294 rulings sage-3153 (boot refusal line, owner transport seam G9, C7 follow-up, access.test.mjs unchanged; unrun, #1800) 2026-10-23 01:37:03 -05:00
jason.woltje afef0ea887 launchpad: row 294 FED R6 build and plan, granted-user sign-in (unrun, #1800)
Console granted-user sign-in, a user-cli transport per session, the
per-request grant re-read, the owner-only gate and user page, the notice,
the hub label and peer links, accessContextFor peers, and the bus boot
access wiring (sage-3142). Tests G1-G8 and B1-B3 are written and not yet
run; runs wait for Sage's CLEAR. Choices C1-C9 in
agents/launchpad/work/queue-294/BUILD.md.
2026-10-23 01:37:03 -05:00
jason.woltje e7d21b91b8 feat(webui): show thread claims separately in Agents 2026-10-22 06:40:05 -05:00
jason.woltje f12441d4fa honker: row 256 (#1761) b2: Webby's N1 (webby-0124): instance-settings.mjs:30 and agents.js:46 comments name the assistant, not the chief of staff; BUILD.md note; comment-only, unrun 2026-10-22 05:33:13 -05:00
jason.woltje e617543b8d honker: row 256 (#1761) b1: the human deletes a creative instance and any other actor is refused organization-creative-human-only; protectedRefusal is the delete check and the listing's per-reader endProtected; actor threaded through planDelete/checkDelete/instances.check; fire unchanged; DEFERRED entry closed for delete; tests T1-T8, unrun 2026-10-22 05:33:13 -05:00
jason.woltje 5d2c274420 honker: row 194 b8 S6 (sage-2241, sage-2246, sage-2261): fire's kill end goes through row 191's stopRun with the fire's request as owner, killed and alive come back as lifecycle.end.killed and lifecycle.end.alive and the Console flags a run still alive; terminate stays SIGTERM-only (V3); halted, the pass closes launches and regenerates processing-halted and a halt joins a fire's stop; terminate's pass narrows to runs spawned by the end's time (N6); T9a, T9b, T15, N6 2026-10-22 03:06:41 -05:00
jason.woltje 3521c23c3e honker: row 194 b6 (webby-0094, sage-2241, sage-2245): every instance-writer verb answers restart (B1) and the CLI and Console show it for veto; fire runs the writer's checks against the file before step A, so an unloaded keep can't strand an instance firing; a fire of a delisted name revokes (N1); a host service makes no token reference (N2); only the human re-points a kept instance's model (N3); DEFERRED a human escape for a stuck fire (N4); S6 waits on row 191's stopRun contract 2026-10-22 03:06:41 -05:00
jason.woltje 2311a50e1c honker: row 194 b4 (sage-2164, sage-2166, sage-2217): a hire and the role's hireable list refuse a creative definition; a library mapping change isn't reloaded (T14); the listing's endProtected hides a Delete the server refuses; DEFERRED creative delete; C1 testerNoSignIn closed; row 213's writer-restart pin follows D3 and T16 uses row 196's tester socket 2026-10-22 03:06:41 -05:00
jason.woltje b8c3d00362 honker: row 194 b3 sage-1620: credential-revoke-failed says the business file is unchanged and a retry is safe (CLI and Console), W2 checks the log per case 2026-10-22 03:06:41 -05:00
jason.woltje 14124d96d4 honker: row 194 b3 (sage-1605, sage-1610): fire and delete revoke before the write (T20), a human add takes a tracker bot, a store-only delete names the bot; the tester keeps the credential refusal (row 175 W2); channel-proof and project-runtime pins 2026-10-22 03:06:41 -05:00
jason.woltje e7fb59f225 honker: row 194 on row 199's landing cb5fdb064 (sage-1601): honker/row194-b2 85edab7c7 squashed, five conflicts kept both sides (broker imports, constructor, dispatch, the credential and lifecycle verbs; runtime imports; organization write takes detail and context; cli credentials and veto dispatch; vocabulary comment as row 199 wrote it) 2026-10-22 03:06:41 -05:00
rocko 0fa7bf421f fix: place processing controls within the Console navigation box 2026-10-21 22:42:13 -05:00
rocko 93d211c295 fix: allocate Console viewport space to processing controls 2026-10-21 22:42:13 -05:00
rocko ad6020754d fix: stop processing controls on Console sign-out and preserve layout 2026-10-21 22:42:12 -05:00
rocko 4bdc7e0e86 processing: inspectable per-run stop seam for lifecycle fire
Unify halt and fire cancellation by verified run identity with durable first-owner receipts and shared deadlines. Integrate the instance control with the current host, library and tester-socket paths. Focused nine-file evidence is 62 passing tests; broad suites, mutants and review remain pending.
2026-10-21 22:42:12 -05:00
jason.woltje 3315977095 row 254: library.sync 130 s human client timeout, six library-* STATUS entries, channel-proof re-pin, README (#1759)
Candidate megavolt/row254 b31300d79 on c3d88840c, manifest be63cfbe
(7 paths). Dewey APPROVE r1, rev 3006 (#1759 c30173). Gate on Sage's
slot by Megavolt, 23:37:27-23:40:52Z on b31300d79: library 77/77, bus
628/628, webui 305 pass with 1 skip (editor rebuild needs esbuild
0.28.2), every scripts/test-*.sh rc 0; the human-cli timeout and
library-fetch-failed STATUS mutants killed by their behaviour tests.
Landed onto 41b0cf755 with the candidate's blobs and modes for the 7
paths; c3d88840c..41b0cf755 touches none of them. Merged-tree rerun of
library, bus, webui and cli on Sage's slot before the push.
2026-10-21 18:44:22 -05:00
jason.woltje 7247d80c7a row 196: human boundary on peer credentials, interpreter receipt and the Console tester socket (#1694)
Candidate 527b9a1e6 (gander/row196-r6-prd19, base f48725cfc), the 39 manifest paths of CANDIDATE.sha256 537d30aef70b6cd1 at ec1e7fad8. Duckworth approved round 1 outside B1/B2 (rev 2973, comment 30145) and round 2 merge-scoped (rev 2986, comment 30156). Gate gander-0066 on grant sage-2145: 2334 pass, 0 fail, 1 skip; mutants 38/38 killed. BUILD-LOG lines and Duckworth's C1 DEFERRED entry follow as a doc-only append.
2026-10-21 15:55:39 -05:00
jason.woltje 0b33f5e9db row 222: C2-03a fetch-only library sync, askpass helper, bus verb and timer (#1723)
Candidate c9aa9c2ee (megavolt, manifest c2121b55, 15 paths), approved by
Dewey (rev 2966, comment 30138). Gate on Sage's slot by Megavolt,
20:08:37Z to 20:11:33Z: library 77/77, bus 609/609, webui library-cli 1/1
and pinned-copy 10/10, cli stack-copy 17/17, every scripts/test-*.sh rc=0,
fixture tokens 0 hits; mutant kills carried from 4a0e0ab3a with equal blobs.
2026-10-21 15:13:31 -05:00
jason.woltje e54e054632 row 215: C2-04 the library entry in the business file, consumer skips, M9 organization-projects-protected, the bare mirror, library.file and library.status (#1716)
The business file accepts a kind "library" project entry, and each consumer
that assumed a project root skips it. An organization write whose projects
differ from the file's is refused (M9). The bare mirror is created at the
projectRepo path with no remote. library.file and library.status are human
only and refuse an agent session with human-required.
Candidate herb/row215-on197 dde3445ab on a36523713, Filbert APPROVE rev 2924.
2026-10-21 14:24:37 -05:00
jason.woltje 4429a104f6 webui: Q175 phase 1, the Console verifies SSO itself under --sso, OIDC RP with oauth4webapi 3.8.8 (row 192, #1690)
Squash of Launchpad's launchpad/row192 53bb59462..37582e820, manifest round 2
6f8cee147713c53652b58d47c5efd15ed47da1efbef6a126464857269b0b7787 (18 paths).
Sage's gate on 088087ac9: package suites 2758 pass 0 fail, scripts/test-*.sh
429 pass 0 fail; mutants 22 of 23 killed, #23 (second origin check) declared
equivalent by Launchpad (sage-1407). New dependency oauth4webapi 3.8.8: the
canonical checkout and any stack copy need npm ci. No live change; the live
re-pin is a window with Mos (mos-1099 item 3).
2026-10-20 16:21:29 -05:00
rocko b2b33aee55 row 178 (#1676, P19 385): the Console checks a proxy proof header on public Hosts
webui serve takes --proof-header NAME --proof-file PATH, only with the --public-host preview flags.
Before listen it reads the file once through O_NOFOLLOW and fstat: a regular file owned by the
Console uid, mode 0400 or 0600, at least 32 base64url bytes with one optional final LF. Any file
problem gives one fixed refusal that names neither the path nor the contents. The header name can't
collide with Host, Origin, auth or tester names.

On a public Host the guard runs before any auth header is read. It needs exactly one proof header
and compares equal-length buffers with timingSafeEqual. Missing, wrong and repeated proofs get the
same fixed 401. A proof header on another Host or on the tester listener gets 403. The existing
auth, Origin, Fetch Metadata and human write checks are unchanged.

webui-service.sh renders both flags and checks the file's metadata and canonical location without
opening it, and the send-status regex accepts the proof pair. stack-release.sh only gains a comment:
it already carries Console flags through re-pin and rollback, and new tests pin that.

This is a partial fix. Same-uid seats can still read the proof file. Activation (middleware, unit
flags, restart, smoke) is a separate Mos-checked window and isn't part of this commit.

Dewey approved round 2 in #1676 comment 29386, candidate 9300a670. Round 1 changes were in 29374.
2026-10-20 00:37:08 -05:00
Researcher d1272e714f row 183 (#1681): chat.mjs names the transport it is given
The chat.mjs header comment now says the seam takes the bus transport it is given: the human one
from the signed-in listener, the tester one from the row 176 listener (row 177). The TypeError for a
missing or non-function call says 'chat needs a bus transport function' and no longer says human.
No behavior changes. The webui README doesn't repeat either phrase and is unchanged.

A new chat.test.mjs test passes undefined, null, a string, a number, an object, an array and no call,
and reads the new TypeError text. Putting the old text back fails it.

Dewey approved round 1 in #1681 comment 29376. Their notes (the tester line names no file, and the
test title says both transports pass when only a stand-in function does) need no change.
2026-10-20 00:03:28 -05:00
dewey 1f994257a5 row 177 (#1675, Q173): tester threads
The tester gets threads of its own: thread.create, thread.open, thread.send, thread.messages and
assistant.stop join TESTER_VERBS, with owner `tester`, and neither the tester nor the human reaches
or lists the other's threads. A tester thread.send is from tester-cli with no human.input; in a
tester thread the lists read the tester as the human, the run answers at `tester`, and its send to
`human` refuses tester-thread-human. The tester stop revokes only tester threads, by `tester`. A
business whose human is `tester` refuses invalid-business at start.

The tester listener (7333) serves chat through the TESTER_CLI caller, its fence admitting only the
four chat write routes, with the listener's own Origin required; 7332's chat is unchanged. The
Console composer is enabled for the tester. READMEs state calls (a)-(c), N1, N2 and where a tester
reads replies (sage-1148).

Design 99ce5780 approved in sage-1146 (#1675 comment 29333).
2026-10-19 22:21:55 -05:00
jason.woltje 89af38a83a webui, bus, scripts: a loopback-only Console listener for the tester; 7332 refuses x-mosaic-tester (row 176, #1674)
serve --tester-port N starts a second listener on 127.0.0.1:N in the same
process, with a bus caller through TESTER_CLI. N is 1024..65535, not
--port and never 7332, and the flag needs the bus configured. The tester
listener takes only instances.set, routes.set and name.set; settings
save, project-file save, assistant stop, bus message and chat writes
refuse 403 with no bus call. It refuses the main listener's auth header,
and every other listener refuses any request carrying x-mosaic-tester.
/api/config answers tester: true and the page shows a tester banner with
the routes, instances and seat name editors only. tester-off and
tester-required map to 403 in a serve.mjs coreBusStatus wrapper, so
bus.mjs stays pinned (row 164).

The broker lets a tester read credentials (with #secretCheck), routes,
project.files and project.file; project.file.save stays human-only.
webui-service.sh takes --tester-port with serve's checks. stack-release
activate --tester-port N writes the flag to the pointer and the unit,
refuses tester-port-target when the target copy's Console lacks it, and
activate or rollback to such a copy drops the flag and says so in --plan.
docs/TOOLS.md rewords the stale row 175 two-phase step (#1673 F1).

Built by Rocko on 473258a51 (manifest a4c728fc...52c9), approved by Dewey
in round 2 (#1674 comment 29322) after round 1 changes (29309), Sage's
gate green on 473258a51 plus the patch in run 2. Run 1 failed T34's
failed-pm_launched subtest with capture-failed: activate and pm-on name
the activation by the second, so the two ran in one second and collided
on the rollback set. That race is row 169's (the base fails the same way
with the id pinned), and a follow-up row fixes it (Vikunja P19 391).
2026-10-19 20:18:14 -05:00
jason.woltje be10e0c838 webui: a Seen click during a Board read waits for the read and posts, and the row 165 test loads the page instead of reloading from an evaluate (row 172, #1670)
The click handler returned on busy, which refresh() holds for the whole /api/board read, so a click during a
poll did nothing and the sign-out test waited 5 s for a sign-out that was never asked for. The row 165 test's
location.reload() from an evaluate let the next wait start on the old document, and the reload killed it.
2026-10-19 15:34:00 -05:00