Files
inter-hub/Web/Controller/FederatedGovernance.hs
Bernd Worsch 9265ca2d9c 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

44 lines
1.9 KiB
Haskell

module Web.Controller.FederatedGovernance where
import Web.Types
import Web.View.FederatedGovernance.Dashboard
import Generated.Types
import IHP.Prelude
import IHP.ControllerPrelude
import Data.Time.Clock (addUTCTime, getCurrentTime)
import Data.Aeson (decode)
import qualified Data.ByteString.Lazy as LBS
import Data.Text.Encoding (encodeUtf8)
instance Controller FederatedGovernanceController where
beforeAction = ensureIsUser
action FederatedGovernanceDashboardAction = autoRefresh do
hubs <- query @Hub |> orderByAsc #name |> fetch
widgets <- query @Widget |> fetch
ownerships <- query @WidgetOwnership |> fetch
rules <- query @HubRoutingRule |> filterWhere (#status, "active") |> fetch
now <- getCurrentTime
let thirtyDaysAgo = addUTCTime (negate $ 30 * 86400) now
ninetyDaysAgo = addUTCTime (negate $ 90 * 86400) now
-- Candidates routed cross-hub in last 30 days
routedCandidates <- sqlQuery
"SELECT * FROM requirement_candidates WHERE routed_to_hub_id IS NOT NULL AND created_at >= ?"
(Only thirtyDaysAgo)
-- Active overlays
overlays <- query @FederatedPolicyOverlay |> filterWhere (#status, "active") |> fetch
-- All decisions for policy compliance check
allDecisions <- query @DecisionRecord |> fetch
allPolicies <- query @PolicyReference |> fetch
-- Active stewardship roles
stewards <- query @StewardshipRole
|> filterWhereSql (#revokedAt, "IS NULL")
|> fetch
-- Archive records in last 90 days
recentArchives <- sqlQuery
"SELECT * FROM archive_records WHERE archived_at >= ?"
(Only ninetyDaysAgo)
render FederatedGovernanceDashboardView
{ hubs, widgets, ownerships, rules, routedCandidates
, overlays, allDecisions, allPolicies, stewards, recentArchives }