Cerebro began with a practical problem: my security environment had more useful consoles than any operator could watch at once.
Wazuh handled detection and endpoint telemetry. Graylog handled retention, search, and operational log analysis. Greenbone and Dependency-Track had different views of vulnerability risk. Shuffle and Velociraptor covered response and investigation. Proxmox, backup infrastructure, identity, secrets, DNS, network, application security, source control, threat intelligence, and physical-security platforms each had their own operational truth.
None of those products was wrong for having a focused console. The problem was the space between them.
I needed to know whether evidence was current, which systems were degraded, whether a collector had lost authorization, whether backups were verifiable, whether security feeds were still moving, and where to continue an investigation. Opening twenty tabs answered those questions slowly. Building one powerful administrative console would have answered them by creating a new concentration of credentials and response authority.
Cerebro is the middle path I chose. It is a read-only security intelligence and operational visibility layer. It collects bounded summaries, assigns explicit freshness and health states, publishes versioned relationships, supports narrow investigations, and links back to the native products. It does not replace those products, store their raw evidence, or execute actions against them.
I described the general architecture behind this approach in Building a Security Control Plane Without Creating Another Crown Jewel. This article is about Cerebro itself: why I built it, how the implementation works, what it can do now, and where I have kept hard boundaries.
The sanitized SOC pipeline reference implementation is maintained separately from the private deployment and evidence repositories.
The problem was not a lack of dashboards
A dashboard can make many systems look like one system. That is useful until the simplification hides a failure.

A green card might mean the source API returned HTTP 200. It might mean a snapshot was healthy yesterday. It might mean a collector filled a missing value with zero. It might mean the source is healthy but the credential is expired. It might mean the portal reached a load balancer while the application behind it was broken.
Those states are operationally different. Cerebro treats them as different facts.
The other problem is authority. A central portal naturally attracts credentials because every integration needs some way to retrieve data. If those credentials can also modify users, isolate endpoints, start workflows, change firewall policy, delete backups, or retrieve secrets, compromise of the portal becomes compromise of the environment.
I did not want a monitoring convenience to become an administration tier.
The governing rule became:
Cerebro can observe, normalize, age, explain, correlate, and link.
Cerebro cannot configure, contain, block, delete, rotate, deploy, or execute.That rule is enforced in code and in source-system identity design. The application exposes GET routes only. POST, PUT, PATCH, and DELETE return HTTP 405 with Allow: GET. Source calls use fixed routes, bounded responses, normal TLS validation or a reviewed certificate pin, and the narrowest practical identity. When a product requires a POST to obtain a token, a scheduled producer performs the authentication outside the portal and writes a sanitized snapshot for Cerebro to consume.
This follows the least-privilege and boundary-protection intent of NIST SP 800-53 controls such as AC-6 and SC-7, but the control mapping is not the point by itself. The point is that a compromised dashboard process should not inherit the authority to change the systems it describes.
Where Cerebro sits
Cerebro is deliberately outside the event-delivery and response paths.

Security and infrastructure platforms
|
+-> native logs, alerts, findings, inventory, and health
|
Scheduled read-only producers or fixed GET connectors
|
+-> schema validation
+-> field allowlisting
+-> aggregation and pseudonymization
+-> atomic last-known-good snapshots
|
Cerebro read-only service
|
+-> normalized health and freshness
+-> bounded analytics and relationships
+-> exact investigation APIs
+-> browser views and native-console links
|
Authenticated operatorA failure in Cerebro cannot stop Wazuh detection, Graylog retention, DNS resolution, backup jobs, identity authentication, or SOAR execution. A failed connector cannot stop the source platform. Removing Cerebro does not require rebuilding any source system.
That separation matters. Cerebro is an operational consumer of evidence, not an inline enforcement point and not a system of record.
The application is a small modular monolith rather than a collection of connector microservices. It uses a threaded Python service, a versioned JSON API, and a dependency-light browser interface. Most collection happens on schedules outside the request path. This keeps browser requests fast and prevents a slow management API from tying up the portal.
I will split components only when measured concurrency, source latency, or independent release ownership justifies it. Service boundaries should solve a real operating problem, not decorate a diagram.
What the operator sees
The default Live view is the operational front door. It reports current SIEM posture, active endpoint coverage, recent contract-event counts, Wazuh and Graylog health, backup state, minimum certificate lifetime, a 24-hour event graph, and geographic clusters derived from qualifying public-source security events.

