Commit Graph

8122 Commits

Author SHA1 Message Date
Katia Bulatova d12e6a85ca style(webapp): merge duplicate imports on the user-actor auth path 2026-08-06 09:24:09 +00:00
Katia Bulatova f58a9dcc89 fix(webapp): only let the browser set the agent's page context
The chat turn's metadata is now a whitelist: the page the user is on is all the browser can set, and every identity, tenancy and token field is filled in by the server.
2026-08-06 09:24:09 +00:00
Katia Bulatova d51cb9a736 fix(webapp): stop the OSS fallback handing a delegated token blanket access
Without an RBAC plugin, a user-actor token got the same permissive ability a personal access token gets. It now gets only what its own scope cap allows, and reads only when it declares no cap. Personal access tokens are unchanged.
2026-08-06 09:24:08 +00:00
Katia Bulatova 9d45284112 fix(webapp): keep the agent token's environment claim on the actor through every route builder
The claim rode beside the authentication result, so a route builder that only forwarded the user id lost it. It now travels on the authenticated actor itself, and a route's resolved org/project/environment is checked against it — a mismatch fails closed.
2026-08-06 09:24:07 +00:00
Katia Bulatova 880bf60f48 test(tsql): pin that no mutating query can pass the query boundary
The agent's run_query path compiles TRQL, which has no write statements, so a
mutation cannot parse. Cover the deny-list evasions a keyword filter would miss
(casing, comments, a statement smuggled after a semicolon) and keep positive
controls so the negatives can't pass by rejecting everything.
2026-08-06 09:10:22 +00:00
Katia Bulatova f5a146b30c fix(webapp): cap the agent's body on any method and on a mixed-case path 2026-08-06 08:50:11 +00:00
Katia Bulatova 85b98ab8dc fix(webapp): mint the agent's token for the caller's own environment, or not at all 2026-08-06 08:20:52 +00:00
Katia Bulatova 62b598da27 docs(webapp): say which layer refuses an oversized agent body
The route-level check only sees a declared content-length; a body without one is
already ended mid-stream by the ingress cap.
2026-08-06 07:14:41 +00:00
Katia Bulatova 1cdf1f087d refactor(webapp): split the dashboard agent's maintenance cron along the watch seam
dashboardAgent.sweepWatches ran the watch sweep, the investigation sweep, the
batch re-arm and eval retention together. Watch is about to ship as its own
stacked PR, so the job is split where the cut will be: dashboardAgent.maintenance
keeps the investigation sweep and eval retention, dashboardAgent.watchMaintenance
takes watch expiry, delivery and the batch re-arm. Same cadence, and each backstop
keeps its own try/catch.
2026-08-06 07:14:41 +00:00
Katia Bulatova 50fd10bf1b fix(webapp): replay a watch submission's recorded outcome instead of re-running it
A retried card submit was only repairable while the first attempt's watch was
still active. Once it had fired, expired, or answered in one shot, the retry
re-evaluated the condition and created a second operation.

