Skip to content

Commit 8cabb86

Browse files
authored
Say what the last change actually did, in the changelog and the docs (#634)
The Unreleased entry described a desktop release for a commit that also put a new route on the server. Rewritten against the code rather than the summary. What it was getting wrong: Bun is not "replaced", the version already on the machine is left untouched and simply not used, and the check now gates Start as well as install. Repair moved under Installation options on the install screen only; it is still a top-level button on the stopped screen. "Existing Docker credentials are preserved" described code that is not in the tree, since nothing reads or writes Docker's config.json; the real change is that the inherited PATH is now kept and appended to rather than replaced. What it was missing: OPENBOT_MODEL_OAUTH_FILE and the route it mounts, the Gemini transport, a provider 403 no longer reading as an expired sign-in, the leftover-database reset, the Windows Compose separator, and the organization sign-in fix for a callback that arrives in pieces. The docs had drifted in the two files that call themselves the full reference. charts/openbot/README.md never absorbed computers.podSecurityContext, so an existing k3s install upgrading to 0.0.14 hits CrashLoopBackOff with the explanation only in the changelog; that upgrade note is the one operators will actually need. docs/configuration.md was missing SIGNIN_ALLOWED_EMAIL_DOMAINS, OPENBOT_ORGANIZATION_AUTH_URL and OPENBOT_ACCESSIBILITY_DISABLED, and said nothing about the desktop owning OPENAI_BASE_URL and OPENAI_API_KEY under provider OAuth. docs/architecture.md now lists the new route beside the other boundaries, and the docs index links the two desktop documents nothing pointed at.
1 parent 6014b39 commit 8cabb86

6 files changed

Lines changed: 132 additions & 10 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,77 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged.
88

99
## Unreleased
1010

11-
### Desktop setup shows progress and works around occupied local ports
12-
13-
Downloads show transferred bytes and elapsed time, Back preserves saved connections, and repair
14-
stays under Installation options after setup. OpenBot selects and remembers usable local ports,
15-
including when Windows reserves a default port. Setup can create a CopilotKit project and offers
16-
Google Gemini and xAI API-key choices, plus OAuth sign-in with automatic token refresh. Google
17-
OAuth requires the distributor's desktop client and quota-project configuration. Unsupported Bun
18-
installations are replaced with the pinned runtime; startup errors retain useful details and provide a configurable setup-help link.
19-
Docker image downloads can find the credential helper bundled beside Docker even when it is
20-
missing from the desktop app's PATH. Existing Docker credentials and helper preferences are preserved.
11+
### A model provider's own sign-in can stand in for an API key
12+
13+
`OPENBOT_MODEL_OAUTH_FILE` names a credential file holding a Google or xAI OAuth grant. Set it and
14+
the server mounts `POST /api/model-provider/v1/chat/completions`, which answers an ordinary Chat
15+
Completions request using that grant, refreshing the access token 120 seconds before it expires and
16+
again on a provider 401, and persisting the rotation under a lock the writer and the desktop share.
17+
Leave it unset, which is every deployment that does not set it, and the route does not exist.
18+
19+
The caller authenticates with a separate local bearer taken from that file, compared in constant
20+
time, never with the provider's own token: a refresh token never leaves the server process. The file
21+
itself is refused unless it is a regular file under 64KB owned readable by nobody else, and a Google
22+
grant must name a quota project. The upstream host, path and headers are fixed, so nothing a caller
23+
sends can redirect the request.
24+
25+
Google is reached through its native generation API rather than a compatibility endpoint, with a
26+
translation layer that carries streaming, tool calls and their results, inline images and
27+
function-call thought signatures across in both directions. An API-key connection is unchanged and
28+
still uses the compatibility endpoint.
29+
30+
**A provider 403 no longer reads as an expired sign-in.** It usually means a missing project or
31+
resource permission, which signing in again cannot fix, so only a 401 now raises "sign in again".
32+
33+
### Desktop setup shows progress, chooses its own local ports, and can sign in to a provider
34+
35+
Downloads report transferred bytes, every running step reports elapsed time, and running, completed
36+
and failed stages are told apart. Back preserves the connections already entered.
37+
38+
OpenBot now chooses its local ports by binding them rather than assuming them, holds them until the
39+
whole set is settled, and writes them to the deployment's `.env` so a restart keeps the same
40+
addresses. That covers a port another program holds and a port Windows has reserved, neither of
41+
which the old fixed defaults survived. A port that becomes unavailable between choosing and starting
42+
now says so and asks for another Start, where it previously refused before trying.
43+
44+
Setup can create a CopilotKit project, and offers Google Gemini and xAI as API-key choices alongside
45+
OAuth sign-in. Google sign-in requires this build's own registered desktop client and quota project,
46+
set at build time or by environment variable, and refuses with a message saying so when it has
47+
neither; xAI falls back to a public client and works in any build. `desktop/PROVIDER_OAUTH.md`
48+
describes what a distributor configures.
49+
50+
A deployment left behind by an earlier installation can be detected and reset from the app, which
51+
removes that deployment's database volume and nothing else.
52+
53+
Startup failures keep enough of the log to name the cause, with every secret value redacted, and
54+
carry a support link a whitelabel build can point elsewhere.
55+
56+
### A Bot's image pull finds the Docker credential helper beside Docker
57+
58+
A Docker install whose credential helper sits next to the `docker` binary rather than on the desktop
59+
app's own PATH failed the pull with a PATH error naming the helper. The directory holding the
60+
resolved `docker`, and the directory holding what it points at when it is a symlink, are now appended
61+
to the PATH the engine is invoked with. Appended, so an existing helper still wins, and the inherited
62+
PATH is now kept rather than replaced, which it was not before.
63+
64+
### OpenBot starts only on the Bun it pins
65+
66+
An installed or cached Bun that is not the pinned version is no longer accepted, on install and on
67+
every start, and OpenBot acquires its own copy instead. The version already on the machine is left
68+
exactly as it is and simply not used.
69+
70+
### Organization sign-in survives a callback that arrives in pieces
71+
72+
The loopback listener that receives an organization or provider sign-in read the callback once and
73+
gave up if the whole request had not arrived, and on Windows the accepted socket inherited the
74+
listener's non-blocking mode, so a timeout did not apply. A good sign-in could be answered "Sign-in
75+
did not match". Both paths now read until the request line is complete, with a real timeout.
76+
77+
### Compose file lists separate correctly on Windows
78+
79+
The separator between Compose files fell back to `:` everywhere, which is right on macOS and Linux
80+
and wrong on Windows, where a drive letter contains one. It now follows the platform. This is
81+
reachable on every platform now that a port overlay is passed, where before it was macOS only.
2182

2283
## 0.0.14
2384

‎charts/openbot/README.md‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,33 @@ install rather than found as a browser that fails on every page.
466466
467467
## Upgrades
468468
469+
### Coming from a release before 0.0.14: a computer now runs as uid 1001
470+
471+
`computers.podSecurityContext` runs a Bot's computer as `pwuser`, uid 1001, in both `shared` and
472+
`sandbox` mode. It was root before. The volumes an existing release created are root-owned, so
473+
something has to hand them over, and that something is `fsGroup`: the kubelet takes ownership of a
474+
volume's contents on mount.
475+
476+
**It does that only where the volume plugin says it can.** The EBS, PD and Azure Disk CSI drivers
477+
do. `hostPath` does not, and `hostPath` is what rancher/local-path-provisioner hands out, which is
478+
the default StorageClass on k3s. There the computer starts as 1001, finds a directory it cannot
479+
write, and refuses to start rather than coming up healthy with a browser profile Chromium silently
480+
replaced. The message names this. Two ways out:
481+
482+
```sh
483+
# Either hand the existing directories to 1001 on the node, or go back to root:
484+
helm upgrade openbot ./charts/openbot --set computers.podSecurityContext=null
485+
```
486+
487+
**`--reuse-values` will not pick this up.** A new key is not in the old release's values, so an
488+
upgrade run that way keeps running as root and says nothing. Pass the value, or drop the flag.
489+
490+
`fsGroupChangePolicy: OnRootMismatch` is deliberate. Unset means `Always`, which walks every file on
491+
every mount, and a real Chromium profile is tens of thousands of small ones; in `sandbox` mode that
492+
pass would run again on every resume from idle.
493+
494+
### How a rollout is sequenced
495+
469496
Migrations run as a `pre-install,pre-upgrade` Job, so no replica ever serves in front of a schema it
470497
has not seen. An init container would mean every replica racing to migrate the same database.
471498

‎desktop/PROVIDER_OAUTH.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ apply.
5656
References: [xAI's OpenCode integration](https://x.ai/news/grok-opencode) and
5757
[xAI OAuth discovery](https://auth.x.ai/.well-known/openid-configuration).
5858

59+
## Other build-time settings
60+
61+
`VITE_OPENBOT_SUPPORT_URL` replaces the support link a startup failure offers. Unset, it points at
62+
this repository's issues. A whitelabel build points it at its own support channel.
63+
5964
## Credential lifecycle
6065

6166
The desktop's provider credentials remain in its local deployment; React does

‎docs/README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@ Start with the root [README](../README.md), then use these references:
1515
- [Kubernetes](../charts/openbot/README.md): the Helm chart, what a cluster needs before it, and the values that differ per cloud.
1616
- [Releasing](releasing.md): how a release is proposed, reviewed and published.
1717
- [Windows desktop signing](windows-signing.md): protected Azure Key Vault signing and verification of the app and NSIS installer.
18+
- [Desktop provider OAuth](../desktop/PROVIDER_OAUTH.md): what a distributor configures to offer Google and xAI sign-in in a desktop build.
19+
- [Desktop telemetry](../desktop/TELEMETRY.md): every event the desktop app sends, and what it carries.
1820

1921
Do not include credential values, customer data, transcripts, or local-only notes in public docs.

‎docs/architecture.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,5 +346,6 @@ Connector credentials are stored through the credential vault and referenced by
346346
- `KEY_ENCRYPTION_KEY` must be a base64-encoded 32-byte value. The example key is refused with `NODE_ENV=production`.
347347
- Credential plaintext is encrypted at rest, never returned by APIs, and redacted from audit events.
348348
- Browser navigation allows `http` and `https`; cloud metadata addresses are refused under every configuration.
349+
- `POST /api/model-provider/v1/chat/completions` exists only when `OPENBOT_MODEL_OAUTH_FILE` names a model credential file, which the desktop app sets and nothing else does. It answers a Chat Completions request using a stored Google or xAI OAuth grant. It does not use the session guard: the caller presents a separate local bearer taken from that file and compared in constant time, and the provider's own refresh token never leaves the server. The credential file is refused unless it is a regular file under 64KB with no group or other permission bits, and the upstream host, path and headers are fixed so a caller cannot redirect the request.
349350
- `AGENT_COMPUTER_ALLOW_PRIVATE_HOSTS=true` is for local development only, and a deployment running with `NODE_ENV=production` refuses to start while it is set.
350351
- Computer tokens and supervisor tokens must be long random values outside local development.

‎docs/configuration.md‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ at `agent-langgraph` on a laptop.
6363
| `AUDIT_RETENTION_DAYS` | unset | Whole number of days to keep audit rows; older ones are removed. Unset keeps the trail forever. |
6464
| `WORKER_SHARED_SECRET` | unset; `start.sh` uses a fixed local default | The secret the routines worker presents to fire a due routine. Without it the server refuses every handoff, whether or not a worker exists to send one. |
6565
| `OPENBOT_GENERATIVE_UI` | unset (capability on) | Set `false` or `0` to stop Bots from answering with generated interfaces. |
66+
| `OPENBOT_ACCESSIBILITY_DISABLED` | `true` or `1` stops naming OpenBot on the analytics the runtime already sends. |
6667
| `COMPOSIO_API_KEY` | unset | One key for the whole deployment, for the broker that holds people's accounts for a few hundred apps. Unset, there is nothing to connect, nothing to grant and no Composio tool for a Bot to call; what remains is one row that goes nowhere, under **More apps** on the admin Plugins page, naming this variable. See [Composio](plugins/composio.md). |
6768

6869
**`OPENBOT_GENERATIVE_UI`** enables generated interfaces by default: streamed HTML/CSS/JavaScript
@@ -179,6 +180,15 @@ Two things are worth knowing before pointing a deployment at any gateway. Not ev
179180
| `INITIAL_ADMIN_EMAILS` | Comma-separated administrators. **Required** with any provider. |
180181
| `OPENBOT_PUBLIC_URL` | Public address of this API. Defaults to `BETTER_AUTH_URL`. |
181182
| `OPENBOT_APP_URL` | Where the browser app is served. Defaults to the first `TRUSTED_ORIGINS` entry. |
183+
| `SIGNIN_ALLOWED_EMAIL_DOMAINS` | Comma-separated email domains admitted at sign-in. Empty means no opinion. Exact, no wildcards. |
184+
| `OPENBOT_ORGANIZATION_AUTH_URL` | An OpenBot deployment that verifies employee identity and roles. Decides sign-in ahead of `OPENBOT_SINGLE_USER`. |
185+
186+
**Some variables belong to the desktop app, not to you.** A desktop installation writes these into
187+
its own deployment's `.env` and owns their values: `OPENBOT_MODEL_OAUTH_FILE`, `CHATGPT_AUTH_FILE`
188+
and `CLAUDE_CODE_OAUTH_TOKEN`. When a model provider is connected by OAuth rather than by key, the
189+
desktop also points `OPENAI_BASE_URL` at OpenBot's own loopback route and sets `OPENAI_API_KEY` to a
190+
local proxy credential rather than a provider key, so those two do not mean what the table above says
191+
in that mode. A server you configure yourself is unaffected by all of this.
182192

183193
**With no provider at all, `OPENBOT_SINGLE_USER=true` is required.** A deployment that configures
184194
nothing to sign anybody in and does not say that was deliberate refuses to start, naming what to
@@ -194,6 +204,22 @@ address and a `.local` name are what this flag is mostly used for, and anybody o
194204
the administrator. A value that cannot be parsed as a URL counts as public, because nobody checked
195205
it.
196206

207+
**`SIGNIN_ALLOWED_EMAIL_DOMAINS` decides who may sign in**, as distinct from who is an
208+
administrator once in. Matching is exact with no wildcards, so `example.com` admits neither
209+
`sub.example.com` nor `evil-example.com`, and both sides go through the same IDNA normalisation, so
210+
a rule may be written `@Example.COM.` or in punycode and still mean what it says. Two arrangements
211+
are refused at start-up rather than documented and hoped for: a list that normalises to nothing,
212+
which `@` and a stray `.` both produce, because it is a non-empty list no address can match; and a
213+
list combined with a `MICROSOFT_OAUTH_TENANT_ID` that names no directory (`common`, `organizations`
214+
or `consumers`), because there the address the list is checked against is one the signing-in tenant
215+
writes for itself. A production deployment that names no domains and leaves the tenant multi-tenant
216+
is warned rather than refused.
217+
218+
**`OPENBOT_ORGANIZATION_AUTH_URL` names an authority, not a provider.** It must be an HTTPS OpenBot
219+
origin, or HTTP on loopback, and a bare origin: a username, password, query, fragment or any path
220+
other than `/` is refused at start-up. Naming one settles sign-in by itself, ahead of
221+
`OPENBOT_SINGLE_USER`.
222+
197223
**Any one provider turns sign-in on**, and several may be configured at once. Each provider's id and
198224
secret must be set together, Okta additionally needs its issuer, and any of them requires
199225
`BETTER_AUTH_SECRET`, `BETTER_AUTH_URL` and `INITIAL_ADMIN_EMAILS`. Every incomplete combination is

0 commit comments

Comments
 (0)