Skip to content

feat(run): let coral.workspace.createProvider configure and publish the Provider itself - #2352

Merged
iaptsiauri merged 16 commits into
feat/create-providerfrom
feat/create-provider-self-publish
Oct 19, 2026
Merged

iaptsiauri merged 16 commits into
feat/create-providerfrom
feat/create-provider-self-publish

Conversation

@iaptsiauri

@iaptsiauri iaptsiauri commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Stack 4 of 7, on feat/create-provider.

Summary

coral.workspace.createProvider now takes the Provider's configuration. Coral publishes the Provider itself when nobody needs to sign in. Otherwise the call returns the Reef link, as before, and does not wait.

await coral.workspace.createProvider({
  namespace: "weather",
  source: { kind: "openapi_url", url: "https://…/openapi.json" }, // or openapi_document / mcp_url
  credentialRoute: "none",                               // new, required: none | fixed | caller
  displayName, servers, authentication, requestHeaders,  // optional: an omitted field keeps the source's suggestion
})
// { status: "published", namespace, displayName, credentialRoute, authentication, operations, accountRequired }
// or, unchanged: { status: "needs_sign_in", url, namespace }
 createProvider.perform (as the invoking User)
+  namespace in use?                     -> provider_namespace_conflict; no fetch, no Setup
   prepare_setup (the fetch; only this step stops with the Run)
+  confirm the Program's fields over the source's suggestion   -> field errors: invalid_input
+  coral_provider::setup_publishability(route)
+    Rejected                            -> invalid_input
+    Person                              -> needs_sign_in link
+    Coral -> WorkspaceProviderPublisher (ProviderWorkflow, as Reef; Universal Search included)
+      namespace taken meanwhile         -> provider_namespace_conflict
+      Publication failed or refused     -> provider_publication_failed
+  a Setup nobody will finish            -> Coral ends it (lifecycle actor: Coral)
-  return the needs_sign_in link
Source none fixed caller
Needs no credential Coral publishes invalid_input invalid_input
Needs a credential invalid_input needs_sign_in Coral publishes if the Setup is Ready, else needs_sign_in
  • The result says what Coral resolved. authentication is spelled as the input spells it. operations counts the Operations a Principal can discover and call. accountRequired uses the route selection an Invocation uses (select_route). There is no callRoot field. The guidance says to call the Operations under coral.providers.<namespace>, and to check later by searching with the namespace as provider.
  • No credential value comes from the Program. A non-empty literal in authentication fails with invalid_input. So does a request header named Authorization, Proxy-Authorization, Cookie, X-API-Key or Api-Key, or ending in -Token or -Secret. Built-in input is now checked at admission, so rejected input is never stored with an Invocation and never waits for approval.
  • An MCP source is discovered with the Program's requestHeaders.
  • Once the Setup exists, the call runs to an end. If the Run has ended by then, Coral publishes nothing, returns no link, and ends the Setup.
  • Recovery: a createProvider lost while dispatching is no longer Indeterminate. Recovery reads the Publication recorded under the Invocation's id. A published Provider becomes the Operation Result (UpstreamOutcome). No Publication, or a Provider deleted since, gives RunTerminated. An unpublished Setup then expires at its deadline.
  • New seam: coral_provider::WorkspaceProviderPublisher. ProviderWorkflow implements it. The server and MCP runtimes inject it with RunModule::with_provider_publisher. coral-run takes coral-administration only as a dev-dependency. Without a publisher, a call Coral would publish fails with operation_unavailable.
  • GLOSSARY: the Built-in Provider entry says when Coral publishes. The Credential Route entry says an Owner's Program chooses the route for the Provider createProvider creates.

Evidence

  • Before: createProvider({ namespace, source }) prepared a Setup and always returned needs_sign_in. Nothing configured or published it. Invalid input was stored with its Invocation, and a lost worker left the Invocation Indeterminate.
    After: coral-run tests/domain/provider_setup.rs:
