Wszystkie projekty
🛰️ AI Delivery Cockpit · Blazor .NET 10 · Homelab

DevHubPlatform

Prywatny „AI delivery cockpit" — Azure DevOps dla małego zaufanego zespołu, z jednym spójnym modelem bezpiecznych akcji AI: propozycja → potwierdzenie → ponowna autoryzacja po stronie serwera → audyt.

24/7 Produkcja na homelabie
100% Mutujących akcji AI za bramką autoryzacji
~36k LOC Skala rozwiązania (solo)
Przewiń w dół
Klient Projekt własny (homelab)
Branża DevTools / AI Delivery Platform
Czas trwania W ciągłym rozwoju (kilka miesięcy, produkcja 24/7)
Moja rola Solo Architect & Developer (twórca i architekt)
01

Przegląd projektu

DevHubPlatform to prywatny „AI delivery cockpit" — jedno miejsce, które zamienia nieustrukturyzowany strumień pracy (czat, poczta, spotkania wideo z transkrypcją na żywo) w zatwierdzone tickety, pamięć projektu i faktycznie wykonany kod, domykając rezultat testem, wdrożeniem i audytem. Działa jak prywatny Azure DevOps dla małego, zaufanego zespołu, ale z AI wplecionym w każdy etap golden path: agent proponuje decyzję lub ticket, człowiek zatwierdza, a uprawniony deweloper uruchamia agenta w izolowanym workspace projektu (tmux + bubblewrap per użytkownik OS, bez Dockera). Rdzeniem jest jeden spójny model bezpiecznych akcji AI — propozycja → jawne potwierdzenie → ponowna autoryzacja po stronie serwera → audyt — egzekwowany serwerowo, nie w UI. Stack to .NET 10 Blazor Web App (global InteractiveServer + WASM), MudBlazor 9.5, ASP.NET Identity, EF Core 10 / Npgsql / PostgreSQL, SignalR + WebRTC oraz współdzielony silnik AiLiveRoom (5 modułów przez ProjectReference). Hostowane na homelabie Dell R620 pod platform.aidamian.uk (Cloudflare Tunnel → nginx → Kestrel, systemd, EF MigrateAsync przy starcie).

🔐 Jeden spójny model bezpiecznych akcji AI: żadne mutujące narzędzie nie wykonuje się „na słowo" modelu — po potwierdzeniu ExecuteConfirmedActionAsync PONOWNIE liczy efektywny dostęp (ProjectAccessLevelAsync) i dopiero wtedy zapisuje. UI-owe bramki ról to tylko wygoda, nigdy granica autoryzacji.
📦 Multi-dev izolacja wykonania na jednym hoście BEZ Dockera: każdy nie-owner dostaje własnego użytkownika OS, cztery ortogonalne pokrętła (OsUser / CanSudo / WorkspaceMode / SandboxMode), a komendy owijane w bubblewrap (ro-bind /usr /etc /bin, prywatny /proc /dev /tmp, --unshare-net w trybie Strict).
🎥 Spotkanie jako pierwszorzędne źródło pracy: WebRTC mesh + transkrypcja na żywo (Whisper + Azure) → AI generuje kandydatów na tickety/pamięć. Sygnalizacja server-authoritative wiąże peer↔uczestnika (dany peerId może przejąć tylko ten sam ParticipantId), więc crafted call nie przejmie cudzego strumienia ani nie dołączy do pokoju po GUID.
👤 Sandbox gości bez tabeli zaproszeń: podpisany, odwoływalny token (ASP.NET Data Protection, base64url w ścieżce URL) + dual auth-scheme (DevHubSmart PolicyScheme). Gość pojawia się w AuthenticationState, ale DefaultPolicy (!HasClaim("guest","1")) daje mu AccessDenied na każdej normalnej stronie.
02

Wyzwanie

Zbudować w pojedynkę prywatny odpowiednik Azure DevOps, w którym AI realnie wykonuje pracę (tickety, komentarze, pamięć, analiza poczty, kod, deploy), a mimo to NIGDY nie przeprowadza ryzykownej mutacji bez człowieka — i to wszystko na jednym homelabowym serwerze współdzielonym przez wielu deweloperów oraz gości. Największe napięcie: dać AI dużą sprawczość i jednocześnie twardą, serwerowo egzekwowaną granicę bezpieczeństwa; pozwolić kilku deweloperom (i ich agentom AI) pracować równolegle w tych samych repozytoriach bez zadeptywania cudzego working tree i bez dostępu do konta oraz sekretów właściciela; wpuścić niezaufanego gościa do jednego pokoju spotkania, nie otwierając reszty platformy; a nad hałaśliwym strumieniem transkrypcji na żywo utrzymać tani, stabilny i odporny na prompt-injection potok AI.

  • Bezpieczna sprawczość AI: każde mutujące narzędzie (ticket, komentarz, wpis pamięci, karta ze spotkania) musi zwracać propozycję (FloatingAssistantAction z RequiresConfirmation), a faktyczny zapis dopiero po ponownym, serwerowym przeliczeniu uprawnień — nie można ufać temu, że „model tak zdecydował" ani bramkom w UI.
  • Multi-dev izolacja bez Dockera (reguła projektu): kilku deweloperów i ich agentów AI na jednym R620, każdy z własnym kontem OS, opcjonalnym worktree/klonem i sandboxem bubblewrap — a zaproszony członek NIE może po cichu odziedziczyć konta ownera (hdtdtr/root/sudo).
  • Sandbox gościa spotkania: wpuścić niezaufaną osobę przez podpisany, odwoływalny link do JEDNEGO pokoju, tak by pojawiła się w Blazorowym AuthenticationState, ale była zablokowana na każdej innej stronie, API, hubie i re-wejściu media — bez osobnej tabeli zaproszeń.
  • Stabilne AI na żywo: nad strumieniem transkrypcji utrzymać analizę tematu jako single-flight (koalescencja żądań, atomowy claim przez Interlocked.CompareExchange), zmianę tematu za dwugłosową histerezą (RequiredShiftConfirmations = 2), hierarchię dowodów (fakty vs. niezweryfikowane tropy) i obronę przed prompt-injection — na trzech rolach modeli (terra/luna/sol) z produkcyjnym hardeningiem Azure.
