Worker

The Worker kit is the hosted auth and Git API boundary for web clients. It owns OAuth redirects, secure credential storage, sessions, and REST access to repositories.

Service

Cloudflare Worker Service

@git-pont/worker (kits/worker) is a deployable Cloudflare Worker that turns @git-pont/core into a hosted service. It handles multi-platform authentication server-side, persists connections so returning users do not reconnect, and exposes a normalized REST API a web app can call.

The first consumer is gitKanban: a user logs in with GitHub OAuth, picks a repository, and the worker serves repository data. With a valid session cookie, a returning user is recognized without logging in again.

Relationship to the core kit: the worker consumes @git-pont/core. The core kit (auth + proxy) is usable standalone; the worker adds the stateful concerns (OAuth callback handling, sessions, persistence, per-user profile).

Endpoints

MethodPathPurpose
GET/auth/github/startRedirect the browser to GitHub's consent screen (sets a short-lived state cookie).
GET/auth/github/callbackExchange the code, persist/reuse the connection, create a session, redirect to the app.
GET/sessionCurrent session and connections. The returning-user check.
POST/logoutDestroy the session and clear the cookie.
GET/repositoriesList repositories for the session's connection.
GET/repos/:owner/:repoRepository metadata (also records a recent repo).
GET/repos/:owner/:repo/branchesList branches.
GET/repos/:owner/:repo/contents/<path>?ref=branchDirectory listing or single file (UTF-8 text when decodable, plus base64).
GET/me/profilePer-user preferences (color mode, recent repos, app preferences).
PATCH/me/profileShallow-merge preference updates.

On a successful OAuth callback the worker mints an opaque, unguessable session id and stores it server-side (KV). The id is returned as a Secure; HttpOnly; SameSite=Lax cookie — the primary path for a web app calling with credentials: "include". The same id may also be sent as Authorization: Bearer <sessionId> for native or cross-origin callers. Both resolve to the same session record; provider access and refresh tokens never leave the worker in either path.

Session lifetime is configurable (SESSION_TTL_SECONDS, default 30 days). While the cookie is valid, /session returns the connection without re-authenticating — this is the "don't reconnect" behavior.

Storage — Cloudflare KV

Three KV namespaces, all keyed so a user only ever sees their own data:

  • SESSIONSsession:<id>{ userId, connectionIds, expiresAt }.
  • CONNECTIONSconn:<userId>:<connId> (metadata, no secrets) and cred:<userId>:<connId> (credentials encrypted at rest with AES-GCM using the GITPONT_ENC_KEY secret).
  • PROFILESprofile:<userId> → color mode, recent repos, app preferences.

The stores implement the core ConnectionStore / CredentialStore interfaces, scoped per user, so the facade never observes cross-user data. KV was chosen for simplicity; because storage sits behind interfaces, D1 (for relational queries) or a Durable Object (for strictly serialized GitLab token refresh) can be swapped in later without touching the facade.

Configuration

Vars (wrangler.toml): ALLOWED_ORIGINS, APP_LOGIN_REDIRECT, OAUTH_REDIRECT_BASE, GITHUB_SCOPES, SESSION_TTL_SECONDS.

Secrets (wrangler secret put / .dev.vars): GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GITPONT_ENC_KEY (base64-encoded 32-byte key).

CORS is locked to ALLOWED_ORIGINS with credentials enabled.

gitKanban integration

  1. Send the user to GET /auth/github/start (full-page navigation).
  2. After consent GitHub returns to /auth/github/callback; the worker sets the session cookie and redirects to APP_LOGIN_REDIRECT.
  3. Call the API with credentials: "include". On load, call GET /session; if authenticated is true, skip the login prompt.
  4. Store UI preferences via PATCH /me/profile.

Follow-ups

  • GitLab / Forgejo-Gitea / Bitbucket login and proxying (GitLab's ~2h tokens introduce a Durable-Object serialized refresh).
  • Write endpoints (commit, pulls, submit) once the app needs writes.
  • An optional thin client SDK for calling the worker.

Security

git-pont handles repository credentials and can write to user repositories. Security rules should be strict from the first commit.

Secrets

Tokens must only live in a CredentialStore.

Do not store tokens in:

  • app config JSON
  • GitConnection
  • GitRepositoryReference
  • remote URLs
  • logs
  • thrown error messages
  • test snapshots

Logging

Logs may include:

  • provider kind
  • host
  • repository namespace/name
  • HTTP status code
  • normalized error code

Logs must not include:

  • access tokens
  • refresh tokens
  • authorization headers
  • raw credential helper scripts containing token values
  • full request bodies for write operations unless redacted

URL Safety

Reject repository paths containing:

  • ..
  • absolute local filesystem paths
  • empty path segments after normalization where a file path is required
  • NUL or control characters

Commit Safety

Updating an existing file must include provider-specific version protection:

  • GitHub: sha
  • GitLab: last_commit_id
  • Forgejo/Gitea: file SHA (required by the API)

If no expected version is available, updating or deleting an existing file requires the explicit caller option allowBlindOverwrite: Bool on GitFileChange / GitFileDeleteRequest. Default must be false; without it and without a version, throw .conflict rather than write.

Deleting a file must go through the explicit delete API. Committing empty content is never a delete.

Refresh Safety

Token refresh must be serialized per connection (GitLab rotates refresh tokens; a duplicate concurrent refresh invalidates the surviving token). The refreshed credential must be persisted to CredentialStore before dependent requests proceed. See Authentication → Token Refresh.

Browser Auth

OAuth flows should:

  • use PKCE when supported
  • use secure random state
  • validate state on callback
  • avoid client secrets in native apps unless there is a backend
  • store refresh tokens only in CredentialStore

Keychain

GitPontKeychain should:

  • use generic password items
  • use a service name configurable by the consuming app
  • use stable account IDs such as git-pont:{connectionID}
  • prefer kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly for local app storage

Git CLI

GitPontGitCLI must avoid token leakage:

  • tokens must be passed through environment variables
  • token values must not appear in command arguments (variable names in the helper script are fine)
  • set GIT_TERMINAL_PROMPT=0
  • do not mutate global git config
  • do not write credential helpers to disk in v1

Network

The package should not disable TLS verification.

Self-hosted instances with invalid certificates are not supported in v1. If this is added later, it must be an explicit app-level trust decision.