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.
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).
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.
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
Rezultaty
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.
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.
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).
Masz podobny projekt?
Porozmawiajmy o tym, jak mogę pomóc Twojej firmie osiągnąć podobne rezultaty.
💬 Komentarze (0)
Zostaw komentarz
Bądź pierwszy, który skomentuje!