The interface keeps Live separate from platform pages. Other views are grouped into operational menus for SOC, Threat/Risk, Security, Infrastructure, Platform, Recovery, and Physical Security. Navigation is bookmarkable, keyboard accessible, and preserved across the normal one-minute refresh.
Every integration carries more than a color:
- current state
- freshness state
- collection timestamp
- evidence age
- maximum accepted age
- source owner
- collection cadence
- bounded record count where applicable
- stable reason code when collection fails
- native-console link
The normalized state vocabulary is intentionally small:
| State | Meaning |
|---|---|
healthy |
The evidence is recent, its schema passed, and the source-specific health requirements passed. |
degraded |
Collection succeeded, but the source reported a partial or unhealthy condition. |
stale |
Previously valid evidence is older than the accepted age. |
unavailable |
The source could not be reached or collection could not complete. |
unauthorized |
The source rejected the connector identity. |
unknown |
Cerebro cannot make a defensible state decision from the supplied evidence. |
planned |
The capability is cataloged but does not claim live data. |
A successful request is not enough to produce healthy. A valid source timestamp and a source-specific health signal are required. Missing timestamps become unknown. Old healthy snapshots become stale. Authentication failures remain distinguishable from network failures.
This prevents two dangerous lies: stale data presented as current, and missing data rendered as zero.
The current integration surface
The current GitLab main branch defines 21 normalized platform integrations. Most production collectors run every five minutes and become stale after fifteen minutes. SIEM and Graylog evidence refresh more frequently. Vulnerability and framework sources use cadences appropriate to their source data.

