Skip to content

feat(cli): preflight installable provider for required capabilities (#3366)#3385

Merged
os-zhuang merged 2 commits into
mainfrom
claude/preflight-installable-provider-5t7j20
Jul 21, 2026
Merged

feat(cli): preflight installable provider for required capabilities (#3366)#3385
os-zhuang merged 2 commits into
mainfrom
claude/preflight-installable-provider-5t7j20

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #3366.

Problem

A capability listed in requires: [...] is fail-fast at serve/start time when its provider package is missing — but when the provider has no installable version in the current edition, the generic "not installed, add it to your dependencies" advice is un-followable. Nothing shifted this left: os validate only checks the token against the vocabulary (ADR-0066), and os build never resolves providers or boots the runtime, so a validate && build && test CI script never caught it. It surfaced only as an opaque os start crash — seen upgrading an open-edition app from 14.7 to 16 after @objectstack/service-ai went cloud-only (ADR-0025).

Change

One machine-readable source of truth (spec). @objectstack/spec/kernel now exports PLATFORM_CAPABILITY_PROVIDERS (every vocabulary token → provider package + edition: open / enterprise / cloud) and a pure classifyRequiredCapability(token, isInstalled). This lifts the provider/edition knowledge the serve resolver encoded informally (its CAPABILITY_PROVIDERS map + tier gating) into data a preflight can read before boot.

Shift-left gate (cli). A new capability-preflight.ts util resolves each declared capability's provider the same way serve loads it (host app dir, then the CLI's own deps where the framework @objectstack/* providers live) and renders an edition-aware message. Wired into os build and os validate:

  • No installable version in the active edition (e.g. ai@objectstack/service-ai, cloud-only) → fails fast with the edition-aware message.
  • Absent but installable → advisory pnpm add hint, not a hard error.
  • Satisfied requires → passes unchanged.

Identical boot message (cli). The two os serve fail-fast sites (the AI block and the CAPABILITY_PROVIDERS loop) now render the same classification, so preflight and boot read identically.

Example, from os validate / os build on a requires: ['ai'] app under the open edition:

Capability "ai" resolves to @objectstack/service-ai, which is not available in the open edition (cloud-only since 11.3.0 / ADR-0025). Remove "ai" from requires, or run under a cloud runtime that provides the "ai" tier.

Tests

  • packages/spec/.../platform-capabilities.test.ts — registry shape + classifier (ok / installable / unavailable / unknown; injected resolution, no I/O).
  • packages/cli/test/capability-preflight.test.ts — preflight aggregation, message rendering, missingProviderMessage proving serve and build render identically, and real on-disk resolution.
  • packages/cli/test/serve-capability-vocabulary.test.ts — extended drift guard: the registry stays 1:1 with the vocabulary and agrees with serve's CAPABILITY_PROVIDERS packages; ai/ai-studio are cloud-only.
  • End-to-end verified: ai fails both validate and build; a satisfied list and an absent-but-installable (enterprise) provider behave as specified.

Notes

  • Additive only (new spec exports, new gate) — no authorable spec key / export / config field removed or renamed.
  • Changeset added (@objectstack/spec + @objectstack/cli, minor).

🤖 Generated with Claude Code

https://claude.ai/code/session_013CQ5vX12KRiZ7mn1U4bSwQ


Generated by Claude Code

…3366)

A capability in `requires: [...]` was only checked at serve time, and a
missing provider printed a generic "not installed — add it to your
dependencies" even when the provider has no installable version in the
current edition (e.g. `ai` -> @objectstack/service-ai, cloud-only since
ADR-0025). `os validate` (token vocabulary only) and `os build` (never
resolved providers) both passed, so a validate && build && test CI script
never caught it — it surfaced only as an opaque `os start` crash.

- spec: add `PLATFORM_CAPABILITY_PROVIDERS` (token -> package + edition) and
  a pure `classifyRequiredCapability()` — one machine-readable source of
  truth for the provider/edition knowledge the serve resolver encoded
  informally. A drift test keeps it 1:1 with the vocabulary and in agreement
  with serve's CAPABILITY_PROVIDERS packages.
- cli: `capability-preflight.ts` resolves each declared capability's provider
  the way serve loads it (host dir, then CLI deps) and renders an
  edition-aware message. `os build` and `os validate` fail fast on a
  `requires` entry with no installable provider in the active edition; an
  absent-but-installable provider is an advisory `pnpm add` hint; a satisfied
  list passes unchanged.
- cli: the `os serve` boot error now renders the same classification, so
  preflight and boot read identically.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013CQ5vX12KRiZ7mn1U4bSwQ
@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Canceled Canceled Jul 21, 2026 2:08pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/l labels Jul 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/cli, @objectstack/spec.

110 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via packages/cli, @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/data-flow.mdx (via @objectstack/cli)
  • content/docs/api/environment-routing.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/cli, packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/backup-restore.mdx (via @objectstack/cli)
  • content/docs/deployment/self-hosting.mdx (via @objectstack/cli)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via packages/cli)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/cli, packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/permissions/authentication.mdx (via @objectstack/cli)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/protocol/kernel/realtime-protocol.mdx (via @objectstack/cli)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…ports

`check:api-surface` gates the @objectstack/spec public API. The #3366
additions (PLATFORM_CAPABILITY_PROVIDERS, classifyRequiredCapability, and
their types) are additive (0 breaking, 12 added) — regenerate the committed
snapshot so the gate passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013CQ5vX12KRiZ7mn1U4bSwQ
@os-zhuang
os-zhuang marked this pull request as ready for review July 21, 2026 14:25
@os-zhuang
os-zhuang merged commit 9e45b63 into main Jul 21, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/preflight-installable-provider-5t7j20 branch July 21, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preflight that required capabilities have an installable provider in the current edition

2 participants