-
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.
Four hops. Each line is the host contacted and by whom.
| # | Who | Host contacted | Request |
|---|---|---|---|
| 1 | Browser | palaestra.thrivetech.ai |
GET https://palaestra.thrivetech.ai/api/auth/login |
| 2 | Browser | www.linkedin.com |
Redirected to LinkedIn's consent page, carrying the public client id and a random state
|
| 3 | Browser | palaestra.thrivetech.ai |
LinkedIn redirects back: GET https://palaestra.thrivetech.ai/api/auth/callback?code=…&state=…
|
| 4 | Server | api.linkedin.com |
Server-to-server over TLS. Exchanges code for an ID token. The browser is not involved. |
The server then writes the player record and sets one session cookie.
Hop 3 returns to palaestra.thrivetech.ai, not to LinkedIn. A filter that
permits palaestra.thrivetech.ai generally but blocks
https://palaestra.thrivetech.ai/api/auth/callback will fail sign-in after
the user has already authenticated with LinkedIn. The user sees a block page at
the end of a successful login, which reads as the site being broken.
Both hosts must be reachable for sign-in to complete:
palaestra.thrivetech.ai and www.linkedin.com from the browser,
api.linkedin.com from the server.
| 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.
All on palaestra.thrivetech.ai.
| Endpoint | Limits |
|---|---|
GET https://palaestra.thrivetech.ai/api/health |
None needed |
GET https://palaestra.thrivetech.ai/api/scenarios |
Read-only catalogue |
POST https://palaestra.thrivetech.ai/api/support |
Message ≤ 2000 chars, page ≤ 200 chars, attached trace ≤ 64 KB. Hard caps, enforced before any write. |
GET https://palaestra.thrivetech.ai/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