The table below describes what each integration contributes. It does not imply that Cerebro replaces the native console or receives the excluded source records.
| Integration | What Cerebro receives | What remains in the native system |
|---|---|---|
| Enterprise SIEM | Active findings, recent contract-event counts, active endpoint count, indexer and Graylog health, backup state, certificate lifetime, and bounded security-activity aggregates | Raw alerts, searches, detection engineering, endpoint administration, and detailed event evidence |
| God’s Eye View | Service and API readiness, feed freshness, aggregate threat-event, live-event, threat-indicator, and correlated-sighting counts | Interactive globe investigation, aircraft and vessel context, coordinates, labels, and source detail |
| OpenCTI | Service and container health, connector activity and freshness, version, and ATT&CK object count | STIX objects, indicators, reports, identities, relationships, curation, and analyst workflows |
| Graylog | Cluster health, node totals, data-node availability, and freshness | Search, streams, pipelines, dashboards, retention, and raw logs |
| Greenbone | Finding totals, affected-asset count, severity distribution, task count, latest scan completion, and delivery state | Scan configuration, raw results, credentials, ports, task detail, and remediation workflow |
| Shuffle SOAR | Workflow, action, trigger, validation, licensing, and platform-capability counts | Workflow definitions, hooks, app credentials, execution arguments, results, and execution authority |
| Velociraptor | Version, uptime, client count, hunt count, and running or stopped hunt totals | Client identities, artifacts, collections, hunt results, and response actions |
| Proxmox | Version, quorum state, node totals, aggregate running and stopped VM and container counts, HA resource count, and replication-job count | Guest names, numeric IDs, addresses, storage identities, task data, and administration |
| Proxmox Backup Server | Capacity, utilization, snapshot and group counts, verification state, protection count, and newest-backup age | Backup contents, datastore administration, restore actions, namespaces, and owner detail |
| Authentik | Total, active, and inactive user counts plus group and provider counts | Usernames, email addresses, memberships, sessions, policies, applications, flows, and identity administration |
| HashiCorp Vault | Version, node count, initialization and seal posture, active and standby counts, service state, and HA forwarding health | Secrets, paths, tokens, accessors, policies, mounts, leases, identities, and audit records |
| Vaultwarden | Service versions, container state, public health, and seven-day aggregate security-event counts | Vault items, organizations, user identifiers, cipher data, source addresses, and secret values |
| UniFi Network | Controller and subsystem health, device and client transport counts, network and WLAN counts, plus bounded WAN and application-traffic analytics | Site, client, device, policy, SSID, VLAN, gateway, and administrative detail |
| UniFi Protect | Version, NVR count, camera count, and connected or disconnected camera totals | Video, audio, thumbnails, events, camera identities, faces, plates, and recordings |
| Technitium DNS | Resolver availability, zone-count consistency, query-log availability, and bounded last-hour query, block, NXDOMAIN, server-failure, and drop totals | Client addresses, domain names, query records, answers, zones, configuration, and administration |
| SOCFortress WAF | Management and proxy health, enabled-site posture, last-hour request and enforcement totals, ingestion lag, and bounded CRS category aggregates | Request and response data, attacker records, site identity, upstream configuration, rules, and policy changes |
| GitLab | Version, project totals, latest-pipeline state, 24-hour pipeline aggregates, and newest-pipeline time | Project names, repositories, commits, jobs, logs, variables, artifacts, users, runners, and deployments |
| Dependency-Track | Portfolio, component, vulnerable-project, severity, KEV, audit, policy-violation, and inherited-risk aggregates | Project and component identity, BOM and VEX documents, vulnerabilities, analysis records, policies, and remediation detail |
| Current threat model | Current assessment metadata, rating totals, attack paths, structured risk chains, provenance, and explicit risk-to-model relationships | The authoritative threat-model artifact, diagrams, narrative evidence, review, and governance |
| Threat Intelligence | Publisher inventory, feed freshness, indicator-type counts, exact bounded IOC lookup, and source-specific allowlisted metadata | Bulk indicator corpus, credentials, source errors, unrestricted searches, and source administration |
| ATT&CK / ATLAS | Version-pinned active technique catalogs and independently approved environment mappings | Source STIX bundles, mapping proposals awaiting review, and framework maintenance |
The latest implementation state is not uniform across every capability. The core portal and the majority of platform connectors are production active and accepted. UniFi Network health and Network Traffic are active as separate views. The vulnerability dashboard is active, with a browser pixel-validation gap retained in its acceptance record. God’s Eye View and OpenCTI monitoring are production candidates. The optional WiGLE layer, current threat-model association, and read-only risk register are implemented but still require production promotion. The OTX-backed threat-intelligence update has completed isolated live acceptance and remains gated on its final production release path. Investigation Graph remains planned.
That distinction is deliberate. Merged code, deployed code, and accepted capability are separate states.
The Live view is an aggregate, not an evidence lake
The 24-hour security activity feed is assembled from geo-located events that match reviewed detection groups such as firewall enforcement, IDS or IPS, WAF, DNS blocking, web attacks, and threat-intelligence matches.

The snapshot carries aggregate event count, distinct public sources, country count, a bounded hourly series, a bounded set of geographic centroids, and ranked countries, sources, and detection lanes. The map does not receive raw alert documents or internal asset identity.
Cerebro renders the basemap with a locally served MapLibre GL JS library and an OpenFreeMap vector style. If map resources are unavailable, the non-map evidence remains visible. A visualization dependency must not make the health table disappear.
Top public sources can become narrow investigation pivots. The IP investigation API accepts a validated public IPv4 address already present in the bounded source set. It can return RDAP registration context, the first and last qualifying observations within the current rolling window, observation count, provenance, and a native SIEM link. It does not accept arbitrary internal addresses or expose a general search interface. RDAP response handling follows the structured registration-data model defined by RFC 9083.
First seen and last seen are labeled carefully. They mean first and last observation within the current 24-hour query, not lifetime history.
Vulnerability intelligence without copying scanner data
The Threat/Risk menu includes a vulnerability view that combines posture from Greenbone and Dependency-Track without merging their underlying evidence stores.

