Component Lifecycle
Install
Section titled “Install”wh component install <org/name> --repo org/repoOnly registered components (<org>/<name>) can be installed. To install your own component, register it first (wh component register <name> --org <org> --manifest <path>). The installer runs through these stages:
WarmHub’s own system components install the same way: the identity system is the registered component warmhub/identity. WarmHub-managed internal components are not installable.
-
Source resolution — Resolves the registered component reference to its latest published manifest snapshot from the component registry.
-
Parse and validate — Validates the resolved manifest’s JSON structure, required fields, and cross-references (for example, credentials and shapes referenced by subscriptions and seeds).
-
Ensure shared infrastructure — Creates the
ComponentInstallandComponentConfigshapes if they don’t already exist in the repo. These are system-managed shapes shared across all components. -
Record install — Creates a
ComponentInstall/<component-id>thing with stateinstallingand the serialized manifest. This thing is a mirror of the install state; the durable install row and the registry manifest are the authoritative sources for later inspection flows such ascomponent.getandcomponent.history. -
Apply manifest-provisioned resources — In order:
- Shapes: Created if they don’t exist. Tagged with the component’s ID.
- Credential sets: Created if they don’t exist. Keys are declared but not populated — the user must set values after install.
- Subscriptions: Manifest subscriptions are compiled into normal WarmHub webhook subscriptions, then bound to credential sets.
- Seeds: Initial things are created if they don’t already exist. A failure on one seed does not prevent the remaining seeds from being applied.
Resources marked
provisioning: "setup"are handled by the backend’s setup flow and are not provisioned during the main resource-apply step. -
Run registered setup — If a registered component advertises a setup endpoint, the backend calls it after the main resource-apply step finishes. This happens whenever the registration has setup enabled, regardless of whether the apply step completed without errors — the apply step may finish in a
degradedstate (for example, due to shape, credential, subscription, or seed errors) and setup will still run. Setup-provisioned shapes, credential sets, and subscriptions are created by that external service. -
Compute state — Checks whether all resources were created successfully. Sets the final state to
readywhen everything succeeded, ordegradedwhen a resource failed. Missing credential values do not change the state — they surface asdoctorfindings instead. -
Finalize — Updates the
ComponentInstallmirror record with the final state. The authoritative install record and the registry manifest snapshot are the sources of truth forcomponent.get,component.history, andwh component doctor.
Subscription compilation
Section titled “Subscription compilation”The installer derives the effective subscription kind from trigger.kind:
eventtriggers compile to normal webhook subscriptions withshape,filter, andwebhookUrl
Component manifests declare webhook subscriptions only; handlers live outside the manifest and are referenced by webhook URL.
Reconciliation (reinstall)
Section titled “Reconciliation (reinstall)”If a component is already installed (a ComponentInstall record exists), the installer enters reconciliation mode:
- Missing resources are added — New shapes, subscriptions, and seeds from the updated manifest are created.
- Dropped shapes are released — Shapes that were in the old manifest but absent from the new one are freed for reuse by
wh component update. The shape rows themselves are not deleted. - Existing subscriptions are preserved — Subscriptions that were in the old manifest but absent from the new one are left in place and are not automatically removed or paused.
- Seeds are updated — If a seed thing already exists, its data is revised to match the new manifest.
- Failed installs are retried — If the previous state was
installingorerror, the reconciler treats the old manifest as empty and retries all resources. - Degraded installs are re-probed — If the previous state was
degraded, the reconciler keeps the old manifest and probes the live resources, deciding per resource whether to add, revise, or update rather than retrying everything. - Paused subscriptions are not automatically resumed — Reinstall adds missing subscriptions, but a subscription that still exists in paused state stays paused until you resume or recreate it yourself.
- Unowned same-name shapes can be adopted — If a shape with the same name exists but has no owning component (for example, because the previous owner was torn down or the shape was dropped by an update), reinstall or update can claim it.
- Registered setup is replayed on update —
wh component updatefor a registered install re-resolves the latest published manifest, sends the install request to the backend, and triggers the setup endpoint again, bringing the component up to the latest published version.
Doctor
Section titled “Doctor”wh component doctor <org/name> --repo org/repoDoctor checks an installed component against the manifest snapshot recorded for that install rather than your local files, so results reflect what is actually deployed. It checks:
| Check | Pass | Fail |
|---|---|---|
| Shape exists and is active | ok | missing or inactive |
| Subscription exists and is active | ok | missing or inactive |
| Credential set exists with all required keys populated | ok | missing keys listed |
| Seed things exist | ok | missing |
| Shape or subscription is owned by this component | ok | warning with owner details |
| Installed version matches latest published revision | ok | non-gating warning (version drift) |
When a shape or subscription exists but is reported as owned by a different component, doctor emits a warning finding with a message such as Shape "..." exists but is owned by "...". The recovery path differs depending on the resource type:
- Shape ownership conflicts — Tearing down the owning component frees those shape names for reuse. Once the owning component is torn down, reinstalling your component can adopt those freed shape names. Doctor will continue to report the conflict until ownership is reclaimed. Alternatively,
wh component updateon the owning component will release any shapes it drops from its manifest, which also frees those names. - Subscription ownership conflicts — Teardown only pauses subscriptions owned by the uninstalling component; it does not release subscription ownership. Reinstall hard-rejects any same-name subscription still owned by a different component, so reclaiming a subscription via reinstall is not possible while that subscription row exists. To resolve a subscription conflict, coordinate with the owning component’s maintainer to remove or rename the subscription, or update your manifest to reference a differently named subscription.
For either resource type, you can also update your manifest to reference a differently named shape or subscription to avoid the conflict entirely.
Version-drift findings
Section titled “Version-drift findings”Doctor emits a non-gating version-drift warning when the installed revision is behind the latest published version of the component. This warning does not change the component state — a behind install can still be ready. To clear it, run wh component update <org/name> --repo org/repo.
Version drift is also surfaced outside of doctor:
wh component listappends(x.y.z available)next to any installed component that has a newer published revision.wh component viewincludes an explicitwh component updatehint when a newer version is available.
Doctor computes and persists the component state:
- All subscriptions paused, nothing else wrong →
paused - Any subscription paused while others remain active →
degraded - Missing resources, inactive non-subscription resources, shape drift, or ownership warnings →
degraded - Everything healthy →
ready
Missing credential values are reported as doctor findings, but they do not change the component state — there is no credentials-required state. If a CLI method needs credentials that aren’t set, the call fails at invocation time with a precise error; populating those keys is the component setup’s job.
Teardown
Section titled “Teardown”wh component teardown <org/name> --repo org/repoTeardown is a single, terminal operation. It:
- Pauses the component’s subscriptions.
- Revokes the install’s component tokens.
- Releases ownership of every shape the component owns, freeing those shape names for reuse. The CLI lists the released shape names after teardown completes.
- Dispatches the uninstall callback, if the component declares an uninstall URL.
- Marks the install record
uninstalled— a terminal state.
Teardown is terminal but non-destructive: the shape rows and any seeded data remain in the repo after ownership is released. Deleting the repo is the only path that eventually removes them. The install record is also retained.
To bring a torn-down component back, reinstall it. Reinstall revives the same install record and reclaims ownership of the previously released shapes; because subscriptions are left paused, a reinstall adds any missing ones but does not automatically resume subscriptions that still exist in paused state — resume or recreate those yourself:
wh sub resume <subscription-name> --repo org/repoState transitions
Section titled “State transitions”install (new) → installing → ready | degraded | errorinstall (exists) → reconcile → ready | degradeddoctor → ready | degraded | paused | uninstalledteardown → uninstalledValidate (offline)
Section titled “Validate (offline)”wh component validate ./my-componentRuns all checks without connecting to a repo:
- JSON syntax and schema validation
- Cross-reference checks (credential refs, shape refs)
- Duplicate name detection
- Subscription trigger and webhook validation
- Component ID format
- Consistency between
component.jsonandmanifest.json