OxalisAdmin

Dashboard

Organizations

NameSlugMembersSeatsStatusExpiresActions

Users

NameEmailRoleOrgStatusLast LoginActions

Invites

OrgEmailRoleStatusExpiresCreatedActions

Trial Links

Share a single link on LinkedIn, WhatsApp, or email to let anyone sign up for a time-limited trial account. Trial users land in the shared Trial org with viewer-only access.

CreatedUsesExpiresStatusActions

Analytics

Logins by user

Who's actually using it, how often, from where. Trial users get a chip; device column is the (OS · browser) mix seen across their sessions; acquisition is where they came from (newsletter / direct / referrer).

UserOrgLogins Page viewsLast login DevicesFrom

Org adoption

Per-organisation activity. lonely seat = paid for >1 user but only one has logged in. no logins = seat exists but nobody's ever signed in. Trial orgs flagged with a chip.

OrgMembers ActiveLogins Page viewsLast activityFlags

Acquisition

Where sessions came from. Built from the ref= URL param on newsletter links, UTM tags on share URLs, and the bare HTTP Referer host as a fallback.

SourceSessionsUsers

Top pages

PageViews

Raw user activity (legacy)

UserPage ViewsSessionsLast Active

Corpus

Inventory counters for the entity-event graph. These were moved off the front-of-house FSI dashboard so it reads as an editorial intelligence brief rather than a bulk-extract preview.

People
Firms
Entities (total)
Events (total)
Growing firms
Shrinking firms
Algo desk signals
Candidates available

Billing

Stripe wiring status. Set STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET, point the Stripe Dashboard webhook at /api/billing/webhook, then bind each plan's Stripe price below. Prices & amounts live in Stripe — here you set the price binding, trial length, and what happens when a trial ends.

Loading…

Plans & packaging

A plan becomes self-serve sellable once it's active and has a Stripe price ID. Trial days > 0 starts every self-serve checkout with a free trial; auto-renew converts to paid at trial end (card required), cancel ends with no charge.

Loading plans…

Offer links (marketing)

Build a shareable link encoding a deal — fixed seats, trial length, and whether a card is required at sign-up. Paste it into outreach. A cold prospect gets a brand-new workspace; a signed-in customer can apply it to theirs. e.g. "5 seats, 14-day trial, auto-bill" vs "10 seats, 30-day trial, no card".

Loading offers…

Firm priorities

Curate which of the ~41k FCA firms are in scope. target_tier1 + target_tier2 appear in the newsletter and refresh weekly; passive is the default for unknown firms; excluded is dropped from the pipelines entirely. Manual overrides always win over auto-rules. The DB is now the source of truth — target_firms.json is a bootstrap seed only; use Export for snapshots, version control, or restoring a fresh instance.

Loading…

Backfill from curated list

Reads data/target_firms.json and stamps every matching firm with the right tier. Idempotent. Skips rows where you've set a manual override.

Bulk exclude

Mark a set of firms as excluded so they stop appearing in the newsletter and refresh queues. Always shows a preview first.

For "classifications only", enter a comma-separated list, e.g. compliance,other.

Triage queue — biggest untriaged firms first

Firms with no priority row (or computed status of passive) ordered by headcount. Click a button to mark each one in place. The list refreshes after every action so you can rip through the long tail.

FirmHCEventsMark as

Manual overrides

Firms where you've manually set include / exclude. These always win over the auto-rules.

FirmStatusOverrideReasonUpdated

Backups

Daily Postgres operational dump (04:00 UTC) and weekly DuckDB snapshot (Mondays 04:15 UTC). Both are GPG-encrypted on the server and rsync'd to the Synology NAS, which POSTs to /api/backups/checkin after each successful pull. A green pulled badge means the off-site copy is fresh; red means the server has the encrypted dump but the NAS hasn't fetched it yet. Read-only view.

Loading…

Recent runs — newest first

Type Started Status Size Duration Pulled off-site Notes

Errors

Every server-side 5xx and every client-side JS error lands here, regardless of whether the Discord webhook succeeded. The Discord column shows whether an alert was scheduled (yes = sent or deduped; no = no webhook configured or scheduling failed). Top errors lets you spot the single hot loop causing most of the noise. Auto-pruned after 90 days.

Top errors (by count)

SourceExceptionSample CountUsers First seenLast seen

Recent (newest first)

WhenSrcExceptionWhere UserDiscord

Control

idle
Loading...
Enrichment: ...

FCA Pipeline

Step 1 — Seed Target Firms

Search FCA for curated target list (250+)

Step 2 — Discover Firms

Search FCA register A-Z (resumable)

Step 3 — Sync CFs

Pull controlled functions for discovered firms

Step 4 — Enrich People

Full career history via /Individuals/{IRN}/CF

Step 5 — Resolve

Entity resolution (Splink) to merge duplicates

SCA Pipeline (UAE Securities & Commodities Authority)

~279 licensed companies + employees, board members, finfluencers. No API key required.

Step 1 — Discover
Step 2 — Sync Details
Step 3 — Finfluencers

FCA Firm Search

Person Search & Enrich

Schedules & Runs

Dagster UI →
Schedules
Loading...
Recent Runs
Loading...
Stats
Loading...
ready.