The dashboard shows severity distribution, source health, collection posture, normalized CVE records, scanner-supplied names and bounded summaries, and pseudonymous affected-asset associations. An exact CVE investigation route returns the accepted context for one canonical CVE identifier.
Source text is treated as untrusted input. Names and summaries have size and character limits, whitespace is normalized, and the browser writes them through text nodes. Scanner report IDs, task names, hostnames, addresses, ports, and raw remediation data are excluded.
Pseudonymous asset association is intentional. Cerebro can show that a CVE affects one or more distinct accepted assets without turning the portal into an asset-identity directory. The native scanner and asset systems remain authoritative when an operator needs the real host and remediation record.
Dependency-Track adds portfolio-level application risk. Cerebro receives project and component totals, vulnerable project and component counts, severity and known-exploited-vulnerability counts, audit state, policy-violation totals, and inherited risk. It does not receive project names, component coordinates, package URLs, repository links, BOMs, VEX documents, vulnerability details, or team data.
Threat models and the risk register are governed data
Cerebro does not scrape the rendered knowledge base for threat-model or risk data.

A scheduled producer reads the exact accepted Git revision, validates the registered current assessment, verifies the declared artifact hash, checks totals and internal references, and writes a bounded snapshot. The portal receives provenance tied to that exact source revision.
The threat-model contract carries assessment metadata, systems in scope, rating counts, structured attack paths, NIST SP 800-30 style risk chains, changes from the prior assessment, and known limitations. It publishes one threat-model entity, one finding entity per stable risk identifier, and explicit associated_with relationships.
Cerebro does not infer asset mappings from prose. If the source artifact does not contain an explicit unambiguous association, the relationship remains unresolved. Absence from a later assessment is not treated as closure.
The read-only Risk Register follows the same governance boundary. Its list and detail APIs support bounded filters for owner, rating, treatment, status, and due state. The dashboard exposes total and open risk, unassigned ownership, overdue work, pending treatment, expired acceptance, inherent rating, and residual rating.
The initial imported records intentionally show governance debt. Unassigned risks remain unassigned. Pending treatments remain pending. Missing dates remain unscheduled. Residual risk remains not assessed until control evidence supports an assessment. Cerebro does not invent an owner, treatment decision, acceptance, or due date to make the dashboard look complete.
Risk acceptance has its own contract. An accepted risk needs an approver, approval time, expiration time, and rationale. Expired acceptance becomes a visible state rather than a permanent waiver.
GitLab and the active knowledge base remain authoritative. Cerebro is the read-only operational lens.
Threat intelligence distinguishes publication from observation
Threat intelligence is easy to misuse in a central dashboard. A feed containing an IP address does not prove that the address touched the environment. A publisher calling an indicator malicious does not prove compromise. A local exact match adds context, but it does not authorize containment.

Cerebro labels its feed inventory as publisher inventory, not observed activity. It reports which sources supplied data, the age and health of each source, indicator-type counts, and the newest successful collection. Bulk IOC data is not returned in the overview.
The exact lookup API accepts one explicit type and one canonical value. Supported types include IP, CIDR, IP and port, domain, URL, MD5, SHA1, SHA256, and CVE. Queries are parameterized and exact. Wildcards, free text, ambiguous formats, oversized results, and credential-bearing source references are rejected.
The current threat-intelligence pipeline includes the existing licensed and open feeds plus an AlienVault OTX integration using its documented API. The same classification rule still applies: publisher data is not local observation.
Locally observed threat-intelligence matches are published through a separate GEOINT sightings contract. That contract says what the data is: locally observed matches in a defined window, aggregated to approximate cells. Keeping publisher inventory and local sightings separate prevents a feed download from appearing as an incident map.
ATT&CK and ATLAS are catalogs first, mappings second
Cerebro carries version-pinned active catalogs for MITRE ATT&CK Enterprise and MITRE ATLAS.

