Architecture
OwlEye separates high-volume analytics facts from application and control-plane metadata.
Data stores
Section titled “Data stores”- ClickHouse stores analytics facts such as page views, custom events, rule events, and performance records.
- SQLite stores users, sites, teams, sessions, rules, dashboards, memberships, API keys, AI prompt allocations, and other application metadata.
This boundary keeps event-heavy queries in the store designed for them while leaving account and configuration workflows in a simple transactional database.
Ingestion path
Section titled “Ingestion path”Browser events enter through a public SDK endpoint and are queued through a bounded in-process batch writer. ClickHouse writes use async inserts with explicit JSONEachRow columns.
The SDK excludes query strings by default. captureCampaigns is the narrow attribution opt-in: it
sends only bounded utm_source, utm_medium, and utm_campaign values while arbitrary parameters
remain excluded. captureQuery is the broader opt-in and exposes the full query string. The
ingestion boundary extracts only those three UTM fields into campaign dimensions.
The ingestion path prefers backpressure over unbounded buffering. If the queue is full, the API returns a retryable service-unavailable response instead of silently growing memory use.
Privacy-preserving visitor cohorts
Section titled “Privacy-preserving visitor cohorts”The public SDK does not create or store a browser identifier. During ingestion, the API uses the
client address long enough to resolve optional GeoIP context and derive cohorts, but does not write
the raw address into the analytics fact row. IPv4 addresses lose their host octet (203.0.113.42
becomes the /24 prefix 203.0.113.0); IPv6 addresses lose the interface half and retain only the
/64 network prefix.
The server derives keyed, site-scoped hashes from that truncated prefix, request signals, and the operator’s private salt. The visitor cohort is stable while those inputs remain stable, so it is a pseudonymous aggregate—not a claim that one person can always be distinguished from every other person on the same network. A separate daily aggregate ID includes the UTC day, and session IDs use 30-minute time buckets. None of these values are returned to or persisted in the visitor’s browser.
Console path
Section titled “Console path”Console APIs use authenticated sessions. Public SDK ingestion and public rule fetching stay separate from dashboard APIs.
Site configuration uses canonical, site-scoped API routes. This is the current management surface:
GET|POST /v1/sitesGET|PUT|DELETE /v1/sites/{siteId}GET /v1/sites/{siteId}/eventsGET|POST /v1/sites/{siteId}/membersPUT|DELETE /v1/sites/{siteId}/members/{userId}GET|PUT /v1/sites/{siteId}/settingsGET|POST /v1/sites/{siteId}/api-keysPUT|DELETE /v1/sites/{siteId}/api-keys/{keyId}GET|POST /v1/sites/{siteId}/rulesGET|PUT|DELETE /v1/sites/{siteId}/rules/{ruleId}GET|POST /v1/sites/{siteId}/dashboardsGET /v1/sites/{siteId}/dashboard-invitesGET /v1/sites/{siteId}/dashboard-invites/{dashboardId}POST /v1/sites/{siteId}/dashboard-invites/{dashboardId}/acceptPOST /v1/sites/{siteId}/dashboard-invites/{dashboardId}/dismissGET|PUT|DELETE /v1/sites/{siteId}/dashboards/{dashboardId}GET|POST|DELETE /v1/sites/{siteId}/dashboards/{dashboardId}/sharesDELETE /v1/sites/{siteId}/dashboards/{dashboardId}/shares/meDELETE /v1/sites/{siteId}/dashboards/{dashboardId}/shares/{userId}POST /v1/sites/{siteId}/dashboards/{dashboardId}/widgetsPOST /v1/sites/{siteId}/dashboards/{dashboardId}/widgets/previewPUT|DELETE /v1/sites/{siteId}/dashboards/{dashboardId}/widgets/{widgetId}Every request resolves the site from the path and verifies organization membership. API-key management and rule mutations require an owner or administrator role; settings mutations are owner-only. Event exploration is read-only. API-key creation returns the secret once; OwlEye stores the hash and non-sensitive lookup metadata, so the secret cannot be recovered by a later read. These routes describe the API contract used by both the authenticated console and direct automation. Console roles and pages and Pro View document the role and dashboard behavior in more detail.
Pro View sharing stores pending, accepted, dismissed, and revoked recipient state in SQLite. Only the dashboard creator manages recipients. A pending recipient can preview and then accept or dismiss an invitation; accepted dashboards appear as read-only views. A recipient can remove only their own copy, while the creator can revoke one recipient, revoke every shared copy while retaining the canonical dashboard, or delete the canonical dashboard for everyone. Each route verifies both current app membership and the capability required for that transition.
AI access is a separate, owner-managed control-plane permission with fluid, equal, or custom prompt allocation. The current prompt handler validates and accounts for allowance but returns no generated content and makes no model-provider call. See AI mode and prompt allocation for the current-phase boundary.
Hosted service boundary
Section titled “Hosted service boundary”This repository runs one product: the OwlEye-managed hosted service. Local loopback HTTP and logged OTP delivery exist only for development. Every non-loopback API deployment fails closed unless it has canonical HTTPS origins, secure cookies, SMTP delivery, and a strong deployment root secret. Hosted retention is stamped at ingestion and its workers run in every service deployment. Hosted launch status documents the remaining operational gates.