* fix(exec): avoid extra prompts for audit suppression commands
Remove the command-text gate and its dedicated approval/reviewer plumbing. Suppression configuration and audit filtering remain unchanged; normal exec policies still decide execution. Keep only the shipped deprecated SDK signature as a no-op.
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
* fix(exec): avoid extra prompts for audit suppression commands
Worked on by:
- @jesse-merhi
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
OpenClaw-Publication: f1fe3778-77d9-432e-b98f-01f680f2cdd3
* fix(plugins): preserve deprecated suppression approval predicate
Retain the shipped SDK result during infra-runtime retirement without restoring internal execution callers. Document the distinct runtime and plugin migration outcomes.
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
---------
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
* fix(sandbox): read pinned file payloads asynchronously
Keep the Gateway event loop available during sandbox file reads while preserving the admitted descriptor, uncapped tool reads, bounded growth checks, and existing overflow errors.
The focused anchored, boundary, and shell suites pass all 43 tests. Both new scheduling regressions failed before the change and pass afterward; they also verify the opened file survives pathname replacement.
* fix(exec): bound reads of growing literal-tilde scripts
Apply the existing fs-safe byte limit while reading the admitted descriptor,
preserving lazy imports and best-effort preflight handling. A real-file growth
regression fails on the old whole-file read and passes with bounded consumption.
Validation: focused regression, complete changed checks including core and core-test
types, and independent review through P2.
* fix(skills): bound file reads and validate scan cache identity
* perf: bound package and skill artifact hashing memory
Keep small package files on a bounded descriptor read and stream larger or growing files through fs-safe. Reuse guarded skill file handles while preserving both provenance digest formats, package modes, ordering, and link policies.
Synthetic interleaved proof reduced large-file payload buffers from 256 MiB to about 2 MiB, with a roughly 21% median latency cost on the warm-cache fixture. Preserve the small-file fast path after unconditional streaming regressed it.
Validation: 50 focused inventory and skill lifecycle tests, an original-code failing hardlink substitution regression, focused core/script lint, formatting, whitespace checks, and independent P0-P2 autoreview. Integrated types and changed gates remain with the parent task owned dependency install.
* fix: keep skill metadata with its captured content hash
Read the selected skill file once during traversal and reuse those bytes for its content hash and frontmatter. Keep candidate priority and digest records unchanged while streaming support files.
Remove the internal byte-or-hash compatibility shape from package inventory entries. Migrate the E2E fixture and use the existing buffer digest owner for the bounded small-file path.
Validation: 82 focused package, skill lifecycle, and first-hop fixture tests; metadata mismatch regression failed against the previous commit; focused lint and format checks; cumulative independent P0-P2 autoreview clean. Final interleaved synthetic runs retain the 256 MiB to about 2 MiB payload allocation reduction. Integrated types remain assigned to the parent task owned install.
* fix: preserve literal tilde names in skill snapshots
Pass listing-derived skill paths to fs-safe through the retained canonical root. This keeps literal tilde directories from expanding to the user home while preserving root confinement and link admission.
Validation: the extended artifact digest fixture fails on 7579ed1d7723 and passes with the fix; 31 focused skill snapshot and lifecycle tests, lint, formatting, whitespace checks, and independent P0-P2 autoreview pass.
* feat(sessions): enable cross-agent session access by default
`tools.sessions.visibility` now defaults to `all` and
`tools.agentToAgent.enabled` to `true`; both widen access.
Narrow access via `tools.sessions.visibility` (agent|tree|self),
`tools.agentToAgent.allow`, or `enabled: false`.
Document that an omitted/empty allow list permits every agent pair.
Denial copy for narrowed visibility no longer instructs enabling the
already-on policy. Regenerate prompt-snapshot fixtures for the visibility
hedge. Maintainer-directed.
* feat(security): audit default cross-agent session access
Add `security.trust_model.cross_agent_session_access_default`: `info`
for plain multi-agent defaults, `warn` with sandbox/tool-restriction/
multi-user ingress signals. No new config keys.
* test(gateway): drain detached a2a flow between agentId send rows
The announce/ping-pong flow outlives the sessions_send tool request; the second agentId row picked up the first row's follow-up agent call for agent:orion:main, so each row now waits for gateway active work to drain before releasing its test state.
* test(security): mock the cross-agent access collector in the non-deep facade
The readonly-setup-fallback test mocks audit.nondeep.runtime with an explicit factory; it now exports collectCrossAgentSessionAccessFindings so the registered collector resolves under the mock (CI run 33699015755, checks-node-compact-large-21).
* fix(security): scope the cross-agent audit to unsandboxed sessions
The audit finding now names which agents can reach other agents
(unsandboxed sessions, or any session when
agents.defaults.sandbox.sessionToolsVisibility is "all"), emits nothing
when every agent is fully sandboxed under the default clamp, and says
sandboxed transcripts stay readable by unsandboxed callers.
Docs qualify the agent-to-agent reference with the requester-owned
native/ACP child exception and correct the security overview's sandbox
wording. Addresses both ClawSweeper rank-up moves on #136755.
* docs(security): qualify the fully sandboxed audit exemption
State in the CLI reference and high-level security audit summary that
fully sandboxed rosters under the default spawn-tree clamp produce no
cross-agent access finding. Disabling that clamp removes the exemption.
Addresses the mechanical ClawSweeper rank-up on #136755 at 3208e19534e.
* fix(security): report per-agent session tool reach in the cross-agent audit
The finding now lists which agents can reach other agents (unclamped sessions that still have a session tool allowed) with their calling context and allowed tools, lists non-reaching agents with the reason, and emits nothing when nobody reaches; help text no longer claims enabled=false isolates agents because requester-owned native/ACP child sessions stay reachable under tree or all visibility; gateway final-effect proof that a disabled policy or restrictive allow list never dispatches to the target. Addresses the ClawSweeper re-review on #136755.
* test(gateway): drain detached a2a flow in an afterEach hook
The in-row drain shared the row's 10s budget and could time out under load, leaking the next row's mock calls; the hook has its own bounded timeout.
* docs: stop describing disabled agent-to-agent access as isolation
enabled: false blocks ordinary cross-agent access, but requester-owned native subagent and ACP child sessions stay reachable under tree or all visibility; every introduced claim now says so and points strict separation to tools.sessions.visibility or separate gateways. Addresses the ClawSweeper P2 on #136755.
* test(qa-lab): prove default cross-agent send and policy denials end to end
Three mock-openai flow scenarios run a two-agent QA Gateway: default config dispatches sessions_send to agent:orion:main (accepted, target run observed, target main session created); enabled=false and a restrictive allow list return forbidden before any target work. Addresses the ClawSweeper P1 merge risk on #136755.
* fix(config): stop listing tree visibility as strict separation
Strict separation is agent or self; tree still admits requester-owned native subagent and ACP child sessions across agents. Addresses a ClawSweeper rank-up move on #136755.
* fix(security): warn on main-scoped group rooms
* fix(security): ignore direct-only group scope bindings
* fix(security): honor group binding precedence
* docs: correct retired cron/audit config keys, cron failure-alert default, memory recall default, and tool-search telemetry claims
- configuration-reference: cron block documented cron.webhook and cron.failureDestination, both retired by the config-surface reduction tranches (58452de711, edecdbd05e); the cron schema is strict so a copied snippet is rejected. Document only the live keys and note the doctor --fix migrations.
- configuration-reference: root-level audit block is retired; canonical path is logging.audit (src/config/zod-schema.root-shape.ts).
- configuration-reference: cron.failureAlert.after default is 2, not 3 (src/cron/service/failure-alerts.ts).
- memory-config: rememberAcrossConversations defaults on for personal installs (packages/memory-host-sdk/src/host/config-utils.ts), matching the canonical table earlier in the page.
- tool-search: telemetry records catalogSize, per-source counts, and search/describe/call counts, and only on tool_search_code results. No byte accounting exists in the runtime.
* docs: retire remaining references to removed cron, audit, and logging config keys
Sweep follow-up to the previous commit, covering the same bug class in the pages that still contradicted it.
- cron-jobs/cli-cron: global cron.failureDestination is retired; the destination fields now live on cron.failureAlert (src/config/zod-schema.root-shape.ts, merged by legacy-config-migrations.runtime.retired.ts:379). Per-job delivery.failureDestination bullets left intact.
- gateway/audit, cli/audit, gateway/protocol: root-level audit.* is retired; canonical path is logging.audit.*.
- logging: logging.redactSensitive is retired (dead-config-keys.test.ts:198; removed by legacy-config-migrations.runtime.tier-eval.ts:12). resolveConfigRedaction hardcodes DEFAULT_REDACT_MODE = tools, so redaction is unconditional. Also documented that redactPatterns replaces the defaults on the log path (redact.ts:419) while tool payloads always merge them.
- logging: consoleStyle accepts only pretty|json (zod-schema.root-shape.ts:106); compact remains the automatic non-TTY rendering style (logging/console.ts:40) but is no longer settable, and doctor maps a stored one to pretty.
- security: security --fix no longer touches redaction and the logging.redact_off audit check is retired (src/security/audit-loopback-logging.test.ts asserts it never fires).
* chore(docs): regenerate docs map after retired-key cleanup
* refactor(sessions): migrate runtime storage to sqlite
* test(sessions): fix sqlite CI regressions
* test(sessions): align remaining sqlite fixtures
* fix(codex): require sqlite trajectory recorder
* test(sessions): align orphan recovery sqlite fixture
* test(sessions): align sqlite rebase fixtures
* fix(sessions): finish current-main integration of the sqlite flip
Resolve the whole-store SDK removal across its owner boundary: drop the
loadSessionStore re-export and the registry whole-store wrappers, wire
hasTrackedActiveSessionRun into gateway chat, complete the
preserveLockedHarnessIds cleanup contract, flip the codex thread-history
import to storePath targets, and port remaining main-side tests from
file-store helpers to session accessor reads.
* chore: drop committed pebbles log, revert plugin-inspector bump, refresh generated docs
Remove the 1.8k-line .pebbles/events.jsonl work log from the branch, restore
the plugin-inspector advisory lane to main's pinned 0.3.10 so the supply-chain
bump gets its own review, and regenerate docs_map, the plugin SDK API baseline,
and the export-surface ratchet for the merged tree.
* feat(sessions): keep archived transcripts by default with zstd cold storage
Codex-style retention: deleting or resetting a session archives its
transcript as a zstd-compressed JSONL artifact (plain when the runtime
lacks node:zlib zstd) and keeps it until the disk budget evicts oldest
first. resetArchiveRetention now governs both deleted and reset archives
and defaults to keep; maxDiskBytes defaults to 2gb so retention stays
bounded, with archives evicted before live sessions. The cron reaper
follows the same knob instead of deleting archives on its own timer.
* fix(state): converge agent DB migration lineages and bound database growth
Merge coherence: run both structure-gated legacy memory-schema repairs
(flip-lineage drop, main-lineage identity rebuild) before the flip
migration so pre-flip v1/v2 and pre-merge flip v1/v4 databases all
converge, and hoist foreign_keys=OFF outside the schema transaction
where the pragma was silently ignored and the v1 sessions rebuild
cascade-deleted session_entries.
Growth guards: fresh agent DBs enable auto_vacuum=INCREMENTAL, WAL
maintenance releases freed pages in bounded passes (never a blocking
full VACUUM), and doctor reports state/agent DB bloat from freelist
stats.
* fix(codex): resolve the store path for thread-history import via the SDK
The supervision catalog passed the legacy sessionFile locator to the
storePath-targeted transcript mirror; resolve the agent store path with
the session-store SDK helper instead of a runtime-object seam so test
fakes and headless callers need no extra surface. Drop the obsolete
missing-session-id preprocessing case: sessions rows are NOT NULL on
session_id and upsert repairs id-less patches at write time.
* fix(sessions): fail safe on malformed disk-budget config and doctor stat errors
A malformed explicit maxDiskBytes disables the budget instead of
falling back to the destructive 2gb default the user never chose, and
the doctor bloat check skips databases whose paths stat-fail instead of
aborting doctor.
* fix(sessions): complete sqlite conflict translations
* test(sqlite): align hardening checks with maintenance
* test(sessions): inspect compressed transcript archives
* fix(tests): await session seeds and drop unused helpers flagged by CI lint
The five unawaited writeSessionStoreSeed calls raced their SQLite seeds
against the assertions, failing compact shards; the bloat probe drops a
useless initializer and the merged tests drop now-unused helpers.
* test(sessions): type legacy proof events directly
* test(sessions): align hardening contracts
* perf(sessions): read usage transcript sizes from SQL aggregates
Usage/cost scans walked every session and materialized every transcript
event just to re-stringify it for a byte estimate — the #86718 stall
class reborn on the DB. readTranscriptStatsSync sums stored JSON bytes
in SQLite without loading a single row.
* fix(sessions): re-root foreign-root transcript paths onto the current sessions dir
Restored backups, moved OPENCLAW_STATE_DIR, and rehearsal copies carry
absolute sessionFile paths from the old root; the containment fallback
kept those foreign paths, so migration read (and would archive) files in
the original root and reported local copies missing. Re-root the
canonical agents/<id>/sessions suffix onto the current dir when the file
exists there; genuine cross-root layouts still fall through unchanged.
* test(agents): seed harness admission through sqlite
* fix(sqlite): close agent db on pragma setup failure
* fix(doctor): compact and retrofit incremental auto-vacuum after session import
The migration is the sanctioned offline window: post-import compact
reclaims import churn and applies auto_vacuum=INCREMENTAL to databases
created before the fresh-DB pragma existed, so runtime maintenance can
release pages in bounded passes on every install.
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Keep startup non-breaking for existing installs when hooks.token reuses Gateway auth, but surface a startup warning, critical security audit finding, and doctor --fix repair that rotates persisted hooks.token.
Closes#87376.
Co-authored-by: Coy Geek <65363919+coygeek@users.noreply.github.com>
Summary:
- The PR expands security audit, CLI docs, and tests so `hooks.token` reuse of active Gateway token/password auth is reported while password-mode Gateway startup remains compatible.
- PR surface: Source +178, Tests +311, Docs +14. Total +503 across 14 files.
- Reproducibility: yes. from source inspection: current main forwards a bearer token as both token and passwor ... ecause this review was read-only, but the linked issue and code path make the reproduction high confidence.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(cr-fmi-hook-ingress-token-unlocks-password-mode-gateway-auth): ap…
- PR branch already contained follow-up commit before automerge: fix: include trusted proxy password in hooks token reuse check
- PR branch already contained follow-up commit before automerge: fix(gateway): audit hooks password reuse without blocking startup
- PR branch already contained follow-up commit before automerge: fix: Hook ingress token unlocks password-mode gateway auth
Validation:
- ClawSweeper review passed for head 7c796b22ec.
- Required merge gates passed before the squash merge.
Prepared head SHA: 7c796b22ec
Review: https://github.com/openclaw/openclaw/pull/86453#issuecomment-4533831028
Co-authored-by: Coy Geek <65363919+coygeek@users.noreply.github.com>
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: jesse-merhi