ObjectStackObjectStack

Package Registry

Package Registry protocol schemas

Package Registry Protocol

Defines the runtime state and lifecycle operations for installed packages.

Key Distinction: App vs Package (ADR-0019)

  • App (AppSchema): the one consumer-facing unit — what a tenant downloads, opens, and uninstalls. Only type: app packages are consumer-installable (see isConsumerInstallable), and a consumer package defines at most one app — there is no "suite contains apps" aggregator.
  • Package (Manifest): the internal / control-plane artifact term (the "row" in the installed-packages table). Never surfaced to consumers as a separate noun.
  • Internal contributions (plugin/driver/server/…): the "frameworks inside the .app bundle" — bundled within an App or operator-provisioned; a consumer never installs them directly.

Architecture Alignment

  • Salesforce: Managed Packages with install/uninstall lifecycle
  • VS Code: Extension marketplace with enable/disable per-workspace
  • Kubernetes: Helm charts with release state tracking
  • npm: Package registry with install/uninstall/version management

Source: packages/spec/src/kernel/package-registry.zod.ts

TypeScript Usage

import { DisablePackageRequestSchema, DisablePackageResponseSchema, EnablePackageRequestSchema, EnablePackageResponseSchema, GetPackageRequestSchema, GetPackageResponseSchema, InstallPackageRequestSchema, InstallPackageResponseSchema, InstalledPackageSchema, ListPackagesRequestSchema, ListPackagesResponseSchema, NamespaceConflictErrorSchema, NamespaceRegistryEntrySchema, PackageStatusEnum, UninstallPackageRequestSchema, UninstallPackageResponseSchema } from '@objectstack/spec/kernel';
import type { DisablePackageRequest, DisablePackageResponse, EnablePackageRequest, EnablePackageResponse, GetPackageRequest, GetPackageResponse, InstallPackageRequest, InstallPackageResponse, InstalledPackage, ListPackagesRequest, ListPackagesResponse, NamespaceConflictError, NamespaceRegistryEntry, UninstallPackageRequest, UninstallPackageResponse } from '@objectstack/spec/kernel';

// Validate data
const result = DisablePackageRequestSchema.parse(data);

DisablePackageRequest

Disable package request

Properties

PropertyTypeRequiredDescription
idstringPackage ID to disable

DisablePackageResponse

Disable package response

Properties

PropertyTypeRequiredDescription
package{ manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … }Disabled package details
messagestringoptionalDisable status message

Nested Shape: DisablePackageResponse.package

