Skip to content

Add connection links via a dedicated #/connect route - #1828

Draft
kmcginnes wants to merge 31 commits into
aws:mainfrom
kmcginnes:url-connection-params
Draft

kmcginnes wants to merge 31 commits into
aws:mainfrom
kmcginnes:url-connection-params

Conversation

@kmcginnes

@kmcginnes kmcginnes commented Jun 16, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Other apps can now send a user into Graph Explorer already pointed at their database with a link like this:

https://<graph-explorer-host>/#/connect?graphDbUrl=https%3A%2F%2Fmy-cluster.us-east-1.neptune.amazonaws.com%3A8182&queryEngine=gremlin&awsRegion=us-east-1&serviceType=neptune-db&name=My%20Database
  • A #/connect route handles the link. The params sit after the # like every other route, so integrators build it the same way as any in-app link. The route always redirects with replace, so #/connect never lingers in history.
  • The link resolves once into one of four intents.
    • none: it matches the active connection, so nothing changes.
    • activate: it matches another connection, so Graph Explorer switches to it silently, the same as clicking it in the connections list.
    • create: nothing matches, so a prefilled form opens and the user has to save it.
    • invalid: a param failed validation, so a toast names each bad param and the link is ignored.
  • The create form is the trust gate. It's the only path that can add a database, so it's fully editable and nothing is saved until the user clicks Add Connection. It renders in the page rather than over a blank one, and outside clicks don't dismiss it. Saving lands on the graph view. Cancel or Escape lands on the connections list.
  • Matching treats auth posture as identity. A connection matches when graphDbUrl (normalized, case-insensitive), queryEngine, and IAM on/off plus region and service type all agree. A link asking for IAM never reuses a plaintext connection to the same endpoint. When several match, the active one wins, then the one named by name, then the first. A nameless link uses the hostname as its name.
  • Bad values are rejected, not coerced. Silently swapping in a default would connect with settings the link never asked for. A link is invalid when:
    • graphDbUrl is missing, isn't http(s), carries a username or password, or contains a backslash (which parses as a slash, so a link could show one host and connect to another)
    • queryEngine or serviceType is unsupported
    • awsRegion isn't shaped like a region
    • queryEngine is anything but openCypher for Neptune Analytics, which defaults to openCypher since that's all it runs
  • Resolution waits for default connections. AppStatusLoader gates the route until they load, so a link matching a default connection activates it instead of prompting for a duplicate. A test pins that ordering.
  • Connections from a link always go through the proxy. The proxy URL comes from document.baseURI, so path-hosted deployments such as Neptune notebooks work.

Shared pieces this needed:

  • DialogSurface is pulled out of DialogContent so the connect route can render the same panel without the portal.
  • CreateConnection.onClose now receives "saved" or "cancelled", so the route can pick the landing page.
  • ConnectionLinkError gives createDisplayError one problem per offending param.

The ADR is docs/adr/20260612-connection-links.md, and the user docs are under Connection Links in docs/features/connections.md.

Follow-ups tracked separately:

Validation

I tried every flow in the browser against a local Gremlin Server with air routes:

  • create, then save and query
  • cancel and Escape
  • silently switching back on reopen
  • an IAM link falling through to the create form
  • each kind of invalid link
  • an empty name falling back to the hostname

history.back() skips #/connect.

To try it, open #/connect?graphDbUrl=http%3A%2F%2Flocalhost%3A8182&queryEngine=gremlin&name=Air%20Routes against a local database, then open the same link again after switching connections.

Related Issues

Closes Activate or create a connection via URL parameters.

This should merge after Unify Docker image by removing SageMaker variant. That PR removes the connection's proxy url and proxyConnection. After it lands I'll rebase and delete deriveProxyBaseUrl, and matching on graphDbUrl then always compares the endpoint that is actually queried.

Check List

  • I confirm that my contribution is made under the terms of the Apache 2.0 license.
  • I have verified pnpm checks passes with no errors.
  • I have verified pnpm test passes with no failures.
  • I have covered new added functionality with unit tests if necessary.
  • I have updated documentation if necessary.

