# Hub-Core Extraction Boundary Last reviewed: 2026-06-06 ## Purpose This note starts `CUST-WP-0025-T05` by translating the original hub-core idea into a current implementation boundary. The State Hub implementation no longer lives under `the-custodian/state-hub`; the authoritative source checkout is `/home/worsch/state-hub`, and the planned package target is `/home/worsch/hub-core`. The extraction must preserve a clean FOS split: - `hub-core` owns reusable hub primitives. - `state-hub` becomes the first dev-hub implementation and keeps development coordination concepts such as topics, workstreams, tasks, decisions, dependencies, SBOM, token accounting, and kaizen agents. - Future hubs such as ops-hub and fin-hub depend on `hub-core` without pulling in dev-hub coordination tables. ## First Package Slice Create `/home/worsch/hub-core` as a uv-managed Python package with this initial layout: ```text hub_core/ __init__.py database.py models/ __init__.py base.py domain.py managed_repo.py agent_message.py capability_catalog.py capability_request.py progress_event.py tpsc.py schemas/ __init__.py domain.py managed_repo.py agent_message.py capability.py progress_event.py tpsc.py routers/ __init__.py domains.py repos.py messages.py tpsc.py policy.py ``` This slice avoids the models that currently carry dev-hub foreign keys. It is large enough to prove packaging, import style, SQLAlchemy metadata ownership, router dependency injection, and State Hub compatibility before the more entangled surfaces move. Current implementation status: - 2026-06-06: `/home/worsch/hub-core` was created and committed with base, domain, managed repo, agent message, capability catalog, and TPSC models plus matching schemas. - 2026-06-06: router factory functions were added for domains, repos, messages, TPSC, and policy lookup. These factories accept host-supplied dependencies instead of importing State Hub globals. - 2026-06-06: shared utilities and migration scaffold were added: slug normalization, pagination, repo path resolution, trailing-slash path normalization, Alembic templates, and an initial core-schema migration. - 2026-06-06: progress event and capability request adapter seams were added. Hub-core uses generic JSON context fields where State Hub currently has dev-specific workstream/task/topic/decision foreign keys. ## Extract Now These State Hub files are suitable for the first extraction after import-path rewriting and small router seams: | Source in `/home/worsch/state-hub` | Target role | | --- | --- | | `api/models/base.py` | Declarative base, timestamps, UUID helper. | | `api/models/domain.py` | Core domain identity; remove relationships to dev-hub-only models from core. | | `api/models/managed_repo.py` | Core repo registry; make `topic_id`, SBOM, and sync timestamps extension fields or keep them in dev-hub until a second pass. | | `api/models/agent_message.py` | Generic agent inbox and thread model. | | `api/models/tpsc.py` | Third-party service catalog/snapshot primitives. | | `api/schemas/domain.py` | Core domain schemas; split dev-hub counts from generic read models. | | `api/schemas/managed_repo.py` | Core repo schemas; keep dispatch/scope-health schemas in dev-hub. | | `api/schemas/agent_message.py` | Generic message schemas. | | `api/schemas/tpsc.py` | Generic TPSC schemas. | | `api/routers/messages.py` | Mostly self-contained generic router. | | `api/routers/tpsc.py` | Generic catalog and GDPR report router. | | `api/routers/policy.py` | Generic policy document router if policy roots become configurable. | The first committed router seam is factory-based rather than global: ```python from hub_core.routers import create_domains_router app.include_router(create_domains_router(get_session)) ``` That shape lets each hub keep its own database session configuration and mount only the generic routers it wants. ## Shared Utilities The initial utility set is intentionally small and dependency-light: | Module | Purpose | | --- | --- | | `hub_core.utils.slugs` | Convert user-facing names into stable lowercase slugs. | | `hub_core.utils.pagination` | Shared limit/offset bounds and SQLAlchemy pagination. | | `hub_core.utils.paths` | Resolve repo paths from `host_paths` before falling back to `local_path`. | | `hub_core.utils.routing` | Normalize a path or URL path component while preserving query strings and fragments. | ## Migration Scaffold `/home/worsch/hub-core` now carries Alembic template files under `hub_core/migrations/` plus `versions/0001_core_schema.py`. The first migration covers only the currently extracted core tables: - `domains` - `managed_repos` - `agent_messages` - `capability_catalog` - `capability_requests` - `progress_events` - `tpsc_catalog` - `tpsc_snapshots` - `tpsc_entries` ## Needs An Adapter Seam These are still part of the target architecture, but the current State Hub implementation is coupled to dev-hub concepts: | Surface | Coupling to resolve | | --- | --- | | `Domain` and `domains.py` detail views | Counts topics, workstreams, extension points, and technical debt. Hub-core should expose a domain summary hook that dev-hub can implement. | | `ManagedRepo` | Contains `topic_id`, SBOM fields, and state-sync timestamps. Keep minimal repo identity in core, then add dev-hub extensions. | | `CapabilityRequest` | Adapter seam implemented with generic `request_context` and `fulfillment_context`; State Hub still needs a later refactor to map workstream/task references into those fields or a dev-hub extension table. | | `ProgressEvent` | Adapter seam implemented with generic `subject_refs`; State Hub still needs a later refactor to map topic/workstream/task/decision foreign keys into that field or a dev-hub extension table. | | MCP tools in `mcp_server/server.py` | Generic tools are mixed into a single dev-hub server module. T06 should create a base registration class that receives API client/config dependencies and lets dev-hub add its own tools. | The first two adapter seams are now implemented in hub-core: - `ProgressEvent.subject_refs`: generic JSON references for hub-local subjects. - `CapabilityRequest.request_context` and `fulfillment_context`: generic JSON context for hub-local workstreams, tasks, incidents, services, budgets, or other future hub entities. ## Keep In Dev-Hub The following State Hub areas should not move into hub-core during T05: - Topics, workstreams, tasks, decisions, dependencies, and flow state. - Extension points, technical debt, interface changes, SBOM, token events, and contribution accounting. - Dashboard-specific loaders and Observable views. - Workplan-file parsing and consistency reconciliation. - Kaizen agents, scope health, dispatch views, and recently-on-scope reports. ## Verification Plan The first hub-core commit should pass these checks before State Hub is refactored to import it: 1. `python3 -m compileall hub_core` 2. A minimal import test that imports every model, schema, and router module. 3. SQLAlchemy metadata inspection proving the initial core tables are registered. 4. A FastAPI smoke app that mounts the extracted routers with an injected `get_session` dependency. 5. `cd /home/worsch/state-hub && make test` remains green before and after the editable `hub-core` dependency is introduced. ## Next Step Create the `/home/worsch/hub-core` package with only the first package slice, commit that seed independently, then return to `/home/worsch/state-hub` for the first import-based refactor. Do not rename State Hub to dev-hub until T05-T08 prove the shared package boundary.