# Path to contract 1.0 This page is an honest read of how stable the plugin contract is today, for a sister site deciding how much to build on it. It is derived from the ADRs and the live code, not aspiration. The authoritative hook reference is [PLUGIN-HOOKS.md](PLUGIN-HOOKS.md); the versioning rules are in [ADR-002](adr/ADR-002-plugin-versioning.md). ## Current version The plugin contract is at **0.6.0**, declared in `shopdb/__init__.py` as `__contract_version__`. It is pre-1.0, which under semver means any 0.x minor bump is allowed to break the contract, and this project has used that latitude. The product release version (`__version__`, currently 0.5.0) is a separate series with its own bump rules; see [ADR-007](adr/ADR-007-product-versioning-and-releases.md). Do not pin against it for compatibility - pin against `__contract_version__`. ### 0.x history Recorded in the comment block in `shopdb/__init__.py`: | Version | Change | Kind | |---------|--------|------| | 0.3.0 | `shopdb.api` expanded to the full plugin import surface (db, cache, model bases, core models, response + pagination helpers, `employee_connection`) so plugins stop importing internal core paths | additive (minor) | | 0.4.0 | Removed the never-implemented `get_searchable_fields` hook (search is a core concern over the asset model) and wired `get_dashboard_widgets` to a real consumer (`/api/dashboard/widgets`) | pre-1.0 contract reduction | | 0.6.0 | Added the `get_reports` hook, consumed by `GET /api/reports` to merge plugin report cards into the Reports hub | additive optional hook (minor) | The source comment block documents 0.3.0, 0.4.0, and 0.6.0. Earlier points (0.1.x / 0.2.x) predate that recorded rationale; `PluginMeta`'s fallback `core_version` default of `>=0.2.0,<1.0.0` is the only remaining trace of the 0.2 baseline. ## Settled surface These are unlikely to break before 1.0. A plugin can depend on them with reasonable confidence; a breaking change to any would be a major bump and would land with a new or amended ADR. | Surface | What it is | |---------|-----------| | `meta` / manifest schema | `PluginMeta` fields and `manifest.json` (ADR-002 single source of truth) | | `get_blueprint` | Flask Blueprint registration at the manifest `api_prefix` | | `get_models` | SQLAlchemy model classes the plugin owns | | `init_app` | Custom init after blueprint + models are known | | `get_cli_commands` | Click commands added to the Flask CLI | | `get_services` | Named service classes, consumed by `plugin_manager.get_service` | | Lifecycle hooks | `on_install`, `on_uninstall`, `on_enable`, `on_disable` | | `get_navigation_items` | Sidebar menu entries | | `get_dashboard_widgets` | Dashboard widgets, consumed by `/api/dashboard/widgets` | | `get_reports` | Report cards, consumed by `/api/reports` (added 0.6.0) | | Collector pair | `get_collector_schema` + `apply_collector_payload` per [ADR-006](adr/ADR-006-collector-contract.md) | | Settings helpers | `get_setting` / `set_setting`, namespaced to the plugin | | `get_provisioning_note` | Setup-wizard transparency note for extra tables | | `get_config_schema` | Setup-wizard config field declarations | | `shopdb.api` import surface | The only core module plugins may import (plus `shopdb.plugins.base`); adding a name is minor, removing one is major | The asset model itself - `Asset`, `AssetType`, `AssetStatus`, `AssetRelationship`, and the shared reference models - is the platform contract locked in [ADR-001](adr/ADR-001-asset-as-platform-contract.md). ## Expected churn before 1.0 Known-unstable areas. Building on these means expecting rework. | Area | Status | Reference | |------|--------|-----------| | Frontend hook contract | Not defined yet. There is no server-side hook for asset-detail panels, map markers, or search-result rendering. A plugin that needs custom UI still hand-edits the Vue frontend. This is the single biggest gap. [ADR-010](adr/ADR-010-frontend-plugin-hooks.md) proposes the path: data-only declarative hooks (`get_settings_cards`, `get_asset_panels`, `get_map_overlays`, `get_asset_presentation`) rendered by generic core components, with build-time glob discovery deferred for real components. | [ADR-010](adr/ADR-010-frontend-plugin-hooks.md) (PROPOSED) | | Per-plugin migrations | Brand new. The per-plugin Alembic engine exists and every bundled plugin now carries a chain, but the pattern has one release of production mileage, not years. | [ADR-008](adr/ADR-008-plugin-migration-ownership.md) (2026-07-10) | | Pip distribution | Deferred to v2. External plugins install by clone / submodule / symlink; there is no entry-point discovery and no automatic update path yet. | [ADR-003](adr/ADR-003-plugin-distribution.md) | ## Bump rules From [ADR-002](adr/ADR-002-plugin-versioning.md), applied to `__contract_version__`: | Bump | Trigger | |------|---------| | major | Breaking change to the `BasePlugin` ABC, the `PluginMeta` schema, or any model in the platform contract (`Asset`, `AssetType`, `AssetStatus`, `AssetRelationship`, `Vendor`, `Location`, `BusinessUnit`, `Model`, `OperatingSystem`). Removing a name from `shopdb.api` is major. | | minor | Additive change: a new optional hook, a new field on a contract model with a default, a new name added to `shopdb.api`. | | patch | Bug fix with no change to the contract surface. | ### Deprecation policy ADR-002 defines the bump classification above but is **silent** on any deprecation window or notice period for pre-1.0 removals. In practice a removal is simply a major (or, pre-1.0, a breaking minor) bump: the hook or name is gone, and the loader fails loud in dev or excludes the mismatched plugin in prod (see the load-time table in [PLUGIN-EXTERNAL-REPO.md](PLUGIN-EXTERNAL-REPO.md)). Because the ADR says nothing about a grace period, this document proposes none; the honest guidance for sister sites is the mitigation that already exists - pin a tight `core_version` range and re-test before widening it. ## Criteria for declaring 1.0 Provisional. This is the maintainer's working list, not a committed checklist, and it will move. ADR-002's own open question ("When does the framework declare 1.0.0?") ties 1.0 to the `Machine` retirement from ADR-001 and the framework being "ready for sister sites"; the items below expand that intent. - Frontend hook contract defined via its own ADR (asset-detail panels, map markers, search results), closing the biggest churn item above. - `Machine` / legacy-model retirement complete per ADR-001, so the asset model is the only contract. - At least two external plugins running in production at a second site - the bar ADR-003 already sets before pip distribution and sister-site readiness are considered justified. - The per-plugin migration pattern (ADR-008) proven across real upgrades, not just fresh installs. - No contract bump needed for N consecutive product releases (N to be fixed when the list is firmed up), showing the surface has actually settled. Until then: pre-1.0, pin tight, re-test on every framework bump.