[split-required] [guardrail-change] Enforce 500 LOC budget across all services

Install LOC guardrails (check-loc.sh, architecture.md, pre-commit hook)
and split all 44 files exceeding 500 LOC into domain-focused modules:

- consent-service (Go): models, handlers, services, database splits
- backend-core (Python): security_api, rbac_api, pdf_service, auth splits
- admin-core (TypeScript): 5 page.tsx + sidebar extractions
- pitch-deck (TypeScript): 6 slides, 3 UI components, engine.ts splits
- voice-service (Python): enhanced_task_orchestrator split

Result: 0 violations, 36 exempted (pipeline, tests, pure-data files).
Go build verified clean. No behavior changes — pure structural splits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-27 00:09:30 +02:00
parent 5ef039a6bc
commit 92c86ec6ba
162 changed files with 23853 additions and 23034 deletions

View File

@@ -2,17 +2,10 @@ package jitsi
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/google/uuid"
)
// JitsiService handles Jitsi Meet integration for video conferences
@@ -292,275 +285,3 @@ func (s *JitsiService) CreateClassMeeting(ctx context.Context, className string,
return s.CreateMeetingLink(ctx, meeting)
}
// ========================================
// JWT Generation
// ========================================
// generateJWT creates a signed JWT for Jitsi authentication
func (s *JitsiService) generateJWT(meeting Meeting, roomName string) (string, *time.Time, error) {
if s.appSecret == "" {
return "", nil, fmt.Errorf("app secret not configured")
}
now := time.Now()
// Default expiration: 24 hours or based on meeting duration
expiration := now.Add(24 * time.Hour)
if meeting.Duration > 0 {
expiration = now.Add(time.Duration(meeting.Duration+30) * time.Minute)
}
if meeting.StartTime != nil {
expiration = meeting.StartTime.Add(time.Duration(meeting.Duration+60) * time.Minute)
}
claims := JWTClaims{
Audience: "jitsi",
Issuer: s.appID,
Subject: "meet.jitsi",
Room: roomName,
ExpiresAt: expiration.Unix(),
NotBefore: now.Add(-5 * time.Minute).Unix(), // 5 min grace period
Moderator: meeting.Moderator,
Context: &JWTContext{
User: &JWTUser{
ID: uuid.New().String(),
Name: meeting.DisplayName,
Email: meeting.Email,
Avatar: meeting.Avatar,
Moderator: meeting.Moderator,
},
},
}
// Add features if specified
if meeting.Features != nil {
claims.Features = &JWTFeatures{
Recording: boolToString(meeting.Features.Recording),
Livestreaming: boolToString(meeting.Features.Livestreaming),
Transcription: boolToString(meeting.Features.Transcription),
OutboundCall: boolToString(meeting.Features.OutboundCall),
}
}
// Create JWT
token, err := s.signJWT(claims)
if err != nil {
return "", nil, err
}
return token, &expiration, nil
}
// signJWT creates and signs a JWT token
func (s *JitsiService) signJWT(claims JWTClaims) (string, error) {
// Header
header := map[string]string{
"alg": "HS256",
"typ": "JWT",
}
headerJSON, err := json.Marshal(header)
if err != nil {
return "", err
}
// Payload
payloadJSON, err := json.Marshal(claims)
if err != nil {
return "", err
}
// Encode
headerB64 := base64.RawURLEncoding.EncodeToString(headerJSON)
payloadB64 := base64.RawURLEncoding.EncodeToString(payloadJSON)
// Sign
message := headerB64 + "." + payloadB64
h := hmac.New(sha256.New, []byte(s.appSecret))
h.Write([]byte(message))
signature := base64.RawURLEncoding.EncodeToString(h.Sum(nil))
return message + "." + signature, nil
}
// ========================================
// Health Check
// ========================================
// HealthCheck verifies the Jitsi server is accessible
func (s *JitsiService) HealthCheck(ctx context.Context) error {
req, err := http.NewRequestWithContext(ctx, "GET", s.baseURL, nil)
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
resp, err := s.httpClient.Do(req)
if err != nil {
return fmt.Errorf("jitsi server unreachable: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 500 {
return fmt.Errorf("jitsi server error: status %d", resp.StatusCode)
}
return nil
}
// GetServerInfo returns information about the Jitsi server
func (s *JitsiService) GetServerInfo() map[string]string {
return map[string]string{
"base_url": s.baseURL,
"app_id": s.appID,
"auth_enabled": boolToString(s.appSecret != ""),
}
}
// ========================================
// URL Building
// ========================================
// BuildEmbedURL creates an embeddable iframe URL
func (s *JitsiService) BuildEmbedURL(roomName string, displayName string, config *MeetingConfig) string {
params := url.Values{}
if displayName != "" {
params.Set("userInfo.displayName", displayName)
}
if config != nil {
if config.StartWithAudioMuted {
params.Set("config.startWithAudioMuted", "true")
}
if config.StartWithVideoMuted {
params.Set("config.startWithVideoMuted", "true")
}
if config.DisableDeepLinking {
params.Set("config.disableDeepLinking", "true")
}
}
embedURL := fmt.Sprintf("%s/%s", s.baseURL, s.sanitizeRoomName(roomName))
if len(params) > 0 {
embedURL += "#" + params.Encode()
}
return embedURL
}
// BuildIFrameCode generates HTML iframe code for embedding
func (s *JitsiService) BuildIFrameCode(roomName string, width int, height int) string {
if width == 0 {
width = 800
}
if height == 0 {
height = 600
}
return fmt.Sprintf(
`<iframe src="%s/%s" width="%d" height="%d" allow="camera; microphone; fullscreen; display-capture; autoplay" style="border: 0;"></iframe>`,
s.baseURL,
s.sanitizeRoomName(roomName),
width,
height,
)
}
// ========================================
// Helper Functions
// ========================================
// generateRoomName creates a unique room name
func (s *JitsiService) generateRoomName() string {
return fmt.Sprintf("breakpilot-%s", uuid.New().String()[:8])
}
// generateTrainingRoomName creates a room name for training sessions
func (s *JitsiService) generateTrainingRoomName(title string) string {
sanitized := s.sanitizeRoomName(title)
if sanitized == "" {
sanitized = "schulung"
}
return fmt.Sprintf("%s-%s", sanitized, time.Now().Format("20060102-1504"))
}
// sanitizeRoomName removes invalid characters from room names
func (s *JitsiService) sanitizeRoomName(name string) string {
// Replace spaces and special characters
result := strings.ToLower(name)
result = strings.ReplaceAll(result, " ", "-")
result = strings.ReplaceAll(result, "ä", "ae")
result = strings.ReplaceAll(result, "ö", "oe")
result = strings.ReplaceAll(result, "ü", "ue")
result = strings.ReplaceAll(result, "ß", "ss")
// Remove any remaining non-alphanumeric characters except hyphen
var cleaned strings.Builder
for _, r := range result {
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' {
cleaned.WriteRune(r)
}
}
// Remove consecutive hyphens
result = cleaned.String()
for strings.Contains(result, "--") {
result = strings.ReplaceAll(result, "--", "-")
}
// Trim hyphens from start and end
result = strings.Trim(result, "-")
// Limit length
if len(result) > 50 {
result = result[:50]
}
return result
}
// generatePassword creates a random meeting password
func (s *JitsiService) generatePassword() string {
return uuid.New().String()[:8]
}
// buildConfigParams creates URL parameters from config
func (s *JitsiService) buildConfigParams(config *MeetingConfig) string {
params := url.Values{}
if config.StartWithAudioMuted {
params.Set("config.startWithAudioMuted", "true")
}
if config.StartWithVideoMuted {
params.Set("config.startWithVideoMuted", "true")
}
if config.DisableDeepLinking {
params.Set("config.disableDeepLinking", "true")
}
if config.RequireDisplayName {
params.Set("config.requireDisplayName", "true")
}
if config.EnableLobby {
params.Set("config.enableLobby", "true")
}
return params.Encode()
}
// boolToString converts bool to "true"/"false" string
func boolToString(b bool) string {
if b {
return "true"
}
return "false"
}
// GetBaseURL returns the configured base URL
func (s *JitsiService) GetBaseURL() string {
return s.baseURL
}
// IsAuthEnabled returns whether JWT authentication is configured
func (s *JitsiService) IsAuthEnabled() bool {
return s.appSecret != ""
}

