بنقرة واحدة
bedrud-server
Full Go backend code map. Load for any server/API/auth/DB/model/handler work.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Full Go backend code map. Load for any server/API/auth/DB/model/handler work.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Admin endpoints — users, rooms, queue, settings, invite tokens, webhooks, overview, recordings.
Auth endpoints — JWT flow, local/OAuth/passkey/verify/password-reset/avatar/preferences.
Room endpoints — CRUD, join, moderation, presence, chat upload, stage stubs, recording.
Complete Bedrud API endpoint reference. Dense index of every route, middleware, status code; deep detail in leaf skills.
All DTO definitions, source file index, Swagger reference.
Auth service + middleware — JWT, passkeys, OAuth, session store, rate limiting, recordings gate.
| name | bedrud-server |
| description | Full Go backend code map. Load for any server/API/auth/DB/model/handler work. |
| license | Apache License |
Go module bedrud. Root: server/. Fiber HTTP + GORM + embedded LiveKit + job queue.
Leaf skills (deeper detail when needed):
| Skill | Scope |
|---|---|
bedrud-http | Entrypoints, bootstrap, handlers, routes, lkutil |
bedrud-auth | AuthService, JWT, middleware, rate limits |
bedrud-data | Models, repos, migrations, testutil |
bedrud-jobs | Queue, scheduler, cleanup, recording service/store, chat storage |
bedrud-realtime | Embedded LiveKit binary lifecycle |
bedrud-ops-cli | Cobra CLI, installer, usercli/roomcli, utils |
bedrud-email-cerberus | Email templates + send_email branding |
cmd/bedrud/main.go — Production CLIThin wrapper → cli.Execute(version) (Cobra in internal/cli/). Legacy flags still work (--run, --livekit, --version).
| Command | Calls | Purpose |
|---|---|---|
run / server | server.Run(configPath, version) | Full app (API + optional embedded LK + SPA) |
livekit / --livekit | livekit.RunLiveKit(configPath) | Standalone LK binary |
install / uninstall | install.LinuxInstall / LinuxUninstall | Linux installer (systemd/OpenRC/SysV) |
user * | usercli.* | create/delete/promote/demote/list/info/password/enable/disable |
room * | roomcli.* | list/info/close/suspend/reactivate/kick |
config / settings / invite-token / cert / db | respective CLI | Ops tooling |
version | Version string |
Config: --config, BEDRUD_CONFIG, or CONFIG_PATH. Management cmds default /etc/bedrud/config.yaml.
cmd/server/main.go — Dev API (Air)No Cobra. Wires subsystems + routes + Swagger/Scalar + SPA. Minor drift vs prod (GET /admin/stats still registered here; prod uses overview). Prefer internal/server/server.go as source of truth.
Health: GET /api/health · Ready: GET /api/ready. Docs: /api/swagger/*, /api/scalar. Disable: DISABLE_API_DOCS.
ui.go — Frontend embed//go:embed all:frontend → UI embed.FS. make build copies apps/web/build/* → server/frontend/.
server/internal/)| Package | Role |
|---|---|
server/ | Prod bootstrap Run(configPath, version) |
handlers/ | HTTP handlers (auth, room, users, admin, recording, webhook, cert, queue) |
auth/ | AuthService, JWT, session store, challenge store, email canonicalize |
middleware/ | Protected, RBAC, CSRF bearer-for-mutations, guest reject, email-verify, rate limit, recordings gate |
models/ | GORM models + admin/overview DTOs |
repository/ | Data access (user, room, passkey, settings, invite, prefs, verification, webhook, recording) |
database/ | GORM init (SQLite/Postgres), AutoMigrate + PG FKs |
queue/ | Job enqueue/worker + 8 handlers + email templates |
scheduler/ | gocron: idle rooms, guests, unverified, tokens, queue cleanup, cert, recording retention |
services/ | RoomCleanupService, RecordingService |
storage/ | Chat upload, avatar, recording store |
livekit/ | Embedded LK binary + temp YAML + process mgmt |
lkutil/ | RoomService/Egress clients, AuthContext, system messages |
cli/ | Cobra command surface |
clioutput/ | --json envelopes |
usercli/ / roomcli/ | CLI domain ops |
install/ | LinuxInstall / LinuxUninstall |
utils/ | TLS certs, SMTP, keys, safeio, net |
testutil/ | In-memory SQLite + LiveKit mocks |
templates/ | Legacy HTML (login/index) — SPA usually embedded |
internal/server/server.go)Run(configPath, version) error sequence:
room, user, recording, …)recordingRepo live; recStore/recCfg currently nil until store wired)Init + hydrate ban set from inactive users*)/livekit when internal/api routes + static uploads + SPAhttpPortRecording bootstrap gap (important): handler, service, repo, store, queue types, and webhook processing are implemented, but prod server.Run still has commented blocks for:
NewRecordingStore / egress client / RecordingService / RecordingHandlerprocess_recording, recording_delete/api/rooms/:id/... and admin recording routesWire same pattern as integration tests when enabling. Jobs enqueued without a registered handler → permanent fail.
All API under Fiber group /api (@BasePath /api).
| Area | Prefix | Notes |
|---|---|---|
| Room lifecycle + moderation | /api/room/... (singular) | create, join, list, :roomId/* |
| Recording | /api/rooms/:id/... (plural) | SHIPPED code; routes still commented in bootstrap |
| Auth | /api/auth/... | register, login, passkeys, verify, preferences, OAuth |
| Admin | /api/admin/... | superadmin group |
| LiveKit webhook | POST /api/livekit/webhook | LK JWT, not app JWT |
| Static | /uploads/chat/* (auth), /uploads/avatars/* (public) | |
| Embedded LK proxy | /livekit/* | internal only |
Admin group middleware: Protected → RequireEmailVerified → RequireAccess(superadmin).
/api/health /api/ready
/api/auth/* register, login, guest-login, refresh, logout
me, me/avatar, password, verify*, forgot/reset
passkey/*, preferences, settings (public)
:provider/login|callback
/api/room/* create, join, guest-join, refresh-token, list, archived
:roomId/{kick,mute,ban,video,promote,demote,chat,deafen,
undeafen,ask,spotlight,screenshare,presence,
participant,stage,settings,chat/upload}
DELETE :roomId → 202 room_delete
/api/rooms/:id/recording* (IMPLEMENTED; bootstrap routes commented)
/api/admin/* users*, rooms*, settings*, invite-tokens, webhooks*
overview, queue, cert-info, online-count, livekit/stats
recordings* (IMPLEMENTED; bootstrap commented)
/api/livekit/webhook
/api/cert
/uploads/chat/* /uploads/avatars/*
/livekit/* (internal LK reverse proxy)
| Handler | Route |
|---|---|
BringToStage | POST /api/room/:roomId/stage/:identity/bring |
RemoveFromStage | POST /api/room/:roomId/stage/:identity/remove |
AdminGenerateToken | POST /api/admin/rooms/:roomId/token |
Repo stage helpers (BringToStage/RemoveFromStage on participants) exist; HTTP layer returns 501.
Do not call email, webhook, or recording “stubs” — they are implemented at handler/service/queue layer.
internal/handlers/)| File | Responsibility |
|---|---|
auth.go | OAuth begin/callback (goth) |
auth_handler.go | Local auth, passkeys, profile/avatar, verify, password reset |
room.go | Room lifecycle, moderation, chat upload, admin room ops |
recording_handler.go | Start/stop/list/get/wait/clear + admin list/bulk delete → RecordingService |
users.go | Admin users, bulk, force-logout, verify, async delete |
admin_handler.go | Settings, invite tokens, webhooks, test email, validate |
preferences_handler.go | User JSON prefs ≤4KB |
admin_overview.go | Aggregated KPIs / health |
admin_queue.go | Queue stats + email diagnostics |
cert_handler.go | Cert PEM download + admin cert-info |
livekit_webhook.go | participant_left, room_finished, egress_started, egress_ended |
cooldown.go / errors.go / room_auth.go / models.go | Shared helpers + DTOs |
| Method | Path | Notes |
|---|---|---|
| POST | /auth/register, /login, /guest-login, /refresh | Rate limited |
| POST | /auth/logout | Protected |
| GET/PUT | /auth/me | Protected + email verified |
| POST/DELETE | /auth/me/avatar | Avatar upload |
| PUT | /auth/password | Change password |
| POST/GET | /auth/verify, /verify/status, /verify/resend | Email verification |
| POST | /auth/forgot-password, /reset-password | Reset flow |
| POST | /auth/passkey/* | Register/login/signup begin+finish |
| GET/PUT | /auth/preferences | Prefs |
| GET | /auth/settings | Public flags (incl. recordingsEnabled) |
| GET | /auth/:provider/login|callback | OAuth |
/room)| Method | Path | Purpose |
|---|---|---|
| POST | /room/create | Create LK + DB |
| POST | /room/join, /guest-join | Join + LK token |
| POST | /room/refresh-token | Refresh LK JWT |
| GET | /room/list, /archived | User rooms / archives |
| POST | /room/:roomId/{kick,mute,ban,...}/:identity | Moderation |
| GET | /room/:roomId/presence | Presence (API rate limit) |
| PUT | /room/:roomId/settings | Settings (incl. recordingsAllowed) |
| DELETE | /room/:roomId | 202 · room_delete (archive, Purge=false) |
| POST | /room/:roomId/chat/upload | Chat image |
/rooms — code ready)| Method | Path | Purpose |
|---|---|---|
| POST | /rooms/:id/recording/start|stop | Egress control · RecordingsEnabled |
| GET | /rooms/:id/recordings, .../:rid, .../:rid/wait | List/get/long-poll |
| DELETE | /rooms/:id/recordings, .../:recordingId | Clear |
| GET | /admin/recordings | Admin list |
| POST | /admin/recordings/bulk/delete | 202 · recording_delete |
Users: list, recent, bulk ban/promote/delete, status, accesses, force-logout, password, detail, sessions, verify, delete.
Rooms admin: list, events, close/suspend/reactivate/update, participants, bulk, livekit stats, online-count.
Settings/webhooks/invite-tokens/overview/queue/cert as in route map.
internal/auth/ + middleware/)Password: HashPassword / VerifyPassword — bcrypt(sha256(password)) with legacy plain-bcrypt fallback.
Flows: Register, Login (email-verify gate), GuestLogin, refresh rotate (RotateRefreshToken), Logout (block refresh + revoke access), profile/avatar/email/password, passkeys (WebAuthn), OAuth Init/ReloadProviders.
jwt.go)GenerateTokenPair); purpose tokens: email_verify, password_reset| Fn | Behavior |
|---|---|
Protected | Bearer or access_token cookie → claims in Locals("user"); ban → 403 |
RequireAccess | Hierarchical: superadmin > admin > moderator > user |
RequireBearerForMutations | CSRF: mutations need Authorization header |
RejectGuest | Block guest provider |
RequireEmailVerified | Always DB EmailVerifiedAt (never trust JWT claim) |
Auth/Resend/Guest/APIRateLimiter | Per-IP Fiber limiters |
RecordingsEnabled | 403 if system flag off |
internal/models/)| Model | Table / notes |
|---|---|
User | email+provider unique; Accesses text[]; EmailVerifiedAt; PasswordChangedAt; refresh stored as SHA-256 |
Room | Settings embedded (settings_* incl. RecordingsAllowed, IsPersistent); LastActivityAt; soft DeletedAt archive; active-name unique partial index |
RoomParticipant / RoomPermissions | Stage, moderator, ban, chat block flags |
Passkey | WebAuthn credentials |
BlockedRefreshToken | Hashed refresh blocklist |
SystemSettings | Singleton ID=1 — registration, OAuth, server, LK, CORS, chat, email, recordings, limits (runtime overlay via GetEffectiveSettings) |
InviteToken | Gated registration |
UserPreferences | JSON blob PK=userID |
ChatUpload | Room/user upload metadata (no dedicated repo) |
Job | Queue rows: pending/active/done/failed |
VerificationEvent | sent/resent/success/failed/admin_force/email_change |
Webhook | Outbound subscriptions; events: room.created/ended, participant.joined, recording.completed, ping |
Recording | LiveKit egress lifecycle: pending→started→processing→completed|failed|deleting |
QueueStats / overview DTOs | Admin API shapes (not tables) |
Relationships: User→Passkeys/BlockedTokens/Prefs/Participants; Room→Participants/Permissions/ChatUploads/Recordings; Job & Webhook standalone; SystemSettings singleton.
internal/repository/)| Repo | Highlights |
|---|---|
UserRepository | Upsert, hashed refresh CAS, cascade delete, admin filters/batch, guest/unverified cleanup |
RoomRepository | Create/join capacity, stage/mod flags, soft/hard delete, admin filters, KPIs/trends |
PasskeyRepository | CRUD + counter advance |
SettingsRepository | Get/Save/GetEffectiveSettings |
InviteTokenRepository | Create/list/mark used/delete |
UserPreferencesRepository | Get/Upsert/Delete |
VerificationEventRepository | Record + recent by user |
WebhookRepository | CRUD, ListActive(event), secret rotate |
RecordingRepository | Optimistic status transitions, list/admin, stale/retention queries |
No SQL migration dir — schema via database.RunMigrations() AutoMigrate + Postgres FKs. Skip: BEDRUD_SKIP_MIGRATE=1.
internal/queue/) — 8 job typesWorker polls jobs. Postgres SKIP LOCKED; SQLite two-step + MaxOpenConns(1). Default poll 500ms, concurrency 1, maxAttempts 3, backoff 2^n * 5s cap 1h. Depth cap 10000.
| Type | Payload | Handler | Status |
|---|---|---|---|
user_delete | UserID, Email, RoomIDs | NewUserDeleteHandler | Registered |
room_delete | RoomID, msgs, Purge | archive (false) or cascade (true) | Registered |
room_suspend | RoomID | SuspendRoom | Registered |
chat_upload_s3 | base64 + meta | Store + tracker | Registered |
send_email | To, Subject, TemplateName, Data | SMTP + Cerberus templates | Registered |
dispatch_webhook | URL, Event, Body, Secret | HMAC POST (soft-fail) | Registered |
process_recording | egress/file meta | Download → RecordingStore → complete + webhooks | Implemented; bootstrap commented |
recording_delete | RecordingID, RoomID, RoomName | Hard-delete DB row | Implemented; bootstrap commented |
handler_stubs.go is an index comment only — no stub handlers remain.
Email templates: welcome, verify_email, password_reset, password_changed, room_invite (registered, not yet enqueued by handlers), generic. Branding from config + SystemSettings.
RoomCleanupService| Fn | Behavior |
|---|---|
CascadeDeleteRoom | Stop egress → system msg → LK delete → chat cleanup → delete recordings → HardDeleteRoom |
ArchiveRoom | Soft-delete; keeps recordings |
SuspendRoom | Idle + disconnect; clears recording rows |
DeleteUserRooms | Cascade each owned room |
RecordingService (SHIPPED)Gates: system RecordingsEnabled → room exists → room RecordingsAllowed → max per room → no active.
StartRecording → RoomCompositeEgress MP4 AudioOnly=true.
StopRecording → StopEgress only; webhook egress_ended owns processing enqueue.
Lifecycle: pending → started → (webhook) processing → process_recording → completed|failed.
| Component | Role |
|---|---|
ChatUploadStore | disk/hybrid/inline/s3 (SigV4) |
ChatUploadTracker | Record + DeleteByRoom + quotas |
Avatar | ./data/uploads/avatars, max 2MB |
RecordingStore | Disk or S3; key recordings/{user}/{room}/{id}-….mp4 |
internal/scheduler/)| Cadence | Task |
|---|---|
| 1 min | Expired rooms + idle LK empty rooms (skip persistent) |
| Weekly 03:00 | Delete old guests (7d) |
| Daily 03:30 | Unverified local/passkey accounts |
| Hourly | Blocked refresh tokens + prune revoked access JWTs |
| Daily 03:00 | Queue cleanup (done 7d / failed 30d); stale recordings 7d |
| Daily 09:00 | Self-signed cert renew if ≤30d |
CleanupIntervalHours | Recording retention on archived rooms (needs recStore) |
internal/livekit/)bin/livekit-server (placeholder OK for build; real binary for run)StartInternalServer / RunLiveKit; skip if LIVEKIT_MANAGED=truehttp://localhost:<httpPort>/api/livekit/webhook/livekit reverse-proxy when internalinternal/lkutil/)NewClient (RoomService), NewEgressClient, AuthContext, SendSystemMessage (+ deletedIdentity variant).
handlers/livekit_webhook.go)Verifies LK JWT. Handles participant/room lifecycle + egress → may enqueue process_recording. External LK: configure webhook URL manually to /api/livekit/webhook.
internal/cli/, usercli/, roomcli/, install/)Cobra root: run, livekit, install/uninstall, cert, user, room, config, settings, invite-token, db, version.
--json via clioutput. Installer: LinuxInstall — multi-init (systemd/OpenRC/SysV/container), secrets, /etc/bedrud, /var/lib/bedrud, optional ACME/self-signed/external LK.
usercli: promote/demote/create/delete/list/info/password/active with full cascade delete via cleanup service.
roomcli: list/info/close/suspend/reactivate/kick.
Utils: TLS multi-algo certs, SMTP, LiveKit keypair, SafeCreate, OutboundIP.
cmd/bedrud → internal/cli
├─ server.Run → handlers → repository → models
│ → auth → repository
│ → middleware → auth
│ → queue → services / storage / email
│ → scheduler → repository + livekit + auth prune
│ → services (cleanup, recording)
│ → storage (chat, avatar, recording)
│ → livekit (embed process)
│ → lkutil (RoomService / Egress)
├─ livekit.RunLiveKit
├─ install.LinuxInstall
├─ usercli / roomcli → repository + services + storage + lkutil
└─ utils / database / clioutput
cmd/server → same wiring inline (dev; Swagger)
| Area | Keys / env |
|---|---|
| Server | host, port, httpPort, TLS, ACME, behindProxy, trustedProxies |
| Auth | JWTSecret, TokenDuration, RequireEmailVerification, OAuth, passkey TTL |
| Database | type sqlite|postgres, path/DSN, pool |
| LiveKit | host, internalHost, apiKey/secret (≥32 embedded), external, nodeIP, configPath |
| Queue | pollInterval, maxAttempts, concurrency |
| SMTP + template branding | |
| Chat | uploads backend/disk/s3/inlineMax |
| Recording | maxFileSizeMB, storageDir, maxPerRoom, retentionHours |
| RateLimit | auth/guest/api/resend max + window |
Runtime overrides: many via SystemSettings + GetEffectiveSettings.
/api/room/*; recording is /api/rooms/:id/*.DeletedAt); hard delete via HardDeleteRoom / purge jobs. No AdminDeleteRoom name.idx_rooms_active_name); idle/archived can reuse names.EmailVerifiedAt is client-facing only.MaxOpenConns(1)); pending jobs stuck → check DB/worker map.internal/cli), not manual arg switch in main.LinuxInstall, not Debian-only.make init.cd server && go vet ./...
cd server && go build ./...
cd server && go test -v -count=1 ./...
# race (CI): go test -race ./...
Swagger regen: make swagger-gen (swag CLI). UI: /api/swagger, /api/scalar.