diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..4f067f6
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "DBIS"]
+ path = DBIS
+ url = https://gitea.d-bis.org/Gov_Web_Portals/DBIS.git
+[submodule "ICCC"]
+ path = ICCC
+ url = https://gitea.d-bis.org/Gov_Web_Portals/ICCC.git
+[submodule "OMNL"]
+ path = OMNL
+ url = https://gitea.d-bis.org/Gov_Web_Portals/OMNL.git
+[submodule "XOM"]
+ path = XOM
+ url = https://gitea.d-bis.org/Gov_Web_Portals/XOM.git
diff --git a/DBIS b/DBIS
new file mode 160000
index 0000000..7cc2042
--- /dev/null
+++ b/DBIS
@@ -0,0 +1 @@
+Subproject commit 7cc20421015f20de2d86f28a68d40db2b20e9a63
diff --git a/DBIS/.env.example b/DBIS/.env.example
deleted file mode 100644
index 8e389e0..0000000
--- a/DBIS/.env.example
+++ /dev/null
@@ -1,8 +0,0 @@
-# Next.js
-NEXTAUTH_URL=http://localhost:3000
-
-# OIDC / OAuth 2.0 (placeholder until identity provider is configured)
-# OIDC_ISSUER=
-# OIDC_CLIENT_ID=
-# OIDC_CLIENT_SECRET=
-# OIDC_REDIRECT_URI=
diff --git a/DBIS/.eslintrc.cjs b/DBIS/.eslintrc.cjs
deleted file mode 100644
index 53dff50..0000000
--- a/DBIS/.eslintrc.cjs
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @type { import("eslint").Linter.Config } */
-module.exports = {
- root: true,
- extends: ["../.eslintrc.cjs", "next/core-web-vitals"],
-};
diff --git a/DBIS/.gitignore b/DBIS/.gitignore
deleted file mode 100644
index 71f76af..0000000
--- a/DBIS/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-node_modules/
-.next/
-out/
-dist/
-.env
-.env.local
-.env.*.local
diff --git a/DBIS/README.md b/DBIS/README.md
deleted file mode 100644
index 2d6b6d2..0000000
--- a/DBIS/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# DBIS Portal
-
-Portal for the **Digital Bank of International Settlements**.
-
-**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/DBIS.git Next-generation web application following the shared tech stack and policies.
-
-## Run locally
-
-```bash
-pnpm install
-pnpm dev
-```
-
-Open [http://localhost:3000](http://localhost:3000).
-
-## Environment
-
-Copy `.env.example` to `.env.local` and set values. No secrets in repo.
-
-## Standards
-
-- [TECH_STACK.md](../TECH_STACK.md)
-- [TECH_POLICIES.md](../TECH_POLICIES.md)
-- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md)
-- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md)
-
-## Structure
-
-Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Financial Bulletins, Monetary Operations.
diff --git a/DBIS/app/(auth)/login/page.tsx b/DBIS/app/(auth)/login/page.tsx
deleted file mode 100644
index 48101a9..0000000
--- a/DBIS/app/(auth)/login/page.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-"use client";
-
-import { Suspense } from "react";
-import { useSearchParams } from "next/navigation";
-import Link from "next/link";
-
-function LoginForm() {
- const searchParams = useSearchParams();
- const returnUrl = searchParams.get("returnUrl") ?? "/dashboard";
-
- return (
-
-
Sign in
-
- Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured.
-
-
-
-
- Return to previous page
-
-
-
- );
-}
-
-export default function LoginPage() {
- return (
- Loading...}>
-
-
- );
-}
diff --git a/DBIS/app/(auth)/logout/page.tsx b/DBIS/app/(auth)/logout/page.tsx
deleted file mode 100644
index fd763a6..0000000
--- a/DBIS/app/(auth)/logout/page.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-
-import { useEffect } from "react";
-import Link from "next/link";
-
-export default function LogoutPage() {
- useEffect(() => {
- document.cookie = "portal-role=; path=/; max-age=0";
- }, []);
-
- return (
-
-
Signed out
-
You have been signed out.
-
- Return to home
-
-
- );
-}
diff --git a/DBIS/app/(public)/about/page.tsx b/DBIS/app/(public)/about/page.tsx
deleted file mode 100644
index 0b87c58..0000000
--- a/DBIS/app/(public)/about/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AboutPage() {
- return (
-
-
Mandate
-
About the Digital Bank of International Settlements.
-
- );
-}
diff --git a/DBIS/app/(public)/accreditation/page.tsx b/DBIS/app/(public)/accreditation/page.tsx
deleted file mode 100644
index c5e95d2..0000000
--- a/DBIS/app/(public)/accreditation/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AccreditationPage() {
- return (
-
-
Accreditation
-
Accreditation and credentials.
-
- );
-}
diff --git a/DBIS/app/(public)/contact/page.tsx b/DBIS/app/(public)/contact/page.tsx
deleted file mode 100644
index 7bb6a85..0000000
--- a/DBIS/app/(public)/contact/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ContactPage() {
- return (
-
-
Contact
-
General contact and enquiries.
-
- );
-}
diff --git a/DBIS/app/(public)/departments/page.tsx b/DBIS/app/(public)/departments/page.tsx
deleted file mode 100644
index ed01731..0000000
--- a/DBIS/app/(public)/departments/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DepartmentsPage() {
- return (
-
-
Departments
-
Mission departments and programs.
-
- );
-}
diff --git a/DBIS/app/(public)/documents/page.tsx b/DBIS/app/(public)/documents/page.tsx
deleted file mode 100644
index c641e1d..0000000
--- a/DBIS/app/(public)/documents/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DocumentsPage() {
- return (
-
-
Documents
-
Library, standards, and directives.
-
- );
-}
diff --git a/DBIS/app/(public)/governance/page.tsx b/DBIS/app/(public)/governance/page.tsx
deleted file mode 100644
index 8cf0212..0000000
--- a/DBIS/app/(public)/governance/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function GovernancePage() {
- return (
-
-
Governance
-
Charters, instruments, and governance.
-
- );
-}
diff --git a/DBIS/app/(public)/leadership/page.tsx b/DBIS/app/(public)/leadership/page.tsx
deleted file mode 100644
index ff1f679..0000000
--- a/DBIS/app/(public)/leadership/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function LeadershipPage() {
- return (
-
-
Leadership
-
Executive leadership and secretariat.
-
- );
-}
diff --git a/DBIS/app/(public)/membership/page.tsx b/DBIS/app/(public)/membership/page.tsx
deleted file mode 100644
index cf191d0..0000000
--- a/DBIS/app/(public)/membership/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function MembershipPage() {
- return (
-
-
Membership
-
Member directory and accreditation.
-
- );
-}
diff --git a/DBIS/app/(public)/news/page.tsx b/DBIS/app/(public)/news/page.tsx
deleted file mode 100644
index 57d0061..0000000
--- a/DBIS/app/(public)/news/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function NewsPage() {
- return (
-
-
News
-
News and announcements.
-
- );
-}
diff --git a/DBIS/app/(public)/org-chart/page.tsx b/DBIS/app/(public)/org-chart/page.tsx
deleted file mode 100644
index e01d431..0000000
--- a/DBIS/app/(public)/org-chart/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function OrgChartPage() {
- return (
-
-
Org Chart
-
Organizational structure.
-
- );
-}
diff --git a/DBIS/app/(public)/programs/page.tsx b/DBIS/app/(public)/programs/page.tsx
deleted file mode 100644
index 57d0bb0..0000000
--- a/DBIS/app/(public)/programs/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ProgramsPage() {
- return (
-
-
Programs
-
Programs and initiatives.
-
- );
-}
diff --git a/DBIS/app/(public)/publications/page.tsx b/DBIS/app/(public)/publications/page.tsx
deleted file mode 100644
index 6b329f6..0000000
--- a/DBIS/app/(public)/publications/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function PublicationsPage() {
- return (
-
-
Publications
-
Publications and reports.
-
- );
-}
diff --git a/DBIS/app/(public)/regions/page.tsx b/DBIS/app/(public)/regions/page.tsx
deleted file mode 100644
index 66978cc..0000000
--- a/DBIS/app/(public)/regions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RegionsPage() {
- return (
-
-
Regional Offices
-
Americas, EMEA, APAC delegations and field missions.
-
- );
-}
diff --git a/DBIS/app/(public)/standards/page.tsx b/DBIS/app/(public)/standards/page.tsx
deleted file mode 100644
index 9327ef0..0000000
--- a/DBIS/app/(public)/standards/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function StandardsPage() {
- return (
-
-
Standards
-
Standards and codes.
-
- );
-}
diff --git a/DBIS/app/api/auth/mock-login/route.ts b/DBIS/app/api/auth/mock-login/route.ts
deleted file mode 100644
index 57f672f..0000000
--- a/DBIS/app/api/auth/mock-login/route.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-
-export async function POST(request: NextRequest) {
- const form = await request.formData();
- const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard";
- const role = (form.get("role") as string) ?? "member";
- const res = NextResponse.redirect(new URL(returnUrl, request.url));
- res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 });
- return res;
-}
diff --git a/DBIS/app/apply/page.tsx b/DBIS/app/apply/page.tsx
deleted file mode 100644
index 7ee15cb..0000000
--- a/DBIS/app/apply/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ApplyPage() {
- return (
-
-
Apply
-
Apply for membership or accreditation.
-
- );
-}
diff --git a/DBIS/app/dashboard/layout.tsx b/DBIS/app/dashboard/layout.tsx
deleted file mode 100644
index 680435b..0000000
--- a/DBIS/app/dashboard/layout.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import Link from "next/link";
-import type { ReactNode } from "react";
-
-export default function DashboardLayout({ children }: { children: ReactNode }) {
- return (
-
-
-
{children}
-
- );
-}
diff --git a/DBIS/app/dashboard/page.tsx b/DBIS/app/dashboard/page.tsx
deleted file mode 100644
index 199cd04..0000000
--- a/DBIS/app/dashboard/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DashboardPage() {
- return (
-
-
Dashboard
-
Role-based dashboard.
-
- );
-}
diff --git a/DBIS/app/dashboard/requests/page.tsx b/DBIS/app/dashboard/requests/page.tsx
deleted file mode 100644
index eb94812..0000000
--- a/DBIS/app/dashboard/requests/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RequestsPage() {
- return (
-
-
My requests
-
Track your requests.
-
- );
-}
diff --git a/DBIS/app/dashboard/submissions/page.tsx b/DBIS/app/dashboard/submissions/page.tsx
deleted file mode 100644
index dc57c54..0000000
--- a/DBIS/app/dashboard/submissions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SubmissionsPage() {
- return (
-
-
My submissions
-
Track your submissions and status.
-
- );
-}
diff --git a/DBIS/app/departments/monetary-operations/page.tsx b/DBIS/app/departments/monetary-operations/page.tsx
deleted file mode 100644
index b92072a..0000000
--- a/DBIS/app/departments/monetary-operations/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function MonetaryOperationsPage() {
- return (
-
-
Monetary Operations
-
Digital reserves and monetary operations.
-
- );
-}
diff --git a/DBIS/app/documents/bulletins/page.tsx b/DBIS/app/documents/bulletins/page.tsx
deleted file mode 100644
index ce3a40d..0000000
--- a/DBIS/app/documents/bulletins/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function BulletinsPage() {
- return (
-
-
Financial Bulletins
-
DBIS financial bulletins and reports.
-
- );
-}
diff --git a/DBIS/app/globals.css b/DBIS/app/globals.css
deleted file mode 100644
index b5c61c9..0000000
--- a/DBIS/app/globals.css
+++ /dev/null
@@ -1,3 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
diff --git a/DBIS/app/layout.tsx b/DBIS/app/layout.tsx
deleted file mode 100644
index b847156..0000000
--- a/DBIS/app/layout.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { Metadata } from "next";
-import type { ReactNode } from "react";
-import "./globals.css";
-import { Header } from "@/components/layout/Header";
-import { Footer } from "@/components/layout/Footer";
-
-export const metadata: Metadata = {
- title: "Digital Bank of International Settlements",
- description: "Official portal of the Digital Bank of International Settlements",
-};
-
-export default function RootLayout({
- children,
-}: Readonly<{
- children: ReactNode;
-}>) {
- return (
-
-
-
- Skip to main content
-
-
-
- {children}
-
-
-
-
- );
-}
diff --git a/DBIS/app/membership/renewals/page.tsx b/DBIS/app/membership/renewals/page.tsx
deleted file mode 100644
index 79e5a75..0000000
--- a/DBIS/app/membership/renewals/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RenewalsPage() {
- return (
-
-
Renewals and Attestations
-
Annual renewals for members.
-
- );
-}
diff --git a/DBIS/app/page.tsx b/DBIS/app/page.tsx
deleted file mode 100644
index b0c3be8..0000000
--- a/DBIS/app/page.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-export default function HomePage() {
- return (
-
-
Digital Bank of International Settlements
-
- Welcome to the official portal. Explore mandate, governance, documents, and services.
-
-
-
- );
-}
diff --git a/DBIS/app/report/page.tsx b/DBIS/app/report/page.tsx
deleted file mode 100644
index 6ae4c22..0000000
--- a/DBIS/app/report/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ReportPage() {
- return (
-
-
Report
-
Report incidents or compliance matters.
-
- );
-}
diff --git a/DBIS/app/request/page.tsx b/DBIS/app/request/page.tsx
deleted file mode 100644
index 6e653db..0000000
--- a/DBIS/app/request/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RequestPage() {
- return (
-
-
Request
-
Request documents or support.
-
- );
-}
diff --git a/DBIS/app/submit/page.tsx b/DBIS/app/submit/page.tsx
deleted file mode 100644
index 62e1cba..0000000
--- a/DBIS/app/submit/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SubmitPage() {
- return (
-
-
Submit
-
Submission portal.
-
- );
-}
diff --git a/DBIS/app/transparency/audit/page.tsx b/DBIS/app/transparency/audit/page.tsx
deleted file mode 100644
index 5fe7056..0000000
--- a/DBIS/app/transparency/audit/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AuditPage() {
- return (
-
-
Audit Reports
-
Audit reports and findings tracker.
-
- );
-}
diff --git a/DBIS/app/transparency/data-protection/page.tsx b/DBIS/app/transparency/data-protection/page.tsx
deleted file mode 100644
index b2454b3..0000000
--- a/DBIS/app/transparency/data-protection/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DataProtectionPage() {
- return (
-
-
Data Protection and Records
-
Records retention and data protection.
-
- );
-}
diff --git a/DBIS/app/transparency/ethics/page.tsx b/DBIS/app/transparency/ethics/page.tsx
deleted file mode 100644
index ff5b47d..0000000
--- a/DBIS/app/transparency/ethics/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function EthicsPage() {
- return (
-
-
Ethics and Conduct
-
Ethics and conduct policies.
-
- );
-}
diff --git a/DBIS/app/transparency/page.tsx b/DBIS/app/transparency/page.tsx
deleted file mode 100644
index f676261..0000000
--- a/DBIS/app/transparency/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function TransparencyPage() {
- return (
-
-
Transparency
-
Audit, ethics, whistleblower, sanctions, and data protection.
-
- );
-}
diff --git a/DBIS/app/transparency/sanctions/page.tsx b/DBIS/app/transparency/sanctions/page.tsx
deleted file mode 100644
index adf23fe..0000000
--- a/DBIS/app/transparency/sanctions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SanctionsPage() {
- return (
-
-
Sanctions and Restricted Parties
-
Eligibility and restricted parties.
-
- );
-}
diff --git a/DBIS/app/transparency/whistleblower/page.tsx b/DBIS/app/transparency/whistleblower/page.tsx
deleted file mode 100644
index 5d9a692..0000000
--- a/DBIS/app/transparency/whistleblower/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function WhistleblowerPage() {
- return (
-
-
Whistleblower Intake
-
Secure anonymous reporting.
-
- );
-}
diff --git a/DBIS/components/layout/Footer.tsx b/DBIS/components/layout/Footer.tsx
deleted file mode 100644
index e337806..0000000
--- a/DBIS/components/layout/Footer.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import Link from "next/link";
-import { navItems } from "@/lib/nav-config";
-
-const footerLinks = [
- { label: "About", href: "/about" },
- { label: "Documents", href: "/documents" },
- { label: "Transparency", href: "/transparency" },
- { label: "Contact", href: "/contact" },
- { label: "Regional Offices", href: "/regions" },
-];
-
-function flatNavItems(items: typeof navItems): { label: string; href: string }[] {
- const out: { label: string; href: string }[] = [];
- for (const item of items) {
- if (item.children) {
- for (const c of item.children) out.push({ label: c.label, href: c.href });
- } else {
- out.push({ label: item.label, href: item.href });
- }
- }
- return out;
-}
-
-export function Footer() {
- const flat = flatNavItems(navItems);
- const keyLinks = footerLinks.length ? footerLinks : flat.slice(0, 6);
-
- return (
-
- );
-}
diff --git a/DBIS/components/layout/Header.tsx b/DBIS/components/layout/Header.tsx
deleted file mode 100644
index 7f5dbf9..0000000
--- a/DBIS/components/layout/Header.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { useState } from "react";
-import { navItems } from "@/lib/nav-config";
-import { NavDropdown } from "./NavDropdown";
-import { MobileNav } from "./MobileNav";
-
-export function Header() {
- const [mobileOpen, setMobileOpen] = useState(false);
-
- return (
-
-
-
- DBIS
-
-
-
-
- Sign in
-
-
-
-
- setMobileOpen(false)} />
-
- );
-}
diff --git a/DBIS/components/layout/MobileNav.tsx b/DBIS/components/layout/MobileNav.tsx
deleted file mode 100644
index 6b94745..0000000
--- a/DBIS/components/layout/MobileNav.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import type { NavItem } from "@public-web-portals/shared";
-
-export function MobileNav({
- items,
- open,
- onClose,
-}: {
- items: NavItem[];
- open: boolean;
- onClose: () => void;
-}) {
- if (!open) return null;
-
- return (
-
- );
-}
diff --git a/DBIS/components/layout/NavDropdown.tsx b/DBIS/components/layout/NavDropdown.tsx
deleted file mode 100644
index d9c6b1b..0000000
--- a/DBIS/components/layout/NavDropdown.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { useState, useRef, useEffect } from "react";
-import type { NavItem } from "@public-web-portals/shared";
-
-export function NavDropdown({ item }: { item: NavItem }) {
- const [open, setOpen] = useState(false);
- const ref = useRef(null);
-
- useEffect(() => {
- function handleClickOutside(event: MouseEvent) {
- if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
- }
- document.addEventListener("mousedown", handleClickOutside);
- return () => document.removeEventListener("mousedown", handleClickOutside);
- }, []);
-
- return (
-
-
-
-
- );
-}
diff --git a/DBIS/lib/auth.ts b/DBIS/lib/auth.ts
deleted file mode 100644
index 1077579..0000000
--- a/DBIS/lib/auth.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { SessionOrNull } from "@public-web-portals/shared";
-
-/**
- * Placeholder session. Replace with OIDC/OAuth 2.0 when identity provider is configured.
- * TECH_POLICIES: use httpOnly cookies / secure token storage.
- */
-export async function getSession(): Promise {
- // TODO: read session from cookie or header (e.g. NextAuth, OIDC)
- return null;
-}
diff --git a/DBIS/lib/nav-config.ts b/DBIS/lib/nav-config.ts
deleted file mode 100644
index 36906b8..0000000
--- a/DBIS/lib/nav-config.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { getNavForPortal } from "@public-web-portals/shared";
-
-export const portalId = "DBIS" as const;
-export const navItems = getNavForPortal(portalId);
diff --git a/DBIS/lib/rbac.ts b/DBIS/lib/rbac.ts
deleted file mode 100644
index 75a5b51..0000000
--- a/DBIS/lib/rbac.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import type { Role } from "@public-web-portals/shared";
-
-/** Route prefixes that require any authenticated role */
-const protectedPrefixes = [
- "/dashboard",
- "/submit",
- "/apply",
- "/report",
- "/request",
- "/membership/renewals",
-];
-
-/** Route prefixes that require admin role */
-const adminOnlyPrefixes = ["/dashboard/admin"];
-
-/** Routes that are always public (no auth) */
-const publicPaths = [
- "/",
- "/about",
- "/governance",
- "/leadership",
- "/org-chart",
- "/departments",
- "/programs",
- "/membership",
- "/accreditation",
- "/documents",
- "/standards",
- "/news",
- "/publications",
- "/contact",
- "/regions",
- "/transparency",
- "/login",
- "/logout",
-];
-
-function pathIsPublic(pathname: string): boolean {
- if (publicPaths.includes(pathname)) return true;
- if (pathname.startsWith("/transparency/")) return true;
- return false;
-}
-
-function pathIsProtected(pathname: string): boolean {
- return protectedPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
-}
-
-function pathIsAdminOnly(pathname: string): boolean {
- return adminOnlyPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
-}
-
-export function canAccess(pathname: string, role: Role | null): boolean {
- if (pathIsPublic(pathname)) return true;
- if (role == null) return false;
- if (pathIsAdminOnly(pathname)) return role === "admin";
- if (pathIsProtected(pathname)) return true;
- return false;
-}
-
-export function requiresAuth(pathname: string): boolean {
- return pathIsProtected(pathname);
-}
-
-export function requiresAdmin(pathname: string): boolean {
- return pathIsAdminOnly(pathname);
-}
diff --git a/DBIS/middleware.ts b/DBIS/middleware.ts
deleted file mode 100644
index a1e26cd..0000000
--- a/DBIS/middleware.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { NextResponse } from "next/server";
-import type { NextRequest } from "next/server";
-import { canAccess, requiresAuth, requiresAdmin } from "./lib/rbac";
-import type { Role } from "@public-web-portals/shared";
-
-const LOGIN = "/login";
-
-function getRoleFromCookie(request: NextRequest): Role | null {
- const role = request.cookies.get("portal-role")?.value;
- if (!role) return null;
- const valid: Role[] = ["member", "judge", "clerk", "diplomat", "donor", "staff", "admin"];
- return valid.includes(role as Role) ? (role as Role) : null;
-}
-
-export function middleware(request: NextRequest) {
- const pathname = request.nextUrl.pathname;
- const role = getRoleFromCookie(request);
-
- if (requiresAdmin(pathname) && role !== "admin") {
- return NextResponse.redirect(new URL("/dashboard", request.url));
- }
-
- if (requiresAuth(pathname)) {
- if (role == null) {
- const url = new URL(LOGIN, request.url);
- url.searchParams.set("returnUrl", pathname);
- return NextResponse.redirect(url);
- }
- if (!canAccess(pathname, role)) {
- return NextResponse.redirect(new URL("/dashboard", request.url));
- }
- }
-
- return NextResponse.next();
-}
-
-export const config = {
- matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
-};
diff --git a/DBIS/next-env.d.ts b/DBIS/next-env.d.ts
deleted file mode 100644
index 40c3d68..0000000
--- a/DBIS/next-env.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/DBIS/next.config.js b/DBIS/next.config.js
deleted file mode 100644
index d0d6b18..0000000
--- a/DBIS/next.config.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @type { import('next').NextConfig } */
-const nextConfig = {
- transpilePackages: ["@public-web-portals/shared"],
- async headers() {
- return [
- {
- source: "/:path*",
- headers: [
- { key: "X-Frame-Options", value: "DENY" },
- { key: "X-Content-Type-Options", value: "nosniff" },
- { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
- {
- key: "Content-Security-Policy",
- value: [
- "default-src 'self'",
- "script-src 'self'",
- "style-src 'self' 'unsafe-inline'",
- "img-src 'self' data: https:",
- "font-src 'self'",
- "connect-src 'self'",
- "frame-ancestors 'none'",
- "base-uri 'self'",
- "form-action 'self'",
- ].join("; "),
- },
- ],
- },
- ];
- },
-};
-
-module.exports = nextConfig;
diff --git a/DBIS/package.json b/DBIS/package.json
deleted file mode 100644
index 8f34394..0000000
--- a/DBIS/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "name": "portal-dbis",
- "version": "0.1.0",
- "private": true,
- "scripts": {
- "dev": "next dev --port 3000",
- "build": "next build",
- "start": "next start --port 3000",
- "lint": "eslint . --max-warnings 0 --config ../.eslintrc.cjs",
- "typecheck": "tsc --noEmit"
- },
- "dependencies": {
- "@public-web-portals/shared": "workspace:*",
- "next": "^14.2.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- },
- "devDependencies": {
- "@types/node": "^20.10.0",
- "@types/react": "^18.2.0",
- "@types/react-dom": "^18.2.0",
- "autoprefixer": "^10.4.0",
- "eslint": "^8.56.0",
- "eslint-config-next": "^14.2.0",
- "postcss": "^8.4.0",
- "tailwindcss": "^3.4.0",
- "typescript": "^5.3.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
-}
diff --git a/DBIS/postcss.config.js b/DBIS/postcss.config.js
deleted file mode 100644
index 12a703d..0000000
--- a/DBIS/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/DBIS/tailwind.config.ts b/DBIS/tailwind.config.ts
deleted file mode 100644
index aae1628..0000000
--- a/DBIS/tailwind.config.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { Config } from "tailwindcss";
-import { designTokens } from "@public-web-portals/shared";
-
-const config: Config = {
- content: [
- "./app/**/*.{js,ts,jsx,tsx,mdx}",
- "./components/**/*.{js,ts,jsx,tsx,mdx}",
- ],
- theme: {
- extend: designTokens as Record,
- },
- plugins: [],
-};
-
-export default config;
diff --git a/DBIS/tsconfig.json b/DBIS/tsconfig.json
deleted file mode 100644
index cd32290..0000000
--- a/DBIS/tsconfig.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "extends": "../tsconfig.base.json",
- "compilerOptions": {
- "plugins": [
- {
- "name": "next"
- }
- ],
- "module": "ESNext",
- "moduleResolution": "bundler",
- "jsx": "preserve",
- "noEmit": true,
- "incremental": true,
- "paths": {
- "@/*": [
- "./*"
- ]
- },
- "allowJs": true
- },
- "include": [
- "next-env.d.ts",
- "**/*.ts",
- "**/*.tsx",
- ".next/types/**/*.ts"
- ],
- "exclude": [
- "node_modules"
- ]
-}
diff --git a/ICCC b/ICCC
new file mode 160000
index 0000000..a488346
--- /dev/null
+++ b/ICCC
@@ -0,0 +1 @@
+Subproject commit a488346ea21d4b884d4834d92ca3824858dc2e29
diff --git a/ICCC/.env.example b/ICCC/.env.example
deleted file mode 100644
index 8e389e0..0000000
--- a/ICCC/.env.example
+++ /dev/null
@@ -1,8 +0,0 @@
-# Next.js
-NEXTAUTH_URL=http://localhost:3000
-
-# OIDC / OAuth 2.0 (placeholder until identity provider is configured)
-# OIDC_ISSUER=
-# OIDC_CLIENT_ID=
-# OIDC_CLIENT_SECRET=
-# OIDC_REDIRECT_URI=
diff --git a/ICCC/.eslintrc.cjs b/ICCC/.eslintrc.cjs
deleted file mode 100644
index 53dff50..0000000
--- a/ICCC/.eslintrc.cjs
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @type { import("eslint").Linter.Config } */
-module.exports = {
- root: true,
- extends: ["../.eslintrc.cjs", "next/core-web-vitals"],
-};
diff --git a/ICCC/.gitignore b/ICCC/.gitignore
deleted file mode 100644
index 71f76af..0000000
--- a/ICCC/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-node_modules/
-.next/
-out/
-dist/
-.env
-.env.local
-.env.*.local
diff --git a/ICCC/README.md b/ICCC/README.md
deleted file mode 100644
index 8f2dc25..0000000
--- a/ICCC/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# ICCC Portal
-
-Portal for the **International Criminal Court of Commerce**.
-
-**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/ICCC.git Next-generation web application following the shared tech stack and policies.
-
-## Run locally
-
-```bash
-pnpm install
-pnpm dev
-```
-
-Open [http://localhost:3000](http://localhost:3000).
-
-## Environment
-
-Copy `.env.example` to `.env.local` and set values. No secrets in repo.
-
-## Standards
-
-- [TECH_STACK.md](../TECH_STACK.md)
-- [TECH_POLICIES.md](../TECH_POLICIES.md)
-- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md)
-- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md)
-
-## Structure
-
-Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Case Law, Registry, Chambers, Judgments.
diff --git a/ICCC/app/(auth)/login/page.tsx b/ICCC/app/(auth)/login/page.tsx
deleted file mode 100644
index 48101a9..0000000
--- a/ICCC/app/(auth)/login/page.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-"use client";
-
-import { Suspense } from "react";
-import { useSearchParams } from "next/navigation";
-import Link from "next/link";
-
-function LoginForm() {
- const searchParams = useSearchParams();
- const returnUrl = searchParams.get("returnUrl") ?? "/dashboard";
-
- return (
-
-
Sign in
-
- Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured.
-
-
-
-
- Return to previous page
-
-
-
- );
-}
-
-export default function LoginPage() {
- return (
- Loading...}>
-
-
- );
-}
diff --git a/ICCC/app/(auth)/logout/page.tsx b/ICCC/app/(auth)/logout/page.tsx
deleted file mode 100644
index fd763a6..0000000
--- a/ICCC/app/(auth)/logout/page.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-
-import { useEffect } from "react";
-import Link from "next/link";
-
-export default function LogoutPage() {
- useEffect(() => {
- document.cookie = "portal-role=; path=/; max-age=0";
- }, []);
-
- return (
-
-
Signed out
-
You have been signed out.
-
- Return to home
-
-
- );
-}
diff --git a/ICCC/app/(public)/about/page.tsx b/ICCC/app/(public)/about/page.tsx
deleted file mode 100644
index 0b87c58..0000000
--- a/ICCC/app/(public)/about/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AboutPage() {
- return (
-
-
Mandate
-
About the Digital Bank of International Settlements.
-
- );
-}
diff --git a/ICCC/app/(public)/accreditation/page.tsx b/ICCC/app/(public)/accreditation/page.tsx
deleted file mode 100644
index c5e95d2..0000000
--- a/ICCC/app/(public)/accreditation/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AccreditationPage() {
- return (
-
-
Accreditation
-
Accreditation and credentials.
-
- );
-}
diff --git a/ICCC/app/(public)/contact/page.tsx b/ICCC/app/(public)/contact/page.tsx
deleted file mode 100644
index 7bb6a85..0000000
--- a/ICCC/app/(public)/contact/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ContactPage() {
- return (
-
-
Contact
-
General contact and enquiries.
-
- );
-}
diff --git a/ICCC/app/(public)/departments/page.tsx b/ICCC/app/(public)/departments/page.tsx
deleted file mode 100644
index ed01731..0000000
--- a/ICCC/app/(public)/departments/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DepartmentsPage() {
- return (
-
-
Departments
-
Mission departments and programs.
-
- );
-}
diff --git a/ICCC/app/(public)/documents/page.tsx b/ICCC/app/(public)/documents/page.tsx
deleted file mode 100644
index c641e1d..0000000
--- a/ICCC/app/(public)/documents/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DocumentsPage() {
- return (
-
-
Documents
-
Library, standards, and directives.
-
- );
-}
diff --git a/ICCC/app/(public)/governance/page.tsx b/ICCC/app/(public)/governance/page.tsx
deleted file mode 100644
index 8cf0212..0000000
--- a/ICCC/app/(public)/governance/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function GovernancePage() {
- return (
-
-
Governance
-
Charters, instruments, and governance.
-
- );
-}
diff --git a/ICCC/app/(public)/leadership/page.tsx b/ICCC/app/(public)/leadership/page.tsx
deleted file mode 100644
index ff1f679..0000000
--- a/ICCC/app/(public)/leadership/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function LeadershipPage() {
- return (
-
-
Leadership
-
Executive leadership and secretariat.
-
- );
-}
diff --git a/ICCC/app/(public)/membership/page.tsx b/ICCC/app/(public)/membership/page.tsx
deleted file mode 100644
index cf191d0..0000000
--- a/ICCC/app/(public)/membership/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function MembershipPage() {
- return (
-
-
Membership
-
Member directory and accreditation.
-
- );
-}
diff --git a/ICCC/app/(public)/news/page.tsx b/ICCC/app/(public)/news/page.tsx
deleted file mode 100644
index 57d0061..0000000
--- a/ICCC/app/(public)/news/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function NewsPage() {
- return (
-
-
News
-
News and announcements.
-
- );
-}
diff --git a/ICCC/app/(public)/org-chart/page.tsx b/ICCC/app/(public)/org-chart/page.tsx
deleted file mode 100644
index e01d431..0000000
--- a/ICCC/app/(public)/org-chart/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function OrgChartPage() {
- return (
-
-
Org Chart
-
Organizational structure.
-
- );
-}
diff --git a/ICCC/app/(public)/programs/page.tsx b/ICCC/app/(public)/programs/page.tsx
deleted file mode 100644
index 57d0bb0..0000000
--- a/ICCC/app/(public)/programs/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ProgramsPage() {
- return (
-
-
Programs
-
Programs and initiatives.
-
- );
-}
diff --git a/ICCC/app/(public)/publications/page.tsx b/ICCC/app/(public)/publications/page.tsx
deleted file mode 100644
index 6b329f6..0000000
--- a/ICCC/app/(public)/publications/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function PublicationsPage() {
- return (
-
-
Publications
-
Publications and reports.
-
- );
-}
diff --git a/ICCC/app/(public)/regions/page.tsx b/ICCC/app/(public)/regions/page.tsx
deleted file mode 100644
index 66978cc..0000000
--- a/ICCC/app/(public)/regions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RegionsPage() {
- return (
-
-
Regional Offices
-
Americas, EMEA, APAC delegations and field missions.
-
- );
-}
diff --git a/ICCC/app/(public)/standards/page.tsx b/ICCC/app/(public)/standards/page.tsx
deleted file mode 100644
index 9327ef0..0000000
--- a/ICCC/app/(public)/standards/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function StandardsPage() {
- return (
-
-
Standards
-
Standards and codes.
-
- );
-}
diff --git a/ICCC/app/api/auth/mock-login/route.ts b/ICCC/app/api/auth/mock-login/route.ts
deleted file mode 100644
index 57f672f..0000000
--- a/ICCC/app/api/auth/mock-login/route.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-
-export async function POST(request: NextRequest) {
- const form = await request.formData();
- const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard";
- const role = (form.get("role") as string) ?? "member";
- const res = NextResponse.redirect(new URL(returnUrl, request.url));
- res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 });
- return res;
-}
diff --git a/ICCC/app/apply/page.tsx b/ICCC/app/apply/page.tsx
deleted file mode 100644
index 7ee15cb..0000000
--- a/ICCC/app/apply/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ApplyPage() {
- return (
-
-
Apply
-
Apply for membership or accreditation.
-
- );
-}
diff --git a/ICCC/app/case-law/page.tsx b/ICCC/app/case-law/page.tsx
deleted file mode 100644
index 4f44594..0000000
--- a/ICCC/app/case-law/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function CaseLawPage() {
- return (
-
-
Case Law
-
Case law and decisions.
-
- );
-}
diff --git a/ICCC/app/chambers/page.tsx b/ICCC/app/chambers/page.tsx
deleted file mode 100644
index f8be373..0000000
--- a/ICCC/app/chambers/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ChambersPage() {
- return (
-
-
Chambers
-
Trial and appeals chambers.
-
- );
-}
diff --git a/ICCC/app/dashboard/layout.tsx b/ICCC/app/dashboard/layout.tsx
deleted file mode 100644
index 680435b..0000000
--- a/ICCC/app/dashboard/layout.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import Link from "next/link";
-import type { ReactNode } from "react";
-
-export default function DashboardLayout({ children }: { children: ReactNode }) {
- return (
-
-
-
{children}
-
- );
-}
diff --git a/ICCC/app/dashboard/page.tsx b/ICCC/app/dashboard/page.tsx
deleted file mode 100644
index 199cd04..0000000
--- a/ICCC/app/dashboard/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DashboardPage() {
- return (
-
-
Dashboard
-
Role-based dashboard.
-
- );
-}
diff --git a/ICCC/app/dashboard/requests/page.tsx b/ICCC/app/dashboard/requests/page.tsx
deleted file mode 100644
index eb94812..0000000
--- a/ICCC/app/dashboard/requests/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RequestsPage() {
- return (
-
-
My requests
-
Track your requests.
-
- );
-}
diff --git a/ICCC/app/dashboard/submissions/page.tsx b/ICCC/app/dashboard/submissions/page.tsx
deleted file mode 100644
index dc57c54..0000000
--- a/ICCC/app/dashboard/submissions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SubmissionsPage() {
- return (
-
-
My submissions
-
Track your submissions and status.
-
- );
-}
diff --git a/ICCC/app/globals.css b/ICCC/app/globals.css
deleted file mode 100644
index b5c61c9..0000000
--- a/ICCC/app/globals.css
+++ /dev/null
@@ -1,3 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
diff --git a/ICCC/app/judgments/page.tsx b/ICCC/app/judgments/page.tsx
deleted file mode 100644
index 32357f7..0000000
--- a/ICCC/app/judgments/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function JudgmentsPage() {
- return (
-
-
Judgments
-
Judgments, orders, and remedies.
-
- );
-}
diff --git a/ICCC/app/layout.tsx b/ICCC/app/layout.tsx
deleted file mode 100644
index af93b88..0000000
--- a/ICCC/app/layout.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { Metadata } from "next";
-import type { ReactNode } from "react";
-import "./globals.css";
-import { Header } from "@/components/layout/Header";
-import { Footer } from "@/components/layout/Footer";
-
-export const metadata: Metadata = {
- title: "International Criminal Court of Commerce",
- description: "Official portal of the International Criminal Court of Commerce",
-};
-
-export default function RootLayout({
- children,
-}: Readonly<{
- children: ReactNode;
-}>) {
- return (
-
-
-
- Skip to main content
-
-
-
- {children}
-
-
-
-
- );
-}
diff --git a/ICCC/app/membership/renewals/page.tsx b/ICCC/app/membership/renewals/page.tsx
deleted file mode 100644
index 79e5a75..0000000
--- a/ICCC/app/membership/renewals/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RenewalsPage() {
- return (
-
-
Renewals and Attestations
-
Annual renewals for members.
-
- );
-}
diff --git a/ICCC/app/page.tsx b/ICCC/app/page.tsx
deleted file mode 100644
index 93ccd9e..0000000
--- a/ICCC/app/page.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-export default function HomePage() {
- return (
-
-
International Criminal Court of Commerce
-
- Welcome to the official portal. Explore registry, chambers, case law, and judgments.
-
-
-
- );
-}
diff --git a/ICCC/app/registry/page.tsx b/ICCC/app/registry/page.tsx
deleted file mode 100644
index 3fa35bd..0000000
--- a/ICCC/app/registry/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RegistryPage() {
- return (
-
-
Registry
-
Clerk of Court and registry.
-
- );
-}
diff --git a/ICCC/app/report/page.tsx b/ICCC/app/report/page.tsx
deleted file mode 100644
index 6ae4c22..0000000
--- a/ICCC/app/report/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ReportPage() {
- return (
-
-
Report
-
Report incidents or compliance matters.
-
- );
-}
diff --git a/ICCC/app/request/page.tsx b/ICCC/app/request/page.tsx
deleted file mode 100644
index 6e653db..0000000
--- a/ICCC/app/request/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RequestPage() {
- return (
-
-
Request
-
Request documents or support.
-
- );
-}
diff --git a/ICCC/app/submit/page.tsx b/ICCC/app/submit/page.tsx
deleted file mode 100644
index 62e1cba..0000000
--- a/ICCC/app/submit/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SubmitPage() {
- return (
-
-
Submit
-
Submission portal.
-
- );
-}
diff --git a/ICCC/app/transparency/audit/page.tsx b/ICCC/app/transparency/audit/page.tsx
deleted file mode 100644
index 5fe7056..0000000
--- a/ICCC/app/transparency/audit/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AuditPage() {
- return (
-
-
Audit Reports
-
Audit reports and findings tracker.
-
- );
-}
diff --git a/ICCC/app/transparency/data-protection/page.tsx b/ICCC/app/transparency/data-protection/page.tsx
deleted file mode 100644
index b2454b3..0000000
--- a/ICCC/app/transparency/data-protection/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DataProtectionPage() {
- return (
-
-
Data Protection and Records
-
Records retention and data protection.
-
- );
-}
diff --git a/ICCC/app/transparency/ethics/page.tsx b/ICCC/app/transparency/ethics/page.tsx
deleted file mode 100644
index ff5b47d..0000000
--- a/ICCC/app/transparency/ethics/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function EthicsPage() {
- return (
-
-
Ethics and Conduct
-
Ethics and conduct policies.
-
- );
-}
diff --git a/ICCC/app/transparency/page.tsx b/ICCC/app/transparency/page.tsx
deleted file mode 100644
index f676261..0000000
--- a/ICCC/app/transparency/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function TransparencyPage() {
- return (
-
-
Transparency
-
Audit, ethics, whistleblower, sanctions, and data protection.
-
- );
-}
diff --git a/ICCC/app/transparency/sanctions/page.tsx b/ICCC/app/transparency/sanctions/page.tsx
deleted file mode 100644
index adf23fe..0000000
--- a/ICCC/app/transparency/sanctions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SanctionsPage() {
- return (
-
-
Sanctions and Restricted Parties
-
Eligibility and restricted parties.
-
- );
-}
diff --git a/ICCC/app/transparency/whistleblower/page.tsx b/ICCC/app/transparency/whistleblower/page.tsx
deleted file mode 100644
index 5d9a692..0000000
--- a/ICCC/app/transparency/whistleblower/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function WhistleblowerPage() {
- return (
-
-
Whistleblower Intake
-
Secure anonymous reporting.
-
- );
-}
diff --git a/ICCC/components/layout/Footer.tsx b/ICCC/components/layout/Footer.tsx
deleted file mode 100644
index 4480f1b..0000000
--- a/ICCC/components/layout/Footer.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import Link from "next/link";
-import { navItems } from "@/lib/nav-config";
-
-const footerLinks = [
- { label: "About", href: "/about" },
- { label: "Documents", href: "/documents" },
- { label: "Transparency", href: "/transparency" },
- { label: "Contact", href: "/contact" },
- { label: "Regional Offices", href: "/regions" },
-];
-
-function flatNavItems(items: typeof navItems): { label: string; href: string }[] {
- const out: { label: string; href: string }[] = [];
- for (const item of items) {
- if (item.children) {
- for (const c of item.children) out.push({ label: c.label, href: c.href });
- } else {
- out.push({ label: item.label, href: item.href });
- }
- }
- return out;
-}
-
-export function Footer() {
- const flat = flatNavItems(navItems);
- const keyLinks = footerLinks.length ? footerLinks : flat.slice(0, 6);
-
- return (
-
- );
-}
diff --git a/ICCC/components/layout/Header.tsx b/ICCC/components/layout/Header.tsx
deleted file mode 100644
index 30fe0fb..0000000
--- a/ICCC/components/layout/Header.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { useState } from "react";
-import { navItems } from "@/lib/nav-config";
-import { NavDropdown } from "./NavDropdown";
-import { MobileNav } from "./MobileNav";
-
-export function Header() {
- const [mobileOpen, setMobileOpen] = useState(false);
-
- return (
-
-
-
- ICCC
-
-
-
-
- Sign in
-
-
-
-
- setMobileOpen(false)} />
-
- );
-}
diff --git a/ICCC/components/layout/MobileNav.tsx b/ICCC/components/layout/MobileNav.tsx
deleted file mode 100644
index 6b94745..0000000
--- a/ICCC/components/layout/MobileNav.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import type { NavItem } from "@public-web-portals/shared";
-
-export function MobileNav({
- items,
- open,
- onClose,
-}: {
- items: NavItem[];
- open: boolean;
- onClose: () => void;
-}) {
- if (!open) return null;
-
- return (
-
- );
-}
diff --git a/ICCC/components/layout/NavDropdown.tsx b/ICCC/components/layout/NavDropdown.tsx
deleted file mode 100644
index d9c6b1b..0000000
--- a/ICCC/components/layout/NavDropdown.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { useState, useRef, useEffect } from "react";
-import type { NavItem } from "@public-web-portals/shared";
-
-export function NavDropdown({ item }: { item: NavItem }) {
- const [open, setOpen] = useState(false);
- const ref = useRef(null);
-
- useEffect(() => {
- function handleClickOutside(event: MouseEvent) {
- if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
- }
- document.addEventListener("mousedown", handleClickOutside);
- return () => document.removeEventListener("mousedown", handleClickOutside);
- }, []);
-
- return (
-
-
-
-
- );
-}
diff --git a/ICCC/lib/auth.ts b/ICCC/lib/auth.ts
deleted file mode 100644
index 1077579..0000000
--- a/ICCC/lib/auth.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { SessionOrNull } from "@public-web-portals/shared";
-
-/**
- * Placeholder session. Replace with OIDC/OAuth 2.0 when identity provider is configured.
- * TECH_POLICIES: use httpOnly cookies / secure token storage.
- */
-export async function getSession(): Promise {
- // TODO: read session from cookie or header (e.g. NextAuth, OIDC)
- return null;
-}
diff --git a/ICCC/lib/nav-config.ts b/ICCC/lib/nav-config.ts
deleted file mode 100644
index 7ecc4e6..0000000
--- a/ICCC/lib/nav-config.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { getNavForPortal } from "@public-web-portals/shared";
-
-export const portalId = "ICCC" as const;
-export const navItems = getNavForPortal(portalId);
diff --git a/ICCC/lib/rbac.ts b/ICCC/lib/rbac.ts
deleted file mode 100644
index 75a5b51..0000000
--- a/ICCC/lib/rbac.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import type { Role } from "@public-web-portals/shared";
-
-/** Route prefixes that require any authenticated role */
-const protectedPrefixes = [
- "/dashboard",
- "/submit",
- "/apply",
- "/report",
- "/request",
- "/membership/renewals",
-];
-
-/** Route prefixes that require admin role */
-const adminOnlyPrefixes = ["/dashboard/admin"];
-
-/** Routes that are always public (no auth) */
-const publicPaths = [
- "/",
- "/about",
- "/governance",
- "/leadership",
- "/org-chart",
- "/departments",
- "/programs",
- "/membership",
- "/accreditation",
- "/documents",
- "/standards",
- "/news",
- "/publications",
- "/contact",
- "/regions",
- "/transparency",
- "/login",
- "/logout",
-];
-
-function pathIsPublic(pathname: string): boolean {
- if (publicPaths.includes(pathname)) return true;
- if (pathname.startsWith("/transparency/")) return true;
- return false;
-}
-
-function pathIsProtected(pathname: string): boolean {
- return protectedPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
-}
-
-function pathIsAdminOnly(pathname: string): boolean {
- return adminOnlyPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
-}
-
-export function canAccess(pathname: string, role: Role | null): boolean {
- if (pathIsPublic(pathname)) return true;
- if (role == null) return false;
- if (pathIsAdminOnly(pathname)) return role === "admin";
- if (pathIsProtected(pathname)) return true;
- return false;
-}
-
-export function requiresAuth(pathname: string): boolean {
- return pathIsProtected(pathname);
-}
-
-export function requiresAdmin(pathname: string): boolean {
- return pathIsAdminOnly(pathname);
-}
diff --git a/ICCC/middleware.ts b/ICCC/middleware.ts
deleted file mode 100644
index a1e26cd..0000000
--- a/ICCC/middleware.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { NextResponse } from "next/server";
-import type { NextRequest } from "next/server";
-import { canAccess, requiresAuth, requiresAdmin } from "./lib/rbac";
-import type { Role } from "@public-web-portals/shared";
-
-const LOGIN = "/login";
-
-function getRoleFromCookie(request: NextRequest): Role | null {
- const role = request.cookies.get("portal-role")?.value;
- if (!role) return null;
- const valid: Role[] = ["member", "judge", "clerk", "diplomat", "donor", "staff", "admin"];
- return valid.includes(role as Role) ? (role as Role) : null;
-}
-
-export function middleware(request: NextRequest) {
- const pathname = request.nextUrl.pathname;
- const role = getRoleFromCookie(request);
-
- if (requiresAdmin(pathname) && role !== "admin") {
- return NextResponse.redirect(new URL("/dashboard", request.url));
- }
-
- if (requiresAuth(pathname)) {
- if (role == null) {
- const url = new URL(LOGIN, request.url);
- url.searchParams.set("returnUrl", pathname);
- return NextResponse.redirect(url);
- }
- if (!canAccess(pathname, role)) {
- return NextResponse.redirect(new URL("/dashboard", request.url));
- }
- }
-
- return NextResponse.next();
-}
-
-export const config = {
- matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
-};
diff --git a/ICCC/next-env.d.ts b/ICCC/next-env.d.ts
deleted file mode 100644
index 40c3d68..0000000
--- a/ICCC/next-env.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/ICCC/next.config.js b/ICCC/next.config.js
deleted file mode 100644
index d0d6b18..0000000
--- a/ICCC/next.config.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @type { import('next').NextConfig } */
-const nextConfig = {
- transpilePackages: ["@public-web-portals/shared"],
- async headers() {
- return [
- {
- source: "/:path*",
- headers: [
- { key: "X-Frame-Options", value: "DENY" },
- { key: "X-Content-Type-Options", value: "nosniff" },
- { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
- {
- key: "Content-Security-Policy",
- value: [
- "default-src 'self'",
- "script-src 'self'",
- "style-src 'self' 'unsafe-inline'",
- "img-src 'self' data: https:",
- "font-src 'self'",
- "connect-src 'self'",
- "frame-ancestors 'none'",
- "base-uri 'self'",
- "form-action 'self'",
- ].join("; "),
- },
- ],
- },
- ];
- },
-};
-
-module.exports = nextConfig;
diff --git a/ICCC/package.json b/ICCC/package.json
deleted file mode 100644
index 7204ea8..0000000
--- a/ICCC/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "name": "portal-iccc",
- "version": "0.1.0",
- "private": true,
- "scripts": {
- "dev": "next dev --port 3000",
- "build": "next build",
- "start": "next start --port 3000",
- "lint": "eslint . --max-warnings 0 --config ../.eslintrc.cjs",
- "typecheck": "tsc --noEmit"
- },
- "dependencies": {
- "@public-web-portals/shared": "workspace:*",
- "next": "^14.2.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- },
- "devDependencies": {
- "@types/node": "^20.10.0",
- "@types/react": "^18.2.0",
- "@types/react-dom": "^18.2.0",
- "autoprefixer": "^10.4.0",
- "eslint": "^8.56.0",
- "eslint-config-next": "^14.2.0",
- "postcss": "^8.4.0",
- "tailwindcss": "^3.4.0",
- "typescript": "^5.3.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
-}
diff --git a/ICCC/postcss.config.js b/ICCC/postcss.config.js
deleted file mode 100644
index 12a703d..0000000
--- a/ICCC/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/ICCC/tailwind.config.ts b/ICCC/tailwind.config.ts
deleted file mode 100644
index aae1628..0000000
--- a/ICCC/tailwind.config.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { Config } from "tailwindcss";
-import { designTokens } from "@public-web-portals/shared";
-
-const config: Config = {
- content: [
- "./app/**/*.{js,ts,jsx,tsx,mdx}",
- "./components/**/*.{js,ts,jsx,tsx,mdx}",
- ],
- theme: {
- extend: designTokens as Record,
- },
- plugins: [],
-};
-
-export default config;
diff --git a/ICCC/tsconfig.json b/ICCC/tsconfig.json
deleted file mode 100644
index cd32290..0000000
--- a/ICCC/tsconfig.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "extends": "../tsconfig.base.json",
- "compilerOptions": {
- "plugins": [
- {
- "name": "next"
- }
- ],
- "module": "ESNext",
- "moduleResolution": "bundler",
- "jsx": "preserve",
- "noEmit": true,
- "incremental": true,
- "paths": {
- "@/*": [
- "./*"
- ]
- },
- "allowJs": true
- },
- "include": [
- "next-env.d.ts",
- "**/*.ts",
- "**/*.tsx",
- ".next/types/**/*.ts"
- ],
- "exclude": [
- "node_modules"
- ]
-}
diff --git a/OMNL b/OMNL
new file mode 160000
index 0000000..7418f3a
--- /dev/null
+++ b/OMNL
@@ -0,0 +1 @@
+Subproject commit 7418f3aab7d7592b0e9b196704fdf2b198f4a627
diff --git a/OMNL/.env.example b/OMNL/.env.example
deleted file mode 100644
index 8e389e0..0000000
--- a/OMNL/.env.example
+++ /dev/null
@@ -1,8 +0,0 @@
-# Next.js
-NEXTAUTH_URL=http://localhost:3000
-
-# OIDC / OAuth 2.0 (placeholder until identity provider is configured)
-# OIDC_ISSUER=
-# OIDC_CLIENT_ID=
-# OIDC_CLIENT_SECRET=
-# OIDC_REDIRECT_URI=
diff --git a/OMNL/.eslintrc.cjs b/OMNL/.eslintrc.cjs
deleted file mode 100644
index 53dff50..0000000
--- a/OMNL/.eslintrc.cjs
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @type { import("eslint").Linter.Config } */
-module.exports = {
- root: true,
- extends: ["../.eslintrc.cjs", "next/core-web-vitals"],
-};
diff --git a/OMNL/.gitignore b/OMNL/.gitignore
deleted file mode 100644
index 71f76af..0000000
--- a/OMNL/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-node_modules/
-.next/
-out/
-dist/
-.env
-.env.local
-.env.*.local
diff --git a/OMNL/README.md b/OMNL/README.md
deleted file mode 100644
index 7b4bad7..0000000
--- a/OMNL/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# OMNL Portal
-
-Portal for the **Organisation Mondiale du Numérique**.
-
-**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/OMNL.git Next-generation web application following the shared tech stack and policies.
-
-## Run locally
-
-```bash
-pnpm install
-pnpm dev
-```
-
-Open [http://localhost:3000](http://localhost:3000).
-
-## Environment
-
-Copy `.env.example` to `.env.local` and set values. No secrets in repo.
-
-## Standards
-
-- [TECH_STACK.md](../TECH_STACK.md)
-- [TECH_POLICIES.md](../TECH_POLICIES.md)
-- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md)
-- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md)
-
-## Structure
-
-Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Programs and Impact, Standards, Cyber Resilience.
diff --git a/OMNL/app/(auth)/login/page.tsx b/OMNL/app/(auth)/login/page.tsx
deleted file mode 100644
index 48101a9..0000000
--- a/OMNL/app/(auth)/login/page.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-"use client";
-
-import { Suspense } from "react";
-import { useSearchParams } from "next/navigation";
-import Link from "next/link";
-
-function LoginForm() {
- const searchParams = useSearchParams();
- const returnUrl = searchParams.get("returnUrl") ?? "/dashboard";
-
- return (
-
-
Sign in
-
- Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured.
-
-
-
-
- Return to previous page
-
-
-
- );
-}
-
-export default function LoginPage() {
- return (
- Loading...}>
-
-
- );
-}
diff --git a/OMNL/app/(auth)/logout/page.tsx b/OMNL/app/(auth)/logout/page.tsx
deleted file mode 100644
index fd763a6..0000000
--- a/OMNL/app/(auth)/logout/page.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-
-import { useEffect } from "react";
-import Link from "next/link";
-
-export default function LogoutPage() {
- useEffect(() => {
- document.cookie = "portal-role=; path=/; max-age=0";
- }, []);
-
- return (
-
-
Signed out
-
You have been signed out.
-
- Return to home
-
-
- );
-}
diff --git a/OMNL/app/(public)/about/page.tsx b/OMNL/app/(public)/about/page.tsx
deleted file mode 100644
index 0b87c58..0000000
--- a/OMNL/app/(public)/about/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AboutPage() {
- return (
-
-
Mandate
-
About the Digital Bank of International Settlements.
-
- );
-}
diff --git a/OMNL/app/(public)/accreditation/page.tsx b/OMNL/app/(public)/accreditation/page.tsx
deleted file mode 100644
index c5e95d2..0000000
--- a/OMNL/app/(public)/accreditation/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AccreditationPage() {
- return (
-
-
Accreditation
-
Accreditation and credentials.
-
- );
-}
diff --git a/OMNL/app/(public)/contact/page.tsx b/OMNL/app/(public)/contact/page.tsx
deleted file mode 100644
index 7bb6a85..0000000
--- a/OMNL/app/(public)/contact/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ContactPage() {
- return (
-
-
Contact
-
General contact and enquiries.
-
- );
-}
diff --git a/OMNL/app/(public)/departments/page.tsx b/OMNL/app/(public)/departments/page.tsx
deleted file mode 100644
index ed01731..0000000
--- a/OMNL/app/(public)/departments/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DepartmentsPage() {
- return (
-
-
Departments
-
Mission departments and programs.
-
- );
-}
diff --git a/OMNL/app/(public)/documents/page.tsx b/OMNL/app/(public)/documents/page.tsx
deleted file mode 100644
index c641e1d..0000000
--- a/OMNL/app/(public)/documents/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DocumentsPage() {
- return (
-
-
Documents
-
Library, standards, and directives.
-
- );
-}
diff --git a/OMNL/app/(public)/governance/page.tsx b/OMNL/app/(public)/governance/page.tsx
deleted file mode 100644
index 8cf0212..0000000
--- a/OMNL/app/(public)/governance/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function GovernancePage() {
- return (
-
-
Governance
-
Charters, instruments, and governance.
-
- );
-}
diff --git a/OMNL/app/(public)/leadership/page.tsx b/OMNL/app/(public)/leadership/page.tsx
deleted file mode 100644
index ff1f679..0000000
--- a/OMNL/app/(public)/leadership/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function LeadershipPage() {
- return (
-
-
Leadership
-
Executive leadership and secretariat.
-
- );
-}
diff --git a/OMNL/app/(public)/membership/page.tsx b/OMNL/app/(public)/membership/page.tsx
deleted file mode 100644
index cf191d0..0000000
--- a/OMNL/app/(public)/membership/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function MembershipPage() {
- return (
-
-
Membership
-
Member directory and accreditation.
-
- );
-}
diff --git a/OMNL/app/(public)/news/page.tsx b/OMNL/app/(public)/news/page.tsx
deleted file mode 100644
index 57d0061..0000000
--- a/OMNL/app/(public)/news/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function NewsPage() {
- return (
-
-
News
-
News and announcements.
-
- );
-}
diff --git a/OMNL/app/(public)/org-chart/page.tsx b/OMNL/app/(public)/org-chart/page.tsx
deleted file mode 100644
index e01d431..0000000
--- a/OMNL/app/(public)/org-chart/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function OrgChartPage() {
- return (
-
-
Org Chart
-
Organizational structure.
-
- );
-}
diff --git a/OMNL/app/(public)/programs/page.tsx b/OMNL/app/(public)/programs/page.tsx
deleted file mode 100644
index 57d0bb0..0000000
--- a/OMNL/app/(public)/programs/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ProgramsPage() {
- return (
-
-
Programs
-
Programs and initiatives.
-
- );
-}
diff --git a/OMNL/app/(public)/publications/page.tsx b/OMNL/app/(public)/publications/page.tsx
deleted file mode 100644
index 6b329f6..0000000
--- a/OMNL/app/(public)/publications/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function PublicationsPage() {
- return (
-
-
Publications
-
Publications and reports.
-
- );
-}
diff --git a/OMNL/app/(public)/regions/page.tsx b/OMNL/app/(public)/regions/page.tsx
deleted file mode 100644
index 66978cc..0000000
--- a/OMNL/app/(public)/regions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RegionsPage() {
- return (
-
-
Regional Offices
-
Americas, EMEA, APAC delegations and field missions.
-
- );
-}
diff --git a/OMNL/app/(public)/standards/page.tsx b/OMNL/app/(public)/standards/page.tsx
deleted file mode 100644
index 9327ef0..0000000
--- a/OMNL/app/(public)/standards/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function StandardsPage() {
- return (
-
-
Standards
-
Standards and codes.
-
- );
-}
diff --git a/OMNL/app/api/auth/mock-login/route.ts b/OMNL/app/api/auth/mock-login/route.ts
deleted file mode 100644
index 57f672f..0000000
--- a/OMNL/app/api/auth/mock-login/route.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-
-export async function POST(request: NextRequest) {
- const form = await request.formData();
- const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard";
- const role = (form.get("role") as string) ?? "member";
- const res = NextResponse.redirect(new URL(returnUrl, request.url));
- res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 });
- return res;
-}
diff --git a/OMNL/app/apply/page.tsx b/OMNL/app/apply/page.tsx
deleted file mode 100644
index 7ee15cb..0000000
--- a/OMNL/app/apply/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ApplyPage() {
- return (
-
-
Apply
-
Apply for membership or accreditation.
-
- );
-}
diff --git a/OMNL/app/dashboard/layout.tsx b/OMNL/app/dashboard/layout.tsx
deleted file mode 100644
index 680435b..0000000
--- a/OMNL/app/dashboard/layout.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import Link from "next/link";
-import type { ReactNode } from "react";
-
-export default function DashboardLayout({ children }: { children: ReactNode }) {
- return (
-
-
-
{children}
-
- );
-}
diff --git a/OMNL/app/dashboard/page.tsx b/OMNL/app/dashboard/page.tsx
deleted file mode 100644
index 199cd04..0000000
--- a/OMNL/app/dashboard/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DashboardPage() {
- return (
-
-
Dashboard
-
Role-based dashboard.
-
- );
-}
diff --git a/OMNL/app/dashboard/requests/page.tsx b/OMNL/app/dashboard/requests/page.tsx
deleted file mode 100644
index eb94812..0000000
--- a/OMNL/app/dashboard/requests/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RequestsPage() {
- return (
-
-
My requests
-
Track your requests.
-
- );
-}
diff --git a/OMNL/app/dashboard/submissions/page.tsx b/OMNL/app/dashboard/submissions/page.tsx
deleted file mode 100644
index dc57c54..0000000
--- a/OMNL/app/dashboard/submissions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SubmissionsPage() {
- return (
-
-
My submissions
-
Track your submissions and status.
-
- );
-}
diff --git a/OMNL/app/departments/cyber-resilience/page.tsx b/OMNL/app/departments/cyber-resilience/page.tsx
deleted file mode 100644
index 8040c4f..0000000
--- a/OMNL/app/departments/cyber-resilience/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function CyberResiliencePage() {
- return (
-
-
Cyber Resilience
-
Incident coordination and cyber resilience.
-
- );
-}
diff --git a/OMNL/app/documents/standards/page.tsx b/OMNL/app/documents/standards/page.tsx
deleted file mode 100644
index 02460af..0000000
--- a/OMNL/app/documents/standards/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DocumentsStandardsPage() {
- return (
-
-
Standards
-
Digital standards and interoperability.
-
- );
-}
diff --git a/OMNL/app/globals.css b/OMNL/app/globals.css
deleted file mode 100644
index b5c61c9..0000000
--- a/OMNL/app/globals.css
+++ /dev/null
@@ -1,3 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
diff --git a/OMNL/app/layout.tsx b/OMNL/app/layout.tsx
deleted file mode 100644
index 28796e3..0000000
--- a/OMNL/app/layout.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { Metadata } from "next";
-import type { ReactNode } from "react";
-import "./globals.css";
-import { Header } from "@/components/layout/Header";
-import { Footer } from "@/components/layout/Footer";
-
-export const metadata: Metadata = {
- title: "Organisation Mondiale du Numérique",
- description: "Official portal of the Organisation Mondiale du Numérique",
-};
-
-export default function RootLayout({
- children,
-}: Readonly<{
- children: ReactNode;
-}>) {
- return (
-
-
-
- Skip to main content
-
-
-
- {children}
-
-
-
-
- );
-}
diff --git a/OMNL/app/membership/renewals/page.tsx b/OMNL/app/membership/renewals/page.tsx
deleted file mode 100644
index 79e5a75..0000000
--- a/OMNL/app/membership/renewals/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RenewalsPage() {
- return (
-
-
Renewals and Attestations
-
Annual renewals for members.
-
- );
-}
diff --git a/OMNL/app/page.tsx b/OMNL/app/page.tsx
deleted file mode 100644
index fac9a35..0000000
--- a/OMNL/app/page.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-export default function HomePage() {
- return (
-
-
Organisation Mondiale du Numérique
-
- Welcome to the official portal. Digital standards, identity, and cyber resilience.
-
-
-
- );
-}
diff --git a/OMNL/app/report/page.tsx b/OMNL/app/report/page.tsx
deleted file mode 100644
index 6ae4c22..0000000
--- a/OMNL/app/report/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ReportPage() {
- return (
-
-
Report
-
Report incidents or compliance matters.
-
- );
-}
diff --git a/OMNL/app/request/page.tsx b/OMNL/app/request/page.tsx
deleted file mode 100644
index 6e653db..0000000
--- a/OMNL/app/request/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RequestPage() {
- return (
-
-
Request
-
Request documents or support.
-
- );
-}
diff --git a/OMNL/app/submit/page.tsx b/OMNL/app/submit/page.tsx
deleted file mode 100644
index 62e1cba..0000000
--- a/OMNL/app/submit/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SubmitPage() {
- return (
-
-
Submit
-
Submission portal.
-
- );
-}
diff --git a/OMNL/app/transparency/audit/page.tsx b/OMNL/app/transparency/audit/page.tsx
deleted file mode 100644
index 5fe7056..0000000
--- a/OMNL/app/transparency/audit/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AuditPage() {
- return (
-
-
Audit Reports
-
Audit reports and findings tracker.
-
- );
-}
diff --git a/OMNL/app/transparency/data-protection/page.tsx b/OMNL/app/transparency/data-protection/page.tsx
deleted file mode 100644
index b2454b3..0000000
--- a/OMNL/app/transparency/data-protection/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DataProtectionPage() {
- return (
-
-
Data Protection and Records
-
Records retention and data protection.
-
- );
-}
diff --git a/OMNL/app/transparency/ethics/page.tsx b/OMNL/app/transparency/ethics/page.tsx
deleted file mode 100644
index ff5b47d..0000000
--- a/OMNL/app/transparency/ethics/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function EthicsPage() {
- return (
-
-
Ethics and Conduct
-
Ethics and conduct policies.
-
- );
-}
diff --git a/OMNL/app/transparency/page.tsx b/OMNL/app/transparency/page.tsx
deleted file mode 100644
index f676261..0000000
--- a/OMNL/app/transparency/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function TransparencyPage() {
- return (
-
-
Transparency
-
Audit, ethics, whistleblower, sanctions, and data protection.
-
- );
-}
diff --git a/OMNL/app/transparency/sanctions/page.tsx b/OMNL/app/transparency/sanctions/page.tsx
deleted file mode 100644
index adf23fe..0000000
--- a/OMNL/app/transparency/sanctions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SanctionsPage() {
- return (
-
-
Sanctions and Restricted Parties
-
Eligibility and restricted parties.
-
- );
-}
diff --git a/OMNL/app/transparency/whistleblower/page.tsx b/OMNL/app/transparency/whistleblower/page.tsx
deleted file mode 100644
index 5d9a692..0000000
--- a/OMNL/app/transparency/whistleblower/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function WhistleblowerPage() {
- return (
-
-
Whistleblower Intake
-
Secure anonymous reporting.
-
- );
-}
diff --git a/OMNL/components/layout/Footer.tsx b/OMNL/components/layout/Footer.tsx
deleted file mode 100644
index 63b1cb6..0000000
--- a/OMNL/components/layout/Footer.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import Link from "next/link";
-import { navItems } from "@/lib/nav-config";
-
-const footerLinks = [
- { label: "About", href: "/about" },
- { label: "Documents", href: "/documents" },
- { label: "Transparency", href: "/transparency" },
- { label: "Contact", href: "/contact" },
- { label: "Regional Offices", href: "/regions" },
-];
-
-function flatNavItems(items: typeof navItems): { label: string; href: string }[] {
- const out: { label: string; href: string }[] = [];
- for (const item of items) {
- if (item.children) {
- for (const c of item.children) out.push({ label: c.label, href: c.href });
- } else {
- out.push({ label: item.label, href: item.href });
- }
- }
- return out;
-}
-
-export function Footer() {
- const flat = flatNavItems(navItems);
- const keyLinks = footerLinks.length ? footerLinks : flat.slice(0, 6);
-
- return (
-
- );
-}
diff --git a/OMNL/components/layout/Header.tsx b/OMNL/components/layout/Header.tsx
deleted file mode 100644
index 0cbfc91..0000000
--- a/OMNL/components/layout/Header.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { useState } from "react";
-import { navItems } from "@/lib/nav-config";
-import { NavDropdown } from "./NavDropdown";
-import { MobileNav } from "./MobileNav";
-
-export function Header() {
- const [mobileOpen, setMobileOpen] = useState(false);
-
- return (
-
-
-
- OMNL
-
-
-
-
- Sign in
-
-
-
-
- setMobileOpen(false)} />
-
- );
-}
diff --git a/OMNL/components/layout/MobileNav.tsx b/OMNL/components/layout/MobileNav.tsx
deleted file mode 100644
index 6b94745..0000000
--- a/OMNL/components/layout/MobileNav.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import type { NavItem } from "@public-web-portals/shared";
-
-export function MobileNav({
- items,
- open,
- onClose,
-}: {
- items: NavItem[];
- open: boolean;
- onClose: () => void;
-}) {
- if (!open) return null;
-
- return (
-
- );
-}
diff --git a/OMNL/components/layout/NavDropdown.tsx b/OMNL/components/layout/NavDropdown.tsx
deleted file mode 100644
index d9c6b1b..0000000
--- a/OMNL/components/layout/NavDropdown.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { useState, useRef, useEffect } from "react";
-import type { NavItem } from "@public-web-portals/shared";
-
-export function NavDropdown({ item }: { item: NavItem }) {
- const [open, setOpen] = useState(false);
- const ref = useRef(null);
-
- useEffect(() => {
- function handleClickOutside(event: MouseEvent) {
- if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
- }
- document.addEventListener("mousedown", handleClickOutside);
- return () => document.removeEventListener("mousedown", handleClickOutside);
- }, []);
-
- return (
-
-
-
-
- );
-}
diff --git a/OMNL/lib/auth.ts b/OMNL/lib/auth.ts
deleted file mode 100644
index 1077579..0000000
--- a/OMNL/lib/auth.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { SessionOrNull } from "@public-web-portals/shared";
-
-/**
- * Placeholder session. Replace with OIDC/OAuth 2.0 when identity provider is configured.
- * TECH_POLICIES: use httpOnly cookies / secure token storage.
- */
-export async function getSession(): Promise {
- // TODO: read session from cookie or header (e.g. NextAuth, OIDC)
- return null;
-}
diff --git a/OMNL/lib/nav-config.ts b/OMNL/lib/nav-config.ts
deleted file mode 100644
index e07e7e8..0000000
--- a/OMNL/lib/nav-config.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { getNavForPortal } from "@public-web-portals/shared";
-
-export const portalId = "OMNL" as const;
-export const navItems = getNavForPortal(portalId);
diff --git a/OMNL/lib/rbac.ts b/OMNL/lib/rbac.ts
deleted file mode 100644
index 75a5b51..0000000
--- a/OMNL/lib/rbac.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import type { Role } from "@public-web-portals/shared";
-
-/** Route prefixes that require any authenticated role */
-const protectedPrefixes = [
- "/dashboard",
- "/submit",
- "/apply",
- "/report",
- "/request",
- "/membership/renewals",
-];
-
-/** Route prefixes that require admin role */
-const adminOnlyPrefixes = ["/dashboard/admin"];
-
-/** Routes that are always public (no auth) */
-const publicPaths = [
- "/",
- "/about",
- "/governance",
- "/leadership",
- "/org-chart",
- "/departments",
- "/programs",
- "/membership",
- "/accreditation",
- "/documents",
- "/standards",
- "/news",
- "/publications",
- "/contact",
- "/regions",
- "/transparency",
- "/login",
- "/logout",
-];
-
-function pathIsPublic(pathname: string): boolean {
- if (publicPaths.includes(pathname)) return true;
- if (pathname.startsWith("/transparency/")) return true;
- return false;
-}
-
-function pathIsProtected(pathname: string): boolean {
- return protectedPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
-}
-
-function pathIsAdminOnly(pathname: string): boolean {
- return adminOnlyPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
-}
-
-export function canAccess(pathname: string, role: Role | null): boolean {
- if (pathIsPublic(pathname)) return true;
- if (role == null) return false;
- if (pathIsAdminOnly(pathname)) return role === "admin";
- if (pathIsProtected(pathname)) return true;
- return false;
-}
-
-export function requiresAuth(pathname: string): boolean {
- return pathIsProtected(pathname);
-}
-
-export function requiresAdmin(pathname: string): boolean {
- return pathIsAdminOnly(pathname);
-}
diff --git a/OMNL/middleware.ts b/OMNL/middleware.ts
deleted file mode 100644
index a1e26cd..0000000
--- a/OMNL/middleware.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { NextResponse } from "next/server";
-import type { NextRequest } from "next/server";
-import { canAccess, requiresAuth, requiresAdmin } from "./lib/rbac";
-import type { Role } from "@public-web-portals/shared";
-
-const LOGIN = "/login";
-
-function getRoleFromCookie(request: NextRequest): Role | null {
- const role = request.cookies.get("portal-role")?.value;
- if (!role) return null;
- const valid: Role[] = ["member", "judge", "clerk", "diplomat", "donor", "staff", "admin"];
- return valid.includes(role as Role) ? (role as Role) : null;
-}
-
-export function middleware(request: NextRequest) {
- const pathname = request.nextUrl.pathname;
- const role = getRoleFromCookie(request);
-
- if (requiresAdmin(pathname) && role !== "admin") {
- return NextResponse.redirect(new URL("/dashboard", request.url));
- }
-
- if (requiresAuth(pathname)) {
- if (role == null) {
- const url = new URL(LOGIN, request.url);
- url.searchParams.set("returnUrl", pathname);
- return NextResponse.redirect(url);
- }
- if (!canAccess(pathname, role)) {
- return NextResponse.redirect(new URL("/dashboard", request.url));
- }
- }
-
- return NextResponse.next();
-}
-
-export const config = {
- matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
-};
diff --git a/OMNL/next-env.d.ts b/OMNL/next-env.d.ts
deleted file mode 100644
index 40c3d68..0000000
--- a/OMNL/next-env.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/OMNL/next.config.js b/OMNL/next.config.js
deleted file mode 100644
index d0d6b18..0000000
--- a/OMNL/next.config.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @type { import('next').NextConfig } */
-const nextConfig = {
- transpilePackages: ["@public-web-portals/shared"],
- async headers() {
- return [
- {
- source: "/:path*",
- headers: [
- { key: "X-Frame-Options", value: "DENY" },
- { key: "X-Content-Type-Options", value: "nosniff" },
- { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
- {
- key: "Content-Security-Policy",
- value: [
- "default-src 'self'",
- "script-src 'self'",
- "style-src 'self' 'unsafe-inline'",
- "img-src 'self' data: https:",
- "font-src 'self'",
- "connect-src 'self'",
- "frame-ancestors 'none'",
- "base-uri 'self'",
- "form-action 'self'",
- ].join("; "),
- },
- ],
- },
- ];
- },
-};
-
-module.exports = nextConfig;
diff --git a/OMNL/package.json b/OMNL/package.json
deleted file mode 100644
index 56abfc6..0000000
--- a/OMNL/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "name": "portal-omnl",
- "version": "0.1.0",
- "private": true,
- "scripts": {
- "dev": "next dev --port 3000",
- "build": "next build",
- "start": "next start --port 3000",
- "lint": "eslint . --max-warnings 0 --config ../.eslintrc.cjs",
- "typecheck": "tsc --noEmit"
- },
- "dependencies": {
- "@public-web-portals/shared": "workspace:*",
- "next": "^14.2.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- },
- "devDependencies": {
- "@types/node": "^20.10.0",
- "@types/react": "^18.2.0",
- "@types/react-dom": "^18.2.0",
- "autoprefixer": "^10.4.0",
- "eslint": "^8.56.0",
- "eslint-config-next": "^14.2.0",
- "postcss": "^8.4.0",
- "tailwindcss": "^3.4.0",
- "typescript": "^5.3.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
-}
diff --git a/OMNL/postcss.config.js b/OMNL/postcss.config.js
deleted file mode 100644
index 12a703d..0000000
--- a/OMNL/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/OMNL/tailwind.config.ts b/OMNL/tailwind.config.ts
deleted file mode 100644
index aae1628..0000000
--- a/OMNL/tailwind.config.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { Config } from "tailwindcss";
-import { designTokens } from "@public-web-portals/shared";
-
-const config: Config = {
- content: [
- "./app/**/*.{js,ts,jsx,tsx,mdx}",
- "./components/**/*.{js,ts,jsx,tsx,mdx}",
- ],
- theme: {
- extend: designTokens as Record,
- },
- plugins: [],
-};
-
-export default config;
diff --git a/OMNL/tsconfig.json b/OMNL/tsconfig.json
deleted file mode 100644
index cd32290..0000000
--- a/OMNL/tsconfig.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "extends": "../tsconfig.base.json",
- "compilerOptions": {
- "plugins": [
- {
- "name": "next"
- }
- ],
- "module": "ESNext",
- "moduleResolution": "bundler",
- "jsx": "preserve",
- "noEmit": true,
- "incremental": true,
- "paths": {
- "@/*": [
- "./*"
- ]
- },
- "allowJs": true
- },
- "include": [
- "next-env.d.ts",
- "**/*.ts",
- "**/*.tsx",
- ".next/types/**/*.ts"
- ],
- "exclude": [
- "node_modules"
- ]
-}
diff --git a/README.md b/README.md
index 9f799c2..85ac9eb 100644
--- a/README.md
+++ b/README.md
@@ -12,10 +12,10 @@ Monorepo for next-generation governmental body web portals. Each subdirectory is
Monorepo for next-generation governmental body web portals. Each subdirectory is named by the body's **initials** and contains one portal application.
-**Repository:** https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git
+**Repository:** https://gitea.d-bis.org/Gov_Web_Portals/gov-portals-monorepo.git
```bash
-git clone https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git
+git clone --recurse-submodules https://gitea.d-bis.org/Gov_Web_Portals/gov-portals-monorepo.git
cd gov-portals-monorepo
pnpm install
```
@@ -35,18 +35,20 @@ pnpm install
This project is a **monorepo**. The canonical repository is:
-- **Monorepo:** https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git
+- **Monorepo:** https://gitea.d-bis.org/Gov_Web_Portals/gov-portals-monorepo.git
-Optional per-portal Gitea repos (for mirroring or separate CI/deploy):
+The four portals (DBIS, ICCC, OMNL, XOM) are **git submodules** linking to per-portal repos:
-| Portal | Repository |
-|--------|------------|
-| DBIS | https://gitea.d-bis.org/Gov_Web_Portals/DBIS.git |
-| ICCC | https://gitea.d-bis.org/Gov_Web_Portals/ICCC.git |
-| OMNL | https://gitea.d-bis.org/Gov_Web_Portals/OMNL.git |
-| XOM | https://gitea.d-bis.org/Gov_Web_Portals/XOM.git |
+| Portal | Submodule | Repository |
+|--------|-----------|------------|
+| DBIS | `DBIS/` | https://gitea.d-bis.org/Gov_Web_Portals/DBIS.git |
+| ICCC | `ICCC/` | https://gitea.d-bis.org/Gov_Web_Portals/ICCC.git |
+| OMNL | `OMNL/` | https://gitea.d-bis.org/Gov_Web_Portals/OMNL.git |
+| XOM | `XOM/` | https://gitea.d-bis.org/Gov_Web_Portals/XOM.git |
-To push the whole monorepo: `git remote add origin https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git` (if not set), then `git push -u origin main`.
+Clone with submodules: `git clone --recurse-submodules https://gitea.d-bis.org/Gov_Web_Portals/gov-portals-monorepo.git`
+
+To push the whole monorepo: set `origin` to the monorepo URL, then `git push -u origin main`. Push submodule changes from each portal directory.
## Standardization
diff --git a/XOM b/XOM
new file mode 160000
index 0000000..9f6bbe3
--- /dev/null
+++ b/XOM
@@ -0,0 +1 @@
+Subproject commit 9f6bbe33e3bd9e4ffa5fe310d591e120b7f2d293
diff --git a/XOM/.env.example b/XOM/.env.example
deleted file mode 100644
index 8e389e0..0000000
--- a/XOM/.env.example
+++ /dev/null
@@ -1,8 +0,0 @@
-# Next.js
-NEXTAUTH_URL=http://localhost:3000
-
-# OIDC / OAuth 2.0 (placeholder until identity provider is configured)
-# OIDC_ISSUER=
-# OIDC_CLIENT_ID=
-# OIDC_CLIENT_SECRET=
-# OIDC_REDIRECT_URI=
diff --git a/XOM/.eslintrc.cjs b/XOM/.eslintrc.cjs
deleted file mode 100644
index 53dff50..0000000
--- a/XOM/.eslintrc.cjs
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @type { import("eslint").Linter.Config } */
-module.exports = {
- root: true,
- extends: ["../.eslintrc.cjs", "next/core-web-vitals"],
-};
diff --git a/XOM/.gitignore b/XOM/.gitignore
deleted file mode 100644
index 71f76af..0000000
--- a/XOM/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-node_modules/
-.next/
-out/
-dist/
-.env
-.env.local
-.env.*.local
diff --git a/XOM/README.md b/XOM/README.md
deleted file mode 100644
index 57242a5..0000000
--- a/XOM/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# XOM Portal
-
-Portal for the **Sovereign Military Hospitaller Order of St. John of Jerusalem of Rhodes and of Malta** (Order of Malta).
-
-**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/XOM.git
-
-## Run locally
-
-```bash
-pnpm install
-pnpm dev
-```
-
-Open [http://localhost:3000](http://localhost:3000).
-
-## Environment
-
-Copy `.env.example` to `.env.local` and set values. No secrets in repo.
-
-## Standards
-
-- [TECH_STACK.md](../TECH_STACK.md)
-- [TECH_POLICIES.md](../TECH_POLICIES.md)
-- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md)
-- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md)
-
-## Structure
-
-Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Programs and Impact, Donors, Get Involved, Hospitaller Services.
diff --git a/XOM/app/(auth)/login/page.tsx b/XOM/app/(auth)/login/page.tsx
deleted file mode 100644
index 48101a9..0000000
--- a/XOM/app/(auth)/login/page.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-"use client";
-
-import { Suspense } from "react";
-import { useSearchParams } from "next/navigation";
-import Link from "next/link";
-
-function LoginForm() {
- const searchParams = useSearchParams();
- const returnUrl = searchParams.get("returnUrl") ?? "/dashboard";
-
- return (
-
-
Sign in
-
- Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured.
-
-
-
-
- Return to previous page
-
-
-
- );
-}
-
-export default function LoginPage() {
- return (
- Loading...}>
-
-
- );
-}
diff --git a/XOM/app/(auth)/logout/page.tsx b/XOM/app/(auth)/logout/page.tsx
deleted file mode 100644
index fd763a6..0000000
--- a/XOM/app/(auth)/logout/page.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-
-import { useEffect } from "react";
-import Link from "next/link";
-
-export default function LogoutPage() {
- useEffect(() => {
- document.cookie = "portal-role=; path=/; max-age=0";
- }, []);
-
- return (
-
-
Signed out
-
You have been signed out.
-
- Return to home
-
-
- );
-}
diff --git a/XOM/app/(public)/about/page.tsx b/XOM/app/(public)/about/page.tsx
deleted file mode 100644
index 0b87c58..0000000
--- a/XOM/app/(public)/about/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AboutPage() {
- return (
-
-
Mandate
-
About the Digital Bank of International Settlements.
-
- );
-}
diff --git a/XOM/app/(public)/accreditation/page.tsx b/XOM/app/(public)/accreditation/page.tsx
deleted file mode 100644
index c5e95d2..0000000
--- a/XOM/app/(public)/accreditation/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AccreditationPage() {
- return (
-
-
Accreditation
-
Accreditation and credentials.
-
- );
-}
diff --git a/XOM/app/(public)/contact/page.tsx b/XOM/app/(public)/contact/page.tsx
deleted file mode 100644
index 7bb6a85..0000000
--- a/XOM/app/(public)/contact/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ContactPage() {
- return (
-
-
Contact
-
General contact and enquiries.
-
- );
-}
diff --git a/XOM/app/(public)/departments/page.tsx b/XOM/app/(public)/departments/page.tsx
deleted file mode 100644
index ed01731..0000000
--- a/XOM/app/(public)/departments/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DepartmentsPage() {
- return (
-
-
Departments
-
Mission departments and programs.
-
- );
-}
diff --git a/XOM/app/(public)/documents/page.tsx b/XOM/app/(public)/documents/page.tsx
deleted file mode 100644
index c641e1d..0000000
--- a/XOM/app/(public)/documents/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DocumentsPage() {
- return (
-
-
Documents
-
Library, standards, and directives.
-
- );
-}
diff --git a/XOM/app/(public)/governance/page.tsx b/XOM/app/(public)/governance/page.tsx
deleted file mode 100644
index 8cf0212..0000000
--- a/XOM/app/(public)/governance/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function GovernancePage() {
- return (
-
-
Governance
-
Charters, instruments, and governance.
-
- );
-}
diff --git a/XOM/app/(public)/leadership/page.tsx b/XOM/app/(public)/leadership/page.tsx
deleted file mode 100644
index ff1f679..0000000
--- a/XOM/app/(public)/leadership/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function LeadershipPage() {
- return (
-
-
Leadership
-
Executive leadership and secretariat.
-
- );
-}
diff --git a/XOM/app/(public)/membership/page.tsx b/XOM/app/(public)/membership/page.tsx
deleted file mode 100644
index cf191d0..0000000
--- a/XOM/app/(public)/membership/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function MembershipPage() {
- return (
-
-
Membership
-
Member directory and accreditation.
-
- );
-}
diff --git a/XOM/app/(public)/news/page.tsx b/XOM/app/(public)/news/page.tsx
deleted file mode 100644
index 57d0061..0000000
--- a/XOM/app/(public)/news/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function NewsPage() {
- return (
-
-
News
-
News and announcements.
-
- );
-}
diff --git a/XOM/app/(public)/org-chart/page.tsx b/XOM/app/(public)/org-chart/page.tsx
deleted file mode 100644
index e01d431..0000000
--- a/XOM/app/(public)/org-chart/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function OrgChartPage() {
- return (
-
-
Org Chart
-
Organizational structure.
-
- );
-}
diff --git a/XOM/app/(public)/programs/page.tsx b/XOM/app/(public)/programs/page.tsx
deleted file mode 100644
index 57d0bb0..0000000
--- a/XOM/app/(public)/programs/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ProgramsPage() {
- return (
-
-
Programs
-
Programs and initiatives.
-
- );
-}
diff --git a/XOM/app/(public)/publications/page.tsx b/XOM/app/(public)/publications/page.tsx
deleted file mode 100644
index 6b329f6..0000000
--- a/XOM/app/(public)/publications/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function PublicationsPage() {
- return (
-
-
Publications
-
Publications and reports.
-
- );
-}
diff --git a/XOM/app/(public)/regions/page.tsx b/XOM/app/(public)/regions/page.tsx
deleted file mode 100644
index 66978cc..0000000
--- a/XOM/app/(public)/regions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RegionsPage() {
- return (
-
-
Regional Offices
-
Americas, EMEA, APAC delegations and field missions.
-
- );
-}
diff --git a/XOM/app/(public)/standards/page.tsx b/XOM/app/(public)/standards/page.tsx
deleted file mode 100644
index 9327ef0..0000000
--- a/XOM/app/(public)/standards/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function StandardsPage() {
- return (
-
-
Standards
-
Standards and codes.
-
- );
-}
diff --git a/XOM/app/api/auth/mock-login/route.ts b/XOM/app/api/auth/mock-login/route.ts
deleted file mode 100644
index 57f672f..0000000
--- a/XOM/app/api/auth/mock-login/route.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-
-export async function POST(request: NextRequest) {
- const form = await request.formData();
- const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard";
- const role = (form.get("role") as string) ?? "member";
- const res = NextResponse.redirect(new URL(returnUrl, request.url));
- res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 });
- return res;
-}
diff --git a/XOM/app/apply/page.tsx b/XOM/app/apply/page.tsx
deleted file mode 100644
index 7ee15cb..0000000
--- a/XOM/app/apply/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ApplyPage() {
- return (
-
-
Apply
-
Apply for membership or accreditation.
-
- );
-}
diff --git a/XOM/app/dashboard/layout.tsx b/XOM/app/dashboard/layout.tsx
deleted file mode 100644
index 680435b..0000000
--- a/XOM/app/dashboard/layout.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import Link from "next/link";
-import type { ReactNode } from "react";
-
-export default function DashboardLayout({ children }: { children: ReactNode }) {
- return (
-
-
-
{children}
-
- );
-}
diff --git a/XOM/app/dashboard/page.tsx b/XOM/app/dashboard/page.tsx
deleted file mode 100644
index 199cd04..0000000
--- a/XOM/app/dashboard/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DashboardPage() {
- return (
-
-
Dashboard
-
Role-based dashboard.
-
- );
-}
diff --git a/XOM/app/dashboard/requests/page.tsx b/XOM/app/dashboard/requests/page.tsx
deleted file mode 100644
index eb94812..0000000
--- a/XOM/app/dashboard/requests/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RequestsPage() {
- return (
-
-
My requests
-
Track your requests.
-
- );
-}
diff --git a/XOM/app/dashboard/submissions/page.tsx b/XOM/app/dashboard/submissions/page.tsx
deleted file mode 100644
index dc57c54..0000000
--- a/XOM/app/dashboard/submissions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SubmissionsPage() {
- return (
-
-
My submissions
-
Track your submissions and status.
-
- );
-}
diff --git a/XOM/app/departments/hospitaller-services/page.tsx b/XOM/app/departments/hospitaller-services/page.tsx
deleted file mode 100644
index f1582ed..0000000
--- a/XOM/app/departments/hospitaller-services/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function HospitallerServicesPage() {
- return (
-
-
Hospitaller Services
-
Humanitarian missions and medical relief.
-
- );
-}
diff --git a/XOM/app/donors/page.tsx b/XOM/app/donors/page.tsx
deleted file mode 100644
index 2cd7de6..0000000
--- a/XOM/app/donors/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DonorsPage() {
- return (
-
-
Donors
-
Donor stewardship and philanthropy.
-
- );
-}
diff --git a/XOM/app/get-involved/page.tsx b/XOM/app/get-involved/page.tsx
deleted file mode 100644
index b9c8285..0000000
--- a/XOM/app/get-involved/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function GetInvolvedPage() {
- return (
-
-
Get Involved
-
Volunteer corps and how to contribute.
-
- );
-}
diff --git a/XOM/app/globals.css b/XOM/app/globals.css
deleted file mode 100644
index b5c61c9..0000000
--- a/XOM/app/globals.css
+++ /dev/null
@@ -1,3 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
diff --git a/XOM/app/layout.tsx b/XOM/app/layout.tsx
deleted file mode 100644
index a522b2e..0000000
--- a/XOM/app/layout.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { Metadata } from "next";
-import type { ReactNode } from "react";
-import "./globals.css";
-import { Header } from "@/components/layout/Header";
-import { Footer } from "@/components/layout/Footer";
-
-export const metadata: Metadata = {
- title: "Order of Malta",
- description: "Official portal of the Sovereign Military Hospitaller Order of St. John of Jerusalem of Rhodes and of Malta",
-};
-
-export default function RootLayout({
- children,
-}: Readonly<{
- children: ReactNode;
-}>) {
- return (
-
-
-
- Skip to main content
-
-
-
- {children}
-
-
-
-
- );
-}
diff --git a/XOM/app/membership/renewals/page.tsx b/XOM/app/membership/renewals/page.tsx
deleted file mode 100644
index 79e5a75..0000000
--- a/XOM/app/membership/renewals/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RenewalsPage() {
- return (
-
-
Renewals and Attestations
-
Annual renewals for members.
-
- );
-}
diff --git a/XOM/app/page.tsx b/XOM/app/page.tsx
deleted file mode 100644
index 5d2946d..0000000
--- a/XOM/app/page.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-export default function HomePage() {
- return (
-
-
Order of Malta
-
- Welcome to the official portal. Humanitarian missions, donor stewardship, and volunteering.
-
-
-
- );
-}
diff --git a/XOM/app/report/page.tsx b/XOM/app/report/page.tsx
deleted file mode 100644
index 6ae4c22..0000000
--- a/XOM/app/report/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function ReportPage() {
- return (
-
-
Report
-
Report incidents or compliance matters.
-
- );
-}
diff --git a/XOM/app/request/page.tsx b/XOM/app/request/page.tsx
deleted file mode 100644
index 6e653db..0000000
--- a/XOM/app/request/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function RequestPage() {
- return (
-
-
Request
-
Request documents or support.
-
- );
-}
diff --git a/XOM/app/submit/page.tsx b/XOM/app/submit/page.tsx
deleted file mode 100644
index 62e1cba..0000000
--- a/XOM/app/submit/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SubmitPage() {
- return (
-
-
Submit
-
Submission portal.
-
- );
-}
diff --git a/XOM/app/transparency/audit/page.tsx b/XOM/app/transparency/audit/page.tsx
deleted file mode 100644
index 5fe7056..0000000
--- a/XOM/app/transparency/audit/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function AuditPage() {
- return (
-
-
Audit Reports
-
Audit reports and findings tracker.
-
- );
-}
diff --git a/XOM/app/transparency/data-protection/page.tsx b/XOM/app/transparency/data-protection/page.tsx
deleted file mode 100644
index b2454b3..0000000
--- a/XOM/app/transparency/data-protection/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function DataProtectionPage() {
- return (
-
-
Data Protection and Records
-
Records retention and data protection.
-
- );
-}
diff --git a/XOM/app/transparency/ethics/page.tsx b/XOM/app/transparency/ethics/page.tsx
deleted file mode 100644
index ff5b47d..0000000
--- a/XOM/app/transparency/ethics/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function EthicsPage() {
- return (
-
-
Ethics and Conduct
-
Ethics and conduct policies.
-
- );
-}
diff --git a/XOM/app/transparency/page.tsx b/XOM/app/transparency/page.tsx
deleted file mode 100644
index f676261..0000000
--- a/XOM/app/transparency/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function TransparencyPage() {
- return (
-
-
Transparency
-
Audit, ethics, whistleblower, sanctions, and data protection.
-
- );
-}
diff --git a/XOM/app/transparency/sanctions/page.tsx b/XOM/app/transparency/sanctions/page.tsx
deleted file mode 100644
index adf23fe..0000000
--- a/XOM/app/transparency/sanctions/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function SanctionsPage() {
- return (
-
-
Sanctions and Restricted Parties
-
Eligibility and restricted parties.
-
- );
-}
diff --git a/XOM/app/transparency/whistleblower/page.tsx b/XOM/app/transparency/whistleblower/page.tsx
deleted file mode 100644
index 5d9a692..0000000
--- a/XOM/app/transparency/whistleblower/page.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function WhistleblowerPage() {
- return (
-
-
Whistleblower Intake
-
Secure anonymous reporting.
-
- );
-}
diff --git a/XOM/components/layout/Footer.tsx b/XOM/components/layout/Footer.tsx
deleted file mode 100644
index 7f98572..0000000
--- a/XOM/components/layout/Footer.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import Link from "next/link";
-import { navItems } from "@/lib/nav-config";
-
-const footerLinks = [
- { label: "About", href: "/about" },
- { label: "Documents", href: "/documents" },
- { label: "Transparency", href: "/transparency" },
- { label: "Contact", href: "/contact" },
- { label: "Regional Offices", href: "/regions" },
-];
-
-function flatNavItems(items: typeof navItems): { label: string; href: string }[] {
- const out: { label: string; href: string }[] = [];
- for (const item of items) {
- if (item.children) {
- for (const c of item.children) out.push({ label: c.label, href: c.href });
- } else {
- out.push({ label: item.label, href: item.href });
- }
- }
- return out;
-}
-
-export function Footer() {
- const flat = flatNavItems(navItems);
- const keyLinks = footerLinks.length ? footerLinks : flat.slice(0, 6);
-
- return (
-
- );
-}
diff --git a/XOM/components/layout/Header.tsx b/XOM/components/layout/Header.tsx
deleted file mode 100644
index f73eb44..0000000
--- a/XOM/components/layout/Header.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { useState } from "react";
-import { navItems } from "@/lib/nav-config";
-import { NavDropdown } from "./NavDropdown";
-import { MobileNav } from "./MobileNav";
-
-export function Header() {
- const [mobileOpen, setMobileOpen] = useState(false);
-
- return (
-
-
-
- XOM
-
-
-
-
- Sign in
-
-
-
-
- setMobileOpen(false)} />
-
- );
-}
diff --git a/XOM/components/layout/MobileNav.tsx b/XOM/components/layout/MobileNav.tsx
deleted file mode 100644
index 6b94745..0000000
--- a/XOM/components/layout/MobileNav.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import type { NavItem } from "@public-web-portals/shared";
-
-export function MobileNav({
- items,
- open,
- onClose,
-}: {
- items: NavItem[];
- open: boolean;
- onClose: () => void;
-}) {
- if (!open) return null;
-
- return (
-
- );
-}
diff --git a/XOM/components/layout/NavDropdown.tsx b/XOM/components/layout/NavDropdown.tsx
deleted file mode 100644
index d9c6b1b..0000000
--- a/XOM/components/layout/NavDropdown.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { useState, useRef, useEffect } from "react";
-import type { NavItem } from "@public-web-portals/shared";
-
-export function NavDropdown({ item }: { item: NavItem }) {
- const [open, setOpen] = useState(false);
- const ref = useRef(null);
-
- useEffect(() => {
- function handleClickOutside(event: MouseEvent) {
- if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
- }
- document.addEventListener("mousedown", handleClickOutside);
- return () => document.removeEventListener("mousedown", handleClickOutside);
- }, []);
-
- return (
-
-
-
-
- );
-}
diff --git a/XOM/lib/auth.ts b/XOM/lib/auth.ts
deleted file mode 100644
index 1077579..0000000
--- a/XOM/lib/auth.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { SessionOrNull } from "@public-web-portals/shared";
-
-/**
- * Placeholder session. Replace with OIDC/OAuth 2.0 when identity provider is configured.
- * TECH_POLICIES: use httpOnly cookies / secure token storage.
- */
-export async function getSession(): Promise {
- // TODO: read session from cookie or header (e.g. NextAuth, OIDC)
- return null;
-}
diff --git a/XOM/lib/nav-config.ts b/XOM/lib/nav-config.ts
deleted file mode 100644
index 2722689..0000000
--- a/XOM/lib/nav-config.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { getNavForPortal } from "@public-web-portals/shared";
-
-export const portalId = "XOM" as const;
-export const navItems = getNavForPortal(portalId);
diff --git a/XOM/lib/rbac.ts b/XOM/lib/rbac.ts
deleted file mode 100644
index 75a5b51..0000000
--- a/XOM/lib/rbac.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import type { Role } from "@public-web-portals/shared";
-
-/** Route prefixes that require any authenticated role */
-const protectedPrefixes = [
- "/dashboard",
- "/submit",
- "/apply",
- "/report",
- "/request",
- "/membership/renewals",
-];
-
-/** Route prefixes that require admin role */
-const adminOnlyPrefixes = ["/dashboard/admin"];
-
-/** Routes that are always public (no auth) */
-const publicPaths = [
- "/",
- "/about",
- "/governance",
- "/leadership",
- "/org-chart",
- "/departments",
- "/programs",
- "/membership",
- "/accreditation",
- "/documents",
- "/standards",
- "/news",
- "/publications",
- "/contact",
- "/regions",
- "/transparency",
- "/login",
- "/logout",
-];
-
-function pathIsPublic(pathname: string): boolean {
- if (publicPaths.includes(pathname)) return true;
- if (pathname.startsWith("/transparency/")) return true;
- return false;
-}
-
-function pathIsProtected(pathname: string): boolean {
- return protectedPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
-}
-
-function pathIsAdminOnly(pathname: string): boolean {
- return adminOnlyPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
-}
-
-export function canAccess(pathname: string, role: Role | null): boolean {
- if (pathIsPublic(pathname)) return true;
- if (role == null) return false;
- if (pathIsAdminOnly(pathname)) return role === "admin";
- if (pathIsProtected(pathname)) return true;
- return false;
-}
-
-export function requiresAuth(pathname: string): boolean {
- return pathIsProtected(pathname);
-}
-
-export function requiresAdmin(pathname: string): boolean {
- return pathIsAdminOnly(pathname);
-}
diff --git a/XOM/middleware.ts b/XOM/middleware.ts
deleted file mode 100644
index a1e26cd..0000000
--- a/XOM/middleware.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { NextResponse } from "next/server";
-import type { NextRequest } from "next/server";
-import { canAccess, requiresAuth, requiresAdmin } from "./lib/rbac";
-import type { Role } from "@public-web-portals/shared";
-
-const LOGIN = "/login";
-
-function getRoleFromCookie(request: NextRequest): Role | null {
- const role = request.cookies.get("portal-role")?.value;
- if (!role) return null;
- const valid: Role[] = ["member", "judge", "clerk", "diplomat", "donor", "staff", "admin"];
- return valid.includes(role as Role) ? (role as Role) : null;
-}
-
-export function middleware(request: NextRequest) {
- const pathname = request.nextUrl.pathname;
- const role = getRoleFromCookie(request);
-
- if (requiresAdmin(pathname) && role !== "admin") {
- return NextResponse.redirect(new URL("/dashboard", request.url));
- }
-
- if (requiresAuth(pathname)) {
- if (role == null) {
- const url = new URL(LOGIN, request.url);
- url.searchParams.set("returnUrl", pathname);
- return NextResponse.redirect(url);
- }
- if (!canAccess(pathname, role)) {
- return NextResponse.redirect(new URL("/dashboard", request.url));
- }
- }
-
- return NextResponse.next();
-}
-
-export const config = {
- matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
-};
diff --git a/XOM/next-env.d.ts b/XOM/next-env.d.ts
deleted file mode 100644
index 40c3d68..0000000
--- a/XOM/next-env.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/XOM/next.config.js b/XOM/next.config.js
deleted file mode 100644
index d0d6b18..0000000
--- a/XOM/next.config.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @type { import('next').NextConfig } */
-const nextConfig = {
- transpilePackages: ["@public-web-portals/shared"],
- async headers() {
- return [
- {
- source: "/:path*",
- headers: [
- { key: "X-Frame-Options", value: "DENY" },
- { key: "X-Content-Type-Options", value: "nosniff" },
- { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
- {
- key: "Content-Security-Policy",
- value: [
- "default-src 'self'",
- "script-src 'self'",
- "style-src 'self' 'unsafe-inline'",
- "img-src 'self' data: https:",
- "font-src 'self'",
- "connect-src 'self'",
- "frame-ancestors 'none'",
- "base-uri 'self'",
- "form-action 'self'",
- ].join("; "),
- },
- ],
- },
- ];
- },
-};
-
-module.exports = nextConfig;
diff --git a/XOM/package.json b/XOM/package.json
deleted file mode 100644
index 0a34560..0000000
--- a/XOM/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "name": "portal-xom",
- "version": "0.1.0",
- "private": true,
- "scripts": {
- "dev": "next dev --port 3000",
- "build": "next build",
- "start": "next start --port 3000",
- "lint": "eslint . --max-warnings 0 --config ../.eslintrc.cjs",
- "typecheck": "tsc --noEmit"
- },
- "dependencies": {
- "@public-web-portals/shared": "workspace:*",
- "next": "^14.2.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- },
- "devDependencies": {
- "@types/node": "^20.10.0",
- "@types/react": "^18.2.0",
- "@types/react-dom": "^18.2.0",
- "autoprefixer": "^10.4.0",
- "eslint": "^8.56.0",
- "eslint-config-next": "^14.2.0",
- "postcss": "^8.4.0",
- "tailwindcss": "^3.4.0",
- "typescript": "^5.3.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
-}
diff --git a/XOM/postcss.config.js b/XOM/postcss.config.js
deleted file mode 100644
index 12a703d..0000000
--- a/XOM/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/XOM/tailwind.config.ts b/XOM/tailwind.config.ts
deleted file mode 100644
index aae1628..0000000
--- a/XOM/tailwind.config.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { Config } from "tailwindcss";
-import { designTokens } from "@public-web-portals/shared";
-
-const config: Config = {
- content: [
- "./app/**/*.{js,ts,jsx,tsx,mdx}",
- "./components/**/*.{js,ts,jsx,tsx,mdx}",
- ],
- theme: {
- extend: designTokens as Record,
- },
- plugins: [],
-};
-
-export default config;
diff --git a/XOM/tsconfig.json b/XOM/tsconfig.json
deleted file mode 100644
index cd32290..0000000
--- a/XOM/tsconfig.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "extends": "../tsconfig.base.json",
- "compilerOptions": {
- "plugins": [
- {
- "name": "next"
- }
- ],
- "module": "ESNext",
- "moduleResolution": "bundler",
- "jsx": "preserve",
- "noEmit": true,
- "incremental": true,
- "paths": {
- "@/*": [
- "./*"
- ]
- },
- "allowJs": true
- },
- "include": [
- "next-env.d.ts",
- "**/*.ts",
- "**/*.tsx",
- ".next/types/**/*.ts"
- ],
- "exclude": [
- "node_modules"
- ]
-}