Security monitoring
Perihelium records every action that touches identity, authority or evidence in your organization — a sign-in, a token minted for an agent, a permission granted, an emergency stop engaged — and reasons about those records on your behalf. This page is the map: what is recorded, what the platform concludes from it, how your team is told, and how all of it reaches the tools you already run.
The one question every security review asks first is answered up front: yes, you can export the audit log and the event stream, and yes, you can stream them to your SIEM. See Ship it to your SIEM.
What is recorded
Every action is an event: who acted (a person, an AI agent, a service credential or the platform itself), what they did, on which organization, with what outcome, and when. The actor is derived from the authenticated principal, never from a field a caller supplies. Events are the raw material; everything below is built from them.
Actions that change authority or evidence are also written to the audit log, an append-only
chain in which every entry carries the hash of the one before it. The platform re-verifies the
entire chain from its genesis every hour and records the verdict; a broken link raises a critical
detection the moment it is found. You can read the latest verdict at any time
(GET /api/v1/command/audit/verify).
| Record | What it is | Where to read it |
|---|---|---|
| Events | The envelope stream: every action, every outcome, newest first, with filters by actor, action, severity, session and time | GET /api/v1/command/events; live tail at GET /api/v1/command/events/stream |
| Audit log | The tamper-evident chain of authority-changing actions, each entry with its compliance tags and hash | GET /api/v1/command/audit; verdict at /audit/verify |
| Detections | The platform's conclusions: a rule matched a pattern in the events (credential stuffing from one address, a replayed refresh token, a cloned passkey, an agent exhausting its budget) | GET /api/v1/command/detections, filterable by family (agents, identity, approvals, …) |
| Findings and incidents | Detections a person triaged, with evidence, assignment and state; an incident groups the findings of one episode | GET /api/v1/command/findings, GET /api/v1/command/incidents |
| Compliance evidence | Each action's control mapping, the register entries, attestations and readiness history (Enterprise plan) | GET /api/v1/command/compliance/* |
| Sessions, organization-wide | Every active session in the organization with its network, the client that holds it and when it moved network | The organization's Sessions view in the console, with revoke-one and revoke-all for administrators |
| Detection and incident summaries | Counts by severity and state, for dashboards | GET /api/v1/command/detections/summary, GET /api/v1/command/incidents/summary |
All of these are under /api/v1/command, read with the command:read permission; the three
mutations (triage, assignment, closing) need command:operate. Scoping is automatic: you read your
own organization, and only yours.
The platform's own health is a separate surface for the platform operator, under
/api/v1/observability (GET /health/deep, /slo, /posture, /jobs): the database
connection pool, Redis memory and persistence, event-bus lag, disk headroom and signing-key age.
On the managed service the operator is Zynth Media; on a self-hosted install it is you.
What the platform concludes
Detections are rules over the event stream, each with a threshold set so the ordinary use of a feature cannot reach it. A person mistyping a device code twice is ordinary; the fifth unmatched code from one person inside 15 minutes is a detection. The rule's description, shown beside every detection in the console and in the alert email, says what the pattern means and what to look at first.
Rules are organized in families so a team can filter by what it is responsible for: the
authentication chokepoint, sessions and tokens, AI agents and the tools they call, the approval
loop, the OAuth surface, the HIPAA and AI-governance registers, retention, webhooks and the
platform's own health. A detection in the agents family names the agent, its delegating human
and the tool or resource involved, because that is the triage an agent incident needs.
Decoys: catching an agent that looks around
The platform plants three decoys in your organization's authorization vocabulary: a permission,
a role and a record that look like ordinary entries and that nothing can legitimately
reach. No role grants the permission, no assignment can seat the role, and the record names no row
in any organization. An AI agent that enumerates the permission catalogue
(GET /api/v1/authz/catalog) is shown them; people and API keys are never shown them, so an
ordinary workload has no way to arrive at one, and a person cannot meet one in the console's role
builder. The decoys' names are deliberately not published here: a decoy an adversary can look up
is a decoy an adversary can avoid.
Touching a decoy is not a failure of any control, because it grants nothing. It is evidence that an agent is reaching past its brief. The platform watches for a request that names one when:
- an authorization check or an action check is made;
- a role is created, changed or assigned, or a delegation is created;
- a manifest is submitted for planning, for approval or to apply, over the API or through the MCP tools;
- an onboarding bootstrap request parks a manifest. That call needs no sign-in, so the touch is recorded against the bootstrap's own identifier.
When one is named, the platform records and carries on. It writes a security.canary_touched
event (critical, outcome denied) whose metadata names the surface and which kind of decoy was
named, and the request is answered exactly as it would have been without the decoy. Nothing about
the answer changes; the decoy only observes.
Two detections watch that event, and a single touch is enough to raise either:
| Detection | Who touched it | Why it is read the way it is |
|---|---|---|
agent-canary-touched | An AI agent | The agent was shown the decoy in the catalogue and reached for it. The detection names the agent. It is bound to the non-human containment response, which freezes the agent (Autonomous response); an onboarding bootstrap that names a decoy raises it too, against the bootstrap's identifier, before any organization exists, so there is nothing to freeze and the alert is the signal; how far containment goes for an agent is the organization's choice in autonomy.level_contain_non_human (manual by default; at recommend the platform proposes the freeze and a person decides). |
canary-touched-by-service | An API key or other service credential | A service is never shown the decoys, so it did not read the name off a catalogue it was served. It learned it somewhere else, which is a stronger signal. |
A person who names a decoy is recorded in the event stream but raises no detection: a person
is never shown the decoys, so the only way to name one is to type a value out of nowhere, and
pointing a critical alert at the one population that could do so innocently is how a decoy earns
the reputation that makes a team ignore it. Both detections are raised as critical and reach
people the way every detection does (How your team is told).
Anomaly rules of your own. Beyond the catalogue, an organization declares its own threshold rules over the same stream — a volume of a named action per principal, per network or per hour, a sequence that should never happen, an action from a network the organization has never seen — and they are evaluated, grouped and surfaced exactly like the catalogue's rules, with the same families, the same triage and the same notification paths.
How your team is told
- In the console and the API. The Command Center lists your organization's detections,
findings and incidents, the audit log with its verification status and the organization's
sessions; the same data is on
GET /api/v1/command/detections,/findingsand/incidents. For alerting inside your own tools, use the exporter in Ship it to your SIEM. - Your own alert channels. On Pro and Enterprise, your organization's own detections can be emailed to the members you choose, or sent to one of your webhook endpoints as a signed
alert.raisednotice, at the severity you choose, with a record of every attempt (Alert channels). - Email to the platform operator. A detection at or above a configured severity floor
(critical by default) is emailed to the operator's alert address with the rule's explanation and
the first thing to check. On the managed service the operator is Zynth Media, who act on it; on a
self-hosted install it is the address you set (
command_alert_email), and the same detection can be posted to a webhook you configure. - Customer webhooks carry the event types in the webhook catalogue: API-key and OAuth-client
changes, sign-ups, email verification, login throttling, session revocation and published
content (Webhooks). Deliveries are signed and retried with backoff, and a failed
window can be replayed from the console or the API. Detections, findings and incidents are
never part of the event catalogue; the one notice that originates from a detection is
alert.raised, sent only through an alert channel you create, with a fixed minimal set of fields and never the detection's group, description or event data. - Containment notices when an AI agent is stopped: always to the platform operator, and, when the organization opts in, to its verified owners.
Ship it to your SIEM
Perihelium integrates with the SIEM you already run; it is not a general log sink.
Streaming export. An organization configures an OTLP or syslog exporter: the event stream, the detections and the audit log are delivered as they are recorded, with the envelope's fields mapped to the target's schema and the organization identifier on every record. The exporter is a tenant-scoped setting with its own audit history; delivery is reported on the status view and a stalled exporter raises a detection of its own, because an export that quietly stops is worse than none.
Bulk export. GET /api/v1/command/events and GET /api/v1/command/audit page backwards
with a keyset cursor, so a complete export never skips or repeats a record as new ones arrive;
each audit entry carries its hash and the hash of the one before, so the receiving system can
re-verify the chain independently. The forensic export of one person's history —
every event they caused and every session they held — is a single call for an investigation or a
data-subject request.
Verifiable checkpoint. The audit chain's tip — its sequence number, hash and time — is published as a signed checkpoint under a published key, so an external log or your own monitoring can witness that the chain has not been rewritten between two readings.
Feeding the platform from your own systems
Your gateway, your LLM router or your own application can report into the same stream through
event ingestion (Event ingestion): a registered vocabulary of agent
actions (a tool invoked, a tool refused, a policy violated, an injection suspected, a budget
exceeded), metadata only, never content. Ingested actions carry the same four decisions as the
platform's own — telemetry, detection, audit, compliance — so the rules in the agents family
evaluate an ingested action as they do a native one.
What you can rely on
- An event is never edited or deleted; the audit chain's verification proves it.
- Reads are scoped to your organization at the database, not at the query.
- Severity and actor are assigned by the platform, never chosen by a caller.
- A notification path that fails is itself recorded, so silence is visible.