View File

@@ -0,0 +1,290 @@
package jitsi
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"crypto/hmac"
"crypto/sha256"
"github.com/google/uuid"
)
// ========================================
// JWT Generation
// ========================================
// generateJWT creates a signed JWT for Jitsi authentication
func (s *JitsiService) generateJWT(meeting Meeting, roomName string) (string, *time.Time, error) {
if s.appSecret == "" {
return "", nil, fmt.Errorf("app secret not configured")
}
now := time.Now()
// Default expiration: 24 hours or based on meeting duration
expiration := now.Add(24 * time.Hour)
if meeting.Duration > 0 {
expiration = now.Add(time.Duration(meeting.Duration+30) * time.Minute)
}
if meeting.StartTime != nil {
expiration = meeting.StartTime.Add(time.Duration(meeting.Duration+60) * time.Minute)
}
claims := JWTClaims{
Audience: "jitsi",
Issuer: s.appID,
Subject: "meet.jitsi",
Room: roomName,
ExpiresAt: expiration.Unix(),
NotBefore: now.Add(-5 * time.Minute).Unix(), // 5 min grace period
Moderator: meeting.Moderator,
Context: &JWTContext{
User: &JWTUser{
ID: uuid.New().String(),
Name: meeting.DisplayName,
Email: meeting.Email,
Avatar: meeting.Avatar,
Moderator: meeting.Moderator,
},
},
}
// Add features if specified
if meeting.Features != nil {
claims.Features = &JWTFeatures{
Recording: boolToString(meeting.Features.Recording),
Livestreaming: boolToString(meeting.Features.Livestreaming),
Transcription: boolToString(meeting.Features.Transcription),
OutboundCall: boolToString(meeting.Features.OutboundCall),
}
}
// Create JWT
token, err := s.signJWT(claims)
if err != nil {
return "", nil, err
}
return token, &expiration, nil
}
// signJWT creates and signs a JWT token
func (s *JitsiService) signJWT(claims JWTClaims) (string, error) {
// Header
header := map[string]string{
"alg": "HS256",
"typ": "JWT",
}
headerJSON, err := json.Marshal(header)
if err != nil {
return "", err
}
// Payload
payloadJSON, err := json.Marshal(claims)
if err != nil {
return "", err
}
// Encode
headerB64 := base64.RawURLEncoding.EncodeToString(headerJSON)
payloadB64 := base64.RawURLEncoding.EncodeToString(payloadJSON)
// Sign
message := headerB64 + "." + payloadB64
h := hmac.New(sha256.New, []byte(s.appSecret))
h.Write([]byte(message))
signature := base64.RawURLEncoding.EncodeToString(h.Sum(nil))
return message + "." + signature, nil
}
// ========================================
// Health Check
// ========================================
// HealthCheck verifies the Jitsi server is accessible
func (s *JitsiService) HealthCheck(ctx context.Context) error {
req, err := http.NewRequestWithContext(ctx, "GET", s.baseURL, nil)
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
resp, err := s.httpClient.Do(req)
if err != nil {
return fmt.Errorf("jitsi server unreachable: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 500 {
return fmt.Errorf("jitsi server error: status %d", resp.StatusCode)
}
return nil
}
// GetServerInfo returns information about the Jitsi server
func (s *JitsiService) GetServerInfo() map[string]string {
return map[string]string{
"base_url": s.baseURL,
"app_id": s.appID,
"auth_enabled": boolToString(s.appSecret != ""),
}
}
// ========================================
// URL Building
// ========================================
// BuildEmbedURL creates an embeddable iframe URL
func (s *JitsiService) BuildEmbedURL(roomName string, displayName string, config *MeetingConfig) string {
params := url.Values{}
if displayName != "" {
params.Set("userInfo.displayName", displayName)
}
if config != nil {
if config.StartWithAudioMuted {
params.Set("config.startWithAudioMuted", "true")
}
if config.StartWithVideoMuted {
params.Set("config.startWithVideoMuted", "true")
}
if config.DisableDeepLinking {
params.Set("config.disableDeepLinking", "true")
}
}
embedURL := fmt.Sprintf("%s/%s", s.baseURL, s.sanitizeRoomName(roomName))
if len(params) > 0 {
embedURL += "#" + params.Encode()
}
return embedURL
}
// BuildIFrameCode generates HTML iframe code for embedding
func (s *JitsiService) BuildIFrameCode(roomName string, width int, height int) string {
if width == 0 {
width = 800
}
if height == 0 {
height = 600
}
return fmt.Sprintf(
`<iframe src="%s/%s" width="%d" height="%d" allow="camera; microphone; fullscreen; display-capture; autoplay" style="border: 0;"></iframe>`,
s.baseURL,
s.sanitizeRoomName(roomName),
width,
height,
)
}
// ========================================
// Helper Functions
// ========================================
// generateRoomName creates a unique room name
func (s *JitsiService) generateRoomName() string {
return fmt.Sprintf("breakpilot-%s", uuid.New().String()[:8])
}
// generateTrainingRoomName creates a room name for training sessions
func (s *JitsiService) generateTrainingRoomName(title string) string {
sanitized := s.sanitizeRoomName(title)
if sanitized == "" {
sanitized = "schulung"
}
return fmt.Sprintf("%s-%s", sanitized, time.Now().Format("20060102-1504"))
}
// sanitizeRoomName removes invalid characters from room names
func (s *JitsiService) sanitizeRoomName(name string) string {
// Replace spaces and special characters
result := strings.ToLower(name)
result = strings.ReplaceAll(result, " ", "-")
result = strings.ReplaceAll(result, "ä", "ae")
result = strings.ReplaceAll(result, "ö", "oe")
result = strings.ReplaceAll(result, "ü", "ue")
result = strings.ReplaceAll(result, "ß", "ss")
// Remove any remaining non-alphanumeric characters except hyphen
var cleaned strings.Builder
for _, r := range result {
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' {
cleaned.WriteRune(r)
}
}
// Remove consecutive hyphens
result = cleaned.String()
for strings.Contains(result, "--") {
result = strings.ReplaceAll(result, "--", "-")
}
// Trim hyphens from start and end
result = strings.Trim(result, "-")
// Limit length
if len(result) > 50 {
result = result[:50]
}
return result
}
// generatePassword creates a random meeting password
func (s *JitsiService) generatePassword() string {
return uuid.New().String()[:8]
}
// buildConfigParams creates URL parameters from config
func (s *JitsiService) buildConfigParams(config *MeetingConfig) string {
params := url.Values{}
if config.StartWithAudioMuted {
params.Set("config.startWithAudioMuted", "true")
}
if config.StartWithVideoMuted {
params.Set("config.startWithVideoMuted", "true")
}
if config.DisableDeepLinking {
params.Set("config.disableDeepLinking", "true")
}
if config.RequireDisplayName {
params.Set("config.requireDisplayName", "true")
}
if config.EnableLobby {
params.Set("config.enableLobby", "true")
}
return params.Encode()
}
// boolToString converts bool to "true"/"false" string
func boolToString(b bool) string {
if b {
return "true"
}
return "false"
}
// GetBaseURL returns the configured base URL
func (s *JitsiService) GetBaseURL() string {
return s.baseURL
}
// IsAuthEnabled returns whether JWT authentication is configured
func (s *JitsiService) IsAuthEnabled() bool {
return s.appSecret != ""
}