Skip to content

feat: universal read data plane + approval executor, brain tools, mcp host allowlist#59

Merged
Basheirkh merged 5 commits into
mainfrom
feat/approval-executor
Jun 26, 2026
Merged

feat: universal read data plane + approval executor, brain tools, mcp host allowlist#59
Basheirkh merged 5 commits into
mainfrom
feat/approval-executor

Conversation

@Basheirkh

Copy link
Copy Markdown
Contributor

Squash-merges the feat/approval-executor stack to main.

Read data plane (new): lean/filtered/paginated reads (schema/count/search/get/aggregate/export), refuse-not-truncate byte cap, capability fallback, read authz, export→data-handles, bulk-write spine; relay byte-cap backstop + nil_search/count/get/aggregate/export tools; read-plane contract schema + skill discipline. Fixes the 590 KB context flood architecturally. 426 tests.

Also carries: approval executor (approving a held proposal executes it), read-only Business Graph MCP tools, NIL_MCP_ALLOWED_HOSTS allowlist, Automations panel empty-state.

🤖 Generated with Claude Code

AI Bot and others added 5 commits June 24, 2026 17:22
…se form is reachable

The panel was hidden when zero automations existed — but the '+ New cross-system
automation' button and operator-token field live inside it, so a first automation
could never be created. Always render it, with an empty state.
…ing allowlist

FastMCP only honors transport_security as a constructor kwarg and otherwise
auto-enables a localhost-only allowlist, so the remote MCP 421s ('Invalid Host
header') when reached by its container/service name or a public mcp.* host
behind a reverse proxy. build_server now accepts allowed_hosts and threads a
TransportSecuritySettings; build_asgi_app reads NIL_MCP_ALLOWED_HOSTS (JSON or
comma-separated, host:* wildcard ok). /mcp stays bearer-gated.
…instances/activity)

Adds deterministic brain-read tools so an agent answers 'show my policies / cycles /
what changed / what's overdue' from the brain read-model instead of improvising (curl,
file search) or mistaking a graph question for a missing kernel verb. BrainTools is a
thin HTTP relay to the brain's /api/graph/* GET endpoints (kernel stays decoupled — it
relays, never imports the brain). Env-gated by NIL_BRAIN_URL (+ NIL_BRAIN_TOKEN/TENANT);
policies are surfaced as nodes via nil_graph(kind='policy'). 11 new tests; full MCP suite green.

Stacks on #57 (fix/mcp-allowed-hosts).
… (CP commits against the active adapter)

The keystone of the core-SSOT plan. Before: a held HIGH-tier proposal lived only in MCP memory
(ephemeral) and its CP approval was dead data — execution required the agent to re-nil_commit, so a
dashboard Approve did nothing. Now: the gate threads the proposal's verb/tier/preview onto the hold
event (so the owner sees WHAT they approve and it survives MCP restarts), and on Approve the control
plane itself commits the proposal against the workspace's active adapter (reusing the _live_runner
client path) and returns the outcome. Approval DRIVES the effect; the agent never re-commits.
Honest on failure (expired / already committed / unreachable). 60 CP tests green.
…reads, refuse-not-truncate, export handles

The 590 KB flood (crm.list_contacts dumped whole res.partner records → context
overflow → agent fell back to read_file) was an architectural gap: the read path
had no contract. This adds one, enforced at the contract + relay seams.

nilscript.dataplane:
- primitives: enforce_byte_cap (REFUSE, never truncate), project/project_items,
  parse_filter/Predicate (closed typed op set).
- ReadPlane engine over a ReadBackend protocol — schema/count/search/get/aggregate/
  export implemented ONCE so every adapter inherits: default projection, byte-cap
  refuse, keyset cursor, capability fallback (edge-filter within a bound, else
  refuse), read-side authz (sensitive fields dropped + redaction declared), and
  bulk-export gating (BulkApprovalRequired — closes the "reads are free" exfil hole).
- export → tenant-scoped, TTL'd, PII-at-rest data handles (rows never enter context).
- bulk-write spine: batched, resumable, stoppable, partial-failure policy.

MCP relay: byte-cap backstop in the query path (a misbehaving adapter still can't
flood the agent) + nil_search/count/get/aggregate/export tools.

Contract: read-plane.schema.json (the SSOT adapters conform to); SKILL.md gains the
count/search/export discipline + the ABSOLUTE "never read_file business data" rule.

426 tests pass (33 new), zero regressions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Basheirkh Basheirkh merged commit aeaf53d into main Jun 26, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant