Providers
Sentry
Uses the Ahena CLI (beta). Install it with npm install -g @ahena/cli, or prefix commands with npx @ahena/cli. See Installation. The dashboard covers projects, connections, Doctor, the Stack Graph, plans and approvals without it.
Overview
Ahena checks that your app's Sentry project is set up and actually receiving errors: the
organization and its data region, the project, its client keys (DSN), the environments Sentry
has seen, an issue alert for production, releases and data scrubbing. It can create the project,
a client key and a production issue alert after you approve them, and generates a small
@sentry/node adapter. Your app sends events to Sentry directly. Ahena is never in the path.
Package: @ahena/provider-sentry · Category: monitoring · API: Sentry web API /api/0/ on
sentry.io, us.sentry.io and de.sentry.io
Capabilities: error-monitoring, projects, client-keys, environments, alerts, releases, data-scrubbing
Maturity: verified against a fake of the API; not yet verified against the real service.
Self-hosted Sentry is out of scope: Ahena only calls sentry.io and its two data-storage regions.
Connection
| Field | Secret | |
|---|---|---|
SENTRY_AUTH_TOKEN |
yes | An internal integration token (recommended). Personal tokens also work but stop working when that person leaves the organization. |
SENTRY_ORG |
no | The organization slug (https://<slug>.sentry.io). Required. |
SENTRY_PROJECT |
no | The project slug. Optional: Ahena lists your projects when you connect, and monitoring.project in ahena.config.ts overrides it. |
SENTRY_AUTH_TOKEN=… ahena connect sentry -e production --set SENTRY_ORG=leo-labs --set SENTRY_PROJECT=leo-web
Organization auth tokens (sntrys_…) aren't enough. Sentry gives them a fixed org:ci
scope for releases and source maps; they can't read projects, client keys or alerts. Ahena
detects one at connect and asks for an internal integration token instead. Keep the
organization token for CI.
Data region. Ahena reads the organization from sentry.io, takes its region URL
(links.regionUrl) and sends every organization-scoped call to that region (us.sentry.io
for US, de.sentry.io for EU), as Sentry's data-residency docs ask. Any other region URL is
refused.
Permissions
permissionCheck: "checked". When connecting, Ahena reads the token's scopes from Sentry's API
index (GET https://sentry.io/api/0/, the call sentry-cli info makes) and reports each
permission as granted, missing or unknown. That endpoint isn't in Sentry's published reference;
if it stops reporting scopes, every permission shows as :unknown, never as granted.
| Scope (internal integration permission) | Needed for |
|---|---|
org:read (Organization: Read) |
the organization and region, the project list, recent error counts |
project:read (Project: Read) |
project details, environments, client keys, releases |
alerts:read (Alerts: Read) |
alerts and the project's error monitor |
project:write (Project: Read & Write) |
creating the project or a client key |
alerts:write (Alerts: Read & Write) |
creating the production issue alert |
These scopes are advisory, never a decision. Because the endpoint is undocumented, any error
or unexpected answer from it makes every permission :unknown, and its answer alone never
refuses a connection or fails Doctor. Whether Ahena can work is decided by documented calls:
the organization read when connecting (401 = token rejected, 403 = it can't read the
organization; a token Sentry reports as CI-only is named as such), and each Doctor check's own
call (a 403 names the scope it needs). Scope-based findings are at most a WARNING. Sentry's reference lists org:read
among the scopes accepted for creating an alert, so a token with org:read and no
alerts:write is reported as alerts:write:unknown. Ahena never needs org:write,
project:admin, member:* or event:write.
Capabilities
| Capability | Access | What Ahena does |
|---|---|---|
error-monitoring |
read-only | Counts error events from the declared environment over the last N days (one aggregate query). |
projects |
writable (read-back) | Reads the project's platform, status and team; creates it for a team. |
client-keys |
writable (read-back) | Lists keys with their public DSN; creates one when none is active. |
environments |
read-only | Lists the environments Sentry has seen for the project. |
alerts |
writable (read-back) | Finds an enabled issue alert covering production; creates one. |
releases |
read-only | Reads the latest releases and their dates. |
data-scrubbing |
read-only | Reads Data Scrubber, default scrubbers and IP scrubbing. Never changes them. |
The public DSN is not a secret: Sentry designs it to ship in browser code. Ahena never reads a
key's secret field, the legacy secret DSN, or the project's options (which hold a security
token); responses are parsed through allowlists. ahena lock records the project's status,
platform and scrubbing settings, client key ids (not secrets) and alert names, environments and
enabled state for drift.
Configure
monitoring: {
provider: "sentry",
organization: "leo-labs", // or SENTRY_ORG on the connection
project: "leo-web", // or SENTRY_PROJECT
team: "leo", // only needed to create the project
platform: "javascript-nextjs", // optional; defaults from `framework`
environments: ["production", "staging"],
environment: { production: "production", staging: "staging" }, // Sentry name per Ahena environment (default: the slug)
alerts: { production: true }, // ensure an issue alert (default: production only)
noEventsDays: 7, // Doctor warns after this many days without events
},
Every value may also be keyed by environment slug.
| Change | Classification | Notes |
|---|---|---|
Create the project (bound to team) |
CONFIRMATION_REQUIRED | Sentry doesn't charge per project; the events it receives count against the organization's quota and, with pay-as-you-go, can be billed. That's shown as a cost notice. Sentry creates the project's default client key; its public DSN is returned as SENTRY_DSN. When an Ahena alert is planned too, Sentry's catch-all default alert is turned off (default_rules: false) so you don't get two. |
| Create a client key | CONFIRMATION_REQUIRED | Only when the project has no active key. Its public DSN is returned as SENTRY_DSN. |
| Create the issue alert for production | CONFIRMATION_REQUIRED | Ahena: new and regressed issues in production (<project>): first-seen, regressed and reappeared issues, emailed to suggested assignees (falling back to active members), at most every 30 minutes, connected to the project's error monitor. Uses the current Monitors & Alerts API (/organizations/{org}/workflows/). |
Why not BILLABLE: creating a project, key or alert costs nothing in Sentry. Cost comes from event volume, which the app generates, not the change. The notice says so before approval.
SENTRY_DSN: Ahena has no non-secret environment values, only encrypted secrets, so the
public DSN is returned through the apply result and stored as the secret SENTRY_DSN. It isn't
sensitive; it's stored there so ahena env reveal and deploy tooling can read it from one
place. For an existing project, copy it from ahena inspect sentry and run
ahena env set <env> SENTRY_DSN.
Every create re-reads first and only creates what's absent, so retrying a plan never makes a second project, key or alert. After apply, a second plan with the same configuration is empty once Sentry shows the change (VERIFIED).
Refused: deleting, disabling or editing projects, client keys or alerts; rotating keys;
changing data scrubbing, IP scrubbing, sensitive fields or any other Security & Privacy setting.
Desired keys such as deleteProject, deleteKey or dataScrubber are rejected with an
explanation.
Generate
ahena generate sentry:
src/ahena/monitoring/index.ts:initMonitoring()starts@sentry/nodefromSENTRY_DSN(does nothing when it's unset), withenvironmentandreleasefromSENTRY_ENVIRONMENT/SENTRY_RELEASE, tracing off, and reduced data collection (no automatic user fields, cookies or request bodies).monitoring.captureException,monitoring.flush,monitoring.raw..env.example.sentry
Add @sentry/node to your app. The generated code is typechecked against @sentry/node 11 in
Ahena's tests. For Next.js, browser apps and source maps use Sentry's own wizard
(npx @sentry/wizard@latest -i nextjs): it sets up client, server and edge configs and the
build plugin, which a small generated file shouldn't try to replace.
Limitations
- Self-hosted Sentry isn't supported.
- Ahena never deletes projects, client keys or alerts, and never changes security, privacy or data-scrubbing settings.
- Only an issue alert for one environment is managed; metric alerts, uptime and cron monitors, integrations (Slack, PagerDuty) and alert routing beyond email to suggested assignees are out of scope.
- If Sentry hasn't created an error monitor for the project, Ahena can't connect an issue alert to it and says so (create the alert in Sentry instead).
- A project's platform isn't changed; a mismatch with your framework is reported only.
- Releases, source maps and deploys are read, not created: do that in CI with an organization token.
- The "no events" check counts error events only. A quiet, healthy app also shows zero.
- Token scopes come from an unpublished (but long-standing) endpoint; if it changes, permissions show as unknown.
- Personal tokens are bound to a person; prefer an internal integration.
Manual steps
- Create an internal integration (below) and connect with its token.
- Initialise the SDK in every deployment with
SENTRY_DSNand the rightenvironment. - Turn on Data Scrubber in Project Settings → Security & Privacy if Doctor reports it off.
- Create releases from CI with an organization auth token (
sentry-clior a bundler plugin).
Doctor checks
| Id | Severity | Meaning |
|---|---|---|
sentry.token |
PASS / WARNING / FAIL | Token valid; scopes reported by Sentry. FAIL for a rejected or CI-only (organization) token or missing read scopes; WARNING for missing write scopes. |
sentry.organization |
PASS / WARNING / FAIL | Organization reachable, with its data region and API host. |
sentry.project |
PASS / INFO / FAIL | Project exists and is active. Missing → CONFIRMATION_REQUIRED fix when team is declared, else MANUAL. INFO when no project is declared. |
sentry.project.platform |
PASS / INFO | Project platform matches the app's framework. |
sentry.data_scrubbing |
PASS / WARNING | Server-side data scrubbing on (MANUAL fix; Ahena doesn't change it). |
sentry.client_key |
PASS / WARNING / FAIL | An active client key exists (FAIL in production without one). |
sentry.environments |
PASS / WARNING | Every expected environment has been seen by Sentry. |
sentry.events.<environment> |
PASS / WARNING / INFO | "Sentry isn't receiving events from production": no error events in noEventsDays (default 7). |
sentry.alert.<environment> |
PASS / WARNING | An enabled issue alert covers the environment (an alert with no environment covers all). |
sentry.releases |
PASS / INFO | Releases are being created (INFO when none, or none in 30 days). |
Set up step by step
Create the credential. In Sentry: Settings → Developer Settings → Create New Integration → Internal Integration. Name it "Ahena", save, and copy the token it shows.
Grant the minimum permissions on that integration: Organization: Read; Project: Read & Write; Alerts: Read & Write. Read-only use (inspect and Doctor) needs only Organization: Read, Project: Read and Alerts: Read.
Connect:
SENTRY_AUTH_TOKEN=… ahena connect sentry -e production --set SENTRY_ORG=… --set SENTRY_PROJECT=…Verify the connection:
ahena inspect sentry -e productionshows the organization and its region, projects, environments, client keys (public DSN), releases and alerts.Run Doctor:
ahena doctor -e production.Plan: add
monitoringtoahena.config.ts, thenahena plan -e production(orahena configure sentry -e productionfor this provider only).Apply an allowed change:
ahena apply -e production(or answer yes inahena configure sentry). Creating the production alert is a typical first change.Verify: Ahena re-plans after applying; the change is VERIFIED when the second plan is empty.
ahena doctor -e productionshould now passsentry.alert.production.Troubleshooting:
Symptom Cause Fix "organization auth token (CI scope only)" An sntrys_tokenUse an internal integration token. "Sentry rejected the auth token" Token revoked or mistyped Create a new token on the integration and reconnect. "missing org:read" / "needs the project:write scope" Integration permissions too narrow Edit the integration's permissions, then reconnect. "organization … wasn't found" Wrong SENTRY_ORGUse the slug from https://<slug>.sentry.io."isn't a sentry.io data-storage region" Self-hosted or unknown region Not supported. "Sentry isn't receiving events from production" SDK not initialised, no DSN, or another environment name Set SENTRY_DSNandenvironment, trigger a test error.Alert action skipped: "no error monitor" Sentry hasn't created the project's error monitor Create the alert in Sentry (Alerts → Create Alert). Disconnect and revoke:
ahena disconnect sentry -e production, then in Sentry go to Settings → Developer Settings → your internal integration and revoke the token (or delete the integration).
Disconnect behavior
Removes the connection and the token Ahena stored. Ahena can't revoke an integration token itself: revoke it in Settings → Developer Settings → your internal integration. Projects, client keys, alerts, releases and events are untouched.