The catalog and environment mappings have separate publication states. Catalog techniques can be active while mappings remain staged. A proposed, rejected, superseded, self-reviewed, or stale mapping publishes no maps_to relationship. Only an independently approved mapping with evidence can become an active relationship.
That review separation prevents a common reporting failure: a suggested technique mapping quietly becoming operational truth because it appeared in a dashboard.
The framework contract validates release pins, checksums, technique identifiers, parent relationships, lifecycle counts, canonical references, mapping evidence, proposer and reviewer separation, and output size. Revoked and deprecated objects remain lifecycle counts rather than active catalog entries.
The result is a complete reference catalog with a much smaller set of claims about this environment.
GEOINT consumers use bounded projections
Cerebro exposes separate GET-only projections for threat activity, threat-intelligence geography, locally observed sightings, and recent live events. These APIs exist so another visualization can consume a narrow, versioned projection without receiving the full portal payload.

Each projection has its own classification and location precision. Country centroids, approximate geohash cells, and bounded event points are not interchangeable. Every consumer has to preserve the stated precision and provenance.
God’s Eye View is one such consumer. Cerebro supplies sanitized projections, while the God’s Eye View connector returns only that application's service health, API readiness, feed freshness, and aggregate counts. This creates a two-way operational relationship without sharing credentials or raw records between browser applications.
An optional WiGLE layer is implemented for street-level wireless context. It remains off by default, requires a minimum zoom, sends only visible map bounds to a server-side fixed-origin client, caps results, removes full BSSIDs and address metadata, rate limits uncached requests, redacts bounds from access logs, and keeps attribution visible. It is useful context, not wireless authorization or location certainty.
UniFi health and Network Traffic are separate views
Cerebro originally used one UniFi integration page. That became confusing when application traffic analytics were added because operational health and traffic analysis answer different questions.

The current interface keeps both views:
UniFi Networkshows controller, site, adopted-device, client-transport, network, WLAN, and subsystem health.Network Trafficshows 24-hour, 7-day, and 30-day WAN and application aggregates.
The traffic view includes WAN download, WAN upload, total transfer, combined peak throughput, identified-application distribution, WAN direction, and a ranked Top Applications table. Application and category names come from the controller's own DPI catalogs. An explicit Other identified traffic segment keeps the displayed distribution reconcilable.
The selected range updates the cards, charts, and table without another browser request and survives the normal portal refresh.
Cerebro does not expose clients, addresses, MACs, device names, SSIDs, VLANs, sites, gateways, ISP details, or policy objects. DPI classification is treated as controller attribution, not proof of user intent or complete network visibility.
The connector still has one material hardening gap: its current source credential is broader than the collector requires. Fixed GET routes, certificate pinning, bounded responses, and strict validation reduce exposure, but they do not create source-side least privilege. A dedicated view-only identity remains the correct endpoint.
The technology stack view answers a different question
Platform health says whether a product is working. The technology stack view says what the environment is built from.

Its versioned snapshot includes a bounded operating-system inventory and technology rows with layer, technology, version, role, coverage, source, and whether the value came from live evidence or a maintained catalog. Summary metrics include virtual machines, running systems, hosts reporting an operating system, and technologies represented.
This view is useful for architecture review, dependency analysis, upgrade planning, and exposure triage. It is not a software-composition database and does not replace an SBOM, package inventory, or vulnerability scanner.
Connector patterns
Cerebro supports three connector shapes.

Local sanitized snapshots
This is the preferred shape for most sources. A scheduled producer performs the source-specific work, validates and reduces the response, then atomically replaces a local JSON snapshot. The portal reads the snapshot without holding the source credential.
The producer preserves the last known good file when collection fails. Cerebro ages that file and changes its state to stale after the accepted threshold. This preserves useful context without pretending the evidence is current.
Exact-origin HTTP JSON
A direct connector can perform a bounded GET to one reviewed origin. Configuration validation rejects other methods, unsafe schemes, missing allowlists, and redirects. Normal certificate validation remains enabled, with an explicit private CA where required.
Browser input cannot select the destination URL or provide an arbitrary source query.
Static catalog entries
A planned or navigational entry can provide a native-console link and an explicit non-live state. A static entry does not claim that the target system is healthy.
Source-specific least privilege
Read-only is not a client-side promise. The source identity should enforce it.

