- Plugin contract gains get_config_schema(); the plugins list API returns it.
Employees plugin declares its directory-DB fields (host/name/user + password).
- employee_connection reads host/name/user settings-first (env fallback); the
password stays env-only.
- Setup wizard Features step renders each enabled plugin's config: non-secret
fields save to settings; secrets are never stored - the wizard emits .env
lines to paste. Fixed the plugins-list data path (data.plugins).
- Settings PUT now upserts (creates the row on first write) so plugin-config
keys can be saved without pre-seeding.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Third core feature pulled into a plugin (blueprint-only, like slides). The
employee directory is a read-only lookup over a separate HR database.
- plugins/employees/: manifest (api_prefix /api/employees, no deps), api/ (moved
blueprint, contract-pure: success/error/ErrorCodes + employee_connection all
from shopdb.api), plugin.py (get_blueprint, get_models -> []).
- employee_connection STAYS core infrastructure in shopdb.api (config-driven
external DB connector, shared by search + the notifications shopfloor feed). So
no get_services needed and no contract change - the plugin owns the directory
FEATURE, core owns the shared connector.
- Fixed a latent bug in the move: error paths used ErrorCodes.DATABASE_ERROR
which does not exist -> ErrorCodes.INTERNAL_ERROR (so a directory outage now
returns a clean 500 envelope instead of an AttributeError crash).
- De-cored: deleted shopdb/core/api/employees.py, removed from
CORE_BLUEPRINT_NAMES + core/api/__init__ import/__all__. Registered in
instance/plugins.json.
Pinned first: validation (400) + graceful-degrade (500) characterization tests;
the degrade test caught the DATABASE_ERROR bug and goes green with the fix.
184 tests pass, naming green, app boots 9 bundled plugins, endpoint verified live.
Plugin extractions complete: knowledgebase, slides, employees.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>