Skip to content

Resource providers

A resource provider is one kind of outside system an organization uses: a package registry, a source control host, a DNS host. It offers several resource types. Jive makes sure each resource exists, using credentials the organization connected once.

Decided (Alex, 2026-11-04): “there’s probably a resource provider and multiple types of resources that said resource provides … Like a source control host provides repos, orgs, maybe teams? A package repository probably provides both packages and orgs.” This is the model Terraform’s providers and Crossplane’s managed resources use; what Jive adds is that its server holds the credentials, and callers hold only a session.

Layer Package Defines
Abstract jive-abstract-resource-provider What every provider exposes: connect, refresh, key sync
Provider kind jive-abstract-resource-provider-package-registry The resource types a package registry offers (org, package) and the arguments each takes
Implementation jive-resource-provider-package-registry-npm Does it on npm: a Convex component and frontend code

Each organization configures exactly one implementation per provider kind. Built for the one kind that exists (schema.ts).

Provider kind Resource types Implementations Status
package-registry package; org npm package built (as the connector below); org proposed
source-control-host org, repo, team GitHub Proposed. Replaces the proposed code-repository connector, which offered repos only.
dns zone, record Cloudflare Proposed

A resource can belong to another: a package to an org, a repo to an org.

Decided (Alex, 2026-11-04): “a package which implements a resource provider needs to have both frontend code and a convex component”.

@jive-sh/server installs it and calls it. Proposed contract, one Convex module per concern:

// Every provider (jive-abstract-resource-provider)
connection.connect({ credential }) // checks the credential against the outside system
→ { status: "connected"; account: { id: string; name: string } } | { status: "refused"; reason: string }
connection.refresh({ credential }) // only for a refreshable credential
→ { status: "refreshed"; credential: Credential } | { status: "refused"; reason: string }
keys.syncPublicKeys({ owner, keys, credential }) // only for a system that holds copies of Jive keys
// One module per resource type the provider kind defines, e.g. package-registry's
package.ensure({ args: { name: string; org: string }, caller, credential }) → EnsureResult
org.ensure({ args: { name: string }, caller, credential }) → EnsureResult
type Credential = {
blob: string; // whatever the outside system issued; only the implementation reads it
expiresAt: number | null; // ms since epoch; null for one that doesn't expire
refreshable: boolean; // whether connection.refresh can renew it (the blob carries what refresh needs)
};
  • Decided (Alex, 2026-11-04): connect takes “the actual credential blob, expiration, and whether it’s refreshable”, and refreshing is a separate call.
  • Decided (Alex, 2026-11-01): “Connectors must expose an API which allows for key rotation”. The draft is keys.syncPublicKeys (jive_key_rotation_api.md).
  • A component stores no credentials: the server passes one on every call. Built that way today.
  • EnsureResult is today’s EnsureInstanceResult: ready, inProgress, personNeeded or refused (instance.ts).
  • The build checks the component’s generated ComponentApi type against the abstract’s contract type for exact equality. Built (abstract.ts).

Runs in the Jive browser extension and walks a person through the outside system’s own screens to produce the credential. See Connecting an account.

Built, under the names used before “provider”:

Today Becomes
jive-abstract-resource stays
jive-abstract-resource-connector: no contract of its own jive-abstract-resource-provider
jive-abstract-resource-connector-package-registry jive-abstract-resource-provider-package-registry
jive-resource-connector-package-registry-npm jive-resource-provider-package-registry-npm

Today’s package-registry contract has one resource type, a package, implied rather than named: resource.ensureInstance with { packageName }. It also has five lower-level calls: packageExists, createPlaceholder, and list, register and remove trusted publishers (contract.ts). There’s no connect, refresh or key sync call yet.