Files
inter-hub/docs/new-hub-quickstart.md
tegwick 750c9f25ff
Some checks failed
Test / test (push) Has been cancelled
docs: add new-hub-quickstart.md — two-pattern domain hub guide
Covers Pattern A (API consumer, any language, start today) and Pattern B
(IHP extension hub, Haskell, shares haskelseed build infra). Includes honest
Haskell/IHP assessment, build-time estimates, hub-core sketch, and a
concrete checklist. References existing domain-hub-extension-guide.md for
type vocabulary registration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 14:53:19 +02:00

9.2 KiB
Raw Blame History

New Domain Hub — Quickstart Guide

Audience: A developer starting a new domain hub (dev-hub, ops-hub, fin-hub, etc.) that will live in its own repository and use inter-hub as the governance substrate.

Current state: inter-hub v0.2.0-alpha.1 is running at http://192.168.178.135:8080.


Two Patterns — Choose One

Pattern A: API Consumer Hub (any language, start today)

Your hub is a standalone application that talks to inter-hub via REST API. No Haskell required. Full framework services available from day one.

Best for: Hubs that already have a tech stack (Node, Python, Go, etc.), prototypes, or teams that want zero build overhead.

Pattern B: IHP Extension Hub (Haskell, shares build infra)

Your hub is a separate IHP project that runs alongside inter-hub, sharing the same Nix/GHC installation on haskelseed and optionally the same PostgreSQL cluster (different schema or database).

Best for: Hubs that need server-rendered UI, deep governance integration, or type-safe access to inter-hub's data model.


Pattern A — API Consumer Hub

1. Create an API consumer in inter-hub

Go to http://192.168.178.135:8080/ApiConsumers → New.

Fill in:

  • Name: dev-hub (or your hub name)
  • Contact: your team email
  • Description: what this hub does

After creating the consumer, go to API Keys → New and generate a key for this consumer. Copy the key — it is shown only once.

2. Register your hub

curl -X POST http://192.168.178.135:8080/api/v2/hubs \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Dev Hub",
    "slug": "dev-hub",
    "domain": "dev.example.com",
    "hubKind": "domain"
  }'

Save the returned id — this is your hubId for all subsequent calls.

3. Register your type vocabulary

Before creating widgets with domain-specific types, register them via the inter-hub UI at /HubCapabilityManifests → New → select your hub.

In the manifest editor, declare your types:

["dev-pipeline-run", "dev-pr-review", "dev-build-status"]

Click Activate. See docs/domain-hub-extension-guide.md for the full naming rules and conflict-resolution workflow.

4. Register widgets

curl -X POST http://192.168.178.135:8080/api/v2/widgets \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pipeline Status Panel",
    "widgetType": "dev-pipeline-run",
    "hubId": "<your-hub-id>",
    "viewContext": "pipeline-dashboard"
  }'

5. Record interaction events

curl -X POST http://192.168.178.135:8080/api/v2/interaction-events \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "widgetId": "<widget-id>",
    "eventType": "clicked",
    "userId": "<optional-user-id>",
    "payload": {"button": "retry", "pipeline": "main-ci"}
  }'

6. What you get for free

Once events are flowing, the inter-hub framework automatically provides:

  • Annotation collection on any widget
  • Requirement candidate escalation from annotations
  • Triage queue and governance lifecycle (Requirement → Decision → Deployment)
  • AI-assisted requirement drafting (if AgentRegistration is configured)
  • Outcome signals and regression detection
  • Widget marketplace discovery

Your hub only needs to POST events. Everything downstream is managed by inter-hub.


Pattern B — IHP Extension Hub (Haskell)

Prerequisites

The same build infrastructure used for inter-hub works directly:

  • haskelseed VM (192.168.178.135) with GHC 9.10.3 in the Nix store
  • devenv for reproducible environments
  • The painful one-time Nix setup is already done — a new IHP project reuses the same Nix store

Bootstrap a new hub repo

# On your workstation (Nix must be installed)
nix profile install nixpkgs#ihp-new
ihp-new dev-hub
cd dev-hub

# Edit devenv.nix to pin to the same IHP version as inter-hub (1.5.0)
# Then:
devenv up

The first devenv up on a fresh machine takes 2040 min to fetch Nix dependencies. On haskelseed, most dependencies are already in the Nix store and the setup takes ~2 minutes.

Connect to inter-hub's API

Add the inter-hub API client to your hub. The simplest approach:

-- Application/Helper/InterHubClient.hs
module Application.Helper.InterHubClient where

import IHP.Prelude
import Network.HTTP.Simple

postEvent :: Text -> Text -> Text -> Value -> IO ()
postEvent apiKey widgetId eventType payload = do
    let req = setRequestMethod "POST"
            $ setRequestHeader "Authorization" ["Bearer " <> cs apiKey]
            $ setRequestHeader "Content-Type" ["application/json"]
            $ setRequestBodyJSON (object
                [ "widgetId"  .= widgetId
                , "eventType" .= eventType
                , "payload"   .= payload
                ])
            $ parseRequest_ "http://192.168.178.135:8080/api/v2/interaction-events"
    void $ httpLBS req

Shared database (optional)

If your hub needs read access to inter-hub's tables (e.g., to join against requirements or decision_records), connect to the same PostgreSQL:

# In your hub's .env:
DATABASE_URL=postgresql://ihp:ihp@192.168.178.135/interhub

Your IHP app can then use query @DecisionRecord directly without going through the API. This is appropriate for tightly-coupled hubs that are part of the same operational boundary.

For loosely-coupled hubs (separate teams, separate deploy cadence), use the API only — do not share the database.

How fast is the Haskell build for a new hub?

A fresh IHP project with 10 controllers and 20 views compiles to ~150 modules (vs inter-hub's 616). With the Nix store already populated on haskelseed:

Stage Time
First devenv up (Nix fetch) ~2 min (store populated)
First GHCi load (150 modules) ~35 min
Incremental reload (1 module changed) ~515 s
Adding a new controller+view pair ~1030 s compile time

This is practical for active development. The painful build experience with inter-hub was caused by its scale (616 modules, 12 phases worth of code) and the Alpine setup being done from scratch. A new hub starts small.


Honest Assessment: Is IHP a Good Framework for Domain Hubs?

Yes, with caveats.

Strengths:

  • Type safety catches integration errors at compile time, not at 2am
  • Server-rendered HSX views are fast to write once you know IHP conventions
  • The query builder and auto-generated types eliminate a whole class of SQL bugs
  • IHP's code generator scaffolds a controller+4 views in seconds
  • Once the Nix environment is set up, it is reproducible — no "works on my machine"

Caveats:

  • The initial Nix setup is still painful on a new machine (~1h)
  • GHC error messages for type inference failures are dense
  • No hot-reload for Haskell (GHCi restart is fast, but not instant)
  • The hub-core shared library is planned but not yet implemented — each new hub currently duplicates boilerplate for API client setup, hub registration, and event posting

Bottom line: If you are already comfortable with Haskell and IHP, building domain hubs in the same stack is efficient and the type safety pays dividends quickly. If your team is not Haskell-native, Pattern A (API consumer) is the pragmatic choice — the API surface is stable and well-documented, and you can add a lightweight web layer in whatever language fits your team.


What hub-core Would Provide

The planned hub-core Haskell library (not yet implemented) would give every domain hub:

  • HubRegistration typeclass — register with inter-hub on startup
  • WidgetEnvelope helpers — consistent widget wrapping across hubs
  • InterHubClient — typed API client with retry and auth built in
  • HubCapabilityManifest bootstrap — auto-activate manifest on startup
  • Shared defaultLayout with inter-hub navigation integration

Until hub-core exists, copy the client helper above and the 3-step registration pattern into your new hub. It is ~50 lines of boilerplate.


Checklist for a New Hub

  • Create ApiConsumer + ApiKey in inter-hub UI
  • Record your hub ID and API key in the new hub's .env
  • Register HubCapabilityManifest with domain type vocabulary
  • Activate the manifest (validates no naming conflicts)
  • Create at least one Widget per meaningful UI surface
  • Instrument interactions with POST to /api/v2/interaction-events
  • Verify events appear in inter-hub at /InteractionEvents
  • (Optional) Configure AgentRegistration and ModelRoutingPolicy for AI-assisted requirement drafting
  • (Optional) Set up HubRoutingRules to route annotations to your hub's triage queue

Reference

Resource Location
API reference (OpenAPI) http://192.168.178.135:8080/api/v2/openapi.json
Type registry browser http://192.168.178.135:8080/TypeRegistries/WidgetTypes
Domain hub extension guide docs/domain-hub-extension-guide.md
IHP data and queries docs/ihp-data-and-queries.md
IHP controllers and views docs/ihp-controllers-views-forms.md
Functional module maturity docs/functional-modules.md
IHF v0.2 specification specs/InteractionHubFrameworkSpecification_v0.2.md