Application layer use cases grouped by domain with invocation chains
Execute AI Config. See the source file for the full orchestration steps and invocation chain.
Updates an existing ai-config record. Only the fields present on the input are touched.
Deletes a bet record. Does not reverse the bankroll transaction — operators use this to remove accidentally-entered manual bets before any money actually moved.
Places a bet through an API-enabled bookmaker: validates the tip and bankroll, submits to the bookmaker's placement endpoint, persists the resulting Bet row, and debits the bankroll + data-source balance.
Updates a bet (odds, stake, status, notes). When odds or stake change, potentialProfit is recalculated.
Records a bet the operator placed by hand at a soft bookmaker (no API). Validates the tip, data source and bankroll balance; calculates potential profit; inserts the Bet row; and debits the bankroll + data-source balance ledgers.
Spins up a new Camoufox browser session on the scraper service. Operators use this to debug a scraper flow interactively or seed an authenticated cookie jar.
Terminates a live Camoufox browser session on the scraper service and frees the port.
Sends a single Playwright-style action (click / fill / navigate) to a live Camoufox session. Used by the browser debugger and scraper authoring tools.
Decodes a base64 PNG from the scraper service and stores it as a BrowserScreenshot row so the debugger can play back a failed scrape frame by frame.
Creates a competition record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deletes a competition record. Cascade rules apply via foreign keys.
Links a competition mapping to its canonical entity after manual review.
Reruns the deterministic matcher for a set of previously-unmatched mappings.
Updates an existing competition record. Only the fields present on the input are touched.
End-to-end onboarding for a new Competition: validates lookups, creates the canonical Competition + first CompetitionMapping, then delegates to FetchSeasons for the full season pipeline (AI generation, mapping sync across every data source, dates, adapter reconcile, competitor counts, retry-match). Fixtures are populated separately via the FETCH_FIXTURES job.
Umbrella pipeline for a single competition. Generates canonical seasons via AI web search (identity only — name, year, isCurrent, hard floor 2021), syncs SeasonMapping rows from every data source, populates dates from the primary adapter, reconciles canonical seasons against adapter truth, then retry-matches anything still unlinked.
Bulk-deletes competition rows that match an admin-supplied filter.
Deletes a competition and every dependent row (mappings, fixtures, tips).
Re-runs the COMPETITION_SEASON_DATES AI call for a single canonical Season and persists the updated startDate / endDate when the AI returned authoritative dates. Exposed on the season row as a per-season refresh button so operators can fix rows that ended up with placeholder dates (e.g. when the adapter had nothing at the time of the prior run).
Bulk-deletes competitor rows that match an admin-supplied filter.
Deletes a competitor and every dependent row (mappings, fixtures, tips).
Creates a competitor record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deletes a competitor record. Cascade rules apply via foreign keys.
Links a competitor mapping to its canonical entity after manual review.
Creates a data-source-balance record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deposit Data Source Balance. See the source file for the full orchestration steps and invocation chain.
Withdraw Data Source Balance. See the source file for the full orchestration steps and invocation chain.
Pulls the current list of sports (event types) from a bookmaker's public API, upserts the resulting mapping rows, and auto-links any that either exact-match or clear the AI confidence threshold against the canonical event-type list. Called from the Data Sources page whenever an operator wants to refresh a source.
Bulk-deletes event-type rows that match an admin-supplied filter.
Deletes a event-type and every dependent row (mappings, fixtures, tips).
Deletes a event-type record. Cascade rules apply via foreign keys.
Links a event-type mapping to its canonical entity after manual review.
Bulk-deletes fixture rows that match an admin-supplied filter.
Deletes a fixture and every dependent row (mappings, fixtures, tips).
Creates a fixture record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deletes a fixture record. Cascade rules apply via foreign keys.
Links a fixture mapping to its canonical entity after manual review.
Searches the connected Gmail account for historical emails matching a sender / subject / date-range filter, then enqueues a TIP_INGEST job per email so the tip-extraction pipeline can backfill tips that predate the inbox monitor.
Handle Gmail OAuth Callback. See the source file for the full orchestration steps and invocation chain.
Logout Gmail. See the source file for the full orchestration steps and invocation chain.
Simulate Kelly Cashflow. See the source file for the full orchestration steps and invocation chain.
Updates an existing kelly record. Only the fields present on the input are touched.
Calculate Kelly. See the source file for the full orchestration steps and invocation chain.
Calculate Kelly Playground. See the source file for the full orchestration steps and invocation chain.
Simulate Kelly. See the source file for the full orchestration steps and invocation chain.
Bulk-deletes outright rows that match an admin-supplied filter.
Deletes a outright and every dependent row (mappings, fixtures, tips).
Creates a outright record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deletes a outright record. Cascade rules apply via foreign keys.
Links a outright mapping to its canonical entity after manual review.
Deletes a race-meeting record. Cascade rules apply via foreign keys.
Links a race-meeting mapping to its canonical entity after manual review.
Creates a race-meeting record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Creates a race record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deletes a race record. Cascade rules apply via foreign keys.
Links a race mapping to its canonical entity after manual review.
Deletes a region record. Cascade rules apply via foreign keys.
Links a region mapping to its canonical entity after manual review.
Removes the link between a region mapping and its canonical entity; the mapping row itself is kept.
Logs into tipstrr.com via the Camoufox scraper, walks a tipster’s /results page back to the configured cutoff date, resolves the advised bookmaker for each row (string match → AI → auto-create), and persists each tip as a PENDING TipMapping so the existing rematch pipeline can promote them to Tip rows.
Creates a scheduled-job record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deletes a scheduled-job record. Cascade rules apply via foreign keys.
Toggle Scheduled Job. See the source file for the full orchestration steps and invocation chain.
Updates an existing scheduled-job record. Only the fields present on the input are touched.
Removes a single SeasonMapping row. Leaves the canonical Season intact and does not touch fixtures — only the link from a data source's season row to our canonical one.
Links a provider's SeasonMapping row to a canonical Season chosen by the operator. Used from the mappings page to manually resolve rows the auto-match flow left unlinked.
Deletes every unmapped SeasonMapping row — optionally scoped to one data source or one competition mapping. Useful after bulk-linking a provider when the surviving unmapped rows are known-junk.
Admin action to create a canonical Season row by hand. Normal season creation happens through GenerateAiSeasonsUseCase; this path exists for edge cases where the AI has missed a split-year or qualifier season that an operator needs immediately.
Deletes a canonical Season and every row that references it via Restrict FKs: fixtures (with their results, scores, mappings), outrights (with their runners, results, mappings), tournament fields (with entries and entry mappings), and SeasonMappings. Tips are detached (FK set to null) rather than deleted, since they are durable user-authored data. Destructive — the UI should confirm before calling it.
Deterministic re-match pass over a specific set of unlinked season mappings. Tries exact name, normalised name, and year — no AI. Typically run as the final step of FetchSeasons or directly from the Seasons Mappings page by an operator.
Updates a canonical Season (name, dates). If the date range changes, existing fixtures whose start falls inside the new range are reassigned to this season so the dashboard numbers stay accurate.
Subscribe Notification. See the source file for the full orchestration steps and invocation chain.
Unsubscribe Notification. See the source file for the full orchestration steps and invocation chain.
Test Monitoring Server. See the source file for the full orchestration steps and invocation chain.
Updates an existing monitoring record. Only the fields present on the input are touched.
Check Notification Subscription. See the source file for the full orchestration steps and invocation chain.
Updates an existing app-config record. Only the fields present on the input are touched.
Start Telegram Auth. See the source file for the full orchestration steps and invocation chain.
Submit Telegram Code. See the source file for the full orchestration steps and invocation chain.
Submit Telegram Password. See the source file for the full orchestration steps and invocation chain.
Creates a tip record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Re-runs the pick matcher against a single PENDING TipMapping. Honours tipster manual aliases added since the original ingest, so a fresh mapping surfaces here. Auto-promotes to MATCHED with a Tip row when the rematch yields a fully-matched, high-confidence pick.
Creates a tipster record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deletes a tipster record. Cascade rules apply via foreign keys.
Updates an existing tipster record. Only the fields present on the input are touched.
Creates a tipster-bankroll record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deposit Tipster Bankroll. See the source file for the full orchestration steps and invocation chain.
Withdraw Tipster Bankroll. See the source file for the full orchestration steps and invocation chain.
Creates a venue record. Used as an admin CRUD action; business-logic creation paths live in their own use cases.
Deletes a venue record. Cascade rules apply via foreign keys.
Links a venue mapping to its canonical entity after manual review.
Umbrella for the daily racing sync: discovers every DataSource that has a mapped horse-racing or greyhounds event type, fetches meetings for today + tomorrow, then pulls races for each already-linked meeting. Delegates per step to FetchRaceMeetings and FetchRaces so the main pipelines can also be run in isolation.
Fetches upcoming and recent fixtures for a competition mapping, matches runners to canonical Competitor rows (AI-assisted where needed), and persists Fixture + FixtureMapping records. Detects disappeared fixtures on the primary data source so cancellations surface in the UI.
Pulls golf head-to-head matchups (Player A vs Player B) for a golf tournament mapping, matches both players to canonical Competitor rows, and stores them as Fixture records with matchup-specific metadata.
Pulls outright markets (winner-of-tournament and similar) for a competition mapping, matches each runner to a canonical Competitor, and upserts OutrightMapping rows. Mostly runs from the scheduled FETCH_OUTRIGHTS job but can be triggered ad-hoc from UI.
Pulls the day's race meetings (tracks + cards) for a given event-type mapping, upserts VenueMapping and RaceMeetingMapping rows. Part of the SyncRacingData job — races are fetched in a follow-up pass.
Fetches the races on a specific race meeting (greyhounds or horse racing), runs every runner through the AI-assisted competitor matcher, and persists Race + Runner mapping records with confidence scores. Part of the SyncRacingData flow.
Pulls the entry list (field) for a golf / tennis / mma tournament — one row per participating competitor — matches each entrant to a canonical Competitor, and stores them as TournamentFieldEntry records on the relevant Season.
Pulls the leaderboard for a tournament (golf / tennis / mma), maps each provider row to the canonical TournamentFieldEntry, and writes positions/scores back so bet settlement can later decide winners.
Umbrella over FetchCompetitions — iterates every mapped event type for a data source and pulls its competitions in sequence. Used by the "fetch everything from this source" scheduled job so operators can refresh a provider without picking event types one by one.
Umbrella over FetchFixtures — iterates every mapped competition for a data source and pulls its fixtures one by one. Used by the scheduled "refresh this provider" job.
Fetches every competition (league / tournament) the given event-type mapping offers, upserts CompetitionMapping rows, AI-matches unmapped rows against the canonical Competition list, and optionally kicks off AI season generation for newly-matched competitions so FetchFixtures has canonical seasons to attach to.
Calls the Betfair SSO keepAlive endpoint using the stored app key and session token so the Betfair session stays active. Runs on a schedule (Betfair sessions expire after ~20 minutes of inactivity).
Ensures every API-enabled bookmaker has a DataSourceBalance row so the dashboard bankroll figures have something to render. Provider-specific balance fetching is handled by the bookmaker adapters separately.
Fan-out scheduled job. Looks up every PENDING TipMapping and enqueues one REMATCH_PENDING_TIP job per row, reusing the manual /tips/pending/rematch-all path. Recovers tips whose canonical fixture / competitor was synced after ingest.
Scans for fixtures that have finished but still have pending tips and resolves each tip (won / lost / void) using the fixture result. Settled tips also cascade to settle their associated bets.
Polls unread emails in the connected Gmail account, enqueues a TIP_INGEST job per email, and archives the email. Runs on a recurring schedule so new tipster emails arrive in /tips automatically.
Verifies the Telegram session, pulls recent messages from a single chat, and enqueues a TIP_INGEST job per non-empty message so the tip-extraction pipeline can ingest them.
Rsyncs the Postgres backup directory from Hetzner to the Mac Mini over Tailscale. Runs on a daily schedule and reports files transferred + total size.
Extracts tip picks from raw email or Telegram content, detects the tipster from the picks + metadata, and writes one PendingTip row per extracted pick for later review and auto-creation. Runs inside the TIP_INGEST queue as a one-job-per-message pipeline.
Deletes browser screenshots and scrape session logs older than 30 days so disk usage on the scraper service stays bounded.
Internal helper used by FetchFixtures to resolve a SeasonMapping for the year being fetched. Pure lookup — does not create mappings or canonical seasons; returns null when nothing matches so the caller can raise a clear "run season setup first" error.
Internal helper that resolves "which Season does this fixture date belong to?". Tries exact date range first, then year (with split-year logic for football-style 2024/2025 seasons), then falls back to the current season or the most recent season.
Asks the AI (web-search prompt) to enumerate every season for a competition (hard floor: 2021 for calendar-year, 2021/2022 for split-year) and persists canonical Season rows with identity fields only (name, year, isCurrent). Dates and expected competitor counts are populated by later pipeline steps. Invoked by SetupCompetition, FetchCompetitions, and the FetchSeasons umbrella.
Populates canonical Season.startDate / Season.endDate from the primary data source's season list. The adapter already encodes the correct calendar-vs-split-year semantics per competition, so the dates it reports are authoritative. AI is not used here.
Runs a focused COMPETITION_SEASON_DATES AI web-search per canonical Season for authoritative start/end dates. Replaces the previous adapter-derived date population, which returned nulls for in-progress and upcoming editions. Skip-if-already-valid keeps the umbrella pipeline cheap; the per-season "Refresh dates" button passes forceRefresh=true to always re-query.
Settle Tips for Fixture. See the source file for the full orchestration steps and invocation chain.
Brings canonical Season rows into agreement with the primary adapter, which knows the authoritative start/end dates. Re-labels names from the actual date range (calendar-year vs split-year), backfills adapter years the AI step missed, and re-flags isCurrent so exactly one season — the one covering today's date — is current. Counter-acts AI hallucinations like Libertadores being labelled "2021/2022" or the in-progress edition being absent.
Creates SeasonMapping rows from each data source's season list for a competition. Year-matches provider seasons against the canonical Season rows — unmatched rows are persisted with seasonId=null so the operator can link them manually on the Mappings page.
Settles a single pending Bet: calculates actual profit from the fixture outcome, marks the bet WON/LOST/VOID, and credits winnings back to the bankroll + data-source ledgers.
Writes a ScrapeSession record capturing what scraper ran, whether it succeeded, how many rows came back, and how long it took. Powers the Scraper Health dashboard.