@kmcginnes kmcginnes mentioned this pull request Jun 16, 2026
5 tasks
@kmcginnes
kmcginnes force-pushed the url-connection-params branch 2 times, most recently from fb3eafb to 72d2c25 Compare June 16, 2026 21:05
@kmcginnes
kmcginnes force-pushed the url-connection-params branch 2 times, most recently from 2edc240 to 7202e99 Compare June 30, 2026 17:53
@kmcginnes
kmcginnes force-pushed the url-connection-params branch from 7202e99 to 66514f0 Compare September 9, 2026 19:22

return {
...parsed.data,
name: parsed.data.name ?? deriveNameFromUrl(graphDbUrl),

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.

Implementation question

When the link does not include a name, this code generates one from the hostname. That generated name is later also used to choose between multiple matching connections.

Could we keep the URL-provided name optional for matching, and only derive a name when the user needs to create a new connection? This would ensure a generated display name does not accidentally influence which existing connection is selected.

A test with two connections pointing to the same database, no name in the link, and one connection named after the hostname would help confirm the expected behavior.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Deliberate, though the rationale wasn't written down anywhere — fixed now.

The derived name is the link's identity, not just a display fallback: a nameless link identifies the connection it would have created, and what it would have created is named after the hostname. So if you open a nameless link (creating a connection named my-cluster.example.com), then later add a second connection to the same endpoint under a name of your own, reopening that original link returns to the original connection rather than picking arbitrarily.

Dropping the name from matching would fall through to matches[0], i.e. Map insertion order — which happens to give the right answer in that scenario only by accident.

I added the test you suggested (a nameless link prefers the connection its own derived name created), with the hand-named connection placed first in the map so a first-match fallthrough fails it, and recorded the reasoning on deriveNameFromUrl.

return (
<Routes>
<Route element={<DefaultLayout />}>
<Route path="/connect" element={<Connect />} />

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.

Spec/design decision, not an implementation defect

This dedicated #/connect?... route differs from #1788, which currently documents top-level search parameters while preserving the hash as the requested landing page. The route-based contract is coherent, but it changes the external URL API.

Can we confirm this intentionally supersedes the issue contract and update #1788 so integrators have one authoritative link format?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed it diverged from the spec. I kept the dedicated route and updated Activate or create a connection via URL parameters to match. Putting the params after the # means integrators build the link like any other in-app route, and nothing in the app shell has to read window.location.search or strip params.

} from "@/modules/CreateConnection";
import { logger } from "@/utils";

const GRAPH_CANVAS_ROUTE = "/graph-explorer";

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.

Spec/design decision, not an implementation defect

Every outcome is hard-coded to /graph-explorer. In #1788, the caller can choose the landing page, and cancelling should strip the parameters while leaving the user on the requested/current page. With the dedicated route, that destination is no longer represented.

Is always landing on the graph canvas the intended replacement behavior? If so, the affected user stories should be updated explicitly. Otherwise, the connect route needs a validated return destination.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Choosing the landing page is split out into Let a connection link choose which page the user lands on. For now, saving and invalid links land on the graph view and cancelling lands on the connections list, so a declined link leaves you where you can pick a connection yourself.

"Activating matching connection from URL params",
connectionIdToActivate,
);
activateConnection(connectionIdToActivate);

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.

Spec/design decision, not an implementation defect

This silently switches to an existing matching connection. That aligns with the PR rationale and normal connection-list behavior, but #1788 also says switching to a different connection should be confirmed before its Session is reset.

Can we confirm silent activation is the final product decision and update the issue accordingly? The current implementation looks internally consistent once that contract is settled.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Confirmed as the final product decision. Two reasons, both now recorded in the ADR:

First, there is no session to lose. Sessions are stored per connection (allGraphSessionsAtom, keyed by connection id) and useResetState only clears the in-memory view atoms — it never touches allGraphSessionsAtom. So switching swaps which session is displayed rather than destroying the previous one: return to that connection and it restores.

