From cf4d2ae16b4e4e6e6dbf7d116014966ff118eb15 Mon Sep 17 00:00:00 2001
From: defiQUG
Date: Thu, 30 Jul 2026 20:29:51 -0700
Subject: [PATCH] Add GFTD portal marketplace discovery
---
.../marketplace/entitlements/[slug]/page.tsx | 90 ++++++++++++++++++-
portal/src/app/marketplace/page.tsx | 5 +-
portal/src/lib/gftd-marketplace.ts | 11 +++
3 files changed, 103 insertions(+), 3 deletions(-)
create mode 100644 portal/src/lib/gftd-marketplace.ts
diff --git a/portal/src/app/marketplace/entitlements/[slug]/page.tsx b/portal/src/app/marketplace/entitlements/[slug]/page.tsx
index 4ed4a69..1eeb812 100644
--- a/portal/src/app/marketplace/entitlements/[slug]/page.tsx
+++ b/portal/src/app/marketplace/entitlements/[slug]/page.tsx
@@ -6,6 +6,7 @@ import { signIn, useSession } from 'next-auth/react';
import { useCallback, useEffect, useState } from 'react';
import { partnerStackServices } from '@/lib/corporate-site-data';
+import { gftdMarketplaceService } from '@/lib/gftd-marketplace';
type ProductInfo = {
slug: string;
@@ -38,7 +39,40 @@ export default function MarketplaceEntitlementPage() {
const [message, setMessage] = useState(null);
const [error, setError] = useState(null);
- const partnerMeta = partnerStackServices.find((s) => s.href?.includes(slug));
+ const partnerMeta = [...partnerStackServices, gftdMarketplaceService].find((s) => s.href?.includes(slug));
+ const isGftd = slug === 'phoenix-gftd-directory';
+
+ const gftdSubscriptionTiers = [
+ {
+ name: 'Preview',
+ description: 'Evaluators, partners, and early adopters with public-safe demo data only.',
+ limits: 'No live restricted data, no authority claims, no production SLA.',
+ },
+ {
+ name: 'Professional',
+ description: 'Operators, integrators, and compliance teams.',
+ limits: 'Approved sources only, role-based access, bounded query depth, and rate limits.',
+ },
+ {
+ name: 'Institutional',
+ description: 'Regulated firms, marketplaces, and service providers.',
+ limits: 'Contractual use terms, approval gates, and stricter access control.',
+ },
+ {
+ name: 'Enterprise',
+ description: 'Market operators and platform teams.',
+ limits: 'Custom SLAs, tenant-specific redaction policies, and governance reporting.',
+ },
+ ];
+
+ const gftdPersonaNeeds = [
+ 'Compliance analyst: rights status, publication boundaries, and audit trails.',
+ 'Integration engineer: stable API, live adapters, and predictable responses.',
+ 'Marketplace operator: packaging, tiers, onboarding, and feature gating.',
+ 'Legal counsel: evidence refs, disclaimers, and approval records.',
+ 'Operations / SRE: health checks, observability snapshots, and runtime limits.',
+ 'Institutional customer: approved data, support, and acceptance artifacts.',
+ ];
const loadProduct = useCallback(async () => {
const res = await fetch(`/api/marketplace/products/${slug}`, {
@@ -144,6 +178,51 @@ export default function MarketplaceEntitlementPage() {
{product?.shortDescription || product?.description || partnerMeta?.description}
+ {isGftd ? (
+
+
+ GFTD Directory
+
+ Rights-aware entity intelligence
+
+ Access approved live source lanes, redacted public-safe outputs, bounded observability,
+ and evidence-backed operational controls through Sankofa Marketplace.
+
+
+
+
+
+ Subscription tiers
+
+
+ {gftdSubscriptionTiers.map((tier) => (
+
+
+ {tier.name}
+
+
{tier.description}
+
{tier.limits}
+
+ ))}
+
+
+
+
+
+ User needs by persona
+
+
+ {gftdPersonaNeeds.map((item) => (
+ -
+ {item}
+
+ ))}
+
+
+
+
+ ) : null}
+
{partnerMeta?.serviceUrl ? (
Service endpoint:{' '}
@@ -192,7 +271,7 @@ export default function MarketplaceEntitlementPage() {
onClick={handleSubscribe}
className="mt-6 rounded-lg bg-teal-600 px-5 py-2.5 text-sm font-medium text-white hover:bg-teal-500 disabled:opacity-60"
>
- {submitting ? 'Submitting…' : 'Request subscription'}
+ {submitting ? 'Submitting…' : isGftd ? 'Request GFTD access' : 'Request subscription'}
)}
@@ -200,6 +279,13 @@ export default function MarketplaceEntitlementPage() {
{error &&
{error}
}
+ {isGftd ? (
+
+ GFTD is rights-aware entity intelligence, not legal authority, not a payment rail, and not a
+ license to republish restricted data.
+
+ ) : null}
+
Contract/PO-first billing — automated Stripe checkout is on the roadmap. Operator Keycloak grants
run via grant-marketplace-entitlements-keycloak.sh.
diff --git a/portal/src/app/marketplace/page.tsx b/portal/src/app/marketplace/page.tsx
index 5e1a1b5..bd46d42 100644
--- a/portal/src/app/marketplace/page.tsx
+++ b/portal/src/app/marketplace/page.tsx
@@ -10,6 +10,7 @@ import {
platformServices,
productDivisions,
} from '@/lib/corporate-site-data';
+import { gftdMarketplaceService } from '@/lib/gftd-marketplace';
export const metadata = {
title: 'Marketplace — Sankofa Phoenix',
@@ -17,6 +18,8 @@ export const metadata = {
};
export default function MarketplacePage() {
+ const marketplacePartnerServices = [...partnerStackServices, gftdMarketplaceService];
+
return (
@@ -97,7 +100,7 @@ export default function MarketplacePage() {
B2B, CTI, Chain 138 onboarding, and X-Road — provisioned via Phoenix marketplace entitlements.
- {partnerStackServices.map((service) => (
+ {marketplacePartnerServices.map((service) => (