import React, { useState } from 'react'; import { ManagedApp, DeploymentManifestItem, ExternalServerItem, AuditEventItem } from './types'; export const App: React.FC = () => { const [activeTab, setActiveTab] = useState<'dashboard' | 'apps' | 'deployments' | 'servers' | 'iam' | 'audit'>('dashboard'); const [apps] = useState([ { appId: 'com.thecr3w.app', name: 'TheCr3w Mobile', description: 'Aplikacja Android dla członków ekosystemu', isPublic: true, platforms: ['android'], defaultChannel: 'stable' }, { appId: 'thecr3w-desktop', name: 'TheCr3w Desktop', description: 'Klient stacjonarny Windows z automatycznym updaterem', isPublic: true, platforms: ['windows'], defaultChannel: 'stable' } ]); const [manifests, setManifests] = useState([ { manifestId: '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d', project: 'thecr3w-backend', environment: 'production', serviceName: 'backend', image: 'git.thecr3wnet.com/thecr3w/backend', immutableDigest: 'sha256:7a59d8134bb8df389a9f24255198ec51787c9dc08269d7b420f1885b0d0ce0bf', manifestSha256: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', status: 'pending_approval', createdAt: new Date().toISOString(), createdBy: 'forgejo-actions-bot' }, { manifestId: '1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d', project: 'thecr3w-download-center', environment: 'production', serviceName: 'download-center', image: 'git.thecr3wnet.com/thecr3w/download-center', immutableDigest: 'sha256:9c8b7a6f5e4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b', manifestSha256: '4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945', status: 'deployed', createdAt: new Date(Date.now() - 86400000).toISOString(), createdBy: 'admin' } ]); const [servers] = useState([ { serverId: '77a8b9c0-1122-3344-5566-778899aabbcc', name: 'Backup Mirror SFTP', protocol: 'sftp', host: 'mirror.thecr3wnet.com', port: 22, remoteRootPath: '/var/www/dist', hostKeyFingerprint: 'SHA256:7kX9JvM81uLwQzRp09b...', status: 'active', updatedAt: new Date().toISOString() } ]); const [auditLogs] = useState([ { eventId: '11111111-2222-3333-4444-555555555555', actor: 'admin', action: 'RELEASE_PUBLISHED', resourceType: 'release', resourceId: 'com.thecr3w.app:1.2.0', correlationId: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee', createdAt: new Date().toISOString(), success: true, ipAddress: '89.58.46.176' }, { eventId: '22222222-3333-4444-5555-666666666666', actor: 'forgejo-actions-bot', action: 'MANIFEST_REGISTERED', resourceType: 'deployment_manifest', resourceId: '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d', correlationId: 'bbbbbbbb-cccc-dddd-eeee-ffffffffffff', createdAt: new Date(Date.now() - 3600000).toISOString(), success: true, ipAddress: '89.58.46.176' } ]); function handleApprove(manifestId: string) { setManifests((prev) => prev.map((m) => (m.manifestId === manifestId ? { ...m, status: 'approved' } : m)) ); alert(`Manifest ${manifestId} zatwierdzony. Oczekiwanie na uruchomienie wdrożenia przez Deployment Agenta.`); } function handleReject(manifestId: string) { setManifests((prev) => prev.map((m) => (m.manifestId === manifestId ? { ...m, status: 'rejected' } : m)) ); } return (
{activeTab === 'dashboard' && (

Dashboard Operacyjny

ŚRODOWISKO ZDROWE
Aktywne Aplikacje
{apps.length}
Oczekujące Akceptacje Wdrożeń
{manifests.filter((m) => m.status === 'pending_approval').length}
Podłączone Serwery Zewnętrzne
{servers.length}
Zdarzenia Audytowe (24h)
{auditLogs.length}

Wymagane Działania: Zatwierdzenia Wdrożeń

{manifests .filter((m) => m.status === 'pending_approval') .map((m) => ( ))}
Projekt Środowisko Immutable Digest Autor Status Akcja
{m.project} {m.environment} {m.immutableDigest.substring(0, 24)}... {m.createdBy} Oczekuje na SHA256
)} {activeTab === 'apps' && (

Zarządzanie Aplikacjami Natywnymi

{apps.map((a) => ( ))}
ID Aplikacji Nazwa Platformy Domyślny Kanał Publiczna Akcje
{a.appId} {a.name} {a.platforms.join(', ')} {a.defaultChannel} {a.isPublic ? TAK : NIE}
)} {activeTab === 'deployments' && (

Historia Wdrożeń Kontenerów Docker

{manifests.map((m) => ( ))}
Manifest ID Projekt Usługa Immutable Digest Status Utworzono
{m.manifestId.substring(0, 8)}... {m.project} {m.serviceName} {m.immutableDigest.substring(0, 28)}... {m.status.toUpperCase()} {new Date(m.createdAt).toLocaleString()}
)} {activeTab === 'servers' && (

Serwery Zewnętrzne (SFTP / FTPS)

{servers.map((s) => ( ))}
Nazwa Protokół Host & Port Zdalna Ścieżka Host Key Pinning Status
{s.name} {s.protocol.toUpperCase()} {s.host}:{s.port} {s.remoteRootPath} {s.hostKeyFingerprint} {s.status.toUpperCase()}
)} {activeTab === 'iam' && (

Zarządzanie Tożsamością i Rolami (Keycloak IAM)

Konfiguracja OIDC w Realm `master`

Wszystkie uprawnienia TheCr3w-dev są zdefiniowane jako role klienta (Client Roles) w obrębie thecr3w-backend, co zapobiega nadaniu uprawnień administracyjnych serwera Keycloak.

Rola Klienta Zakres Uprawnień Przypisane Grupy / Konta
thecr3w:admin Pełna administracja całym systemem, zarządzanie kluczami i audyt Grupa: thecr3w-administrators
thecr3w:release-manager Publikacja wydań, upload R2, podpisywanie Ed25519, wycofywanie Grupa: thecr3w-release-managers
thecr3w:approver Zatwierdzanie wdrożeń produkcyjnych (weryfikacja SHA256) Grupa: thecr3w-approvers
thecr3w:deployer Zgłaszanie manifestów i synchronizacja SFTP/FTPS Konto: forgejo-ci-service-account
thecr3w:viewer Dostęp tylko do odczytu: podgląd dashboardu i logów Wszyscy uwierzytelnieni użytkownicy TheCr3w
)} {activeTab === 'audit' && (

Niezmienny Dziennik Audytowy

{auditLogs.map((log) => ( ))}
Data i Czas Aktor Akcja Zasób ID Zasobu IP Status
{new Date(log.createdAt).toLocaleString()} {log.actor} {log.action} {log.resourceType} {log.resourceId} {log.ipAddress || '—'} {log.success ? OK : FAIL}
)}
); };