Second, a link cannot change an already-open window's state. Following one opens a new tab, or the user pastes it deliberately. Either way the intent to start somewhere new is explicit.

Together that makes this identical to clicking a connection in the connections list, which has never prompted. The create path keeps its friction, since it is the only one that can introduce a new database.

Worth noting the issue contradicts itself here, which is probably what prompted the question: #1788's Modules section item 3 says "prompts to switch (resetting the Session on confirm)", while that same issue's Implementation Decisions say activation is "identical to a manual connection switch". The implementation follows the latter, and I'm correcting the issue text.

// crafted link from seeding the form with something like `javascript:` —
// defense in depth on top of the editable create form and proxy allowlist.
graphDbUrl: z.url({ protocol: /^https?$/ }),
queryEngine: z.enum(queryEngineOptions).catch("gremlin"),

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.

Could we default queryEngine and serviceType only when they are absent, and reject explicitly invalid values? With .catch(), queryEngine=sql silently becomes Gremlin, while an invalid serviceType can later become neptune-db when a region is present. The resulting connection may differ from what the caller requested instead of following the existing invalid-link path.

Using optional schemas with defaults for missing values would preserve the convenience while allowing malformed explicit values to produce the invalid intent. The current coercion tests should then become rejection tests.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done. .catch() is gone. An absent queryEngine still defaults, but an explicit unsupported value for either param now rejects the link, and the toast names the param.

continue.
</DialogDescription>
</DialogHeader>
<DialogBody>

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.

Dialog composition

CreateConnection already renders its own DialogBody and DialogFooter, so this outer DialogBody nests two body containers and places the footer inside the outer scrolling region. That can duplicate spacing and make the actions scroll with the form instead of remaining in the dialog footer position.

Could we render CreateConnection directly after the header, or extract form content so one component clearly owns the body and footer?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed. CreateConnection owns its body and footer. The connect route also renders the form in the page with DialogSurface now, instead of a modal over a blank page.

// Only http(s) endpoints are meaningful, and constraining the scheme keeps a
// crafted link from seeding the form with something like `javascript:` —
// defense in depth on top of the editable create form and proxy allowlist.
graphDbUrl: z.url({ protocol: /^https?$/ }),

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.

Security hardening

This accepts HTTP(S) URLs containing embedded credentials, such as https://user:password@host. Because the value comes from an external link and can be persisted as the database endpoint after confirmation, credentials could end up stored and forwarded as part of the URL.

Could the schema reject URLs whose parsed username or password is non-empty? That also avoids userinfo being used to make an unintended host look trustworthy at a glance.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed. A graphDbUrl with a username or password is rejected. I also reject backslashes, since https://evil.tld\@prod.neptune.amazonaws.com parses to evil.tld while the form shows a Neptune host.

Comment thread docs/references/security.md Outdated

