579 Commits
Author SHA1 Message Date
RockChinQandmultica-agent 0608408352 chore(deps): pin langbot-plugin 0.7.19 (#2801)
* chore(deps): pin langbot-plugin 0.7.19

Co-authored-by: multica-agent <[email protected]>

* test(agent): accept the SDK 0.7.19 cancel_peer_on_cancel handoff in runtime doubles

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-28 19:26:01 +08:00
RockChinQandmultica-agent 0219007acd fix(qqofficial): correct group mentions and reply sequences (LANG-181) (#2799)
* fix(qqofficial): preserve native mentions and reply sequences (LANG-181)

Co-authored-by: multica-agent <[email protected]>

* fix(qqofficial): respect group mention rendering capability

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-28 18:43:18 +08:00
4b537973f9 feat(plugin): upload debug plugin to LangBot Space with optional GitH… (#2612)
* feat(plugin): upload debug plugin to LangBot Space with optional GitHub sync

- SDK: reusable in-memory .lbpkg packaging + git sync helper (local git by default, optional repo/token override)
- routing: space-upload config/upload/git-sync endpoints; debug plugins resolved via OSS bridge without touching get_plugin_info
- frontend: debug-card entry + upload dialog with multi-language metadata, icon upload and changelog
- i18n across 8 locales; operation-trace + action allowlist entries

* fix(plugin-space-upload): stable dialog width, single-line locale tabs, broader error surfacing

- fixed dialog width so toggling the GitHub section no longer resizes it
- language tabs render on one line (horizontal scroll when needed)
- surface the real upload/git error message (msg field) instead of [object Object]
- hint that a missing GitHub repo is auto-created when a token is provided

* fix(plugin-space-upload): narrow dialog and reset sm:max-w clamp

The base DialogContent applies sm:max-w-lg at the sm breakpoint, which overrode the unprefixed max-w-none and clamped the upload card to 32rem on desktop. Set an explicit sm:max-width and size the card to ~36rem. Locale tabs now wrap instead of scrolling horizontally.

* fix

* fix(plugin-space-upload): address CI and UX feedback

- narrow the upload dialog to ~36rem and reset the sm:max-w clamp
- guide the publisher to the Space review page after a successful upload
- drop the redundant null comparison flagged by code quality
- update the operation-action expectation and Space/LangBot Account wording
- ruff format the touched API modules

* feat(plugin-space-upload): public repo, editable author/license, card red dot

* fix(market): replace yellow download count with update available badge

* style(market): unify installed and update indicators into badges

* feat(plugin): redesign debug card banner, style debug icon, and prioritize debug plugins

* feat(plugin-space-upload): simplify upload dialog layout, add creator verification and market redirection

* fix(i18n): use LangBot Account terminology in Space upload dialog

Co-authored-by: multica-agent <[email protected]>

* style(i18n): reflow reworded locale strings for prettier

Co-authored-by: multica-agent <[email protected]>

* test(utils): stop timing out the pattern-count cap test on loaded runners

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Hyu <[email protected]>
Co-authored-by: RockChinQ <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 18:23:09 +08:00
Chin Rockandmultica-agent 4687fc96e7 fix(auth): allow sole OSS account to adopt Space email
Co-authored-by: multica-agent <[email protected]>
2026-10-28 10:21:35 +00:00
RockChinQandmultica-agent 3a77306c3c feat(plugins): consolidate official plugins with independent releases (LANG-180) (#2797)
Co-authored-by: multica-agent <[email protected]>
2026-10-28 17:32:24 +08:00
huanghuoguoguo 82eef2496a fix(http-bot): reset persistent conversation context through shared service (#2788) 2026-10-28 10:29:17 +08:00
0c99832298 fix(qqofficial): receive full-group messages and preserve bot mentions (#2769)
* fix(qqofficial): support full-group messages and native bot mentions

* test(qqofficial): cover full-group form reply targets

---------

Co-authored-by: Chin Rock <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 09:57:00 +08:00
6b57a1074f fix(events): normalize millisecond timestamps before datetime conversion (LANG-170) (#2722)
* fix(events): normalize millisecond timestamps before datetime conversion

- run_journal: _event_time_to_utc normalizes second/millisecond/
  microsecond epoch values (loop-divide above 1e10) with guards for
  bool/non-numeric/zero/non-finite inputs; OverflowError contained
- run_ledger_store, interaction_store: divide epoch values above 1e11
  by 1000 before datetime conversion; OverflowError added to the
  handled exceptions

Second-based inputs are unchanged. Verified in production on a
self-hosted v4.11.0 deployment.

* fix(events): harden timestamp conversion and cover persistence regressions

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: leonoxo <[email protected]>
Co-authored-by: Chin Rock <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 23:49:01 +08:00
Li-john1021andLi-john1021 bd4e408d7e fix(plugin): honor display_plugin_debug_url port for managed Runtime (#2782)
Stdio and Windows launches always bound the SDK default debug port 5401,
so changing plugin.display_plugin_debug_url only updated the console URL
and a second Core instance hit Address already in use. Pass the configured
debug (and Windows control) ports into the Runtime CLI, and document the
behavior.

Fixes #2713

Co-authored-by: Li-john1021 <[email protected]>
2026-10-27 20:56:26 +08:00
Martin 12debe2747 fix(plugin): persist v4 runtime state and tolerate runner registration gaps (#2774)
Persist the v4 plugin runtime state so recreating the runtime container no
longer discards installed plugins' artifacts, dependency environments and
installation-private data, and stop a transient Runner registry miss during
steering from dropping the message.

- docker-compose: bind-mount ./data/plugin-runtime for the plugin runtime
  alongside ./data/plugins.
- kubernetes: add the langbot-plugin-runtime-state claim (5Gi) mounted at
  /app/data/plugin-runtime, kept separate from the plugin data claim so
  runtime state does not land inside the plugin directory.
- chat handler: treat RunnerNotFoundError while claiming steering as
  "steering unavailable" and continue with a normal run; every other error
  keeps propagating. The runner error imports move to module scope, which
  the new early reference requires.
- tests: cover the steering fallback, the claimed-steering interrupt, and
  the lasting-gap path that still reports runner-not-found.

The steering fallback buys one extra uncached registry lookup while a
runtime reconnects; it does not recover a gap that outlasts the message.
2026-10-27 20:31:49 +08:00
Dongze Yang 6990607c5c Merge pull request #2743 from ydzat/fix/normalize-access-control-ids
fix(pipeline): normalize IDs in wildcard access control
2026-10-27 20:18:51 +08:00
0582d1b3d4 chore: rename internal docs/ to dev-docs/ and prepare docs site merge
Move the 27 internal design docs (87 tracked files) from docs/ to dev-docs/
to make room for the public documentation site, adjust Docker/fnOS ignores,
refresh the README/AGENTS/ARCHITECTURE references, and land the docs
workflows ahead of the subtree import so they cannot diverge from mirror.

Co-Authored-By: Mika (Multica) <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 08:04:20 +00:00
huanghuoguoguo 7865ad51f7 perf(plugin): negotiate ordered batch event dispatch (#2778) 2026-10-27 11:36:47 +08:00
huanghuoguoguo 62c0f46dc4 perf(persistence): avoid formatting missing SQL attribute errors (#2776) 2026-10-27 11:19:44 +08:00
huanghuoguoguo fd255a13f4 perf(pipeline): skip redundant binding reads for silent stage output (#2777) 2026-10-27 11:19:33 +08:00
Guanchao Wang 1d3c47c439 fix(wecomcs): preserve provider error details (#2772) 2026-10-26 18:05:38 +08:00
huanghuoguoguo b1b7ddc259 feat(skill): wire standard host skill contract (#2771)
* feat(skill): wire standard host skill contract

* chore(skill): pin bounded SDK revision

* fix(skill): correct SDK pin and formatting

* chore: use released SDK 0.7.17

* fix(deps): validate nested component imports with SDK 0.7.18rc1

* fix(deps): pin validated SDK 0.7.18
2026-10-26 12:11:27 +08:00
bifangknt bba442a8d3 test(vector): prevent event loop leak in base database test
Use pytest-asyncio and await instead of asyncio.run() to preserve
pytest's event loop lifecycle.
2026-10-25 00:14:41 +08:00
彼方 a75f9e2953 Merge pull request #2768 from langbot-app/fix/sqlite-startup-wal-checkpoint
fix(sqlite): reclaim startup WAL and ship patched SQLite
2026-10-24 23:45:56 +08:00
bifangknt 73d5c7d46e test(storage): make SQLite query plan assertions version-independent
Classify event cleanup queries by selected columns instead of CORRELATED
plan text, preserving covering-index, primary-key, and no-sort checks.

Validated all 15 tests on ARM64 with SQLite 3.53.4 and 3.46.1.
2026-10-24 23:23:55 +08:00
RockChinQ 4b4830d4b6 Merge pull request #2542 from Nikarhub/feat/box-local-env
feat(box): 支持 box.local.env 注入每次 exec,便于 skill 读取配置/凭据
2026-10-24 20:19:44 +08:00
49afd9f320 fix(box): ignore box.local.env in multi-workspace deployments
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-24 12:06:00 +00:00
BiFangKNT 95a378a8f1 fix(persistence): reclaim oversized SQLite WAL files
- Require successful WAL truncation before starting application producers
- Preserve completed migrations and retry checkpoint failures on restart
- Set a 64 MiB WAL retention limit on every SQLite connection
- Preserve default automatic checkpoint behavior and reader snapshots
- Cover startup failures, connection recreation, and WAL reclamation
2026-10-24 02:03:41 +08:00
BiFangKNT 4eafc3c22e test(mcp): reduce scope retirement test overhead
- Replace per-session mocks with lightweight shutdown counters
- Preserve the one-second timeout and 100-workspace coverage
- Assert that every session shuts down exactly once
2026-10-24 00:52:50 +08:00
BiFangKNT 93e5ae4689 fix(persistence): replace online SQLite VACUUM with incremental reclamation
- Add migration 0042 to enable incremental vacuum with verified backup and restore
- Enable incremental vacuum before creating tables in new SQLite databases
- Adapt reclamation batches to elapsed time and lock contention
- Cover migration recovery, WAL mode, and concurrent writes with regression tests
2026-10-23 23:59:00 +08:00
BiFangKNT ce5b7ffea1 fix(agent): preserve terminal events when cancelling runner execution
Emit and persist a Host cancellation event before closing the runner stream.
Preserve existing terminal events and record cancelled runs consistently.

Serialize Host event sequence allocation to prevent conflicts with admin
cancellation audits, and notify observers with the persisted sequence.

Add deterministic cancellation and concurrent event allocation regressions.
2026-10-23 17:23:44 +08:00
BiFangKNT 24ce4ebe47 perf(persistence): remove unused resource URL indexes
- Keep only primary-key and URL-hash unique indexes
- Fold index cleanup into migration 0041
- Verify SQLite and PostgreSQL migration behavior
2026-10-23 14:58:22 +08:00
BiFangKNT 5d774ff555 fix(persistence): resolve resource URL migration and scoped SQL failures
- Reflect migration tables without resolving foreign-key targets
- Allow validated resource URL expansion through the tenant SQL AST guard
- Add regression coverage for trusted and malformed expansion expressions
2026-10-23 14:39:38 +08:00
BiFangKNT 3456668497 feat(media): centralize resource URLs and persist refreshed image URLs
- Deduplicate message and history resource URLs using stable catalog references
- Persist renewed URLs with concurrent refresh protection
- Refresh OneBot images via get_msg intervals or NapCat rkey TTL
- Migrate historical payloads and cover SQLite and PostgreSQL behavior
2026-10-23 12:49:56 +08:00
BiFangKNT 1be47ae925 fix(monitoring): refresh image URLs in execution details
- Refresh images in inputs, outputs, deliveries, and conversation history
- Reuse OneBot refresh logic without rewriting persisted records
- Cover existing image URLs across agent and pipeline execution views
2026-10-23 10:21:54 +08:00
BiFangKNT e3c7e49214 test(provider): initialize Codex requester fixture 2026-10-23 09:02:23 +08:00
BiFangKNT baddaa2b74 feat(onebot): refresh expired image URLs in history and model requests
- Cache NapCat rkeys by type and refresh only when their TTL expires
- Renew image URLs through get_msg for other OneBot v11 implementations
- Refresh session views, Runner history, and each model request attempt
- Isolate caches by connection without downloading images or rewriting history
2026-10-23 08:41:50 +08:00
RockChinQ 7fa9c0e426 fix: 修复独立环境登录 404 与「添加第一个模型」500(4.11 回归) (#2755)
* fix(space): keep dedicated-environment Space login working

A dedicated environment runs the OSS runtime with system.edition=cloud. The
process-level 'LangBot Models' compatibility provider is part of the OSS
single-Workspace contract, but write_space_model_providers() skipped creating it
for every non-community edition. The Space OAuth callback then unconditionally
rewarded the provider row by api key, so provider_service raised
WorkspaceNotFoundError('Provider not found') and the whole callback returned 404
-- after the Account and its Workspace had already been created. Every retry
failed the same way, making dedicated-environment login impossible on 4.11.x.

Gate the compatibility provider on the deployment shape instead of the edition
(genuine multi-tenant Cloud runs in CLOUD_RUNTIME persistence and never reaches
this path), and treat a missing provider row as a model-routing warning rather
than an authentication failure so a data anomaly can never block login.

* fix(agent): bind the first model to the 4.11 runner config

create_llm_model() still wrote the auto-selected model into the pre-4.11
ai['local-agent'] container. On a 4.11 Workspace that key does not exist, so the
assignment raised KeyError and POST /provider/models/llm returned 500 the first
time a user added a model -- and the default pipeline kept primary='', so every
Agent run failed with 'No authorized model for local-agent'.

Delegate to RunnerDefaultConfigService, which resolves the selected runner and
writes the schema-defined model selector into ai.runner_config[<runner id>].

Also default the NOT NULL description column on pipeline and bot creation:
omitting an optional description returned a 500 from the constraint instead of
creating the resource.

* fix(agent): keep seeding the model for pipelines that never migrated

set_pipeline_llm_model_if_empty() returns False when a pipeline has no 4.11
runner selected -- that is exactly the un-migrated shape, which still carries
ai.local-agent. Seed that container, but only when it exists, so the legacy path
keeps its old behaviour without the KeyError.
2026-10-22 23:26:30 +08:00
RockChinQandmultica-agent da508f9603 fix(plugin): reject archive entry names the SDK would refuse to extract (#2757)
The host inspects a package to read manifest.yaml and requirements.txt before the
SDK extracts it. Inspection normalized entry names with only
replace('\\','/').strip('/'), so it accepted names its own extractor rejects
(absolute paths, '..' components, drive letters) and it silently kept the first
member when two normalized to the same path.

There was no traversal write, because the SDK's _extract_verified_zip validates
every member before writing and the host only reads members by ZipInfo. The bug
is the divergence: a package could pass inspection and then fail to install, and
the two rule sets could drift further as either side changes.

Inspection now applies the same rule set as the SDK, via
_normalize_archive_entry_name: reject empty/NUL names, absolute paths, any '..'
component and drive letters; reject a duplicate after normalization. '.' and
empty segments are still collapsed, so './manifest.yaml' and 'components//x.py'
keep working.

Tests: 13 cases covering each rejection, the duplicate, traversal taking
precedence over the duplicate check, and two positive cases (nested/unicode
layout, cosmetic separators).

Co-authored-by: multica-agent <[email protected]>
2026-10-22 22:04:36 +08:00
RockChinQandmultica-agent 0b341086fb LANG-145: enforce credential-session TTL on a timer, not on traffic (#2756)
* fix(platform): enforce credential-session TTL on a timer, not on traffic

The four adapter registration flows (Lark one-click app, DingTalk device flow,
WeCom bot, QQ Official bind) each park a short-lived secret in an in-memory
session dict until the caller persists it: app_secret, client_secret, or the bot
secret.

Each store had a TTL and a cleanup function, but the cleanup only ran at the top
of a route handler. An abandoned flow therefore kept its secret in memory until
some *other* request happened to arrive, which for a quiet instance can be far
past the validity window (15 min for Lark, 10 for DingTalk, 5 for WeCom/QQ).

Changes:
- Move the sweep to module level as _sweep_credential_sessions(stores) so it is
  directly testable, and have it scrub app_secret/client_secret/secret as it
  evicts, so an evicted session dict no longer retains a readable credential.
- Add a background sweeper task started from the router group's initialize(),
  running every 60s, so the TTL holds regardless of traffic.
- Keep the per-route cleanups: they make eviction immediate under load.

Tests: 9 new cases (expiry, fresh sessions survive, secret scrubbing, per-store
TTL, cancelling a pending handshake task, not cancelling a finished one,
malformed session without created_at, multiple evictions, empty stores).

Co-authored-by: multica-agent <[email protected]>

* fix(platform): tolerate a task manager without create_task when starting the sweeper

The sweeper is started from the adapter router group's initialize(). Some
embeddings of the app provide a task manager that only exposes create_user_task,
so an unconditional create_task broke those harnesses. Fall back to the per-route
cleanups when create_task is unavailable.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-22 21:51:01 +08:00
RockChinQandmultica-agent c759da50b1 fix(adapters): stop SSRF and arbitrary local file reads in media handling (#2753)
The platform adapters fetch URLs and open paths that come from inbound
messages, so both are attacker-influenced.

New guard module pkg/utils/outbound_url.py:

- assert_safe_outbound_url: checks the scheme, rejects literal private /
  loopback / link-local / reserved / multicast addresses, and resolves the
  hostname so a public-looking name pointing at an internal address is refused
  too. Optional allowed_domains confines a fetch to a known prefix.
- assert_safe_local_media_path: resolves a caller-supplied path and requires it
  to stay inside the media roots (data dir + temp dir), so symlinks and .. cannot
  escape. Directories are refused.

Wired in:

- DingTalk send_message: session_webhook is taken from the inbound event and was
  POSTed verbatim, so a forged event could redirect reply content (including LLM
  output) to any host. Now restricted to dingtalk.com.
- DingTalk send_attachment: component.url was fetched with no destination check;
  now goes through the SSRF guard, which also covers cloud metadata.
- DingTalk upload_image_media: caller-supplied file_path was opened directly; now
  confined to the media roots.
- Slack attachment_bytes: component.path was opened directly and uploaded to the
  channel (arbitrary file exfiltration); now confined to the media roots.
- Slack download_media: redirects were followed with no destination check. Every
  hop is now validated, the hop count is bounded, and a redirect off the Slack
  domain drops the bearer token.

Tests: 25 new cases for the guard (internal address forms, scheme rejection,
suffix impostor, traversal, symlink escape, directory). The Slack credential test
now stubs DNS because the guard resolves before fetching, and asserts
allow_redirects is False for every case since redirects are handled manually.

Co-authored-by: multica-agent <[email protected]>
2026-10-22 20:46:27 +08:00
RockChinQandmultica-agent 01789e498a LANG-145: bind WebAuthn to server config and make passkeys OSS-only (#2744)
* LANG-145: bind WebAuthn to server config and make passkeys OSS-only

Two problems in the passkey implementation:

1. The RP ID and expected origin came from the request: a JSON 'origin' field,
   then the Origin/Referer headers, then the request URL. WebAuthn's
   anti-phishing guarantee depends on values the server chose; trusting the
   request lets a sibling host under the same registrable domain obtain a valid
   assertion for a victim's credential. Resolution now follows the same rule the
   OAuth and invitation links already use: api.webui_url, then
   api.webhook_prefix, then the configured port on loopback.

2. Passkeys are now an OSS-only feature. Cloud deployments authenticate through
   their own account service, so every passkey route (register options/verify,
   auth options/verify, list, rename, delete) refuses with
   edition_unsupported, and /account-info advertises neither passkey_login_enabled
   nor passkey_supported. Both cloud flavours are covered: system.edition ==
   'cloud' and deployment.mode == 'cloud'.

Tests:
- New unit suite for the edition matrix and for origin resolution (including
  that client-supplied origin/Origin/Referer are ignored).
- The three 'reverse proxy scenario' tests asserted the old, unsafe behaviour
  (server trusting the request). They now assert the server-config contract.
- test_smoke cloud capabilities expectation updated to passkey_* = false.

Co-authored-by: multica-agent <[email protected]>

* style(api): drop the typing import left unused by the WebAuthn origin change

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-22 20:39:21 +08:00
huanghuoguoguo cc19395f5c perf(core): reduce execution projection and dispatch overhead (#2746)
* perf(core): join execution projection and reuse authorized tool schemas

* perf(pipeline): avoid duplicate checks before stage output validation

* perf(plugin): reuse reconciled settings within event dispatch

* fix(workspace): keep execution projection reads free of unrelated flushes
2026-10-22 20:00:42 +08:00
huanghuoguoguo 7a410bcb31 test(core): strengthen handler contracts and report source quality (#2632) 2026-10-22 17:33:09 +08:00
RockChinQandmultica-agent d45b0a3957 feat(cloud): add configurable Cloud-only WebUI notice banner
Cloud deployments need a way to tell readers what is happening to the
instance they are using (maintenance windows, service notices) without
shipping a release per notice.

Add a cloud.banner config block (switch, tone, dismissal, link targets and
per-language copy) and expose the resolved banner on the unauthenticated
/api/v1/system/info payload so the WebUI can render it before login. The
banner resolves to null on OSS deployments, so a self-hosted copy of
config.yaml never shows managed-service copy. Copy is plain text; only
absolute http(s) link targets are rendered.

The WebUI renders it once from the root layout, offsets the fixed app shell
and the wizard through --cloud-banner-height, and keeps a dismissal bound to
the notice it dismissed so new copy reappears.

Co-authored-by: multica-agent <[email protected]>
2026-10-21 16:26:43 +00:00
RockChinQandmultica-agent d13ae56ea5 fix: bot routing setup and busy-session response checks (#2728)
Apply group response rules before busy-session steering. Initialize usable private-message and group-mention routes for new bots, including Wizard-created pipelines, and preserve member-configured rules across saves and retries.

Fix empty pipeline configuration, refresh the processor sidebar after automatic creation, and show creation feedback. Align routing regressions and use Node 24 for the browser CI job.

Correct the task's erroneous agent attribution while preserving every code tree and the original human contribution.

Co-authored-by: multica-agent <[email protected]>
2026-10-20 21:22:53 +08:00
RockChinQandmultica-agent f8e32ef14f LANG-134: Finish original inbound monitoring row on pipeline error (#2729)
* fix(inbound-error-state): Finish original inbound monitoring row on pipeline error (LANG-134)

* fix(pipeline): finalize monitoring on early exits and cancellation

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-20 20:39:10 +08:00
RockChinQ 819f65bd8a Merge pull request #2731 from langbot-app/task/LANG-136-explicit-response-files
LANG-136: Deliver explicit attachments without implicit Box scan
2026-10-20 19:46:48 +08:00
RockChinQ 71feb33244 Merge pull request #2730 from langbot-app/task/LANG-135-safe-history-indexes
LANG-135: Guard 0039 indexes against missing historical columns
2026-10-20 18:11:30 +08:00
Chin Rock 0990cc429d fix(explicit-response-files): Deliver explicit attachments without implicit Box scan (LANG-136) 2026-10-20 07:54:05 +00:00
Chin Rock 4d91903596 fix(safe-history-indexes): Guard 0039 indexes against missing historical columns (LANG-135) 2026-10-20 07:54:02 +00:00
Chin Rock 40d40204cf fix(install-diagnostics): Sanitize plugin installation network diagnostics (LANG-132) 2026-10-20 07:53:56 +00:00
彼方 1baba1b9f9 Merge pull request #2725 from langbot-app/fix/session-summary-persistence
fix(monitoring): persist session summaries to avoid history scans
2026-10-20 11:53:06 +08:00
BiFangKNT 3b1ea56f4f fix(monitoring): avoid historical payload reads in execution filters
- Add covering indexes through migration 0040
- Preserve PostgreSQL FORCE RLS state when marking historical summaries
- Add query-plan and migration regression tests to CI
2026-10-20 10:45:44 +08:00
BiFangKNT 7129e20cf6 fix(monitoring): paginate conversation IDs before loading message payloads
Count and paginate lightweight records, then load payloads only for the
selected page to avoid materializing large historical messages.

Add regression coverage for oversized history, ingress deduplication,
stable pagination, and PostgreSQL tenant isolation.
2026-10-20 09:34:05 +08:00