Repository navigation
Conversation
tnunamak
force-pushed
the
fix/connector-readiness-projection
branch
from
November 5, 2026 21:58
e4c7947 to
54f2e2f
Compare
tnunamak
changed the base branch from
main
to
fix/console-install-before-account-setup
November 5, 2026 21:58
tnunamak
force-pushed
the
fix/connector-readiness-projection
branch
2 times, most recently
from
November 6, 2026 13:20
16ba397 to
a269447
Compare
…a roster Whether the owner could add an account for a browser connector depended on an optional vendored conformance roster. When the roster did not load, no connector could be added. When it did, a connector on its scaffold list was refused even after it was published and installed. The new projection in server/connector-readiness.ts answers from three separate facts: the artifact a run would execute (a developer-local source, else the installed version, re-verified against its recorded bytes), whether this host meets that artifact's declared requirements (the scheduler's own checks), and the signed catalog, which only decides between "install" and "not published" when nothing is selected. The result is an action (connect, install, repair, configure, retry, unavailable) and a reason. Roster membership and the listing tier are not inputs. One resolver feeds the owner template list, a new readiness endpoint (GET /v1/owner/connector-install/readiness) and the browser-enrollment shell route. The route recomputes the verdict when it is called and returns 409 unless the action is connect, so a stale console cannot enroll a connector whose artifact has since broken. Removes browserEnrollmentSupport, isKnownScaffoldConnector and the is_known_scaffold template field. The roster exports stay in polyfill-connectors-runtime.ts for non-availability callers. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…ving it The console ran the same roster-dependent rule in its own process, so the picker and the server could answer differently from the same inputs. A published, installable connector (LinkedIn, Goodreads) read "Not built yet" and its Install control was hidden. The owner template now carries the server's readiness verdict (connector_readiness), and the browser-session routes fetch it from GET /v1/owner/connector-install/readiness. The console parses it at the boundary, drops a malformed verdict, and lets only a "connect" action add an account. A blocked verdict is explained next to the package control, which stays available so an invalid package can be reinstalled. A manifest alone grants no browser enrollment, so the manifest-only fallback catalog fails closed. A server that predates the endpoint answers 404; the console then defers to that server's own enrollment check instead of blocking every browser connector. Removes the console's browser-connect-support rule, the isKnownScaffold entry field and the "Not built yet" copy. The picker test that compared the card to browserEnrollmentSupport now asserts the picker's action follows the verdict. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
CONFORMANCE_ROSTER_LOADED and KNOWN_SCAFFOLD_CONNECTORS had one consumer each, both removed with the roster-based availability rule. Keep PRODUCTION_READY_CONNECTORS, which the supported-collector tier helpers still read. Also remove an unused type from the readiness route test. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…e artifact The browser-enrollment-shell route now refuses a connector that has no verified selected artifact. This test registered the ChatGPT manifest only, so the route answered 409 not_installed before the draft was classified. Publish the manifest as a developer-local source and set browser host capability, the same fixtures the readiness tests use, so the test again reaches the classification it asserts. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The staged-console check looked for a bundled roster predicate (isSupportedBrowserCollectorConnector or isKnownScaffoldConnector) and failed the stage when none answered from the roster. The console no longer bundles either predicate: whether the owner can add a browser connector is now decided by the server's readiness verdict, so the Windows and Linux reference-stack staging steps failed with "no bundled roster predicate answers from the roster". Keep the checks that still protect something the console reads: the roster module is required by a bundled module, it and the two other connector package modules resolve inside the stage, and PRODUCTION_READY_CONNECTORS is non-empty. Drop the predicate probe, its scaffold-only test and the fixture's predicate option. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Render the catalog card with a ready verdict and with a failed-verification verdict and assert what the owner sees: account setup and no note for the ready one, the repair explanation and no setup link for the other. Both cases fail against the card without the readiness note. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…bound the readiness reads The enrollment verdict reused the scheduler's host rule, which requires a browser surface configured through environment variables because a scheduled run has no one at the keyboard. Enrollment is attended: the owner opens the browser themselves. A bare host with no such variables therefore got `configure` and a 409 for a connector that could run. The host rule is now one function with two callers: the scheduler keeps the unattended browser requirement, enrollment checks only required tools and local paths. Resolution is now total. A manifest that cannot be hashed, a malformed requirements block or a throwing probe yields `inspection_failed` for that connector instead of failing the whole template list. The list read reuses host-check results for 30 seconds and bounds the catalog read to 5 seconds; the action-time check in the enrollment route always asks the host. `/readiness` accepts at most 50 `connector_id` values and takes its candidate keys from the install store without hashing each artifact twice. The 409 message and the console copy now use a fixed sentence per reason. `detail` stays on the wire for diagnosis but no longer reaches owner-facing text, so an absolute path or a raw store error cannot leak through it. The wire shape drops the unused `artifact`, `catalog` and `host` fields, and the dead `not_consulted` branch is removed. A test compares the console's copy of the action and reason vocabulary with the server's. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…be read The console OR-ed the server's `browserBound` with the bundled manifest, so a connector the server called not browser-bound still opened the repair routes, and any failed fetch of the verdict read as "not found". The verdict now decides both fields. The bundled manifest is consulted only when the server answers 404, meaning it predates the readiness endpoint; that branch is labeled as a stopgap with its removal condition. Any other fetch failure is rethrown so the page shows the error state with its retry action. The catalog card shows a fixed sentence per reason and no longer appends the server's `detail`. The note is computed once per card. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…res it does not collect Removing the conformance roster also removed the only thing that kept a placeholder connector out of enrollment. A placeholder's package verifies, its host requirements are met, and its collection step only reports a skip, so the readiness verdict said `connect`: the owner could create an enrollment shell, sign in, and collect nothing, repeatedly. The package now declares this about itself: `capabilities.collection.implemented: false` in its manifest. A verified, browser-bound package with that declaration reads `unavailable` with the new reason `not_implemented`, before the host is asked, so the enrollment route answers 409 and the catalog card shows a fixed placeholder note. The server holds no connector list for this, and an absent or other declaration changes nothing. Manifest validation already accepts the key, and an older server ignores it. Until a placeholder package publishes the declaration, the server cannot tell it from a working one; that is a change in the connector package, not here. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…connectors When the server predates the readiness endpoint the console has no verdict and defers to the server's own enrollment check. It opened the add action for every connector in that case, including ones the bundled manifest does not mark browser-bound; the old rule returned false for those. Both `browserBound` and `canAddAccount` now defer only for a connector the bundled manifest marks browser-bound. Also adds the `not_implemented` reason to the console's copy of the vocabulary, with its fixed note. The drift test against the server's list covers it. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The readiness endpoint answers for many connectors, but getConnectorReadiness took the first entry of the response. A reordered or multi-connector answer would have applied another connector's verdict to the one the owner asked about. It now selects the entry whose canonical key matches the requested connector and returns null when none matches. The `detail` field is documented as a server diagnostic that the console does not render, matching what the copy module does. It still travels on the wire for the owner-only endpoint. A comment on the UAT static-secret branch records why it is not gated on browser readiness. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
… from its package The rule that withholds Install from a connector with no setup path says that installing a package never creates one. That held while a bundled list decided browser setup. Now the server's verdict decides, and for a browser connector it is the package that makes the connector runnable: a manifest-only entry (no template yet) reads as a runbook disposition, so it would show "Not installable" and could never be installed. A browser-bound entry in an offered tier now counts as awaiting its package when it has no verdict and is not registered, or when the verdict is install or repair. Any other verdict (placeholder, host requirement, not browser-bound) still withholds Install. While the package catalog is busy the offer stays "unknown", as before. The earlier runbook fixture used a verdict-less entry to mean "no path"; it now carries the verdict that says installing cannot help. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…ctor on runnable browser setup A connector that declares credential capture is exposed for UAT without asking whether its setup can run. For a browser-bound connector that is wrong: it takes stored credentials but is still set up through the owner's browser session, so with no verified package it was exposed with no way to complete setup. A connector that is not browser-bound has no such dependency and stays exposed. The check is one helper used by the base rule and the development-tier allowlist rule, which had the same gap. It replaces a comment that wrongly said credential-capture connectors never open the browser shell. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…-checking it here reference-implementation's tsc program statically resolved the console contract file through the readiness vocabulary test's literal import and failed with TS1287 four times, because the console package is compiled as CommonJS under this package's verbatimModuleSyntax. `tsc --noEmit` in reference-implementation therefore exited 1. Build the specifier at runtime and type the result by hand, the way sources-report-model.test.ts already imports console modules. The test still loads the real file at runtime and still compares both vocabularies. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
biome's import-order assist flagged five files this PR added or edited, and the new console contract test used six non-null assertions. Sort the imports and replace the assertions with one helper that asserts the owner copy exists. No behaviour change. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
… the disposition rule A browser connector with no readiness verdict counted as awaiting its package whenever it was not registered. That also matched an entry built from a template that a server without the readiness endpoint reports with no verdict, so a connector whose disposition has no setup path (provider-auth gated, unsupported) offered Install on a page where the earlier rule says "Not installable". Five of that rule's own tests failed. Only a manifest-only entry, which has no registrationStatus because no template exists yet, awaits its package without a verdict. The earlier revision hid the problem by giving those tests a blocking verdict; they are back to their original form and pass. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
tnunamak
force-pushed
the
fix/connector-readiness-projection
branch
from
November 6, 2026 14:28
a269447 to
2223a67
Compare
…r-package bundle module The desktop build stages the console and then probes it (scripts/check-staged-console-connectors.mjs): it evaluates every webpack module whose text names the connector conformance roster package, loading only .next/server/chunks. Selecting a readiness verdict by key made connector-install-client.ts import connection-modality.ts, which imports the shared setup planner and, through it, polyfill-connectors-runtime. Webpack concatenated the client, the owner-token code it imports and that runtime into one module that names the roster. Evaluating it needed next/headers externals that live only in route entry files, so the probe threw "e[a] is not a function" and all four desktop builds failed. Move the key rule into the pure connector-readiness-contract.ts (readinessConnectorKey, selectConnectorReadiness) and have the client import that. A test pins the copy to the console's canonicalConnectorKey, and a second test fails if the client reaches the setup planner or the connector package again. Reproduced locally by building the console and running the staging probe: it failed before this change and passes after it. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Base automatically changed from
fix/console-install-before-account-setup
to
main
November 6, 2026 17:12
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.
Stacked on #617: the base is its branch, so review only the commits after it.
Whether the owner could add a browser connector was decided by an optional bundled list of connectors. Without that list, published and installable connectors such as LinkedIn and Goodreads read "Not built yet", and the console's copy of the rule could disagree with the server's.
The server now projects one verdict per connector from the selected package (developer-local first, else installed and re-verified), the host's attended-enrollment requirements and the catalog, which is used for discovery only. The action is connect, install, repair, configure, retry or unavailable, with a reason. A package that declares
capabilities.collection.implemented: falseis unavailable, not connect.GET /v1/owner/connector-install/readinessand the template fieldconnector_readinesscarry the verdict. The console only reads it.POST /_ref/connectors/:id/browser-enrollment-shellchecks it again at request time and answers 409 unless the action isconnect. The roster,is_known_scaffoldand the console's duplicate rule are deleted.For the owner, a published connector offers Install, then account setup once it is installed and the host is ready; a blocked connector says why in one fixed sentence. The server's
detailtext is not shown, because it can name a store error or a host path.Open dependency: a placeholder package must publish
implemented: false. Until it does, a not-yet-installed placeholder still shows Install.Proof: each test file ran alone on this head (server readiness, routes, shell route, templates, setup plan; console verdict contract, catalog, presentation, picker, install client).
tsc --noEmitexits 0 in both packages. The desktop build's staging probe failed on an earlier head withe[a] is not a function, and passes now after a local console build and stage.Not verified: PostgreSQL and the full suite. The mutation job rejects this change because it is over the 60-line sampling bound.
Assisted-by: AI