Remote contract catalogs, first-run platform setup, and SDK session refresh hardening - #120
Open
juicycleff wants to merge 7 commits into
Open
juicycleff wants to merge 7 commits into
juicycleff wants to merge 7 commits into
Conversation
fetchClientConfig and getClientConfig built the request with
new URL("/v1/client-config", baseURL). A leading slash resolves against
the origin only, so an API mounted under a path prefix, the way a
gateway serves it at /identity/authsome, was asked at the gateway root.
Every page load got a 404 and an unhandled AuthClientError, and the
server helper handed the provider a null config.
Both now join the path onto the base, which is what the generated client
does for every other endpoint. Tests pin the prefixed URL on each.
…refresh The upstream manifest endpoint can now return a catalog of manifests, one per installed plugin. The extension fetches the catalog, validates and registers every entry, and still accepts the old single-manifest shape so an older upstream keeps working. Local registration now goes through RegisterContractContributor, so the embedded server and the remote path share one wiring. auth.setup accepts optional platform and environment blocks. They update the bootstrapped platform app and its default environment in place, after validating names, slugs, the logo URL, and metadata size. Setup never creates or removes environments, and a mutex serializes concurrent calls so two first-run requests cannot both pass the empty-deployment check. On the SDK side, the manager serializes refresh behind a Web Lock (with an in-process queue as the fallback) and always re-reads storage under that lock. A tab that wakes up holding a token another tab already spent adopts the saved replacement and skips the exchange. Rotated tokens hit storage before the profile request, so a failure there cannot lose them. A 401 on restore before the advertised expiry now triggers a refresh. Rejected credentials are cleared from storage so recovery cannot loop back from sign-in. Duplicate initialize calls, as React makes in strict mode, share one promise. Client config fetches in core and nextjs now go through the generated client so the X-Publishable-Key header rides along with the query key. Tests cover the setup handler end to end (platform, environment, owner role, session cookie, second-run denial), the catalog fetch and dispatch, and the session recovery paths.
…setup handler goimports ordering on three test files, http.NoBody for the catalog request, named results on validateSetupNameAndSlug, and the platform and environment update blocks in the setup handler move into two helpers so the inner err no longer shadows the one validateSetupInput returned. Behaviour is unchanged.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This lands the commits that were sitting on local main and never reached origin, plus the contract catalog and session refresh work on top of them.
What changes for you
The dashboard extension now fetches a manifest catalog from the upstream authsome, one manifest per installed plugin, and registers every entry as a remote contributor. An older upstream that still returns a single manifest keeps working. Local registration goes through RegisterContractContributor as well, so the embedded contract server and the remote path share one wiring. The notification, organization, and subscription billing plugins gain contract handlers and manifests along the way.
First-run setup grew two optional blocks. auth.setup-status returns safe platform and environment defaults for the form, and auth.setup accepts platform and environment objects that update the bootstrapped platform app and its default environment in place. Names, slugs, the logo URL, the environment type, and metadata size are validated before anything is written. A bad payload leaves the app, the environment, and the user table untouched, and a mutex serializes concurrent setup calls so two first-run requests cannot both pass the empty-deployment check.
On the SDK side, the client-config request keeps the base URL's path prefix. A gateway serving the API at /identity/authsome was being asked at the gateway root, so every page load 404ed. The request now goes through the generated client so the X-Publishable-Key header rides along with the query key. Session refresh is serialized behind a Web Lock, with an in-process queue as the fallback, and always re-reads storage under that lock. A tab that wakes up holding a token another tab already spent adopts the saved replacement. Rotated tokens hit storage before the profile request. A 401 on restore before the advertised expiry triggers a refresh, rejected credentials are cleared so recovery cannot loop back from sign-in, and duplicate initialize calls from React strict mode share one promise.
Forge moves to v1.11.1.
Testing
go build ./...,go vet, andgo teston extension and extension/contract pass locally, as does vitest in ui/packages/core and ui/packages/nextjs.