03

Rozwiązanie

Rdzeniem jest propose → confirm → server-side re-authorize → audit: mutujące narzędzia asystenta zwracają FloatingAssistantAction z RequiresConfirmation, a realny zapis następuje dopiero w ExecuteConfirmedActionAsync, które ponownie liczy ProjectAccessLevelAsync i odrzuca akcję przy braku uprawnień (próg AccessLevel.Designer) — potwierdzenie w UI nie jest granicą autoryzacji (gotcha #11/#13). Wykonanie kodu izoluje ExecutionProfileService + TmuxAgentService: UserExecutionProfile to cztery ortogonalne pokrętła (OsUser, CanSudo, WorkspaceMode, SandboxMode), a BuildSudoArgs owija komendę w bubblewrap (ro-bind /usr /etc /bin, prywatny /proc /dev /tmp, --unshare-net dla Strict); ResolveForTerminalAsync twardo odmawia, gdy profil celuje w hdtdtr/root albo ma CanSudo, a sesje solo żyją na własnym serwerze tmux dewelopera. Spotkania obsługuje współdzielony silnik AiLiveRoom (5 modułów przez ProjectReference) spięty z hostem przez DevHubLiveRoomHostAdapter; LiveRoomHub wiąże peer↔uczestnika serwerowo, a LiveRoomAiRuntime trzyma analizę tematu jako single-flight z dwugłosową histerezą, hierarchią dowodów i obroną przed prompt-injection na modelach Azure OpenAI GPT-5.6 (terra/luna/sol). Gości sandboxuje DevHubSmart PolicyScheme z ForwardDefaultSelector i podpisanymi, odwoływalnymi tokenami (RoomInviteService, znacznik RevokedBeforeUtc). Notyfikacje idą przez kanoniczny outbox NotificationOutboxWorker z re-checkiem preferencji, profilu i dostępu w momencie wysyłki.

Wykorzystane technologie

.NET 10 / Blazor Web App (global InteractiveServer + WASM)
MudBlazor 9.5.0
ASP.NET Core Identity 10.0.5 (custom DevHubSmart PolicyScheme)
EF Core 10 + Npgsql.EntityFrameworkCore.PostgreSQL 10.0.1
PostgreSQL (devhubplat)
SignalR + WebRTC mesh (Cloudflare Realtime TURN)
Azure OpenAI GPT-5.6 (terra/luna/sol)
Google Gemini Live (gemini-3.1-flash-live-preview)
Whisper (Mac mini) + Azure Speech Translation
MailKit 4.16 · Markdig 1.3.2 · SixLabors.ImageSharp 3.1.12
tmux + bubblewrap (per-OS-user agent isolation, no Docker)
Cloudflare Tunnel → nginx → Kestrel · systemd · Dell R620
xUnit 2.9.3 · Playwright (Node.js e2e / WebRTC 2-peer)
HashiCorp Vault · Telegram + WhatsApp Cloud API (HMAC webhooks)
04

Rezultaty

24/7
Produkcja na homelabie

Działa pod platform.aidamian.uk na Dell R620: systemd devhubplatform.service, Kestrel 127.0.0.1:5061, ścieżka Cloudflare Tunnel → nginx → Kestrel, EF MigrateAsync przy starcie (28 migracji), własny login Identity zamiast Cloudflare Access. Deploy lokalny (tar źródła na Windows → scp → dotnet publish -c Release na R620 → rsync do releases → symlink current → restart systemd), bez CI/GitHub Actions.

100%
Mutujących akcji AI za bramką autoryzacji

Każde mutujące narzędzie AI (tickety, komentarze, wpisy pamięci, pokoje/karty ze spotkań; maile pozostają wersją roboczą — wysyłka przez osobne potwierdzenie composera) przechodzi przez propozycja → jawne potwierdzenie → ponowna, serwerowa reautoryzacja (ProjectAccessLevelAsync) → audyt (AuditEntry). UI-owe bramki ról są tylko wygodą; granica jest zawsze po stronie serwera. Terminal odmawia zawsze, gdy profil to hdtdtr/root lub ma CanSudo.

~36k LOC
Skala rozwiązania (solo)

Monorepo: 130 plików C# (52 w Services/, z tego 34 bezpośrednio + 18 w podkatalogach LiveRooms/ExternalMessaging), 105 komponentów Blazor (34 trasy @page), model domenowy 38 DbSet / 66 typów (38 klas + 28 enumów) w Domain.cs (769 LOC), PlatformService.cs 1525 LOC, Program.cs 1118 LOC, 65 testów xUnit oraz 5 modułów silnika AiLiveRoom przez ProjectReference. ~36k LOC kodu aplikacyjnego (C# bez wygenerowanych migracji EF + Razor).

💬 Komentarze (0)

?

Zostaw komentarz

💭

Bądź pierwszy, który skomentuje!

🚀

Masz podobny projekt?

Porozmawiajmy o tym, jak mogę pomóc Twojej firmie osiągnąć podobne rezultaty.

Asystent AI Damiana

Online • Odpowiadam natychmiast

Cześć! 👋

Jestem asystentem AI Damiana. Zapytaj mnie o technologie, projekty lub jak mogę Ci pomóc!

Powered by GPT-5.6 • Odpowiedzi mogą zawierać błędy

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please reload the page.