Add ability to use response_format in call function in order to
have better result with albert-large model
Use reponse_format for next steps and plan generation
This chart exposes an external API from the backend pod.
Currently, it does not include conditional addition of the external API route.
This functionality will be added later.
Add configurable room name regex filtering to exclude Tchap events from shared
LiveKit server webhooks, preventing backend spam from unrelated application
events while maintaining UUID-based room processing for visio.
Those unrelated application events are spamming the sentry.
Acknowledges this is a pragmatic solution trading proper namespace
prefixing for immediate spam reduction with minimal refactoring impact
leaving prefix-based approach for future improvement.
Restrict metadata manager signal triggers to transcription-specific Celery
tasks to prevent exceptions when new summary worker executes tasks
not designed for metadata operations, reducing false-positive Sentry errors.
Make WhisperX language detection configurable through FastAPI settings
to handle empty audio start scenarios where automatic detection fails and
incorrectly defaults to English despite 99% French usage.
Quick fix acknowledging long-term solution should allow dynamic
per-recording language selection configured by users through web
interface rather than global server settings.
Correct accidentally swapped keyboard shortcuts between video and
microphone toggle controls introduced during device component
refactoring, restoring expected shortcut behavior reported by users.
Instead of relying on make commands to set-up the minio webhook,
use a compose service, as we did for the createbucket one.
Aligned with the dev stack, and run by default when starting
for the first time the stack.
Introduce ENABLE_EXTERNAL_API setting (defaults to False) to allow
administrators to disable external API endpoints, preventing unintended
exposure for self-hosted instances where such endpoints aren't
needed or desired.
Document the external API using a simple Swagger file that can be opened
in any Swagger editor.
The content was mostly generated with the help of an LLM and has been human-
reviewed. Corrections or enhancements to the documentation are welcome.
Currently, my professional email address is included as a contact. A support
email will be added later once available. The documentation will also be
expanded as additional endpoints are added.
From a security perspective, the list endpoint should be limited to return only
rooms created by the external application. Currently, there is a risk of
exposing public rooms through this endpoint.
I will address this in upcoming commits by updating the room model to track
the source of generation. This will also provide useful information
for analytics.
The API viewset was largely copied and adapted. The serializer was heavily
restricted to return a response more appropriate for external applications,
providing ready-to-use information for their users
(for example, a clickable link).
I plan to extend the room information further, potentially aligning it with the
Google Meet API format. This first draft serves as a solid foundation.
Although scopes for delete and update exist, these methods have not yet been
implemented in the viewset. They will be added in future commits.
Enforce the principle of least privilege by granting viewset permissions only
based on the scopes included in the token.
JWTs should never be issued without controlling which actions the application
is allowed to perform.
The first and minimal scope is to allow creating a room link. Additional actions
on the viewset will only be considered after this baseline scope is in place.
This endpoint does not strictly follow the OAuth2 Machine-to-Machine
specification, as we introduce the concept of user delegation (instead of
using the term impersonation).
Typically, OAuth2 M2M is used only to authenticate a machine in server-to-server
exchanges. In our case, we require external applications to act on behalf of a
user in order to assign room ownership and access.
Since these external applications are not integrated with our authorization
server, a workaround was necessary. We treat the delegated user’s email as a
form of scope and issue a JWT to the application if it is authorized to request
it.
Using the term scope for an email may be confusing, but it remains consistent
with OAuth2 vocabulary and allows for future extension, such as supporting a
proper M2M process without any user delegation.
It is important not to confuse the scope in the request body with the scope in
the generated JWT. The request scope refers to the delegated email, while the
JWT scope defines what actions the external application can perform on our
viewset, matching Django’s viewset method naming.
The viewset currently contains a significant amount of logic. I did not find
a clean way to split it without reducing maintainability, but this can be
reconsidered in the future.
Error messages are intentionally vague to avoid exposing sensitive
information to attackers.
Prepare for the introduction of new endpoints reserved for external
applications. Configure the required router and update the Helm chart to ensure
that the Kubernetes ingress properly routes traffic to these new endpoints.
It is important to support independent versioning of both APIs.
Base route’s name aligns with PR #195 on lasuite/drive, opened by @lunika
We need to integrate with external applications. Objective: enable them to
securely generate room links with proper ownership attribution.
Proposed solution: Following the OAuth2 Machine-to-Machine specification,
we expose an endpoint allowing external applications to exchange a client_id
and client_secret pair for a JWT. This JWT is valid only within a well-scoped,
isolated external API, served through a dedicated viewset.
This commit introduces a model to persist application records in the database.
The main challenge lies in generating a secure client_secret and ensuring
it is properly stored.
The restframework-apikey dependency was discarded, as its approach diverges
significantly from OAuth2. Instead, inspiration was taken from oauthlib and
django-oauth-toolkit. However, their implementations proved either too heavy or
not entirely suitable for the intended use case. To avoid pulling in large
dependencies for minimal utility, the necessary components were selectively
copied, adapted, and improved.
A generic SecretField was introduced, designed for reuse and potentially
suitable for upstream contribution to Django.
Secrets are exposed only once at object creation time in the Django admin.
Once the object is saved, the secret is immediately hashed, ensuring it can
never be retrieved again.
One limitation remains: enforcing client_id and client_secret as read-only
during edits. At object creation, marking them read-only excluded them from
the Django form, which unintentionally regenerated new values.
This area requires further refinement.
The design prioritizes configurability while adhering to the principle of least
privilege. By default, new applications are created without any assigned scopes,
preventing them from performing actions on the API until explicitly configured.
If no domain is specified, domain delegation is not applied, allowing tokens
to be issued for any email domain.
Add detailed documentation on signaling server configuration
and associated environment variables to help administrators properly
configure WebRTC connection establishment.
Add documentation noting subtitle functionality is currently under
active development to set appropriate expectations for administrators
and prevent deployment assumptions about feature maturity.
Add comprehensive telephony documentation explaining system requirements
and component interactions to help administrators understand infrastructure
needs.
Add comprehensive recording documentation explaining system requirements
and component interactions to help administrators understand infrastructure
needs and troubleshoot recording functionality.
Expand authentication documentation to clarify supported authentication
mechanisms and their configuration nuances, helping administrators
understand different authentication flows and choose appropriate methods
for their deployment security requirements.
Add initial theming documentation covering both runtime customization and
build-time configuration methods to help self-hosters adapt the
application's visual identity to their organizational branding needs.
Improve installation instructions to prepare for comprehensive Docker
Compose documentation launch, clarifying setup steps and addressing
common deployment questions to reduce onboarding friction.
Enhance README by incorporating content from LaSuite Docs, adding
comprehensive list of other LaSuite Meet instances, and refining
presentation details to improve project discoverability and onboarding.
Delete deprecated internal release process documentation that no longer
applies to current deployment practices, eliminating confusion from
obsolete workflow references.
Sadly, we used user db id as the posthog distinct id
of identified user, and not the sub.
Before this commit, we were only passing sub to the
summary microservice.
Add the owner's id. Please note we introduce a different
naming behavir, by prefixing the id with "owner". We didn't
for the sub and the email.
We cannot align sub and email with this new naming approach,
because external contributors have already started building
their own microservice.
Manually update libexpat to 2.7.2-r0 in Alpine 3.21.3 base image
to address CVE-2025-59375 high-severity vulnerability until newer
Alpine base image becomes available, ensuring Trivy security scans pass.
Add additional room event tracking to PostHog analytics to better
understand and diagnose disconnection error patterns. Enhanced
telemetry will provide insights for improving connection stability.
Remove incorrect whitespace in queue names that prevented Celery
workers from listening to proper queues. Workers were attempting to
connect to non-existent queues, breaking task distribution.
Ensure transcribe jobs are properly assigned to their specific queue
instead of using default queue. This prevents job routing issues and
ensures proper task distribution across workers.
Implement automated MinIO webhook configuration using Kubernetes job
to enable recording feature functionality. This eliminates manual
setup requirements and ensures consistent webhook configuration
across deployments.
Restore certificate mounting for MinIO webhook communication to
backend after migrating away from unmaintained Bitnami chart.
Mount certificate in proper volume to enable secure bucket-to-backend
webhook delivery.
Add Celery summarize and transcribe worker configuration to Helm
charts for summary microservice. Create new deployment resources
and increment chart version to support distributed task processing.
Introduce FastAPI settings configuration option to completely disable
the summary feature. This improves developer experience by allowing
developers to skip summary-related setup when not needed for their
workflow.
Add watch configuration to Docker Compose file enabling compose watch
mode for Docker Compose 2.22+. This enhances developer experience on
Visio by providing automatic file synchronization and hot reloading
during development on the celery workers.
The recording feature and call to the summary service wasn't working
in the docker compose stack. It was a pain for new developper joining
the project to understand every piece of the stack.
Resolve storage webhook trigger issues by configuring proper environment
variables, settings, and MinIO setup to enhance developer experience
and eliminate manual configuration requirements.
Add new Makefile command to configure MinIO webhook via CLI since
webhook configuration cannot be declared as code. Update summary
microservice to reflect secure access false setting for MinIO bucket
consistency with Tilt stack configuration.
Implement summarization functionality that processes completed meeting
transcripts to generate concise summaries.
First draft base on a simple recursive agentic scenario.
Observability and evaluation will be added in the next PRs.
Name the Celery queue used by transcription worker to prepare for
dedicated summarization queue separation, enabling faster transcript
delivery while isolating new agentic logic in separate worker processes.
Rename incorrectly named OpenAI configuration settings since
they're used to instantiate WhisperX client which is not OpenAI
compatible, preventing confusion about actual service dependencies.
Include PostHog analytics configuration example in the summary
environment file with default disabled state. This provides developers
with clear setup guidance while maintaining privacy-first defaults.
Consolidate summary service into main development stack to centralize
development environment management and simplify service orchestration
with shared infrastructure like MinIO storage.
Adjust permission modal dimensions to properly fit mobile viewports
and prevent poor responsive user experience. Ensures modal content
remains accessible and readable across different screen sizes.
Resolve issue where users with disabled track preferences in local
storage wouldn't receive permission prompts in subsequent sessions,
causing app deadlock. Toggle tracks when permissions are disabled to
re-trigger permission requests.
This is a hotfix addressing critical user feedback. Permission handling
requires further testing and improvements based on gathered user
reports since release.
Resolve regression where non-admin/anonymous users couldn't mute
their microphone from participant list after mute permissions refactoring.
Replace API call with local track mute for better performance and
proper permission handling.
Add accessibility label to screenshare control button to ensure screen
readers can properly announce the button's function to users with
visual impairments.
Hide audio output selector component for Safari browsers due to lack
of native support for audio output device selection APIs. This
prevents user confusion and improves browser compatibility.
Revert recent changes to dynacast and adaptive streaming functionality
to isolate potential causes of regression issues. Changes will be
reintroduced in future commits with improved error handling and
thorough investigation of root causes.
Restore proper controlbar layout and spacing on mobile screens that broke
during recent audio control component refactoring, ensuring consistent
user interface across all device sizes.
Temporarily roll back LiveKit client SDK version to investigate and
resolve production stability problems that emerged after recent upgrade,
enabling system restoration while root cause analysis is performed.
Update development environment LiveKit server from previous version
to 1.9.0 for latest features and bug fixes.
Ensures development environment stays current
with LiveKit production version.
Replace text elements in switch components with proper icons to eliminate
dependency on font size variations and ensure consistent visual
appearance.
Improves component reliability across different font scaling scenarios
and provides clearer visual indicators that remain legible regardless of
user font preferences or system scaling settings.
Add extensive list of favicon formats and sizes to resolve display
issues specifically affecting Safari browser, ensuring proper icon rendering
across all devices and platforms.
Add information to recording panel indicating maximum recording
duration when time limits are configured to prevent user confusion
and help with session planning.
Fix regression where Crisp chatbot CSS changes caused their button to
cover useful room actions due to failing CSS override rules.
Updates CSS specificity and positioning to ensure Crisp chat button
doesn't interfere with room functionality while maintaining chatbot
accessibility for user support.
Refactor feature flag mechanism from Django permission classes to custom
decorator that returns 404 Not Found when features are disabled instead
of exposing API structure through permission errors.
Improves security by preventing information disclosure about disabled
features and provides more appropriate response semantics. Custom
decorator approach is better suited for feature toggling than Django's
permission system which is designed for authorization.
Configure LiveKit token to explicitly allow users to subscribe to other
participants' video and audio tracks instead of relying on default
permissions.
git-lint steps are independant and we would like to have all checks at
once. Using the `if: always()` instruction should ensure all steps
should be run event if the previous fails.
thanks @lunika
Expand text area input character limit from default to 2000 characters
to allow users more space for detailed chat messages.
Provides better user experience for longer form communication within
chat interface while maintaining reasonable message size constraints.
Replace ReturnType<typeof usePagination> prop type with explicit Props
interface defining only required fields (currentPage, totalPages,
onPageChange) to decouple component from internal hook implementation.
Eliminates unnecessary runtime dependency and improves component API
clarity by explicitly declaring required props instead of coupling to
hook internals, making the component more maintainable and reusable.
Disable previous/next pagination controls when users are on the first or
last page respectively to prevent offering non-functional interactions.
Improves user experience by clearly indicating when navigation options
are unavailable and preventing confusion from inactive controls that
appear interactive.
Hide pagination dot indicators from screen readers using aria-hidden
to prevent noisy output when dots are purely visual decorations.
Improves accessibility by removing redundant announcements
while maintaining visual pagination cues for sighted users.
Add internationalization support to pagination controls and include
aria labels for improved accessibility and screen reader support
across different languages.
Refactor participant list to avoid nested React component definitions
that lose state on parent re-renders and cause unnecessary recreation.
Moves component definitions outside render methods to prevent state loss
bugs and improve performance by eliminating redundant component
instantiation on each parent render cycle.
Send notification to participants when admin revokes their camera,
microphone, or screenshare permissions so they understand why their
media suddenly stopped.
Improves user experience by providing clear feedback about permission
changes instead of leaving users confused about unexpected media
interruptions during meetings.
Update user experience by clearly marking device toggle and control
components as disabled when users have insufficient room permissions.
Prevents confusion by providing visual feedback that device controls are
unavailable, improving clarity about what actions users can perform
in their current role.
Improve mute-all functionality by filtering out participants who are
already muted or lack microphone publishing permissions, and ignore
cases where microphone tracks are unavailable.
Prevents unnecessary mute operations on participants who cannot be
muted, prevent API errors.
Correct microphone muted indicator logic that only showed muted state
when participants explicitly muted themselves, missing cases where
admins prevented microphone publishing.
Now properly displays muted indicator for both self-muted and
admin-restricted microphone states, providing accurate visual feedback
for all muting scenarios.
Enhance participant permission update logic to only affect users
without room privileges, ensuring admins can maintain their microphone
and camera access during bulk permission changes.
Prevents accidental disruption of admin functionality when applying
permission restrictions to regular participants, maintaining proper
role-based access control hierarchy.
Replace hardcoded default publishing source constants with values from
Django backend settings to prevent desynchronization between frontend
and backend configurations.
Introduce pin icon to visually notify users when a participant has
their track pinned in the interface.
Provides clear visual feedback for pin status, helping users understand
which participants are currently highlighted or prioritized in the
meeting view.
Introduce participant menu in participant list to enable more
participant actions and interactions beyond current capabilities.
Initialize menu with universal pin/unpin track action available to all
users, plus admin-restricted participant removal action. Completes
admin action set by enabling room ejection functionality.
Menu designed for reuse when called from participant tile focus
components, providing consistent interaction patterns across different
contexts where participant management is needed.
Implement admin capability to mute everyone's microphone in large rooms
where participants forget to mute themselves and are hard to identify
quickly.
Feature requested by @arnaud-robin. Provides instant room-wide muting
without individual confirmation popups, enabling efficient moderation
in busy conference scenarios.
Update interface to hide admin-only actions like participant muting from
users without room admin privileges, reflecting backend permission
restrictions implemented in previous commits.
Add host identification display for participants using boolean flag from
LiveKit token attributes. Currently passes simple boolean but will be
refactored to distinguish owner/admin/member roles and host/co-host
with different privileges.
Security note: attributes are not fully secure as participants can
update their own metadata, potentially faking admin status. However,
consequences are limited to user confusion without destructive
capabilities. Metadata updates currently needed for name changes and
hand raising functionality.
Plan to remove canUpdateOwnMetadata permission to strengthen security
while preserving essential user interaction capabilities.
Switch from metadata to attributes when generating LiveKit tokens for
more convenient dict-like structure handling during token creation and
client-side reading.
Attributes provide better data structure flexibility compared to
metadata, simplifying both server-side token generation and client-side
data access patterns.
Introduce new admin panel actions allowing room owners to restrict
participant source publication (video/audio/screenshare) with immediate
real-time updates across all participants.
Provides granular room-wide media control for admins to manage
bandwidth, focus attention, or handle disruptive situations by
selectively enabling or disabling specific media types instantly.
Introduce new Field variant using Switch input with different props
structure from other input components.
Displays description after switch component rather than mixed with
label due to layout requirements, preventing reuse of standard label
and description composition patterns.
Refactor frontend to use backend-mediated API calls instead of direct
LiveKit client-side requests for participant management operations.
Removes hacky direct LiveKit API usage in favor of proper server-side
endpoints, improving security posture and following LiveKit's
recommended architecture for participant control functionality.
Refactor client-side LiveKit API calls to server-side endpoints
following LiveKit documentation recommendations for participant
management operations.
Replaces hacky direct client calls with proper backend-mediated
requests, improving security and following official LiveKit
Introduce new method on lobby system to clear lobby cache for specific
room and participant combinations.
Enables targeted cleanup of lobby state when participants leave or are
removed, improving cache management and preventing stale lobby entries.
Refactor lobby system to use consistent UUID v4 across lobby
registration and LiveKit token participant identity instead of
generating separate UUIDs.
Maintains synchronized identifiers between lobby cache and LiveKit
participants, simplifying future participant removal operations by
using the same UUID reference across both systems.
Extend LiveKit token creation utility with additional room configuration
and user role parameters to properly adapt room_admin grants and
publish sources based on permission levels.
This creates technical debt in utility function design that should be
refactored into proper service architecture for token
generation operations in future iterations.
Eliminates code duplication across validation serializers, improving
maintainability and ensuring consistent validation behavior throughout
the API layer.
Add required whitespace between braces in template directives to
comply with Kubernetes rule S6893.
Improves template readability and follows Kubernetes best practices for
template formatting and maintainability.
Sync ruff's target Python version to match Docker image version
used for summary component to ensure runtime consistency.
Prevents syntax/feature mismatches, catches version-specific issues
before deployment, and ensures linting targets the actual runtime
environment for better deployment safety.
Replace custom Docker Hub authentication with standard, secure,
official GitHub actions for improved security and maintainability.
Uses officially supported actions that follow security best practices
and receive regular updates from GitHub.
Avoid unsecure handling of GitHub secrets.
Implement CI build and push workflow for meet-agents Docker image,
following the same pattern established by the summary image.
Extends CI pipeline to include meet-agents image distribution through
dockerhub for consistent deployment infrastructure.
Remove default unprivileged Docker user that was incompatible with hot
reloading in tilt stack. Update tilt config to resolve path issues.
CI builds still use unprivileged user, making this change safe while
enabling proper development workflow with hot reloading functionality.
Replace outdated numerique.gouv.fr repository references with current
repository location for accurate documentation and links.
Maintenance cleanup unrelated to current PR but necessary to keep
references up-to-date. Better addressed now than deferred.
Kickstart frontend with first draft of subtitle control visible only
to users with appropriate feature flag enabled.
Opens new container at bottom of screen displaying transcription
segments organized by participant. Transcription segment handling was
heavily LLM-generated and will likely need refactoring and review to
simplify and enhance the implementation.
Initial implementation to begin testing subtitle functionality with
real transcription data from LiveKit agents.
Allow any user, anonymous or authenticated, to start subtitling
in a room only if they are an active participant of it.
Subtitling a room consists of starting the multi-user transcriber agent.
This agent forwards all participants' audio to an STT server and returns
transcription segments for any active voice to the room.
User roles in the backend room system cannot be used
to determine subtitle permissions.
The transcriber agent can be triggered multiple times but will only join a
room once. Unicity is managed by the agent itself.
Any user with a valid LiveKit token can initiate subtitles. Feature flag
logic is implemented on the frontend. The frontend ensures the "start
subtitle" action is only available to users who should see it. The backend
does not enforce feature flags in this version.
Authentication in our system does not imply access to a room. The only
valid proof of access is the LiveKit API token issued by the backend.
Security consideration: A LiveKit API token is valid for 6 hours and
cannot be revoked at the end of a meeting. It is important to verify
that the token was issued for the correct room.
Calls to the agent dispatch endpoint must be server-initiated. The backend
proxies these calls, as clients cannot securely contact the agent dispatch
endpoint directly (per LiveKit documentation).
Room ID is passed as a query parameter. There is currently no validation
ensuring that the room exists prior to agent dispatch.
TODO: implement validation or error handling for non-existent rooms.
The backend does not forward LiveKit tokens to the agent. Default API
rate limiting is applied to prevent abuse.
Create basic Helm chart for LiveKit agent framework deployment on
Kubernetes, inspired by meet-summary FastAPI server configuration.
Integrate chart into local tilt development stack and properly handle
certificate issues that typically occur when calling LiveKit server
with nip.io domain names.
Create Python script based on LiveKit's multi-user transcriber example
with enhanced request_fnc handler that ensures job uniqueness by room.
A transcriber sends segments to every participant present in a room and
transcribes every participant's audio. We don't need several
transcribers in the same room. Made the worker hidden - by default it
uses auto dispatch and is visible as any other participant, but having
a transcriber participant would be weird since no other videoconference
tool treats this feature as a bot participant joining a call.
Job uniqueness is ensured using agent identity by forging a
deterministic identity for each transcriber by room. This makes sure
two transcribers would never be able to join the same room. It might be
a bit harsh, but our API calling to list participants before accepting
a new transcription job should already filter out situations where an
agent is triggered twice.
We chose explicit worker orchestration over auto-dispatch because we
want to keep control of this feature which will be challenging to
scale. LiveKit agent scaling is documented but we need to experiment in
real life situations with their Worker/Job mechanism.
Currently uses Deepgram since Arnaud's draft Kyutai plugin isn't ready
for production. This allows our ops team to advance on deploying and
monitoring agents. Deepgram was a random choice offering 200 hours
free, though it only works for English. ASR provider needs to be
refactored as a pluggable system selectable through environment
variables or settings.
Agent dispatch will be triggered via a new REST API endpoint to our
backend. This is quite a first naive version of a minimal dockerized
LiveKit agent to start playing with the framework.
Leverage reference to initial processor choice to prevent unnecessary
preview track recreation when updating processor options.
Improves performance by maintaining existing track instance during
processor updates instead of creating new tracks, eliminating visual
interruptions and reducing resource overhead.
Replace multiple processor wrappers with single unified class that
enables seamless transformer switching and option updates without
visual blinking artifacts.
Leverages LiveKit track processor v0.6.0 updateTransformerOptions fix
to provide smooth transitions between transformer types, eliminating
the recreation-based approach that caused flickering during effects
switching.
Streamline processor factory logic to prepare for unified transformer
class refactoring.
Reduces complexity and establishes foundation for consolidated
transformer approach.
Update LiveKit track processor to version 0.6.0 which includes fix for
updateTransformerOptions allowing seamless switching between transformer
types without visual artifacts.
Eliminates weird flickering behavior when users select different
transformer types by enabling proper transformer transitions instead of
recreation, improving user experience during effects switching.
Remove call to generate demo data in tilt stack as it was never useful
to developers and only complicated the migration job unnecessarily.
Migration job should be laser focused on applying database migrations
rather than seeding mock data, improving clarity and reducing
complexity.
Replace mock Django secret key with longer version to resolve security
warnings in development stack.
Still not production-suitable as key remains versioned in repository,
but eliminates security warnings during development workflow.
Remove dependencies on bitnami Helm charts since recent changes in
bitnami organization led to charts no longer being maintained or
published.
Enhanced the Tilt dependencies to avoid any bootstrap or refresh
errors while developping using the Tilt stack.
Making components dependant from each others increase slightly
the time required to spin up the stack the first time.
Implement pip dependency caching across all CI jobs requiring package
installation and upgrade actions/setup-python from v4 to v5.
The setup-python action is able to cache the dependencies and reuse this
cache while the pyproject file has not changed. It is easy to setup,
just the package manager used has to be declared in the cache settings
Introduce cross icon to switch component when in disabled/negative
state to provide clearer visual feedback to users.
Improves component usability by making the negative state more
explicitly recognizable through visual indicators.
Replace settings context provider with valtio global store for easier
access outside room components and better long-term maintainability.
Prepares for upcoming prejoin screen settings access by making settings
globally available without React context limitations.
Document that toggleButtonProps are intended to override default and
computed values within ToggleComponent, acknowledging this breaks
encapsulation but serves as useful starting point.
Skip state updates when selected device hasn't actually changed to
prevent unnecessary re-renders that caused visible camera track
blinking.
Improves user experience by eliminating visual artifacts during device
selection interactions when no actual change occurs.
Enhance toggle naming in video controls to explicitly indicate special
processor handling functionality and improve toggleProps TypeScript
typing.
Makes code more self-documenting by clearly identifying processor-aware
toggle behavior while strengthening type safety
Correct wrong copy-paste error in audio track dynamic initialization
that was missed during previous PR merge process.
Fixes initialization logic that was accidentally duplicated or
incorrectly modified during merge conflict resolution.
Restore participant name display in transcription and recording toast
notifications that was accidentally removed in recent changes.
Simple regression fix to ensure proper participant identification in
notification messages.
Close device control popover automatically when user opens sidepanels
or external dialogs to prevent confusing UI state.
Improves focus management by ensuring only one interface element
demands user attention at a time, reducing cognitive load during
interactions.
Fix bug where device toggling shortcuts remained active despite lacking
permissions, by disabling device-related shortcuts until permissions
are granted.
Prevents confusing user experience where shortcuts appear to work but
have no effect due to missing media permissions.
Convert audio tab device selections to controlled behavior matching
video tab implementation for consistency.
Maintains current component structure without migrating to SelectDevice
component yet, focusing on controlled state pattern alignment first.
Provide direct access to background and effects options from video
device controls during conference for additional user convenience.
Creates another pathway to effects configuration, giving users more
flexibility in accessing video enhancement features while in meetings.
Update tooltip and aria-label text for in-room device controls to
indicate they now open comprehensive settings dialog instead of simple
device selection.
Enable opening settings dialog directly from device controls while
inside a conference for quick access to device configuration.
Improves UX by providing immediate settings access without
enhancing convenience during meetings.
Requested by users.
Update localization keys for device toggling and selection to be more
generic, enabling translation sharing between join and room contexts.
Eliminates duplicate translations and creates consistent messaging for
device interactions regardless of application context.
Replace separate prejoin and room toggle components with unified
component that's adaptable and easier to evolve without overfitting.
Adds responsibilities to join component but eliminates duplication. Join
component needs future refactoring as complexity is growing
significantly.
Remove ugly toggle device configuration and implement hook to determine
appropriate keyboard shortcuts based on media device kind.
Cleaner approach that encapsulates shortcut logic in reusable hook
instead of scattered configuration objects.
Create simple hook to assign icons to toggle/select components based on
media kind using dictionary lookup for optimization.
Eliminates duplicate icon assignment logic across components with
straightforward, performant implementation that's easy to maintain.
Create hook to encapsulate permission denied/prompted/loading checks
based on media kind, eliminating props drilling and simplifying code.
Returns appropriate permission state for consuming components based on
media type, cleaning up code structure with small enhancement.
Refactor device selection within rooms and add audio output selection
to audio controls as requested by users.
Ensures code reuse between join and room components by sharing device
selection logic across both contexts.
Temporary state separating audio and video controls to improve clarity
and prepare for device selection/toggle component reorganization.
Work in progress to better structure device-related components before
implementing final unified control architecture.
Add dark variant to Select component following same approach as Popover
primitive. Same design inconsistency as other variant patterns.
Quick implementation pending UI v2 refactoring for unified variant
system across all components.
Add placement prop to Popover primitive to leverage React Aria's
explicit placement control functionality.
Provides better positioning control for popovers by exposing underlying
React Aria placement options, enabling more precise UI layouts.
Implement ability to pass defaultSelectedTab key to settings component
for scenarios requiring specific tab to open automatically.
Enables programmatic control over initial tab selection, improving UX
when directing users to specific settings sections from different
application contexts.
Allow enabling/disabling arrow graphics in Popover component to create
more modular and flexible primitive.
Provides greater design flexibility by making arrow display optional,
enabling different visual presentations based on specific use cases.
Add dark variant following same approach as Menu component. Not ideal
as light/dark pattern differs from primary/primaryDark variants used
elsewhere.
Quick implementation that will be refactored during UI v2 migration for
better consistency across component variants.
Replace default usePreviewTrack behavior that acquired media streams
even when users disabled audio/video in preferences, causing OS
recording indicators to show despite explicit user rejection.
Implement custom logic to only initiate preview tracks when actually
needed by user. Code is naive and could be optimized, but fixes the
misleading OS-level recording feedback that created user distrust.
Update LiveKit client JavaScript SDK to version 2.15.5 which includes
a patch for Firefox SVC compatibility with AV1 codec.
Fixes video encoding issues specific to Firefox when using AV1 codec
with Scalable Video Coding, improving browser compatibility and video
quality performance.
Extract shared layout components from audio and video tabs to eliminate
code duplication and improve maintainability.
Creates reusable layout components that both tabs can utilize, reducing
redundancy and ensuring consistent styling and behavior across settings
tabs.
Add configuration option allowing users to set maximum video quality
for subscribed tracks, requested by users who prefer manual control
over automatic behavior.
Implements custom handling for existing and new video tracks since
LiveKit lacks simple global subscription parameter mechanism. Users can
now override automatic quality decisions with their own preferences.
Implement user choice persistence for video resolution settings of
subscribed tracks from other participants.
Maintains user preferences for received video quality across sessions,
allowing consistent bandwidth optimization and viewing experience
without reconfiguring subscription settings each visit.
Introduce select option allowing users to set maximum publishing
resolution that instantly changes video track resolution for other
participants.
Essential for low bandwidth networks and follows common patterns across
major videoconferencing solutions. Users can optimize their video
quality based on network conditions without leaving the call.
Implement user choice persistence for video publishing resolution
configuration to maintain user preferences across sessions.
Stores selected video resolution in user settings, ensuring consistent
video quality preferences without requiring reconfiguration on each
visit.
Introduce new video tab in settings modal requested by users who found
it misleading to lack camera configuration options in settings.
Currently implements basic camera device selection. Future commits will
expand functionality to include resolution management, subscription
settings, and other video-related configurations.
Limit useResolveDefaultDeviceId hook execution to initial rendering
only, considering removal due to ux concerns.
Hook's purpose is to populate select fields when 'default' device
option isn't available in enumerated device list. Current
implementation may be too confusing for code execution.
Replace usePreviewTrack approach with manual track management inspired
by deprecated LiveKit implementation that only toggles what's needed
instead of resetting entire preview track on config changes.
Previous approach created new videoTrack when updating audio track,
causing video preview to blink black during audio configuration
changes.
It was also acquiring video streams even when disabled.
New implementation:
* Initializes tracks once with user permissions for both devices
* Manually handles muting/unmuting and device updates
* Preserves muted state when changing device IDs
* Uses exact device constraints on Chrome for proper device selection
Prevents unnecessary track recreation and eliminates preview blinking.
Update track muting/unmuting to prioritize immediate UI state changes
over error handling to prevent weird UX delays.
Ensures toggle buttons reflect new state instantly rather than waiting
for operation completion. Users expect immediate visual feedback when
interacting with mute controls, even if errors occur later.
When browsers don't return 'default' audio output device ID and only
one device is available, automatically select the single option to
improve user experience.
Prevents unnecessary user interaction when there's only one choice
available, making the device selection flow smoother and more intuitive
for users with single audio output setups.
This is necessary only for audio output because we don't create
a preview track, compare to video or mic.
Disable speaker selection on prejoin screen for Safari based on LiveKit
documentation stating audio output selection isn't supported, though
this needs further verification.
Maintains consistency with audio tab behavior until Safari audio output
support can be confirmed. Feature remains available on other browsers
where support is verified.
Fix issue where requesting audio output devices triggers microphone
permission prompts in certain browsers by linking audio output select
permissions with microphone permissions.
Ensures no unexpected permission prompts occur before preview tracks
are acquired, maintaining smooth user flow during device selection
without interrupting the permission sequence.
Introduce speaker selection component requested by users to allow audio
output device configuration before entering calls.
Enables users to test and configure their preferred audio output device
during prejoin setup, ensuring proper audio routing before call begins.
Improves user experience by preventing audio issues during meetings.
Implement audio output device persistence in localStorage since LiveKit
doesn't handle this by default.
Ensures user's preferred audio output selection is remembered across
sessions, improving user experience by maintaining device preferences
without requiring re-selection on each visit.
Add symmetric shadows at top and bottom of white circle buttons to
ensure sufficient visual contrast against varying background colors.
Improves button visibility and accessibility by providing consistent
visual definition regardless of background context.
Major refactor of device select component with several key improvements:
* Set permission=true for Firefox compatibility - without this flag,
device list returns empty on Firefox
* Implement controlled component pattern for active device selection,
ensuring sync with preview track state
* Remove default device handling as controlled behavior eliminates need
* Render selectors only after permissions granted to prevent double
permission prompts (separate for mic/camera)
Ensures usePreviewTrack handles initial permission request, then
selectors allow specific device choice once access is granted.
Update default device IDs when preview track starts to match the
actual device being used. LiveKit returns 'default' string which may
not exist in device list, causing ID mismatch.
Prevents misleading situation where default device ID doesn't
correspond to the device actually used by the preview track. Now
synchronizes IDs once preview starts for accurate device tracking.
Reset video element reference when track stops to ensure "camera
starting" to "camera started" message transitions work correctly on
repeated camera toggles.
Previously only worked on initial video element load. Now properly
handles state transitions for multiple camera enable/disable cycles.
Update select toggle device component used in conference to display
upward arrow when dropdown menu opens above the select component.
Improves visual consistency by matching arrow direction with actual
menu opening direction, providing clearer user interface feedback.
Fix useTrackToggle hook that wasn't properly muting/unmuting tracks
outside room context. Previously only toggled boolean state via
setUpManualToggle without actual track control.
This caused misleading visual feedback where prejoin showed "camera
disabled" while hardware remained active. Users could see camera/mic
LEDs still on despite UI indicating otherwise.
Refactor provides genuine track muting for accurate user feedback.
Decouple prejoin components from conference context to enable different
behaviors when inside vs outside room environments. Components can now
evolve independently with lighter coupling.
Refactor layout structure to prepare for upcoming speaker selector
introduction. This decoupling allows for more flexible component
evolution and cleaner architecture.
Provides Safari-specific UI guidance that matches the browser's unique
permission flow, ensuring users receive appropriate instructions for
their specific browser environment.
Attempt to resolve React aria warnings by adding aria-label to form
components. Visual label should be reusable by screen readers, but
warning persists with only form wrapper as apparent difference.
Uncertain if warning is harmful. Added aria-label as potential fix but
removed after feedback from Sophie and Manu. Warning remains annoying
during development.
Add polling mechanism to detect permission changes on Safari where
permission change events are not reliably fired when users interact
with system prompts.
Implements 500ms polling when permissions are in 'prompt' state to
catch grant/deny actions that Safari's event system misses. Polling
stops when permissions resolve to prevent performance impact.
Fixes UI inconsistency where Safari users' permission changes weren't
detected, leaving outdated status displays.
Add explicit messaging on join screen explaining why users should
allow camera/microphone access, with quick button to open permission
modal dialog.
Targets first-time users who need guidance on permission requirements.
Message persists until permissions are granted to ensure proper user
onboarding and reduce support issues.
Introduce accessible visual indicator on device toggle buttons to hint
when users have permission issues that require action.
Provides clear visual warning to help users understand they need to
resolve permissions before using camera/microphone features. Follows
accessibility guidelines for proper user guidance.
Introduce guided permissions dialog to help users understand and
resolve camera/microphone access issues step-by-step.
Addresses common user support requests where users cannot enable their
hardware and don't understand the permission requirements. Provides
clear instructions to reduce confusion and support burden.
Image was quickly prototyped. It will be updated later on.
Introduce permissions watcher that continuously monitors browser
permission changes and keeps the valtio global store synchronized
with actual browser permission state.
Introduce new global state management to watch and expose browser
permissions status across the application.
Sets foundation for upcoming changes that will prevent the app from
offering hardware features (camera/microphone) when permissions are
not granted, improving user experience and reducing confusion.
Major refactoring of prejoin interface to improve user onboarding and
camera/microphone permission handling:
* Create extensible hint message system for easier addition of
permission-related guidance.
* Design flexible layout structure to accommodate future camera/mic
options and component selection features.
* Establish foundation for comprehensive prejoin redesign
In upcoming commits, UX will be enhanced to a smoother user
experience when joining calls and requesting media permissions.
Extract clipboard content logic from UI components into a separate
custom hook to decouple interface elements from clipboard functionality.
Creates a reusable hook that can better adapt to future UX changes
without requiring modifications to individual UI components.
Update PIN formatting to remove space before the # symbol to clearly
indicate that # is part of the complete PIN code.
Improves user understanding that the hash symbol is an integral part
of the PIN entry sequence, not a separate element.
Add telephony information to the share dialog when available to help
users take advantage of the newly introduced phone join feature.
Promotes phone participation as an alternative connection method when
users need it, improving meeting accessibility and user adoption of
telephony capabilities.
Change secondaryText button style from default to medium font weight
for improved visual comfort and better readability.
I haven't tested this change with Marianne.
Remove incorrect public room warning that was always displayed
regardless of room privacy settings.
Warning should only appear for genuinely public rooms since the lobby
system introduction changed room privacy behavior.
Prevents user confusion about room privacy settings.
Add telephony information display to the later meeting dialog while
preserving existing layout when telephony is disabled.
Prevent layout shift on modal close by collapsing all modal content
immediately when room becomes undefined.
Critical enhancement for users creating meeting links to have complete
connection information available.
Remove ProConnect mentions from frontend locale and enhance the meeting
dialog description text to clearly explain that meeting links are
permanent and persistent.
Improves user understanding of meeting link permanence and cleans up
branding references.
Change UI text to use "room information" instead of "room address"
to better reflect the functionality whether copying just the meeting
link or complete meeting details.
Remove protocol prefix from room URLs in the information sidepanel to
match the syntax used in the meeting dialog.
This creates consistent URL display formatting across both UI components
for better user experience.
Rework clipboard functionality to copy complete meeting information when
users click the copy button in the information side panel.
Previously only partial data was copied, causing user confusion. Now
includes all relevant meeting details as expected.
Improves user experience by meeting user expectations for copy behavior.
Add default telephony configuration to the tilt stack to enable
development workflow around authentication features.
Note: This is a fake/mock configuration and is not functional for
production use. It's intended solely for development purposes.
We've introduced simplifications that improve performance, enhance ux,
and contribute to the overall perception of experience quality.
Previously, our processor handling was overly complex. LiveKit allows us to set
a processor before starting the local video preview track, which eliminates
the black blink glitch that appeared when loading the join component
with a default processor.
This change prevents the unnecessary stopping and restarting
of the local video track.
I'm glad this issue is now resolved.
We also simplified component communication by avoiding props drilling.
Now, we use a single flag to indicate when the user is ready to enter the room.
This significantly reduces the complexity of props passed through components.
Users requested an enhanced visual indicator
for raised hands on the participant tile.
Most major video conferencing platforms display the position of a raised hand
in the queue. This helps hosts quickly see who is requesting to speak,
and in what order, without needing to open the full participant list.
While a minor feature, this improvement is especially valuable for power user
Previously, the participant list was sorted alphabetically by name.
This unintentionally affected the raised hands list,
which inherited the same sorting behavior.
Users requested that raised hands be sorted by order of arrival.
This simple change improves the UX by ensuring that raised hands
are displayed in the correct order.
Previously managed participant hand raised using raw metadata. LiveKit
introduced attributes concept, saves as metadata under hood but makes
update/handling easier.
Still pain that attributes must be strings, cannot pass boolean…
Refactor whole app to use attributes instead of metadata for the raised
hand feature. This commit might introduce regressions. I've double
checked participant list side pannel and the notification features.
Previously I persisted a boolean, I now persist the timestamp at which
the hand was raised. This will be useful in upcoming commits, especially
for sorting raised hands by order of arrival.
The LiveKit API URL is necessary to interact with the API. It uses https
protocol.
Eplicit wss protocol is necessary in Websocket constructor for some
older browsers.
This resolves critical compatibility issues with legacy browsers
(notably Firefox <124, Chrome <125, Edge <125) that lack support
for HTTPS URLs in the WebSocket() constructor. Without explicit WSS
URLs, WebSocket signaling connections may fail, crash, or be blocked
entirely in these environments.
The setting is optional and defaults to the current behavior when
not specified, ensuring zero breaking changes for existing deployments.
Replace hardcoded true values with supportsAdaptiveStream() and
supportsDynacast() checks. LiveKit SDK supports broad browser range but
requires specific APIs - modern features need explicit compatibility checks.
Prevents enabling unsupported WebRTC features on incompatible browsers,
which could led to a poor user experience.
One alternative solution could be to install polyfills.
Connection warmup wasn't working properly - only works when trying to
establish WebSocket first, then workaround kicks in. Call WebSocket
endpoint without auth info expecting 401 error, but enough to initiate
cache for subsequent WebSocket functionality.
Scope this **dirty** trick to Firefox users only. Haven't figured out
how to detect proxy from JS code simply.
Tested in staging and works on our constrained WiFi.
Implement HTTPS prefetch before joining rooms to resolve WebSocket
handshake failures where Firefox+proxy returns HTTP 200 instead of 101.
Reproduced locally with Squid container. No proxy configuration fixes
found - HTTPS warmup is only working workaround. Issue doesn't occur
when signaling server shares webapp domain, making warmup unnecessary.
Use HEAD request to minimize bandwidth.
Test tracking signaling failures to determine root causes when connection
fails. Will remove if it spams analytics - goal is understanding failure
patterns and reasons.
Fix crash when switching from admin session to app with superuser account
that lacks email field. Add null check to prevent Crisp initialization
errors.
Enable Celery task lifecycle events and broker dispatch events per
@rouja's exporter requirements. Basic configuration following
documentation without parameterization.
Show explicit warning when microphone/camera are occupied by other
applications. Helps users understand permission failures and reminds
them to close other video conferencing apps.
Spotted issue through Crisp support - users often forget to quit other
webconfs that don't auto-disconnect when alone.
Add context to feedback page when user is disconnected for joining with
same identity, which is forbidden by LiveKit. Improves user understanding
of disconnection reasons.
Centralize disconnect handling to ensure all client-initiated disconnects
trigger feedback page navigation. More extensible for future disconnect
event routing needs, especially when errors happen.
Display notification to prevent silent recording failures. Shows
configured max duration in proper locale if backend provides the limit.
Prevents users from missing recording termination.
Implement method to process egress limit reached events from LiveKit
webhooks for better recording duration management.
Livekit by default is not notifying the participant of a room when
an egress reached its limit. I needed to proxy it through the back.
Create new service to handle recording-related webhooks, starting with
limit reached events. Will expand to enhance UX by notifying backend
of other LiveKit events.
Doesn't fit cleanly with existing recording package - may need broader
redesign. Chose dedicated service over mixing responsibilities.
Move from lobby service to utils for reuse across services. Method is
generic enough for utility status. Future: create dedicated LiveKit
service to encapsulate all LiveKit-related utilities.
Send backend recording duration limit to frontend to display warning
messages when recordings approach or reach maximum allowed length.
This configuration needs to be synced with the egres. I chose to keep
this duration in ms to be consistent with other settings.
Add optional room name, recording time and date to generate better
document names based on user feedback. Template is customizable for
internationalization support.
Reorganize exception handling in recording download screen to prevent
unauthenticated users from getting stuck in loading state. Caught by
production users - my bad;
Resolve float/int to string conversion problems when deserializing Redis
data for PostHog. Added type conversion fix - not bulletproof but works
for most cases. Avoid using for critical operations.
Set default 1h30 limit for audio processing to prevent Whisper from
running excessively long on large recordings. Improves resource
management and job completion times.
Only retry jobs on HTTP errors (docs push failures) rather than all
errors. Skip retries for Whisper processing failures as they won't
succeed on retry.
Add product analytics to understand summary feature usage and behavior.
Track transcript and task metadata for insights without exposing sensitive
content or speaker data.
Hacky but functional PostHog usage - fully optional for self-hosting.
Extensive tracking approach works for current needs despite not being
PostHog's typical use case.
Add PostHog CLI step to inject proper IDs into chunks, enabling error
tracking to map exceptions back to original source code locations
via sourcemaps.
Enable sourcemaps via env variable to link Sentry/PostHog exceptions to
source code. Enable by default for DINUM frontend image to improve
debugging capabilities.
Fix missing Keycloak service in tilt-dinum stack. Error went unnoticed
when switching from tilt-keycloak due to pods not being cleaned between
stack changes.
Implemented a service that automatically creates a SIP dispatch rule when
the first WebRTC participant joins a room and removes it when the room
becomes empty.
Why? I don’t want a SIP participant to join an empty room.
The PIN code could be easily leaked, and there is currently no lobby
mechanism available for SIP participants.
A WebRTC participant is still required to create a room.
This behavior is inspired by a proprietary tool. The service uses LiveKit’s
webhook notification system to react to room lifecycle events. This is
a naive implementation that currently supports only a single SIP trunk and
will require refactoring to support multiple trunks. When no trunk is
specified, rules are created by default on a fallback trunk.
@rouja wrote a minimal Helm chart for LiveKit SIP with Asterisk, which
couldn’t be versioned yet due to embedded credentials. I deployed it
locally and successfully tested the integration with a remote
OVH SIP trunk.
One point to note: LiveKit lacks advanced filtering capabilities when
listing dispatch rules. Their recommendation is to fetch all rules and
filter them within your backend logic. I’ve opened a feature request asking
for at least the ability to filter dispatch rules by room, since filtering
by trunk is already supported, room-based filtering feels like a natural
addition.
Until there's an update, I prefer to keep the implementation simple.
It works well at our current scale, and can be refactored when higher load
or multi-trunk support becomes necessary.
While caching dispatch rule IDs could be a performance optimization,
I feel it would be premature and potentially error-prone due to the complexity
of invalidation. If performance becomes an issue, I’ll consider introducing
caching at that point. To handle the edge case where multiple dispatch rules
with different PIN codes are present, the service performs an extensive
cleanup during room creation to ensure SIP routing remains clean and
predictable. This edge case should not happen.
In the 'delete_dispatch_rule' if deleting one rule fails, method would exit
without deleting the other rules. It's okay IMO for a first iteration.
If multiple dispatch rules are often found for room, I would enhance this part.
Allow configuration variables that handles secrets, like
`DJANGO_SECRET_KEY` to be able to read from a file which is given
through an environment file.
For example, if `DJANGO_SECRET_KEY_FILE` is set to
`/var/lib/meet/django-secret-key`, the value of `DJANGO_SECRET_KEY` will
be the content of `/var/lib/meet/django-secret-key`.
Replace `new RegExp()` constructor calls with regex literal
notation (`/pattern/flags`) following TypeScript best practices.
Improves readability and performance while maintaining
equivalent functionality.
Add readonly modifier to private class attributes that are never reassigned
after initialization. Improves code safety and clearly communicates immutable
intent to other developers.
Remove unnecessary empty constructor that provides no functionality beyond
default constructor behavior. Simplifies class definition and reduces
boilerplate code.
Remove unnecessary React fragments that contain only one child or are direct
children of HTML elements. Simplifies JSX structure by eliminating redundant
wrapper elements that don't add functional value.
Replace `||` operators and conditional checks with `??` where appropriate
for safer null/undefined handling. Nullish coalescing only triggers for
null/undefined values, preventing unexpected behavior with falsy values
like 0 or empty strings.
Remove package manager index caches in Dockerfile to reduce image size and
improve deployment speed.
Even in multi-stage builds, ensure no unnecessary cache data is stored.
Package indexes are redundant for runtime operation and only increase storage,
bandwidth, and deployment time.
Remove assertion statement that was placed after code expected to raise an
exception. The assertion was never evaluated due to the exception flow,
making the test ineffective.
Rework regex pattern to exclude empty string matches since
url_encoded_folder_path is optional.
Add additional test cases covering edge cases and failure
scenarios to improve validation coverage
and prevent false positives.
Replace inverted boolean comparisons (not ... ==) with direct opposite
operators (!=) to improve code readability and reduce unnecessary
complexity in conditional statements.
Arrange system package installation arguments in alphabetical order within
RUN instructions to improve readability and maintainability. Enables easier
tracking of changes and helps prevent potential installation errors.
Create DINUM-specific frontend build from generic white-label base to
validate recent white-labeling work. Sources will eventually be extracted
to separate repo and pulled as submodule.
Rewrite copy to avoid direct product name mentions where possible. Use
env variable for unavoidable brand references to enable proper
customization for different deployments.
Replace default "visio" with "LaSuite Meet" and allow env variable
customization. Default Docker image uses "LaSuite Meet", but deployments
can override with custom values by setting env vars and rebuilding.
Add configuration to disable transcription beta form for self-hosted
deployments that don't offer this feature. Quick implementation, needs
refinement.
Clean up fast-shipped features that broke design system by using proper
primary/semantic tokens instead of hardcoded colors. Enables better theme
customization for all implementations.
the footer used is very specific to the DINUM/French gov instance so it
should not be enabled by default for everyone.
it's still a bit weird to keep this footer in the code here but at least
it removes the issue easily. any PR to clean the code is appreciated :)
The Marianne font is pretty specific to the DINUM instance and shouldn't
really be there as default in the repo. We can use a custom CSS file to
load Marianne if needed on a specific instance.
This shouldn't have been in the repo really. Instead of this, add some
css classes, that kinda act as hooks for people using a custom css file
(for example, DINUM) in case they need to
Encapsulate noise reduction availability logic in hook and add feature flag
for quick production disable if issues arise. Gives product owners emergency
control over the feature.
Prevent React warnings about uncontrolled/controlled components by ensuring
lk-user-choice store initializes with default value when noise reduction
setting is missing from existing localStorage.
Create concise hook that listens to audio track status and user noise
reduction preference to automatically handle processor state changes.
Note: Logging could be improved in future iterations.
Implement settings option to enable/disable noise suppression with clear
beta indicator. Label will be removed after production battle-testing.
Note: Settings styling needs polish, will address in future commits.
Implement noise reduction copying Jitsi's approach. RNNoise isn't optimal
but chosen for first draft. Needs production battle-testing for CPU/RAM.
Use global audio context with pause/resume instead of deletion to avoid
WASM resource leak issues in @timephy/rnnoise-wasm dependency. Audio context
deletion may not properly release WASM resources.
Requires discussion with senior devs on resource management approach.
Install wrapper around Jitsi's RNNoise implementation for easier reuse.
Note: Library may not properly release WebAssembly resources based on
code review.
I may have introduced a misusage of the usePersistentUserChoice hook.
I ended using it while expecting it to be a global state, it wasn't.
Fix broken global state that caused user choice desync. Use LiveKit default
persistence functions similar to notification store approach. Carefully
handles existing localStorage data to prevent regressions.
Note: Audio output persistence will be added in future commits.
Replace wildcard imports with specific function imports, particularly for
OS package which could expose dangerous functions. Follows security audit
recommendations to minimize attack surface.
Implement brittle message count tracking to handle chat emissions after
useChat API changes. Temporary fix until refactoring to new text stream
approach recommended by LiveKit team.
Ref: https://github.com/livekit/components-js/issues/1158
Add session duration tracking and consolidate all disconnect events
(including client-initiated) with timing data for comprehensive
connection analytics.
Correct OIDC_REDIRECT_ALLOWED_HOSTS configuration that was preventing proper
URL validation. Thanks to @nathanvss for identifying and fixing the issue.
Note: Update your common env file with corrected values.
Track connection issues to identify user problems. Skip client-initiated
disconnects (normal flow). Disconnect events provide richer data than
reconnect events which lack reason details.
Next: Add error screen for JOIN_FAILURE disconnects to trigger support
workflow for users experiencing connection problems.
The settings CORS_ALLOW_ALL_ORIGINS was set to True by default.
This error is inherited from a old mistake made back in the days
while working on the initial impress demo.
I wrongly configured the settings. This error was propagated when
@sampaccoud copied impress code to kickstart LaSuite Meet.
This is not something we want, this should be only allowed in
development. We change the value in all the manifests in order to have
the desired behavior in non development environments.
Our Helm chart wasn't suitable for use with Helm alone because jobs
remained after deployment. We chose to configure ttlSecondsAfterFinished
to clean up jobs after a period of time.
Add handling for when users forget to activate microphones resulting in
empty transcripts. User message not yet internationalized, planned for
next version.
Add friendly instructions to give them hint about the situation.
Display notification clarifying recording is processing and show which email
will receive completion notification. Reduces user mental load per
@sampaccoud's feedback.
Add explicit messaging that recording save is automatic and continues
even after leaving meeting. Reduces user anxiety based on feedback
from Samuel Paccoud.
Handle unhandled exceptions to prevent UX impact. Marketing email operations
are optional and should not disrupt core functionality.
My first implementation was imperfect, raising error in sentry.
To ease filtering issues on sentry, we want to use tags instead of extra
scope. Tags are indexed and searchable, it's not the case with extra
scope. Moreover using set_extra to add additional data is deprecated.
Commit #ebf6d46 on docs.
Show recording owner(s) directly in admin list interface to speed up
troubleshooting. Previously required clicking into each object to identify
owner. Handles multiple owners (rare) by displaying a default message.
The current path is `/api/v`, and it doesn't work with `ingress-nginx`.
I'm not sure if other ingress controllers work with this prefix,
but changing it to `/api/` will work for `ingress-nginx`
and likely for others as well.
Downgrade @livekit/components-js due to bug introduced in version 2.9.0.
Issue has been reported to upstream maintainers at:
https://github.com/livekit/components-js/issues/1158
Reverting to last known stable version until fix is available.
Add 19 missing env variables and correct typo in description. Used
Claude to generate the list, please feel free to correct any of these
values/descriptions through PR.
Correct spelling in environment variable name as identified by @K900. This
is technically a breaking change for existing deployments using this setting,
but acceptable as we haven't released an official version yet. Will personally
notify known users of this setting about the change to minimize disruption.
Fix issue where user language preferences stopped properly syncing between
frontend and backend, causing inconsistent language experience. Issue was
reported by user and affected localization settings persistence.
Fix test cases for room PIN code generation that were not updated when
max retry limit was increased during code review. Aligns test expectations
with actual implementation to prevent false failures.
Refine French translations to be less literal and preserve English terms for
standard technical concepts. Enhances clarity and maintains industry
terminology conventions.
Add internationalization support for previously untranslated strings related
to room PIN code logic. Ensures consistent localization across all user-
facing room access features.
Enable users to join rooms via SIP telephony by:
- Dialing the SIP trunk number
- Entering the room's PIN followed by '#'
The PIN code needs to be generated before the LiveKit room is created,
allowing the owner to send invites to participants in advance.
With 10-digit PINs (10^10 combinations) and a large number of rooms
(e.g., 1M), collisions become statistically inevitable. A retry mechanism
helps reduce the chance of repeated collisions but doesn't eliminate
the overall risk.
With 100K generated PINs, the probability of at least one collision exceeds
39%, due to the birthday paradox.
To scale safely, we’ll later propose using multiple trunks. Each trunk
will handle a separate PIN namespace, and the combination of trunk_id and PIN
will ensure uniqueness. Room assignment will be evenly distributed across
trunks to balance load and minimize collisions.
Following XP principles, we’ll ship the simplest working version of this
feature. The goal is to deliver value quickly without over-engineering.
We’re not solving scaling challenges we don’t currently face.
Our production load is around 10,000 rooms — well within safe limits for
the initial implementation.
Discussion points:
- The `while` loop should be reviewed. Should we add rate limiting
for failed attempts?
- A systematic existence check before `INSERT` is more costly for a rare
event and doesn't prevent race conditions, whereas retrying on integrity
errors is more efficient overall.
- Should we add logging or monitoring to track and analyze collisions?
I tried to balance performance and simplicity while ensuring the
robustness of the PIN generation process.
The idea behind wrapping choices in `lazy` function was to allow
overriding the list of languages in tests with `override_settings`.
This was causing makemigrations to keep on including the field in
migrations when it is not needed. Since we finally don't override
the LANGUAGES setting in tests, we can remove it to fix the problem.
Taken from docs #c882f13
Remove translation markers from backend strings that are never displayed to
users. Streamlines localization process by focusing only on user-visible
content that requires actual translation.
Implement German translations throughout the application to better serve
German-speaking users. Expands language options beyond existing French,
English, and Dutch to improve accessibility for German counterparts.
Block recording and transcript features when user isn't connected to prevent
database state corruption. Users were previously able to trigger these
actions despite being disconnected.
Enhance meeting code input to accept codes without hyphens and make input
case-insensitive. Addresses usability issue observed with touch screen and
virtual keyboard users who struggled with precise formatting. Improves
accessibility for users with pointing pens and limited input precision.
requested by @spaccoud
Implement light color variant for reactions triggered by current user versus
standard color for other participants' reactions. Provides visual cue to help
users easily identify their own emoji reactions in the conversation flow.
Replace UTF character-based emoji with custom image assets designed by our
UX/UI team. Enhances cross-platform compatibility of reactions that were
previously inconsistent between operating systems. Specifically addresses
issue where emoji sent from Mac weren't properly displayed on all client
systems.
Prevent layout shift in vertical menu by adapting video element height based on
orientation. Eliminates glitchy effect where stopping a processor doubled
video height and pushed menu options downward for a few ms.
Separate landmark processor logic to avoid entanglement with background
processing. Ensures future refactoring can replace custom background
implementation without affecting landmark functionality.
Implement browser detection to explicitly stop processors in Firefox and other
browsers that lack full support for modern web APIs, before switching from
one processor to another.
This issue was introduced by recent upgrade of track processor.
An issue has been opened.
Implement modal alert dialog when recording initialization fails. Provides
clear error feedback to users when API cannot start recording process,
improving error state communication.
Display loading spinner when recording request is sent instead of waiting
for API confirmation. Provides immediate feedback during slow server
responses to improve perceived responsiveness.
Implement broad exception handling to catch any non-twirp errors
during recording operations. Ensures recording status is properly reset to
"failed to start" when errors occur, allowing users to retry the recording
while still logging errors to Sentry for investigation.
It's generally a bad practice, however in this case it's fine, I am
catching exception beforehand and it only acts as a fallback.
Restrict access to room user permissions data by excluding this information
from room serializer response for non-admin/owner users. Previously all
members could see complete access lists. Change enforces stricter information
access control based on user role.
Spotted in #YWH-PGM14336-5.
Remove BrowsableAPIRenderer from API options, restricting output to JSON
format only. Prevents leakage of sensitive information like resource IDs and
user identifiers that were previously exposed in renderer dropdown options.
Issue identified in #YWH-PGM14336-4 report.
These information was considered as a critical disclosure by hackers.
Restructure ResourceAccess viewset to align with Room and Recording viewset
patterns. Clean up implementation while preserving identical behavior and
API contract. Improves code consistency and maintainability across related
viewsets.
ResourceAccessPermission inherits from IsAuthenticated.
Reverse default behavior for Panel component to unmount content from DOM when
closed instead of keeping it alive. Makes DOM updates more lightweight by
removing unused panel content. Improves performance particularly in complex
room with hundred of participants.
Exception made for chat panel which retains keepAlive=true to preserve
unsent messages that users may want to submit later.
Implement new keepAlive property for Panel component to control DOM retention
when panel is closed. When false, panel content is unmounted from DOM on
close, resetting scroll position and input states. Provides finer control
over panel behavior and memory management.
Implement conditional rendering that hides all feedback-related UI components
when feedback is disabled in backend configuration.
Also, feedback URL is now customizable.
This change enhances user experience by making automatic login more responsive.
Only occurs on app navigation/refresh, not internal navigation.
Testing in production, can revert if needed. Will later refactor to use
backend configuration.
Fix calendar integration by preventing silent login triggers within webmail
iframes. Refactor code to only initialize app components when not in SDK
context. Resolves unexpected behavior in Firefox where iframes were
incorrectly rendering the homepage instead of intended calendar content.
Fix container networking issue where app-dev container couldn't resolve
localhost address when calling LiveKit API. Update configuration to use
proper container network addressing for backchannel communication between
services.
Create dedicated utility function for livekit API client initialization.
Centralizes configuration logic including custom session handling for SSL
verification. Improves code reuse across backend components that interact
with LiveKit.
Refactor BaseEgress class to leverage latest livekit-api client's custom
session support. Simplifies code by using built-in capability to disable SSL
verification in development environments instead of previous workaround.
Remove BaseEgress tests that were overly complicated and had excessive
mocking, making them unrealistic and difficult to maintain. Will replace with
more straightforward tests in future commits that better reflect actual code
behavior.
Update livekit-api dependency to most recent release, enabling custom session
configuration. New version allows disabling SSL verification in local
development environment through session parameter support.
Add recording expiration information to frontend interface, showing number
of days until expiration or indicating permanent status. For expired
recordings, display the date since which content has been unavailable.
Improves transparency about content lifecycle.
Add validity duration (number of days valid) to email
notifications for recordings. Informs users about their recording's lifespan,
providing important context about content availability.
Add expiration system for recordings.
Include option for users to set recordings as permanent (no expiration)
which is the default behavior.
System only calculates expiration dates and tracks status - actual deletion
is handled by Minio bucket lifecycle policies, not by application code.
Customize email notifications for recording availability based on each user's
language and timezone settings. Improves user experience through localized
communications.
Prioritize simple, maintainable implementation over complex code that would
form subgroups based on user preferences. Note: Changes individual email
sending instead of batch processing, which may impact performance for large
groups but is acceptable for typical recording access patterns.
Fix inconsistent test naming resulting from copy-pasted examples. Rename
tests to properly reflect their actual testing purpose and improve code
maintainability.
Implement new hook that synchronizes user language and timezone preferences
from frontend to backend. Ensures consistent localization across and
notifications. Note: Current implementation works but auth code requires
future refactoring.
Rename generic "isLoading" variable to more specific "isConfigLoading" to
accurately reflect its purpose. Improves code readability by making state
variable names more explicit.
Add user language and timezone to serialized user data to enable frontend
customization. Allows backend email notifications to respect user's
localization preferences for improved communication relevance.
Add Dutch language translations for backend text strings and compile
translation files for production use. Improves localization support for
Dutch-speaking users.
Add English language translations for backend text strings and compile
translation files for production use. Improves localization support for
English-speaking users.
Add French language translations for backend text strings and compile
translation files for production use. Improves localization support for
French-speaking users.
Replace simple trans tags with blocktrans tags in download instructions
to properly handle quoted text in translations. Ensures quotes within
translated strings are correctly preserved during localization.
Add Dutch (nl) language configuration to backend to match available frontend
languages. Ensures consistent language options across the entire application.
Update translation files to include previously missed strings from email
templates. Ensures complete localization coverage across all backend
components including notification emails.
Add aria-label to microphone buttons in participant list to clearly indicate
mute functionality for current user and other participants. Set
aria-hidden on SVG icons to prevent redundant screen reader announcements.
Increment Helm chart version to reflect changes to backend job component
naming. Ensures proper versioning of configuration changes in deployment
pipeline.
Update backend job configurations to use distinct component names instead of
sharing names with deployments. Prevents conflicts during cluster updates
and migrations that were causing unexpected behavior. Improves deployment
reliability and resource identification.
Rename backend migration job to a more descriptive name that clearly
indicates its purpose. Improves code clarity and makes deployment
configuration more self-documenting.
Add environment variable to control data directory location when building
outside of Docker. Improves flexibility for non-containerized deployments
where storing data at filesystem root is inappropriate or undesirable.
Fix UI flickering where authentication screen briefly appeared for logged-in
users during initial data loading. Address issue caused by increased request
delay from waterfall cascade introduced by configurable silent auth setting.
Modify media auth endpoint to properly handle recordings with "Notification
succeeded" status alongside "Saved" status. Previous code incorrectly
expected only "Saved" status, causing access issues after email notifications
were sent and status was updated.
Implement new side panel that provides easy access to meeting information
with copy/paste capabilities. Introduces xs text size to accommodate longer
URLs. Panel includes space for future documentation links about meeting
functionality. Addresses direct user requests for simpler sharing of meeting
details.
Implement proper error message display when recordings are unavailable due
to being active, pending webhook notification, or other transitional states.
Improves user experience by clearly communicating why content cannot be
accessed and setting appropriate expectations.
Create initial version of dedicated page for recording downloads, linked
directly from email notifications sent to users. Implementation is basic
but functional, serving as temporary solution until files can be stored in
drive storage. Enables recipients to access recordings through direct links.
Encapsulate URL base generation logic for media downloads into a reusable
utility function, mirroring the approach used in the API. Improves code
consistency and reduces duplication across frontend components.
Add new API call to retrieve detailed information about recordings.
Enables frontend to access metadata and status information needed for
download interfaces.
Add recording key to serialized API response to enable frontend to generate
proper download links without additional backend calls. Simplifies media
access workflow across the application.
Generalize error message in HasPrivilegesOnRoom permission class to reflect
its broader usage beyond just recording contexts. Improves clarity when
this permission check fails in various application scenarios.
Implement new endpoint allowing admin/owner to invite participants via email.
Provides explicit way to search users and send meeting invitations with
direct links.
In upcoming commits, frontend will call ResourceAccess endpoint to add
invited people as members if they exist in visio, bypassing waiting room
for a smoother experience.
Add new application base URL configuration setting. While somewhat redundant
with existing domain setting, these serve different purposes in the
application. Base URL will be used for constructing complete URLs in
notifications and external references.
Enable recording status toast to function as clickable element that reopens
the side panel for admins and owners. Provides convenient way to access
recording controls when side panel has been previously closed.
Implement discreet visual notification that appears when tools are active.
Helps users locate and return to active tools they may have closed
during their session.
Fix code that accidentally exposed personal email addresses in logs during
email sending failures. Modify logging to remove identifying information
to protect user privacy while still providing useful debugging context.
Original code was inspired by Docs.
Add visual distinction between recording initialization and active recording
phases in status toast. Clearly communicates to users when recording becomes
active versus when it's still in the loading/preparation phase.
Change recording toast color to red following standard recording conventions.
Improves visibility based on user feedback to make recording status more
apparent during active sessions.
Add explicit beta tags to transcript and screen recording functionality to
clearly indicate these features are still in development. Helps set proper
user expectations by communicating that these capabilities may be unstable.
Add visual spinner indication to start button when initializing transcript
or screen recording. Provides clear feedback that recording process is
starting rather than leaving users uncertain about system status.
Display loading spinner in side panel during transcript and screen recording
save operations. Provides visual feedback about ongoing processing that was
previously only indicated by title text, making the save status more explicit
to users.
Modify screen recording layout to focus on active speaker or shared screen
content. Provides better recording quality by prioritizing relevant visual
elements. Temporary solution until custom visio template is implemented.
Implement configuration option in backend to enable or disable silent login
functionality. Provides flexibility to control this authentication behavior
through server settings.
Requested by user self-hosting the project. Not all OIDC provider support
prompt=none param.
Implement cancel/reset functionality that appears while meeting creation is
processing. Allows users to abort the operation if it stalls or encounters
issues, improving recovery from error states.
Update button text based on user feedback to more clearly communicate that
it creates a link with Visio tool.
Improves user understanding of the feature's purpose.
Add a sound notification while a participant is waiting in the lobby.
KISS, use the same notification as the one when participant join
the room, thus, without any extra works, user can already toggle the
notification in settings.
In a v2, a dedicated notification could be added.
Requested by a user.
Implement secure recording file access through authentication instead of
exposing S3 bucket or using temporary signed links with loose permissions.
Inspired by docs and @spaccoud's implementation, with comprehensive
viewset checks to prevent unauthorized recording downloads.
The ingress reserved to media intercept the original request, and thanks to
Nginx annotations, check with the backend if the user is allowed to donwload
this recording file. This might introduce a dependency to Nginx in the project
by the way.
Note: Tests are integration-based rather than unit tests, requiring minio in
the compose stack and CI environment. Implementation includes known botocore
deprecation warnings that per GitHub issues won't be resolved for months.
Add Django built-in mixins to recording viewset to support individual record
retrieval. Enables frontend to access single recording details needed for
the upcoming download page implementation.
Introduce new property that verifies if a recording file has a saved
status. While the implementation is straightforward, it improves code
readability and provides a clear, semantic way to check file status.
Move logic for calculating recording keys and file extensions into proper
properties on recording objects. Simplifies access to Minio storage keys
and clearly documents expected behavior when saving recordings across the
application.
Convert hardcoded string file extensions into a well-defined Python enum.
Improves type safety and centralizes extension definitions for better
maintainability and consistency across the codebase.
It was dirty manipulating literals for file extension validation …
Include recording mode in serialized data to enable conditional UI elements
in frontend. Allows download controls to be dynamically enabled or disabled
based on the specific recording type being used.
Screen recording will be downloadable when transcript won't.
Implement backend method to send email notifications when screen recordings
are ready for download. Enables users to be alerted when their recordings are
available. Frontend implementation to follow in upcoming commits.
This service is triggered by the storage hook from Minio.
Add minimal unit test coverage for notification service, addressing previous
lack of tests in this area. The notification service was responsible for
calling the unstable summary service feature, which was developped way too
quickly.
The email template has been reviewed by a LLM, to make it user-friendly and
crystal clear.
Regenerate translation files to include all recent backend string changes.
Address backlog of untranslated content that accumulated during recent
development cycles.
Update recording side panel to use semantic header element instead of plain
text. Improves accessibility by providing proper document structure and
enhances visual hierarchy in the user interface.
Implement mutual exclusivity between transcript and screen recording modes
to prevent both from being active simultaneously. Add validation logic to
ensure users can only enable one recording type at a time.
Extend recording availability and access hook to work with all recording
types instead of being transcript-specific. Create flexible implementation
that determines availability and permissions for screen recordings and
future recording formats.
Extend recording state badge component to work with all types of recordings
instead of just transcripts. Create flexible implementation that supports
screen recordings and future recording formats while maintaining consistent
visual indicators.
Convert transcript-specific toast notification into a flexible component
that works with any recording type. Create extensible design that can
accommodate screen recordings and future recording formats. Implementation
is functional though not perfect, with room for future enhancement.
Introduce a dedicated store for transcription to better manage its status
independently of meeting recording status. This lays the groundwork for
future improvements, especially as we plan to support additional recording
options beyond the current setup.
This isn't perfect and still coupled with room recording status
On the first room creation, when the authentication redirection takes
place, the iframe wasn't properly messaging the parent.
Fixed it. Send the room data in any of the two methods to acquire it.
Actually, the code when gathering data through the callback endpoint is
a bit dirty.
Improve UX by adding a delay before showing tooltips in the lateral menu.
Users often hover from bottom to top, causing tooltips to overlap other
options too quickly.
Use a totally different strategy, which hopefully works in prod env.
Actually broadcast channel cannot be shared between two different
browsing context, even on a same domain, an iFrame and a pop up
cannot communicate.
Moreover, in an iFrame session cookie are unavailable.
Rely on a newly created backend endpoint to pass room data.
Necessary in cross browser context situation, where we need to
pass data of a room newly created between two different windows.
This happens in Calendar integration.
Enhanced the FaceLandmarksProcessor to include
a new 'french' effect, allowing users to add
a beret image to detected faces. Updated the
EffectsConfiguration component to toggle this
effect and modified localization files to
reflect the change from 'mustache' to 'french'.
Added functionality to display mustache effects
on detected faces. Enhanced the EffectsConfiguration
component to toggle these effects and updated
localization files for this effects.
Added functionality to draw glasses on detected
faces by calculating eye positions and scaling
the glasses image accordingly. Initialized glasses
image in the constructor for improved visual
effects during face tracking.
Switch from insanely-fast-whisper to WhisperX for transcription services,
gaining word-level granularity not available with FlashAttention in previous
API. Whisper was packaged in FastAPI image with basic diarization and
speaker-segment association capabilities.
Implementation prioritized speed to market over testing. Future iterations
will enhance diarization quality and add proper test coverage. API consumers
should expect behavioral differences and new capabilities.
This change allows the marketing service timeout to be easily adjusted
via an environment variable, eliminating the need for a new software release.
Additionally, the update makes the code more explicit and easier to maintain.
Improves sendData reliability by preventing execution when the room
doesn’t exist.
This change addresses errors in staging and production where waiting
participants arrive before the room owner creates the room.
In remote environments, the LiveKit Python SDK doesn’t return a clean
Twirp error when the room is missing; instead of a proper "server unknown"
response, it raises a ContentTypeError, as if the LiveKit server weren’t
responding with a JSON payload, even though the code specifies otherwise.
While the issue cannot be reproduced locally,
this should help mitigate production errors.
Part of a broader effort to enhance data transmission reliability.
Importantly, a participant requesting entry to a room before the owner
arrives should not be considered an exception.
Invert operation sequence to first notify people in room before setting
participant in cache. Fixes infinite loop issue caused by 3s cache timeout
for waiting participants when requests take too long. Problem only occurred
when notifications were delayed, as faster notification delivery masked the
race condition.
Updated styling system to implement the official French font used across all
La Suite products. This enhances brand consistency and improves the visual
identity alignment with other government digital services.
Created modal that appears when users fail to share their entire screen. Also
added documentation helper that explains proper screen sharing setup steps for
different operating systems and browsers.
Related to 5b1a2b20de
There are no references to the `generate_document.html` template
in the codebase. The same goes for the `INVITATION_VALIDITY_DURATION` setting,
which arrived straigt from https://github.com/suitenumerique/docs
WeasyPrint is (I believe) not used in the project, so it is a ghost dependency.
Fixed two HIGH severity vulnerabilities in libxslt:
- CVE-2024-55549: Use-After-Free in libxslt (xsltGetInheritedNsList)
- CVE-2025-24855: Use-After-Free in libxslt numbers.c
The image was manually updated as no more recent unprivileged nginx-based
images were available. This addresses the security scan failures from Trivy.
Revamp README to be more engaging and informative.
Goal: Foster a true open-source spirit by making it easier for
contributors to engage, interact, and contribute.
Heavily inspired by PostHog's excellent README.
Upgraded libxml2 from version 2.12.7-r1 to 2.12.7-r2 to address
a HIGH severity NULL Pointer Dereference vulnerability. This security update
prevents potential application crashes that could be triggered through
malicious XML input.
Added intuitive make commands that help new developers quickly set up
frontend dependencies and launch the entire stack. This streamlines
onboarding by providing clear entry points for common development tasks
without requiring deep knowledge of the project structure.
Added configuration to docker-compose stack allowing users to run the
frontend in production mode. This simplifies the developer onboarding,
for those wanting to run the project locally.
Specified the expected platform in dockerize configuration to ensure
compatibility with Mac M2 architecture. This resolves build failures
experienced by developers using Apple Silicon, enabling seamless
development across different hardware.
Add a clear explanatory text about the project's opensource nature.
This provides better context for users while maintaining transparency
about the software license.
Created a proper terms of service page within the application to replace
external doc page redirects. Implemented based on Sophie's accessibility
requirements to improve user experience for all users regardless
of ability.
Created a proper accessibility page within the application to replace external
doc page redirects. Implemented based on Sophie's accessibility requirements
to improve user experience for all users regardless of ability.
Created a proper legal notice page within the application to replace
external doc page redirects. Implemented based on Sophie's
accessibility requirements to improve user experience for all users
regardless of ability.
Added a new style variant to the link primitive component that
visually highlights technical links specifically within legal notices.
This improves clarity and helps users distinguish different link types
in legal documentation.
Override LiveKit Docker image to include nip.io Certificate Authority for
development environment. Addresses issue where LiveKit webhook calls fail in
dev mode due to unknown CA. Custom image places certificate in appropriate
location since LiveKit chart lacks volume mounting options for CA certs or
webhook SSL disabling capabilities.
Discussed with @rouja.
Enable LiveKit webhook feature to notify backend when events occur in rooms.
Configure LiveKit to call our endpoint whenever events are triggered,
providing real-time updates on room activities. Refer to LiveKit
documentation or LiveKitWebhookEventType enum for complete list of available
events.
This commit is not functionnal, LiveKit fails verifying our backend's
certificate. It will be fixed in the upcoming commits.
Add new endpoint to access the event-handler matching service. Route is
protected by LiveKit authentication, handle at the service level.
Enables webhook event processing through standardized API.
Create new service that matches received events with their appropriate
handlers. Provides centralized system for event routing and processing
across the application.
If an event has no handler, it would be ignored.
Implement new lobby service method to clear all participant entries from cache.
Lays foundation for upcoming feature where participant permissions reset when
meetings end. Currently introduces only the cache clearing functionality;
event handling for meeting conclusion will be implemented in future commits
Fix regression caused by competing styling methods in Box component. Remove
duplicate position properties and standardize on simple div with css-in-js
approach to prevent style conflicts and unexpected layout behavior.
Implement text truncation for excessively long usernames in waiting
participant list items to prevent layout overflow and maintain consistent UI
appearance.
Remove group action buttons for accept/deny all participants as they were not
included in the designer's mockups. Functionality may be reintroduced in a
future iteration based on user feedback.
Not necessary for this v1
Add adaptive content to existing notification that displays quick approval
action for the first 10 seconds when new participants request entry. Makes
room access management more efficient without requiring admin to open the
participant panel.
This approach could be apply to the two first participants waiting.
Let's discuss it with the designer.
Add new usePrevious utility hook to track previous values in functional
components. Enables comparing current and previous prop/state values across
renders for improved state management.
Correct throttling configuration for request_entry endpoint from hours to
minutes. Previous setting of 150 requests per hour was insufficient as
participants query approximately once per second while in the lobby.
Replace current red with higher contrast variant when used as background with
white text to meet accessibility contrast requirements. Improves readability
for all users.
Update the menu rendering to an earlier breakpoint due to added admin controls
taking up more space. Temporary adjustment until a more comprehensive layout
enhancement is implemented.
Change the "more options" button layout to horizontal orientation following
patterns used in Jitsi and Whereby. Improves discoverability and makes the
button's purpose more apparent to users.
Update switch component following accessibility consultant recommendations:
make indicator outlined instead of filled when not selected and add checkmark
when selected. Changes align with DSFR guidelines to improve state visibility.
Add aria-hidden="true" attribute to the "site under construction" banner icon
to prevent it from being announced by screen readers. Improves accessibility
by avoiding unnecessary and potentially confusing vocalization
Change footer text from "Accessibility: audit in progress" to "Accessibility:
non-compliant" to accurately reflect current status until formal audit is
completed. Provides more transparent information about accessibility
compliance.
Adjust background color of emoji hover state to ensure minimum visual
contrast ratio as recommended by accessibility consultant.
Change ensures compliance with RGAA accessibility standards.
Add informational message suggesting authentication for users waiting in
lobby without being logged in. Highlight that logging in could grant
immediate access without admin approval when rooms have trusted
access level enabled.
Update admin panel interface to include the newly introduced trusted
user access level option alongside existing public and restricted settings.
Allows room administrators to select this intermediate permission level
through the frontend configuration panel.
Introduce new intermediate access level between public and restricted that
allows authenticated users to join rooms without admin approval. Not making
this the default level yet as current 12hr sessions would create painful
user experience for accessing rooms. Will reconsider default settings after
improving session management.
This access level definition may evolve to become stricter in the future,
potentially limiting access to authenticated users who share the same
organization as the room admin.
Replace excessive mocking with more realistic test scenarios to better
reflect actual code execution. Improves debuggability while maintaining
thorough test coverage.
Deactivate inherited user listing capability that allows authenticated users
to retrieve all application users in JSON format. This potentially unsecure
endpoint exposes user database to scraping and isn't currently used in the
application.
Implement security flag to disable access until properly refactored for
upcoming invitation feature. Will revisit and adapt endpoint behavior when
developing user invitation functionality.
Change entry text to interrogative form to make it sound more polite and
welcoming. Improves tone and friendliness of the user interface through
more considerate language.
Add comprehensive validation for metadata that can be input by users with
LiveKit access tokens. Handle all user-controlled metadata with extra care,
implementing strict checks to prevent injection attacks or other security
issues from malicious input.
Implement regex validation for HSL color format in notification metadata.
Ensures only properly formatted color values are accepted, preventing
potential injection or rendering issues from malformed color strings.
Strengthen decodeNotificationDataReceived function with additional validation
to properly handle malicious input. Ensures application security when
processing potentially dangerous notification data from untrusted sources.
Redis was made a required dependency for running project tests. Update CI
environment to include Redis instance as tests now depend on it for proper
execution. Affects all backend test suites.
This dependency was intorduced by the lobby service.
Implement interface allowing room creators to configure access settings,
with options to set rooms as either public or restricted. Provides users
with control over who can join their rooms.
Introduce new dedicated side panel for room administration, providing
centralized interface for admins to manage room settings and participants.
Content will be added in the upcoming commits.
Add special non-closing notifications for waiting participants that remain
visible until all have been reviewed. Implement complementary system alongside
existing toaster notifications.
Designed with accessibility in mind but would benefit from expert review.
Current UX provides good foundation with quick actions planned for v2.
Add raw loading spinner component from react-aria library to handle
loading states. Will refine styling and appearance after receiving design
review feedback.
Implement list showing waiting participants for admins already in the room.
Initial fetch on render, then stops polling if empty until LiveKit emits event
for new arrivals. Uses long polling with configurable timeouts to prevent UI
flicker. Focus on UX implementation with responsive layout issues remaining
for long participant names.
Update Join component to integrate with the newly introduced lobby system.
Current implementation has functional UX but UI elements and copywriting
still need refinement and will be polished in upcoming commits.
Implement lobby service using cache as LiveKit doesn't natively support
secure lobby functionality. Their teams recommended to create our own
system in our app's backend.
The lobby system is totally independant of the DRF session IDs,
making the request_entry endpoint authentication agnostic.
This decoupling prevents future DRF changes from breaking lobby functionality
and makes participant tracking more explicit.
Security audit is needed as current LiveKit tokens have excessive privileges
for unprivileged users. I'll offer more option ASAP for the admin to control
participant privileges.
Race condition handling also requires improvements, but should not be critical
at this point.
A great enhancement, would be to add a webhook, notifying the backend when the
room is closed, to reset cache.
This commit makes redis a prerequesite to run the suite of tests. The readme
and CI will be updated in dedicated commits.
Extract serialization logic for LiveKit server connection data to make it
reusable across endpoints. Function naming will be improved in future
refactoring when utility functions are moved to a proper service.
Replace unused is_public boolean field with access_level to allow for more
granular control. Initially maintains public/restricted functionality while
enabling future addition of "trusted" access level.
LiveKit uses aiohttp which relies on the ssl module under the hood.
Set certificate file using an env variable, similar to @rouja's fix
for the request module.
This tweak applies only in the dev environment.
Update CI environment to use the same Python version as our Docker image.
Issue surfaced when upgrading IPython to v9, which requires Python 11.
Ensures consistent runtime behavior between CI tests and production.
Add data attributes to important buttons in the frontend to enable tracking
through PostHog actions. Allows measurement of user interaction with key
features to inform future product decisions.
Add optional email collection step for anonymous users submitting survey
responses. Store email in new "unsafe_email" property on PostHog user
profile to enable follow-up troubleshooting while maintaining anonymity.
Addresses inability to contact users reporting issues without accounts.
Fix logout functionality that was failing in 2 out of 3 scenarios where
support and analytics sessions weren't properly closed. Prevents bugs and
behavioral issues when enabling feature flags or advanced PostHog features.
Increase message notification size to improve text readability when
notifications appear, enhancing user experience by making content more
visible at a glance.
Add link to technical notice for our videoconference product describing
network engineering details, required ports, and IP addresses that need to be
allowed in client systems. Helps users properly configure their environments.
Add validation for emoji received through notifications to ensure
participants cannot send forbidden emoji characters. Improves security
by filtering potentially problematic content before display.
Replace invalid session/end endpoint with correct logout endpoint in Keycloak
configuration. Fixes broken logout functionality that prevented developers
from properly signing out of the application during development.
Tilt live updates generate a new image for each change, ending up storing
a lot of images when you are really developing with Tilt.
I have not found a built-in way of cleaning old images from Tilt documentation,
I create a utility doing the dirty work.
The notifications namespace was being lazy-loaded when the first notification
appeared, causing a screen flicker during translation loading. Now preloading
the namespace during i18n initialization to ensure smooth rendering.
Implement a new reactions system allowing users
to send quick emoji responses during video calls.
This feature is present in most visio softwares.
Particulary this commit:
- Add ReactionsButton to control bar with emoji selection
- Support floating emoji animations
This feature is far from perfect. Still not working on Safari.
Also, we should display this warning when user share the current
opened window. Minor enhancement, I don't have time currently
to prioritize these enhancements.
Visual regression was introduced probably by a change on button style.
As this button is quite different than the usual one, remove its inheritance
from the primitive ones.
Users requested that their raised hands be lowered automatically if they become
the active speaker. This change ensures a more natural experience during
discussions, preventing user from forgetting to lower their hand while speaking.
It includes a consumer project which is simply a demo app. The sdk
project includes the first version of the SDK, with a light React
implementation. The first version lays down the foundations of
the iframe sdk framework. The npm package logic is also already
ready to be published.
The create room button is a dedicated route. There is also a bit of
logic implied in this commit, including the BroadcastChannel.
The router has been updated with a /sdk negation in order to avoid
including support and react query debug tool in the iframe.
When displayed in an iframe, not being logged-in causes a redirection
to the home page. Which is not what we want with the SDK integration.
We just want to stay on the same page.
Following user feedback about infinite loops risks, add warning overlay
when users attempt to share their entire screen. The warning explains
the risk and suggests sharing a specific tab instead, providing options
to stop sharing or dismiss the warning while respecting user preferences
for future sessions.
Added temporary root privileges to update OpenSSL libraries. Upgrades libssl3
and libcrypto3 to 3.3.3-r0 to fix HIGH severity vulnerability. Properly
switches back to nginx user after updates. Maintains unprivileged execution
while addressing security concern affecting RFC7250 Raw Public Keys
authentication.
Security: CVE-2024-12797
When loading notification settings from localStorage,
keep user preferences for existing notification types while adding
new notification types with default values.
If a notification type is removed, make sure to get rid of it.
My initial implementation wasn't future proof.
Introduce ToastDuration enum to replace magic numbers for notification
timeouts. Added semantic duration constants for different notification types
(alerts, messages, join/leave events). Improves maintainability and
consistency across toast implementations.
Users frequently miss chat messages due to discrete visual indicators.
Implemented toast notifications showing sender name and message preview to
improve visibility. Added message tracking and auto-dismiss when chat panel
opens.
Remove the warning in handleDataReceived function, it was triggered by
chat message events.
The participant's name in the query key prevented proper cache invalidation
when renamed. Since name changes don't affect query data, removed this
dependency.
On hover, based on participant's type (remove/local) offer an
appropriate action. Either applying effects on the local participant
video or muting the remote participant.
This is a huge enhancement in term of UX, nobody was finding these two
controls in the current menus, and though the features were not
implemented.
Inspired by GMeet. Make central actions available on a participant
tile when a user hover it.
This new interactive zone will be extended with more actions and
controls.
useSyncAfterDelay allows to enable loading indicators only if the
loading takes more than a specific time. It prevent blinking
effect when the loading time is nearly instant.
Some users have ad-blockers or privacy extensions that prevent the Crisp chat
widget script from loading properly. This was causing the support toggle to
still display in rooms, but clicking it had no effect since Crisp was blocked.
This ensures users don't see an inactive support button when their browser
is blocking Crisp functionality.
BackgroundBlurCustomProcessor is renamed to BackgroundCustomProcessor in
order to reflect the fact that is now handles virtual backgrounds too.
BackgroundBlurFactory is also renamed to BackgroundProcessorFactory.
The processor serialization handling has also been updated in order
to support various options, also if persisted in local storage.
This is a wrapper around track-processor-js virtual background
processor. This is needed in order to be used in a generic way
in our code between firefox processors.
I introduced a bug while moving the border radius css style to the
parent element of the video.
On safari, the video element wasn't rounded anymore.
Fix this! Please note our approach should be refactored, nit-picking,
but there are few pixels leaking from the black background on the
video corner.
Disable Picture-In-Picture option for browsers that support it,
to avoid having the option appearing on the video element.
It's not appropriate.
Actually, I am not sure we should disable remote playback ones,
feel free to challenge it.
On unsupported browser showing this option whitout offering the
blur effects to the user would be quite frustrating.
At the moment, safari user cannot blur their background.
Also, avoid offering the option on mobile which are really
cpu-constrained devices.
We need to have an agnostic component to apply effects on any video
track, enters EffectsConfiguration. It takes in input the video
track and outputs the processor applied. This is gonna be used in
order to use the same component on the pre join screen and the in
room customization side panel.
Prevents runtime error when Crisp chat hasn't initialized before component mount
Previously caused crash since we assumed $crisp global was always available.
- Always enable camera/mic by default (like Google Meet)
- Fix video state transitions and add visual feedback
- Simplify form using React Aria components
- Reduce shadow intensity for better visual balance
Each menu item is now a standalone component, improving:
- Code organization & reusability
- Maintainability by reducing OptionsMenuItems complexity
This breaks down large components.
Added an option allowing users to trigger the fullscreen mode while on desktop.
Heavily inspired by the PR #279 from @sylvinus.
Yet, this option allow user to enable/disable the fullscreen mode on the whole
ui, in the next iteration I'll add the same feature but for a given video track.
This is on purpose that the feature is available on desktop only.
The hook code has been partially written by Claude and inspired by @sylvinus
first suggestion.
When using nip.io for local development DNS mapping (which allows hostname-based
access to localhost), we need to explicitly allow these domains in Vite's server
configuration to prevent host security violations.
This check should be ignored when using https.
Implemented collapsible advanced options to maintain usability on narrow screens
following GMeet's UX pattern. Dialog and popover components were chosen
based on GMeet choices, though this introduces potential accessibility concerns
that should be addressed in future iterations.
Current implementation uses JS for breakpoint handling due to challenges with
Panda CSS's pure CSS approach. This workaround was necessary to resolve a
persistent issue where the popover remained open after window expansion beyond
750px, even after the lateral menu trigger was removed from view.
Technical debt note: Code needs refinement, particularly around breakpoint
management and component architecture. Prioritized shipping over perfection to
meet immediate responsive design needs.
We want this screen to have a better ux, the join button was invisible on
some small screen sizes, also we want to align the style of this screen with
the ui of the video conference previously made.
Inspired by GMeet. Actually, these menus are horrible to work with.
This is clearly some technical debt. I fixed the styles, but not the
code, we should refactor them to make easy to chose between two
variant, a light and a dark one.
Updates build configuration to support new major version.
This might introduce some breaking changes.
I've read their migration guide, everything seems okay.
Key prop was incorrectly passed down as a regular prop to ParticipantListItem
instead of being used at the array mapping level. Key is a special React prop
for list rendering and cannot be accessed as a component prop.
We cannot use track-processor-js for Firefox because it uses various
approaches not compatible with Firefox. Firefox cannot run inference
on GPU, so we must use CPU, we could also not use MediaStreamTrackProcessor nor
MediaStreamTrackGenerator. So I had to make a new implementation from
the ground up, using canvas filters and CPU inferences.
Improved script portability by switching to `/usr/bin/env bash`, ensuring
better support across environments where `bash` may not be the default shell.
Avoid disabling SSL verification in development environment,
simply mount in the right folder, an extra volume, that declares
the certificate authority necessary to validate nip.io domains.
Updated deployments metadata to include configurable annotations using
`.Values.xxx.dpAnnotations`. This change supports the new approach of
storing secrets in an external Vault, allowing annotations to be added in
staging/prod to trigger refreshes when external secrets change.
Will be configured accordingly in La Suite deploiement repository.
Refactored ClusterSecretStore and ExternalSecret deployment to support
VaultWarden custom fields beyond login/password, including multi-line
values via file input. Also made the secret template name configurable
for added flexibility.
ClusterSecretStore are supposed to be cluster-wide objects, it's useless
to precise any namespace.
Previous merge of helm chart refactoring was incomplete. Currently,
linting only occurs during chart publication rather than on each PR.
This temporary solution will be improved in a future update.
Existing make command wasn't working on Mac. Fixed it, plus
refactored it in a proper script, so we can share it among
projects, as for the build kind cluster one.
External secrets are created in a dedicated namespace, to avoid
duplicating them if we spawn several LaSuite applications on the
same local stack.
Fix the following issue :
```
The workflow is not valid. .github/workflows/release-helmchart.yml
(Line: 25, Col: 12): Job 'release' depends on unknown job
'helmfile-lint'.
```
Use the common create_cluster.sh in order to improve cooperation
between teams.
Also, mount extra volume, to avoid setting ssl_verify to false,
while using request module in Python.
We have a dedicated deployment repository, also containing
the Helm chart. To avoid duplicating and maintaining twice
a chart, we decided to publish our Helm chart.
At first we tried the official chart releaser action, however,
this ended in creating a new release on Github for each chart
update, which wasn't acceptable.
Offer a standalone dev environment or a dinum specific dev
environment with ProConnect authentication.
Needed to refactor the way secrets are managed in the project,
and also re-organize the Helm chart to make it totally standalone.
Particulary useful for external wanting to run the project.
Work done by @rouja.
Submitting new users to the marketing service is currently handled
during signup and is performed only once.
This is a pragmatic first implementation, yet imperfect.
In the future, this should be improved by delegating the call to a Celery
worker or an async task.
Introduced a MarketingService protocol for typed marketing operations,
allowing easy integration of alternative services.
Implemented a Brevo wrapper following the protocol to decouple
the codebase from the sdk. These implementations are simple and pragmatic.
Feel free to refactor them.
Found this solution googling on Stack Overflow.
Without a default ordering on a model, Django raises a warning, that
pagination may yield inconsistent results.
The new endpoint requires title and content, breaking
the original implementation. This hotfix ensures staging works
immediately while I plan an LLM-based solution
for title generation.
It led to an error, with two occurrences of the form's URL being
desynchronized. Fix this minor issue, and refactor the constant
in a constant file to be shared across the app.
Enabled recording feature in production. MinIO needs to trigger a webhook
when a new recording is saved. Secret will be updated in the upcoming commits.
Updated the webhook URL to the definitive version in docs.
Jacques also updated the webhook secret for authentication
against Impress API. Not tested locally.
We want to have a specific responsive menu on mobile browsers.
It also implied to refactor a bit the way the settings modals is opened
because it could be opened from this responsive menu, so in order to achive
that a specific context has been created in order to allow its opening
from any sub component of the control bar.
We want to be able to customize the variant which those toggle uses as
well as being able to trigger an event when the toggle is pressed. This
is going to be useful to close the responsive menu after each clic as
react-aria prevent click event propgation.
According to the documentation:
Dynacast dynamically pauses video layers that are
not being consumed by any subscribers, significantly
reducing publishing CPU and bandwidth usage.
Dynacast will be enabled if SVC codecs (VP9/AV1) are used.
Multi-codec simulcast requires dynacast
My goal is to reduce CPU and bandwidth usage for clients.
Dynacast is enabled both in OpenTalk and LiveKit demo app!
Adaptive stream is a key optimization in large room.
Enabled adaptive stream to automatically manage
the quality of subscribed video tracks, optimizing
for bandwidth and CPU usage.
When video elements are visible, it adjusts
the resolution based on the size of the largest visible
element. If no video elements are visible, it
temporarily pauses the track until they are visible again.
Additionally, introduced support for custom pixel density,
which defaults to `2` for high-density screens
(devicePixelRatio ≥ 3) or `1` for standard screens.
Setting it to `screen` allows the pixel density to match
the actual screen's devicePixelRatio, optimizing video
clarity on ultra-high-definition displays.
This ensures a balance between streaming quality
and resource consumption.
This might also significantly increase the bandwidth
consumed by people streaming on high definition screens.
It needs to be battle tested.
OpenTalk uses a adaptiveStream equals true, while LiveKit
demo app uses 'screen' value. I followed OpenTalk choice,
I was scared 'screen' value creates performance issues
for user with high resolution screen in poor network conditions.
As a mandatory codec in WebRTC specifications, VP8 serves as
the baseline for compatibility, making it the default choice
in LiveKit client configuration.
There is room for optimization.
Newer codecs like VP9 offer significant efficiency gains
compared to VP8, with a 23-33% improvement in compression
efficiency. This translates to better video quality at
the same bitrate or reduced bandwidth usage for the same quality.
VP9 is supported in Safari starting from version 15.0+,
and Firefox offers partial support. However, Firefox lacks
support for VP9's Scalable Video Coding (SVC).
With SVC, participants can send a single VP9 stream
with multiple spatial or temporal layers. This allows receivers
to dynamically adjust video quality by using lower layers when
resolution or bandwidth needs to be reduced, improving
adaptability in heterogeneous network conditions.
Simulcast, by contrast, sends multiple separate streams
at different resolutions. While widely supported in VP8 and VP9,
it consumes more bandwidth compared to SVC.
The configuration added here is based on the LiveKit demo app,
which defaults to VP9 when supported. OpenTalk’s configuration
also recommends VP9.
If a browser does not support VP9, LiveKit falls back to VP8 or
other codecs as needed. Notably, LiveKit disables VP9 encoding for
Firefox due to longstanding issues, but it can still decode VP9
streams and encode VP8 for outgoing streams. This ensures
compatibility with other participants, even in mixed environments
where some browsers use VP9 and others fallback to VP8.
In theory, participants do not all need to switch to a single codec,
as both LiveKit and browsers intelligently handle codec negotiation
on a per-participant basis. This dynamic adaptation ensures seamless
communication without manual intervention.
A similar challenge with codec compatibility was raised
in Jitsi two years ago, check issue #10657.
Before any release, this needs to be battle tested
with Firefox 115 browsers.
Introduced a global state to handle user preferences related to notifications.
The first use case is sound notifications, allowing users to disable them
based on feedback.
Additionally, the sound volume is now stored globally, making it easy to
configure in the future if needed. I've lowered the volume of
the notifications to make them more discreet.
Preferences are persisted in local storage, ensuring they are retained
between meetings.
Add STORAGE_KEYS object to centralize localStorage keys,
ensuring no key overlaps by maintaining a single source
of truth for key declarations across the app.
Might be premature, as only the notification store will be persisted.
Valtio allows state persistence in local storage, which is
necessary for the notification store. In this case, I'll need
to persist a `proxyMap`—a utility provided by Valtio to create
an observable map.
However, since `proxyMap` isn't natively serializable,
I'll need to implement two custom functions: one for serialization
and another for deserialization (revival).
Regarding the file structure, I've named the file `utils/valtio`,
but this can be discussed further. The purpose of this file is
to centralize common utility functions related to Valtio
for better organization and reuse.
I found the item names unclear, so I updated them for better clarity.
I also removed the unnecessary 'lowered' item and added
a TODO comment about handling the message received notification,
which is not yet implemented in the code.
Inspired by Robin's design, I've styled a React Aria
Switch component using our DSFR theme.
This is an initial draft and isn't yet pixel-perfect compared
to Robin's design. It also hasn't been integrated into
the form inputs yet.
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at visio@numerique.gouv.fr. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [PostHog Code of Conduct](https://github.com/PostHog/posthog/blob/master/CODE_OF_CONDUCT.md), inspired from Contributor Covenant version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
Thank you for taking the time to contribute! Please follow these guidelines to ensure a smooth and productive workflow. 🚀🚀🚀
To get started with the project, please refer to the [README.md](https://github.com/suitenumerique/meet/blob/main/README.md) for detailed instructions.
Please also check out our [dev handbook](https://suitenumerique.gitbook.io/handbook) to learn our best practices.
## Creating an Issue
When creating an issue, please provide the following details:
1.**Title**: A concise and descriptive title for the issue.
2.**Description**: A detailed explanation of the issue, including relevant context or screenshots if applicable.
3.**Steps to Reproduce**: If the issue is a bug, include the steps needed to reproduce the problem.
4.**Expected vs. Actual Behavior**: Describe what you expected to happen and what actually happened.
5.**Labels**: Add appropriate labels to categorize the issue (e.g., bug, feature request, documentation).
## Commit Message Format
All commit messages must adhere to the following format:
`<gitmoji>(type) title description`
* <**gitmoji**>: Use a gitmoji to represent the purpose of the commit. For example, ✨ for adding a new feature or 🔥 for removing something, see the list here: <https://gitmoji.dev/>.
***(type)**: Describe the type of change. Common types include `backend`, `frontend`, `CI`, `docker` etc...
***title**: A short, descriptive title for the change, starting with a lowercase character.
***description**: Include additional details about what was changed and why.
### Example Commit Message
```
✨(frontend) add user authentication logic
Implemented login and signup features, and integrated OAuth2 for social login.
```
## Changelog Update
Please add a line to the changelog describing your development. The changelog entry should include a brief summary of the changes, this helps in tracking changes effectively and keeping everyone informed. We usually include the title of the pull request, followed by the pull request ID to finish the log entry. The changelog line should be less than 80 characters in total.
### Example Changelog Message
```
## [Unreleased]
## Added
- ✨(frontend) add AI to the project #321
```
## Pull Requests
It is nice to add information about the purpose of the pull request to help reviewers understand the context and intent of the changes. If you can, add some pictures or a small video to show the changes.
### Don't forget to:
- check your commits
- check the linting: `make lint && make frontend-lint`
- check the tests: `make test`
- add a changelog entry
Once all the required tests have passed, you can request a review from the project maintainers.
## Code Style
Please maintain consistency in code style. Run any linting tools available to make sure the code is clean and follows the project's conventions.
## Tests
Make sure that all new features or fixes have corresponding tests. Run the test suite before pushing your changes to ensure that nothing is broken.
## Asking for Help
If you need any help while contributing, feel free to open a discussion or ask for guidance in the issue tracker. We are more than happy to assist!
## Réutilisation de l’« Information » sous cette licence
Le « Concédant » concède au « Réutilisateur » un droit non exclusif et gratuit de libre « Réutilisation » de l’« Information » objet de la présente licence, à des fins commerciales ou non, dans le monde entier et pour une durée illimitée, dans les conditions exprimées ci-dessous.
**Le « Réutilisateur » est libre de réutiliser l’« Information » :**
- de la communiquer, la reproduire, la copier ;
- de l’adapter, la modifier, l’extraire et la transformer, notamment pour créer des « Informations dérivées » ;
- de la diffuser, la redistribuer, la publier et la transmettre, de l’exploiter à titre commercial, par exemple en la combinant avec d’autres informations, ou en l’incluant dans votre propre produit ou application.
**Sous réserve de :**
- mentionner la paternité de l’«Information» : sa source (a minima le nom du « Concédant ») et la date de la dernière mise à jour de l’« Information » réutilisée.
Le « Réutilisateur » peut notamment s’ acquitter de cette condition en indiquant l’adresse (URL) renvoyant vers « l’Information » et assurant une mention effective de sa paternité.
**Par exemple :**
Dans le cas d’une réutilisation de la base SIRENE de l’INSEE, mentionner l’URL du « Concédant » : www.insee.fr + la date de dernière mise à jour de l’Information réutilisée.
Cette mention de paternité ne doit ni conférer un caractère officiel à la « Réutilisation » de l’« Information », ni suggérer une quelconque reconnaissance ou caution par le « Concédant », ou par toute autre entité publique, du « Réutilisateur » ou de sa « Réutilisation ».
## Données à caractère personnel
L’« Information » mise à disposition peut contenir des « Données à caractère personnel » pouvant faire l’objet d’une « Réutilisation ». Alors, le « Concédant » informe le « Réutilisateur » (par tous moyens) de leur présence, l’ « Information » peut être librement réutilisée, sans faire obstacle aux libertés accordées par la présente licence, à condition de respecter le cadre légal relatif à la protection des données à caractère personnel.
## Droits de propriété intellectuelle
Il est garanti au « Réutilisateur » que l’ « Information » ne contient pas de « Droits de propriété intellectuelle » appartenant à des tiers qui pourraient faire obstacle aux libertés qui lui sont accordées par la présente licence.
Les éventuels « Droits de propriété intellectuelle » détenus par le « Concédant » sur l’ « Information » ne font pas obstacle aux libertés qui sont accordées par la présente licence. Lorsque le « Concédant » détient des « Droits de propriété intellectuelle » » sur l’ « Information », il les cède au « Réutilisateur » de façon non exclusive, à titre gracieux, pour le monde entier, pour toute la durée des « Droits de propriété intellectuelle », et le « Réutilisateur » peut en faire tout usage conformément aux libertés et aux conditions définies par la présente licence.
## Responsabilité
L’ «Information» est mise à disposition telle que produite ou reçue, sans autre garantie expresse ou tacite qui n’est pas prévue par la présente licence. L’absence de défauts ou d’erreurs éventuellement contenues dans l’ «Information», comme la fourniture continue de l’ « Information » n’est pas garantie par le «Concédant». Il ne peut être tenu pour responsable de toute perte, préjudice ou dommage de quelque sorte causé à des tiers du fait de la « Réutilisation ».
Le « Réutilisateur » est seul responsable de la « Réutilisation » de l’« Information ».
La « Réutilisation » ne doit pas induire en erreur des tiers quant au contenu de l’« Information », sa source et sa date de mise à jour.
## Droit applicable
La présente licence est régie par le droit français.
### Compatibilité de la présente licence
Elle a été conçue pour être compatible avec toute licence libre qui exige _a minima_ la mention de paternité. Elle est notamment compatible avec la version antérieure de la présente licence ainsi qu’avec les licences « Open Government Licence » (OGL) du Royaume-Uni, « Creative Commons Attribution » (CC-BY) de Creative Commons et « Open Data Commons Attribution » (ODC-BY) de l’Open Knowledge Foundation.
## Définitions
Sont considérés, au sens de la présente licence comme :
- Le « **Concédant** » : toute personne concédant un droit de « Réutilisation » sur l’« Information » dans les libertés et les conditions prévues par la présente licence.
- L’« **Information** » :
- toute information publique figurant dans des documents communiqués ou publiés par une administration mentionnée au premier alinéa de l’article L.300-2 du CRPA ;
- toute information mise à disposition par toute personne selon les termes et conditions de la présente licence.
- La « **Réutilisation** » : l’utilisation de l’« Information » à d’autres fins que celles pour lesquelles elle a été produite ou reçue.
- Le « **Réutilisateur** » : toute personne qui réutilise les « Informations » conformément aux conditions de la présente licence.
- Des « **Données à caractère personnel** » : toute information se rapportant à une personne physique identifiée ou identifiable, pouvant être identifiée directement ou indirectement. Leur « Réutilisation » est subordonnée au respect du cadre juridique en vigueur.
- Une « **Information dérivée** » : toute nouvelle donnée ou information créées directement à partir de l’« Information » ou à partir d’une combinaison de l’ « Information » et d’autres données ou informations non soumises à cette licence.
- Les « **Droits de propriété intellectuelle** » : tous droits identifiés comme tels par le Code de la propriété intellectuelle (droit d’auteur, droits voisins au droit d’auteur, droit sui generis des producteurs de bases de données).
## À propos de cette licence
La présente licence a vocation à être utilisée par les administrations pour la réutilisation de leurs informations publiques. Elle peut également être utilisée par toute personne souhaitant mettre à disposition de l’« Information » dans les conditions définies par la présente licence
La France est dotée d’un cadre juridique global visant à une diffusion spontanée par les administrations de leurs informations publiques afin d’en permettre la plus large réutilisation.
Le droit de la « Réutilisation » de l’« Information » des administrations est régi par le code des relations entre le public et l’administration (CRPA) et, le cas échéant, le code du patrimoine (livre II relatif aux archives).
Cette licence facilite la réutilisation libre et gratuite des informations publiques et figure parmi les licences qui peuvent être utilisées par l’administration en vertu du décret pris en application de l’article L.323-2 du CRPA.
Etalab est la mission chargée, sous l’autorité du Premier ministre, d’ouvrir le plus grand nombre de données publiques des administrations de l’État et de ses établissements publics. Elle a réalisé la Licence Ouverte pour faciliter la réutilisation libre et gratuite de ces informations publiques, telles que définies par l’article L321-1 du CRPA.
Cette licence est une version 2.0 de la Licence Ouverte.
Etalab se réserve la faculté de proposer de nouvelles versions de la Licence Ouverte. Cependant, les « Réutilisateurs » pourront continuer à réutiliser les informations disponibles sous cette licence s’ils le souhaitent.
Meet is a simple video and phone conferencing tool, powered by [LiveKit](https://livekit.io/).
Meet is built on top of [Django Rest
Framework](https://www.django-rest-framework.org/) and [Vite.js](https://vitejs.dev/).
## Getting started
### Prerequisite
#### Docker
Make sure you have a recent version of Docker and [Docker
Compose](https://docs.docker.com/compose/install) installed on your laptop:
```bash
$ docker -v
Docker version 20.10.2, build 2291f61
$ docker compose -v
docker compose version 1.27.4, build 40524192
```
> ⚠️ You may need to run the following commands with `sudo` but this can be
> avoided by assigning your user to the `docker` group.
#### LiveKit CLI
Install LiveKit CLI, which provides utilities for interacting with the LiveKit ecosystem (including the server, egress, and more), please follow the instructions available in the [official repository](https://github.com/livekit/livekit-cli).
### Project bootstrap
The easiest way to start working on the project is to use GNU Make:
```bash
$ make bootstrap FLUSH_ARGS='--no-input'
```
Then you can access to the project in development mode by going to http://localhost:3000.
You will be prompted to log in, the default credentials are:
```bash
username: meet
password: meet
```
---
This command builds the `app` container, installs dependencies, performs
database migrations and compile translations. It's a good idea to use this
command each time you are pulling code from the project repository to avoid
dependency-related or migration-related issues.
Your Docker services should now be up and running 🎉
[FIXME] Explain how to run the frontend project.
### Configure LiveKit CLI
For the optimal DX, create a default project named `meet` to use with `livekit-cli` commands:
```bash
$ livekit-cli project add
URL: http://localhost:7880
API Key: devkey
API Secret: secret
Give it a name for later reference: meet
? Make this project default?? [y/N] y
```
Thus, you won't need to pass the project API Key and API Secret for each command.
The application is deployed across staging, preprod, and production environments using Kubernetes (K8s).
Reproducing environment conditions locally is crucial for developing new features or debugging issues.
This is facilitated by [Tilt](https://tilt.dev/) ("Kubernetes for Prod, Tilt for Dev"). Tilt enables smart rebuilds and live updates for services running locally in Kubernetes. We defined our services in a Tiltfile located at `bin/Tiltfile`.
Powered by [LiveKit](https://livekit.io/), La Suite Meet offers Zoom-level performance with high-quality video and audio. No installation required—simply join calls directly from your browser. Check out LiveKit's impressive optimizations in their [blog post](https://blog.livekit.io/livekit-one-dot-zero/).
### Features
- Optimized for stability in large meetings (+100 p.)
- Support for multiple screen sharing streams
- Non-persistent, secure chat
- End-to-end encryption (coming soon)
- Meeting recording
- Meeting transcription & Summary (currently in beta)
- Telephony integration
- Secure participation with robust authentication and access control
- Customizable frontend style
- LiveKit Advances features including :
- speaker detection
- simulcast
- end-to-end optimizations
- selective subscription
- SVC codecs (VP9, AV1)
#### Getting Started
La Suite Meet is fully self-hostable and released under the MIT License, ensuring complete control and flexibility. It's simple to [get started](https://visio.numerique.gouv.fr/) or [request a demo](mailto:visio@numerique.gouv.fr).
Make sure you have installed:
- kubectl
- helm
- helmfile
- tilt
We’re continuously adding new features to enhance your experience, with the latest updates coming soon!
To build and start the Kubernetes cluster using Kind:
```shell
$ make build-k8s-cluster
```
Once the Kubernetes cluster is ready, start the application stack locally:
```shell
$ make start-tilt
```
These commands set up and run your application environment using Tilt for local Kubernetes development.
## Table of Contents
You can monitor Tilt's at `http://localhost:10350/`. After Tilt actions finish, you can access the app at `https://meet.127.0.0.1.nip.io/`.
- [Get started](#get-started)
- [Docs](#docs)
- [Self-host](#self-host)
- [Contributing](#contributing)
- [Philosophy](#philosophy)
- [Open source](#open-source)
#### Debugging frontend
Tilt deploys the `meet-dev` for the frontend by default, to benefit from Vite.js hot reloading while developing.
To troubleshoot production issues, please modify the Tiltfile, switch frontend's target to `frontend-production`:
## Get started
```yaml
...
## Docs
We're currently working on both technical and user documentation for La Suite Meet. In the meantime, many of the essential aspects are already well covered by the [LiveKit documentation](https://docs.livekit.io/home/) and their [self-hosting guide](https://docs.livekit.io/home/self-hosting/deployment/). Stay tuned for more updates!
## Self-host
### La Suite Meet is easy to install on your own servers
We use Kubernetes for our [production instance](https://visio.numerique.gouv.fr/) but also support Docker Compose. The community contributed a couple other methods (Nix, YunoHost etc.) check out the [docs](/docs/installation/README.md) to get detailed instructions and examples.
**Questions?** Open an issue on [GitHub](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md) or join our [Matrix community](https://matrix.to/#/#meet-official:matrix.org).
> [!NOTE]
> Some advanced features (ex: recording, transcription) lack detailed documentation. We're working hard to provide comprehensive guides soon.
#### Known instances
We hope to see many more, here is an incomplete list of public La Suite Meet instances. Feel free to make a PR to add ones that are not listed below🙏
| [visio.numerique.gouv.fr](https://visio.numerique.gouv.fr/) | DINUM | French public agents working for the central administration and the extended public sphere. ProConnect is required to login in or sign up|
| [visio.suite.anct.gouv.fr](https://visio.suite.anct.gouv.fr/) | ANCT | French public agents working for the territorial administration and the extended public sphere. ProConnect is required to login in or sign up|
| [visio.lasuite.coop](https://visio.lasuite.coop/) | lasuite.coop | Free and open demo to all. Content and accounts are reset after one month |
| [meet.demo.mosacloud.eu](https://meet.demo.mosacloud.eu/) | mosa.cloud | Demo instance of mosa.cloud, a dutch company providing services around La Suite apps. |
target='frontend-production', # Update this line when needed
live_update=[
sync('../src/frontend', '/home/frontend'),
]
)
...
```
## Contributing
This project is intended to be community-driven, so please, do not hesitate to
get in touch if you have any question related to our implementation or design
decisions.
We <3 contributions of any kind, big and small:
- Vote on features or get early access to beta functionality in our [roadmap](https://github.com/orgs/suitenumerique/projects/11/views/4)
- Open a PR (see our instructions on [developing La Suite Meet locally](https://github.com/suitenumerique/meet/blob/main/docs/developping_locally.md))
- Submit a [feature request](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=enhancement&template=Feature_request.md) or [bug report](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md)
## Philosophy
We’re relentlessly focused on building the best open-source video conferencing product—La Suite Meet. Growth comes from creating something people truly need, not just from chasing metrics.
Our users come first. We’re committed to making La Suite Meet as accessible and easy to use as proprietary solutions, ensuring it meets the highest standards.
Most of the heavy engineering is handled by the incredible LiveKit team, allowing us to focus on delivering a top-tier product. We follow extreme programming practices, favoring pair programming and quick, iterative releases. Challenge our tech and architecture—simplicity is always our top priority.
## Open-source
Gov 🇫🇷 supports open source! This project is available under [MIT license](https://github.com/suitenumerique/meet/blob/0cc2a7b7b4f4821e2c4d9d790efa739622bb6601/LICENSE).
All features we develop will always remain open-source, and we are committed to contributing back to the LiveKit community whenever feasible.
To learn more, don't hesitate to [reach out](mailto:visio@numerique.gouv.fr).
### Help us!
Come help us make La Suite Meet even better. We're growing fast and [would love some help](mailto:visio@numerique.gouv.fr).
We're using the awesome [LiveKit](https://livekit.io/) implementation. We're also thankful to the teams behind [Django Rest Framework](https://www.django-rest-framework.org/), [Vite.js](https://vite.dev/), and [React Aria](https://github.com/adobe/react-spectrum) — Thanks for your amazing work!
This project is tested with BrowserStack.
## License
This work is released under the MIT License (see [LICENSE](./LICENSE)).
Code in this repository is published under the MIT license by DINUM (Direction interministériel du numérique).
Documentation (in the docs/) directory is released under the [Etalab-2.0 license](https://spdx.org/licenses/etalab-2.0.html).
If you have any issue regarding security, please disclose the information responsibly submiting [this form](https://vdp.numerique.gouv.fr/p/Send-a-report?lang=en) and not by creating an issue on the repository. You can also email us at visio@numerique.gouv.fr
We appreciate your effort to make Visio more secure.
## Vulnerability disclosure policy
Working with security issues in an open source project can be challenging, as we are required to disclose potential problems that could be exploited by attackers. With this in mind, our security fix policy is as follows:
1. The Maintainers team will handle the fix as usual (Pull Request,
release).
2. In the release notes, we will include the identification numbers from the
GitHub Advisory Database (GHSA) and, if applicable, the Common Vulnerabilities
and Exposures (CVE) identifier for the vulnerability.
3. Once this grace period has passed, we will publish the vulnerability.
By adhering to this security policy, we aim to address security concerns
effectively and responsibly in our open source software project.
d="m 55.435527,103.08144 c -0.72898,0 -1.249045,-0.56007 -1.249045,-1.25349 0,-0.69342 0.502285,-1.25349 1.204595,-1.25349 0.41783,0 0.760095,0.20447 0.96901,0.50673 l 0.333375,-0.25781 c -0.28448,-0.38227 -0.742315,-0.64008 -1.302385,-0.64008 -0.973455,0 -1.63576,0.75565 -1.63576,1.64465 0,0.889 0.680085,1.64465 1.68021,1.64465 0.582295,0 1.05791,-0.24892 1.346835,-0.64008 v -1.21349 h -1.31572 v 0.36005 h 0.89789 v 0.70231 c -0.217805,0.24447 -0.54229,0.40005 -0.929005,0.40005 z m 3.569334,-2.89814 c -0.973455,0 -1.63576,0.75565 -1.63576,1.64465 0,0.889 0.662305,1.64465 1.63576,1.64465 0.96901,0 1.631315,-0.75565 1.631315,-1.64465 0,-0.889 -0.662305,-1.64465 -1.631315,-1.64465 z m 0,2.89814 c -0.70231,0 -1.204595,-0.56007 -1.204595,-1.25349 0,-0.69342 0.502285,-1.25349 1.204595,-1.25349 0.697865,0 1.20015,0.56007 1.20015,1.25349 0,0.69342 -0.502285,1.25349 -1.20015,1.25349 z m 4.276088,-0.84455 c 0,0.53784 -0.31115,0.84455 -0.786765,0.84455 -0.48006,0 -0.79121,-0.30671 -0.79121,-0.84455 v -1.96469 h -0.41783 v 1.93802 c 0,0.8001 0.48006,1.26238 1.20904,1.26238 0.72898,0 1.204595,-0.46228 1.204595,-1.26238 v -1.93802 h -0.41783 z m 0.942341,-1.96469 1.2446,3.1115 h 0.55118 l 1.2446,-3.1115 h -0.4445 l -1.07569,2.68922 -1.07569,-2.68922 z m 3.653795,3.1115 h 1.67132 v -0.3556 h -1.25349 v -1.05347 h 1.07569 v -0.35115 h -1.07569 v -0.99568 h 1.25349 v -0.3556 h -1.67132 z m 2.502533,0 h 0.41783 v -1.36462 h 0.40894 c 0.03111,0 0.06667,0 0.09779,-0.004 l 0.902335,1.36906 h 0.493395 l -1.00457,-1.44907 c 0.333375,-0.13335 0.52451,-0.41339 0.52451,-0.78677 0,-0.5334 -0.386715,-0.87566 -1.01346,-0.87566 h -0.82677 z m 0.84455,-2.7559 c 0.3556,0 0.564515,0.19558 0.564515,0.51117 0,0.33338 -0.208915,0.52451 -0.564515,0.52451 h -0.42672 v -1.03568 z m 2.004699,2.7559 h 0.41783 v -2.60033 l 1.76022,2.60033 h 0.546735 v -3.1115 h -0.41783 v 2.60032 l -1.76022,-2.60032 h -0.546735 z m 3.71158,0 h 1.67132 v -0.3556 h -1.25349 v -1.05347 h 1.07569 v -0.35115 h -1.07569 v -0.99568 h 1.25349 v -0.3556 h -1.67132 z m 2.502533,0 h 0.41783 v -2.55143 l 0.90678,1.48463 h 0.32004 l 0.90678,-1.48463 v 2.55143 h 0.41783 v -3.1115 h -0.5334 l -0.95123,1.56908 -0.95123,-1.56908 h -0.5334 z m 3.951605,0 h 1.67132 v -0.3556 h -1.25349 v -1.05347 h 1.07569 v -0.35115 h -1.07569 v -0.99568 h 1.25349 v -0.3556 h -1.67132 z m 2.502535,0 h 0.41783 v -2.60033 l 1.76022,2.60033 h 0.546735 v -3.1115 h -0.41783 v 2.60032 l -1.76022,-2.60032 H 85.89712 Z m 3.373758,-2.72923 h 1.03124 v 2.72923 h 0.41783 v -2.72923 h 1.03124 v -0.38227 h -2.48031 z"
Before setting up, let's review Visio's architecture.
Visio consists of four main components that run simultaneously:
- React frontend, built with Vite.js
- Django server
- LiveKit server
- FastAPI server (optional, required for AI beta features)
These components rely on a few key services:
- PostgreSQL for storing data (users, rooms, recordings)
- Redis for caching and inter-service communication
- MinIO for storing files (room recordings)
- Celery workers for meeting transcript (optional, required for AI beta features)
We provide two stack options for getting Visio up and running for development:
- Docker Compose stack (recommended for most users)
- Kubernetes stack powered by Tilt (Advanced)
We recommend starting with the **Docker Compose** option for simplicity. However, if you're comfortable with running Kubernetes locally, the advanced option mirrors the production environment and provides most of the tools required for development (e.g., hot reloading).
These instructions are for macOS or Ubuntu. For other distros, adjust as needed.
If any steps are outdated, please let us know!
---
We also provide **GNU make utilities**. To view all available Make rules, run:
```shellscript
$ make help
```
---
## Need Help?
If you need any assistance or have questions while getting started, feel free to reach out to @lebaudantoine anytime! Antoine is available to help you onboard and guide you through the process. Chat with him @antoine.lebaud:matrix.org, or from the [support hotline](https://go.crisp.chat/chat/embed/?website_id=58ea6697-8eba-4492-bc59-ad6562585041).
---
## Option 1: Developing with Docker
### Prerequisites
1. Ensure you have a recent version of **Docker** and **Docker Compose** installed:
```shellscript
$ docker -v
Docker version 20.10.2, build 2291f61
$ docker compose version
Docker Compose version v2.32.4
```
2. Install **LiveKit CLI** by following the instructions available in the [official repository](https://github.com/livekit/livekit-cli). After installation, verify that it's working:
```shellscript
$ lk --version
lk version 2.3.1
```
---
### Project Bootstrap
1. Bootstrap the project using the **Make** command. This will build the `app` container, install dependencies, run database migrations, and compile translations:
```shellscript
$ make bootstrap FLUSH_ARGS='--no-input'
```
2. Access the project:
- The frontend is available at [http://localhost:3000](http://localhost:3000) with the default credentials:
- username: meet
- password: meet
- The Django backend is available at [http://localhost:8071](http://localhost:8071)
---
## Developing
- To **stop** the application:
```shellscript
$ make stop
```
- To **restart** the application:
```shellscript
$ make run
```
- For **frontend development**, start all backend services without the frontend container:
```shellscript
$ make run-backend
```
Then:
```shellscript
$ make frontend-development-install
$ make run-frontend-development
```
Which is equivalent to these direct npm commands:
```shellscript
$ cd src/frontend
$ npm i
$ npm run dev
```
---
## Adding Content
You can bootstrap demo data with a single command:
```shellscript
$ make demo
```
---
## Option 2: Developing with Kubernetes
Visio is deployed across staging, preprod, and production environments using **Kubernetes (K8s)**. Reproducing the environment locally is crucial for developing new features or debugging.
This is facilitated by [Tilt](https://tilt.dev/), which provides Kubernetes-like development for local environments, enabling smart rebuilds and live updates.
### Getting Started
Make sure you have the following installed:
- kubectl
- helm
- helmfile
- tilt
To build and start the Kubernetes cluster using **Kind**:
```shellscript
$ make build-k8s-cluster
```
Once the Kubernetes cluster is ready, start the application stack locally:
```shellscript
$ make start-tilt-keycloak
```
Monitor Tilt’s progress at [http://localhost:10350/](http://localhost:10350/). After Tilt actions finish, you can access the app at [https://meet.127.0.0.1.nip.io/](https://meet.127.0.0.1.nip.io/).
LiveKit offers Universal Egress, designed to provide universal exports of LiveKit sessions or tracks to a file or stream data.
It is kept in a separate system to keep the load off the [Single Forwarding Unit (SFU)](https://docs.livekit.io/reference/internals/livekit-sfu/) and avoid impacting real-time audio or video performance/quality.
## Getting started
### Prerequisite
1.**Verify Services**: Ensure the LiveKit server and Egress service are both up and running.
2.**Install CLI**: Confirm that the LiveKit CLI utility is installed on your system.
3.**Set Permissions**: Since the Egress service does not run as the root user, you need to grant write permissions to all users for the output directory. Update the permissions of the `docker/livekit/out` folder before starting the docker-compose stack:
```bash
$ chmod o+w ./docker/livekit/out
```
### Make a recording
LiveKit provides examples for creating Egress requests, which you can find [here](https://github.com/livekit/livekit-cli/tree/main/cmd/livekit-cli/examples). One of these examples has been added to the repository under `docker/livekit/egress-example`.
Follow these steps to start an Egress request:
1.**Create a Room**: Create a room either through the frontend or using the `livekit-cli` command.
2.**Retrieve Room Name**: Get the room's name (e.g., the UUID4 in the URL from the frontend).
3.**Update Configuration**: Edit the `docker/livekit/egress-example/room-composite-file.json` file with your room's name.
4.**Start Egress Request**: Initiate a new Egress request.
La Suite Meet supports **OIDC authentication** using the Authorization Code Flow.
Authentication relies on [django-lasuite](https://github.com/suitenumerique/django-lasuite) for OIDC integration, token validation, and user management.
| OIDC_CREATE_USER | Automatically create a local user if none exists | `true` |
| **Security & Verification** | | |
| OIDC_VERIFY_SSL | Verify SSL certificates when contacting the OIDC provider | `true` |
| OIDC_USE_NONCE | Use `nonce` to prevent replay attacks | `true` |
| OIDC_STORE_ID_TOKEN | Store the ID token returned by the OIDC provider (useful for backend validation) | `true` |
| OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION | Fallback to identifying users by email if `sub` claim does not match. Enable only if emails are unique. | `false` |
| **Endpoints** | | |
| OIDC_OP_JWKS_ENDPOINT | URL to retrieve JSON Web Key Sets (for token verification) | — |
| OIDC_OP_AUTHORIZATION_ENDPOINT | URL for authorization requests | — |
| OIDC_OP_TOKEN_ENDPOINT | URL to exchange authorization code for tokens | — |
| OIDC_OP_USER_ENDPOINT | URL to fetch user information | — |
| OIDC_OP_USER_ENDPOINT_FORMAT | Format of user endpoint response. Options: `AUTO` (detect automatically), `JWT`, or `JSON` | `AUTO` |
| OIDC_OP_LOGOUT_ENDPOINT | URL for logout requests | — |
| **User Info Mapping** | | |
| OIDC_USERINFO_FULLNAME_FIELDS | List of OIDC claims used to build user’s full name | `["given_name", "usual_name"]` |
| OIDC_USERINFO_SHORTNAME_FIELD | OIDC claim used for the user’s short name | `given_name` |
| OIDC_USERINFO_ESSENTIAL_CLAIMS | List of essential claims required from the provider | `[]` |
| **Redirects & Scopes** | | |
| OIDC_REDIRECT_REQUIRE_HTTPS | Require HTTPS for OIDC redirect URIs (**recommended in production**) | `false` |
| OIDC_PKCE_CODE_VERIFIER_SIZE | Length of the random string used as PKCE code verifier (43–128 characters) | `64` |
| **Other** | | |
| FRONTEND_IS_SILENT_LOGIN_ENABLED | Silent login allows La Suite Meet to authenticate users automatically without showing a login prompt, providing a seamless experience when an active session already exists with the OIDC provider. It works by replaying the authentication request with prompt=none: if the user has a valid session, login succeeds silently; otherwise, it fails gracefully and redirects the user to the initial page. Silent login is optional and enabled by default in standard deployments. The app retries silent login after any 401 response, with at least a 30-second interval between attempts (not configurable via environment variables). Controlled by the backend parameter. /!\ Your OIDC provider must support `prompt=none`. | `false` |
## Sessions
* After login, users receive a **Django session cookie** to maintain authentication across requests.
These features are currently under active development and are not yet ready for official documentation. Comprehensive documentation will be provided as soon as possible.
An initial integration with OpenExchange is already available and will be documented shortly.
La Suite Meet offers a room recording feature that is currently in beta, with ongoing improvements planned.
The feature allows users to record their room sessions. When a recording is complete, the room owner receives a notification with a link to download the recorded file. Recordings are automatically deleted after `RECORDING_EXPIRATION_DAYS`.
It uses LiveKit Egress to record room sessions. For reference, see the [LiveKit Egress repository](https://github.com/livekit/egress) and the [official documentation](https://docs.livekit.io/home/egress/overview/).
**Current Limitations**:
* Users cannot record and transcribe simultaneously. ([Issue #527](https://github.com/suitenumerique/meet/issues/527)
is on our backlog)
* Recording layout cannot be configured from the frontend. By default, the egress captures the active speaker and any shared screens. (not yet planned)
* Shareable links with an embedded video player are not yet supported. (not yet planned)
> [!NOTE]
> Questions? Open an issue on [GitHub](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md) or join our [Matrix community](https://matrix.to/#/#meet-official:matrix.org).
## Special requirements
To use the room recording feature, the following components are required:
- A running [LiveKit Egress](https://github.com/livekit/egress) server capable of handling room composite recordings.
- A S3-compatible object storage that supports webhook events to notify the backend when recordings are uploaded.
- An email service to notify room owners when a recording is available for download.
- Webhook events configured between LiveKit Server and the backend.
> [!CAUTION]
> Minio supports lifecycle events; other providers may not work out of the box. There is currently a dependency on Minio, which is planned to be refactored in the future.
> [!NOTE]
> Celery isn’t in use for these async tasks yet. It’s something we’d like to add, but it’s not planned at this stage.
## How It Works
```mermaid
sequenceDiagram
participant User
participant Frontend as Frontend (React)
participant Backend as Django Backend
participant LiveKit as LiveKit API
participant Egress as LiveKit Egress
participant Storage as Object Storage
participant Room as LiveKit Room
participant Email as Email Service
User->>Frontend: Click start recording button
Frontend->>Backend: POST /api/v1.0/rooms/{id}/start-recording/
Backend->>LiveKit: Create egress request
LiveKit->>Egress: Start room composite egress
Egress->>Room: Join room as recording participant
Note over Egress,Room: Egress joins room to capture audio/video
LiveKit-->>Backend: Return egress_id
Backend->>Backend: Update Recording with worker_id
Backend-->>Frontend: HTTP 201 - Recording started
Frontend->>Frontend: Update recording status
Frontend->>Frontend: Notify other participants
Note over Frontend: Via LiveKit data channel
Note over Egress,Room: Recording in progress...
User->>Frontend: Click stop recording button
Frontend->>Backend: POST /api/v1.0/rooms/{id}/stop-recording/
Backend->>LiveKit: Stop egress request
LiveKit->>Egress: Stop recording
Egress->>Storage: Upload recorded file
Storage->>Backend: Storage event notification
Backend->>Backend: Update Recording status to SAVED
Backend->>Email: Send notification to room owner
Backend-->>Frontend: HTTP 200 - Recording stopped
Frontend->>Frontend: Update UI and notify participants
Email->>User: Send email with recording link
User->>Frontend: Navigate to /recording/{id} to download file
| **RECORDING_ENABLE** | Boolean | `False` | Enable or disable the room recording feature. |
| **RECORDING_OUTPUT_FOLDER** | String | `"recordings"` | Folder/prefix where recordings are stored in the object storage. |
| **RECORDING_WORKER_CLASSES** | Dict | `{ "screen_recording": "core.recording.worker.services.VideoCompositeEgressService", "transcript": "core.recording.worker.services.AudioCompositeEgressService" }` | Maps recording types to their worker service classes. |
| **RECORDING_EVENT_PARSER_CLASS** | String | `"core.recording.event.parsers.MinioParser"` | Class responsible for parsing storage events and updating the backend. |
| **RECORDING_STORAGE_EVENT_ENABLE** | Boolean | `False` | Enable handling of storage events (must configure webhook in storage). |
| **RECORDING_STORAGE_EVENT_TOKEN** | Secret/File | `None` | Token used to authenticate storage webhook requests, if `RECORDING_ENABLE_STORAGE_EVENT_AUTH` is enabled. |
| **RECORDING_EXPIRATION_DAYS** | Integer | `None` | Number of days before recordings expire. Should match bucket lifecycle policy. Set to `None` for no expiration. |
| **RECORDING_MAX_DURATION** | Integer | `None` | Maximum duration of a recording in milliseconds. Must be synced with the LiveKit Egress configuration. Set to None for unlimited duration. When the maximum duration is reached, the recording is automatically stopped and saved, and the user is prompted in the frontend with an alert message. |
### Manual Storage Webhook
Storage events must be configured manually; the Kubernetes chart does not do this automatically.
1. Configure your S3 bucket to send file creation events to the backend webhook.
2. Enable events and token in settings:
```python
RECORDING_STORAGE_EVENT_ENABLE=True
RECORDING_ENABLE_STORAGE_EVENT_AUTH=True
RECORDING_STORAGE_EVENT_TOKEN=<token>
```
> [!NOTE]
> Questions? Open an issue on [GitHub](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md) or join our [Matrix community](https://matrix.to/#/#meet-official:matrix.org).
## LiveKit Egress
La Suite Meet uses LiveKit Egress to record room sessions. For reference, see the [LiveKit Egress repository](https://github.com/livekit/egress) and the [official documentation](https://docs.livekit.io/home/egress/overview/).
Currently, only `RoomCompositeEgress` is supported. This mode combines all video and audio tracks from the room into a single recording.
To monitor egress workers and inspect recording status, it is recommended to install `livekit-cli`. For example, you can list active egress sessions using the following command:
Signaling is essential for LiveKit’s real-time communication. It enables peers to discover each other, exchange session descriptions, and negotiate network paths for audio and video streams.
## How Signaling Works
LiveKit signaling relies on a WebSocket connection between the client and the LiveKit API server. This WebSocket is required for all signaling messages, including session descriptions, ICE candidates, and connection state updates.
We do not cover internal signaling behavior. For full reference, see the [LiveKit client protocol](https://docs.livekit.io/reference/internals/client-protocol/).
> [!IMPORTANT]
> The WebSocket is the backbone of LiveKit signaling. All signaling messages rely on it, and without it, ICE candidate exchange and peer connection setup cannot occur. If the WebSocket connection is lost, the client automatically attempts to resume the RTC session once connectivity is restored.
| `LIVEKIT_FORCE_WSS_PROTOCOL` | Boolean | `True` | Forces the WebSocket URL to use `wss://`. Required for legacy browsers (Firefox <124, Chrome <125, Edge <125) where HTTPS URLs in `WebSocket()` may fail. |
| `LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND` | Boolean | `True` | Workaround for Firefox clients behind proxies that fail to establish WebSocket connections. Pre-establishes a dummy connection to “prime” the WebSocket. |
> [!NOTE]
> Questions? Open an issue on [GitHub](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md) or join our [Matrix community](https://matrix.to/#/#meet-official:matrix.org).
This feature is currently under development and not yet ready for production use. Documentation and detailed instructions will be provided once the feature is stable and officially released.
This feature is currently under development and not yet ready for production use. Documentation and detailed instructions will be provided once the feature is stable and officially released.
Enable participants to join a video conference via phone, allowing them to participate in the room even when their internet connection is poor or unavailable.
**Current Limitations**:
* Supports only a single SIP trunk provider per instance.
* A participant joining over the phone cannot enter the room until the first WebRTC participant has connected.
## Special requirements
To use the telephony feature, the following components are required:
* A running [LiveKit SIP server](https://github.com/livekit/sip) ([documentation](https://docs.livekit.io/home/self-hosting/sip-server/)) to handle SIP participants and connect them to room sessions.
* A SIP trunk to route incoming and outgoing phone calls.
* Webhook events configured between the LiveKit server and the backend.
| ROOM_TELEPHONY_ENABLED | Boolean | False | Enable or disable telephony (phone call) support for rooms. |
| ROOM_TELEPHONY_PIN_LENGTH | Positive Integer | 10 | Length of the PIN code participants must enter to join a call. |
| ROOM_TELEPHONY_PIN_MAX_RETRIES | Positive Integer | 5 | Maximum number of attempts a participant can make when entering the PIN. |
| ROOM_TELEPHONY_PHONE_NUMBER | String | None | The phone number associated with the room for incoming calls. Required to route calls via the telephony system. |
| ROOM_TELEPHONY_DEFAULT_COUNTRY | String | "US" | Default country code for phone numbers, used for parsing and formatting phone numbers. |
### SIP Trunk Authentication
You may need to configure authentication between LiveKit SIP and your SIP trunk provider to enable participants to join via phone.
Please refer to [the official documentation](https://docs.livekit.io/sip/quickstarts/configuring-sip-trunk/).
> [!NOTE]
> Questions? Open an issue on [GitHub](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md) or join our [Matrix community](https://matrix.to/#/#meet-official:matrix.org).
### Language Customization for Audio Prompts
You may need to configure the default LiveKit voice to match your locale. By default, all LiveKit audio instructions are in English.
To customize the prompts, mount the appropriate audio files as a volume in your deployment. The audio resources are available here: [LiveKit SIP audio files](https://github.com/livekit/sip/tree/main/res).
## Documentation
For detailed information on integrating and configuring SIP with LiveKit, refer to the official LiveKit SIP documentation: [LiveKit SIP Documentation](https://docs.livekit.io/sip/). This guide covers SIP server setup, trunk configuration, dispatch rules, etc.
La Suite Meet provides a room transcription capability, currently available in beta. This feature is under active development, with ongoing enhancements planned.
The transcription feature enables users to record room sessions. Upon completion of a recording, the room owner receives a notification containing a link to LaSuite Docs, where the transcribed meeting content can be accessed.
> [!NOTE]
> Audio recordings are automatically deleted after the configured `RECORDING_EXPIRATION_DAYS` period.
For configuration and setup details of the recording functionality, refer to the [Recording feature documentation](https://github.com/suitenumerique/meet/blob/main/docs/features/recording.md).
This page only describes the supplementary tools required for audio processing.
Example of a transcript :
```
**SPEAKER_00**: Hello everyone!
**SPEAKER_01**: Yes, it works.
```
### Current Limitations
* Participant identification is not yet implemented; participants are labeled generically (e.g., `PARTICIPANT_1`).
* Transcription backend relies on [WhisperX](https://github.com/m-bain/whisperX), which does not provide an OpenAI-compatible API.
> [!NOTE]
> Questions? Open an issue on [GitHub](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md) or join our [Matrix community](https://matrix.to/#/#meet-official:matrix.org).
## Special requirements
To enable the transcription feature, the following components must be in place:
* Recording feature components: All dependencies and configurations required for the [recording feature](https://github.com/suitenumerique/meet/blob/main/docs/features/recording.md).
* LaSuite Docs instance: A running [LaSuite Docs](https://github.com/suitenumerique/docs) capable of handling requests to the `/create-for-owner` endpoint.
* WhisperX API: A running WhisperX service. An open-source implementation combining WhisperX and FastAPI is available [here](https://github.com/suitenumerique/meet-whisperx).
* Deployment of the [summary service](https://hub.docker.com/r/lasuite/meet-summary), a Celery worker, and a Redis instance.
## How It Works
```mermaid
sequenceDiagram
participant Backend as Backend API
participant Summary as Summary Service
participant Celery as Celery Workers (transcribe-queue)
participant MinIO as MinIO (Object Storage)
participant STT as WhisperX API
participant Docs as LaSuite Docs
Backend->>Summary: POST /api/v1/tasks/ (bearer token, payload)
Note right of Backend: Payload contains 7 params: owner_id, filename, email, sub, room, recording_date, recording_time
| app_name | String | `"app"` | Name of the application/service. |
| app_api_v1_str | String | `"/api/v1"` | Base path for the API endpoints. |
| app_api_token | Secret | — | API token for authenticating requests. |
| recording_max_duration | Integer | `None` | Maximum duration of audio recordings in milliseconds. Set to `None` for unlimited. Audio recordings longer than the configured limit will be ignored and not processed. |
If you want to install La Suite Meet you've come to the right place.
Here are a bunch of resources to help you install the project.
## Kubernetes
La Suite Meet maintainers use only the Kubernetes deployment method in production, so advanced support is available exclusively for this setup. Please follow the instructions provided [here](/docs/installation/kubernetes.md).
## Docker Compose
We understand that not everyone has a Kubernetes cluster available.
We also provide [Docker images](https://hub.docker.com/u/lasuite?page=1&search=meet) that can be deployed using Compose.
> [!WARNING]
> Under construction: A PR is in progress to support deploying La Suite Meet via Docker Compose.
## Other ways to install La Suite Meet
Community members have contributed alternative ways to install La Suite Meet 🙏. While maintainers may not provide direct support, we help keep these instructions up to date, and you can reach out to contributors or the community for assistance.
Here is the list of other methods in alphabetical order:
This document is a step-by-step guide that describes how to install LaSuite Meet on a k8s cluster without AI features.
## Prerequisites for a kubernetes setup
- k8s cluster with an nginx-ingress controller
- an OIDC provider (if you don't have one, we will provide an example)
- a LiveKit server (if you don't have one, we will provide an example)
- a PostgreSQL server (if you don't have one, we will provide an example)
- a Memcached server (if you don't have one, we will provide an example)
### Test cluster
If you do not have a kubernetes test cluster, you can install everything on a local kind cluster. In this case, the simplest way is to use our script located in this repo under **bin/start-kind.sh**.
IMPORTANT: The kind method will only deploy meet as a local instance(127.0.0.1) that can only be accessed from the device where it has been deployed.
To be able to use the script, you will need to install the following components:
In order to initiate the local kind installation via **start-kind.sh** do the following:
1) Make sure administrator/root user context is able to execute mkcert, docker, kind etc. commands or the script might fail
2) Download the script to the device where the above components are installed
3) Make the script executable
4) Run the script with proper permissions (administrator/sudo etc.)
The output of the script will resemble the below example:
```
$ ./bin/start-kind.sh
0. Create ca
The local CA is already installed in the system trust store! 👍
The local CA is already installed in the Firefox and/or Chrome/Chromium trust store! 👍
Created a new certificate valid for the following names 📜
- "127.0.0.1.nip.io"
- "*.127.0.0.1.nip.io"
Reminder: X.509 wildcards only go one level deep, so this won't match a.b.127.0.0.1.nip.io ℹ️
The certificate is at "./127.0.0.1.nip.io+1.pem" and the key at "./127.0.0.1.nip.io+1-key.pem" ✅
It will expire on 23 March 2027 🗓
1. Create registry container unless it already exists
2. Create kind cluster with containerd registry config dir enabled
Creating cluster "visio" ...
✓ Ensuring node image (kindest/node:v1.27.3) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-visio"
You can now use your cluster with:
kubectl cluster-info --context kind-visio
Thanks for using kind! 😊
3. Add the registry config to the nodes
4. Connect the registry to the cluster network if not already connected
5. Document the local registry
configmap/local-registry-hosting created
Warning: resource configmaps/coredns is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
configmap/coredns configured
deployment.apps/coredns restarted
6. Install ingress-nginx
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
When your k8s cluster is ready, you can start the deployment. This cluster is special because it uses the \*.127.0.0.1.nip.io domain and mkcert certificates to have full HTTPS support and easy domain name management.
Please remember that \*.127.0.0.1.nip.io will always resolve to 127.0.0.1, except in the k8s cluster where we configure CoreDNS to answer with the ingress-nginx service IP.
## Preparation of components
### What will you use to authenticate your users ?
LaSuite Meet uses OIDC, so if you already have an OIDC provider, obtain the necessary information to use it. In the next step, we will see how to configure Django (and thus LaSuite Meet) to use it. If you do not have a provider, we will show you how to deploy a local Keycloak instance (this is not a production deployment, just a demo).
If you haven't run the script **bin/start-kind.sh**, you'll need to manually create the namespace by running the following command:
```
$ kubectl create namespace meet
```
If you have already run the script, you can skip this step and proceed to the next instruction. NOTE: Before you proceed, and is using the kind method, make sure you download this repo examples/ directory and its contents to the location where you will be executing the helm command. Helm will look for "examples/<name>values.yaml" from based on the path it is being executed.
In your OIDC provider, set LaSuite Meet's redirect URI to `https://.../api/v1.0/callback/` where `...` should be replaced with the domain name LaSuite Meet is hosted on.
From here the important information you will need are :
You can find these values in **examples/keycloak.values.yaml**
### Find livekit server connexion values
LaSuite Meet use livekit for streaming part so if you have a livekit provider, obtain the necessary information to use it. If you do not have a provider, you can install a livekit testing environment as follows:
Livekit need a redis (and meet too) so we will start by deploying a redis :
LaSuite Meet uses a postgresql db as backend so if you have a provider, obtain the necessary information to use it. If you do not have, you can install a postgresql testing environment as follows:
From here important information you will need are :
```
DB_HOST: postgres-postgresql
DB_NAME: meet
DB_USER: dinum
DB_PASSWORD: pass
DB_PORT: 5432
```
## Deployment
Now you are ready to deploy LaSuite Meet without AI. AI required more dependencies (Openai-compliant API, LiveKit Egress, Cold storage and a docs deployment to push resumes). To deploy meet you need to provide all previous information to the helm chart.
| CSRF_TRUSTED_ORIGINS | CSRF trusted origins list | [] |
| FRONTEND_CUSTOM_CSS_URL | URL of an additional CSS file to load in the frontend app. If set, a `<link>` tag with this URL as href is added to the `<head>` of the frontend app | |
| FRONTEND_ANALYTICS | Analytics information | {} |
| FRONTEND_SUPPORT | Crisp frontend support configuration, also you can pass help articles, with `help_article_transcript`, `help_article_recording`, `help_article_more_tools` | {} |
| FRONTEND_TRANSCRIPT | Frontend transcription configuration, you can pass a beta form, with `form_beta_users` | {} |
| FRONTEND_MANIFEST_LINK | Link to the "Learn more" button on the homepage | {} |
| OIDC_USE_PKCE | Enable the use of PKCE (Proof Key for Code Exchange) during the OAuth 2.0 authorization code flow. Recommended for enhanced security. | False |
| OIDC_PKCE_CODE_CHALLENGE_METHOD | Method used to generate the PKCE code challenge. Common values include S256 and plain. Refer to the mozilla-django-oidc documentation for supported options. | S256 |
| OIDC_PKCE_CODE_VERIFIER_SIZE | Length of the random string used as the PKCE code verifier. Must be an integer between 43 and 128, inclusive. | 64 |
| LOGIN_REDIRECT_URL | Login redirect URL | |
| LOGIN_REDIRECT_URL_FAILURE | Login redirect URL for failure | |
| LOGOUT_REDIRECT_URL | URL to redirect to on logout | |
| ALLOW_LOGOUT_GET_METHOD | Allow logout through GET method | true |
External API for room management with application-delegated authentication.
#### Authentication Flow
1. Exchange application credentials for a JWT token via `/external-api/v1.0/applications/token`.
2. Use the JWT token in the `Authorization: Bearer <token>` header for all subsequent requests.
3. Tokens are scoped and allow applications to act on behalf of specific users.
#### Scopes
* `rooms:list` – List rooms accessible to the delegated user.
* `rooms:retrieve` – Retrieve details of a specific room.
* `rooms:create` – Create new rooms.
* `rooms:update` – **Coming soon** Update existing rooms, e.g., add attendees to a room.
* `rooms:delete` – **Coming soon** Delete rooms generated by the application.
#### Upcoming Features
* **Create rooms for unknown users from the web app:** Support for generating rooms for users who are not yet registered in the system.
* **Add attendees to a room:** You will be able to update a room to include a list of attendees, allowing them to bypass the lobby system automatically.
* **Delete application-generated rooms:** Rooms created via the application can be deleted when no longer needed.
Whenever we are cooking a new release (e.g. `4.18.1`) we should follow a standard procedure described below:
1. Create a new branch named: `release/4.18.1`.
2. Bump the release number for backend project, frontend projects, and Helm files:
- for backend, update the version number by hand in `pyproject.toml`,
- for each frontend projects (`src/frontend`, `src/mail`), run `npm version 4.18.1` in their directory. This will update both their `package.json` and `package-lock.json` for you,
- for Helm, update Docker image tag in files located at `src/helm/env.d` for both `preprod` and `production` environments:
```yaml
image:
repository: lasuite/meet-backend
pullPolicy: Always
tag: "v4.18.1" # Replace with your new version number, without forgetting the "v" prefix
...
frontend:
image:
repository: lasuite/meet-frontend
pullPolicy: Always
tag: "v4.18.1" # Replace with your new version number, without forgetting the "v" prefix
```
The new images don't exist _yet_: they will be created automatically later in the process.
3. ~~Update the project's `Changelog` following the [keepachangelog](https://keepachangelog.com/en/0.3.0/) recommendations~~ _we don't keep a changelog yet for now as the project is still in its infancy. Soon™!_
4. Commit your changes with the following format: the 🔖 release emoji, the type of release (patch/minor/patch) and the release version:
```text
🔖(minor) bump release to 4.18.0
```
5. Open a pull request, wait for an approval from your peers and merge it.
6. Checkout and pull changes from the `main` branch to ensure you have the latest updates.
7. Tag and push your commit:
```bash
git tag v4.18.1 && git push origin --tags
```
Doing this triggers the CI and tells it to build the new Docker image versions that you targeted earlier in the Helm files.
8. Ensure the new [backend](https://hub.docker.com/r/lasuite/meet-frontend/tags) and [frontend](https://hub.docker.com/r/lasuite/meet-frontend/tags) image tags are on Docker Hub.
9. The release is now done!
# Deploying
> [!TIP]
> The `staging` platform is deployed automatically with every update of the `main` branch.
Making a new release doesn't publish it automatically in production.
Deployment is done by ArgoCD. ArgoCD checks for the `production` tag and automatically deploys the production platform with the targeted commit.
To publish, we mark the commit we want with the `production` tag. ArgoCD is then notified that the tag has changed. It then deploys the Docker image tags specified in the Helm files of the targeted commit.
- **Runtime Theming**. You can load a custom CSS file to apply any CSS you want. You can change all design-system tokens through CSS variables: colors, fonts, spacing multipliers, and more.
- **Build-time Theming**. Some additional things, like the app name appearing in the browser tab, can be customized through environment variables that are applied at build-time.
## Runtime Theming
### How to Use
To use this feature, simply set the `FRONTEND_CSS_URL` environment variable to the URL of your custom CSS file. For example:
> If you serve your CSS file on the same domain as LaSuite Meet, paths are supported, i.e. `FRONTEND_CSS_URL=/custom/style.css` will load `https://your-domain.com/custom/style.css`.
Setting this variable makes the app load your CSS at runtime, adding a `<link>` to `<head>` so you can override CSS variables and customize the frontend without rebuilding.
This feature lets you customize the app’s look with any CSS, giving full flexibility and allowing changes to take effect instantly at runtime without touching the code.
### Example Use Case
Let's say you want to change the font of our application to a custom font. You can create a custom CSS file with the following contents:
Then, set the `FRONTEND_CSS_URL` environment variable to the URL of your custom CSS file. Once you've done this, our application will load your custom CSS file and apply the styles, changing the default font to the one you specified.
> [!IMPORTANT]
> You can override any CSS token—semantic or palette. See [panda.config.ts](../src/frontend/panda.config.ts) for all defined semantic tokens.
> The app does **not provide separate light/dark themes**: outside a meeting it defaults to light, and in a room it switches to dark.
### Key Semantic Tokens
These control the main visual aspects of the interface:
The footer cannot be customized yet. This is a work in progress, and we welcome contributions — feel free to open a pull request if you’d like to help add this feature.
You can enable the official French government footer by setting the environment variable `FRONTEND_USE_FRENCH_GOV_FOOTER` to true. This option is disabled (false) by default.
field=models.CharField(choices="(('en-us', 'English'), ('fr-fr', 'French'), ('nl-nl', 'Dutch'))",default='en-us',help_text='The language in which the user wants to see the interface.',max_length=10,verbose_name='language'),
field=models.CharField(blank=True,help_text='Unique n-digit code that identifies this room in telephony mode.',max_length=None,null=True,unique=True,verbose_name='Room PIN code'),
('id',models.UUIDField(default=uuid.uuid4,editable=False,help_text='primary key for the record as UUID',primary_key=True,serialize=False,verbose_name='id')),
('created_at',models.DateTimeField(auto_now_add=True,help_text='date and time at which a record was created',verbose_name='created on')),
('updated_at',models.DateTimeField(auto_now=True,help_text='date and time at which a record was last updated',verbose_name='updated on')),
('name',models.CharField(help_text='Descriptive name for this application.',max_length=255,verbose_name='Application name')),
('client_secret',core.fields.SecretField(blank=True,default=core.utils.generate_client_secret,help_text='Hashed on Save. Copy it now if this is a new secret.',max_length=255)),
('id',models.UUIDField(default=uuid.uuid4,editable=False,help_text='primary key for the record as UUID',primary_key=True,serialize=False,verbose_name='id')),
('created_at',models.DateTimeField(auto_now_add=True,help_text='date and time at which a record was created',verbose_name='created on')),
('updated_at',models.DateTimeField(auto_now=True,help_text='date and time at which a record was last updated',verbose_name='updated on')),
('domain',models.CharField(help_text='Email domain this application can act on behalf of.',max_length=253,validators=[django.core.validators.DomainNameValidator(accept_idna=False,message='Enter a valid domain')],verbose_name='Domain')),
"""Enum for file extensions used in recordings."""
OGG="ogg"
MP4="mp4"
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.