inter-hub-haskell/Web/FrontController.hs

235 lines
13 KiB
Haskell
Raw Normal View History

module Web.FrontController where
import IHP.RouterPrelude
import IHP.LoginSupport.Middleware
import IHP.ControllerPrelude
import IHP.ViewPrelude (Html, hsx, Layout, autoRefreshMeta)
import Generated.Types
import Web.Types
import Web.Routes ()
-- Controllers
import Web.Controller.Hubs ()
import Web.Controller.Widgets ()
import Web.Controller.InteractionEvents ()
import Web.Controller.Annotations ()
import Web.Controller.AnnotationThreads ()
import Web.Controller.RequirementCandidates ()
import Web.Controller.Requirements ()
import Web.Controller.DecisionRecords ()
import Web.Controller.DeploymentRecords ()
import Web.Controller.AgentProposals ()
import Web.Controller.ApiInteractionEvents ()
import Web.Controller.EnvelopeEmissionContracts ()
import Web.Controller.InteractionReportingContracts ()
import Web.Controller.WidgetAdapterSpecs ()
import Web.Controller.CrossHubPropagations ()
feat(P8): IHF Phase 8 complete — Federated Hub Maturity Implements the final phase of the IHF v0.1 specification: - WidgetOwnership: delegated ownership registry (local/delegated/global), append-only audit artefacts, ownership badge on widget show page - HubRoutingRule + RoutingEngine: priority-ordered inter-hub routing engine; null-inclusive category/widget-type matching; RouteNowAction for manual re-evaluation; RoutedCandidates view per hub - FederatedPolicyOverlay: draft → active → retired lifecycle; activated overlays are immutable (same pattern as Phase 6 contracts); policy compliance dashboard with decision coverage metrics - StewardshipRole: named governance roles per hub; point-in-time revocation pattern; hub and ops-board integration - ArchiveRecord + is_archived: soft-delete on widgets; lineage inspector traces full traceability chain (Widget → Events → Annotations → Candidates → Requirements → Decisions → Deployments → Signals + ArchiveRecord) - FederatedGovernanceDashboard: 5-panel autoRefresh org-wide governance view (ownership coverage, routing activity, policy compliance, stewardship coverage, archive activity) Schema: widget_ownerships, hub_routing_rules, federated_policy_overlays, stewardship_roles, archive_records; ALTER widgets ADD is_archived; ALTER requirement_candidates ADD routed_to_hub_id Migration: 1743638400-ihf-phase8-federated-hub-maturity.sql Tests: Phase 8 integration tests appended to Test/Integration.hs Docs: docs/phase8-summary.md; SCOPE.md updated to Phase 8 complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 22:53:01 +00:00
import Web.Controller.WidgetOwnerships ()
import Web.Controller.HubRoutingRules ()
import Web.Controller.FederatedPolicyOverlays ()
import Web.Controller.StewardshipRoles ()
import Web.Controller.ArchiveRecords ()
import Web.Controller.FederatedGovernance ()
import Web.Controller.TypeRegistries ()
import Web.Controller.HubCapabilityManifests ()
2026-04-01 19:52:20 +00:00
-- Phase 9 — External API Surface (IHUB-WP-0010)
import Web.Controller.ApiConsumers ()
import Web.Controller.ApiKeys ()
import Web.Controller.WebhookSubscriptions ()
import Web.Controller.ApiDashboard ()
import Web.Controller.Api.V2.Widgets ()
import Web.Controller.Api.V2.InteractionEvents ()
import Web.Controller.Api.V2.Annotations ()
import Web.Controller.Api.V2.RequirementCandidates ()
import Web.Controller.Api.V2.DecisionRecords ()
import Web.Controller.Api.V2.DeploymentRecords ()
import Web.Controller.Api.V2.OutcomeSignals ()
import Web.Controller.Api.V2.Registries ()
import Web.Controller.Api.V2.OpenApi ()
import Web.Controller.Api.V2.Token ()
import Web.Controller.Api.V2.Sdk ()
import Web.Controller.Api.V2.Hubs ()
import Web.Controller.Api.V2.HubCapabilityManifests ()
-- Phase 10 — Hub Registry and Widget Marketplace (IHUB-WP-0011)
import Web.Controller.HubRegistry ()
import Web.Controller.WidgetPatterns ()
import Web.Controller.GovernanceTemplates ()
import Web.Controller.MarketplaceDashboard ()
import Web.Controller.Api.V2.HubRegistry ()
import Web.Controller.Api.V2.WidgetPatterns ()
feat(WP-0012): IHF Phase 11 — Advanced AI Federation - Schema: AgentRegistration, ModelRoutingPolicy, AgentDelegation, CollectiveProposal, CollectiveProposalContribution, AiGovernancePolicy, AgentPerformanceRecord + ALTER TABLE agent_proposals (migration 1744156800; CHECK constraints on trust_level, status, consensus_status — GAAF compliant) - Bridge: scripts/llm_bridge.py (llm-connect subprocess seam) + Application/Helper/AgentBridge.hs (callBridge, callAgent, checkGovernancePolicy, jsonArrayTexts) - Routing: Application/Helper/ModelRouter.hs (resolveAgent, resolveAllAgents) + ModelRoutingPolicies CRUD - Registry: AgentRegistrations CRUD (Index/Show/New/Edit/Performance), DeactivateAgentAction, ComputeAgentPerformanceAction - Delegation: AgentDelegations controller + views, DelegateSubtaskAction with token budget enforcement at bridge call time - Collective: CollectiveProposals controller + views, CreateCollectiveProposalAction (fan-out → synthesis → consensus detection) - Governance: AiGovernancePolicies CRUD + ToggleAiGovernancePolicyAction; checkGovernancePolicy enforced at all 4 Phase 5 invocation points - Phase 5 wiring: replaced callClaudeApi in Widgets, DecisionRecords, RequirementCandidates with resolveAgent + callAgent + token tracking - llm-connect feature requests: ~/llm-connect/FEATURE_REQUESTS.md (FR-1 HTTP serve, FR-2 RoutingPolicy, FR-3 async, FR-4 BudgetTracker) - GAAF scorecard: 3.61 (up from 3.56); Functional 3.4→3.6, Extensions 3.8→3.9 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 20:57:17 +00:00
-- Phase 11 — Advanced AI Federation (IHUB-WP-0012)
import Web.Controller.AgentRegistrations ()
import Web.Controller.ModelRoutingPolicies ()
import Web.Controller.AgentDelegations ()
import Web.Controller.CollectiveProposals ()
import Web.Controller.AiGovernancePolicies ()
feat(WP-0013): IHF Phase 12 — Platform Memory and Continuous Learning Closes the long-range feedback loop: outcome signals now enrich the full traceability chain and feed back into routing, triage, and AI proposals. Schema (T01): - outcome_correlations (CHECK correlation_type) - pattern_performance_records - adaptive_threshold_configs - institutional_knowledge_entries (GIN tsvector FTS) - learning_insights (CHECK insight_type) - ALTER TABLE decision_records + requirement_candidates: outcome_summary JSONB - AFTER INSERT trigger trg_enrich_lineage on outcome_signals - contracts/core/ updated (outcome-summary-columns-v1, append-only addendum) Correlation engine (T02): - Application/Helper/CorrelationEngine.hs: pure annotation→outcome SQL - Web/Controller/OutcomeCorrelations.hs: ComputeCorrelationsAction + index Pattern performance (T03): - Web/Controller/PatternPerformance.hs: ComputePatternPerformanceAction Adaptive thresholds (T04): - Web/Controller/AdaptiveThresholds.hs: CalibrateThresholdsAction - Application/Helper/FrictionScore.hs: applyAdaptiveWeights Institutional knowledge (T05): - DistilDecisionAction in DecisionRecords controller - Web/Controller/InstitutionalKnowledge.hs: QueryKnowledgeBaseAction Lineage enrichment (T06): - Web/Controller/LineageEnrichment.hs: EnrichLineageAction (batch backfill) - enrich_lineage_on_outcome_batch() PL/pgSQL helper in migration Learning dashboard (T07): - Web/Controller/LearningDashboard.hs: 5-panel autoRefresh view - "Learning" nav link in FrontController API v2 learning endpoints (T08): - GET /api/v2/outcome-correlations, /pattern-performance, /knowledge-base/{id} - OpenAPI schemas: OutcomeCorrelation, PatternPerformanceRecord, InstitutionalKnowledgeEntry GAAF scorecard + docs (T09): - Core 3.8→3.9, Functional 3.6→3.8, overall 3.61→3.68 - CLAUDE.md: IHF v0.2 complete, no active workplan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:14:15 +00:00
-- Phase 12 — Platform Memory and Continuous Learning (IHUB-WP-0013)
import Web.Controller.OutcomeCorrelations ()
import Web.Controller.PatternPerformance ()
import Web.Controller.AdaptiveThresholds ()
import Web.Controller.InstitutionalKnowledge ()
import Web.Controller.LineageEnrichment ()
import Web.Controller.LearningDashboard ()
import Web.Controller.Api.V2.Learning ()
import Web.Controller.Sessions ()
-- WP-0015 — Public intro / tutorial pages
import Web.Controller.StaticPages ()
instance FrontController WebApplication where
controllers =
[ parseRoute @SessionsController
, parseRoute @HubsController
, parseRoute @WidgetsController
, parseRoute @InteractionEventsController
, parseRoute @AnnotationsController
, parseRoute @AnnotationThreadsController
, parseRoute @RequirementCandidatesController
, parseRoute @RequirementsController
, parseRoute @DecisionRecordsController
, parseRoute @DeploymentRecordsController
, parseRoute @AgentProposalsController
, parseRoute @ApiInteractionEventsController
, parseRoute @EnvelopeEmissionContractsController
, parseRoute @InteractionReportingContractsController
, parseRoute @WidgetAdapterSpecsController
, parseRoute @CrossHubPropagationsController
feat(P8): IHF Phase 8 complete — Federated Hub Maturity Implements the final phase of the IHF v0.1 specification: - WidgetOwnership: delegated ownership registry (local/delegated/global), append-only audit artefacts, ownership badge on widget show page - HubRoutingRule + RoutingEngine: priority-ordered inter-hub routing engine; null-inclusive category/widget-type matching; RouteNowAction for manual re-evaluation; RoutedCandidates view per hub - FederatedPolicyOverlay: draft → active → retired lifecycle; activated overlays are immutable (same pattern as Phase 6 contracts); policy compliance dashboard with decision coverage metrics - StewardshipRole: named governance roles per hub; point-in-time revocation pattern; hub and ops-board integration - ArchiveRecord + is_archived: soft-delete on widgets; lineage inspector traces full traceability chain (Widget → Events → Annotations → Candidates → Requirements → Decisions → Deployments → Signals + ArchiveRecord) - FederatedGovernanceDashboard: 5-panel autoRefresh org-wide governance view (ownership coverage, routing activity, policy compliance, stewardship coverage, archive activity) Schema: widget_ownerships, hub_routing_rules, federated_policy_overlays, stewardship_roles, archive_records; ALTER widgets ADD is_archived; ALTER requirement_candidates ADD routed_to_hub_id Migration: 1743638400-ihf-phase8-federated-hub-maturity.sql Tests: Phase 8 integration tests appended to Test/Integration.hs Docs: docs/phase8-summary.md; SCOPE.md updated to Phase 8 complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 22:53:01 +00:00
, parseRoute @WidgetOwnershipsController
, parseRoute @HubRoutingRulesController
, parseRoute @FederatedPolicyOverlaysController
, parseRoute @StewardshipRolesController
, parseRoute @ArchiveRecordsController
, parseRoute @FederatedGovernanceController
, parseRoute @TypeRegistriesController
, parseRoute @HubCapabilityManifestsController
2026-04-01 19:52:20 +00:00
-- Phase 9 — External API Surface (IHUB-WP-0010)
, parseRoute @ApiConsumersController
, parseRoute @ApiKeysController
, parseRoute @WebhookSubscriptionsController
, parseRoute @ApiDashboardController
-- /api/v2/ REST endpoints (registered before /api/v1/ to avoid prefix clash)
, parseRoute @ApiV2WidgetsController
, parseRoute @ApiV2InteractionEventsController
, parseRoute @ApiV2AnnotationsController
, parseRoute @ApiV2RequirementCandidatesController
, parseRoute @ApiV2DecisionRecordsController
, parseRoute @ApiV2DeploymentRecordsController
, parseRoute @ApiV2OutcomeSignalsController
, parseRoute @ApiV2RegistriesController
, parseRoute @ApiV2OpenApiController
, parseRoute @ApiV2TokenController
, parseRoute @ApiV2SdkController
, parseRoute @ApiV2HubsController
, parseRoute @ApiV2HubCapabilityManifestsController
-- Phase 10 — Hub Registry and Widget Marketplace (IHUB-WP-0011)
, parseRoute @HubRegistryController
, parseRoute @WidgetPatternsController
, parseRoute @GovernanceTemplatesController
, parseRoute @MarketplaceDashboardController
, parseRoute @ApiV2HubRegistryController
, parseRoute @ApiV2WidgetPatternsController
feat(WP-0012): IHF Phase 11 — Advanced AI Federation - Schema: AgentRegistration, ModelRoutingPolicy, AgentDelegation, CollectiveProposal, CollectiveProposalContribution, AiGovernancePolicy, AgentPerformanceRecord + ALTER TABLE agent_proposals (migration 1744156800; CHECK constraints on trust_level, status, consensus_status — GAAF compliant) - Bridge: scripts/llm_bridge.py (llm-connect subprocess seam) + Application/Helper/AgentBridge.hs (callBridge, callAgent, checkGovernancePolicy, jsonArrayTexts) - Routing: Application/Helper/ModelRouter.hs (resolveAgent, resolveAllAgents) + ModelRoutingPolicies CRUD - Registry: AgentRegistrations CRUD (Index/Show/New/Edit/Performance), DeactivateAgentAction, ComputeAgentPerformanceAction - Delegation: AgentDelegations controller + views, DelegateSubtaskAction with token budget enforcement at bridge call time - Collective: CollectiveProposals controller + views, CreateCollectiveProposalAction (fan-out → synthesis → consensus detection) - Governance: AiGovernancePolicies CRUD + ToggleAiGovernancePolicyAction; checkGovernancePolicy enforced at all 4 Phase 5 invocation points - Phase 5 wiring: replaced callClaudeApi in Widgets, DecisionRecords, RequirementCandidates with resolveAgent + callAgent + token tracking - llm-connect feature requests: ~/llm-connect/FEATURE_REQUESTS.md (FR-1 HTTP serve, FR-2 RoutingPolicy, FR-3 async, FR-4 BudgetTracker) - GAAF scorecard: 3.61 (up from 3.56); Functional 3.4→3.6, Extensions 3.8→3.9 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 20:57:17 +00:00
-- Phase 11 — Advanced AI Federation (IHUB-WP-0012)
, parseRoute @AgentRegistrationsController
, parseRoute @ModelRoutingPoliciesController
, parseRoute @AgentDelegationsController
, parseRoute @CollectiveProposalsController
, parseRoute @AiGovernancePoliciesController
feat(WP-0013): IHF Phase 12 — Platform Memory and Continuous Learning Closes the long-range feedback loop: outcome signals now enrich the full traceability chain and feed back into routing, triage, and AI proposals. Schema (T01): - outcome_correlations (CHECK correlation_type) - pattern_performance_records - adaptive_threshold_configs - institutional_knowledge_entries (GIN tsvector FTS) - learning_insights (CHECK insight_type) - ALTER TABLE decision_records + requirement_candidates: outcome_summary JSONB - AFTER INSERT trigger trg_enrich_lineage on outcome_signals - contracts/core/ updated (outcome-summary-columns-v1, append-only addendum) Correlation engine (T02): - Application/Helper/CorrelationEngine.hs: pure annotation→outcome SQL - Web/Controller/OutcomeCorrelations.hs: ComputeCorrelationsAction + index Pattern performance (T03): - Web/Controller/PatternPerformance.hs: ComputePatternPerformanceAction Adaptive thresholds (T04): - Web/Controller/AdaptiveThresholds.hs: CalibrateThresholdsAction - Application/Helper/FrictionScore.hs: applyAdaptiveWeights Institutional knowledge (T05): - DistilDecisionAction in DecisionRecords controller - Web/Controller/InstitutionalKnowledge.hs: QueryKnowledgeBaseAction Lineage enrichment (T06): - Web/Controller/LineageEnrichment.hs: EnrichLineageAction (batch backfill) - enrich_lineage_on_outcome_batch() PL/pgSQL helper in migration Learning dashboard (T07): - Web/Controller/LearningDashboard.hs: 5-panel autoRefresh view - "Learning" nav link in FrontController API v2 learning endpoints (T08): - GET /api/v2/outcome-correlations, /pattern-performance, /knowledge-base/{id} - OpenAPI schemas: OutcomeCorrelation, PatternPerformanceRecord, InstitutionalKnowledgeEntry GAAF scorecard + docs (T09): - Core 3.8→3.9, Functional 3.6→3.8, overall 3.61→3.68 - CLAUDE.md: IHF v0.2 complete, no active workplan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:14:15 +00:00
-- Phase 12 — Platform Memory and Continuous Learning (IHUB-WP-0013)
, parseRoute @OutcomeCorrelationsController
, parseRoute @PatternPerformanceController
, parseRoute @AdaptiveThresholdsController
, parseRoute @InstitutionalKnowledgeController
, parseRoute @LineageEnrichmentController
, parseRoute @LearningDashboardController
, parseRoute @ApiV2LearningController
-- WP-0015 — Public intro / tutorial pages (must be last; catches "/" root)
, parseRoute @StaticPagesController
]
instance InitControllerContext WebApplication where
initContext = do
setLayout defaultLayout
initAuthentication @User
defaultLayout :: (?context :: ControllerContext, ?request :: Request) => Layout
defaultLayout inner =
let authWidget :: Html
authWidget = case currentUserOrNothing @User of
Just _ -> [hsx|
<form method="POST" action={DeleteSessionAction} style="display:inline">
<input type="hidden" name="_method" value="DELETE" />
<button type="submit" class="text-sm text-gray-500 hover:text-gray-700 bg-transparent border-0 p-0 cursor-pointer">Sign out</button>
</form>
|]
Nothing -> [hsx|
<a href={NewSessionAction} class="text-sm text-gray-500 hover:text-gray-900">Sign in</a>
|]
in [hsx|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>inter-hub</title>
{autoRefreshMeta}
<link rel="stylesheet" href="/app.css" />
<script src="/vendor/morphdom.js"></script>
<script src="/vendor/ihp-auto-refresh.js"></script>
<script src="/js/ihf-annotation-launcher.js"></script>
</head>
<body class="bg-gray-50 text-gray-900" style="min-height:100vh;display:flex;flex-direction:column">
<nav class="bg-white border-b border-gray-200 px-6 py-3 flex items-center">
<a href={LandingAction} class="font-semibold text-indigo-600">inter-hub</a>
<div class="ml-auto flex items-center" style="gap:2rem">
<div class="flex items-center" style="gap:1.75rem">
<a href={CapabilitiesAction} class="text-sm text-gray-500 hover:text-gray-900">About</a>
<a href={TutorialAction} class="text-sm text-gray-500 hover:text-gray-900">Tutorial</a>
<a href={ExtensionGuideAction} class="text-sm text-gray-500 hover:text-gray-900">Extend</a>
</div>
<span class="text-gray-200">|</span>
{authWidget}
</div>
</nav>
<div class="flex" style="flex:1">
<aside class="w-48 bg-white border-r border-gray-200 flex-shrink-0 overflow-y-auto">
<nav class="px-3 py-4 space-y-0.5">
<a href={HubsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Hubs</a>
<a href={WidgetsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Widgets</a>
<div class="pt-4 pb-1 px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider">Governance</div>
<a href={RequirementCandidatesAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Candidates</a>
<a href={RequirementsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Requirements</a>
<a href={DecisionRecordsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Decisions</a>
<a href={DeploymentRecordsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Deployments</a>
<div class="pt-4 pb-1 px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider">Intelligence</div>
<a href={AgentProposalsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Agent Proposals</a>
<a href={AgentRegistrationsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Agents</a>
<a href={ModelRoutingPoliciesAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Routing</a>
<a href={CollectiveProposalsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Collective</a>
<a href={AiGovernancePoliciesAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">AI Gov</a>
<a href={LearningDashboardAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Learning</a>
<div class="pt-4 pb-1 px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider">Platform</div>
<a href={WidgetAdapterSpecsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Adapters</a>
<a href={CrossHubPropagationsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Propagations</a>
<a href={OperationalReviewBoardAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Ops Review</a>
<a href={FederatedGovernanceDashboardAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Federation</a>
<a href={FederatedPolicyOverlaysAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Policies</a>
<a href={ArchiveRecordsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Archive</a>
<div class="pt-4 pb-1 px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider">Registry</div>
<a href={WidgetTypeRegistryAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Registries</a>
<a href={HubCapabilityManifestsAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Extensions</a>
<div class="pt-4 pb-1 px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider">API &amp; Market</div>
<a href={ApiConsumersAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">API Consumers</a>
<a href={ShowApiDashboardAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">API Dashboard</a>
<a href={HubRegistryAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Hub Registry</a>
<a href={MarketplaceDashboardAction} class="block px-3 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100">Marketplace</a>
</nav>
</aside>
<main class="px-8 py-8 overflow-y-auto" style="flex:1">
<div class="max-w-5xl">
{inner}
</div>
</main>
</div>
</body>
</html>
|]