Cerebro uses several patterns because platforms expose different security models:
- dedicated API identities with narrow view permissions
- built-in auditor roles for virtualization and backup platforms
- fixed-command SSH exporters when a broad management API would grant too much authority
- source-local producers for systems whose useful health state is available only on the application host
- certificate-pinned connections for reviewed appliances
- internal-CA validation and exact-origin enforcement for internal HTTPS services
- read-only SQLite replicas for exact threat-intelligence lookup
- no source credential at all for snapshots delivered through a restricted transport
The Authentik connector, for example, uses only the view permissions needed for bounded user, group, and provider counts. The portal itself sits behind Authentik single-application forward authentication and MFA.
The Vault collector does not receive a Vault token. It uses a fixed status command that can report seal, role, version, and HA state without exposing secrets or general CLI access.
The portal receives no Wazuh indexer credential for the Live view. A separate producer queries the detection plane and delivers only the accepted aggregate.
These patterns reduce the effect of portal compromise, but none makes aggregation risk disappear. A compromised portal can still disclose every summary and relationship it is allowed to read. That is why field-level minimization, source-specific identities, network controls, and browser security all matter.
The API surface
The current API is intentionally narrow:
| Route | Purpose |
|---|---|
/api/v1/overview |
Portal metadata, normalized state, platform integrations, entities, relationships, and bounded analytics |
/api/v1/integrations |
Compatibility alias for the overview contract |
/api/v1/geoint/threat-activity |
Bounded aggregate map projection from recent security activity |
/api/v1/geoint/threat-intelligence |
Bounded publisher-intelligence geography projection |
/api/v1/geoint/sightings |
Bounded locally observed threat-intelligence matches |
/api/v1/geoint/live-events |
Bounded recent-event projection with explicit labels and provenance |
/api/v1/geoint/wigle |
Optional validated visible-bounds wireless lookup |
/api/v1/threat-intelligence/lookup |
Exact typed IOC lookup against a read-only replica |
/api/v1/reference/tech-stack |
Bounded technology and operating-system inventory |
/api/v1/vulnerabilities |
Paginated normalized vulnerability list |
/api/v1/investigations/cve/{cve} |
Exact CVE detail and pseudonymous affected-asset context |
/api/v1/investigations/ip/{ipv4} |
Exact public-IP registration and observation context |
/api/v1/risks |
Paginated and filtered governed risk list |
/api/v1/risks/{risk-id} |
Exact governed risk detail |
/healthz |
Process health only |
/readyz |
Configuration-loaded readiness only |

Health and readiness are deliberately modest claims. They do not claim that every source is healthy. Source status belongs in the integration payload where age, provenance, and reason codes can explain it.
Data contracts fail closed
The top-level integration schema defines stable entity types such as IP address, asset, alert, finding, CVE, threat model, ATT&CK technique, ATLAS technique, and source system. Relationships include affects, associated_with, detected_by, maps_to, observed_by, and supports.

Adding a field name to configuration does not automatically allow new entities or relationships through the API. Each producer and consumer validates exact keys, types, ranges, timestamps, record counts, output size, arithmetic invariants, and prohibited fields.
Examples include:
- backup totals must reconcile with verification and protection counts
- virtualization running and stopped totals must reconcile with overall guest totals
- network traffic window totals and the Other segment must reconcile
- risk summaries must equal the records actually present
- framework catalog counts and checksums must match the pinned release
- threat-model risk references must resolve to declared attack paths
- public-IP observation timestamps must be ordered and remain inside the stated rolling window
- future timestamps beyond the accepted skew are rejected
This is more work than copying a JSON response into a card. It is also the difference between a status claim and a styled guess.
Browser and service controls
Cerebro listens on loopback. Caddy is the network-facing TLS proxy and delegates authentication to Authentik. The service runs under a dedicated non-login account rather than root.

The browser receives restrictive response headers: a self-oriented content security policy, denied framing, MIME-sniffing protection, no-referrer behavior, disabled camera, microphone, and geolocation permissions, no forms, and no caching. OWASP recommends delivering Content Security Policy as an HTTP response header so it applies across responses.
MapLibre is self-hosted. The only routine browser network exception is the reviewed vector-map origin. Source-controlled labels are written through textContent or equivalent text-node APIs rather than HTML insertion.
The systemd unit applies a read-only filesystem view, private temporary storage, NoNewPrivileges, kernel and control-group protections, personality locking, executable-memory denial, and a restrictive umask.
Logs retain request state and connector reason codes without retaining authorization headers, tokens, source payloads, secret paths, or coordinate query strings.
Integration testing focuses on false confidence
The tests I care about most are not the happy-path cards.

