Repository navigation
Conversation
…ay do, where it goes The consent screen names a self-registered app by where its access goes, its own name quoted beside it, warns that Fizzy hasn't checked it, explains each access level in plain words, says who is signed in and where the browser goes next. An account picker partial is ready for account binding. Errors shown on Fizzy say what to do next. Connected apps groups apps by kind (web, on your devices, Fizzy's own), with access, when connected and last active, and an empty state.
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ca5c1ba0d3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A self-registered client may list a loopback callback first and an https one later, and its grant may have come through either, so the first callback doesn't speak for the app.
|
Review summary for head 56bd25c:
|
…t is Switching signs out and brings whoever signs in next back to the same authorization request, rebuilt from parameters that passed the consent screen's checks rather than taken as a URL. Connected apps says when an app last renewed its access, which is what the timestamp records.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0cc090101c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…y when the request can be resumed An authorization request naming no known client has nowhere to send the browser back to, so it gets the error page rather than raw JSON. Not you? refuses a request too long to keep in the session before signing anyone out, since there would be nothing to return to.
|
Status for head cc77884:
|
|
@codex review |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
* origin/oauth-token-digests: Refuse an OAuth parameter that arrives as a list where one value is meant
* origin/oauth-token-digests: (48 commits) Bring main's tests up to this branch: Ruby 4, webhook attribution, token digests Pin the fizzy_mcp accessory to fizzy-mcp-server v0.1.0 by digest Scope webhook dispatch by account as well as board Test the reviewer audit against the structured log line production writes Revoke on the email alone, and record each use in the request's structured log Remove the reviewer's access tokens and passkeys on sign-out, so a code holder can't keep a way back in Wire the reviewer sign-in into production from Deploy/Fizzy Close the reviewer's live sockets on sign-out, and keep the identity id out of Sentry End the reviewer's sessions on rotation, so the old code's sessions don't outlive it Refuse a code that normalizes to nothing, not just a blank one Let the directory reviewer sign in with a fixed code, SaaS only and off unless configured Refuse docker-dev's shared default port in a git worktree Ruby 4.0.9 (#3234) Retry the offline clear only in an active worker Retry clearing old offline pages whenever the worker starts Clear offline pages rendered under an older rendering version Re-key every fragment and page ETag past crass 1.0.7 Bump crass to 1.0.8 in Gemfile.saas.lock, and test rich text style scrubbing Bump crass to 1.0.8 for GHSA-pq4g-8rxf-4g29 story accepted ...
* origin/oauth-token-digests: Filter the code parameter by its whole name, so code_challenge stays readable
* origin/oauth-token-digests: Redact retired refresh tokens from logged SQL
… lowercase Read's description names the people in every account the person belongs to, or in the one account an audienced grant is bound to, matching the reach line beside it. A redirect's host is shown in lowercase, as a browser reads it.
… DCR allowlist B's account-picker test asserted its plain select; #3212 renders radio cards. CIMD's unknown-client tests read a JSON error; #3212 shows the error page. DCR's app-scheme test looked for the old consent line; #3212 says the app on your device. #3212's connected-apps test registered two https hosts that #3229 now vets.
|
@codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
Ruling (Jeremy, 2026-10-24): the read copy doesn't mention email addresses, as on bc3#14090. This PR's copy already leaves them out, so it stays as it is. The "name set by" wording is still open and unchanged here. |
…ping partway * origin/oauth-token-digests: Make this branch's migrations safe to run again after stopping partway Make this branch's migrations safe to run again after stopping partway Make the OAuth migrations safe to run again after stopping partway
* origin/oauth-token-digests: Answer 404 from a dark endpoint however many times it's asked
…ked it The name line reads Says it's "<name>": a registered name is whatever the registrant typed, so it is presented only as the app's own claim. The warning leads with "We haven't checked this app." in our voice, and a web app's heading names where its access goes: Authorize the app at <host>. Same wording as bc3's consent.
|
@codex review |
|
@codex review |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 07a7519ccd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 07a7519ccd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
* origin/oauth-dcr-allowlist: Record a metadata document's registration as the client's own, find a revoking client by exact id, and read a quoted max-age Judge an exchange by the client row it locked, and look only for a delegated token's digest on the primary Deliver an app's push in an account only through a grant that reaches that account, and drop a duplicate render_error
…nt names in Connected apps' reach
|
🤖 @codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
* origin/oauth-dcr-allowlist: Count a successful delegation exchange as a token grant, and run its sweep as a named cleanup step Refuse a whitespace resource indicator, and let an account-bound grant refresh only while its account is the person's
|
🤖 @codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
* origin/oauth-dcr-allowlist: Answer a denial with access_denied whatever the stored row's scopes, and refund the fetch budget when admission is lost
|
🤖 @codex review |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
…s loopback apps as on this device
|
🤖 @codex review |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |

Held draft for Jeremy. Don't merge. This is the consent and Connected apps design pass (hosted plan, Decision 8). Production acceptance waits on it. It's stacked on #3192.
It's modelled on bc3's consent page and Connected apps (
oauth/authorizations/consent,oauth/_client_self_namefrom bc3#13580, grouping by kind from bc3#13579), in Fizzy's own pieces:panel,btn,divider, the dialog controller andlocal_datetime_tag. The only new stylesheet isoauth.css.Consent screen
Who's asking. A self-registered app goes by where its access goes, not by the name it gave itself. That's the callback's host, with the port if it isn't the default, or "an app on your device" for a loopback or app-scheme callback. The heading reads "Authorize the app at connector.example.com". Its own name is only its claim, shown subdued under that: "Says it’s “Totally Fizzy Assistant”". A trusted app is known by its name and gets "Made by 37signals". An operator-registered app is known by its name alone.
Warning. Self-registered apps get "We haven’t checked this app. Anyone can run an app at any address, so only authorize it if you trust ." Device apps get "We haven’t checked this app. It runs on your device and will get this access, so only authorize it if you started it." Same wording as bc3#14089, as Jeremy ruled.
Name safety. Bidirectional control characters are stripped from a self-registered name, and
bdiisolates it, so a right-to-left name can't move the quotes or the host.Access. The select is replaced by two radio cards:
A read-only client gets the single card. A line under the cards says the app reaches only what you can, in every account you belong to (or "in the account above" once account binding lands).
Identity. "Signed in as ", with a Not you? button. It's a CSRF-protected POST to
oauth/authorization/switch, which re-runs every check the consent screen ran, rebuilds the authorize URL from those parameters (never from a URL in the request), signs out, and saves that URL so whoever signs in next returns to consent for the same request. The saved URL is used once. The account choice isn't carried over, since it belonged to the identity that signed out.Destination. "Either way, you'll go back to ", with a link to Connected apps.
Buttons keep the names Authorize and Deny, so the system test and muscle memory hold.
Account picker.
oauth/authorizations/_account_picker(localsform,accounts,selected_account_id) renders when the controller sets@accounts. The account-binding lane owns the controller and theaccount_idparam, and this partial is its markup. With one account it names it and carries it in a hidden field; with several it shows radio cards.Errors shown on Fizzy
This is the page shown when a request can't be redirected back safely, for example an unknown client or a redirect that doesn't match. It says "Can't authorize this app", the reason, "Nothing was shared. Close this window and start again from the app. If it keeps happening, let whoever made the app know", and the error code. The old "Go back" link to the referer is gone: it could point at the requesting site.
Connected apps
Grouped by what the app is.
Oauth::Client#connection_kinddecides it by how the app is registered, never by its name:Empty groups don't show.
Each app shows:
Access last renewed is the newest token's
updated_at, which moves each time the app renews its access. (Renamed from "last active" per Jeremy; it reads fine in the layout, so it stays.)Disconnect keeps the existing dialog, including the webhooks it set up. It's now a labelled button rather than a bare trash icon, and its wording is "It loses its access to Fizzy right away."
Empty state: "Nothing connected yet." with a line on what shows up here.
Screenshots
Dark theme, from a system-test browser with fixtures. Desktop is 1200 px wide, mobile 390 px. Before is #3192's head
617edb87b.The images live on the
pr-assets/oauth-consent-designbranch, pinned to its commit.Rulings applied
Jeremy kept the group names, the host as heading, and the read copy naming people. "Last active" is now "access last renewed". "Not you?" is added (above).
After the rulings (head 0cc0901)
Tests
test/integration/oauth_consent_screen_test.rb(identity line, warnings, bidi stripping, access levels, signed-in email, the error page),test/helpers/oauth_helper_test.rb(identity, access levels, grouping, both shapes of the account picker),Oauth::Client#connection_kindin the model tests, and Connected apps grouping and empty state.test/integration/oauth_authorization_switch_test.rbcovers the button on consent, same-origin (CSRF) required, a forgedreturn_toignored, an unregistered redirect or unknown client refused with the person still signed in and nothing saved, and a full round trip that lands the next identity back on consent and uses the saved URL once.oauth_flow_test.rb's scope assertions now look for radios instead of a select.