Three fixes in the same leak class (a remote caller reading or writing
outside its granted sources), for multi-source / multi-tenant brains:
1. dispatchToolCall now refuses remote calls that arrive without a
resolved sourceId (missing_source_scope error envelope) instead of
silently falling back to the shared 'default' source. Every shipped
transport already passes sourceId explicitly (serve-http from the
OAuth client row, http-transport from the legacy token grant, stdio
from GBRAIN_SOURCE); reaching the fallback remotely always meant a
programmatic caller skipped scope resolution — the bug class behind
#1924 / #1371. Trusted local callers (remote === false) keep the
historical fallback. Direct-dispatch tests updated to carry an
explicit sourceId, matching the real transport contract.
2. log_ingest threads ctx.sourceId (same pattern as get_chunks /
get_page), so ingest events are attributed to the caller's source
instead of piling into 'default'. Engines already accept
entry.source_id (v0.31.2).
3. get_ingest_log is source-scoped for remote callers via the
linkReadScopeOpts collapse rule (scalar grant → [scalar]; federated
grant → granted array); it previously returned the whole brain's
ingest log to any read-scoped remote client, and ingest summaries can
carry another source's private context. Trusted local callers keep
the whole-brain view.
Tests: dispatch guard (refuse remote-without-source, keep local
fallback, guard ordering after op lookup) and end-to-end ingest-log
attribution + scoping over the real dispatch path, on PGLite.