coral_publishes_a_provider_that_needs_nobody_to_sign_in        none -> published, operations 1, accountRequired false
create_provider_returns_the_reef_page_that_finishes_its_setup  fixed -> needs_sign_in; Setup Ready; one fetch
a_namespace_in_use_fails_before_any_fetch_or_setup             provider_namespace_conflict; 0 fetches, no Setup
a_namespace_taken_while_coral_publishes_is_a_conflict          provider_namespace_conflict
a_failed_publication_is_a_failure_the_program_catches          Failed / Setup canceled first -> provider_publication_failed
a_configuration_the_source_cannot_take_leaves_no_setup_open    bearer source under none -> invalid_input; Setup Canceled
a_run_that_ends_before_the_call_returns_leaves_nothing_behind  none and fixed: no Provider, no open Setup
recovery_settles_a_lost_publication_from_its_publication       published -> UpstreamOutcome; deleted since / never -> RunTerminated
invalid_input_fails_before_storage_approval_fetch_or_setup     no approval, no Invocation, no fetch, no lifecycle event
credential_headers_are_rejected_by_their_exact_name            7 names -> invalid_input; Idempotency-Key -> published
  • coral-provider: publishability_says_who_can_publish_a_setup_under_a_route (the table above, and an unconfirmed Setup gives NotConfigured). ending_cancels_an_open_setup_and_expires_one_past_its_deadline (ended by a User or by Coral; one past its deadline expires; an ended Setup stays as it is).
  • coral-catalog: each_published_builtin_generation_retains_the_coral_defined_catalog checks the new input and both result shapes in the TypeScript declaration.
  • New Reel scenario, main suite, providers/agent-created: "An agent adds a provider that needs no sign-in, and Coral publishes it with no Reef step". Not yet run in this repo.
  • make rust-checks (fmt, clippy -D warnings, workspace tests) passed on the top of the stack (feat/builtin-catalog-update, 57525dc; the head since changed only one Reef test fixture): 1344 of 1344 tests, 2 skipped. Not yet run in this repo: make postgres-tests, the Reef gates, the Reel scenarios.

Merge Danger

Door: two-way

There is no migration. credentialRoute is now required, so a call written for feat/create-provider's { namespace, source } fails with invalid_input. Nothing has been released. A Workspace's Built-in Generation pins the catalog it materialized, so a Workspace created on feat/create-provider still describes the old input until its catalog is updated (feat/builtin-catalog-update).

Blast Radius: narrow

Only an Owner's Program reaches createProvider, and it waits for approval by default. Coral now publishes Providers with no Reef step, through the workflow Reef uses. The Run can still end between Coral's last check and the Publication. The Provider then exists and search finds it, though the call ended. The credential-header rule is a name list: a secret under another header name gets through.

@iaptsiauri
iaptsiauri added this pull request to stack #2356 October 13, 2026 11:18
@cubic-dev-ai

cubic-dev-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Running ultrareview automatically — this PR appears to change authentication, authorization, or input validation, where a missed bug can expose data or grant the wrong access, so a deeper multi-pass review is worth running. I'll post findings when complete.

@cubic-dev-ai cubic-dev-ai Bot 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.

Ultrareview ran automatically — this PR appears to change authentication, authorization, or input validation, where a missed bug can expose data or grant the wrong access, so a deeper multi-pass review is worth running.

All reported issues were addressed across 32 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread crates/coral-run/src/builtin.rs
Comment thread crates/coral-provider/src/lib.rs Outdated
Comment thread crates/coral-test-support/src/provider.rs Outdated
Comment thread crates/coral-catalog/src/builtin.rs
Comment thread crates/coral-provider/src/setup_tests.rs
Comment thread crates/coral-run/tests/domain/provider_setup.rs
Comment thread apps/reef/e2e/scenarios/main/providers/agent-created.test.ts Outdated
Comment thread crates/coral-catalog/tests/builtin_catalog.rs
Comment thread crates/coral-catalog/src/builtin.rs Outdated
Comment thread crates/coral-provider/src/account.rs Outdated
@iaptsiauri
iaptsiauri force-pushed the feat/create-provider-self-publish branch from dc12825 to 427b364 Compare October 13, 2026 12:32
…hten createProvider review fixes

ProviderModule now owns the transactions that createProvider used to open
itself: abandon_setup ends an unfinished Setup, and published_provider reads
the published Provider from one snapshot. BuiltinHost no longer carries the
raw Database.

setup_publishability rejects a consumed, expired or canceled Setup with
ProviderSetupNotApplicable instead of asking a person to finish it.
credentials_ready_in_transaction is the one readiness check that discovery
and the createProvider result share.

Tests and wording: publish_setup_fixture only publishes a configured Setup;
the ending matrix asserts cancel_setup's result; the catalog test pins the
createProvider wrapper again; the e2e scenario names the owner's Program, not
an agent; the custom server URL accepts HTTP or HTTPS; the glossary says Coral
publishes the Provider from a Setup.

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 11 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread GLOSSARY.md Outdated
iaptsiauri and others added 8 commits October 13, 2026 16:31
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
…blish

# Conflicts:
#	crates/coral-app/src/bootstrap/server.rs
…blish

Brings main's search-after-commit change and the Coral UI wording. This
branch's own createProvider description now names the Coral UI too.
…blish

