feat(api): read-only JSON API for automation and AI agents - #67
Merged
Conversation
Add Observer.Web.Router.observer_api/2, an opt-in mount exposing the
existing collectors as bounded, read-only JSON endpoints: /system
(runtime info, limits, allocators), /processes (etop-style ranking
with sort/limit), /ets (table metadata) and /apps, plus an index
listing endpoints and visible nodes.
The mount is separate from the dashboard so hosts place it inside
their own API authentication pipeline. Access resolves through the
same Observer.Web.Resolver behaviour ({:forbidden, _} renders 403).
Node parameters only resolve against currently known cluster nodes -
crafted values never reach RPC or allocate atoms - and process/table
identifiers are serialized with inspect.
Risk assessment:
- Impact: additive opt-in macro; hosts that do not mount observer_api
see zero change.
- Blast radius: new Observer.Web.Api plug and router macro; collectors
and dashboard untouched.
- Regression risk: low - read-only endpoints over existing context
modules, params whitelisted/bounded; suite green (405 tests, 96.0%
coverage).
- Rollback plan: revert the commit; hosts drop the observer_api mount.
thiagoesteves
force-pushed
the
thiagoesteves/json-api
branch
from
July 20, 2026 12:25
32f4326 to
13147ff
Compare
Observer.Web.Api's send_json/3 is a bare Plug that calls send_resp/2 directly, a pattern Sobelow can't distinguish from an HTML XSS sink even though the content-type is always explicit JSON. Mark it skipped and pass --skip in both the sobelow CI step and the local test.ci alias so the annotation is honored. Also wires observer_api into dev.exs behind a bearer-token pipeline so the new endpoints can be exercised locally.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
Observer.Web.Router.observer_api/2: an opt-in, read-only JSON API over the same collectors the dashboard renders, aimed at automation and AI agents (the direction observer_cli 2.0 just validated with its JSON output).GET /- endpoints + visible nodesGET /system?node=- runtime info, VM limits, allocator utilizationGET /processes?node=&sort_by=reductions|memory|message_queue_len&limit=- etop-style ranking (limit capped at 1000)GET /ets?node=- table metadata (size, memory, owner, protection)GET /apps?node=- running applicationsThe mount is deliberately separate from the dashboard (no session/LiveView) so hosts place it inside their own API auth pipeline:
Security notes
Observer.Web.Resolverbehaviour;{:forbidden, _}renders a 403. All endpoints are read-only, so:alland:read_onlyare both accepted.?node=values only resolve against currently known cluster nodes - crafted values never reach RPC and never allocate atoms; sort/limit params are whitelisted and bounded.inspect; unreachable nodes render a 502 instead of crashing.Why
Part of the roadmap derived from comparing ObserverWeb against OTP observer, observer_cli and Phoenix LiveDashboard: a machine-readable surface makes ObserverWeb the richest BEAM data source an agent can query, reusing collectors that already exist.
Risk assessment
Observer.Web.Apiplug + router macro; collectors and dashboard untouched.observer_apimount.Checklist
mix testgreen (405 tests)mix coveralls96.0% (threshold 95%)mix credo --strict,mix sobelow,mix dialyzer,mix format --check-formattedclean🤖 Generated with Claude Code