A watch_submissions ledger, keyed (chat_id, client_request_id), is now written
before the condition is read and carries the outcome once there is one. A retry
looks it up first: a recorded outcome is replayed, a different draft under the
same id conflicts, and only a pending row proceeds - converging on the watch id
reserved up front rather than creating another.
2026-08-06 07:14:40 +00:00
Katia Bulatova 4ff8859e1d fix(webapp): keep the agent's alert delete to channels the watch type is on 2026-08-06 01:54:46 +00:00
Katia Bulatova cbc2edc879 test(webapp): pin the watch submit's ordering, its retry repair and its refusal record 2026-08-06 01:54:45 +00:00
Katia Bulatova 49a953871a fix(webapp): record a watch request before the watch starts, and repair a retried submit 2026-08-06 01:54:44 +00:00
Katia Bulatova 28b1f3896c fix(webapp): cap the agent's request body while it streams, not after
The message-size checks ran after the body had been read, so a request without a
content-length was buffered and parsed in full before being refused. An ingress
cap on the agent's paths now counts the bytes as they arrive, and the chat proxy
reads its body with a ceiling instead of reading it whole first.
2026-08-06 01:53:17 +00:00
Katia Bulatova d719c9b2d3 fix(webapp): start the wake poll for a browser that has only an active watch
The page load reported unread wakes only, so a fresh browser whose watch was
created elsewhere and hasn't fired yet never started polling: the wake landed
without a toast or a dot until a reload. The loader now returns the active-watch
presence too, in one read per page load.
2026-08-06 01:53:16 +00:00
Katia Bulatova e599f1299c fix(dashboard-agent): rotate an over-cap watch group instead of starving it
The batch took the 500 soonest-expiring watches of a group every tick, so a group
larger than the cap could leave the rest unchecked until the first 500 expired.
The group is now ordered least-recently-checked first, with a generated
cadence_minutes column and an index so the due predicate no longer re-parses the
spec JSON per tick.
2026-08-06 01:53:15 +00:00
Katia Bulatova a3be7bda6b fix(dashboard-agent): cap the output of the summariser and the wake narration 2026-08-06 01:41:05 +00:00
Katia Bulatova 4e39228be1 fix(dashboard-agent): pin only a live investigation into a compacted context 2026-08-06 01:41:04 +00:00
Katia Bulatova ddc6d25a66 fix(dashboard-agent): describe a value at the redaction depth cap instead of passing it to the judge 2026-08-06 01:41:04 +00:00
Katia Bulatova 6c993f213b chore: note the summarised long conversations in the release note 2026-08-06 00:49:02 +00:00
Katia Bulatova 0c41a70fa4 perf(dashboard-agent): cap search_docs to a few short excerpts 2026-08-06 00:49:01 +00:00
Katia Bulatova 42a76fb93d perf(dashboard-agent): say a settled watch outcome without a model, and narrate the rest with Haiku 2026-08-06 00:49:01 +00:00
Katia Bulatova 1d083f3ea9 test(dashboard-agent): budget the real prompt prefix with ceilings and a committed snapshot 2026-08-06 00:49:00 +00:00
Katia Bulatova 99850acc2d feat(dashboard-agent): summarise an oversized conversation, keeping live investigations and watches 2026-08-06 00:48:59 +00:00
Katia Bulatova f96361452a chore(webapp): restore the dashboard agent's flag gate 2026-08-06 00:38:40 +00:00
Katia Bulatova fc32fc61e2 refactor(webapp): split the suggested-prompt registry by responsibility
The chip factory and slot vocabulary, the evergreen docs chips, the per-page slot
table and the signal chips each get their own module; registry.ts is now the
public face that re-exports them. A pure move.
2026-08-06 00:13:25 +00:00
Katia Bulatova 4876e074ed refactor(webapp): give each watch condition family its own module
dashboardAgentWatchChecks.ts keeps the dispatcher, the failure envelope and the
previous-facts reader, and re-exports the run, queue, error and health families
plus the shared reader contract. A pure move; every import path is unchanged.
2026-08-06 00:13:25 +00:00
Katia Bulatova fea1a29220 refactor(dashboard-agent): split the watch tick into delivery, condition, batch and adapters
watch-tick.ts keeps the two task definitions and the per-watch check; the wake
delivery, the condition lifecycle, the group tick and the db/session/callback
adapters each move to their own module. A pure move: watch-tick.ts re-exports
everything it exported before.
2026-08-06 00:13:24 +00:00
Katia Bulatova 31698fa0db refactor(dashboard-agent): split the tool set into one module per responsibility
tools.ts now only assembles ready adapters, in the same frozen key order: the
HTTP/JWT client, result curation, the docs client, the source-read ledger,
evidence canonicalisation, investigation persistence, and the api/navigation/
watch/alert tool groups each own their own module. A pure move.

