Skip to content

System landscape

This page shows the whole universe: FINNS’s own services, integration partners and the third-party services we rely on. See External services and the Roadmap for payment, POS, CDP and hotel systems.

flowchart TB
  classDef ours fill:#13686C,stroke:#0B4A4D,color:#ffffff
  classDef ext fill:#F3ECDF,stroke:#B9A88B,color:#12191B
  classDef person fill:#E9724C,stroke:#C55A37,color:#ffffff
  classDef staff fill:#FDE9E2,stroke:#E9724C,color:#12191B

  guest(["Guest"]):::person
  staff(["Staff"]):::person

  subgraph touch["Touchpoints"]
    direction TB
    pass["<b>FINNS Pass</b><br/>Apple/Google Wallet"]:::ours
    app["<b>Guest app</b><br/>Flutter (mobile app + web)"]:::ours
    booking["<b>Booking website</b><br/>CTG"]:::ext
    gate["<b>Gate scanner</b><br/>Vendor TBD"]:::ext
    admin["<b>Admin console</b><br/>SvelteKit"]:::staff
  end

  subgraph platform["Trident platform"]
    direction TB
    api["<b>API</b>"]:::ours
    loyalty[("<b>Loyalty</b><br/>Points ledger and membership")]:::ours
    assets[("<b>Assets</b><br/>Wallet balance, wristbands")]:::ours
    accesses[("<b>Accesses</b><br/>Gym")]:::ours
    rel[("<b>Relationships</b>")]:::ours
    resv[("<b>Reservations</b><br/>Events")]:::ours
    txn[("<b>Transactions</b>")]:::ours
    pii[("<b>Customer PII</b>")]:::ours
  end

  subgraph services["Services"]
    direction TB
    kc["<b>Guest identity</b><br/>Keycloak"]:::ext
    jc["<b>Staff identity</b><br/>JumpCloud"]:::ext
    ses["<b>Transactional email</b><br/>Amazon SES"]:::ext
    pg["<b>Payment gateway</b><br/>Airwallex"]:::ext
    pos["<b>POS</b><br/>Shiji"]:::ext
    pms["<b>PMS</b><br/>Daylight"]:::ext
    sota["<b>Customer engagement</b><br/>Sota Platforms"]:::ext
    cdp["<b>CDP</b><br/>Insider"]:::ext
  end

  guest --> touch
  staff --> touch

  touch -- "REST · handoff and launch codes ·<br/>check-ins · sign-out revoke" --> platform
  touch -- "OIDC sign-in" --> services
  platform -- "user changes · Points API ·<br/>integrations" --> services
  • FINNS platform built and run by FINNS
  • Vendor or third party built or bought outside FINNS, to our contract
  • Staff tool used by FINNS staff, not guests
  • Person guest or staff
Container Owner Built with Runs on Talks to
Core FINNS Java 25, Quarkus 3.39 (native image) DigitalOcean App Platform PostgreSQL, Keycloak, partners’ revoke endpoints
PostgreSQL FINNS PostgreSQL 18, Flyway migrations DigitalOcean Managed Postgres Core (and Keycloak’s own database, same cluster)
Keycloak FINNS (operated) Keycloak 26.8 + FINNS event-listener extension DigitalOcean droplet, Docker Compose, Caddy Core (webhook), browsers (sign-in)
Guest app FINNS Flutter 3.47 / Dart 3.13 iOS, Android, web on Cloudflare Workers Keycloak, core, engagement partner, booking website
Admin console FINNS SvelteKit 2, Svelte 5, Tailwind 4, shadcn-svelte Cloudflare Workers JumpCloud, core
Booking website CTG Vendor’s choice Vendor’s choice Keycloak, core
Customer engagement Sota Platforms Vendor’s choice Vendor’s choice Core
Gate scanner Vendor Vendor’s choice Vendor’s hardware Core
JumpCloud SaaS n/a JumpCloud Admin console

The booking website, the customer engagement partner and the gates each have a reference implementation that FINNS built to prove the contracts. Those are examples only. Vendors build their own on whatever stack they choose, and the only requirement is that they follow the API contracts: booking, engagement, gate.

From → To Protocol Authenticated by Direction of trust
App → Core HTTPS JSON Keycloak access token (azp=trident-app) Core validates JWT against Keycloak’s keys
App → Partner HTTPS + one-time code Code issued by core Partner redeems the code with core
Admin console → Core HTTPS JSON, server to server Static service token + acting staff member’s id Core re-checks the staff member on each call
Booking / Engagement partner / Gate → Core HTTPS JSON, server to server One static bearer token per integration Core checks before routing
Core → Partners HTTPS POST /auth/revoke A separate revoke token per partner Partner checks
Keycloak → Core HTTPS POST (async, retried) Webhook token Core checks, then reads the user itself
Core → Keycloak Admin REST API Client credentials (finns-core-sync, view-users only) Keycloak checks

There is no message broker. Changes flow as direct HTTPS calls, plus one pull-based feed (the points events feed) that the engagement partner polls. See Points & membership.

Internal and confidential. Share partner sections only as partner builds (pnpm build:partner).