-
Notifications
You must be signed in to change notification settings - Fork 0
Security Review
Facts for a security reviewer assessing palaestra.thrivetech.ai. Every item
below is verifiable against published source, linked at the bottom.
| Type | Browser-based simulation. Single-page application plus JSON API. |
| Hosting | Cloudflare Workers. Static assets and API served from one Worker. |
| Domain | palaestra.thrivetech.ai |
| Data stores | Cloudflare D1 (SQLite), Cloudflare R2 (scenario files) |
| Commercial model | None. Nothing is sold. No payment processing exists. |
| Destination | When | Purpose |
|---|---|---|
www.linkedin.com |
Sign-in only | OAuth consent, as a top-level browser navigation |
api.linkedin.com |
Sign-in only | Server-to-server exchange of authorization code for name and email |
The server contacts no other host. The browser contacts no host other than
palaestra.thrivetech.ai.
There is no CDN, analytics, web font, advertising network, tracking pixel, or
error-reporting service. The only external strings in the built JavaScript are
the SVG XML namespace (www.w3.org) and two documentation URLs inside a
markdown library's error messages. None is fetched at runtime.
- Browser requests
/api/auth/login. Server redirects to LinkedIn with the public client id, a redirect URI, and a randomstate. - LinkedIn authenticates the user and redirects to
/api/auth/callback?code=…&state=…. - Server validates
state, then exchangescodefor an ID token over TLS toapi.linkedin.com. - Server writes the player record and sets one session cookie.
A filter that permits the domain but blocks /api/auth/callback will fail
sign-in after the user has already authenticated.
| Property | Value |
|---|---|
| Providers | LinkedIn OpenID Connect. No others. |
| Passwords | None exist. None is created, transmitted, stored, or recoverable. |
| Session token | HMAC-SHA256 over an internal player id, keyed by a server-side secret |
| Verified | Locally, by recomputing the signature. Not a bearer token for any third party. |
| Cookie flags |
HttpOnly, Secure, SameSite=Lax, Path=/
|
| Lifetime | 30 days |
| Revocation | Sign-out deletes the cookie immediately |
Administrative access is a comma-separated allowlist of player ids in the deployment configuration, not a database column. It cannot be granted by anything the running application does, only by a deployment.
Administrative endpoints fail closed: an unauthorized caller receives 404,
indistinguishable from a route that does not exist. A missing or empty
allowlist grants nothing, including to the operator.
SESSION_SECRET and LINKEDIN_CLIENT_SECRET are set through the deployment
platform and appear in no file in either repository.
LINKEDIN_CLIENT_ID is public by construction; it travels in the address bar
of every sign-in.
Static JavaScript, HTML and CSS served from the site's own origin. No plugin, extension, or local agent is required or offered. No file is downloaded. No file is uploaded. No user-supplied content is rendered to other users.
| Endpoint | Limits |
|---|---|
GET /api/health |
None needed |
GET /api/scenarios |
Read-only catalogue |
POST /api/support |
Message ≤ 2000 chars, page ≤ 200 chars, attached trace ≤ 64 KB. Hard caps, enforced before any write. |
GET /api/unsubscribe/:token |
Signed token |
Everything else requires a valid session and returns 403 without one.
The application writes structured error logs to the platform console. It writes no request log of its own.
Cloudflare Workers observability is enabled at full sampling. It records request method, path, status, ray id, and timing, under Cloudflare's retention.
Runtime dependencies are a small set of published npm packages: React, TanStack Router and Query, Hono, Observable Plot, and a markdown renderer. Dependabot is enabled. There is no vendored binary and no build-time network fetch beyond the package registry.
Copies of the running code:
-
inspect/worker/auth.ts— the sign-in flow -
inspect/worker/session.ts— session signing and verification -
inspect/worker/support.ts— the unauthenticated endpoint and its caps -
inspect/wrangler.jsonc— every binding the server has, two values redacted and marked - SECURITY.md
support@palaestra.thrivetech.ai
See also Privacy Review.
Exedra
Why
How it is built
What you write
Boundaries
For reviewers