Skip to content

docs: ADR 0021 amended for tenant-registered clients, and SDK 1.28.0 (#1125) - #1885

Merged
jhgaylor merged 1 commit into
mainfrom
stack/1125-9-docs
Sep 11, 2026
Merged

docs: ADR 0021 amended for tenant-registered clients, and SDK 1.28.0 (#1125)#1885
jhgaylor merged 1 commit into
mainfrom
stack/1125-9-docs

Conversation

@jhgaylor

@jhgaylor jhgaylor commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Part 9 of 9 for #1125 (re-cut of #1489). Based on #1884. Last in the stack.

The record of the decision, the manual, the app skill and the SDK version.

ADR 0021's consequence said a third-party clients table would come "when a third party asks". The amendment says what the ask turned out to be, and writes down the wrong answer — wildcard the sandbox domain in both lists — so nobody re-proposes it. It marks the two consequences it changes rather than rewriting them, its frontmatter is re-verified, and decisions/index.md is regenerated by scripts/decisions-index.sh. okf validate decisions is clean.

docs/api.md gains the registration endpoints, the development-mode rule and the twenty-five ceiling. docs/sdk.md and docs/build/team-chat.md stop telling a browser app that API_CORS_ORIGINS is its only way in. The build-fountain-app skill loses the "ask the operator, open an issue" path and gains the one command that replaces it.

SDK 1.28.0 — re-check before merge

The wire types were regenerated in #1882 with no bump (sdk-no-release); this carries the version across package.json, the lockfile, USER_AGENT and the SDK changelog.

main was at 1.27.0 when this was written. Re-check it immediately before merging this PR, because concurrent bumps must land in ascending order and another stack in flight may have taken 1.28.0 in the meantime.

What this stack covers, and what it does not

Everything in #1489 is carried except its unrelated hunks. #1489 was branched off the unmerged #1033 sandbox-queue work, so its CHANGELOG.md, docs/configuration.md, sdk/contract/contract.json, sdk/contract/omissions.json and sdk/typescript/src/generated/openapi.ts diffs were largely that feature, not OAuth. None of it is carried here.

Two things were fixed on the way, both named in the PRs that fix them: #1489 declared /api/oauth/clients in neither an SDK manifest nor omissions.json (#1882), and its Go file imported the pre-move module path (#1884).

🤖 Generated with Claude Code

https://claude.ai/code/session_01S9jevFQT5MkF3rJUieeiHW

Closes #1125

@jhgaylor

Copy link
Copy Markdown
Collaborator Author

⚠️ Updated: this is now a three-way SDK version collision.

All three of these claim 1.28.0, against a main (and npm) at 1.27.0:

PR stack branch
#1860 detached permission requests (#1635) stack/1635-9-docs
#1876 bounded sandbox queue (#1033) stack/1033-7-docs
#1885 self-service OAuth clients (#1125) stack/1125-9-docs

Each is individually correct and all three release gates are green, because the gate compares against the PR's base, not main. Only the first to merge can keep the number.

Merging any one of these obliges re-numbering the other two before they merge1.29.0 and 1.30.0 in whatever order they land. Four edits each: sdk/typescript/package.json, sdk/typescript/package-lock.json (two places), USER_AGENT in sdk/typescript/src/http.ts, and the CHANGELOG.md heading. Bumps must land in ascending order, so this cannot be corrected after the fact.

A fourth stack (#1565, conversation reapply) is still being cut and will want a number too.

Given that, it is probably worth picking the merge order for all four now and assigning 1.28.01.31.0 up front, rather than resolving this one gate at a time. Each of these stacks has already been re-numbered once or twice mid-flight for exactly this reason (1.26.0 went to #1634, then 1.27.0 to #1637/#1849).

@jhgaylor

Copy link
Copy Markdown
Collaborator Author

⚠️ Updated again: four stacks now claim 1.28.0. main and npm are both at 1.27.0.

PR stack branch
#1860 detached permission requests (#1635) stack/1635-9-docs
#1876 bounded sandbox queue (#1033) stack/1033-7-docs
#1885 self-service OAuth clients (#1125) stack/1125-9-docs
#1893 conversation reapply (#1565) stack/1565-8-docs-sdks

All four are individually correct and all four release gates are green, because the gate compares against each PR's base, not main. Only the first to merge keeps the number, and bumps have to land in ascending order — so this cannot be corrected after the fact.

Recommendation: take the version bump out of all four, and do one SDK release afterwards.

Assigning 1.28.01.31.0 up front works only if the four stacks then merge in exactly that order, and each of these has already been re-numbered once or twice mid-flight precisely because merge order kept changing (1.26.0 went to #1634, then 1.27.0 to #1637/#1849). Pinning an order now just sets the trap again.

Instead:

  1. Label all four final PRs sdk-no-release and drop the four-file version bump from each, keeping their generated openapi.ts changes.
  2. Land the stacks in whatever order suits.
  3. Open one SDK release PR bumping 1.27.01.28.0 once, with a changelog entry covering all four features.

That removes the ordering constraint entirely, gives users one coherent release note instead of four near-simultaneous minors, and means no stack can silently publish nothing by merging second.

The cost is that the SDK types for whichever features land first sit unreleased on main until that final PR merges. That is exactly what sdk-no-release exists to express, and it is a far smaller risk than a bump that merges green and publishes nothing.

@BinaryBourbon BinaryBourbon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ADR amendment is the right shape: 0021 is amended rather than superseded, the two consequences that changed are marked in place with pointers to the amendment, and the amendment is appended rather than rewriting the original — so a reader who arrives at the 2026-08 decision still sees what was decided then and why it moved. verified and stale_after are refreshed and decisions/index.md is regenerated in the same PR, which is what okf validate wants.

"The wrong answer, on the record" is the most valuable paragraph in the stack. Wildcarding the sandbox domain is the answer a future contributor will reach for, "PKCE does not help when the attacker initiates the flow" is the sentence that stops them, and it is now written somewhere they will look. The "Still not done" list is honest — per-scope consent, secrets, refresh rotation, and publishing being SQL until someone needs more — which matters given this repo's own rule that an ADR must not describe unbuilt behaviour as existing.

The SDK release is a complete four-edit bump — package.json, package-lock.json, USER_AGENT in http.ts, and CHANGELOG.md — and it sits at the tip of the stack, which is where a version bump belongs so it does not race another bump on main. The changelog entry explains why the hand-written layer does not model these endpoints rather than just listing the types, which matches the reason in omissions.json.

docs/api.md reads as Simplified Technical English throughout ("One account registers a maximum of 25 apps", "A bearer key is the one credential that crosses an origin") without the usual fight. The build-fountain-app skill description dropping OAUTH_CLIENTS/API_CORS_ORIGINS for "self-service OAuth client registration" is correct now — that skill was telling people to go find an operator.

One consequence of this PR being where the bump lives: #1882 goes red on A change to the SDK says whether it releases, because it changes sdk/typescript/src/generated/openapi.ts against a base still at 1.27.0. That is the gate behaving correctly and the fix belongs there (the sdk-no-release label), not here — noted so the two are read together.

Approving.

@jhgaylor

Copy link
Copy Markdown
Collaborator Author

Review feedback applied; force-pushed (amended commit).

"Still not done" now records that there is no operator switch that turns self-registration off — any verified account on any deployment may register — and that this is deliberate rather than an oversight, since the CORS consequence admits nobody who does not already hold a bearer key. If a self-hoster ever asks for one, that is a new flag rather than a change of mind here.

Frontmatter is untouched, so decisions/index.md needs no refresh.

@BinaryBourbon BinaryBourbon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Still not done" section gained the paragraph I asked for on #1877, and it answers the question rather than deferring it.

There is no operator switch that turns self-registration off. Any verified account on any deployment may register, which is deliberate: it is the whole point of the amendment, and the CORS consequence admits nobody who does not already hold a bearer key. A self-hoster who wants the old behaviour has no setting to reach for, so if one is ever asked for, it is a new flag rather than a change of mind here.

Three things it gets right. It is bold-led, so it reads as a decision rather than as an omission in a list of omissions. It carries its own justification (the Access-Control-Allow-Credentials argument, in one clause) so a reader who arrives here from a self-hosting question does not have to go to #1879's moduledoc to find out whether it is safe. And the last sentence pre-registers the answer: a future OAUTH_CLIENT_REGISTRATION=false is additive and does not reopen this decision — which is the sentence that stops a "we should never have done this" PR six months out.

Placing it inside "Still not done" rather than in its own section is arguable — it is not a thing that is not done, it is a thing deliberately not built. But the section already holds "Publishing is SQL or a mix task until somebody needs more", which is the same shape, so it is consistent with its neighbours.

okf validate is green and decisions/index.md needs no refresh, since the status block did not move — the amendment is prose inside an already-amended ADR.

The 1.28.0 bump and the four edits under it are unchanged, and the sdk-no-release label on #1882 means this is still the only PR in the stack that releases.

Approving. This is the last of the nine; the whole stack is approved.

…1125)

The last part of the stack: the record of the decision, the manual, the app
skill and the SDK version.

ADR 0021's consequence said a third-party clients table would come "when a
third party asks". The amendment says what the ask turned out to be, and
writes down the wrong answer -- wildcard the sandbox domain -- so nobody
re-proposes it. It marks the two consequences it changes rather than
rewriting them, and its frontmatter is re-verified; `decisions/index.md` is
regenerated by `scripts/decisions-index.sh`.

`docs/api.md` gains the registration endpoints, the development-mode rule and
the twenty-five ceiling. `docs/sdk.md` and `docs/build/team-chat.md` stop
telling a browser app that `API_CORS_ORIGINS` is its only way in. The
build-fountain-app skill loses the "ask the operator, open an issue" path and
gains the one command that replaces it.

**SDK 1.28.0.** The wire types were regenerated in part 6 of this stack
without a bump; this carries the version across `package.json`, the lockfile,
`USER_AGENT` and the SDK changelog. `main` was at 1.27.0 when this was
written -- **re-check it immediately before merging**, because concurrent
bumps must land in ascending order and another stack may have taken 1.28.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S9jevFQT5MkF3rJUieeiHW
@jhgaylor
jhgaylor changed the base branch from stack/1125-8-cli to main September 11, 2026 11:56
@jhgaylor
jhgaylor added this pull request to the merge queue Sep 11, 2026
Merged via the queue into main with commit 18d6d08 Sep 11, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OAuth apps people can register themselves: tenant-owned clients in dev mode, CORS from the registry

2 participants