A client ↔ server poker-room suite where the server owns every write
kHold'em (by eShark / LiPoker) is a .NET Framework 4.6 Windows tournament-management suite installed at C:\kHoldem. Clients never touch the database — they speak to a WCF/binary-TCP server that is the only sanctioned path to the data.
service.json are DPAPI-encrypted and non-portable.kHoldem DBEvery client funnels through one core server into one database
2505 · 5856 · 7215
SSPI
.\KHOLDEM · db kHoldemkholdemsync (HTTPS)kHoldemBackup, kHoldemPrintEngine, and kHoldemPokerLens hang off the same server/DB layer. Every backend service is the same binary — kholdemhost.exe /service <Name> — running as LocalSystem.Backend roles & ports
| Service | Role | Ports |
|---|---|---|
| kHoldemServer | Core app server — logic, SQL connection, serves all clients | 250558567215 |
| kHoldemWebServer | Local Web + API (OWIN, Swagger), serves pages & Angular app | 5855 |
| kholdemsync | Cloud sync engine — pushes/pulls to eShark | outbound |
| kHoldemBackup | Scheduled DB backups | — |
| kHoldemPrintEngine | Ticket / receipt / report printing | — |
| kHoldemPokerLens | RFID / card-recognition integration | — |
| MSSQL$KHOLDEM | SQL Server instance | UDP 1434 |
System of record
- Engine: Microsoft SQL Server 2017 (
MSSQL14.KHOLDEM), running asNT AUTHORITY\LOCALSERVICE. - Database:
kHoldem— 145 tables, 11 stored procedures. - Auth: Mixed mode enabled, but the app uses Windows integrated (trusted) —
service.jsonhas a Connection block with server + database but no password. - Keys: nearly every table uses an app-generated
uniqueidentifier(GUID) primary key; async_lastupdatedcolumn drives optimistic concurrency. - Collation caveat: columns mix
Latin1_General_CI_AS_KS_WSandSQL_Latin1_General_CP1_CI_AS— cross-collation string concatenation throws in ad-hoc SQL.
Domain families: Tournament*, Cash*, Player / PlayerClub / VIP*, Ranking / Season / League, Transaction / Payment / Document, Mail / SMS, Server / Device / Domain, BlackList, Permission / Group / User (RBAC).
C:\kHoldemWhat sits on disk
| Path | What it is |
|---|---|
| kholdem.exe | Desktop client — WinForms + DevExpress + WebView2. The operator UI. |
| kholdemhost.exe | Service host — one process per backend service. |
| kholdemmedia.exe | Media / clock renderer (tournament clock, displays). |
| Components\ | Application assemblies — LiPoker.*.dll core, DevExpress UI, Twilio, AWS SNS, Chilkat, Google APIs, SignalR, OWIN. |
| Addons\ | Plug-in modules (*.kpl): triton, pslive, barriere, igt, pokerlens, eid, apt, cis, leris, luxon, neon, zino, direpay, ci, spider — evidence of a supported extension mechanism. |
| Web\ | Local web + API host: legacy ASP.NET (LiPokerWS) pages + Web\v2\ compiled Angular SPA (public results / clock viewer). |
| Configuration\syncengine.json | Declarative map of every table that participates in multi-site cloud sync. |
| Database\Release.bak | Shipped baseline DB backup, used to provision the DB on install. |
Runtime state lives outside the install dir in C:\ProgramData\kHoldem\: service.json (connection + cloud identity), version.json, *.lic, Log\, Data\, and server-side addon binaries under Addons\Server\ (Core, Sync, Backup, PokerLens, PrintEngine, Security).
Timestamp-based, last-writer-wins delta sync
syncengine.jsondeclares ~110 replicating tables, each with GUID key(s) and UTC-vs-date-only markers (DateTimeMode).Account,Club,Player,TournamentcarryNetworkLastUpload/NetworkLastDownload/LastUpdatedmarkers.
What each layer requires
| Target | Credential |
|---|---|
| SQL DB .\KHOLDEM / kHoldem | Windows login on the instance (services run as LocalSystem = sysadmin). No SQL password stored. |
| kHoldemServer WCF | A kHold'em user account + a registered Device. Identity stored in HKCU\SOFTWARE\kHoldem. |
| eShark Cloud sync / licensing | Membership account + DPAPI-encrypted token & AccessToken, licenseId, ServerID. |
| Local Web/API port 5855 | App-level auth — returns HTTP 500 to anonymous probes. |
DPAPI blobs in service.json start with AQAAANCMnd8B… — decryptable only on this machine, by the account that encrypted them. Not portable, not a liftable API key.
It already exists — you configure it, not build it
KnockOut = 1. Real events today include "NLH Big Bounty: $3,000", "Speed Racer – NLH Bounty", and "NLH Mystery Bounty". Standard bounty, Progressive KO, and Mystery Bounty are all modeled end-to-end.Tournament bounty configuration
| Column | Type | Meaning |
|---|---|---|
| KnockOut | bit | Is this a bounty/KO tournament |
| KnockOutType | int | 1 = standard, 3 = Mystery Bounty |
| KnockOutAmount | float | Bounty value per player |
| KnockOutProgressive | float | PKO — share rolling onto the eliminator |
| KnockOutProgressiveRoundType | int | Rounding rule for the split |
| KnockOutTax · KnockOutHouse | bit | Tax / house-rake on the bounty portion |
| TotalKnockOut | decimal | Roll-up of bounty money in the pool |
TournamentPlayers per-player accounting
KnockOutCount,KnockOutValue,KnockOutAmountKnockedOutPlayerID,KnockedOutPlayersIDString— who this player eliminatedPayoutKnockOutAmount,PayoutAmount,PayoutAssigned
KnockOut = 1, set KnockOutType and KnockOutAmount, and a non-zero KnockOutProgressive. The UI, schema, and payout engine are already in place.Four ways in — ranked by safety and supportability
Drive the server, not the database. The options below run from most-native to actively-discouraged.
Addon (.kpl) plugin
kHold'em has a first-party plug-in model (triton.kpl, pslive.kpl, direpay.kpl…) with server-side binaries under ProgramData\…\Addons\Server\ and a LiPoker.Modules.Base.API.dll. A .kpl runs inside the server process, so it inherits the sanctioned data layer, sync-safe writes, and event hooks for free.
Client-protocol side-car
A standalone service that speaks the same WCF client protocol as kholdem.exe, reusing shipped SDK assemblies (LiPoker.Modules.Base.Client/API.dll, LiPoker.Network.dll). It authenticates as a user + Device and issues the same commands the UI does — every write passes server validation, permissions, and sync bookkeeping.
AdministrationHandler) — feasible but unofficial.Local Web / API (5855)
kHoldemWebServer self-hosts an ASP.NET Web API (LiPokerWS) with Swagger. Cleanest transport (HTTP/JSON) if the endpoints you need are exposed — but observed surface is live-results / display / cloud-registration oriented and returns 500 to unauthenticated probes.
Direct SQL writes
A local process can open a trusted connection and write — but don't, except read-only reporting:
- Server holds in-memory caches — out-of-band writes go stale/incoherent until reload.
- Sync engine overwrites hand-written rows or pushes bad deltas.
- GUID keys, invariants, payout math & permissions are enforced in code — you'll create orphans.
- The one safe direct use is READ — ideally against a restored
Release.bak, not the live DB.
Configure first, automate through the server, never write raw
Tournament, TournamentPlayers, payout tables) for dashboards/exports — safe and easy. Write side: implement Option B side-car, or pursue Option A Addon SDK. Never write tournament/player/payout rows straight into the live DB.