The prompt-prefix fingerprints are unchanged, which is what keeps the head-start
and agent prefixes byte-identical.
2026-08-06 00:13:23 +00:00
Katia Bulatova 29d9a8e423 chore: note the conversation scoring in the release note 2026-08-06 00:11:26 +00:00
Katia Bulatova 99b89338c3 docs(dashboard-agent): make the eval docs match the code
The docs claimed every turn is judged; the sampled rate, the redaction rule, the code-mode
skip, the opt-out and the retention period are now written down in one place.
2026-08-06 00:11:26 +00:00
Katia Bulatova 263b32467d feat(dashboard-agent): give the golden runs their own eval sample rate
The CI lane reads its own variable and defaults to every turn, so neither lane can change
the other's rate.
2026-08-06 00:11:25 +00:00
Katia Bulatova a4b4ef1b55 feat(webapp): let an organization turn off judging of its agent turns
A per-org feature flag the agent checks before every judged turn, and a turn is judged only
on an explicit yes.
2026-08-06 00:11:23 +00:00
Katia Bulatova 3c5b2d5d6b feat(dashboard-agent): never judge a turn that read source 2026-08-06 00:11:22 +00:00
Katia Bulatova 42ddcffef0 feat(dashboard-agent): keep customer data out of the judged-turn row and the judge
Payloads, outputs, query rows and file contents are replaced by their shape before a turn
reaches the judge, and the row now keeps the derived verdict only.
2026-08-06 00:11:22 +00:00
Katia Bulatova 7f13add1a0 feat(webapp): retire judged-turn rows after 30 days
The table is append-only quality data with no reader, so the sweep now drops rows past
the period in one bounded statement per run.
2026-08-06 00:11:21 +00:00
Katia Bulatova 08dc7ba732 fix(webapp): keep the watch card in step with its draft, and frozen while it submits 2026-08-05 23:48:03 +00:00
Katia Bulatova c3ee6a4dbe perf(webapp): resolve the agent card's links in one request 2026-08-05 23:48:02 +00:00
Katia Bulatova ebad471b43 fix(webapp): cap the size of a message to the agent 2026-08-05 23:48:01 +00:00
Katia Bulatova a0d06e4eec fix(webapp): send the agent wake signal to a browser that has never opened the panel 2026-08-05 23:48:01 +00:00
Katia Bulatova 18dffa6364 refactor(dashboard-agent): give the watch tests their own file
The wake narration and watch investigation cases move verbatim to
watch-actions.test.ts; the scaffolding both test files use moves to
test-support.ts. Same 146 passed / 2 skipped.
2026-08-05 23:42:35 +00:00
Katia Bulatova 46290d1ca6 refactor(dashboard-agent): move the watch wake and investigate lanes out of the agent
Pure move. The wake narration and the consented investigation now live in
watch-actions.ts, reached from one call in onAction; the runtime they share with
the agent's own hooks moves to agent-runtime.ts. Every export is re-exported from
dashboard-agent.ts, so no import path changes.
2026-08-05 23:42:35 +00:00
Katia Bulatova 2ed5d52260 refactor(dashboard-agent-db): move the watch tables into their own schema module
Pure move, re-exported from schema.ts so drizzle-kit reads the same six tables
and the generated SQL is unchanged.
2026-08-05 23:42:34 +00:00
Katia Bulatova 30ec754a37 refactor(dashboard-agent-db): move the watch queries into their own module
Pure move: the watch, wake and batch-chain queries leave queries.ts for
watch-queries.ts, re-exported so every import path still resolves.
2026-08-05 23:42:33 +00:00
Katia Bulatova d6debe8fb7 test(webapp): cover the user-actor token's environment scope on every route that accepts one 2026-08-05 23:34:45 +00:00
Katia Bulatova 5b5a25882f fix(webapp): scope a delegated user-actor token to the environment it was minted for 2026-08-05 23:34:44 +00:00
Katia Bulatova b6ebe55500 fix(dashboard-agent): escape the prefix separator so the file reviews as text 2026-08-05 23:23:40 +00:00
Katia Bulatova a88228c838 chore(webapp): move the agent storybook gallery out to a follow-up
The gallery pages, their fixtures and the screenshot script only exist to
look at the agent UI, so they ship separately. The fixtures two unit tests
read — the report view models and the page contexts — stay here.
2026-08-05 22:30:45 +00:00
Katia Bulatova cafd920060 chore: keep the release notes as one 2026-08-05 22:18:03 +00:00
Katia Bulatova be1cb0458e perf(dashboard-agent-db): index the open investigations the sweep scans 2026-08-05 22:17:43 +00:00