Every connector needs cases for recent healthy evidence, source-reported degradation, stale data, missing data, malformed types, oversized responses, excessive pagination, invalid timestamps, future timestamps, unauthorized identities, TLS failures, redirects, unavailable sources, unknown state values, and atomic preservation of the prior snapshot.
API tests cover exact query syntax, bounded pagination, canonical identifiers, rejected wildcards, safe error codes, and method denial. Contract tests verify that prohibited source fields cannot appear in normalized output.
Frontend acceptance includes more than an HTTP 200. A normal authenticated browser must render recognizable cards, menus, charts, tables, and maps. Keyboard navigation, time-range controls, filters, drill-down panels, responsive overflow, failed requests, and console errors are part of acceptance.
A repository test pass is still not production acceptance. A connector becomes live only after deployment, source parity sampling, authentication checks, TLS validation, service read-back, evidence-age checks, and a retained rollback path.
Recovery is intentionally small
Cerebro is stateless in the application sense. Source control holds the service, non-secret configuration, frontend, schemas, tests, deployment logic, and documentation. Source platforms retain their own records. Scheduled producers recreate disposable snapshots. The secrets platform retains connector credentials.

A rebuild restores the accepted source revision, dedicated account, loopback service, authenticated proxy, internal trust anchors, producer schedules, restricted evidence paths, and server-side secret references. The portal does not need a database restore.
Rollback can restore the previous immutable application release or remove the proxy route. Source systems do not need to be restarted or rolled back. Connector-specific identities can be revoked independently if they no longer have a consumer.
That is a useful architecture test. If removing a visibility layer requires changing the detection, identity, backup, network, and secrets platforms, the layer has acquired too much authority.
Current boundaries and next work
Cerebro still has limits that I intend to keep visible.

It is an internal, low-concurrency application behind a trusted reverse proxy. It is not an Internet-facing application server. Aggregate health can hide source-record detail, so it cannot replace investigation. Geographic data is approximate. Threat-intelligence publisher data is not local observation. DPI attribution is not user intent. Pseudonymous assets are not an asset inventory. A framework mapping is not valid until it receives independent approval.
Several capabilities are implemented but not yet production promoted. Those include the read-only Risk Register, optional WiGLE layer, and parts of the threat-model and newer threat-intelligence path. God’s Eye View and OpenCTI monitoring remain production candidates in the current implementation record. Investigation Graph remains planned because cross-source correlation needs a stricter identity, provenance, and evidence model before it can be trusted.
There are also credential hardening items. The UniFi Network collector needs a dedicated source-side view-only identity. Some platforms provide APIs whose role model is broader than the metric being collected. Client-side GET restrictions help, but the gap remains until the source enforces the same boundary.
I do not plan to add containment buttons to this service. If an action plane becomes necessary, it should have separate identities, step-up authorization, approvals, target validation, idempotency, audit records, canaries, and rollback. It should not inherit trust merely because the read-only portal already has an operator's attention.
What Cerebro is for
Cerebro is not the place where every security record goes. It is the place where an operator can answer a smaller set of high-value questions:
- Which security and infrastructure systems are healthy now?
- Which evidence is fresh, stale, unavailable, unauthorized, or unknown?
- Is the SOC still receiving and correlating expected activity?
- Are backups recent and verified?
- Is identity, secrets, DNS, network, application security, source control, and dependency risk in an expected posture?
- Which public source, CVE, threat-model risk, framework technique, or IOC deserves a bounded next look?
- What is the authoritative native system for the next step?
- What governance work is missing rather than silently defaulted?

The portal reduces console hopping without flattening every source into the same meaning. It makes evidence age visible. It preserves native authority. It creates cross-platform context without copying the evidence lake or collecting response permissions.
That is the rationale behind Cerebro and the boundary I intend to defend as its integration surface grows.