PropertyTypeRequiredDescription
manifest{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }Full package manifest
statusEnum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>optional (default: "installed")Package state: installed, disabled, installing, upgrading, uninstalling, or error
enabledbooleanoptional (default: true)Whether the package is currently enabled
installedAtstringoptionalInstallation timestamp
updatedAtstringoptionalLast update timestamp
installedVersionstringoptionalCurrently installed version for quick access
previousVersionstringoptionalVersion before the last upgrade
statusChangedAtstringoptionalStatus change timestamp
errorMessagestringoptionalError message when status is error
settingsRecord<string, any>optionalUser-provided configuration settings
upgradeHistory{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' | 'failed' | 'rolled_back'>; … }[]optionalVersion upgrade history
registeredNamespacesstring[]optionalNamespace prefixes registered by this package

EnablePackageRequest

Enable package request

Properties

PropertyTypeRequiredDescription
idstringPackage ID to enable

EnablePackageResponse

Enable package response

Properties

PropertyTypeRequiredDescription
package{ manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … }Enabled package details
messagestringoptionalEnable status message

Nested Shape: EnablePackageResponse.package

PropertyTypeRequiredDescription
manifest{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }Full package manifest
statusEnum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>optional (default: "installed")Package state: installed, disabled, installing, upgrading, uninstalling, or error
enabledbooleanoptional (default: true)Whether the package is currently enabled
installedAtstringoptionalInstallation timestamp
updatedAtstringoptionalLast update timestamp
installedVersionstringoptionalCurrently installed version for quick access
previousVersionstringoptionalVersion before the last upgrade
statusChangedAtstringoptionalStatus change timestamp
errorMessagestringoptionalError message when status is error
settingsRecord<string, any>optionalUser-provided configuration settings
upgradeHistory{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' | 'failed' | 'rolled_back'>; … }[]optionalVersion upgrade history
registeredNamespacesstring[]optionalNamespace prefixes registered by this package

GetPackageRequest

Get package request

Properties

PropertyTypeRequiredDescription
idstringPackage identifier

GetPackageResponse

Get package response

Properties

PropertyTypeRequiredDescription
package{ manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … }Package details

Nested Shape: GetPackageResponse.package

PropertyTypeRequiredDescription
manifest{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }Full package manifest
statusEnum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>optional (default: "installed")Package state: installed, disabled, installing, upgrading, uninstalling, or error
enabledbooleanoptional (default: true)Whether the package is currently enabled
installedAtstringoptionalInstallation timestamp
updatedAtstringoptionalLast update timestamp
installedVersionstringoptionalCurrently installed version for quick access
previousVersionstringoptionalVersion before the last upgrade
statusChangedAtstringoptionalStatus change timestamp
errorMessagestringoptionalError message when status is error
settingsRecord<string, any>optionalUser-provided configuration settings
upgradeHistory{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' | 'failed' | 'rolled_back'>; … }[]optionalVersion upgrade history
registeredNamespacesstring[]optionalNamespace prefixes registered by this package

InstallPackageRequest

Install package request

Properties

PropertyTypeRequiredDescription
manifest{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }Package manifest to install
settingsRecord<string, any>optionalUser-provided settings at install time
enableOnInstallbooleanoptional (default: true)Whether to enable immediately after install
platformVersionstringoptionalCurrent platform version for compatibility verification

Nested Shape: InstallPackageRequest.manifest

PropertyTypeRequiredDescription
idstringUnique package identifier (reverse domain style)
namespacestringoptionalShort namespace identifier; also the mandatory prefix of every object name (e.g. "todo" → object names "todo_task", "todo_project")
defaultDatasourcestringoptional (default: "default")Default datasource for all objects in this package
versionstringPackage version (semantic versioning)
typeEnum<'plugin' | 'ui' | 'driver' | 'server' | 'app' | 'theme' | 'agent' | 'objectql' | …>Type of package
scopeEnum<'cloud' | 'system' | 'project'>optional (default: "project")Deployment scope: cloud | system | project
namestringHuman-readable package name
descriptionstringoptionalPackage description
permissionsstring[] | { services?: string[]; hooks?: string[]; network?: string[]; fs?: string[] }optionalRequired permissions: legacy string[] or structured plugin block (ADR-0025 §3.2)
objectsstring[]optionalGlob patterns for ObjectQL schemas files
datasourcesstring[]optionalGlob patterns for Datasource definitions
dependenciesRecord<string, string>optionalPackage dependencies
configurationneveroptional[REMOVED] manifest.configuration was removed in @objectstack/spec 17 (ADR-0049 enforce-or-remove) — nothing ever read the block: no settings UI rendered it and no loader resolved a setting from it, so authoring it configured nothing. Worse, properties.*.secret promised "value is encrypted/masked (e.g. API Keys)" while nothing encrypted, masked or even parsed the flag — a false assurance about credential handling. Delete the key. A plugin is configured by the host that composes it: pass options to its constructor in defineStack({ plugins: [new MyPlugin({ … })] }), which is the enforced channel. A declarative settings surface must be designed with an enforcing reader first, not revived here.
contributes{ kinds?: object[] }optionalPlatform contributions
data{ object: string; externalId?: string | string[]; mode?: Enum<'insert' | 'update' | 'upsert' | 'replace' | 'ignore'>; env?: Enum<'prod' | 'dev' | 'test'>[]; … }[]optionalInitial seed data (prefer top-level data field)
capabilitiesneveroptional[REMOVED] manifest.capabilities was removed in @objectstack/spec 17 (ADR-0049 enforce-or-remove) — no discovery path ever consulted the block: nothing read implements, provides, requires, extensionPoints or extensions, so the declared "interoperability and automatic discovery" never happened. Delete the key. Real dependency resolution runs off top-level manifest.dependencies, which stays. Capability-based discovery must be designed with an enforcing reader first, not revived here.
extensionsneveroptional[REMOVED] manifest.extensions was removed in @objectstack/spec 17 (ADR-0049 enforce-or-remove) — an untyped map with zero readers: whatever was parked here was stored and never consulted. Delete the key. Extend the platform through the enforced channels instead: contributes.kinds registers metadata kinds, navigationContributions injects navigation into other packages' apps, and code-level extension happens in the plugin itself (init/start).
navigationContributions{ app: string; group?: string; priority?: integer; items: (object | … +8 more)[] }[]optionalNavigation items this package contributes into apps owned by other packages
loadingneveroptional[REMOVED] manifest.loading was removed in @objectstack/spec 17.0.0 (ADR-0049 enforce-or-remove) — the entire block (strategy, preload, codeSplitting, dynamicImport, initialization, dependencyResolution, hotReload, caching, sandboxing, monitoring) had no runtime reader in any repo, so authoring it configured nothing. Delete the key. Plugins are composed at boot — defineStack registers them and the kernel runs init then start in an order topologically resolved from each composed plugin's own dependencies / optionalDependencies (resolvePluginOrder); the set is fixed until the process restarts. ⚠️ loading.sandboxing in particular never isolated anything: it did not run plugins in a process, vm, iframe or web-worker, and allowedServices gated no call. If you were relying on it for isolation, you had none — and the plugin trust tier (manifest.runtime) does not give it back: that tier is enforced at the cloud marketplace PUBLISH gate only (an unverified publisher requesting the node tier is rejected with HTTP 422 and forced to manual review), while load-side enforcement is NOT implemented, so a locally installed plugin is not isolated by the tier it declares. Use the permission declarations, which are enforced.
engine{ objectstack: string }optionalPlatform compatibility requirements (legacy; superseded by engines)
engines{ platform?: string; protocol?: string }optionalPlugin compatibility ranges (ADR-0025 §3.2; supersedes engine)
runtimeEnum<'node' | 'sandbox' | 'worker'>optionalPlugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting node → HTTP 422 + manual review); load-side enforcement is NOT implemented, so a locally installed plugin is not isolated by the tier it declares
packagingEnum<'bundled' | 'manifest-deps'>optionalDependency packaging strategy (ADR-0025 §3.3)
integrityRecord<string, string>optionalPer-file content digests of the plugin artifact (ADR-0025 §3.2)

InstallPackageResponse

Install package response

Properties

PropertyTypeRequiredDescription
package{ manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … }Installed package details
messagestringoptionalInstallation status message
dependencyResolution{ dependencies: object[]; canProceed: boolean; requiredActions: object[]; installOrder: string[]; … }optionalDependency resolution result from install analysis

Nested Shape: InstallPackageResponse.package

PropertyTypeRequiredDescription
manifest{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }Full package manifest
statusEnum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>optional (default: "installed")Package state: installed, disabled, installing, upgrading, uninstalling, or error
enabledbooleanoptional (default: true)Whether the package is currently enabled
installedAtstringoptionalInstallation timestamp
updatedAtstringoptionalLast update timestamp
installedVersionstringoptionalCurrently installed version for quick access
previousVersionstringoptionalVersion before the last upgrade
statusChangedAtstringoptionalStatus change timestamp
errorMessagestringoptionalError message when status is error
settingsRecord<string, any>optionalUser-provided configuration settings
upgradeHistory{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' | 'failed' | 'rolled_back'>; … }[]optionalVersion upgrade history
registeredNamespacesstring[]optionalNamespace prefixes registered by this package

Nested Shape: InstallPackageResponse.dependencyResolution

PropertyTypeRequiredDescription
dependencies{ packageId: string; requiredRange: string; resolvedVersion?: string; installedVersion?: string; … }[]Resolution result for each dependency
canProceedbooleanWhether installation can proceed
requiredActions{ type: Enum<'install' | 'upgrade' | 'confirm_conflict'>; packageId: string; description: string }[]Actions required before proceeding
installOrderstring[]Topologically sorted package IDs for installation
circularDependenciesstring[][]optionalCircular dependency chains detected (e.g. [["A", "B", "A"]])

InstalledPackage

Installed package with runtime lifecycle state

Properties

PropertyTypeRequiredDescription
manifest{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }Full package manifest
statusEnum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>optional (default: "installed")Package state: installed, disabled, installing, upgrading, uninstalling, or error
enabledbooleanoptional (default: true)Whether the package is currently enabled
installedAtstringoptionalInstallation timestamp
updatedAtstringoptionalLast update timestamp
installedVersionstringoptionalCurrently installed version for quick access
previousVersionstringoptionalVersion before the last upgrade
statusChangedAtstringoptionalStatus change timestamp
errorMessagestringoptionalError message when status is error
settingsRecord<string, any>optionalUser-provided configuration settings
upgradeHistory{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' | 'failed' | 'rolled_back'>; … }[]optionalVersion upgrade history
registeredNamespacesstring[]optionalNamespace prefixes registered by this package

Nested Shape: InstalledPackage.manifest

PropertyTypeRequiredDescription
idstringUnique package identifier (reverse domain style)
namespacestringoptionalShort namespace identifier; also the mandatory prefix of every object name (e.g. "todo" → object names "todo_task", "todo_project")
defaultDatasourcestringoptional (default: "default")Default datasource for all objects in this package
versionstringPackage version (semantic versioning)
typeEnum<'plugin' | 'ui' | 'driver' | 'server' | 'app' | 'theme' | 'agent' | 'objectql' | …>Type of package
scopeEnum<'cloud' | 'system' | 'project'>optional (default: "project")Deployment scope: cloud | system | project
namestringHuman-readable package name
descriptionstringoptionalPackage description
permissionsstring[] | { services?: string[]; hooks?: string[]; network?: string[]; fs?: string[] }optionalRequired permissions: legacy string[] or structured plugin block (ADR-0025 §3.2)
objectsstring[]optionalGlob patterns for ObjectQL schemas files
datasourcesstring[]optionalGlob patterns for Datasource definitions
dependenciesRecord<string, string>optionalPackage dependencies
configurationneveroptional[REMOVED] manifest.configuration was removed in @objectstack/spec 17 (ADR-0049 enforce-or-remove) — nothing ever read the block: no settings UI rendered it and no loader resolved a setting from it, so authoring it configured nothing. Worse, properties.*.secret promised "value is encrypted/masked (e.g. API Keys)" while nothing encrypted, masked or even parsed the flag — a false assurance about credential handling. Delete the key. A plugin is configured by the host that composes it: pass options to its constructor in defineStack({ plugins: [new MyPlugin({ … })] }), which is the enforced channel. A declarative settings surface must be designed with an enforcing reader first, not revived here.
contributes{ kinds?: object[] }optionalPlatform contributions
data{ object: string; externalId?: string | string[]; mode?: Enum<'insert' | 'update' | 'upsert' | 'replace' | 'ignore'>; env?: Enum<'prod' | 'dev' | 'test'>[]; … }[]optionalInitial seed data (prefer top-level data field)
capabilitiesneveroptional[REMOVED] manifest.capabilities was removed in @objectstack/spec 17 (ADR-0049 enforce-or-remove) — no discovery path ever consulted the block: nothing read implements, provides, requires, extensionPoints or extensions, so the declared "interoperability and automatic discovery" never happened. Delete the key. Real dependency resolution runs off top-level manifest.dependencies, which stays. Capability-based discovery must be designed with an enforcing reader first, not revived here.
extensionsneveroptional[REMOVED] manifest.extensions was removed in @objectstack/spec 17 (ADR-0049 enforce-or-remove) — an untyped map with zero readers: whatever was parked here was stored and never consulted. Delete the key. Extend the platform through the enforced channels instead: contributes.kinds registers metadata kinds, navigationContributions injects navigation into other packages' apps, and code-level extension happens in the plugin itself (init/start).
navigationContributions{ app: string; group?: string; priority?: integer; items: (object | … +8 more)[] }[]optionalNavigation items this package contributes into apps owned by other packages
loadingneveroptional[REMOVED] manifest.loading was removed in @objectstack/spec 17.0.0 (ADR-0049 enforce-or-remove) — the entire block (strategy, preload, codeSplitting, dynamicImport, initialization, dependencyResolution, hotReload, caching, sandboxing, monitoring) had no runtime reader in any repo, so authoring it configured nothing. Delete the key. Plugins are composed at boot — defineStack registers them and the kernel runs init then start in an order topologically resolved from each composed plugin's own dependencies / optionalDependencies (resolvePluginOrder); the set is fixed until the process restarts. ⚠️ loading.sandboxing in particular never isolated anything: it did not run plugins in a process, vm, iframe or web-worker, and allowedServices gated no call. If you were relying on it for isolation, you had none — and the plugin trust tier (manifest.runtime) does not give it back: that tier is enforced at the cloud marketplace PUBLISH gate only (an unverified publisher requesting the node tier is rejected with HTTP 422 and forced to manual review), while load-side enforcement is NOT implemented, so a locally installed plugin is not isolated by the tier it declares. Use the permission declarations, which are enforced.
engine{ objectstack: string }optionalPlatform compatibility requirements (legacy; superseded by engines)
engines{ platform?: string; protocol?: string }optionalPlugin compatibility ranges (ADR-0025 §3.2; supersedes engine)
runtimeEnum<'node' | 'sandbox' | 'worker'>optionalPlugin trust tier the plugin declares (ADR-0025 §3.6) — enforced at the cloud marketplace publish gate (unverified publisher requesting node → HTTP 422 + manual review); load-side enforcement is NOT implemented, so a locally installed plugin is not isolated by the tier it declares
packagingEnum<'bundled' | 'manifest-deps'>optionalDependency packaging strategy (ADR-0025 §3.3)
integrityRecord<string, string>optionalPer-file content digests of the plugin artifact (ADR-0025 §3.2)

Nested Shape: InstalledPackage.upgradeHistory[number]

PropertyTypeRequiredDescription
fromVersionstringVersion before upgrade
toVersionstringVersion after upgrade
upgradedAtstringUpgrade timestamp
statusEnum<'success' | 'failed' | 'rolled_back'>Upgrade outcome
migrationLogstring[]optionalMigration step logs

ListPackagesRequest

List packages request

Properties

PropertyTypeRequiredDescription
statusEnum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>optionalFilter by package status
typeEnum<'plugin' | 'ui' | 'driver' | 'server' | 'app' | 'theme' | 'agent' | 'objectql' | 'module' | 'gateway' | 'adapter'>optionalFilter by package type
enabledbooleanoptionalFilter by enabled state

ListPackagesResponse

List packages response

Properties

PropertyTypeRequiredDescription
packages{ manifest: object; status?: Enum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>; enabled?: boolean; installedAt?: string; … }[]List of installed packages
totalnumberTotal package count

Nested Shape: ListPackagesResponse.packages[number]

Installed package with runtime lifecycle state

PropertyTypeRequiredDescription
manifest{ id: string; namespace?: string; defaultDatasource?: string; version: string; … }Full package manifest
statusEnum<'installed' | 'disabled' | 'installing' | 'upgrading' | 'uninstalling' | 'error'>optional (default: "installed")Package state: installed, disabled, installing, upgrading, uninstalling, or error
enabledbooleanoptional (default: true)Whether the package is currently enabled
installedAtstringoptionalInstallation timestamp
updatedAtstringoptionalLast update timestamp
installedVersionstringoptionalCurrently installed version for quick access
previousVersionstringoptionalVersion before the last upgrade
statusChangedAtstringoptionalStatus change timestamp
errorMessagestringoptionalError message when status is error
settingsRecord<string, any>optionalUser-provided configuration settings
upgradeHistory{ fromVersion: string; toVersion: string; upgradedAt: string; status: Enum<'success' | 'failed' | 'rolled_back'>; … }[]optionalVersion upgrade history
registeredNamespacesstring[]optionalNamespace prefixes registered by this package

NamespaceConflictError

Namespace collision error during installation

Properties

PropertyTypeRequiredDescription
type'namespace_conflict'Error type
requestedNamespacestringRequested namespace
conflictingPackageIdstringConflicting package ID
conflictingPackageNamestringConflicting package display name
suggestionstringoptionalSuggested alternative namespace

NamespaceRegistryEntry

Namespace ownership entry in the registry

Properties

PropertyTypeRequiredDescription
namespacestringNamespace prefix
packageIdstringOwning package ID
registeredAtstringRegistration timestamp
statusEnum<'active' | 'disabled' | 'reserved'>Namespace status

PackageStatusEnum

Package installation status

Allowed Values

  • installed
  • disabled
  • installing
  • upgrading
  • uninstalling
  • error

UninstallPackageRequest

Uninstall package request

Properties

PropertyTypeRequiredDescription
idstringPackage ID to uninstall

UninstallPackageResponse

Uninstall package response

Properties

PropertyTypeRequiredDescription
idstringUninstalled package ID
successbooleanWhether uninstall succeeded
messagestringoptionalUninstall status message

On this page