# Conflicts:
#	crates/coral-run/tests/domain/provider_setup.rs
@iaptsiauri iaptsiauri changed the title feat(run): let coral.admin.createProvider configure and publish the Provider itself feat(run): let coral.workspace.createProvider configure and publish the Provider itself Oct 16, 2026
@iaptsiauri
iaptsiauri merged commit 088faaf into main Oct 19, 2026
29 of 36 checks passed
@iaptsiauri
iaptsiauri deleted the feat/create-provider-self-publish branch October 19, 2026 14:13
simonwhitaker pushed a commit that referenced this pull request Oct 22, 2026
🤖 I have created a release *beep* *boop*
---


## [1.2.0](v1.1.0...v1.2.0)
(2026-10-22)


### Features

* **activity:** record authored source locations for calls and outputs
([#2535](#2535))
([2d735ca](2d735ca))
* **activity:** show persistent Program source beside selected records
([#2569](#2569))
([f403819](f403819))
* add the Claude recipe and read gzipped OpenAPI documents
([#2513](#2513))
([07c27a2](07c27a2))
* **catalog:** share named TypeScript types across a Provider
([#2482](#2482))
([256e37d](256e37d))
* **desktop:** run the runtime on a Postgres database named in
desktop.json ([#2485](#2485))
([96465a0](96465a0))
* **functions:** type coral.providers, coral.workspace and
coral.functions at Saved Function save
([#2526](#2526))
([a465850](a465850))
* **provider:** create the Coral Built-in Provider at coral.workspace in
every new Workspace
([#2349](#2349))
([06e65ca](06e65ca))
* **provider:** store an agent's createProvider request on its Setup
([#2593](#2593))
([92847d2](92847d2))
* **provider:** update every Workspace's Built-in Provider catalog at
boot ([#2355](#2355))
([24615d9](24615d9))
* **reef:** add NextDNS provider recipe
([#2509](#2509))
([e44880e](e44880e))
* **reef:** calmer providers table and a flush app shell
([#2462](#2462))
([ffe279c](ffe279c))
* **reef:** improve the UI on small screens
([#2531](#2531))
([75e020a](75e020a))
* **reef:** make the providers rail vertical tabs with an All providers
entry ([#2552](#2552))
([08d007a](08d007a))
* **reef:** providers page UI tweaks
([#2562](#2562))
([7ca218e](7ca218e))
* **reef:** put the list pages' main action back in the top bar as a
primary button ([#2546](#2546))
([761ea6d](761ea6d))
* **reef:** read ^, $ and * in every filter field
([#2520](#2520))
([d322356](d322356))
* **reef:** refuse a provider display name another provider uses
([#2518](#2518))
([fdcd473](fdcd473))
* **reef:** review provider configuration changes in a dialog
([#2579](#2579))
([24417e9](24417e9))
* **reef:** show search indexing failures on a Provider and its
Operations ([#2504](#2504))
([6cffed0](6cffed0))
* **reef:** show your recent activity summary on the workspace overview
([#2574](#2574))
([0d1dba5](0d1dba5))
* **reef:** title list pages in their toolbar, with the main action
beside it ([#2525](#2525))
([fd44b72](fd44b72))
* **reef:** UI tweaks to provider's page
([#2566](#2566))
([62204ca](62204ca))
* **reef:** unify Activity detail panels and action reviews
([#2544](#2544))
([409d062](409d062))
* return only declared successes from Operation calls
([#2517](#2517))
([0270bf1](0270bf1))
* **run:** enforce the Fan-out Limit inside the Run Owner
([#2571](#2571))
([cb53419](cb53419))
* **run:** introduce the Run Owner for Program requests
([#2524](#2524))
([245d19d](245d19d))
* **run:** let coral.workspace.createProvider configure and publish the
Provider itself
([#2352](#2352))
([088faaf](088faaf))
* **run:** let createProvider configure sign-in and link to Reef's
sign-in step ([#2353](#2353))
([8d5495c](8d5495c))
* **run:** list a workspace's providers with
coral.workspace.listProviders
([#2374](#2374))
([179c43a](179c43a))
* **run:** make the Run Owner survive uncertain commits and lost leases
([#2541](#2541))
([3a1fad1](3a1fad1))
* **run:** name Tasks and Runs with four-word identifiers
([#2558](#2558))
([c82259a](c82259a))
* **run:** prepare a Provider from a Program with
coral.workspace.createProvider
([#2351](#2351))
([e7e56fd](e7e56fd))
* **run:** reshape the Dispatch Fence into one batched check per chunk
commit ([#2550](#2550))
([120c9d3](120c9d3))
* **run:** route approval decisions and cancellation through the Run
Owner ([#2577](#2577))
([77bcbf5](77bcbf5))
* **run:** summarize your recent activity in a Workspace
([#2573](#2573))
([bf4c75e](bf4c75e))
* **search:** show a Saved Function's result fields in its signature
line ([#2522](#2522))
([41365f6](41365f6))
* **search:** trace each reconcile pass and its steps
([#2456](#2456))
([0594094](0594094))
* **ui:** add option to create a correctly-configured Slack app during
Slack provider setup
([#2585](#2585))
([8c3a883](8c3a883))
* **ui:** move Add provider to the providers toolbar
([#2591](#2591))
([e1ee4cb](e1ee4cb))


### Bug Fixes

* **app:** sweep device authorization leases every 15 s
([#2452](#2452))
([1a4e4ae](1a4e4ae))
* **auth:** drop the unverified client name note from the approval page
([#2578](#2578))
([ddf5aa4](ddf5aa4))
* **catalog:** derive each Built-in Operation's contract from the types
Coral parses ([#2582](#2582))
([534e636](534e636))
* **catalog:** import OpenAPI Providers whose Operations request
different OAuth scopes
([#2401](#2401))
([3acfe55](3acfe55))
* **catalog:** keep keyword names in Operation Call Paths
([#2506](#2506))
([b20795b](b20795b))
* **catalog:** never make an Operation unavailable for search material
([#2465](#2465))
([f83c909](f83c909))
* **catalog:** stop rejecting createProvider request headers by name
([#2589](#2589))
([39e54b9](39e54b9))
* **provider:** ask for an OAuth client ID when Coral cannot register
one ([#2580](#2580))
([baefe9e](baefe9e))
* **provider:** bind each Setup to its starter and hide Coral from
Members ([#2480](#2480))
([6011a64](6011a64))
* **reef:** align the catalog table with the first rail entry
([#2484](#2484))
([fb59758](fb59758))
* **reef:** calm the Activity badge and keep it while the stream
reconnects ([#2468](#2468))
([1b66639](1b66639))
* **reef:** frame the providers table again and lower the top bar
([#2472](#2472))
([87e41ee](87e41ee))
* **reef:** pin third-party recipe OpenAPI documents to a commit
([#2510](#2510))
([b4e9280](b4e9280))
* **reef:** replace loose help text with info tips and banners
([#2461](#2461))
([695500a](695500a))
* **reef:** round the page's corners beside the sidebar
([#2503](#2503))
([a1fef64](a1fef64))
* **reef:** shorten OAuth scope chips that share a URL prefix
([#2455](#2455))
([5ae67ec](5ae67ec))
* **reef:** suggest a provider's namespace from its document name, not
its host ([#2565](#2565))
([8d77893](8d77893))
* **run:** name every argument to correct in an invalid_input failure
([#2354](#2354))
([07bd727](07bd727))
* **run:** reject a credential beside createProvider's bearer method and
report unreachable sources as upstream_incomplete
([#2542](#2542))
([590eab7](590eab7))
* **run:** report an MCP JSON-RPC rejection as invalid_input or
upstream_rejected
([#2402](#2402))
([749770b](749770b))
* **search:** load each Generation's schema graph once per search
([#2448](#2448))
([445d945](445d945))
* **search:** retry a failed Saved Function only after one interval
([#2460](#2460))
([a61ab3a](a61ab3a))
* **search:** return no hits for a query without a letter or digit
([#2561](#2561))
([bb0a4f0](bb0a4f0))
* **search:** start the write limit at the lock and build rows before
the write ([#2575](#2575))
([06ad55d](06ad55d))
* **search:** stop a self-referential Promise result from overflowing
the stack ([#2543](#2543))
([1d4f257](1d4f257))
* **search:** stop retrying an index write that fails the same way every
time ([#2548](#2548))
([e3b6d15](e3b6d15))


### Performance Improvements

* **catalog:** dedup credential destinations once per build, not per
Operation ([#2555](#2555))
([0afbcf5](0afbcf5))
* **catalog:** project each named TypeScript type once per Provider
([#2443](#2443))
([153c273](153c273))
* **search:** drop schema text from the phrase test
([#2559](#2559))
([cfdbafa](cfdbafa))
* **search:** index each word of schema text once
([#2547](#2547))
([d1123fb](d1123fb))
* **search:** prepare search entries in the indexer after commit
([#2467](#2467))
([1ab6765](1ab6765))
* **search:** recount only Workspaces whose rows changed
([#2457](#2457))
([777cfb3](777cfb3))
* **search:** skip unchanged rows when an index write runs again
([#2459](#2459))
([43b5188](43b5188))
* **search:** write only the statistics rows that changed
([#2458](#2458))
([8e2832c](8e2832c))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: coral-release-bot[bot] <269256696+coral-release-bot[bot]@users.noreply.github.com>
Co-authored-by: release-please[bot] <release-please[bot]@users.noreply.github.com>
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.

1 participant