> [!NOTE]
>
> [Connection links](../features/connections.md#connection-links) never connect to a new database without your confirmation: a link whose details do not match an existing connection only pre-fills the create form for you to review. A link may switch to a connection you already created, but it cannot create one on your behalf. And in every case the proxy still rejects forwarding to any origin outside `PROXY_SERVER_ALLOWED_DB_ORIGINS`, so a crafted link cannot reach an arbitrary database.

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.

Security documentation

This guarantee is broader than the current behavior. The allowlist permits any origin when PROXY_SERVER_ALLOWED_DB_ORIGINS is unset, and matching does not require an existing connection to be proxy-backed. A matching direct connection can therefore activate without proxy allowlist enforcement.

Could we either enforce proxy-backed matching for connection links, or qualify this note to say the allowlist applies only when configured and only to requests routed through the proxy?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed, that overstated it. I dropped the note from security.md, and the ADR now says the allowlist only bounds a link when PROXY_SERVER_ALLOWED_DB_ORIGINS is set.

Comment thread docs/features/connections.md Outdated
- **The link matches your active connection** — nothing changes.
- **The link matches a different existing connection** — Graph Explorer switches to it, the same as selecting it in the connections list. No prompt: the connection was already created and validated by you, so there is nothing new to confirm.
- **The link matches no existing connection** — the create-connection form opens, pre-filled with the link's details so you can review or edit any setting before creating it.
- **The link's details are invalid** (for example, a `graphDbUrl` that is not a valid `http`/`https` URL) — the link is ignored and a notification explains what went wrong.

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.

Documentation accuracy

The notification currently reports a generic invalid-link message rather than explaining which value or rule failed. The creation flow also has two outcomes worth stating explicitly: saving creates the connection, while closing or cancelling creates nothing; both then navigate to the graph view.

Could we describe the error as generic and document those two dialog outcomes, or enhance the UI if specific validation feedback is intended?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed both. The toast now names each bad param and what it requires, for example "graphDbUrl must be a valid http or https URL", and the docs cover the save and cancel outcomes separately.

Comment thread docs/adr/20260612-connection-links.md Outdated
shell.

Connection links are now a first-class route, `#/connect?graphDbUrl=…`. The
route resolves the params once on entry and redirects (router `navigate`, with

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.

Architecture documentation

The implementation does not snapshot the intent once on entry. useUrlConnectionIntent() reads live Jotai state and resolves again on each render, including while the creation dialog is open.

Could we describe this as reactive resolution, or snapshot the initial intent if one-shot processing is an architectural invariant? CONTEXT.md uses the same “resolved once” wording and should stay aligned.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in the code, not just the doc. The route now resolves the link once in a useState initializer and acts on that. The AppStatusLoader gate makes that safe, and a test pins the ordering.

@mjuarros

Copy link
Copy Markdown
Contributor

Manual testing found that the invalid-link warning is not visible.

Reproduction:

  1. Open /#/connect?graphDbUrl=not-a-url.
  2. The app redirects to the graph explorer and does not open the create form, as expected.
  3. No Invalid connection link toast is displayed.

The PR contract specifies invalid as “warn with a toast and ignore,” and Connect.tsx calls toast.error(...), so the redirect behavior is correct but the user-facing warning appears to be missing. The current route test verifies the mocked toast.error call, but does not mount the real Toaster or assert that the notification is rendered and remains visible after navigation.

kmcginnes added a commit that referenced this pull request Sep 24, 2026
## Description

- `TestProvider` now always renders a `MemoryRouter` and takes
`initialEntries`, and `renderHookWithState` passes it through. Anything
that reads the location works without each test wiring its own router.
- Moved `DataExplorer.test.tsx` onto it. It was hand-rolling the query
client, jotai, and router providers that `TestProvider` already covers.
- Dropped the inner `MemoryRouter` in
`SchemaDiscoveryBoundary.integration.test.tsx`. Nesting a second router
inside `TestProvider` now throws.

I split this out of [Add connection links via a dedicated #/connect
route](#1828), whose route
tests use it, so that PR only carries the feature.

## Validation

Test-only change. The full suite passes.

## Related Issues

Prep for [Add connection links via a dedicated #/connect
route](#1828).

### Check List

- [x] I confirm that my contribution is made under the terms of the
Apache 2.0 license.
- [x] I have verified `pnpm checks` passes with no errors.
- [x] I have verified `pnpm test` passes with no failures.
- [x] I have covered new added functionality with unit tests if
necessary.
- [ ] I have updated documentation if necessary.
kmcginnes added a commit that referenced this pull request Sep 24, 2026
## Description

- Pulled the "switch to this connection" logic out of `ConnectionRow`
into a `useActivateConnection` hook, with its own tests. No behavior
change.

The connect route in [Add connection links via a dedicated #/connect
route](#1828) activates a
matching connection the same way the connections list does. Sharing one
hook keeps the two from drifting, and splitting it out keeps the
refactor from hiding inside a feature diff.

## Validation

Clicking a connection in the connections list should still activate it
and reset the graph view, exactly as before.

## Related Issues

Prep for [Add connection links via a dedicated #/connect
route](#1828).

### Check List

- [x] I confirm that my contribution is made under the terms of the
Apache 2.0 license.
- [x] I have verified `pnpm checks` passes with no errors.
- [x] I have verified `pnpm test` passes with no failures.
- [x] I have covered new added functionality with unit tests if
necessary.
- [ ] I have updated documentation if necessary.
@kmcginnes
kmcginnes force-pushed the url-connection-params branch from 66514f0 to 9301e02 Compare September 24, 2026 22:36
kmcginnes added a commit to kmcginnes/graph-explorer that referenced this pull request Sep 24, 2026
## Description

- `TestProvider` now always renders a `MemoryRouter` and takes
`initialEntries`, and `renderHookWithState` passes it through. Anything
that reads the location works without each test wiring its own router.
- Moved `DataExplorer.test.tsx` onto it. It was hand-rolling the query
client, jotai, and router providers that `TestProvider` already covers.
- Dropped the inner `MemoryRouter` in
`SchemaDiscoveryBoundary.integration.test.tsx`. Nesting a second router
inside `TestProvider` now throws.

I split this out of [Add connection links via a dedicated #/connect
route](aws#1828), whose route
tests use it, so that PR only carries the feature.

## Validation

Test-only change. The full suite passes.

## Related Issues

Prep for [Add connection links via a dedicated #/connect
route](aws#1828).

### Check List

- [x] I confirm that my contribution is made under the terms of the
Apache 2.0 license.
- [x] I have verified `pnpm checks` passes with no errors.
- [x] I have verified `pnpm test` passes with no failures.
- [x] I have covered new added functionality with unit tests if
necessary.
- [ ] I have updated documentation if necessary.
kmcginnes added a commit to kmcginnes/graph-explorer that referenced this pull request Sep 24, 2026
## Description

- `TestProvider` now always renders a `MemoryRouter` and takes
`initialEntries`, and `renderHookWithState` passes it through. Anything
that reads the location works without each test wiring its own router.
- Moved `DataExplorer.test.tsx` onto it. It was hand-rolling the query
client, jotai, and router providers that `TestProvider` already covers.
- Dropped the inner `MemoryRouter` in
`SchemaDiscoveryBoundary.integration.test.tsx`. Nesting a second router
inside `TestProvider` now throws.

I split this out of [Add connection links via a dedicated #/connect
route](aws#1828), whose route
tests use it, so that PR only carries the feature.

## Validation

Test-only change. The full suite passes.

## Related Issues

Prep for [Add connection links via a dedicated #/connect
route](aws#1828).

### Check List

- [x] I confirm that my contribution is made under the terms of the
Apache 2.0 license.
- [x] I have verified `pnpm checks` passes with no errors.
- [x] I have verified `pnpm test` passes with no failures.
- [x] I have covered new added functionality with unit tests if
necessary.
- [ ] I have updated documentation if necessary.
@kmcginnes
kmcginnes force-pushed the url-connection-params branch from 9301e02 to f6f255c Compare September 24, 2026 22:46
kmcginnes added a commit that referenced this pull request Sep 24, 2026
## Description

- `CreateConnection` takes an `initialValues` prop. It prefills a new
connection form and stays in add mode, so none of the edit-mode
"meaningful change" reset logic runs.
- `mapToConnectionForm` now takes a name and a connection body instead
of a whole stored configuration, so it can map a connection that hasn't
been saved and has no id. The edit form still falls back to the id when
a connection has no label, which matches how the rest of the app names
it.

Nothing on main passes `initialValues` yet. The connect route in [Add
connection links via a dedicated #/connect
route](#1828) will use it to
prefill the form from a link. I split this out so the form change gets
reviewed separately from the feature.

## Validation

The add and edit connection dialogs behave as before. New tests cover
the prefill, the mapping, and editing a connection that has no label.

## Related Issues

Prep for [Add connection links via a dedicated #/connect
route](#1828).

### Check List

- [x] I confirm that my contribution is made under the terms of the
Apache 2.0 license.
- [x] I have verified `pnpm checks` passes with no errors.
- [x] I have verified `pnpm test` passes with no failures.
- [x] I have covered new added functionality with unit tests if
necessary.
- [ ] I have updated documentation if necessary.
kmcginnes added a commit to kmcginnes/graph-explorer that referenced this pull request Sep 24, 2026
- `TestProvider` now always renders a `MemoryRouter` and takes
`initialEntries`, and `renderHookWithState` passes it through. Anything
that reads the location works without each test wiring its own router.
- Moved `DataExplorer.test.tsx` onto it. It was hand-rolling the query
client, jotai, and router providers that `TestProvider` already covers.
- Dropped the inner `MemoryRouter` in
`SchemaDiscoveryBoundary.integration.test.tsx`. Nesting a second router
inside `TestProvider` now throws.

I split this out of [Add connection links via a dedicated #/connect
route](aws#1828), whose route
tests use it, so that PR only carries the feature.

Test-only change. The full suite passes.

Prep for [Add connection links via a dedicated #/connect
route](aws#1828).

- [x] I confirm that my contribution is made under the terms of the
Apache 2.0 license.
- [x] I have verified `pnpm checks` passes with no errors.
- [x] I have verified `pnpm test` passes with no failures.
- [x] I have covered new added functionality with unit tests if
necessary.
- [ ] I have updated documentation if necessary.
@kmcginnes
kmcginnes force-pushed the url-connection-params branch 2 times, most recently from 4e137a0 to 4163264 Compare September 25, 2026 19:58
External applications can deep-link into Graph Explorer with a connection
preconfigured: #/connect?graphDbUrl=...&queryEngine=...&awsRegion=...&serviceType=...&name=...

The route resolves the params against existing connections into one of four
intents and acts on it, then redirects to the graph canvas so the connect URL
never lingers in history:

- none — the params target the active connection; nothing to do.
- activate — the params match an existing connection; switch to it silently,
  the same no-prompt operation as clicking it in the connections list.
- create — no match; open the create form prefilled but fully editable. This
  is the trust gate for the untrusted endpoint details a link can carry, and
  the only path that can introduce a new database.
- invalid — the link's graphDbUrl failed validation; warn with a toast and
  ignore it.

Matching identity folds in auth posture (IAM on/off, and when on, region and
service type) alongside graphDbUrl and queryEngine, so a link requesting IAM
never silently reuses a plaintext connection to the same endpoint, or vice
versa — a mismatch falls through to the create form.

graphDbUrl is validated as an http(s) URL with zod; a malformed or non-http
link is ignored. The proxy base URL is derived from document.baseURI rather
than window.location.origin so a link produces a working proxy connection on
path-hosted deployments (e.g. a Neptune notebook at /proxy/9250/explorer/
resolves the proxy to /proxy/9250).

Contract core lives in core/urlConnectionParams.ts (parse/match/build/resolve)
and core/useUrlConnectionIntent.ts. Documented in the connections feature page,
the security reference, CONTEXT.md, and an ADR.
Cancelling a link now lands on the connections list instead of the graph view.
@kmcginnes
kmcginnes force-pushed the url-connection-params branch from 4163264 to dcae968 Compare September 25, 2026 21:52
@kmcginnes

Copy link
Copy Markdown
Collaborator Author

Thanks for catching this. sonner dropped toasts raised before the Toaster subscribed, and the connect route raises its toast on mount. sonner 2.0.8, which came in with Bump the minor-and-patch group, replays those early toasts, so it shows now. I checked /#/connect?graphDbUrl=not-a-url in the browser: the toast reads "graphDbUrl must be a valid http or https URL. The link was ignored, so nothing changed." and then it redirects.

This branch has not been deployed

No deployments
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.

Activate or create a connection via URL parameters

2 participants