Compare commits

...

1362 Commits

Author SHA1 Message Date
lebaudantoine 1306f0bcfe (backend) expose is_active field for Application in Django admin
Add minimal admin support to allow administrators to mark an
application account as inactive if it becomes rogue or compromised.

This capability was missing when the application concept was
initially introduced in the backend.
2026-03-12 13:27:08 +01:00
lebaudantoine ca4494c09e ♻️(backend) align Application model field with is_active convention
Most models in the project use `is_active` rather than `active`.
The Application model was not aligned with this convention.

Rename the field and add a migration to standardize the naming.
Update related tests accordingly.

This change should not introduce breaking changes for external
applications.
2026-03-12 13:26:37 +01:00
lebaudantoine f57db0acc8 ♻️(backend) refactor uploaded file's key format
Remove the user-provided filename while preserving the extension,
and switch to the format `uuid.extension`.

This is more natural than the previous `uuid/.extension` format
and avoids confusion.

Update related tests accordingly.
2026-03-12 10:39:59 +01:00
Florent Chehab 342f992556 🔨(python-env) migrate meet main app to UV
Migrate main meet app to use UV for dependancy management.
Also optimized the backend image build sequence for faster rebuilds
when dependencies don't change.
Also removed compiled django translations files are they are done in the build
process now.

Changes inspired by drive repo.
2026-03-12 10:25:35 +01:00
lebaudantoine d0cf3974ad 🚸(frontend) allow downloading recordings with "failed to stop" status
When support manually marks a recording as "failed to stop," enable
users to download the recording from the frontend.

This ensures users can recover their recordings even if the
automatic stop process fails.
2026-03-11 19:41:45 +01:00
lebaudantoine 0f3eb35c83 🩹(backend) add Django admin action to update recording status manually
Making the status read-only improved security and enforced least
privilege, but in production some recordings could not be properly
stopped, leaving them in an active state.

Introduce an admin action to allow support staff to mark recordings
as "failed to stop" or update their status when necessary.
2026-03-11 19:41:45 +01:00
lebaudantoine d15fb37932 📝(doc) fix changelog formatting
Wrap lines that were excessively long to improve readability.
2026-03-11 19:19:00 +01:00
lebaudantoine 051f33bb1e (backend) add tests for request-entry throttling in the lobby system
Cover throttling behavior for both authenticated users and
anonymous participants identified via the lobby cookie.
2026-03-11 18:07:39 +01:00
lebaudantoine 566eacc8fe (backend) add authenticated user rate throttling on request-entry
Throttle the request-entry endpoint for authenticated users also
to guard against accidental hammering from buggy clients.

Authenticated users are throttled via RequestEntryUserRateThrottle.
Anonymous users are throttled using the lobby participant cookie
through RequestEntryAnonRateThrottle.
2026-03-11 18:07:39 +01:00
lebaudantoine d19023a1ba 🐛(backend) refactor lobby throttling to use participant id instead of IP
use the lobby participant cookie ID as the throttle cache key
rather than the client IP address.

This avoids penalising multiple users behind the same NAT or proxy
and aligns throttling with how LobbyService identifies participants.

This bug was spotted in production where users from ministries behind
NAT was blocked by throttling while using visio.

If no cookie is present yet, skip throttling for the request. The
cookie will be set on the first response and throttling will apply
from subsequent requests.

This throttle is intended to protect against accidental hammering
from buggy clients, not as a security control against DoS attacks.

This is not a security measure, we should use a WAF.
2026-03-11 18:07:39 +01:00
lebaudantoine a6e36f02a7 🌐(frontend) remove references to ProConnect from the login hint
ProConnect (DINUM SSO) should not be mentioned in this context.
Clean up the login hint to avoid confusion.
2026-03-11 17:06:07 +01:00
lebaudantoine c3fd1a89ef 🩹(backend) add page_size to pagination for room endpoints
Align room endpoints with the pagination behavior used across
other API endpoints and resolve issue #1055.
2026-03-11 16:27:02 +01:00
ColorfulRhino 8b1ff536b3 🌐(frontend) improve German translation
Enhancements to the German localization include:

- Refine phrases to sound more natural
- Ensure consistency in words usage
- Adapt phrases to be inclusive and gender-neutral
- Standardize to the "du" form of address, aligning with modern
  practices and other open-source projects like GitLab and the Android
  Open Source Project
2026-03-10 22:56:25 +01:00
Hadrien Blanc 6b08b8da1b 📝 Fix documentation and comment typos 2026-03-10 22:56:08 +01:00
lebaudantoine c4ff42f181 📝(doc) update changelog 2026-03-10 18:36:04 +01:00
lebaudantoine ee0aa0fe5b 🔖(helm) release chart 0.0.17 2026-03-10 18:36:04 +01:00
lebaudantoine 09c871fc29 🩹(helm) fix MinIO ingress port configuration
The wrong port was configured, causing CORS issues
when uploading files directly to the MinIO bucket.

Port 9001 is reserved for the MinIO console;
use the correct API port instead.
2026-03-10 18:36:04 +01:00
Florent Chehab 8496959188 (infra) add celery backend to helm & improvements
* Add a simple celery-backend deployment to helm chart, which
  uses the same docker image as the backend, and runs a single
  worker.
* Update dev keycloack values accordingly
* Update Tiltfile to properly set service dependencies
* Update minio deployment to increase the default max body size limit
  (relevant to uploading files)
2026-03-10 18:36:04 +01:00
Florent Chehab 77105001e0 (settings) configure celery & run task in dedicated queue
Improve celery configuration from env variables and set
meet backend related tasks to run in the `meet-backend` queue
to ease sharing a single redis instance for multiple celery.
2026-03-10 18:36:04 +01:00
lebaudantoine 2d57d38644 🔨(helm) update helm chart for custom background image
Add media_files_svc and ingress_media_files to helm chart
for serving medias related to the new files.

This setup is more straightforward than merging the
existing recording related media ones.

Also updated values to enable file upload by default in dev.

Mostly done by @lebaudantoine.
2026-03-10 18:36:04 +01:00
dependabot[bot] c9d13619a6 ⬆️(deps) bump rollup from 4.44.2 to 4.59.0 in /src/frontend #1088
Bumps [rollup](https://github.com/rollup/rollup) from 4.44.2 to 4.59.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.44.2...v4.59.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 4.59.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-10 16:52:00 +01:00
Florent Chehab b99ec9bb50 🔨(tilt) use default user in dev
This change avoid permission issues when syncing files
with tilt.
2026-03-10 15:51:00 +01:00
Cyril b3f26469c8 🐛(frontend) fix hand icon and queue position alignment
Use inline-flex with alignItems center so number and icon align vertically.
2026-03-10 12:12:42 +01:00
Cyril d5c53c7dd4 ️(frontend) improve ui and qria labels for help article links
Screen readers now announce full link text instead of "Learn more".
2026-03-10 11:36:10 +01:00
Cyril f43ac2e4eb ♻️(refactor) apply caption text size to subtitles
Use accessibilityStore.captionTextSize in Transcription component.
2026-03-10 11:15:52 +01:00
Cyril ea5dd5bc0e (feat) add caption text size setting in Accessibility tab
Extract CaptionsSettings component, Settings > Accessibility > Captions.
2026-03-10 11:14:40 +01:00
Cyril 86427fa2b7 🌐(i18n) add captions text size setting translations
EN, FR, DE, NL for Accessibility > Captions > Text size.
2026-03-10 11:14:39 +01:00
Cyril 3959c3657c ️(frontend) add caption text size to accessibility store
Persist captionTextSize (small/medium/large) in user preferences.
2026-03-10 11:14:08 +01:00
Cyril 191f8abbcc ️(frontend) improve chat a11y for screen readers
Chat messages announced via role="log" when open, toast+announce when closed.
2026-03-09 16:06:08 +01:00
Cyril d91f8bb6e1 Merge branch 'fix/homepage-knowmore-link' 2026-03-09 14:41:26 +01:00
lebaudantoine d612f9b26b 🩹(changelog) fix changelog organisation for v1.10 2026-03-09 14:32:30 +01:00
Cyril 042be17cfa ️(frontend) improve MoreLink a11y and UX on home page
Render MoreLink once in LeftColumn, make full phrase clickable and add icon.
2026-03-09 14:27:39 +01:00
Cyril d00f4fa695 ️(frontend) sync html lang attribute with i18n for screen readers
Set document.documentElement.lang in i18n init and on languageChanged,
2026-03-09 13:32:10 +01:00
Ömer Fatih İlhan fd36469fc2 kubernetes documentation helm path updated 2026-03-06 16:16:14 +01:00
Florent Chehab dc278a6064 (backend) add file upload feature & tests
For the coming features we will need to store files on the meet side.
(for instance user backgrounds).

This commits adds a new Model to manage files, and the associated
serializers & viewsets. All are tested.

This work was heavily inspired by the work done by our friends at
https://github.com/suitenumerique/drive
It build on the same architecture design (upload directly to S3 but
download goes through our proxy), but model is much much simplier
(no folders, no file sharing, etc.).
2026-03-06 11:31:39 +01:00
Florent Chehab 047da94494 (backend) add mimetype detection logic from drive
Reused the logic developed by the team working on drive.
This is usefull for our own upload file backend (that will
come in later commits).

Dockefile was updated to add a required system dependency.

We might want to put this shared logic in a lib.
2026-03-06 11:31:39 +01:00
Florent Chehab 124a8bf8d9 🔨(docker) improve docker ignore
Tweak syntax to ignore folders recursively (important).
And add few missing ones.
2026-03-06 11:22:39 +01:00
Cyril c72c5cae1a ️(frontend) dynamic tab title when connected to meeting
Display room name, date and app title in browser tab
2026-03-05 17:58:00 +01:00
lebaudantoine b564044e70 🔖(minor) bump release to 1.10.0 2026-03-05 14:19:25 +01:00
renovate[bot] 4717143251 ⬆️(dependencies) update django to v5.2.12 [SECURITY] 2026-03-05 12:19:47 +01:00
dependabot[bot] 805e983749 Bump @hono/node-server from 1.19.9 to 1.19.10 in /src/frontend
Bumps [@hono/node-server](https://github.com/honojs/node-server) from 1.19.9 to 1.19.10.
- [Release notes](https://github.com/honojs/node-server/releases)
- [Commits](https://github.com/honojs/node-server/compare/v1.19.9...v1.19.10)

---
updated-dependencies:
- dependency-name: "@hono/node-server"
  dependency-version: 1.19.10
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-05 12:13:29 +01:00
Cyril 6dfafb7f67 💄(fix) truncate long names with ellipsis in reaction overlay
Long participant names under emoji reactions overflow without truncation.
2026-03-05 11:38:47 +01:00
lebaudantoine e56c0f997e 🩹(frontend) fix overflow in participant metadata layout
Recent styling changes introduced an overflow, causing the network
indicator to be pushed outside of the participant tile.

Remove width: 100% and add a minimal gap to prevent metadata
elements from being too close to each other.
2026-03-04 20:39:09 +01:00
lebaudantoine 61afd94e3a 🩹(frontend) enhance shortcut hint styling using PandaCSS utilities
Refactor styles to leverage PandaCSS inline capabilities for
better clarity and consistency.

Remove an unnecessary div wrapper that was causing a layout shift.
2026-03-04 20:39:09 +01:00
Cyril 3d7aec2b4a ️(frontend) announce selected state to SR in select and menu list
Add visually hidden "selected" text for screen readers.
2026-03-04 19:07:34 +01:00
dependabot[bot] 9c009839f0 Bump minimatch from 3.1.2 to 3.1.5 in /src/frontend
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.1.2 to 3.1.5.
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-04 17:22:29 +01:00
lebaudantoine ec63ddcd47 🔒️(helm) introduce a dedicated Kubernetes Ingress for webhook-livekit
Create a separate Ingress resource to isolate traffic targeting the
webhook-livekit endpoint and allow applying specific NGINX
annotations to this route.

Use an exact path match to take precedence over the default /api
regex rule defined in the base Ingress.

No similar change is made for the S3 webhook endpoint, as this
dependency will be removed from the project.
2026-03-04 16:30:01 +01:00
lebaudantoine fcde8757e6 🩹(frontend) remove incorrect reference to ProConnect on the prejoin
Remove incorrect reference to ProConnect (DINUM SSO) from content
literals, where it should not be mentioned by default in the
white labeled version.

It closes #1075
2026-03-04 14:04:37 +01:00
Cyril 9610e606eb ️(frontend) prevent focus ring clipping
Change overflow from hidden to visible on invite dialog
2026-03-04 13:39:02 +01:00
Cyril 8362ac0e24 ️(frontend) shortcuts table: semantic structure and kbd badge
caption, th scope, <kbd> for keys, no Tab stops on rows
2026-03-04 12:09:38 +01:00
Cyril f1ddd7fa2f ♻️(frontend) show shortcut hint only on first grid tile via CSS
Use :first-child and :focus-within to restrict hint visibility to the first tile
2026-03-04 12:08:22 +01:00
Cyril 487340efca ♻️(frontend) move fullscreen and recording shortcuts to their components
Register Ctrl+Shift+F in DesktopControlBar, Ctrl+Shift+L in ToolsToggle
2026-03-04 12:07:39 +01:00
Cyril 7ebc928dd3 (frontend) add Ctrl+Shift+/ to open shortcuts settings
Update toolbar hint and register shortcut to open settings on shortcuts tab
2026-03-04 12:07:39 +01:00
Cyril 85de214ca7 💄(frontend) truncate pinned participant name with ellipsis on overflow
Long participant names are now truncated with an ellipsis.
2026-03-04 11:21:10 +01:00
lebaudantoine e3e34dbf31 ️(frontend) optimize countdown check in IsIdleDisconnectModal.tsx
Using Array.includes runs in O(n) on every second of the countdown.

Replace the array with a Set to achieve O(1) lookups for better
performance.
2026-03-04 10:22:29 +01:00
lebaudantoine 555afe4abd ️(frontend) fix roomId RegExp recompilation
The regex was being recreated on every function call, causing
unnecessary performance overhead.

Hoist the RegExp to a module-level constant to reuse the compiled
pattern.
2026-03-04 10:22:29 +01:00
lebaudantoine 78ddb121e3 ️(frontend) avoid recreating inline array props in VideoTab.tsx
The items array was defined inline, creating a new reference on
every render.

Hoist the array to a module-level constant or memoize it with
useMemo to prevent unnecessary re-renders.
2026-03-04 10:22:29 +01:00
lebaudantoine ca9c7fc152 ️(frontend) avoid non-primitive default props recreation on each render
The empty object literal created a new reference every render,
potentially triggering unnecessary re-renders.

Hoist an EMPTY_PROPS constant to the module level and reuse it
instead of allocating a new object.
2026-03-04 10:22:29 +01:00
lebaudantoine 6e3845d0c1 ️(frontend) fix missing import type in Rating.tsx
Replace runtime import of PostHog with a type-only import to
avoid loading the module at runtime.
2026-03-04 10:22:29 +01:00
lebaudantoine 41b171da68 🩹(frontend) fix double await in Join.tsx
Remove redundant await in videoTrack.setDeviceId call
to avoid unnecessary promise chaining.
2026-03-04 10:22:29 +01:00
lebaudantoine 4ad897e756 ️(frontend) optimize enterRoom calls in useWaitingParticipants
Replace sequential await inside the loop with Promise.all, since
each enterRoom call is independent.

This prevents unnecessary delays when multiple participants are
waiting (e.g. 10 participants previously resulted in ~10x longer
execution time).
2026-03-04 10:22:29 +01:00
lebaudantoine 42647d6d25 🦺(backend) strengthen API validation for recording options
Improve validation of parameters accepted when starting a
recording to prevent unsupported or unexpected values.

Language validation will be further tightened to only accept
languages supported by the transcribe microservice.

Add extensive API validation tests to cover these scenarios.
2026-03-03 19:05:15 +01:00
leo 14526808ab ♻️(summary) clean up code and unify logging in preparation for testing
Refactor the summary service to better separate concerns, making components
easier to isolate and test. Unify logging logic to ensure consistent
behavior and reduce duplication across the service layer. These changes
set up the codebase for granular testing.
2026-03-03 15:44:53 +01:00
Florent Chehab 25167495cc 🐛(migrations) use settings in migrations
Use settings directly in migrations to avoid noop
migrations. This might have undisered side effects
if we change the config over time 'invalid' data will be
in the database.

It's a simple quick fix.
Keeping some migrations that are no useless to avoid changing
too much the migration history for users.

Similar to https://github.com/suitenumerique/people/commit/
469014ac415b25be0ceed08b31a87d2d40d743cd
2026-03-03 14:48:06 +01:00
lebaudantoine 720eb6a93e ♻️(backend) extract forbidden permission fields from the serializer
These fields previously triggered a suspicious operation exception
when passed to the API.

Make the list configurable so the serializer behavior can be
adjusted without requiring a new release.
2026-03-03 13:30:10 +01:00
lebaudantoine bfbf253033 🔒️(backend) enhance API input validation to strengthen security
During the bug bounty, attempts were made to pass unexpected hidden
fields to manipulate room behavior and join as a ghost.

Treat these parameters as suspicious. They are not sent by the
frontend, so their presence likely indicates tampering.

Explicitly allow the parameters but emit warning logs to help detect
and investigate suspicious activity.
2026-03-03 13:30:10 +01:00
lebaudantoine 692e0e359e (backend) install pydantic and django-pydantic-field to strengthen API
Super useful for validation when handling unstructured dictionaries.

Follow qbey's recommendation and align with the
suitenumerique/conversation project approach to improve schema
validation and data integrity.
2026-03-03 13:30:10 +01:00
Cyril 1d23cb889a ️(frontend) announce mic/camera state for screen readers on shortcut
announce "Microphone/Camera turned on/off" when toggling via
keyboard shortcut so screen reader users get feedback
2026-03-03 09:46:47 +01:00
lebaudantoine b2ad423886 🔖(minor) bump release to 1.9.0 2026-03-02 14:33:25 +01:00
lebaudantoine 2c7b4bea04 🔒️(ci) disable Trivy scan pending clarification from Aqua Security
The Trivy GitHub repository was wiped over the weekend, raising
suspicions of a potential supply chain attack.

Temporarily disable the scan until the situation is clarified.
2026-03-02 11:29:31 +01:00
lebaudantoine 1eda18ea6e 🔧(ci) introduce Claude security review GitHub Action
Add automated security review on new pull requests to strengthen
early detection of potential vulnerabilities.

Leverage Claude to help identify security issues and highlight
areas requiring special attention.
2026-03-02 11:29:31 +01:00
Cyril 8d5488c333 ️(frontend) add skip link component for keyboard navigation
Improve a11y: skip to main heading, bypass header. RGAA 12.7.
2026-02-27 22:49:03 +01:00
lebaudantoine 5c0e6b6479 ⬆️(frontend) update react-aria-components to a newer version
The previously pinned version (July release) did not support
passing the aria-disabled prop to React Aria Button.

A more recent release (August) introduced this capability.
Upgrade is required to make Cyril's proposal work.
2026-02-27 19:39:55 +01:00
Cyril 077cf59082 ️(frontend) keep carousel nav buttons focusable at first and last slide
use aria-disabled  to prevent focus loss when reaching slide limits
2026-02-27 19:39:55 +01:00
Cyril 4881fa20f5 ️(frontend) fix carousel focus ring visibility with NVDA
add :focus fallback for nav buttons when focus-visible detection fails
2026-02-27 19:39:55 +01:00
Cyril 116db1e697 ️(frontend) improve IntroSlider accessibility for screen readers
add aria-labels with slide position, carousel semantics, live region
2026-02-27 19:39:55 +01:00
Florent Chehab 4b76e9571f ⬆️ (python) bump minimal required python version to 3.13
We are going to use features only available in python 3.13.
We already ship docker images based on python 3.13.

For https://github.com/suitenumerique/meet/pull/1030
2026-02-27 12:37:14 +01:00
Cyril e8739d7e70 ️(frontend) improve JoinMeetingDialog screen reader
Focus input on modal open and improve screen reader announcements
2026-02-26 18:35:15 +01:00
Florent Chehab 602bcf3185 🩹(devex) fix Makefile special character support
Under some shells echo doesn't work as expected with the special formatting.

Using printf when creating the variables make it work and should be more robust.
2026-02-25 18:08:57 +01:00
leo f5e0ddf692 (summary) add localization support for transcription context text
Transcription and summarization results were always generated
using a French text structure (e.g. "Réunion du..."), regardless
of user preference or meeting language. Introduced basic localization
support to adapt generated string languages.
2026-02-25 18:07:19 +01:00
lebaudantoine cd0cec78ba 🩹(frontend) fix German language preference update
German was missing from the frontend/backend language list in the
sync hook, causing user preference updates to be ignored.

Add the language to ensure preference changes are properly applied.
2026-02-25 17:01:02 +01:00
leo e647787170 ♻️(devex) run service as part of make bootstrap
Add run to make bootstrap, thus starting the service. This fixes a
mismatch with development documentation.
2026-02-25 11:15:34 +01:00
lebaudantoine d76b4c9b9f 🔧(dependencies) update default renovate config
Update default Renovate configuration to open PRs on
the first day of each month instead of weekly.

Security updates remain handled immediately by Dependabot, while
Renovate manages regular dependency updates to keep the project
up to date with third-party packages.
2026-02-24 18:51:49 +01:00
lebaudantoine 09c7edecb8 📌(dependencies) pin Django to a version below 6.0.0
Delay upgrading until the ecosystem around Django 6 matures.
Also prevent Renovate from suggesting updates beyond v6.
2026-02-24 18:51:49 +01:00
lebaudantoine f625df6508 ♻️(backend) refactor external API tests
Refactor tests to avoid duplicating JWT secret key configuration.

Introduce configuration of the JWT audience, which previously had no
default value.
2026-02-24 16:07:23 +01:00
lebaudantoine ac87980a27 ♻️(backend) refactor external API authentication classes
Refactor external API authentication classes to inherit from a
common base authentication backend.

Prepare the introduction of a new authentication class responsible
for verifying tokens provided to calendar integrations.

Move token decoding responsibility to the new token service so it
can both generate and validate tokens.

Encapsulate external exceptions and expose a clear interface by
defining custom Python exceptions raised during token validation.

Taken from #897.
2026-02-24 16:07:23 +01:00
lebaudantoine 7cab46dc29 ♻️(backend) encapsulate token generation in a service
Encapsulate token generation logic for authenticating to the
external API in a well-scoped service.

This service can later be reused in other parts of the codebase,
especially for providing tokens required by calendar integrations.

Commit was cherry picked from #897
2026-02-24 16:07:23 +01:00
Cyril 259b739160 ️(a11y) fix focus ring on tab container components
Suppress inherited global focus ring on Tabs, TabList, and TabPanel containers.
2026-02-24 14:37:49 +01:00
lebaudantoine 6f77559633 ⬆️(backend) update python dependencies
Updating ruff led me to refactor an unnecessary lambda
2026-02-24 12:23:22 +01:00
Cyril 2cdf19de77 ♻️(frontend) remove redundant formatLongPressLabel helper
Use i18next interpolation directly in useShortcutFormatting
2026-02-24 09:16:16 +01:00
Cyril fcf08a6dbd 🌐(frontend) localize SR modifier labels
Replace hardcoded 'Alt'/'Shift' in SR formatter with i18next
labels. Use Option/Alt distinction on Mac like Ctrl/Command.
2026-02-24 09:13:03 +01:00
Cyril 7bf623f654 🌐(frontend) localize SR modifier labels
Replace hardcoded 'Alt' and 'Shift' in the SR shortcut
2026-02-24 09:06:53 +01:00
lebaudantoine 1c1d1938d9 🚚(frontend) rename "wellknown" directory to "well-known"
Fix a typo introduced while configuring the correct directory for
automatic container view opening on Windows.
2026-02-23 20:20:54 +01:00
lebaudantoine ddb81765f3 🔧(ci) explicitly set CI permissions to read-only as a precaution
Clarify intent and avoid any ambiguity regarding granted permissions.
2026-02-23 18:00:04 +01:00
Ovgodd 8ca52737cd (frontend) introduce a shortcut settings tab
Work adapted from PR #859 and partially extracted to ship as a
smaller, focused PR.

This allows users to view the full list of available shortcuts.
An editor to customize these shortcuts may be introduced later.
2026-02-23 14:26:52 +01:00
Stephan Meijer 87b9ca2314 👷(docker) add arm64 platform support for image builds
Signed-off-by: Stephan Meijer <me@stephanmeijer.com>
2026-02-23 14:06:54 +01:00
lebaudantoine 8a6419da44 🔨(livekit) pin LiveKit version in the dev stack to match production
Avoid potential synchronization issues caused by version drift.
2026-02-23 12:14:00 +01:00
lebaudantoine 127d4e1d5a ⬆️(frontend) update livekit-related dependencies
Bring packages to the latest compatible versions.
2026-02-23 12:14:00 +01:00
lebaudantoine 99cbc1f784 ⬆️(frontend) update panda-related dependencies
Bring packages to the latest compatible versions.
2026-02-23 12:14:00 +01:00
lebaudantoine 246312c51c ⬆️(frontend) update i18next-related dependencies
Bring packages to the latest compatible versions.
2026-02-23 12:14:00 +01:00
lebaudantoine 1b09683938 ⬆️(frontend) update vite-related dependencies
Bring packages to the latest compatible versions.
2026-02-23 12:14:00 +01:00
lebaudantoine db3d3d61ef ⬆️(frontend) update tanstack-related dependencies
Bring packages to the latest compatible versions.
2026-02-23 12:14:00 +01:00
Cyril c1a797c2c1 💄(frontend) add focus ring to reaction emoji buttons
show outline on keyboard focus, fix when sr is opened
2026-02-23 10:29:17 +01:00
lebaudantoine 4d6a7573c4 ⬆️(mail) update mail-related dependencies
Bring packages to the latest compatible versions.
2026-02-23 10:28:45 +01:00
dependabot[bot] 0b73fd8f06 Bump undici from 6.19.8 to 6.23.0 in /src/frontend
Bumps [undici](https://github.com/nodejs/undici) from 6.19.8 to 6.23.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.19.8...v6.23.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 6.23.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-23 10:00:40 +01:00
lebaudantoine e362765b21 🔒️(frontend) uninstall curl from the frontend production image
Remove unnecessary package to reduce image size and surface area.
2026-02-20 18:27:17 +01:00
lebaudantoine be79fdac80 🩹(summary) fix pip uninstall order in build stages
Pip was removed before copying the builder stage output, which caused
it to be reinstalled unintentionally. Adjust the order to align with
the backend image behavior.
2026-02-20 18:27:17 +01:00
François Petitit 75a15a0004 Fix typo in buildpack environment variable name 2026-02-20 18:26:24 +01:00
Cyril 3087dfe486 ♻️(frontend) replace custom reactions toolbar with react aria popover
use react aria primitives for escape, focus containment and restore
2026-02-20 18:21:33 +01:00
lebaudantoine 9916ab7d7e 🔖(minor) bump release to 1.8.0 2026-02-20 13:44:19 +01:00
lebaudantoine bd2ad3bb99 📝(changelog) update changelog with recent changes
Update changelog.
2026-02-20 13:17:45 +01:00
lebaudantoine f02fbc85a3 🔒️(agents) upgrade OpenSSL to address CVE-2025-15467
Upgrade OpenSSL and related dependencies to address CVE-2025-15467
in meet-agents.

This vulnerability was blocking the image signature workflow, as it
is classified as a critical dependency.
2026-02-20 13:17:45 +01:00
lebaudantoine 4fd4e074e0 📌(agents) pin protobuf to 6.33.5 to fix CVE-2026-0994
Protobuf is a transitive dependency. Pin it to version 6.33.5 to
address CVE-2026-0994.
2026-02-20 13:17:45 +01:00
lebaudantoine ec3d4f7462 🔒️(agents) uninstall pip from the agents image
Reduce surface area and keep the runtime image minimal.
2026-02-20 13:17:45 +01:00
lebaudantoine 4507325331 🔒️(summary) switch to Alpine base image
Reduce surface area and keep the runtime image minimal.

Alpine 3.22 provides ffmpeg v6 as the latest version.
Alpine 3.23 does not include ffmpeg v7, so upgrade directly to v8.

Install pip temporarily for build steps, then remove it from the
production image.
2026-02-20 13:17:45 +01:00
lebaudantoine dac4a72838 🔒️(backend) uninstall pip in the production image
Reduce surface area and keep the runtime image minimal.
2026-02-20 13:17:45 +01:00
lebaudantoine 5048005fc1 🔧(tilt) use the same user as in production to facilitate testing
Use the same user as in production to facilitate local testing with
the production image.

Assign group 127 to the docker user to mirror CI and match production
practices, even though the rationale for this group mapping is unclear.
2026-02-20 13:17:45 +01:00
lebaudantoine 002c7c0e42 🩹(tilt) fix minor indentation issue in the Tilt file
No functional impact, just a formatting cleanup.
2026-02-20 13:17:45 +01:00
Stephan Meijer e18b732776 ⬆️(ci) upgrade GitHub Actions workflow steps to latest versions
Update all GitHub Actions to their latest major versions for improved
performance, security patches, and Node.js runtime compatibility.

Signed-off-by: Stephan Meijer <me@stephanmeijer.com>
2026-02-20 11:49:14 +01:00
lebaudantoine ce9f812a7e 🔖(minor) bump release to 1.7.0 2026-02-19 12:37:26 +01:00
lebaudantoine b02591170f 🐛(frontend) configure missing participants shortcut
Configure missing shortcut in the frontend for the participant
side panel.

It was accidentally omitted while merging Cyril's changes.
2026-02-19 12:12:23 +01:00
lebaudantoine e58181f846 🧑‍💻(backend) configure the external application API
Configure the external application API across different Kubernetes setups
to enable seamless usage without repeated configuration
when iterating on endpoints.
2026-02-19 11:16:10 +01:00
lebaudantoine d37f47e82c (frontend) expose Windows app web link
Expose a Windows application web link requested by a partner who wraps Visio
inside a containerized Chrome application due to security concerns and limited
trust in video codecs.

This commit introduces a proof of concept implementation.
We plan to iterate on this approach and likely generalize it under a more
neutral lasuite meet naming in future revisions.
2026-02-19 10:17:06 +01:00
lebaudantoine db80c09c10 ⬆️(frontend) update prettier 2026-02-18 22:10:24 +01:00
lebaudantoine fd9f2a81ca ⬆️(dependencies) update js dependencies 2026-02-18 22:10:24 +01:00
unteem d865db5f1b 📝(doc) fix variable name 2026-02-18 21:45:26 +01:00
unteem 7cc5b2b961 📝(doc) fix env files for docker compose
remove unused env file
mount .env
2026-02-18 21:45:26 +01:00
Cyril c85977cb68 (frontend) add clickable settings general link in idle modal
helps users quickly disable idle warning from the right settings tab.
2026-02-18 15:17:37 +01:00
Ovgodd 3c3b4a32e3 (frontend) support additional shortcuts to broaden accessibility
Add support for additional shortcuts to broaden accessibility and
integration capabilities. Some of these are required to ensure full
functionality with the RENATER SIP media gateway, allowing shortcut
mapping to DTMF signals. Others improve usability for keyboard-only
users; a lightweight helper will be introduced to surface available
shortcuts and make them easier to discover and use.
2026-02-12 18:56:48 +01:00
Ovgodd 9b033c55b2 (frontend) support Shift and Alt key when building shortcuts
Add support for Shift and Alt modifiers when building shortcuts,
expanding the range of possible combinations and allowing more expressive
and flexible shortcut definitions.
2026-02-12 18:56:48 +01:00
Ovgodd a2c7becaf4 ♻️(frontend) centralize shortcuts in a catalog
Centralize shortcuts into a single source of truth, making them easier to
discover and manage, and laying the groundwork for future override support
and the ability to revert to default definitions if needed.

Shortcuts are now retrieved by identifier, while leaving each component
responsible for declaring when a shortcut should be enabled and which
handler should be called;
2026-02-12 18:56:48 +01:00
lebaudantoine 89031abb63 🔖(minor) bump release to 1.6.0 2026-02-10 15:31:29 +01:00
Bastien Ogier fc92fa4eb4 🚀(docs) document Scalingo deployment
(docs) document Scalingo deployment
2026-02-10 10:44:13 +01:00
Bastien Ogier 2c65cc061e 🚀(settings) standardize DATABASE_URL environment retrieval
(settings) standardize DATABASE_URL environment retrieval
2026-02-10 10:44:13 +01:00
Bastien Ogier bfadeae6ee 🚀(scalingo) custom logo override
(scalingo) custom logo override
2026-02-10 10:44:13 +01:00
Sylvain Zimmer 117677bd14 🚀(paas) add PaaS deployment scripts, tested on Scalingo
add PaaS deployment scripts, tested on Scalingo
2026-02-10 10:44:13 +01:00
lebaudantoine 69c6e58017 🔒️(backend) add application validation when consuming external JWT
Token generation already verifies that the application is active, but this
guarantee was not enforced when the token was used. This change adds a
runtime check to ensure the client_id claim matches an existing and active
application when evaluating permissions.

This also introduces an emergency revocation mechanism, allowing all previously
issued tokens for a given application to be invalidated if the application is
disabled.
2026-02-09 22:18:09 +01:00
lebaudantoine 6742f5d19d (backend) monitor throttling rate failure through sentry
Use a mixin, introduced by @lunika in the shared
backend library to monitor throttling behavior.

The mixin tracks when throttling limits are reached, sending errors to Sentry
to trigger alerts when configured. This helps detect misconfigurations,
fine-tune throttling settings, and identify suspicious operations.

This enables safely increasing API throttling limits while ensuring stability,
providing confidence that higher limits won’t break the system.
2026-02-09 15:50:53 +01:00
lebaudantoine 23de7e52bc ♻️(backend) extract throttling classes into a module
Extract throttling classes into a dedicated Python module, following the
structure of suitenumerique/docs.

This is a preparatory refactor to ease upcoming changes to the throttling
implementation. No functional behavior change is introduced in this commit.
2026-02-09 15:50:53 +01:00
lebaudantoine 3887255e9c ♻️(backend) rework permission to better align with DRF responsibilities
If a viewset action is not implemented, the permission layer no longer returns
a 403. Instead, it lets DRF handle the request and return the appropriate 405
Method Not Allowed response, ensuring cleaner and more standard API error
handling.
2026-02-09 12:16:12 +01:00
lebaudantoine 5d6ad3f3f6 🔒️(backend) enhance scope manipulation
Enhance scope manipulation by normalizing and sanitizing
scope values before processing.

Scopes are now converted to lowercase to ensure consistent behavior,
deduplicated while preserving their original order, and handled in a
deterministic way aligned with the intended authorization model.
2026-02-09 12:16:12 +01:00
lebaudantoine 44d68a9c80 (backend) strengthen external API viewset test coverage
Reinforce the test suite around the external API viewset to better
prevent regressions, permission leaks, and unexpected failures.

Adds additional scenarios covering permission enforcement, edge cases,
and error handling to ensure the external API behavior remains stable
and secure as it evolves.
2026-02-09 12:16:12 +01:00
lebaudantoine ed5c1bbd84 ♻️(backend) improve scope prefix removal logic
The previous replace usage was too broad and could remove multiple
occurrences, which was not the original intention.

Replace the replace call with removeprefix, which more accurately
matches the expected behavior by only removing the prefix when present
at the start of the string.
2026-02-09 12:16:12 +01:00
lebaudantoine f8c6da8021 🔐(backend) enforce object-level permission checks on room endpoint
Apply strict permission validation on the external API room endpoint to
enforce the principle of least privilege. Unlike the default API (which allows
unauthenticated room retrieval and filters access in the serializer), the
external API now only exposes rooms to users with explicit permissions.

This change fixes a security issue. Slug-based room retrieval, as supported
by the default API, is not introduced here but could be added later if needed.
Retrieving rooms by UUID is retained, as guessing a UUID is significantly harder
than a slug.

A dedicated permission class was created to avoid coupling permissions between
the default and external APIs. The external API enforces stricter access rules.

Access policies may be revisited based on user and integrator feedback. The
external API currently has no production usage.
2026-02-09 12:16:12 +01:00
lebaudantoine 5ba1657e00 🧪(backend) add test exposing rooms permission flaw in external API
Add a failing test demonstrating that a user can retrieve a room they
do not have access to when the room UUID is known.

This highlights an improper object-level permission verification in the
external API. While exploitation requires obtaining the target room
UUID, this still represents a security issue (BOLA / IDOR class
vulnerability) and must be fixed.

The test documents the expected behavior and will pass once proper
access filtering or permission checks are enforced.
2026-02-09 12:16:12 +01:00
René Fischer c28b8ba902 🌐(frontend) add missing DE translation for accessibility settings 2026-02-08 23:57:51 +01:00
lebaudantoine 6962367e18 🐛(backend) fix notification tests broken by renaming env var
SCREEN_RECORDING_BASE_URL was renamed to RECORDING_DOWNLOAD_BASE_URL.

The new variable supersedes the old one, which is temporarily kept for backward
compatibility. This test failure was missed because the local common file was
out of sync with common.dist.

Add the new variable with a default value of None to ensure a smooth
deprecation path when the old variable is removed.
2026-02-07 00:14:49 +01:00
Cyril 0bd57e8623 💄(frontend) clean up spinner styles
remove inline styles for better maintainability
2026-02-06 23:29:23 +01:00
Cyril 27f2023104 ️(frontend) add reduced-motion spinner fallback
show an hourglass when animations are reduced
2026-02-06 23:29:23 +01:00
lebaudantoine 44362eca23 📝(changelog) update changelog
Update changelog with PR's purpose
2026-02-05 19:16:02 +01:00
lebaudantoine c34a85699b ⬆️(backend) upgrade Django to address multiple high-severity CVEs
This update fixes several SQL injection vulnerabilities, including issues in
RasterField band index handling and crafted column aliases (notably in
QuerySet.order_by()), as reported in CVE-2026-1207, CVE-2026-1287, and
CVE-2026-1312.
2026-02-05 19:16:02 +01:00
lebaudantoine 12d8c4a9db ️(admin) improve recording access select component performance
Replace the basic select component that loaded thousands of options into the
DOM with a smarter component supporting dynamic loading and search.

With large user bases, linking users to recording access caused massive option
lists to render, severely impacting performance. This change dramatically
improves page loading speed.
2026-02-05 19:16:02 +01:00
lebaudantoine 42a05da5c0 🔒️(admin) make recording fields read-only for security and performance
These values should not be updated from the admin interface. Allowing changes
to a recording’s associated room could lead to data leaks (e.g., notifications
being resent to the wrong users after a malicious modification).

Also remove the room select field, which rendered a dropdown with ~150k options,
flooding the DOM and severely degrading page performance.
2026-02-05 19:16:02 +01:00
lebaudantoine 4344dd6e35 ️(admin) optimize room view queries by prefetching user access
Use prefetch_related for the room–user access relationship to avoid N+1
queries. select_related cannot be used here since this is a many-to-many
relation. This significantly improves performance.
2026-02-05 19:16:02 +01:00
lebaudantoine fe28902b2e ️(admin) optimize recording view by selecting room at the SQL level
Use select_related on the room foreign key to avoid N+1 queries. This makes
Django perform a join between tables instead of triggering additional queries
per row, reducing complexity from O(n²) patterns to O(n) and significantly
improving performance.
2026-02-05 19:16:02 +01:00
lebaudantoine 1e1e1a2657 ️(admin) remove list filters based on room in recording view
This was a mistake: the filter was never used in production and caused
performance issues. It generated a list of unique room slugs, bloating the DOM
with thousands of values and slowing down view rendering. Remove this
regression.
2026-02-05 19:16:02 +01:00
lebaudantoine f4e48dafac 📝(frontend) update legal terms
Update legal terms following review and validation by the legal team.
2026-02-05 19:09:12 +01:00
lebaudantoine 9f58efb851 🥅(summary) catch file-related exceptions when handling recording objects
Previously, if a recording file was not found in the bucket, the code would
crash. This adds proper error handling to avoid unhandled failures.
2026-02-05 17:50:35 +01:00
Cyril 716e11b5b3 ️(frontend) fix form labels and autocomplete wiring
Ensure labels map to inputs and avoid empty describedby output
2026-02-04 09:28:15 +01:00
lebaudantoine 88a1136dfd ♻️(backend) refactor ApplicationViewSet to use a basic ViewSet
This endpoint only exposes a custom action for token generation and does not
rely on serializers or querysets. Using ViewSet is more appropriate here, as
it provides routing without enforcing standard CRUD patterns or requiring a
serializer_class.

This removes unnecessary constraints and avoids warnings related to missing
serializer configuration, while better reflecting the actual responsibility of
this view.

I noticed this bug from Sentry issue 241308
2026-02-03 16:22:06 +01:00
lebaudantoine 90633928a8 💚(backend) reactivate trivy scan on backend image
Protobuff has been patched, rebuilding the backend image should be
enough with pip to pull its latest version, which fixes the CVE.
2026-02-03 11:57:02 +01:00
lebaudantoine fd894eb61f 🔧(compose) configure LiveKit webhooks in the local Docker Compose stack
Without this configuration, LiveKit does not notify the backend when a recording
starts, leaving it stuck in a “starting recording” state.

Thanks to @leobouloc for spotting the issue.
2026-01-29 18:22:00 +01:00
lebaudantoine bb64532cff 🔖(minor) bump release to 1.5.0 2026-01-28 21:28:55 +01:00
Cyril 692c55ed1b Merge branch 'refactor/issue-921-generic-sr-announcer' 2026-01-28 17:07:43 +01:00
lebaudantoine df616ae711 🩹(doc) fix github rendering of docker compose doc
The docker compose rendering was broken because of a recent merge.
Fix it. I've also fixed other minor issues.
2026-01-28 16:17:53 +01:00
Cyril 021d7a7e06 ️(frontend) centralize aria-live announcements in store
avoid per-feature live regions and reduce a11y duplication.
2026-01-28 14:01:35 +01:00
Andrew Hunter f2a3e7c8de 📝(doc) Fix typo 2026-01-28 12:13:19 +01:00
Andrew Hunter cf07ceb67e 🔧(docker) Fix incorrect env variable
Incorrect capitalization prevents correct MEET_HOST variable
subsitution.
2026-01-28 12:13:19 +01:00
Andrew Hunter ea7fb5fc27 📝(doc) Use an empty directory for postgres
Use an empty directory for postgres data, otherwise it will complain the
directory is not empty and fail to start.
2026-01-28 12:13:19 +01:00
Andrew Hunter 6e8a6ce82a 📝(doc) Add -p swich to mkdir
Add the -p switch to create the parent directory before we try to cd
into it.
2026-01-28 12:13:19 +01:00
Andrew Hunter ce960ae330 📝 (doc) Add key gen example
Add a API key generation example using OpenSSL.
2026-01-28 12:13:19 +01:00
Cyril f9dd2e1909 ️(frontend) add global screen reader announcer
centralize live region rendering with a shared announce hook.
2026-01-28 11:44:39 +01:00
Cyril 9023e54352 ️(frontend) add screen reader announcer store
create shared state for screen reader announcements.
2026-01-28 11:40:54 +01:00
Cyril 8295574616 (frontend) sr pin/unpin announcements with dedicated messages
improves accessibility by announcing pin/unpin on state change
2026-01-28 11:13:09 +01:00
Cyril db15c8b6cc ️(frontend) adjust visual-only tooltip a11y labels
Ensure tooltips stay visual while exposing correct aria-labels.
2026-01-28 10:08:01 +01:00
Cyril e1aeec6053 ️(frontend) adjust sr announcements for idle disconnect timer
reduces screen reader noise while keeping key countdown cues
2026-01-27 22:12:55 +01:00
lebaudantoine c5aa762e11 📝(doc) update mosacloud link in the list of saas instances
Link has changed. Update it.
2026-01-27 18:38:34 +01:00
lebaudantoine 8f710a4626 🔒️(frontend) fix an XSS vulnerability on the recording page
An XSS vulnerability was identified by an open-source contributor. While the
impact was limited, only a room owner could inject the content and then view the
recording page, it is important to address, especially before introducing
multi-owner support.
2026-01-27 14:12:45 +01:00
virgile-deville 60d1338eff 📝(readme) mention french state wide deployment
To indicate product maturity to reusers

Signed-off-by: virgile-deville <virgile.deville@beta.gouv.fr>
2026-01-26 12:04:16 +01:00
lebaudantoine f8436d9ae2 🔖(minor) bump release to 1.4.0 2026-01-25 20:02:37 +01:00
lebaudantoine 39fb273201 💩(ci) disable temporarily Trivy scan step for backend image
A new vulnerability (CVE-2026-0994) was reported and is not yet fixed.
It affects protobuf libraries used by the livekit-api Python package.

A fix is in progress upstream, but the related PR has not yet been merged or
released. Since a release is required tonight, the Trivy scan step is
temporarily disabled to allow the build to proceed. This should be re-enabled
once a patched version is available.

https://github.com/protocolbuffers/protobuf/pull/25239
2026-01-25 18:01:13 +01:00
lebaudantoine d101459115 (frontend) add configurable external redirect for unauthenticated users
Offer a way to redirect unauthenticated users to an external home page when they
visit the app, allowing a more marketing-focused entry point with a clearer
value proposition.

In many self-hosted deployments, the default unauthenticated home page is not
accessible or already redirects elsewhere. To ensure resilience, the client
briefly checks that the target page is reachable and falls back to the default
page if not.
2026-01-25 16:49:56 +01:00
aleb_the_flash 88696a23fd 🩹(doc) update link to the environment variables
Link was invalid. Update it to point to the chart's README file.
Please note this file might be removed.
2026-01-25 00:17:50 +01:00
Cyril 13d26a76b3 (frontend) scope scrollbar gutter override to video rooms
limit scrollbar gutter override to video conference context
2026-01-25 00:07:51 +01:00
lebaudantoine b675517a60 🚧(frontend) debug transcript segment organization
for the big monday demo, push a draft commit.
2026-01-23 19:43:29 +01:00
lebaudantoine a5254ffd59 🔊(frontend) log participant and segments
Log transcription segments to troubleshoot duplication issue.
2026-01-23 18:53:10 +01:00
lebaudantoine ff82bca9ec 🐛(frontend) ensure transcript segments are sorted by their timestamp
Switching from Deepgram to our custom Kyutai implementation introduced changes
in how segment data is returned by the LiveKit agent, so the segment start time
is now treated as optional.
2026-01-23 18:22:40 +01:00
lebaudantoine 99a18b6e90 🩹(backend) use case-insensitive email matching in the external api
Fix a minor issue in the external API where users were matched using
case-sensitive email comparison, while authentication treats emails as
case-insensitive. This caused inconsistencies that are now resolved.

Spotted by T. Lemeur from Centrale.
2026-01-20 20:50:13 +01:00
Cyril 250e599465 📝(frontend) align close dialog label in rooms locale
keep close label consistent with global wording
2026-01-20 12:39:03 +01:00
Cyril 144a4e1b85 ️(frontend) improve background effect announcements
ensure sr announces clear and virtual background state
2026-01-20 12:34:32 +01:00
Cyril 78ab3cdbdf ️(frontend) improve aria-label with accessible emoji description
replace raw emoji with descriptive label to enhance screen reader support
2026-01-19 23:35:18 +01:00
Cyril a815d6c00d 📝(docs) add changelog file to document project changes
helps track notable changes and improvements over time
2026-01-19 23:35:18 +01:00
Cyril dfbc3a9d17 💄(frontend) add globally available sr-only utility class
provides reusable hidden style for screen reader-only content
2026-01-19 23:35:18 +01:00
Cyril 086db3d089 📝(frontend) update a11y store labels and link for clarity
improves naming and navigation for better user understanding of options
2026-01-19 23:35:18 +01:00
Cyril 014ef3d804 (frontend) create a11y store to manage user option toggles
sets up state handling for enabling or disabling a11y preferences
2026-01-19 23:35:18 +01:00
Cyril de3e1a56a8 (frontend) add placeholder for accessibility menu in settings panel
prepares UI for future accessibility options without implementing logic yet
2026-01-19 23:35:18 +01:00
Cyril 459749b992 (frontend) getEmojiLabel util for accessible emoji labeling across app
centralizes emoji label logic to ensure consistency and reuse in UI components
2026-01-19 23:35:18 +01:00
Cyril e1450329f2 ️(frontend) add screen reader announcements for reactions interactions
ensures users get feedback when adding reactions via assistive tech
2026-01-19 23:35:18 +01:00
Cyril c7e3194331 ️(frontend) announce copy state in invite dialog
improves screen reader feedback after copying the link
2026-01-19 22:55:47 +01:00
Cyril 902b005f32 ️(frontend) improve contrast for selected options
add dark inner border to enhance visibility and accessibility
2026-01-19 22:28:46 +01:00
Cyril 51d22783b2 ️(frontend) make carousel image decorative
avoid screen reader announcing redundant visual content
2026-01-19 18:29:25 +01:00
blipp 76f80a0f2f Fix k8s link in Docker Compose installation guide 2026-01-19 18:29:25 +01:00
Cyril 82eb930200 📝(docs) update changelog
document the latest change in the project history
2026-01-19 18:29:25 +01:00
Cyril eeeb950e08 ️(frontend) improve participants toggle a11y label
avoid screen reader duplication by using visual-only tooltip
2026-01-19 18:29:19 +01:00
Cyril cb77688572 ️(frontend) add accessible back button in side panel
label the back button and separate it from the heading for a11y
2026-01-19 15:14:25 +01:00
lebaudantoine f9524b2f0a 🔒️(backend) prevent automatic upgrade setuptools
The latest `setuptools` version pulls in a `jaraco.context` version that
triggers a Trivy scan failure. `jaraco.context` has a path traversal
vulnerability.

This fix is inspired by suitenumerique/people, specifically Marie’s PR #1010.
2026-01-19 14:16:00 +01:00
lebaudantoine a50aabeaf8 🔖(minor) bump release to 1.3.0 2026-01-13 15:44:23 +01:00
lebaudantoine 594bd5a692 🚸(frontend) hide back button when a user is ejected by an admin
Avoid showing a back button when a user is kicked out of a meeting by an admin,
to prevent them from repeatedly rejoining the room.
2026-01-13 15:28:39 +01:00
lebaudantoine 69d92e6f30 🩹(frontend) icon font loading to avoid text/icon flickering
Icon fonts were loading just in time, which is good for performance, but caused
a visible blink where fallback text appeared before the font loaded. I followed
the documentation introduced in PR 963 of the fontsource repository.

This introduces preloading for critical fonts, slightly increases initial load
time, and defines custom @font-face rules to control font-display and avoid
font swapping. This approach only works with Vite-based frameworks,
as noted in the documentation.

See the advanced installation section for material-symbols-outlined on
fontsource.org, and apply the same approach for Material Icons.

I manually built the preload headers based on a comment from issue #83.
This works well with Vite, which replaces the font URLs at build time.
2026-01-12 12:56:08 +01:00
lebaudantoine c47e830b40 ♻️(frontend) introduce an Icon primitive
Encapsulate icon and symbol rendering in a dedicated component that applies
aria-hidden and disables translation attributes.

This prevents browsers from translating icon names and breaking the UI, and
ensures screen readers do not announce decorative icons.

This is a first draft and can be extended with additional variants later.
2026-01-12 12:56:08 +01:00
lebaudantoine d7f1b7b94c 🚸(frontend) explain to a user her was ejected
Add a clear feedback message explaining to users when they are ejected from a
meeting, explicitly stating that the action was taken by an admin.
2026-01-11 23:07:54 +01:00
lebaudantoine 8072d2c950 ♻️(frontend) refactor disconnection reason handling and state
Refactor the duplicateIdentity boolean URL parameter into an extensible string
reason parameter, making it easier to customize the disconnection message
shown to users.

Avoid passing this value via URL parameters, which are easy to manipulate.
Instead, use Wouter’s built-in navigation state to pass data across pages.

This was initially missed because navigateTo is a wrapper around Wouter’s
official navigation function, and its arguments were easy to overlook. This is
now fixed.

This prepares the ground for supporting additional disconnection reasons in
upcoming commits.
2026-01-11 23:07:54 +01:00
lebaudantoine 726f9097f9 ♻️(frontend) refactor the onDisconnected function to use a switch
This makes the logic more extensible in preparation for introducing
additional disconnect reason handlers.
2026-01-11 23:07:54 +01:00
Cyril bbc7fa8012 ️(frontend) focus first background effect button on panel open
improves keyboard navigation by placing focus on first actionable element
2026-01-09 19:03:34 +01:00
Cyril 41db3e766b ️(frontend) add blur status with sr announcement and sr-only class
improves a11y by exposing blur state to sr users and hiding visual labels

Signed-off-by: Cyril <c.gromoff@gmail.com>
2026-01-09 19:03:34 +01:00
Cyril 1ab3ce6d47 ️(frontend) improve background effects a11y and blur labels
Signed-off-by: Cyril <c.gromoff@gmail.com>
2026-01-09 19:03:34 +01:00
lebaudantoine 3cd5c77f42 ️(frontend) enhance sidepanel accessibility
Use the appropriate HTML <aside> element for the side panel and enhance
it with the correct ARIA attributes to improve accessibility.
2026-01-09 19:03:34 +01:00
lebaudantoine 3ddb075c6b ️(frontend) enhance vocalization of blur options
Hide non-essential icons and refine the labels to emphasize that one option
applies a stronger blur than the other. This should provide clearer cues for
screen reader users.
2026-01-09 19:03:34 +01:00
lebaudantoine 9ed2500565 🚸(frontend) remove the “none” effect button
While this makes it slightly less explicit that clicking an already selected
option will disable the active effect, it improves accessibility by avoiding
automatic focus movement from the previously active option to a separate “none”
option. That focus shift could be misleading or hard to follow
for screen reader users.

Open to feedback on this decision.
2026-01-09 19:03:34 +01:00
lebaudantoine 1001783d3c ️(frontend) enhance vocalized indication of virtual background
Update the virtual background effects tooltip and ARIA label with more
descriptive and concise wording based on Sophie’s feedback. This helps all
users, especially those using assistive technologies, by improving how
each virtual background is vocalized.
2026-01-09 19:03:34 +01:00
lebaudantoine 97b5e8780c 🩹(frontend) fix minor layout issue hidding focus ring
Fix an issue where the focus visual indication was hidden due to an overly tight
layout with no padding on the background and effects toggle buttons.
2026-01-09 19:03:34 +01:00
lebaudantoine 7c7074aa99 🚸(frontend) refine effects wording
Refine the Effects title to clearly indicate it covers both background and
effects, improving clarity. Inspired by Google Meet.
2026-01-09 19:03:34 +01:00
lebaudantoine 35b3bcad63 🔧(agents) make Silero VAD optional
Allow configuring whether a VAD model runs before calling an external ASR API.
Running VAD can save API calls (and costs) when no audible sound is detected,
but comes with the trade-off of additional computational overhead.
2026-01-08 18:03:23 +01:00
lebaudantoine 137a2c7f6f 🩹(frontend) close subtitles on room disconnections
Subtitles were still visible when leaving and rejoining a meeting, even though
the backend API call to start them was not triggered again.

Introduce a hook that closes the subtitles layout on unmount, ensuring users
must explicitly click the button to restart subtitles when they rejoin a room.
2026-01-08 15:13:37 +01:00
lebaudantoine d681e25bcc 💄(frontend) adjust spacing in the recording side panels
Based on @Arnaud’s feedback, adjust the spacing between the title, details
section, and control buttons to make the layout feel more homogeneous.
2026-01-08 13:17:46 +01:00
lebaudantoine 1f1a6371b4 🚸(frontend) remove the default comma delimiter in humanized durations
The comma caused values like 1h30 to be rendered as “1 heure, 30 minutes,”
which feels awkward in most European languages.
2026-01-08 13:17:46 +01:00
Cyril bbfbb23be5 ♻️(frontend) extract tools panel focus logic into reusable hook
prepares logic reuse for consistent focus restoration across the app
2026-01-07 14:50:45 +01:00
Cyril 6e20bc1f43 ️(frontend) restore focus to trigger button when panel closes
improves keyboard navigation and accessibility consistency

Signed-off-by: Cyril <c.gromoff@gmail.com>
2026-01-07 14:50:45 +01:00
lebaudantoine fed05f2396 ️(frontend) fix jump and animation break on panel open with auto-focus
used requestAnimationFrame and preventScroll to preserve smooth transition

Signed-off-by: Cyril <c.gromoff@gmail.com>
2026-01-07 14:50:45 +01:00
lebaudantoine 865acf2838 (frontend) focus transcript and record buttons on open
move keyboard focus to transcript or recording button when the panel opens.

Signed-off-by: Cyril <c.gromoff@gmail.com>
2026-01-07 14:50:45 +01:00
lebaudantoine 6ae68013af (frontend) add SR announcements for transcript and recording
announce transcript and record events to sr to provide clear feedback

Signed-off-by: Cyril <c.gromoff@gmail.com>
2026-01-07 14:50:45 +01:00
lebaudantoine 394a1be322 (frontend) add sr-only class
add a utility class to hide content visually while keeping it available to sr.

Signed-off-by: Cyril <c.gromoff@gmail.com>
2026-01-07 14:50:45 +01:00
Cyril a71a1fd968 📝(docs) add changelog entry for visio button tooltip a11y fix
documents fix ensuring tooltip appears only on keyboard nav
2026-01-07 12:55:51 +01:00
Cyril 40af264562 🐛(frontend) remove unexpected F2 tooltip when clicking video screen
fixes accidental tooltip trigger unrelated to visio screen interaction
2026-01-07 12:44:52 +01:00
Arnaud Robin 8b2d06976e 📝(terms) update terms of service
Enhance the terms of service by adding detailed sections on
service availability, security, support management,
and monitoring of service use. This update aims to provide clearer
guidelines and responsibilities for users and the DINUM administration.
2026-01-06 22:57:04 +01:00
lebaudantoine 58313666ed 👷(ci) ignore trivy scan output temporary
CVE-2025-13601 has yet no fix. I don't want to migrate the base image
in this pull request, as it could introduce regression.

I'll open an issue to fix this CVE later on. The summary service isn't
exposed on internet, and the agent isn't used in production.
2026-01-06 19:49:23 +01:00
lebaudantoine f3c8aec189 🔧(ci) add trivy scans for summary and agent
Closes #685: add a Trivy scan to the CI build steps for Meet Summary
and Meet Agents to ensure no vulnerabilities are present before pushing images
to the registry.
2026-01-06 19:49:23 +01:00
lebaudantoine 0a0c7ba618 (summary) add dutch and german languages
Based on a request from our European partners, introduce new languages for the
transcription feature. Dutch and German are now supported, which is a great
addition.

It closes #837.

WhisperX is expected to support both languages.
2026-01-06 17:52:04 +01:00
renovate[bot] d7ad5aed05 ⬆️(dependencies) update aiohttp to v3.13.3 [SECURITY] 2026-01-06 17:00:00 +01:00
lebaudantoine 4acc9cf40d 🩹(frontend) render the NoAccessView for unprevileged users
Simplify a broken conditional check that allowed users without
the required permissions to see the control menu. The `NoAccessView`
is now shown to any user who is neither an admin nor the meeting owner.
2026-01-06 16:43:15 +01:00
lebaudantoine 13d0d3d801 📈(frontend) track metadata on recording-started events
I introduced transcript + screen recording modes but forgot
to properly track them in PostHog. Fix this issue.
2026-01-06 16:43:15 +01:00
lebaudantoine 47cd3eff74 🔖(minor) bump release to 1.2.0 2026-01-05 18:10:05 +01:00
lebaudantoine 5769203705 💄(frontend) add minor layout adjustments
Propose minor layout adjustments to ensure the DINUM version with French
copywriting does not look visually awkward due to line breaks.
2026-01-05 17:47:26 +01:00
lebaudantoine cadc186c62 🐛(backend) fix certificates volume mount path for Python 3.13
After upgrading Python to 3.13, not all development environments were
updated accordingly. This fixes the incorrect volume mount path
introduced by that upgrade.
2026-01-05 17:47:26 +01:00
lebaudantoine 5be7595533 🐛(summary) fix MinIO endpoint handling in constructor
Fix MinIO client configuration: I was incorrectly passing a full URL instead of
an endpoint, which caused errors in staging. Local development values did not
reflect the staging setup and were also out of sync with the backend.
2026-01-05 15:40:11 +01:00
lebaudantoine 0fe8d9b681 🐛(backend) fix ignore recording webhook events
Fix an unexpected behavior where filtering LiveKit webhook events sometimes
failed because the room name was not reliably extracted from the webhook data,
causing notifications to be ignored.

Configure the same filtering logic locally to avoid missing this kind of issue
in the future.
2026-01-05 13:34:55 +01:00
lebaudantoine 83654cf7c0 📌(egress) pin egress version to v1.11.0
Pin egress to the production version, which uses a more recent release than the
default chart value (1.9.0).

Using the default could have led to issues; hopefully this change avoids them.
2026-01-05 11:00:12 +01:00
lebaudantoine f6cdb1125b ♻️(backend) refactor backend recording state management
Instead of relying on the egress_started event—which fires when egress is
starting, not actually started—I now rely on egress_updated for more accurate
status updates. This is especially important for the active status, which
triggers after egress has truly joined the room. Using this avoids prematurely
stopping client-side listening to room.isRecording updates. A further
refactoring may remove reliance on room updates entirely.

The goal is to minimize handling metadata in the mediator class. egress_starting
is still used for simplicity, but egress_started could be considered in the
future.

Note: if the API to start egress hasn’t responded yet, the webhook may fail to
find the recording because it currently matches by worker ID. This is unstable.
A better approach would be to pass the database ID in the egress metadata and
recover the recording from it in the webhook.
2026-01-05 00:14:00 +01:00
lebaudantoine 2863aa832d 🔥(frontend) remove useless font block on icons
Myabd, this css property is useful only on font face, it has
no effect on materials-related classes.
2026-01-05 00:14:00 +01:00
lebaudantoine 48af2e3a5f 📝(changelog) list all the recent recording-related enhancements
Worked on a large PR (#827) and chose to consolidate all new features and
refactorings in the changelog at the end of the work instead of updating it per
commit. Not ideal—acknowledge this is bad practice.
2026-01-04 20:22:15 +01:00
lebaudantoine 8a0dfd1478 🩹(frontend) make recording statuses more accurate
Link recording statuses to the `isRecording` attribute from the room on the
client side.

After the refactor, the frontend relied only on recording statuses computed by
the backend. However, when egress is started and the backend is notified, the
recording is not actually active yet. It takes some time for the egress to join
the room and begin recording.

Enrich the frontend by combining backend statuses with the room recording state
to more accurately reflect when recording is truly active. This avoids missing
the first few seconds of audio at the beginning of a recording.
2026-01-04 20:22:15 +01:00
lebaudantoine 37a2f3985a 🛂(frontend) display transcription settings for privileged users
Only display transcription settings to room admins or owners. Showing these
controls to users without the required privileges would be misleading, since
they cannot actually configure or apply the settings.
2026-01-04 20:22:15 +01:00
lebaudantoine 39271544d7 (summary) link transcript to their downloadable recording
Link the transcription document to its related recording by adding a short
header explaining that users can download the audio file via a dedicated link.

This was a highly requested feature, as many users need to keep their audio
files.

As part of a small refactor, remove the argument length check in the metadata
analytics class. The hardcoded argument count made code evolution harder and was
easy to forget updating. Argument unwrapping remains fragile and should be
redesigned later to be more robust.

The backend is responsible for generating the download link to ensure
consistency and reliability.

I tried adding a divider, but the Markdown-to-Yjs conversion is very lossy and
almost never handles it correctly. Only about one out of ten conversions works
as expected.
2026-01-04 20:22:15 +01:00
lebaudantoine f7b45622bc 🚸(frontend) enhance recording state toast icon
Specify distinct icons in the recording state toast for each mode to provide
clearer visual feedback on what is actually happening. Remove the pulse CSS
animation, as it did not improve visual clarity and accessibility.
2026-01-04 20:22:15 +01:00
lebaudantoine f3e2bbf701 (frontend) allow user to request recording
Inspired by @ericboucher’s proposal, allow non-admin or non-owner participants
to request the start of a transcription or a recording.

All participants are notified of the request, but only the admin can actually
open the menu and start the recording.

This is a first simple and naive implementation and will be improved later.

Prefer opening the relevant recording menu for admins instead of offering a
direct quick action to start recording. With more options now tied to recording,
keeping the responsibility for starting it encapsulated within the side panel
felt cleaner.

This comes with some UX trade-offs, but it’s worth trying.

I also simplified the notification mechanism by disabling the action button for
the same duration as the notification, preventing duplicate triggers. This is
not perfect, since hovering the notification pauses its display, but it avoids
most accidental re-triggers.
2026-01-04 20:22:15 +01:00
lebaudantoine 6e1ad7fca5 🚸(frontend) introduce an icon on the login prompt for visual distinction
This will be useful when adding an alternative card to request the meeting
creator to start the recording.
2026-01-04 20:22:15 +01:00
lebaudantoine d9dbededee 🚸(frontend) enhance the visual hierarchy of the no access view
Rework the visual hierarchy of the “no access” view to align it with other
presentation modes and ensure the title order is clear and understandable for
users.
2026-01-04 20:22:15 +01:00
lebaudantoine 70403ad0d8 (frontend) handle another recording mode is active
Refactor literals in the recording status hook and introduce a new status.
Align the login prompt style with the newly introduced warning message, and
guide users by clearly indicating that the two modes are mutually exclusive.
Users are prompted to stop the other mode before starting a new one.

This situation should happen less often now that checkboxes allow users to start
transcription and recording together. Hopefully, the UX is clear enough.

The growing number of props passed to the controls buttons may become an issue
and will likely require refactoring later.
2026-01-04 20:22:15 +01:00
lebaudantoine 9d69fe4f4f ♻️(frontend) introduce a recording mutation hook
Mutualize and factorize the recording API error modal in a single place, and
extract all recording mutations into a dedicated hook exposing both start and
stop actions.

This hook is responsible for interacting with the API error dialog when needed.
Previously, this logic was duplicated across each side panel; centralizing it
clarifies responsibilities and reduces duplication.
2026-01-04 20:22:15 +01:00
lebaudantoine 08f281e778 ♻️(frontend) introduce a recording provider with clear responsibilities
This component is now extensible and way easier to understand.

Previously, the recording state toast was implicitly acting as a provider,
making its core responsibility unclear for developers. Its role is not to
inject all recording-related elements into the videoconference DOM, but to
expose a clean recording state toast reflecting the current recording status.

This commit also fixes the limit-reached modal that was no longer appearing
after the refactor, ensures the modal is always rendered,
and removes unused React ARIA labels.

In the original code, the limit reached dialog was wrongly rendered
only when the recording state toast was null.
It was a bug in the implementation. Fix it.
2026-01-04 20:22:15 +01:00
lebaudantoine da3dfedcbc (frontend) update recording metadata alongside recording state changes
Following the previous commit, refactor the frontend to rely on room metadata to
track which recording is running and update the interface accordingly. This
implementation is not fully functional yet.

The limit-reached dialog triggering mechanism is currently broken and will be
fixed in upcoming commits. I also simplified the interface lifecycle, but some
edge cases are not yet handled—for example, transcription controls should be
disabled when a screen recording is started. This will be improved soon.

Controls were extracted into a reusable component using early returns. This
makes the logic easier to read, but slightly increases the overall complexity of
the recording side panel component.

Relying on literals to manage recording statuses is quite poor, feel free to
enhance this part.
2026-01-04 20:22:15 +01:00
lebaudantoine 16badde82d 🚧(backend) update recording metadata alongside recording state changes
Previously, this was handled manually by the client, sending notifications to
other participants and keeping the recording state only in memory. There was no
shared or persisted state, so leaving and rejoining a meeting lost this
information. Delegating this responsibility solely to the client was a poor
choice.

The backend now owns this responsibility and relies on LiveKit webhooks to keep
room metadata in sync with the egress lifecycle.

This also reveals that the room.isRecording attribute does not update as fast
as the egress stop event, which is unexpected and should be investigated
further.

This will make state management working when several room’s owner will be in
the same meeting, which is expected to arrive any time soon.
2026-01-04 20:22:15 +01:00
lebaudantoine 57a7523cc4 ♻️(frontend) extract recording row layout in reusable component
Now that screen recording and transcription share the same UI presentation,
extract the row logic into a reusable component to avoid code duplication and
improve code maintainability.
2026-01-04 20:22:15 +01:00
lebaudantoine 398ef1ae8a ♻️(frontend) encapsulate transcript language logic in a hook
Provide a clear interface to handle transcription language selection and
behavior, reducing code duplication across the codebase.
2026-01-04 20:22:15 +01:00
lebaudantoine f7d463f380 ♻️(frontend) encapsulate recording maximum duration handling
Centralize the logic to compute, internationalize, and present the maximum
recording duration in a human-readable way, reducing duplication across the
codebase.
2026-01-04 20:22:15 +01:00
lebaudantoine 5e1705d259 🚸(frontend) align screen recording side panel ux
Refactor the screen recording side panel to align with the transcription UX,
ensuring a more consistent and homogeneous user experience.

This commit also introduces a checkbox allowing users to request transcription
of the screen recording, which is one of the most requested features.

The side panel will be enriched with more information soon, especially once
Fichier is integrated for storing recordings, so the destination can be made
explicit.

More recording settings (layout, quality, etc.) will be introduced in upcoming
commits.
2026-01-04 20:22:15 +01:00
lebaudantoine 236245740f ♻️(frontend) refactor recording side panels to reduce code duplication
A lot of duplication existed, so I started factorizing components
now that a proper user experience is clearer.

Without over-abstracting, the first step introduces a reusable
“no access” view with configurable message and image.

This is just the beginning: props passing is still not ideal, but
it’s sufficient to merge and significantly reduce duplication.
2026-01-04 20:22:15 +01:00
lebaudantoine 9ebf2f277b 🔊(summarize) log language with more details
Enhance transcription language logging by explicitly indicating
when no language is provided and the code falls back to automatic
detection mode.
2026-01-04 20:22:15 +01:00
lebaudantoine 049a9079c4 (frontend) chose transcription’s language in settings
Add a key feature allowing users to choose the language
of their transcription via a setting.

The default value is set to French, the most commonly used
language across our user base.

Users can still select English or “Automatic,” which re-enables automatic
language detection if no default is configured on the microservice.
2026-01-04 20:22:15 +01:00
lebaudantoine 19f8c96e9d (frontend) allow parametrization of the transcrip document destination
Not all self-hosted instances will configure this setting, so a default text is
shown when the destination is unknown.

This is important to let users quickly click the link and understand which
platform is used to handle the transcription documents.
2026-01-04 20:22:15 +01:00
lebaudantoine 857b4bd1f1 (summary) handle video files more efficiently
Video files are heavy recording files, sometimes several hours long.

Previously, recordings were naively submitted to the Whisper API without
chunking, resulting in very large requests that could take a long time
to process. Video files are much larger than audio-only files, which
could cause performance issues during upload.

Introduce an extra step to extract the audio component from MP4 files,
producing a lighter audio-only file (to be confirmed). No re-encoding
is done, just a minimal FFmpeg extraction based on community guidance,
since I’m not an FFmpeg expert.

This feature is experimental and may introduce regressions, especially
if audio quality or sampling is impacted, which could reduce Whisper’s
accuracy. Early tests with the ASR model worked, but it has not been
tested on long recordings (e.g., 3-hour meetings),
which some users have.
2026-01-04 20:22:15 +01:00
lebaudantoine 309c532811 (backend) submit screen recordings to the summary microservice
Screen recording are MP4 files containing video)

The current approach is suboptimal: the microservice will later be updated to
extract audio paths from video, which can be heavy to send to the Whisper
service.

This implementation is straightforward, but the notification service is now
handling many responsibilities through conditional logic. A refactor with a
more configurable approach (mapping attributes to processing steps via
settings) would be cleaner and easier to maintain.
For now, this works; further improvements can come later.

I follow the KISS principle, and try to make this new feature implemented
with the lesser impact on the codebase. This isn’t perfect.
2026-01-04 20:22:15 +01:00
lebaudantoine 4e5032a7a4 ♻️(summary) enhance file handling in the Celery worker
The previous code lacked proper encapsulation, resulting in an overly complex
worker. While the initial naive approach was great for bootstrapping the
feature, the refactor introduces more maturity with dedicated service classes
that have clear, single responsibilities.

During the extraction to services, several minor issues were fixed:

1) Properly closing the MinIO response.

2) Enhanced validation of object filenames and extensions to ensure
correct file handling.

3) Introduced a context manager to automatically clean up temporary
local files, removing reliance on developers.

4) Slightly improved logging and naming for clarity.

5) Dynamic temporary file extension handling when it was previously
always an hardcoded .ogg file, even when it was not the case.
2026-01-04 20:22:15 +01:00
lebaudantoine 4cb6320b83 (summary) add a language parameter for transcription
Pass recording options’ language to the summary service, allowing users to
personalize the recording language.

This is important because automatic language detection often fails, causing
empty transcriptions or 5xx errors from the Whisper API. Users then do not
receive their transcriptions, which leads to frustration. For most of our
userbase, meetings are in French, and automatic detection is unreliable.

Support for language parameterization in the Whisper API has existed for some
time; only the frontend and backend integration were missing.

I did not force French as the default, since a minority of users hold English or
other European meetings. A proper settings tab to configure this value will be
introduced later.
2026-01-04 20:22:15 +01:00
lebaudantoine 587a5bc574 (frontend) allow starting both a recording and a transcription
Major user feature request: allow starting recording and transcription
simultaneously. Inspired by Google Meet UX, add a subtle checkbox letting users
start a recording alongside transcription.

The backend support for this feature is not yet implemented and will come in
upcoming commits, I can only pass the options to the API. The update of the
notification service will be handled later.
We’re half way with a functional feature.

This is not enabled by default because screen recording is resource-intensive. I
prefer users opt in rather than making it their default choice until feature
usage and performance stabilize.
2026-01-04 20:22:15 +01:00
lebaudantoine 0d8c76cd03 (backend) add a flexible JSON field to store recording options
Using a JSON field allows iterating on recording data without running a new
migration each time additional options or metadata need to be tracked.

This comes with trade-offs, notably weaker data validation and less clarity on
which data can be stored alongside a recording.

In the long run, this JSON field can be refactored into dedicated columns once
the feature and data model have stabilized.
2026-01-04 20:22:15 +01:00
lebaudantoine b19ac7f82b 🚸(frontend) rework the transcription side panel
Inspired by proprietary solutions, add clearer details on how transcription
works and what users can expect from the feature. This new presentation is much
simpler to read, parse, and understand than the previous large block of text
that users were not reading at all.

Using icons helps users quickly understand where the transcription is sent, how
they are notified, and which meeting language is used.

Some information is currently hardcoded and will be parameterized in upcoming
commits. This work is ongoing.
2026-01-04 20:22:15 +01:00
lebaudantoine d3e6af6f82 🚸(frontend) rework the meeting tools side panel UX
Explicitly explain that transcription is reserved for public servants. Remove
the temporary beta form: the feature is now available to all public servants,
with restrictions based on domain. Make white-labeling rules explicit and
clarify who to contact for access.

The beta form created frustration, with users registering and never hearing
back from the team.

Improve guidance when a user may be the meeting host but is not logged in, and
therefore cannot activate recording. Add a clear hint and a quick action to log
in. This decision is based on frequent support requests where users could not
understand why recording was unavailable while they were simply not logged in.
2026-01-04 20:22:15 +01:00
lebaudantoine 2fbb476b02 🔥(frontend) remove beta tag on recording feature
Initially, I thought presenting the recording feature as a beta would clearly
signal that it was still under construction and being improved. In practice, it
sent a negative signal to users, reduced trust, and still generated many
questions for the support team.

Without clearly explaining why the feature was in beta or what was coming next,
the label only added confusion. I chose to simplify the interface and remove the
beta indication altogether.
2026-01-04 20:22:15 +01:00
lebaudantoine 1b2139a9ff 💄(frontend) refactor meeting tools presentation
Follow Robin’s suggestion on the meeting tool layout presentation. The result
does not yet exactly match the Figma design, and I took some freedom to stay
closer to a Google Meet–like layout.

In the initial approach, it was hard to understand that the full option was
clickable. Adding a light background improves discoverability and usability.
2026-01-04 20:22:15 +01:00
lebaudantoine 54e47e33a9 🔧(frontend) configure Material Icons and Symbols
Robin chose to adopt Material Design icons, inspired by NVasse’s commit on
Fichier. This sets up the required CSS to easily use Material Icons throughout
the application.

Eventually, all icons in the app will be replaced with Material ones. For now,
the setup is only used in the recording UI refactor.
2026-01-04 20:22:15 +01:00
lebaudantoine 20b99cf2ad 🚸(frontend) simplify recording wording
Simplify wording and presentation of the recording feature heading,
using a more concise and familiar product-style language inspired by
well-known proprietary solutions.
2026-01-04 20:22:15 +01:00
lebaudantoine db75b0eae9 📱(frontend) solve recording responsiveness issue
Many public servants use PCs with unusual screen resolutions. The screen
height is often quite small, which caused responsiveness issues on the
vertical axis.

When opening the side panel, they could not see the button to start the
recording. I improved the vertical responsiveness to address this issue and
reduce support requests such as “I cannot see the button”.

Users typically do not think about scrolling inside the side panel, so the
layout now better fits constrained screen heights.
2026-01-04 20:22:15 +01:00
lebaudantoine 5163f849e4 ♻️(frontend) enhance feedback banner copywritting
Eliminate the perception of being 'under development,'
which can undermine trust with potential users.

Focus on creating a more confident and reassuring experience.
2025-12-29 12:29:22 +01:00
lebaudantoine 4345711771 (frontend) remove the beta badge
Product is out of beta since the 15th of December.
2025-12-29 12:29:22 +01:00
lebaudantoine 7c690c369e ♻️(agents) remove deprecation warning for RoomInput/OutputOptions
Follow LiveKit's recommendations.
2025-12-28 22:34:38 +01:00
lebaudantoine ef09629566 ⬆️(agent) upgrade temporary livekit-agent plugin for kyutai
0.0.5 was ignoring the API key environment variable. I fixed it.
2025-12-28 22:34:38 +01:00
lebaudantoine cff1dbf39e ♻️(agent) simplify Deepgram config and support Kyutai
The previous attempt to make the Deepgram configuration extensible
introduced unnecessary complexity for a very limited use case and
made it harder to add new STT backends.

Refactor to a deliberately simple and explicit design with minimal
cognitive overhead. Configuration is now fully driven by environment
variables and provides enough flexibility for ops to select and
parameterize the STT backend.
2025-12-28 21:14:20 +01:00
lebaudantoine b466515306 (agent) add a temporary livekit-agent plugin for kyutai
Until a Pull Request is merged with our changes on livekit-agent
to support Kyutai API, we will use a custom and hacky python
library made from Arnaud's researches and published on an
unofficial pypi project page.

Everything is quite "draft" but it allows us to deploy and test
in real situation the work from Arnaud.
2025-12-28 21:14:20 +01:00
lebaudantoine c678e9420e ⬆️(agent) upgrade livekit-agent related dependencies
Our custom LaSuite Kyutai plugin requires livekit-agent above 1.3.3.
2025-12-28 21:14:20 +01:00
lebaudantoine 3af115dafb 🐛(agent) restore missing system deps in Docker image
Some system dependencies were unexpectedly missing, causing the
LiveKit agent framework to fail at runtime.

Install the required dependencies based on runtime error logs.
This fixes Docker image failures in the remote (staging) environment.
2025-12-28 21:14:20 +01:00
lebaudantoine 0daa6d0432 🔖(release) release 1.1.0
- enable user provisioning through the external viewset
- add LLM observability on the summary service
2025-12-22 11:23:28 +01:00
lebaudantoine 493d7b96f1 📝(docs) add missing trailing slash
A trailing slash was missing in the documentation.
Spotted by T. Lemeur when integrating the API.
2025-12-22 09:57:34 +01:00
lebaudantoine c2c478c367 🩹(backend) remove environment prefix from recently introduced settings
The prefix was unintentionally added and wasn’t caught during review.
This change corrects it.
2025-12-21 16:27:11 +01:00
lebaudantoine b5895ccba0 🩹(summary) fix missing f-string
Spotted by code rabbit. Missing F-string was leading
to an unexpected behavior.
2025-12-19 14:29:56 +01:00
lebaudantoine aff87d4953 (summary) add Langfuse observability for LLM API calls
Implement Langfuse tracing integration for LLM service calls to capture
prompts, responses, latency, token usage, and errors, enabling
comprehensive monitoring and debugging of AI model interactions
for performance analysis and cost optimization.
2025-12-19 14:29:56 +01:00
lebaudantoine c81ef38005 ♻️(summary) extract LLMService class into dedicated module
Move LLMService class from existing file into separate dedicated
module to improve code organization.
2025-12-19 14:29:56 +01:00
lebaudantoine 4256eb403d 🔒️(summary) refactor configuration secrets to use Pydantic SecretStr
Replace plain string fields with Pydantic SecretStr class for all
sensitive configuration values in FastAPI settings to prevent accidental
exposure in logs, error messages, or debugging output, following
security best practices for credential handling.
2025-12-19 14:29:56 +01:00
lebaudantoine 43f3e4691b (summmary) add Langfuse to summary service dependencies
Install Langfuse observability client in summary service
to enable LLM tracing, monitoring, and debugging capabilities
for AI-powered summarization workflows,
improving visibility into model performance and behavior.
2025-12-19 14:29:56 +01:00
lebaudantoine 10aac93c36 📝(backend) improve user provisioning documentation
try to make explicit all implicit implementation's details
2025-12-19 13:41:37 +01:00
lebaudantoine 4e6bc157b0 ♻️(backend) standardize error response format in token endpoint
Align error response with the pattern used at other places of the codebase.
2025-12-19 13:41:37 +01:00
lebaudantoine fe83c5fa07 (backend) add unit tests for user provisioning via external API
Add test coverage for provisional user creation through the external API,
including creating users with email-only (no sub)
2025-12-19 13:41:37 +01:00
lebaudantoine 827014c952 ♻️(backend) explicitly enforce sub field immutability
Add OIDC_USER_SUB_FIELD_IMMUTABLE setting to our config and enforce
it in the user viewset. Previously relied on implicit Django
LaSuite defaults.

Makes the sub mutability constraint explicit and ensures it's enforced
at the application level, critical for provisional users where sub is
assigned on first login.
2025-12-19 13:41:37 +01:00
lebaudantoine 9523f52546 📝(docs) clarify sub as optional to support email-only user provisioning
Update the sub field documentation to explicitly reflect its optional nature.
Originally intended to be mandatory, sub became optional due to a code issue.
This change acknowledges and formalizes that behavior as intentional.

The optional sub enables external API integrations to provision users with
only an email address. Full identity (sub) is assigned on first login,
allowing third-party platforms to create users before they authenticate.
2025-12-19 13:41:37 +01:00
lebaudantoine 8348a55f7e (backend) enable user creation via email for external integrations
Allow external platforms using the public API to create provisional users
with email-only identification when the user doesn't yet exist in our
system. This removes a key friction point blocking third-party integrations
from fully provisioning access on behalf of new users.

Provisional users are created with email as the primary identifier. Full
identity reconciliation (sub assignment) occurs on first login, ensuring
reliable user identification is eventually established.

While email-only user creation is not ideal from an identity perspective,
it provides a pragmatic path to unlock integrations and accelerate adoption
through external platforms that are increasingly driving our videoconference
tool's growth.
2025-12-19 13:41:37 +01:00
lebaudantoine a4b76433ab 🧑‍💻(release) introduce a release helper tool
Discussed at lunch with our CTO, enhance tooling
around release preparation. Naive bash script generated
using Claude. Please feel free to enhance it.
2025-12-17 19:55:24 +01:00
lebaudantoine ae863418cd 📝(changelog) reorganize sections to match Keep a Changelog convention
Reorder CHANGELOG section headings to follow standard Keep a Changelog format
(Added, Changed, Deprecated, Removed, Fixed, Security) for consistent structure
that users expect when reviewing release notes.
2025-12-17 18:41:45 +01:00
lebaudantoine dcdae26610 🔖(release) release 1.0.1
Patch several accessibility issues.
2025-12-17 17:36:01 +01:00
Cyril 90c0442d35 (frontend) fix focus scroll jump during side panel animation
preventScroll avoids layout shift that broke the slide-in chat animation

Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-17 16:13:25 +01:00
Cyril 9093371d25 (frontend) restore focus on chat close
restore keyboard focus to the triggering element when the chat panel closes.

Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-17 16:13:24 +01:00
Cyril 1d45d3aa7c (frontend) focus chat input on panel open
move keyboard focus to the message input when the chat panel opens.

Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-17 16:12:44 +01:00
Cyril fcb89c520e ️(frontend) fix heading level in modal to maintain semantic hierarchy
replaced h3 with h2 for accessibility and proper document structure
2025-12-17 16:00:35 +01:00
Cyril 309ce0989d ️(frontend) indicate external link opens in new window on feedback
added title attribute to clarify link behavior for screen reader users
2025-12-17 15:42:30 +01:00
Cyril a6c154374f ️(frontend) change ptt keybinding from space to v
ptt now uses v key to avoid accidental activation when typing
2025-12-17 15:18:46 +01:00
lebaudantoine b0e27b38e2 🔒️(backend) avoid serializing rooms's pin code when restricted
Prevent anonymous users waiting in the lobby, or attacker
to discover the room pin code, that would allow them to join a room.
2025-12-17 10:05:23 +01:00
Cyril 9bdc68f9c9 (frontend) create reusable shortcut tooltip component
extracted tooltip into a component to unify style and ease reuse across ui

Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-16 09:41:43 +01:00
Cyril 4545e9fa1e 💄(frontend) update shortcut tooltip position and style for consistency
moved tooltip from left to right to avoid overlap with recording indicator
2025-12-16 09:41:43 +01:00
Cyril 3f1edbf134 ️(frontend) fix SR texts/translations to avoid double announcement
Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-16 09:41:42 +01:00
Cyril 4f2764eef4 ️(frontend) add tooltip and sr hint for f2 shortcut to bottom toolbar
helps keyboard and sr users discover the f2 shortcut for toolbar access

Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-11 14:57:51 +01:00
Cyril b11cc6e9da ️(frontend) update blur and focus translations for participants
adds fr/en/de/nl translations for blur and focus accessibility labels

Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-11 14:57:40 +01:00
Cyril 0a7eb97c90 ️(frontend) hide avatar initials from sr to avoid duplicate names
prevents screen readers from announcing participant names twice

Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-11 14:57:26 +01:00
Cyril db188075af ️(frontend) improve meeting a11y: blur, focus, hover, sr announcements
enhances keyboard nav and screen reader support for meeting interface

Signed-off-by: Cyril <c.gromoff@gmail.com>
2025-12-11 14:56:58 +01:00
lebaudantoine 98e568d63c 🔖(major) release 1.0.0
Wouhou, finally. Important milestone, as our software is used by
thousand of users in production.
2025-12-11 00:18:59 +01:00
lebaudantoine 97e1f7f53f 🔥(changelog) remove outdated unreleased entries from CHANGELOG
Clean up CHANGELOG by removing old unreleased changes that are
no longer relevant or superseded by subsequent work.
2025-12-11 00:18:59 +01:00
lebaudantoine 6022809888 👷(ci) add CI check for CHANGELOG updates in pull requests
Implement automated CI validation ensuring pull request authors
update CHANGELOG with their changes, preventing undocumented
changes from merging and maintaining accurate release
documentation for users and maintainers.
2025-12-11 00:18:59 +01:00
lebaudantoine d241de6af1 🔖(minor) bump release to 0.1.43
- upgrade dependencies for security reason
- handle hallucination in transcription
- minor frontend fixes
- support resource server authentification
2025-12-10 23:16:22 +01:00
Martin Guitteny ad494f5de5 ♻️(summary) refactor transcript formatting into unified handler class
Consolidate scattered transcript formatting functions into single
cohesive class encapsulating all transcript processing logic
for better maintainability and clearer separation of concerns.

Add transcript cleaning step to remove spurious recognition artifacts
like randomly predicted "Vap'n'Roll Thierry" phrases that appear
without corresponding audio, improving transcript quality
by filtering model hallucinations.
2025-12-10 20:40:23 +01:00
lebaudantoine fba879e739 (backend) allow prefixing resource server scopes
When declaring scopes with our OIDC provider, they require us to prefix
each scope with our application name. This is to prevent reserving generic
scopes like rooms:list for only our app, as they manage a large federation.

I’m proposing a workaround where, if a resource server prefix is detected in
the scope, it’s stripped out. This solution is simple and sufficient
in my opinion.

Since the scopes are defined in the database, I don’t want to update
them directly. Additionally, each self-hosted instance may have a different
application name, so the prefix should be configurable via a Django setting.
2025-12-10 19:47:36 +01:00
renovate[bot] cac5595a91 ⬆️(dependencies) update vite to v7.0.8 [SECURITY] 2025-12-10 17:25:55 +01:00
lebaudantoine 78e5c72310 🐛(frontend) prevent invite dialog to show up on mobile
While creating a meeting on mobile, the dialog was opening,
and when its width exceeds the mobile width, users are unable
to close the dialog.

Prevent the dialog opening on mobile as a hot fix.
2025-12-10 12:52:41 +01:00
lebaudantoine 2ab31189f4 🐛(frontend) fix unclickable fullscreen warning buttons
Adjust z-index values to restore button interactivity broken by previous
z-index changes in commit 53e68b7, ensuring fullscreen warning dismiss
controls remain accessible to users instead of being blocked
by overlay layering.
2025-12-10 12:48:24 +01:00
lebaudantoine bb4a863f8d ⬆️(frontend) manually upgrade Alpine dependencies to fix libpng vul
Manually update libexpat to 1.6.53-r0 in Alpine 3.21.3 base image
to address CVE-2025-64720, CVE-2025-65018,
CVE-2025-66293 high-severity vulnerability until newer Alpine base image
becomes available, ensuring Trivy security scans pass.
2025-12-10 12:43:19 +01:00
renovate[bot] 0241f67787 ⬆️(dependencies) update django to v5.2.9 [SECURITY] 2025-12-09 22:18:27 +01:00
lebaudantoine 908bbb828a 📝(backend) add resource server quickstart documentation
Create initial resource server integration documentation based on existing
service account documentation structure to help developers understand
authentication flow and implementation requirements for external services
consuming Meet's protected resources.
2025-11-24 19:50:12 +01:00
lebaudantoine c7f5dabbad (backend) integrate ResourceServerAuthentication on the external api
Upgrade django-lasuite to v0.0.19 to benefit from the latest resource server
authentication backend. Thanks @qbey for your work. For my needs, @qbey
refactored the class in #46 on django-lasuite.

Integrate ResourceServerAuthentication in the relevant viewset. The integration
is straightforward since most heavy lifting was done in the external-api viewset
when introducing the service account.

Slightly modify the existing service account authentication backend to defer to
ResourceServerAuthentication if a token is not recognized.

Override user provisioning behavior in ResourceServerBackend: now, a user is
automatically created if missing, based on the 'sub' claim (email is not yet
present in the introspection response). Note: shared/common implementation
currently only retrieves users, failing if the user does not exist.
2025-11-24 18:23:38 +01:00
lebaudantoine a642c6d9a2 🔧(backend) add Docker network for shared Keycloak OIDC authentication
Define Docker network enabling external service providers to share Keycloak
instance with local development stack, supporting OIDC authentication flow
where services obtain tokens from shared Keycloak then pass to Meet
for introspection and validation.

Prepares Meet infrastructure for multi-service authentication architecture
though external service provider Docker Compose integration changes remain
in separate repository.
2025-11-24 18:23:38 +01:00
lebaudantoine a6dc12d91c 🩹(frontend) avoid unnecessary redirection while authenticating
A manually constructed authentication URL didn’t match the actual endpoint
address, causing the Django backend to issue a 301 redirect to the correct URL.

This wasn’t a problem for regular users at first, but once a client integrating
through a virtual browser came on board, it became significant. The 301 redirect
was disrupting the virtual browser’s cookie/cache system, which in turn broke
the authentication flow.

This change aims to resolve the issue, although it’s not yet certain that
it will fully address their problem.
2025-11-20 10:10:03 +01:00
lebaudantoine 307987d94d 🌐(backend) compile missing translations
I forgot to compile newly added backend translations.
Fix it.
2025-11-15 16:31:07 +01:00
lebaudantoine d7ebdbf401 🔖(minor) bump release to 0.1.42
- add admin action to retry a recording notification to external services
- log more Celery tasks' parameters
- add multilingual support for real-time subtitles
- update backend dependencies
2025-11-14 18:23:22 +01:00
lebaudantoine dad396273c ️(frontend) hide decorative icons from screen readers per issue #730
Mark unnecessary decorative icons as aria-hidden following feedback
from @cyberbaloo to eliminate redundant screen reader announcements
that create noisy and annoying experience for users relying on
assistive technologies.
2025-11-13 18:23:49 +01:00
lebaudantoine 555daedeba 🌐(backend) update translation files with newly introduced strings
Regenerate backend translation files to include missing translations for newly
added translatable strings in recent code changes, ensuring complete
internationalization coverage across all supported languages.
2025-11-13 18:02:49 +01:00
lebaudantoine 0d09d1df08 (backend) fix auth unit test with django-lasuite 0.1.16 update
django-lasuite 0.1.16 changed the user update mechanism from .update()
to .save(), which triggers Django's constraint validation. This causes
an additional SELECT query to verify 'sub' field uniqueness on every
user update, despite 'sub' being immutable in our auth flow.

This commit update the test to make them pass again.
2025-11-13 16:26:17 +01:00
lebaudantoine a40af726b6 📌(backend) pin pylint to 3.x to resolve compatibility conflict
Restrict pylint version to 3.x in renovate configuration because
pylint-django 2.6.1 requires pylint<4, preventing automatic upgrades
to pylint 4.x that would create unresolvable dependency conflicts
until pylint-django releases compatible version.
2025-11-13 16:26:17 +01:00
renovate[bot] f8a37e55b1 ⬆️(dependencies) update python dependencies 2025-11-13 16:26:17 +01:00
lebaudantoine 3baec0a863 ⬆️(backend) upgrade brotli to 1.2.0 to fix CVE-2025-6176
Update brotli compression library to version 1.2.0 addressing
CVE-2025-6176 security vulnerability to maintain secure
compression functionality and pass security scans.
2025-11-13 10:28:10 +01:00
lebaudantoine 5b6ed6bbf0 ⬆️(backend) upgrade Django to 5.2.8 to fix security vulnerabilities
Update Django from previous version to 5.2.8 addressing CVE-2025-64459
and CVE-2025-64458 security vulnerabilities to maintain secure
application infrastructure and pass security audits.
2025-11-13 10:28:10 +01:00
anonymous candidate aea01636cf 👷(ci) use variables in pipeline for docker registry
Introduce new variables for the docker registry where to push docker images on forks:
- DOCKER_CONTAINER_REGISTRY_HOSTNAME for the docker registry hostname, with default value "docker.io"
- DOCKER_CONTAINER_REGISTRY_NAMESPACE for the docker registry namespace, with default value "lasuite"
2025-11-13 09:43:16 +01:00
unteem e4c2b42e4a 📝(self-hosted) add documentation for self-hosting on docker compose
It describes the minimalist LaSuite Meet instance, with the simple
feature of having a room conference.
2025-11-13 09:38:47 +01:00
unteem 36ba0f9c8e 📝(self-hosted) reorganize doc for new installation exmaples
We will introduce in the next commits the compose set-up that also
require examples values/config files. Thus, re-organize the kube ones
to  dedicated folder, to make the files organisation extensible.
2025-11-13 09:38:47 +01:00
Ghislain LE MEUR 2d6fe6ee7d 🔖(helm) release chart 0.0.15
This release adds support for injecting custom Kubernetes
resources through the extraManifests parameter.

New features:
- Add extraManifests support for deploying custom resources
- Support multiple input formats (list, map, raw YAML strings)
- Enable Helm template variables in injected manifests
2025-11-12 14:38:20 +01:00
Ghislain LE MEUR e2fcf7dd2c (helm) add extraManifests support for custom resources
Add ability to inject custom Kubernetes manifests through the
values.yaml file. This allows users to deploy additional
resources (Deployments, Services, ConfigMaps, etc.) without
modifying the chart templates.

The template supports multiple input formats: list of objects,
map of named objects, and raw YAML strings, providing maximum
flexibility for users.

- Create templates/extra-objects.yaml with flexible rendering
- Add extraManifests parameter in values.yaml with documentation
- Support Helm template variables in injected manifests
- Handle list, map, and string YAML formats automatically
2025-11-12 14:38:20 +01:00
Ghislain LE MEUR 9f9cef7e2a (agents) add multilingual support for real-time subtitles
Add dynamic configuration for Deepgram STT via environment variables,
enabling multilingual real-time subtitles with automatic language
detection.

Changes:
- Add DEEPGRAM_STT_* environment variables pattern for configuration
- Implement _build_deepgram_stt_kwargs() to dynamically build STT
  parameters from environment variables
- Add whitelist of supported parameters (model, language) for LiveKit
  Deepgram plugin
- Log warnings for unsupported parameters (diarize, smart_format, etc)
- Set default configuration: model=nova-3, language=multi
- Document supported parameters in Helm values.yaml

Configuration:
- DEEPGRAM_STT_MODEL: Deepgram model (default: nova-3)
- DEEPGRAM_STT_LANGUAGE: Language or 'multi' for automatic detection
  of 10 languages (en, es, fr, de, hi, ru, pt, ja, it, nl)

Note: Advanced features like diarization and smart_format are not
supported by the LiveKit Deepgram plugin in streaming mode.
2025-11-12 11:45:08 +01:00
lebaudantoine b403ac56bf 🚨(summary) disable linter warning too many statements
summarize_transcribe_v2 as now slightly too many statements,
ignore it for now, but I'll reorganize the code asap.
2025-10-23 06:39:12 +02:00
lebaudantoine baf378d53d (backend) add the owner column to the Room Admin view
Enable administrators to easily identify the owners of a room
when possible. Save one precious click and time.
2025-10-23 06:39:12 +02:00
lebaudantoine 990507e3c7 🔊(summary) increase transcription Celery task logging verbosity
Add detailed logging for owner ID, recording metadata, and
processing context in transcription tasks to improve debugging
capabilities.

It was especially important to get the created document id,
so when having trouble with the docs API, I could share
with them the newly created documents being impacted.
2025-10-23 06:39:12 +02:00
lebaudantoine 6cd54f7e1e 🐛(backend) catch all request exceptions in summary service integration
Replace narrow HTTPError handling with broad RequestException
catch to prevent crashes from network failures (ConnectionError),
timeouts (30s exceeded), SSL/TLS errors, and other request failures
that previously caused unhandled exceptions.

Ensures consistent False return and proper logging for all network-related
failures instead of crashing application when summary service
communication encounters infrastructure issues beyond HTTP errors.
2025-10-23 06:39:12 +02:00
lebaudantoine 315d48a501 (backend) add recording mode column to the list display
While helping users, it was such a pain to determine quickly which recording
was indeed a transcription or a video recording.

Added the column to help me, and support team.
The recording / transcription is the most unstable part of the project.
2025-10-23 06:39:12 +02:00
lebaudantoine 2f7b56f918 (backend) add admin action to manually retrigger notifications
Enable administrators to manually retrigger external service notifications
from Django admin for failed or missed notification scenarios,
providing operational control over notification delivery.
2025-10-23 06:39:12 +02:00
lebaudantoine 53e68b7780 🐛(frontend) remove excessive z-index from screenshare warning overlay
Remove 1000 z-index from screenshare warning that was
causing conflicts with reaction menu and reaction displays,
retaining only necessary layering to hide participant
metadata underneath.
2025-10-22 12:00:40 +02:00
lebaudantoine 10eda5c2ea 🔖(minor) bump release to 0.1.41
- fix transcription observability
- introduce auto idle disconnection
2025-10-22 11:04:04 +02:00
lebaudantoine ba3b3fe0ba (frontend) add localStorage persistence for user preference settings
Persist user preference choices across sessions using localStorage
following notification store pattern, eliminating need to reconfigure
disabled features on every meeting join and respecting user's
long-term preference decisions.
2025-10-22 10:04:47 +02:00
lebaudantoine 0c3bcd81c9 ♻️(frontend) refactor notification preferences to use Field switch
Adopt unified switch component pattern for notification preferences to
enable future addition of descriptive text per notification type,
improving consistency and providing clearer explanation capability
for notification behaviors.
2025-10-22 10:04:47 +02:00
lebaudantoine dbc66c2f07 (frontend) add user setting to disable idle disconnect feature
Allow users to opt-out of idle participant disconnection despite
default enforcement, trusting power users who modify this setting
won't forget to disconnect, though accepting risk they may block
maintenance configuration updates.
2025-10-22 10:04:47 +02:00
lebaudantoine 39be4697b0 💄(frontend) add right margin to switch description for better spacing
Add margin between switch description text and toggle button to
improve visual breathing room and prevent text from appearing
cramped against interactive control element.
2025-10-22 10:04:47 +02:00
lebaudantoine 2443fa63a5 (frontend) add idle disconnect warning dialog for LiveKit maintenance
Introduce pop-in alerting participants of automatic 2-minute idle
disconnect to enable LiveKit node configuration updates during
maintenance windows, preventing forgotten tabs from blocking
overnight production updates following patterns
from proprietary videoconference solutions.
2025-10-22 10:04:47 +02:00
lebaudantoine 214dc87b1f (frontend) add narrow "alert" dialog mode for concise messages
Introduce new narrow-width alert dialog variant to improve
readability of short messages by preventing excessively
long line lengths that occur when brief alerts use
standard dialog widths.
2025-10-22 10:04:47 +02:00
lebaudantoine 3dc23be101 (backend) add configuration for idle disconnect timeout
Expose idle disconnect timeout as configurable parameter accepting None value
to disable feature entirely, providing emergency killswitch for buggy behavior
without redeployment, following other frontend configuration patterns.
2025-10-22 10:04:47 +02:00
lebaudantoine 6b5e8081bc 🐛(celery) fix metadata task_args order broken by signal sender argument
Restore correct task_args ordering in metadata manager after commit f0939b6f
added sender argument to Celery signals for transcription task scoping,
unexpectedly shifting positional arguments and breaking metadata creation.

Issue went undetected due to missing staging analytics deployment, silently
losing production observability on microservice without blocking transcription
job execution, highlighting need for staging analytics activation.
2025-10-22 07:17:00 +02:00
lebaudantoine df671ea994 🐛(frontend) posthog-cli 0.5.0 release introduced breaking changes
Posthog-cli version wasn't pinned.
Please check issue #39846, which describe our issue, starting
0.5.0, the cli needs an API token and a Project ID.

Pin to the last stable version we used 0.4.8, and wait a bit
they already released a 0.5.1 that mitigate some of the breaking
change.

I would wait the 0.5.x to be stable and battle tested by other
developpers before switching.

Also as I consider switching the Error tracking to sentry.
2025-10-22 05:48:06 +02:00
lebaudantoine 06a5b9b17e 🩹(doc) fix wrong endpoint path
Applications to application in the application/token endpoint.
Spotted by external contributor.
2025-10-22 05:07:02 +02:00
Ghislain LE MEUR 59d4c2583b 🐛(auth) fix LiveKit token authentication field mismatch
Fixes "Invalid LiveKit token" errors caused by field mismatch between
token generation and authentication lookup.

Previously:
- generate_token() used user.sub as token identity
- LiveKitTokenAuthentication tried to retrieve user via user.id field
- This failed when sub was not a UUID (e.g., from LemonLDAP OIDC provider)

Now:
- generate_token() continues using user.sub (canonical OIDC identifier)
- LiveKitTokenAuthentication correctly looks up by sub field
- Both sides now consistently use the same field

This ensures compatibility with all RFC 7519-compliant OIDC providers,
regardless of their sub claim format.
2025-10-20 04:57:02 +02:00
Ghislain LE MEUR 4b80b4ac9f 🔖(helm) release chart 0.0.14
Fix missing image and command attributes for celery workers
2025-10-17 12:18:31 +02:00
Ghislain LE MEUR 96d7a8875b 🐛(helm) add default commands for celery workers
Without explicit commands in values.yaml,
celeryTranscribe and  celerySummarize pods
were using the Dockerfile's default CMD (uvicorn),
which started the REST API instead of Celery workers.

This fix adds default commands to values.yaml for both services,
ensuring they run as Celery workers processing their respective
queues (transcribe-queue and summarize-queue).
2025-10-17 12:18:31 +02:00
Ghislain LE MEUR dc177b69d8 🐛(summary) add image
Add missing image attributes for summary, celerySummarize and celeryTranscribe
2025-10-17 12:18:31 +02:00
Martin Guitteny 36b2156c7b ️(summary) change formating from prompt to response_format
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
2025-10-13 12:07:54 +02:00
lebaudantoine ec94d613fa 🔖(minor) bump release to 0.1.40
- enhance technical documentation
- introduce external-api and service account
- fix inverted keyboard shortcuts
- allow configuring whisperX language (still wip)
- filter livekit event when sharing a single livekit instance
2025-10-12 17:13:09 +02:00
lebaudantoine 70d9d55227 🔖(helm) release chart 0.0.13
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.
2025-10-12 17:05:58 +02:00
lebaudantoine 5c74ace0d8 🐛(backend) filter LiveKit events by room name regex to exclude Tchap
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.
2025-10-12 16:57:44 +02:00
lebaudantoine f0939b6f7c 🐛(summary) scope metadata manager signals to transcription tasks only
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.
2025-10-10 14:00:00 +02:00
lebaudantoine aecc48f928 🔧(summary) add configurable language settings for WhisperX transcription
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.
2025-10-10 13:55:53 +02:00
lebaudantoine 4353db4a5f 🐛(frontend) fix inverted keyboard shortcuts for video and microphone
Correct accidentally swapped keyboard shortcuts between video and
microphone toggle controls introduced during device component
refactoring, restoring expected shortcut behavior reported by users.
2025-10-09 22:44:14 +02:00
Martin Guitteny 469e824167 ♻️(devexp) refactor minio webhook setup
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.
2025-10-07 21:12:06 +02:00
lebaudantoine 4c6741c905 🔧(backend) add Django setting to disable external API endpoints
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.
2025-10-06 19:34:24 +02:00
lebaudantoine 69a9a07d21 📝(backend) add Swagger documentation for external API
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.
2025-10-06 19:34:24 +02:00
lebaudantoine c9fcc2ed60 (backend) draft initial Room viewset for external applications
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.
2025-10-06 19:34:24 +02:00
lebaudantoine b8c3c3df3a (backend) add minimal scope control for external API JWTs
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.
2025-10-06 19:34:24 +02:00
lebaudantoine 1f3d0f9239 (backend) add delegation mechanism to external app /token endpoint
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.
2025-10-06 19:34:24 +02:00
lebaudantoine 062afc5b44 (backend) introduce an external API router
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
2025-10-06 19:34:24 +02:00
lebaudantoine 3fd5a4404c (backend) add application model with secure secret handling
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.
2025-10-06 19:34:24 +02:00
Martin Guitteny c07b8f920f 📝(docs) add summarization documentation
Add documentation for transcription et summarization
Include sequence diagrams
2025-10-06 14:53:56 +02:00
lebaudantoine a25baa628a 📝(docs) document calendar integrations as under construction
Add documentation noting calendar integrations is currently
under active development.
2025-10-06 13:08:46 +02:00
lebaudantoine ad084e2e52 📝(docs) document signaling configuration and related env vars
Add detailed documentation on signaling server configuration
and associated environment variables to help administrators properly
configure WebRTC connection establishment.
2025-10-06 13:08:46 +02:00
lebaudantoine dedac9106c 📝(docs) document subtitle feature as under construction
Add documentation noting subtitle functionality is currently under
active development to set appropriate expectations for administrators
and prevent deployment assumptions about feature maturity.
2025-10-06 13:08:46 +02:00
lebaudantoine cbea1c0c01 📝(docs) document telephony feature and component interactions
Add comprehensive telephony documentation explaining system requirements
and component interactions to help administrators understand infrastructure
needs.
2025-10-06 13:08:46 +02:00
lebaudantoine a92633a4bb 📝(docs) document recording feature architecture and interactions
Add comprehensive recording documentation explaining system requirements
and component interactions to help administrators understand infrastructure
needs and troubleshoot recording functionality.
2025-10-06 13:08:46 +02:00
lebaudantoine 7f8fad42cb 📝(docs) document authentication configuration and supported methods
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.
2025-10-06 13:08:46 +02:00
lebaudantoine fab046a729 📝(frontend) document application theming with different approaches
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.
2025-10-06 13:08:46 +02:00
lebaudantoine 6bb22ae6f1 📝(docs) enhance installation documentation for Docker Compose deployment
Improve installation instructions to prepare for comprehensive Docker
Compose documentation launch, clarifying setup steps and addressing
common deployment questions to reduce onboarding friction.
2025-10-06 13:08:46 +02:00
lebaudantoine 8f72769dff 📝(frontend) update README with docs inspired content
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.
2025-10-06 13:08:46 +02:00
lebaudantoine fa1feceb8b 🔥(docs) remove outdated legacy release documentation
Delete deprecated internal release process documentation that no longer
applies to current deployment practices, eliminating confusion from
obsolete workflow references.
2025-10-06 13:08:46 +02:00
lebaudantoine 57aa812ef6 🔖(minor) bump release to 0.1.39
Enable meeting summary (/w a feature flag)
2025-10-06 11:28:12 +02:00
lebaudantoine c36d99b855 ⬆️(backend) upgrade django to 5.2.7
Resolve vulnerability CVE-2025-59681, that triggers Trivy scan
and block PR's merging.

More information there https://avd.aquasec.com/nvd/cve-2025-59681
2025-10-06 10:52:44 +02:00
lebaudantoine c83d3b99fc 💡(summary) improve metadata manager error messages with explicit source
Enhance error logging in metadata manager to explicitly identify
the metadata manager as error source.
2025-10-01 15:32:27 +02:00
lebaudantoine a58d3416e0 🐛(summary) fix metadata manager args after adding owner_id parameter
Update metadata manager initialization with additional required arguments
after owner_id field addition broke existing initialization logic, restoring
proper metadata handling functionality in summary microservice.
2025-10-01 15:32:27 +02:00
Martin Guitteny c3eb877377 🐛(summary) fix feature flag on summary job
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.
2025-09-30 22:46:30 +02:00
lebaudantoine 9cb9998384 ⬆️(frontend) manually upgrade Alpine dependencies to fix libexpat vul
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.
2025-09-30 15:14:51 +02:00
lebaudantoine a3ca6f0113 📈(frontend) track more room events in PostHog for disconnections
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.
2025-09-18 23:47:13 +02:00
lebaudantoine 1d9caeb17f 🐛(helm) fix broken worker assignment due to extra space
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.
2025-09-18 18:27:10 +02:00
lebaudantoine 5caed6222b 🐛(summary) fix transcribe job queue assignment
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.
2025-09-18 18:27:10 +02:00
lebaudantoine 46fdbc0430 (helm) configure MinIO webhook with Kubernetes job for recordings
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.
2025-09-18 18:27:10 +02:00
lebaudantoine 534f3b2d47 🐛(helm) fix MinIO webhook certificate after Tilt stack changes
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.
2025-09-18 18:27:10 +02:00
lebaudantoine ebf7a1956e 🔧(helm) configure Celery workers for summary microservice in Helm
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.
2025-09-18 01:44:16 +02:00
lebaudantoine c2e6927978 📝(summary) add minimal README for dev experience
Basic README with developer setup info. Will be expanded
with more details in future commits.
2025-09-18 00:56:00 +02:00
lebaudantoine 1b4a144650 🔧(summary) add settings to disable summary feature entirely
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.
2025-09-18 00:56:00 +02:00
lebaudantoine 7004b7e2c8 🔧(summary) introduce watch section to Docker Compose file
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.
2025-09-18 00:56:00 +02:00
Martin Guitteny 848893a79f 🐛(backend) fix Docker Compose stack for recording features
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.
2025-09-18 00:56:00 +02:00
lebaudantoine 849f8ac08c (summary) introduce summary logic for meeting transcripts
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.
2025-09-18 00:56:00 +02:00
lebaudantoine 9fd264ae0e 🔧(summary) specify dedicated transcription queue for Celery worker
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.
2025-09-18 00:56:00 +02:00
lebaudantoine bfdf5548a0 🔧(backend) rename OpenAI settings to WhisperX to avoid confusion
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.
2025-09-18 00:56:00 +02:00
lebaudantoine 0102b428f1 📦️(summary) vendor existing logic for agentic system transition
Vendoring dead code before introducing new agent-based
summarization architecture to maintain clean code.
2025-09-18 00:56:00 +02:00
lebaudantoine 91a8d85db3 🔧(summary) add PostHog configuration example to summary env file
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.
2025-09-18 00:56:00 +02:00
lebaudantoine e301c5deed (summary) wrap PostHog feature flag checks in analytics client
Encapsulate PostHog SDK feature flag functionality within analytics
client.
2025-09-18 00:56:00 +02:00
lebaudantoine 67b046c9ba ♻️(summary) integrate summary Docker compose into global dev tooling
Consolidate summary service into main development stack to centralize
development environment management and simplify service orchestration
with shared infrastructure like MinIO storage.
2025-09-18 00:56:00 +02:00
lebaudantoine 1b3b9ff858 (summary) add development stage to summary Docker image for hot reload
Introduce new Docker stage enabling hot reload during active API
development to eliminate rebuild cycles and improve developer workflow
efficiency.
2025-09-18 00:56:00 +02:00
lebaudantoine 64fca531fa 🔖(minor) bump release to 0.1.38
- bump LiveKit dependencies
- fix some regressions link to permissions
2025-09-18 00:43:47 +02:00
lebaudantoine e73b0777e3 📱(frontend) fix permission modal width on mobile screens
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.
2025-09-18 00:35:50 +02:00
lebaudantoine 0489033e03 🚑️(frontend) fix mobile permission deadlock with disabled tracks
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.
2025-09-18 00:35:50 +02:00
lebaudantoine 04710f5ecd 🐛(frontend) fix mic mute for non-admin users in participant list
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.
2025-09-18 00:35:50 +02:00
lebaudantoine 4afa03d7c8 ⬆️(frontend) bump livekit-track-processor to 0.6.1
Update livekit-track-processor dependency from previous version to
0.6.1 to incorporate latest bug fixes and feature improvements.
2025-09-18 00:35:50 +02:00
lebaudantoine e57685ebe3 ⬆️(frontend) bump livekit-client to 2.15.7
Update livekit-client dependency from previous version to 2.15.7 to
incorporate latest bug fixes and feature improvements.
2025-09-18 00:35:50 +02:00
lebaudantoine 381b7c4eb7 ️(frontend) add missing aria-label to screenshare button
Add accessibility label to screenshare control button to ensure screen
readers can properly announce the button's function to users with
visual impairments.
2025-09-16 14:52:40 +02:00
lebaudantoine e0fe78e3fa 🔖(minor) bump release to 0.1.37
- revert dynacast / simulcast change
- fix safari audio output selector
2025-09-15 23:32:43 +02:00
lebaudantoine 2a85f45e69 🐛(frontend) prevent displaying audio output selector to Safari users
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.
2025-09-15 18:39:48 +02:00
lebaudantoine 8aa035ae00 ️(frontend) revert dynacast and adaptive streaming checks
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.
2025-09-15 15:54:47 +02:00
lebaudantoine d39d02d445 🔖(minor) bump release to 0.1.36 2025-09-10 22:05:39 +02:00
lebaudantoine e28e0024be ⬆️(backend) bump Django to 5.2.6 to fix severe security issue
Upgrade Django from previous version to 5.2.6 to address critical
security vulnerabilities:
https://www.djangoproject.com/weblog/2025/sep/03/security-releases/
2025-09-10 21:32:09 +02:00
lebaudantoine c492243ab1 🐛(frontend) fix controlbar mobile responsiveness after refactor
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.
2025-09-10 21:32:09 +02:00
lebaudantoine 38e6adf811 ⬇️(frontend) downgrade livekit-js-sdk to troubleshoot production issues
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.
2025-09-10 21:32:09 +02:00
lebaudantoine 88dbfae925 🔖(minor) bump release to 0.1.35
- fix crisp regression
2025-09-09 23:30:54 +02:00
Martin Guitteny bf7e17921d 📝(docs) fix path developping locally
Fix the path of the app in the doc to improve developer experience
2025-09-09 15:21:52 +02:00
lebaudantoine 3393858552 ⬆️(livekit) upgrade local LiveKit server to version 1.9.0
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.
2025-09-09 15:20:51 +02:00
lebaudantoine e7c12b4253 🐛(frontend) fix CSS rules that hide Crisp support button
Correct CSS specificity issues that were overriding and hiding the Crisp
chatbot button, ensuring support functionality remains accessible to
users.
2025-09-09 10:38:02 +02:00
lebaudantoine 45a69aaaf0 🚨(backend) fix Helmfile compatibility issue
Update Helmfile to resolve compatibility errors that occur
when running the tilt stack with latest helmfile version.
2025-09-09 10:04:58 +02:00
lebaudantoine 9565e7a5d2 🔖(minor) bump release to 0.1.34
- refactor pre-join screen
- handle permission errors
- add advanced admin controls over meeting
- display raised hand order
- add video settings
- add quick access video / microphone settings
- fix crisp regression
2025-09-08 22:27:12 +02:00
lebaudantoine a02cd26044 💄(frontend) replace switch text with icons for font-size independence
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.
2025-09-08 21:53:54 +02:00
lebaudantoine 34353b5cba 💄(frontend) narrow lobby column width on prejoin screen
Reduce lobby column width on prejoin screen for better visual balance
and improved layout proportions.
2025-09-08 21:53:54 +02:00
lebaudantoine b34a1c8695 🐛(frontend) fix favicon issues with comprehensive icon set for Safari
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.
2025-09-08 21:53:54 +02:00
lebaudantoine 7c16852a56 (frontend) add quick action to open transcription menu
Implement quick access button to open the transcription menu directly,
providing faster navigation to transcript controls and settings.
2025-09-08 21:53:54 +02:00
lebaudantoine bcdc93f405 (frontend) add quick action to open recording menu
Implement quick access button to open the recording menu directly,
providing faster navigation to recording controls and settings.
2025-09-08 21:53:54 +02:00
lebaudantoine fa588ee147 🚸(frontend) display recording duration limit in recording panel
Add information to recording panel indicating maximum recording
duration when time limits are configured to prevent user confusion
and help with session planning.
2025-09-08 21:53:54 +02:00
lebaudantoine 95e4b77b7e 🐛(frontend) fix Crisp chatbot CSS override covering room actions
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.
2025-09-08 17:22:09 +02:00
lebaudantoine 8044e3d6d8 ♻️(backend) replace Django permissions with feature flag decorator
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.
2025-09-08 17:17:45 +02:00
lebaudantoine 58722cab00 🔧(backend) set explicit user subscription permissions for other tracks
Configure LiveKit token to explicitly allow users to subscribe to other
participants' video and audio tracks instead of relying on default
permissions.
2025-09-08 17:16:52 +02:00
Quentin BEY 5f75b085ec 🔧(ci) always run all git-lint steps
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
2025-09-05 14:49:25 +02:00
lebaudantoine afd7139d39 (frontend) increase chat message limit to 2000 characters
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.
2025-09-05 14:28:51 +02:00
lebaudantoine 67d61b8cf7 ♻️(frontend) decouple PaginationControl from usePagination hook
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.
2025-09-05 13:57:46 +02:00
lebaudantoine 47cc88c820 🚸(frontend) disable pagination controls at first and last pages
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.
2025-09-05 13:57:46 +02:00
lebaudantoine 0bf7755855 ️(frontend) mark pagination indicators as decorative for screen readers
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.
2025-09-05 13:57:46 +02:00
lebaudantoine 4e75a17916 🌐(frontend) internationalize pagination controls and add aria labels
Add internationalization support to pagination controls and include
aria labels for improved accessibility and screen reader support
across different languages.
2025-09-05 13:57:46 +02:00
lebaudantoine 73a9fb3a72 📦️(frontend) vendor GridLayout components
Vendor LiveKit layout components to internationalize them
2025-09-05 13:57:46 +02:00
lebaudantoine e86dc12bf9 📦️(frontend) vendor CarouselLayout components
Vendor LiveKit layout components to start enhancing them.
2025-09-05 13:57:46 +02:00
lebaudantoine ef2b0b64bb 🔖(helm) release new Helm chart 0.0.11 with subtitle features
Release updated Helm chart including subtitle functionality and LiveKit
agent framework integration for transcription services.
2025-09-04 19:34:39 +02:00
lebaudantoine 1f71bfc5d2 🎨(backend) use pylint error names instead of codes in disable comments
Replace pylint error codes with descriptive error names in disable comments
to make suppressed warnings explicit and improve code readability.
2025-09-04 11:26:48 +02:00
lebaudantoine 888fbbcd5f 🎨(backend) use object primary key instead of id attribute
Replace id attribute references with object primary key for better code
consistency and Django model conventions.

requested by @qbey
2025-09-04 11:26:48 +02:00
lebaudantoine 9b6b32c3d5 🐛(frontend) fix nested React components in participant list
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 00a3c0a37c 🏷️(frontend) make toast props readonly for enhanced type safety
Refactor toast component props to use readonly TypeScript modifiers,
preventing accidental mutations and strengthening type safety.
2025-09-04 11:26:48 +02:00
lebaudantoine ff9487eb2f ️(frontend) add missing aria attribute to lower hand button
Add required aria accessibility attribute to the lower hand button for
proper screen reader support and compliance.
2025-09-04 11:26:48 +02:00
lebaudantoine 242e7cb148 🚸(frontend) add notifications when admin removes participant permissions
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 86a04ed718 🐛(frontend) prevent effects access when camera permissions denied
Block effects functionality when users lack camera publishing
permissions since they cannot open their camera and shouldn't be able
to start effects.
2025-09-04 11:26:48 +02:00
lebaudantoine 3d3242e148 🚸(frontend) disable device controls when user lacks room permissions
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 7d1f15ef91 🐛(frontend) optimize mute-all to skip participants without mic tracks
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 00b58288cf 🐛(frontend) fix LiveKit mic indicator for admin-muted participants
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.
2025-09-04 11:26:48 +02:00
lebaudantoine aeb5c3790c ♻️(frontend) refactor permission updates to preserve admin privileges
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 3e69a2380f ♻️(frontend) sync publishing sources with Django backend settings
Replace hardcoded default publishing source constants with values from
Django backend settings to prevent desynchronization between frontend
and backend configurations.
2025-09-04 11:26:48 +02:00
lebaudantoine 57f63bf891 💄(frontend) add visual pin indicator for pinned participant tracks
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.
2025-09-04 11:26:48 +02:00
lebaudantoine da86b30455 (frontend) add participant menu with pin/unpin and admin remove actions
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 6a76041a70 (frontend) add "mute all participants" feature for admins
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 26bd947541 🔥(frontend) remove dead code
Clean up unused commented code elements that are no longer
referenced or needed in the codebase.
2025-09-04 11:26:48 +02:00
lebaudantoine a85a62eb1a 🔒️(frontend) hide admin actions from unprivileged users in UI
Update interface to hide admin-only actions like participant muting from
users without room admin privileges, reflecting backend permission
restrictions implemented in previous commits.
2025-09-04 11:26:48 +02:00
lebaudantoine 4793f2fa8f (frontend) display host status to meeting participants
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 1268346405 ♻️(backend) replace LiveKit token metadata with attributes
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.
2025-09-04 11:26:48 +02:00
lebaudantoine f28da45b4c (frontend) add admin controls for real-time source publication limits
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 740355d494 (frontend) add Switch Field component with custom layout handling
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 34fde10854 (frontend) add client-side API call for participant removal
Implement frontend functionality to call backend endpoints for removing
participants from rooms through proper server-mediated requests.
2025-09-04 11:26:48 +02:00
lebaudantoine 84c820bc60 (frontend) add client-side API call for participant permission updates
Implement frontend functionality to call backend endpoints for updating
specific participant permissions through proper server-mediated
requests.
2025-09-04 11:26:48 +02:00
lebaudantoine 1539613bf8 ♻️(frontend) replace direct LiveKit calls with backend API endpoints
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 5f70840398 ♻️(backend) move LiveKit participant management to server-side API
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
2025-09-04 11:26:48 +02:00
lebaudantoine 84e62246b7 (backend) add lobby cache clearing method for room and participant
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 6c633b1ecb ♻️(backend) sync lobby and LiveKit participant UUID generation
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.
2025-09-04 11:26:48 +02:00
lebaudantoine 0f76517957 💩(backend) pass room config and user role data to LiveKit token utility
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.
2025-09-04 11:26:48 +02:00
lebaudantoine fd7a78e80e ♻️(backend) factorize validation-only serializers to reduce duplication
Eliminates code duplication across validation serializers, improving
maintainability and ensuring consistent validation behavior throughout
the API layer.
2025-09-04 11:26:48 +02:00
lebaudantoine 206babb20f 🔧(backend) extract LiveKit publishing sources to Django settings
Move hardcoded LiveKit publishing sources from backend code to
configurable Django settings for better reusability and self-hosting
flexibility.

Enables self-hosters to customize LiveKit token generation sources
without code modifications, improving deployment configurability.
2025-09-04 11:26:48 +02:00
lebaudantoine 081c860e04 🚨(helm) fix whitespace in Kubernetes template directive braces
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.
2025-09-03 18:09:00 +02:00
lebaudantoine 83192f69e3 🔧(summary) align ruff Python target with Docker image version
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.
2025-09-03 18:09:00 +02:00
lebaudantoine 2ceb94a966 👷(summary) add CI job to lint Python summary sources
Implement CI job to lint summary Python sources and enforce merging
only linted code to maintain code quality standards.
2025-09-03 18:09:00 +02:00
lebaudantoine 3c13e287e6 🔒️(all) refactor Docker Hub login to use official GitHub actions
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.
2025-09-03 18:09:00 +02:00
lebaudantoine eee17b6b58 👷(agents) add CI job to lint Python agent sources
Implement CI job to lint agent Python sources and enforce merging only
linted code to maintain code quality standards.
2025-09-03 18:09:00 +02:00
lebaudantoine 185d5c2c60 👷(agents) add meet-agents image build and push to CI docker hub
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.
2025-09-03 18:09:00 +02:00
lebaudantoine 31ac4cd767 🐛(summary) fix hot reloading in tilt stack for summary image/pod
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.
2025-09-03 18:09:00 +02:00
lebaudantoine a6aa77cb97 🔧(all) update numerique.gouv.fr references to new repo location
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.
2025-09-03 18:09:00 +02:00
lebaudantoine 42b9a34c7a 🔥(backend) remove useless imports from backend code
Clean up unused imports in backend modules as minor maintenance work
not related to current PR.
2025-09-03 18:09:00 +02:00
lebaudantoine 9ff4b23ea7 (frontend) add subtitle control with transcription display
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.
2025-09-03 18:09:00 +02:00
lebaudantoine f48dd5cea1 (backend) add start-subtitle endpoint
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.
2025-09-03 18:09:00 +02:00
lebaudantoine 49ee46438b 🧱(backend) add Helm chart for LiveKit agent deployment
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.
2025-09-03 18:09:00 +02:00
lebaudantoine ea2e5e8609 (agents) initialize LiveKit agent from multi-user transcriber example
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.
2025-09-03 18:09:00 +02:00
lebaudantoine 6ca73c665b ️(frontend) use initial processor reference to avoid track recreation
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.
2025-09-02 16:59:18 +02:00
lebaudantoine cfa68d0eb4 🐛(frontend) fix modal overflow when stopping processors in join screen
Fixes visual glitch where processor termination caused height increase
beyond modal boundaries, ensuring consistent modal dimensions
regardless of processor state changes.
2025-09-02 16:59:18 +02:00
lebaudantoine fac0c53123 ♻️(frontend) refactor processor wrapper to unified class architecture
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.
2025-09-02 16:59:18 +02:00
lebaudantoine a8f1ee0530 ♻️(frontend) simplify processor factory for transformer unification
Streamline processor factory logic to prepare for unified transformer
class refactoring.

Reduces complexity and establishes foundation for consolidated
transformer approach.
2025-09-02 16:59:18 +02:00
lebaudantoine 651d299068 ⬆️(frontend) upgrade LiveKit track processor to v0.6.0
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.
2025-09-02 16:59:18 +02:00
lebaudantoine 51ed277941 🔥(backend) remove demo data generation from tilt migration job
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.
2025-08-25 17:23:58 +02:00
lebaudantoine f46a5dc157 🔒️(backend) fix Django security warning with longer dev secret key
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.
2025-08-25 17:23:58 +02:00
Jacques ROUSSEL 4f4b4d3231 ♻️(tilt) remove bitnami dependencies from dev stack
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.
2025-08-25 17:23:58 +02:00
lebaudantoine 25a39a1fb6 👷(ci) add pip caching and upgrade setup-python action to v5
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
2025-08-24 23:39:41 +02:00
lebaudantoine a5003b55e3 💄(frontend) add visual cross to switch component for negative state
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.
2025-08-23 02:43:38 +02:00
lebaudantoine bcf551a25c 🐛(frontend) fix shortcut handler type to properly handle promises
Correct TypeScript typing for shortcut handler that wasn't properly
handling Promise return types.

Ensures proper async operation handling and prevents potential runtime
issues with promise-based shortcut actions.
2025-08-22 17:05:31 +02:00
lebaudantoine c1c2d0260d ♻️(frontend) refactor settings from context to valtio global store
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.
2025-08-22 17:05:31 +02:00
lebaudantoine e80b9c2485 🚚(frontend) rename screenshare preference store for naming consistency
Update screenshare preference store name to follow established naming
convention used across other preference stores.
2025-08-22 17:05:31 +02:00
lebaudantoine 04f7412307 🏷️(frontend) make controlbar props readonly for enhanced type safety
Strengthens type safety by ensuring props immutability and catching
potential side effects during development.
2025-08-22 17:05:31 +02:00
lebaudantoine ba422110f8 📝(frontend) clarify toggleButtonProps override behavior in documentation
Document that toggleButtonProps are intended to override default and
computed values within ToggleComponent, acknowledging this breaks
encapsulation but serves as useful starting point.
2025-08-22 17:05:31 +02:00
lebaudantoine a83afdbb0c 🐛(frontend) prevent state updates when device selection unchanged
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.
2025-08-22 17:05:31 +02:00
lebaudantoine a5d8aae293 ️(frontend) optimize device icon hook to share icons between components
Optimize device icon hook calls to ensure parent select components and
their children share the same icon instances for better performance.
2025-08-22 17:05:31 +02:00
lebaudantoine 8a3a0d5759 🔥(frontend) remove obsolete props from duplicated LiveKit controlbar
Simplify duplicated controlbar component by removing props that became
useless after solving prop drilling issues.
2025-08-22 17:05:31 +02:00
lebaudantoine aa8362c470 🎨(frontend) clarify video toggle naming and improve typing
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
2025-08-22 17:05:31 +02:00
lebaudantoine c2586a392c 🔥(frontend) remove dead code left from previous PR
Clean up unused code that was forgotten during previous pull request
implementation.
2025-08-22 17:05:31 +02:00
lebaudantoine ea3f0cc59e 🐛(frontend) fix audio track initialization bug from merge error
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 9aa9342054 ✏️(frontend) fix French typo in "arrière-plan" missing hyphen
Correct French translation typo where "arrière plan" was missing the
required hyphen to properly spell "arrière-plan".
2025-08-22 17:05:31 +02:00
lebaudantoine ca38c4851f 🐛(frontend) fix missing participant name in recording toaster
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.
2025-08-22 17:05:31 +02:00
lebaudantoine a97895c383 🚸(frontend) auto-close device popover when opening dialogs or sidepanels
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.
2025-08-22 17:05:31 +02:00
lebaudantoine e88aeedbf1 🐛(frontend) disable device shortcuts when permissions not granted
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 5f32a9e6a3 ♻️(frontend) refactor audio tab to controlled device selection pattern
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.
2025-08-22 17:05:31 +02:00
lebaudantoine aa09c15ecc (frontend) add effects quick access from in-conference video controls
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 7ec3e481ff ️(frontend) update device control tooltips to reflect settings dialog
Update tooltip and aria-label text for in-room device controls to
indicate they now open comprehensive settings dialog instead of simple
device selection.
2025-08-22 17:05:31 +02:00
lebaudantoine 42107f4698 (frontend) add settings quick access from device controls
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.
2025-08-22 17:05:31 +02:00
lebaudantoine a49893696b 🌐(frontend) refactor device i18n keys for reusability across contexts
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 6f3339fbdc ♻️(frontend) unify toggle components into single flexible implementation
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.
2025-08-22 17:05:31 +02:00
lebaudantoine f17e0a3ba0 ♻️(frontend) replace toggle device config with keyboard shortcut hook
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 2367750395 ♻️(frontend) extract media icon logic into optimized reusable hook
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 5eb70384e3 🚚(frontend) move ToggleDevice controls to Device folder
Reorganize ToggleDevice control components by moving them to the Device
folder for better code organization and logical grouping.
2025-08-22 17:05:31 +02:00
lebaudantoine 22c68da2af ♻️(frontend) extract permission checks into reusable hook by media kind
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.
2025-08-22 17:05:31 +02:00
lebaudantoine ebf676529f ♻️(frontend) refactor in-room device selection with audio output control
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 40cedba8ae ♻️(frontend) decouple audio/video controls for reorganization clarity
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 59e0643dde 💄(frontend) add dark variant prop to Select primitive
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 7b89395f42 (frontend) expose placement prop in Popover primitive
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 3d047b5124 (frontend) add default tab selection mechanism to settings dialog
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 89b1190bb4 (frontend) add arrow toggle option to Popover primitive
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.
2025-08-22 17:05:31 +02:00
lebaudantoine 8f28a46a5f 💄(frontend) add dark variant prop to Popover primitive
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.
2025-08-22 17:05:31 +02:00
lebaudantoine ac88c046dc ♻️(frontend) replace generic tab IDs with explicit string identifiers
Change tab identification from integer IDs to explicit string
identifiers for better code readability and maintainability.
2025-08-22 17:05:31 +02:00
lebaudantoine b7f55ac35d 🐛(frontend) fix camera/mic acquisition when disabled in user preferences
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.
2025-08-20 16:11:01 +02:00
lebaudantoine 329a729bdc ⬆️(frontend) bump LiveKit client JS SDK to 2.15.5
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.
2025-08-20 14:03:34 +02:00
lebaudantoine 2215b621f4 ♻️(frontend) refactor audio/video tabs to share common layout components
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.
2025-08-20 12:26:22 +02:00
lebaudantoine c330ec6ff4 (frontend) add subscription video quality selector to video tab
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.
2025-08-20 12:26:22 +02:00
lebaudantoine 8245270f28 ♻️(frontend) refactor video tab i18n strings with common prefix
Reorganize internationalization strings for video tab to use shared
"video" prefix, improving code maintainability and consistency.
2025-08-20 12:26:22 +02:00
lebaudantoine 9728603f72 (frontend) add persistence for subscribed video resolution 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.
2025-08-20 12:26:22 +02:00
lebaudantoine 803c94a80c (frontend) add video resolution selector for publishing control
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.
2025-08-20 12:26:22 +02:00
lebaudantoine fd90d0b830 (frontend) add persistence for video publishing resolution setting
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.
2025-08-20 12:26:22 +02:00
lebaudantoine f380d0342d (frontend) add video tab to settings modal for camera configuration
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.
2025-08-20 12:26:22 +02:00
lebaudantoine 4cdf257b6a ️(frontend) fix incorrect aria label on tab component
Correct wrong aria label that was accidentally copied from another
component during development.
2025-08-20 12:26:22 +02:00
lebaudantoine 338f8d8a69 ♻️(frontend) refactor useResolveDefaultDeviceId to run initially
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.
2025-08-13 10:26:37 +02:00
lebaudantoine ab4f415d23 🩹(frontend) fix audiotrack typing issue from refactoring
Correct TypeScript typing issue for audiotrack that was introduced
during the recent app refactoring changes.
2025-08-13 10:26:37 +02:00
lebaudantoine e926b407b1 ♻️(frontend) refactor preview track to avoid unnecessary resets
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.
2025-08-13 10:26:37 +02:00
lebaudantoine 4e655a0a64 🚸(frontend) prioritize UI reactivity over error handling in track toggle
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.
2025-08-12 00:09:08 +02:00
lebaudantoine d2bde299be 🚸(frontend) auto-select single audio output device for smoother UX
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.
2025-08-12 00:09:08 +02:00
lebaudantoine 9b44ed0974 🩹(frontend) disable Safari speaker select for LiveKit compatibility
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.
2025-08-12 00:09:08 +02:00
lebaudantoine aeaa9b7ffd 🐛(frontend) link audio output permissions to mic to prevent prompts
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.
2025-08-12 00:09:08 +02:00
lebaudantoine da73424f72 🌐(frontend) fix Dutch plural forms in join screen translations
Correct plural form usage in Dutch language translations for the join
screen interface elements.
2025-08-12 00:09:08 +02:00
lebaudantoine 2b9b977f57 (frontend) add speaker select component for audio output configuration
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.
2025-08-12 00:09:08 +02:00
lebaudantoine 355db6ef9a (frontend) add localStorage persistence for audio output device
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.
2025-08-12 00:09:08 +02:00
lebaudantoine 890e043d29 🚨(frontend) remove redundant undefined type or optional specifier
Fix TypeScript warning by removing either 'undefined' type annotation
or '?' optional specifier where both were redundantly specified.
2025-08-11 19:04:59 +02:00
lebaudantoine 9eb412758a 🚨(frontend) fix unnecessary destructuring rename in devices assignment
Remove unnecessary renaming in destructuring assignment where variable
was renamed to the same name, violating TypeScript rule S6650.
2025-08-11 19:04:59 +02:00
lebaudantoine fa27afdfdf 💄(frontend) add symmetric shadows for white button contrast enhancement
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.
2025-08-11 19:04:59 +02:00
lebaudantoine cb8b415ef9 ♻️(frontend) refactor device select for controlled behavior
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.
2025-08-11 19:04:59 +02:00
lebaudantoine 7c6182cc4e 🐛(frontend) fix default device ID mismatch with actual preview track
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.
2025-08-11 19:04:59 +02:00
lebaudantoine 2d47e90a1a 🐛(frontend) reset video ref on track stop for state transitions
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.
2025-08-11 19:04:59 +02:00
lebaudantoine 56ec2dd8cb ♻️(frontend) refactor select to show arrow up when menu opens upward
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.
2025-08-11 19:04:59 +02:00
lebaudantoine 361de29780 🩹(frontend) refactor track muting for proper audio/video control
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.
2025-08-11 19:04:59 +02:00
lebaudantoine e4d5ca64b9 ♻️(frontend) refactor prejoin screen for room context flexibility
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.
2025-08-11 19:04:59 +02:00
lebaudantoine bd139a1ef9 🎨(frontend) personalize permission modal for Safari UX differences
Provides Safari-specific UI guidance that matches the browser's unique
permission flow, ensuring users receive appropriate instructions for
their specific browser environment.
2025-08-10 18:42:42 +02:00
lebaudantoine f682f8feb3 🐛(frontend) fix React aria warnings with label/wrapper investigation
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.
2025-08-10 18:42:42 +02:00
lebaudantoine 5f1d59c753 🐛(frontend) fix Safari permission change detection with polling
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.
2025-08-10 18:42:42 +02:00
lebaudantoine c45b91dc58 🩹(frontend) fix missing aria text for camera preview status
Add missing accessibility text to video container that explains to
screen reader users whether camera preview is currently enabled or
disabled.
2025-08-10 18:42:42 +02:00
lebaudantoine 0e72f61650 🚸(frontend) add permission hints and modal button to join screen
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.
2025-08-10 18:42:42 +02:00
lebaudantoine 4fae3c6c47 (frontend) add visual permission indicator to device toggle button
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.
2025-08-10 18:42:42 +02:00
lebaudantoine 120bcdc720 🚸(frontend) add permissions dialog to guide users through setup
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.
2025-08-10 18:42:42 +02:00
lebaudantoine f1b20d7981 (frontend) add permissions watcher to sync valtio store with browser
Introduce permissions watcher that continuously monitors browser
permission changes and keeps the valtio global store synchronized
with actual browser permission state.
2025-08-10 18:42:42 +02:00
lebaudantoine 95190ec690 (frontend) add global store for browser permissions monitoring
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.
2025-08-10 18:42:42 +02:00
lebaudantoine adb99cc5d9 ♻️(frontend) refactor prejoin layout for better extensibility
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.
2025-08-08 13:10:08 +02:00
lebaudantoine 201069aa4c ♻️(frontend) refactor clipboard logic into dedicated reusable hook
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.
2025-08-07 12:51:03 +02:00
lebaudantoine b6a5b1a805 🎨(frontend) remove space between PIN digits and # symbol
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.
2025-08-07 12:51:03 +02:00
lebaudantoine f3af637fd6 (frontend) add telephony info to encourage phone participation
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.
2025-08-07 12:51:03 +02:00
lebaudantoine de3a5aa404 💄(frontend) update secondaryText button variant to medium font weight
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.
2025-08-07 12:51:03 +02:00
lebaudantoine 5e9d20e685 🐛(frontend) fix public room warning showing for all rooms
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.
2025-08-07 12:51:03 +02:00
lebaudantoine b54445739a (frontend) add telephony info to meeting dialog with layout stability
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.
2025-08-07 12:51:03 +02:00
lebaudantoine 7c67bacd94 🚸(frontend) fix locale issues and improve meeting dialog copywriting
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.
2025-08-07 12:51:03 +02:00
lebaudantoine 1fd1b184ee 💬(frontend) update wording from "room address" to "room information"
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.
2025-08-07 12:51:03 +02:00
lebaudantoine adb517a336 🎨(frontend) harmonize room info sidepanel display with meeting dialog
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.
2025-08-07 12:51:03 +02:00
lebaudantoine eec9ff9f26 🚸(frontend) fix copy to include all meeting info from side panel
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.
2025-08-07 12:51:03 +02:00
lebaudantoine e0258a1765 🔧(tilt) configure telephony in tilt stack for development
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.
2025-08-07 12:51:03 +02:00
lebaudantoine 872ce1ecc6 (frontend) add icon support to select primitive component
Enhance select component by adding icon display capability for better
visual representation of options.
2025-08-01 17:45:48 +02:00
lebaudantoine e2c3b745ca 🩹(frontend) avoid video glitch on the prejoin while init a processor
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.
2025-08-01 17:40:11 +02:00
lebaudantoine 965d823d08 (frontend) display position of a raised hand in the queue
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
2025-08-01 16:54:24 +02:00
lebaudantoine 1db189ace2 🚸(frontend) sort raised hand by order of arrival
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.
2025-08-01 16:54:24 +02:00
lebaudantoine 199e0908e9 ♻️(frontend) refactor raised hand to rely on participant's attributes
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.
2025-08-01 16:54:24 +02:00
Jacques ROUSSEL 8518f83211 (helm) add the ability to configure tls secretName
Yesterday during a deployment, we were unable to configure the tls
secretName for ingress.
2025-08-01 16:53:36 +02:00
lebaudantoine 0240d85837 📝(backend) add Firefox proxy workaround parameter to installation guide
Document LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND setting that enables
connection warmup by pre-calling WebSocket endpoint to resolve proxy
connectivity issues.
2025-08-01 16:23:22 +02:00
lebaudantoine 162896c93c 🩹(backend) allow enforcing WSS protocol to resolve browser compatibility
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.
2025-08-01 16:23:22 +02:00
Jacques ROUSSEL 483a219ac4 ♻️(documentation) remove unused environment variables
Yesterday during a deployment, we discovered that these variables are
unused:
POSTGRES_DB
POSTGRES_USER
POSTGRES_PASSWORD
2025-08-01 16:14:55 +02:00
lebaudantoine 1b26dea178 🐛(frontend) use feature detection for adaptiveStream and dynacast
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.
2025-08-01 15:46:17 +02:00
lebaudantoine bdaf4245da 🔖(minor) bump release to 0.1.33
Warmup with WebSocket pre-authentication on FF
2025-07-25 08:50:33 +02:00
lebaudantoine be63993ba2 🩹(frontend) fix connection warmup with WebSocket pre-authentication
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.
2025-07-25 08:50:33 +02:00
lebaudantoine 3d245c3bd4 🔖(minor) bump release to 0.1.32
warmup livekit connection.
2025-07-24 14:57:48 +02:00
lebaudantoine 66a36eff73 ♻️(frontend) refactor connection warmup to use LiveKit methods
Replace custom connection warmup implementation with LiveKit's built-in
methods for better reliability and consistency.
2025-07-24 14:49:49 +02:00
lebaudantoine 387bc2e1f4 🐛(frontend) add LiveKit connection warmup for Firefox+proxy fixes
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.
2025-07-24 14:32:51 +02:00
lebaudantoine d44b45b6aa 🐛(frontend) prevent shortcut handling when key is undefined
Add null check to avoid processing keyboard shortcuts with undefined
key values that could cause errors.

Exception caught in PostHog
2025-07-23 12:06:39 +02:00
lebaudantoine 224b98fd9a 🧪(frontend) capture LiveKit exceptions in PostHog for debugging
Test tracking signaling failures to determine root causes when connection
fails. Will remove if it spams analytics - goal is understanding failure
patterns and reasons.
2025-07-23 12:06:39 +02:00
lebaudantoine 031852d0b1 🔖(minor) bump release to 0.1.31
Fix noise reduction feature flag
2025-07-21 12:00:06 +02:00
lebaudantoine 24915b0485 🐛(frontend) fix wrong feature flag for noise reduction
Replace incorrect faceLandmarks flag with proper noiseReduction flag
to ensure correct feature availability checking.
2025-07-21 10:29:36 +02:00
ericboucher 0862203d5d 🚸(frontend) add Safari warning for unavailable speaker settings
Display notice explaining that missing browser settings are due to Safari
limitations, not app bugs, to prevent user confusion.
2025-07-20 18:35:32 +02:00
ericboucher ee604abe00 🐛(frontend) replace useSize with useMediaQuery in account settings
Fix buggy layout transitions on Safari mobile by using media queries
instead of size detection for smoother settings panel responsive behavior.
2025-07-20 18:35:32 +02:00
lebaudantoine 26d668b478 🐛(frontend) prevent Crisp crash when superuser has no email
Fix crash when switching from admin session to app with superuser account
that lacks email field. Add null check to prevent Crisp initialization
errors.
2025-07-20 18:00:08 +02:00
lebaudantoine 04081f04fc 🌐(frontend) internationalize missing error message
Add translation support for previously untranslated error message to
complete localization coverage.
2025-07-20 18:00:08 +02:00
ericboucher f7268c507b 🚸(frontend) display email with username to clarify logged-in account
Show email alongside full name when available to prevent user confusion
about which account is currently logged in. Enhances general app UX.
2025-07-20 18:00:08 +02:00
lebaudantoine cadb20793a 🔖(minor) bump release to 0.1.30
various fixes
2025-07-18 11:48:02 +02:00
lebaudantoine 8a417806e4 🐛(backend) fix lobby notification type error breaking participant alerts
Correct data type issue that was preventing lobby notifications from
being sent to other participants in the room.
2025-07-18 11:42:43 +02:00
lebaudantoine 223c744e3f 🚨(summary) lint celery_config module to pass ruff checks
Apply code formatting and style fixes to celery configuration
module to meet linting standards.
2025-07-18 11:29:13 +02:00
lebaudantoine f67335f306 🐛(summary) fix Celery task execution by number of required args
Forgot to update the args verification while enriching the task
with more recording metadata.
2025-07-18 11:29:13 +02:00
lebaudantoine 4eb7f29f8e 🔊(summary) add Celery exporter configuration for monitoring
Enable Celery task lifecycle events and broker dispatch events per
@rouja's exporter requirements. Basic configuration following
documentation without parameterization.
2025-07-17 23:53:09 +02:00
lebaudantoine 912bac8756 🔖(minor) bump release to 0.1.29
What:

- fix minor issue on summary microservice
- PKCE (oidc) support
- add limitation on recording if supported

and more.
2025-07-17 20:41:29 +02:00
lebaudantoine 3c97418a70 🐛(summary) fix Celery task execution by switching to apply_async()
Replace delay() with apply_async() to resolve invalid arguments error.
2025-07-17 20:41:29 +02:00
lebaudantoine 26a90456f7 🚸(frontend) add alert for media devices already in use
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.
2025-07-17 20:41:29 +02:00
lebaudantoine d068558c8f 🚸(frontend) explain duplicate identity disconnect on feedback page
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.
2025-07-17 20:41:29 +02:00
lebaudantoine dac6bfe142 ♻️(frontend) refactor feedback redirect to global onDisconnect hook
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.
2025-07-17 17:41:04 +02:00
lebaudantoine 6b3e5d747a 📝(backend) add OIDC PKCE parameters to installation documentation
Document PKCE-related configuration options for OpenID Connect setup
in installation guide for proper authentication flow.
2025-07-16 15:17:39 +02:00
K900 3066e3a83c 🔒️(backend) add environment variables for PKCE settings
Defaulting to off for now to keep compatibility.
2025-07-16 14:52:44 +02:00
lebaudantoine 5e05b6b2a5 ⬆️(frontend) bump libphonenumber-js dependency
Update phone number formatting library to latest version for bug fixes
and improved international number handling.
2025-07-16 14:47:24 +02:00
lebaudantoine d075d60d19 🚸(frontend) notify all participants when recording/transcription stops
Broadcast limit-reached notifications to all room participants, not just
owner, to ensure everyone knows recording has stopped due to duration
limits.
2025-07-16 14:47:24 +02:00
lebaudantoine 7c631bb76f 🚸(frontend) alert room owner when recording exceeds max duration
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.
2025-07-16 14:47:24 +02:00
lebaudantoine 59cd1f766a (backend) add egress limit notification handler to LiveKit service
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.
2025-07-16 14:47:24 +02:00
lebaudantoine f0a17b1ce1 (backend) add dedicated service for LiveKit recording webhook events
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.
2025-07-16 14:47:24 +02:00
lebaudantoine 17c486f7bf ♻️(backend) extract notify_participant to util function
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.
2025-07-16 14:47:24 +02:00
lebaudantoine 85bde9633f 🔧(frontend) pass recording max duration to frontend for user alerts
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.
2025-07-16 14:47:24 +02:00
Charles Hall 0eb715b0cd 📝(doc) document the oidc redirect uri 2025-07-14 16:58:50 +02:00
Charles Hall b0617dcfed 📝(doc) update project name in installation prose
References relating to k8s and things remain unchanged, because that's
probably going to be more involved to make sure such changes are
accurate.
2025-07-14 16:58:50 +02:00
lebaudantoine 6c4c44e933 (summary) enhance transcription document naming with room context
Add optional room name, recording time and date to generate better
document names based on user feedback. Template is customizable for
internationalization support.
2025-07-11 15:40:12 +02:00
lebaudantoine 16dde229cc 🚨(summary) lint analytics sources
Fix formatting issues.
2025-07-11 15:40:12 +02:00
lebaudantoine d01d6dd9d1 🚸(backend) clarify link sharing limitations in recording email
Add notice to email notifications that recording link sharing is not
supported in beta to prevent user confusion.
2025-07-11 14:14:02 +02:00
lebaudantoine 2a39978245 🚸(frontend) add beta warning about recording link sharing limitations
Display notice on recording page that link sharing is not available in
beta to prevent user confusion and set proper expectations.
2025-07-11 14:14:02 +02:00
lebaudantoine d85ed031a9 🚸(frontend) improve error messaging for recording access failures
Clarify that recording links are not shareable when users cannot load
recordings. Previous error messages were unclear about access restrictions.
2025-07-11 14:14:02 +02:00
lebaudantoine 5c8c81f97b 🐛(frontend) fix infinite loading for unauthenticated users on downloads
Reorganize exception handling in recording download screen to prevent
unauthenticated users from getting stuck in loading state. Caught by
production users - my bad;
2025-07-11 14:14:02 +02:00
lebaudantoine 3368a9b6af 🔧(summary) extract hardcoded title to configurable setting
Replace hardcoded title with configurable option to enable custom
branding for different deployments of the microservice.
2025-07-11 11:38:28 +02:00
lebaudantoine e87d0519ff 🔧(summary) make audio duration limit optional for deployment safety
Allow deploying without breaking changes while frontend implements proper
egress limit handling. Duration restriction can be enabled when ready.
2025-07-11 11:38:28 +02:00
lebaudantoine 731f0471aa ♻️(summary) rename TaskTracker to MetadataManager for clarity
Update class name to better reflect its responsibility for handling task
metadata rather than tracking tasks themselves.
2025-07-11 11:38:28 +02:00
lebaudantoine e458272745 🐛(summary) fix data type serialization issues with Redis and PostHog
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.
2025-07-11 11:38:28 +02:00
lebaudantoine d71e417d58 📝(summary) replace "wip" placeholder with proper docstring
Add proper function documentation to replace temporary placeholder
committed in previous hasty commit.
2025-07-11 11:38:28 +02:00
lebaudantoine d91f343ba9 🔖(minor) bump release to 0.1.28
telephony frontend + backend
source map
enhance analytics on the summary microservice
2025-07-10 22:25:07 +02:00
lebaudantoine 4fc0744433 🐛(summary) fix minor Python typing issue
Correct type annotation to resolve static type checking warnings.
2025-07-10 18:13:32 +02:00
lebaudantoine 93e3f05348 🔧(backend) make PostHog event names configurable for transcript tracking
Add setting to customize PostHog event names when tracking transcript
results for flexible analytics configuration.
2025-07-10 18:13:32 +02:00
lebaudantoine cbabcb877b 🐛(summary) add audio duration limit to prevent long-running jobs
Set default 1h30 limit for audio processing to prevent Whisper from
running excessively long on large recordings. Improves resource
management and job completion times.
2025-07-10 18:13:32 +02:00
lebaudantoine 30cd6573ef 🔧(backend) refine Celery retry policy to HTTP errors only
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.
2025-07-10 18:13:32 +02:00
lebaudantoine 921d69031e 🔊(summary) increase logging level to info for Celery worker insights
Change logging levels to provide more visibility into Celery worker
operations and task processing for better monitoring.
2025-07-10 18:13:32 +02:00
lebaudantoine 1716e11900 🔧(summary) configure OpenAI max retries via FastAPI settings
Set default OpenAI retries to 0 and add configurable setting to control
retry behavior for API requests in summary service.
2025-07-10 18:13:32 +02:00
lebaudantoine 6e55013b15 📈(summary) kickstart analytics tracking in summary microservice
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.
2025-07-10 18:13:32 +02:00
lebaudantoine 21bed40484 (summary) add mutagen library for audio file duration detection
Install mutagen to analyze audio file metadata and determine recording
length for summary processing.
2025-07-10 18:13:32 +02:00
lebaudantoine 5959e82bf0 (summary) install PostHog in summary microservice
Add PostHog analytics integration to summary service for error
tracking and usage monitoring capabilities.
2025-07-10 18:13:32 +02:00
lebaudantoine b5113580b3 📸(frontend) inject PostHog sourcemap ID in chunks during build
Add PostHog CLI step to inject proper IDs into chunks, enabling error
tracking to map exceptions back to original source code locations
via sourcemaps.
2025-07-08 15:56:26 +02:00
lebaudantoine 053e4bc7b9 🔧(frontend) add conditional sourcemap generation for error tracking
Enable sourcemaps via env variable to link Sentry/PostHog exceptions to
source code. Enable by default for DINUM frontend image to improve
debugging capabilities.
2025-07-08 15:56:26 +02:00
lebaudantoine 9e57c25a25 🌐(frontend) fix wrong plural in footer
Accessibility should be singular.
2025-07-08 15:30:21 +02:00
lebaudantoine dfbcbed485 🐛(tilt) enable Keycloak in DINUM Tilt stack configuration
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.
2025-07-08 14:39:01 +02:00
lebaudantoine 9c28e1b266 📝(readme) document BrowserStack free license usage in README
Add note about using BrowserStack's free open-source license for
cross-browser testing to clarify testing infrastructure.
2025-07-07 19:45:43 +02:00
lebaudantoine 2a586445b5 📝(readme) update feature status in README with recent developments
Reflect current implementation status of features that have been completed
or are in progress to keep documentation accurate.
2025-07-07 19:45:43 +02:00
lebaudantoine 75ffb7f5f7 (frontend) add phone number and pin display in info side panel
Create minimal UI to show telephony access details for testing SIP
functionality in staging deployment. Basic implementation for feature
validation.
2025-07-07 19:21:39 +02:00
lebaudantoine 6a1c85809d (frontend) add libphonenumber-js for phone number formatting
Install JavaScript implementation of Google's libphonenumber for proper
international phone number validation and formatting.
2025-07-07 19:21:39 +02:00
lebaudantoine 70d250cc9c 🔧(frontend) add telephony feature configuration from backend
Pass telephony service availability and settings to frontend to enable
conditional UI rendering based on SIP functionality status.
2025-07-07 19:21:39 +02:00
lebaudantoine 988e5aa256 (backend) add telephony service for automatic SIP dispatch rules
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.
2025-07-07 19:21:39 +02:00
lebaudantoine d3178eff5d (backend) serialize room pin code for frontend access
Add pin code to API response to enable frontend display of room access
codes. UI implementation will follow in upcoming commits.
2025-07-07 19:21:39 +02:00
lebaudantoine 9c840a4e06 🐛(frontend) revert || to ?? operator for metadata parsing
Fix broken parsing when metadata contains empty strings. Nullish coalescing
operator (??) doesn't handle empty strings like logical OR (||) does.
2025-07-07 19:21:39 +02:00
renovate[bot] e6754b49e0 ⬆️(dependencies) update js dependencies 2025-07-07 15:14:15 +02:00
lebaudantoine ec586eaab4 🔥(backend) remove outdated GitHub workflow
Clean up CI/CD by deleting obsolete workflow file that is no longer
needed or maintained since we deploy project through private repo.
2025-07-07 11:02:50 +02:00
lebaudantoine e4e4fcbbfc 🔖(minor) bump release to 0.1.27
White label frontend. Docs is missing, will be
written shortly after the v0.1.27 release.
2025-07-04 23:41:47 +02:00
lebaudantoine 8929ec5714 ♻️(frontend) use LiveKit mobile detection in noise reduction hook
Replace custom mobile browser detection with livekit-client's built-in
isMobile() function for consistency and better reliability.
2025-07-02 11:07:53 +02:00
soyouzpanda 26045bbffa 🔧(backend) support _FILE for secret environment variables
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`.
2025-07-01 13:41:02 +02:00
lebaudantoine 641a311bca ️(frontend) add accessible label to "clear effect" button
Add missing aria-label or tooltip to clear effect button to provide context
for screen-reader users.
2025-06-30 19:10:41 +02:00
lebaudantoine 0d84b1c9ad 🎨(frontend) use regex literals instead of RegExp constructor
Replace `new RegExp()` constructor calls with regex literal
notation (`/pattern/flags`) following TypeScript best practices.
Improves readability and performance while maintaining
equivalent functionality.
2025-06-30 19:10:41 +02:00
lebaudantoine 4255308010 🎨(frontend) mark non-reassigned private attributes as readonly
Add readonly modifier to private class attributes that are never reassigned
after initialization. Improves code safety and clearly communicates immutable
intent to other developers.
2025-06-30 19:10:41 +02:00
lebaudantoine e20619d9a2 🔥(frontend) delete empty constructor from noise reduction class
Remove unnecessary empty constructor that provides no functionality beyond
default constructor behavior. Simplifies class definition and reduces
boilerplate code.
2025-06-30 19:10:41 +02:00
lebaudantoine 4a6b84ed50 🎨(frontend) remove redundant React fragments
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.
2025-06-30 19:10:41 +02:00
lebaudantoine b058e6add9 🎨(frontend) replace logical OR with nullish coalescing operator
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.
2025-06-30 19:10:41 +02:00
lebaudantoine b265c3c7cb 🔥(frontend) delete duplicated frontend imports
Remove duplicate import statements to improve code clarity and potentially
reduce bundle size through better tree-shaking optimization.
2025-06-30 19:10:41 +02:00
lebaudantoine 459280b384 ️(backend) clean package manager cache in Docker builds
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.
2025-06-30 17:55:55 +02:00
lebaudantoine 9d01dde9e4 🧪(backend) fix unreachable assertion after expected exception
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.
2025-06-30 17:55:55 +02:00
lebaudantoine de92d7d5ac 🐛(backend) prevent regex from matching empty string
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.
2025-06-30 17:55:55 +02:00
lebaudantoine 077d38f5e3 ⚰️(backend) remove apps.py
Legacy code, never used.
2025-06-30 17:55:55 +02:00
lebaudantoine 3e315e92fa 🎨(backend) simplify boolean comparisons by using opposite operators
Replace inverted boolean comparisons (not ... ==) with direct opposite
operators (!=) to improve code readability and reduce unnecessary
complexity in conditional statements.
2025-06-30 17:55:55 +02:00
lebaudantoine 5ef38fcba6 🎨(docker) sort package arguments alphabetically in Dockerfiles
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.
2025-06-30 17:55:55 +02:00
lebaudantoine ea754e96c9 📝(doc) add missing documentation for new backend env variables
Complete installation guide by documenting previously undocumented
environment variables for proper configuration.
2025-06-26 20:19:41 +02:00
lebaudantoine e692a0cf8a 📝(doc) format env variable table with even column widths
Improve documentation readability by standardizing table column spacing
in installation guide.
2025-06-26 20:19:41 +02:00
lebaudantoine 46eee4ce9d ✏️(frontend) fix typo and capitalize sentence start
Correct capitalization error in text to follow proper grammar conventions.
2025-06-26 20:19:41 +02:00
lebaudantoine 5c2305d710 👷(frontend) add temporary CI workflow for DINUM frontend image
Create build and push pipeline for custom DINUM image to test white-label
deployment process. Will be moved to separate repo later.
2025-06-26 20:19:41 +02:00
lebaudantoine fb6b6f2b03 (tilt) add Tilt environment for testing DINUM frontend image
Introduce new development environment to test custom DINUM image locally
and validate white-label customizations.
2025-06-26 20:19:41 +02:00
lebaudantoine 77e7e9cdd4 (frontend) build specialized DINUM image from generic frontend
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.
2025-06-26 20:19:41 +02:00
lebaudantoine ac2451e327 🔧(frontend) set LaSuite Meet as default white-label logo
Update default branding to use LaSuite Meet logo for white-label
deployments before custom overrides are applied.
2025-06-26 20:19:41 +02:00
lebaudantoine e356dcb4c3 ♻️(frontend) rename VisioIcon to CameraIcon for clarity
Replace misleading component name that suggested brand-specific usage.
Generic camera icon is reusable across white-label versions.
2025-06-26 20:19:41 +02:00
lebaudantoine 2699edeaad 🚚(frontend) move logo to public folder for deployment customization
Relocate logo asset to enable easy branding override when rebuilding
images for different deployments.
2025-06-26 20:19:41 +02:00
lebaudantoine d417c21d77 🔥(frontend) remove unused play icon asset
Clean up codebase by removing unnecessary icon file to reduce bundle size
and eliminate dead assets.
2025-06-26 20:19:41 +02:00
lebaudantoine 830da365c4 🚚(frontend) move slider assets to public folder with simplified names
Relocate and rename slider assets for easier customization when rebuilding
images. Enables deployments to override branding elements more simply.
2025-06-26 20:19:41 +02:00
lebaudantoine b33df66158 🔧(frontend) make web app manifest optional
Add configuration to conditionally include manifest article,
allowing deployments to customize or disable MoreLink component.
2025-06-26 20:19:41 +02:00
lebaudantoine 211e05a0cb 🌐(frontend) remove hardcoded "visio" references from translations
Rewrite copy to avoid direct product name mentions where possible. Use
env variable for unavoidable brand references to enable proper
customization for different deployments.
2025-06-26 20:19:41 +02:00
lebaudantoine 018eec8a46 🔧(frontend) make app title customizable with env variable override
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.
2025-06-26 20:19:41 +02:00
lebaudantoine e01b1713c4 🔧(frontend) make transcription beta registration form optional
Add configuration to disable transcription beta form for self-hosted
deployments that don't offer this feature. Quick implementation, needs
refinement.
2025-06-26 20:19:41 +02:00
lebaudantoine 1b9af5bf6d 🎨(frontend) replace hardcoded hex values with design tokens
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.
2025-06-26 20:19:41 +02:00
Emmanuel Pelletier 260eab23be 💄(proconnect) replace all proconnect buttons when env is off
The home button was already updated but I missed a few places where it
was also used.
2025-06-26 20:19:41 +02:00
lebaudantoine 98de4f9145 ♻️(frontend) extract hardcoded domain to use dynamic window origin
Replace hardcoded visio.numerique.gouv.fr with automatic detection based on
window.location.origin for better environment flexibility.
2025-06-26 20:19:41 +02:00
lebaudantoine c82168b6c0 🌐(frontend) remove hardcoded DINUM-specific URLs from support forms
Replace instance-specific URLs with configurable values to make the
application more generic and reusable for other deployments.
2025-06-26 20:19:41 +02:00
Emmanuel Pelletier ba286724f3 💄(fonts) use system fonts as default
We don't really need Source Sans as default, system font is enough
2025-06-26 20:19:41 +02:00
Emmanuel Pelletier bbd700270f 🔧(homepage) let people use a simple login button instead of proconnect
This is done to have people self-hosting meet be able to show a simple
"login" button instead of having the ProConnect branding
2025-06-26 20:19:41 +02:00
Emmanuel Pelletier 15330ad4e1 🔧(env) disable the DINUM-specific footer by default
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 :)
2025-06-26 20:19:41 +02:00
Emmanuel Pelletier 4db3e205d2 💄(frontend) remove Marianne font
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.
2025-06-26 20:19:41 +02:00
Emmanuel Pelletier dd0b570fea 💄(header) remove the French gov motto + marianne from header
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
2025-06-26 20:19:41 +02:00
Emmanuel Pelletier 3088299c0b 🔧(env) add a way to load a custom css file to ease up UI customization
This is the first step in removing DINUM-related styling of the default
meet install
2025-06-26 20:19:41 +02:00
lebaudantoine d1bb414cb4 🔖(minor) bump release to 0.1.26
Add noise reduction with RNNoise.
New feature needs to be battle tested,
it's protected with a feature flag.
2025-06-25 22:40:01 +02:00
lebaudantoine 513f3c588a 🚩(frontend) add noise reduction availability hook with feature flag
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.
2025-06-25 22:21:23 +02:00
lebaudantoine b407bfda07 🐛(frontend) default noise reduction to disabled for existing users
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.
2025-06-25 22:21:23 +02:00
lebaudantoine 3de4cc01dc (frontend) disable noise reduction on mobile devices
Prevent enabling noise reduction on mobile to avoid performance issues
from resource-intensive audio processing.
2025-06-25 22:21:23 +02:00
lebaudantoine 1fe1a557ad (frontend) add hook to manage noise reduction processor toggling
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.
2025-06-25 22:21:23 +02:00
lebaudantoine fb92e5b79f (frontend) add noise reduction toggle setting with beta label
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.
2025-06-25 22:21:23 +02:00
lebaudantoine e71bc093bd (frontend) add RNNoise processor for meeting noise suppression
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.
2025-06-25 22:21:23 +02:00
lebaudantoine 43df855461 (frontend) add @timephy/rnnoise-wasm for noise suppression
Install wrapper around Jitsi's RNNoise implementation for easier reuse.
Note: Library may not properly release WebAssembly resources based on
code review.
2025-06-25 22:21:23 +02:00
lebaudantoine 12fc33d30a 🔖(minor) bump release to 0.1.25
Fix chat issue livekit/components-js#1173
Bump backend dependencies
Switch to python v13
2025-06-25 19:59:34 +02:00
lebaudantoine 892a98193d 🎨(backend) format sources and clean up ruff configuration
Apply formatting changes from recent ruff upgrade and remove obsolete
ignored error rules that are no longer needed.
2025-06-25 15:02:44 +02:00
lebaudantoine c5379f29e7 (backend) remove unused june-analytics-python dependency
Clean up dependencies by removing unused analytics package to reduce
bundle size and eliminate unnecessary maintenance overhead.
2025-06-25 15:02:44 +02:00
lebaudantoine 2fddc82333 🔧(backend) fix Redis dependency conflict by downgrading to v5.2.1
Resolve ResolutionImpossible error where meet requires redis==6.2.0
but kombu[redis] 5.5.x requires redis<=5.2.1. Downgrade to redis==5.2.1
satisfies overlapping constraints and testing confirms compatibility.

Pin the redis dependency.
2025-06-25 15:02:44 +02:00
renovate[bot] c9ba6cbc05 ⬆️(dependencies) update python dependencies 2025-06-25 15:02:44 +02:00
lebaudantoine 76807a54f2 🚑️(frontend) bump livekit-react-components to fix critical chat issue
Urgent update to resolve chat functionality problems.

Refs: livekit/components-js#1173, #1174
2025-06-25 14:31:43 +02:00
lebaudantoine 15aff4db8e 🌐(frontend) add missing internationalization for "micro désactivé"
Fix overlooked French text that wasn't properly internationalized in
the microphone status display.
2025-06-24 20:09:02 +02:00
lebaudantoine 27a0128b2a 🐛(frontend) fix audio device ID persistence from settings panel
Ensure user's audio device selection is properly saved to localStorage
when changed through settings to maintain preference across sessions.
2025-06-24 20:09:02 +02:00
lebaudantoine 4a18e188e4 ♻️(frontend) refactor usePersistentUserChoice to fix state sync issues
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.
2025-06-24 20:09:02 +02:00
lebaudantoine 1cd8fd2fc6 🔒️(backend) enhance participant ID serialization in lobby per audit
Improve participant ID handling in lobby serialization following security
auditor recommendations to prevent potential data exposure.
2025-06-24 13:57:53 +02:00
lebaudantoine 64eadadaef 🔒️(backend) clarify administrator role checking function names
Rename vague functions to explicitly indicate administrator permission checks,
or owner ones. Prevents developer confusion and potential security misuse
per auditor recommendations.
2025-06-24 13:57:53 +02:00
lebaudantoine 6e48f8f222 🔒️(backend) remove realistic password data from test fixtures
Replace test fixture passwords that resembled real credentials to avoid
confusion during security audits and follow security best practices.
2025-06-24 13:57:53 +02:00
lebaudantoine 866a2cea20 🔒️(backend) specify explicit imports to limit security exposure
Replace wildcard imports with specific function imports, particularly for
OS package which could expose dangerous functions. Follows security audit
recommendations to minimize attack surface.
2025-06-24 13:57:53 +02:00
lebaudantoine 17b1dde050 ♻️(summary) dry docker image summary by extracting base image name
Eliminate duplication by using variables for base image references to
improve maintainability and reduce configuration redundancy.
2025-06-23 16:36:02 +02:00
lebaudantoine 0b25374cef ⬆️(docker) upgrade backend image to python 3.13
Python 3.13 is now stable, our libraries are compatible with it. We also
upgrade the alpine version and node one used in the backend.
2025-06-23 16:36:02 +02:00
lebaudantoine fb8b2d752b 🔒️(backend) upgrade Django to 5.2.3 for security compliance
Update Django and related libraries per security auditor recommendations
as current version is aging. Django 5.2.3+ changed email validation per

Remove failing test cases affected by stricter validation.

Refs:
- https://code.djangoproject.com/ticket/36014
- https://github.com/django/django/commit/c068f000
2025-06-23 14:59:01 +02:00
lebaudantoine 3c0a712f45 🔖(minor) bump release to 0.1.24
Fix blurry screenshare issue.
See livekit/client-sdk-js#1556
2025-06-22 19:54:01 +02:00
lebaudantoine 17795c69d6 🩹(frontend) add temp workaround for LiveKit useChat breaking changes
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
2025-06-20 23:20:47 +02:00
lebaudantoine d1b0378a45 ⬆️(frontend) bump livekit-client from 2.11 to 2.13
Fix critical Chrome screenshare bug and other issues. See:
https://github.com/livekit/client-sdk-js/pull/1556

Breaking change: Chat functionality affected by behavior changes.
Discussion: https://github.com/livekit/components-js/issues/1158
2025-06-20 23:20:47 +02:00
lebaudantoine ef4dcf57b0 📈(frontend) add analytics tracking for connection events
Implement connection event tracking to monitor user connectivity
patterns and identify potential issues.
2025-06-12 14:54:51 +02:00
lebaudantoine bbb6e4f317 ♻️(frontend) refactor useConnectionObserver to track session time
Add session duration tracking and consolidate all disconnect events
(including client-initiated) with timing data for comprehensive
connection analytics.
2025-06-12 14:54:51 +02:00
lebaudantoine 77d2365a61 🐛(backend) fix OIDC returnTo parameter validation in Docker compose
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.
2025-06-11 18:34:41 +02:00
lebaudantoine e6caa0a2fd 📈(frontend) add analytics for disconnect/reconnect events
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.
2025-06-11 18:28:29 +02:00
lebaudantoine f9614fc108 🩹(backend) default CORS_ALLOW_ALL_ORIGINS to False
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.
2025-06-10 16:16:55 +02:00
Jacques ROUSSEL 9d516bf638 🚸(helm) improve helm chart
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.
2025-06-06 16:52:30 +02:00
lebaudantoine 5bac9a1d59 🔒️(frontend) hide Nginx server version in error responses
Remove version disclosure in /assets/ error pages identified by security
auditor to prevent information leakage vulnerability.
2025-06-03 15:17:21 +02:00
lebaudantoine 61aa3c79c5 🩹(backend) replace requests exception with urllib3 ones
My bad, I caught the wrong exception, issue is still raising in Sentry.
It fixes commit #2a7d963f
2025-05-28 10:49:03 +02:00
lebaudantoine 0c6cd8223d 🔖(minor) bump release to 0.1.23
Misc updates and fixes.
2025-05-27 21:50:21 +02:00
lebaudantoine b692314646 🐛(backend) handle empty transcription files gracefully
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.
2025-05-27 21:27:09 +02:00
lebaudantoine e816475981 🚨(summary) lint backend sources
Run ruff format to fix linter warnings.
2025-05-27 19:12:37 +02:00
lebaudantoine 8d1f01645a 🚸(frontend) add notification with recording handling details
Display notification clarifying recording is processing and show which email
will receive completion notification. Reduces user mental load per
@sampaccoud's feedback.
2025-05-27 19:12:37 +02:00
lebaudantoine 29a46a413e 🚸(frontend) clarify transcription/recording access restrictions in UI
Make it explicit that non-owner/admin users cannot enable transcription.
Beta feature behavior that may change in future versions.
2025-05-27 19:12:37 +02:00
lebaudantoine b618b2347f 🚸(frontend) clarify automatic recording save process in UI
Add explicit messaging that recording save is automatic and continues
even after leaving meeting. Reduces user anxiety based on feedback
from Samuel Paccoud.
2025-05-27 19:12:37 +02:00
lebaudantoine 7038f2a85d 🐛(backend) fix KeyError crash when role is undefined in request data
Use dict.get() instead of direct key access to prevent server crashes when
role field is missing. Fix inherited from magnify project codebase.
2025-05-27 16:20:36 +02:00
lebaudantoine b7dfafaf47 🔇(backend) downgrade marketing exceptions from error to warning level
Replace logger.exception with logger.warning to reduce Sentry noise for
unavoidable timeout errors that developers cannot act upon.
2025-05-27 15:15:46 +02:00
lebaudantoine 2a7d963f50 🥅(backend) catch request timeout and Brevo contact addition errors
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.
2025-05-27 15:15:46 +02:00
lebaudantoine 980117132f (backend) add 'sandbox' configuration class for demo environment
Create dedicated config for sandbox environment used for external demos,
bug bounties, and security auditing purposes.
2025-05-27 15:06:02 +02:00
lebaudantoine 7a8b50b5f0 ♻️(backend) use sentry tags instead of extra scope
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.
2025-05-27 15:06:02 +02:00
lebaudantoine 409e403581 🚸(backend) display recording owners directly in admin list view
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.
2025-05-26 14:45:57 +02:00
lebaudantoine 0c0eed6f59 🚸(backend) enhance recording search UX in admin debugging interface
Improve user experience when searching for recording to streamline admin
troubleshooting workflows.
2025-05-26 14:45:57 +02:00
lebaudantoine 750b7f86b4 🚸(backend) replace user select with autocomplete in admin interface
Convert basic select to autocomplete for adding users to rooms. Improves
admin UX when managing 10k+ users
2025-05-26 14:45:57 +02:00
lebaudantoine 9569c58315 🚸(backend) enhance room search UX in admin debugging interface
Improve user experience when searching for rooms to streamline admin
troubleshooting workflows.
2025-05-26 14:45:57 +02:00
Baptiste Massemin 922a968418 🔧(helm) fix the path prefix of the backend ingress
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.
2025-05-23 19:15:33 +02:00
lebaudantoine 48e6cef763 ⬇️(frontend) rollback LiveKit component library from 2.9.0 to 2.8.1
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.
2025-05-23 19:05:51 +02:00
lebaudantoine ac4ec6c752 📝(backend) update documentation on backend options
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.
2025-05-23 15:24:01 +02:00
lebaudantoine 7454d44329 🔥(ci) remove unused Crowdin i18n steps
We're not using Crowdin yet and failing CI steps confuse external
contributors. Clean up pipeline to remove unnecessary complexity.
2025-05-23 14:37:16 +02:00
Jacques ROUSSEL 1e3e7de753 🔒️(front) improve docker image security
Cyberwatch reported security issues with the frontend Docker image.
2025-05-23 14:25:06 +02:00
lebaudantoine 4c2eb31a6a ✏️(backend) fix typo in FRONTEND_IS_SILENT_LOGIN_ENABLED env var
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.
2025-05-20 22:54:51 +02:00
lebaudantoine a2a44a6546 🌐(frontend) rename "appliquer des effets" to "effets d'arrière plan"
Update French translation of effects feature based on user feedback to better
reflect its purpose as background effects rather than generic effects.
2025-05-20 22:54:34 +02:00
lebaudantoine f1fa99f918 (backend) allow setting session cookie age via env var
We want to be able to increase the duration of the cookie session
by setting an environment variable.
2025-05-20 13:56:22 +02:00
lebaudantoine 4a6e65d4be 🐛(frontend) restore user language synchronization between front and back
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.
2025-05-20 13:49:54 +02:00
lebaudantoine c8772bb1ad 🐛(backend) update pin code tests after increasing max retry limit
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.
2025-05-19 11:13:59 +02:00
lebaudantoine d54925bd97 🔧(helm) update ASR model name after switch to WhisperX
Correct Automatic Speech Recognition model naming configuration to reflect
the transition from insanely-fast-whisper to WhisperX implementation.
2025-05-19 11:13:59 +02:00
lebaudantoine e9f3e27058 🌐(backend) improve French translations for technical terminology
Refine French translations to be less literal and preserve English terms for
standard technical concepts. Enhances clarity and maintains industry
terminology conventions.
2025-05-19 11:13:59 +02:00
lebaudantoine 0abbe4a26f 🌐(backend) add missing translations for room PIN functionality
Add internationalization support for previously untranslated strings related
to room PIN code logic. Ensures consistent localization across all user-
facing room access features.
2025-05-19 11:13:59 +02:00
lebaudantoine 3e93f5924c (backend) add 10-digit PIN codes on rooms for telephony
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.
2025-05-15 17:17:55 +02:00
Jacques ROUSSEL d70dc41643 ️(tilt) fix cp for linux users
Fix the cp permission issue for linux users
2025-05-15 17:17:07 +02:00
lebaudantoine 6e81b55403 (frontend) add prayer hands emoji reaction
Implement new 🙏 reaction in response to user requests for more diverse
emotional expression options.

Requested by a beta user.
2025-05-15 15:44:06 +02:00
keda82 b8cc21debc 📝(backend) improve deployment documentation with missing prerequisites
Add critical setup requirements including kubectl installation, script download
instructions, executable permissions for mkcert and Docker, and clarify
local-only access limitation.
2025-05-15 15:20:57 +02:00
lebaudantoine 36ddb84982 🐛(backend) fix ingress path to use specific API path
Replace generic '/api' path with versioned '/api/v' pattern in Helm
ingress template to ensure proper routing for backend requests.

It closes #539
2025-05-15 14:57:50 +02:00
lebaudantoine 496ae12fa9 ♻️(backend) remove lazy from languages field on User model
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
2025-05-15 13:50:25 +02:00
lebaudantoine ae4ef48d05 ♻️(backend) remove internationalization from non-user-facing strings
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.
2025-05-15 12:08:41 +02:00
lebaudantoine 952104fd82 🌐(i18n) add German language support
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.
2025-05-15 12:04:17 +02:00
lebaudantoine 60dc8bf174 🌐(backend) update translation files after authentication refactoring
Refresh Django translation files to remove strings from authentication
system refactoring and recent minor backend changes.
2025-05-15 12:04:17 +02:00
renovate[bot] d54a61cbcc ⬆️(dependencies) update vite [SECURITY] 2025-05-12 16:33:05 +02:00
lebaudantoine f90a1e3549 🚨(frontend) resolve TypeScript build errors after dependencies upgrade
Fix type checking failures caused by recent dependency updates.
2025-05-12 16:00:23 +02:00
renovate[bot] 572b80d3fe ⬆️(dependencies) update js dependencies 2025-05-12 16:00:23 +02:00
Ghislain LE MEUR 82d840a15f 🔧(helm) remove affinity for jobs
Affinity isn't necessary for jobs.
Please have a look to PR #509
2025-05-12 14:34:40 +02:00
renovate[bot] 500c690fa0 ⬆️(dependencies) update django to v5.1.9 [SECURITY] 2025-05-12 14:18:52 +02:00
lebaudantoine 577111d864 🔒️(frontend) prevent disconnected users from accessing recording tools
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.
2025-05-12 11:46:32 +02:00
lebaudantoine 563f1e4c0f (frontend) improve meeting code input accessibility for touch devices
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
2025-05-12 10:34:49 +02:00
lebaudantoine 2e8407ac7c 🚸(frontend) visually differentiate user's reactions from others
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.
2025-05-05 23:27:22 +02:00
lebaudantoine 2af9ec0d85 ♻️(frontend) replace UTF emoji characters with designer-created images
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.
2025-05-05 23:27:22 +02:00
lebaudantoine b70799c2db 🔖(minor) bump release to 0.1.22
Upgrade track processor to benefits from webgl.
2025-05-05 23:26:49 +02:00
lebaudantoine 0facfc11be 🐛(frontend) fix video distortion when stopping processors
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.
2025-05-03 19:13:29 +02:00
lebaudantoine 8023e44f71 🥚(frontend) add Konami code detector to unlock April Fool's effects
Implement easter egg that reveals fun features originally created for
April Fool's Day when users enter the Konami sequence.
2025-05-03 19:13:29 +02:00
lebaudantoine b27c5e9b92 🏗️(frontend) decouple landmark processor from background processors
Separate landmark processor logic to avoid entanglement with background
processing. Ensures future refactoring can replace custom background
implementation without affecting landmark functionality.
2025-05-03 19:13:29 +02:00
lebaudantoine 3e5c4c32e9 🔥(frontend) remove version upgrade warning for LiveKit WebGL update
Delete obsolete user notification now that the stable WebGL-powered version
with improved performance has been officially released.
2025-05-03 19:13:29 +02:00
lebaudantoine 551207ab86 🩹(frontend) add conditional stopProcessor call for cross-browser compat
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.
2025-05-03 19:13:29 +02:00
lebaudantoine 0aa47fcd1e ⬆️ (frontend) upgrade track processor to enable WebGL support
Update dependency to gain improved browser compatibility and WebGL
acceleration for better video processing performance.
2025-05-03 19:13:29 +02:00
virgile-deville c289f79d8e 📝(readme) add matrix room to readme
So that community members can gather and chat about meet

Signed-off-by: virgile-deville <virgile.deville@beta.gouv.fr>
2025-05-03 19:05:05 +02:00
lebaudantoine b79fa14919 🔖(minor) bump release to 0.1.21
Refactor authentication.
Address few bug bounties.
2025-05-01 16:49:30 +02:00
lebaudantoine c7c0df5b6d 🚸(frontend) add alert dialog for recording start failures
Implement modal alert dialog when recording initialization fails. Provides
clear error feedback to users when API cannot start recording process,
improving error state communication.
2025-04-30 14:54:41 +02:00
lebaudantoine cb00347be6 🚸(frontend) show spinner immediately on recording request initiation
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.
2025-04-30 14:54:41 +02:00
lebaudantoine bcb004ab4b 🥅(backend) add broad exception handling for non-twirp error in recording
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.
2025-04-30 14:54:41 +02:00
lebaudantoine 422f838899 🔒️(backend) remove accesses list from room serializer for non-admins
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.
2025-04-30 14:13:30 +02:00
lebaudantoine 462c6c50e5 🔒️(backend) disable BrowsableAPIRenderer to prevent information leakage
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.
2025-04-30 14:13:30 +02:00
lebaudantoine 63565b38c3 ♻️(backend) simplify ResourceAccess viewset implementation
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.
2025-04-30 14:13:30 +02:00
Quentin BEY 10d759bdbb (backend) add django-lasuite dependency
Use the OIDC backend from the `django-lasuite` library
2025-04-28 23:38:45 +02:00
lebaudantoine 51f1f0ebbf 🔖(minor) bump release to 0.1.20
Misc fixes.
2025-04-28 23:13:31 +02:00
lebaudantoine 9e27d0f345 🚑️(frontend) throttle emoji reaction sending to prevent DoS attacks
Apply rate limiting to emoji reactions after discovering malicious users using
auto-clickers to flood the system and crash other participants' apps.
2025-04-28 20:08:47 +02:00
lebaudantoine 978d931bd7 (frontend) create hook for rate-limiting functions that could spam UI
Implement custom hook to throttle JavaScript function calls and prevent
interface performance degradation.
2025-04-28 20:08:47 +02:00
lebaudantoine 0c811222d4 ♻️(frontend) change Panel keepAlive default to false for all side panels
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.
2025-04-28 18:04:26 +02:00
lebaudantoine 94171dcb82 (frontend) add keepAlive option to Panel component
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.
2025-04-28 18:04:26 +02:00
lebaudantoine 56c1cd98fa 🔧(frontend) make feedback form configurable via backend settings
Implement conditional rendering that hides all feedback-related UI components
when feedback is disabled in backend configuration.

Also, feedback URL is now customizable.
2025-04-28 17:37:31 +02:00
lebaudantoine f2e6edb90d 🚩(frontend) disable meeting rating when analytics is not configured
Hide the rating module in the feedback route when analytics service is
unavailable to self host La Suite Meet without analytics.
2025-04-28 17:37:31 +02:00
lebaudantoine bc76c44fe9 ♻️(frontend) refactor ParticipantName component for internationalization
Component now supports i18n. The participant tile needs further refactoring as
it still mixes LiveKit CSS with custom styling.
2025-04-28 16:49:06 +02:00
lebaudantoine e519f00342 🔥(frontend) remove duplicated aria-label from join screen username input
Eliminate redundant accessibility attribute that wasn't providing relevant
information to screen readers.
2025-04-28 16:48:52 +02:00
lebaudantoine 2246bb7782 ️(frontend) lower silent login retry interval from 5 min to 30 sec
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.
2025-04-28 13:21:17 +02:00
lebaudantoine e210f26f9c 🐛(frontend) prevent silent login in webmail iframe integration
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.
2025-04-28 13:21:17 +02:00
lebaudantoine 888dfe76c7 🐛(backend) resolve backchannel calls to LiveKit in docker-compose
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.
2025-04-25 12:52:14 +02:00
lebaudantoine ae17fbdaa8 ♻️(backend) extract livekit API client creation to reusable utility
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.
2025-04-24 18:05:52 +02:00
lebaudantoine 2ef95aa835 ♻️(backend) update BaseEgress to use custom session from livekit-api
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.
2025-04-24 18:05:52 +02:00
lebaudantoine a83e5c4b1c 🔥(backend) delete overly complex BaseEgress tests
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.
2025-04-24 18:05:52 +02:00
lebaudantoine 9cc79ba159 🩹(backend) correct typo in WorkerConfig parameter name
Fix minor spelling error in WorkerConfig parameter that had no functional
impact but improves code clarity and consistency.
2025-04-24 18:05:52 +02:00
lebaudantoine c63adf9c8c ⬆️(backend) upgrade livekit-api to latest version
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.
2025-04-24 18:05:52 +02:00
lebaudantoine 9366c8c4dd 🔖(minor) bump release to 0.1.19
Introduce screen recording.
2025-04-23 23:45:20 +02:00
lebaudantoine 3636bfa703 (frontend) display recording expiration status in frontend
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.
2025-04-23 19:52:29 +02:00
lebaudantoine 34c14cc516 (mail) include expiration information in recording notification emails
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.
2025-04-23 19:52:29 +02:00
lebaudantoine 1a0051a90b (backend) implement recording expiration mechanism
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.
2025-04-23 18:53:42 +02:00
renovate[bot] af21478143 ⬆️(dependencies) update vite [SECURITY] 2025-04-23 15:36:44 +02:00
lebaudantoine 986b75ba39 (backend) personalize recording notification emails by user preferences
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.
2025-04-23 15:36:44 +02:00
lebaudantoine df55fb2424 🐛(backend) rename copy-pasted unit tests
Fix inconsistent test naming resulting from copy-pasted examples. Rename
tests to properly reflect their actual testing purpose and improve code
maintainability.
2025-04-23 14:17:09 +02:00
lebaudantoine ec114808b2 (frontend) add hook to sync user preferences
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.
2025-04-23 14:17:09 +02:00
lebaudantoine 7f0e866eac ♻️(frontend) rename isLoading to isConfigLoading for clarity
Rename generic "isLoading" variable to more specific "isConfigLoading" to
accurately reflect its purpose. Improves code readability by making state
variable names more explicit.
2025-04-23 14:17:09 +02:00
lebaudantoine 8e0e286bc4 (backend) serialize user language and timezone for frontend use
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.
2025-04-23 14:17:09 +02:00
lebaudantoine ee9148fe9f 🌐(backend) add and compile Dutch translations for backend
Add Dutch language translations for backend text strings and compile
translation files for production use. Improves localization support for
Dutch-speaking users.
2025-04-23 14:17:09 +02:00
lebaudantoine c863bc7456 🌐(backend) add and compile English translations for backend
Add English language translations for backend text strings and compile
translation files for production use. Improves localization support for
English-speaking users.
2025-04-23 14:17:09 +02:00
lebaudantoine eab361326f 🌐(backend) add and compile French translations for backend
Add French language translations for backend text strings and compile
translation files for production use. Improves localization support for
French-speaking users.
2025-04-23 14:17:09 +02:00
lebaudantoine 86c82f584c 🌐(backend) convert translation tags to blocktrans for quoted strings
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.
2025-04-23 14:17:09 +02:00
lebaudantoine af6ac954e9 🌐(backend) add Dutch language support to backend
Add Dutch (nl) language configuration to backend to match available frontend
languages. Ensures consistent language options across the entire application.
2025-04-23 14:17:09 +02:00
lebaudantoine 35cc6cd902 🌐(backend) regenerate translation files including email templates
Update translation files to include previously missed strings from email
templates. Ensures complete localization coverage across all backend
components including notification emails.
2025-04-23 14:17:09 +02:00
lebaudantoine 9cb7b0f154 ️(frontend) improve mic button accessibility in participant list
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.
2025-04-23 10:02:41 +02:00
lebaudantoine d105603a9b 🔖(helm) bump Helm chart version after job name modifications
Increment Helm chart version to reflect changes to backend job component
naming. Ensures proper versioning of configuration changes in deployment
pipeline.
2025-04-22 18:26:40 +02:00
lebaudantoine d2da1e37b9 🚚(helm) specify unique component names for all backend jobs
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.
2025-04-22 18:26:40 +02:00
lebaudantoine 0206762e6d 🚚(helm) rename migration job to more explicit 'backend_job_migrate'
Rename backend migration job to a more descriptive name that clearly
indicates its purpose. Improves code clarity and makes deployment
configuration more self-documenting.
2025-04-22 18:26:40 +02:00
lebaudantoine c4fe341a74 🔧(backend) make data directory location configurable via env var
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.
2025-04-22 16:25:59 +02:00
lebaudantoine bc53916c68 🚸(frontend) prevent auth screen flashing during user data fetch
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.
2025-04-18 11:05:47 +02:00
lebaudantoine 886919c23d 🐛(backend) update media auth endpoint to check correct recording status
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.
2025-04-18 10:48:44 +02:00
lebaudantoine 4afbd9ba7f 🔐(helm) bump chart version
Bump chart version to publish a new one with media related
logic (ingress, service, etc…)
2025-04-18 10:01:05 +02:00
lebaudantoine a5fb3b910f (frontend) add meeting info side panel with copy functionality
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.
2025-04-18 09:42:09 +02:00
lebaudantoine d1a17d2aa9 🚸(frontend) add error handling for unsaved recording states
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.
2025-04-17 16:58:33 +02:00
lebaudantoine e5af74685e (frontend) introduce dedicated recording download page
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.
2025-04-17 16:58:33 +02:00
lebaudantoine 06462a55b0 (frontend) create utility for media download URL generation
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.
2025-04-17 16:58:33 +02:00
lebaudantoine 67967f00b5 (frontend) add date formatting utility function
Create reusable utility function to format dates into specified patterns.
Provides consistent date formatting across the application.
2025-04-17 16:58:33 +02:00
lebaudantoine a8053b46cd (frontend) implement API endpoint for recording details
Add new API call to retrieve detailed information about recordings.
Enables frontend to access metadata and status information needed for
download interfaces.
2025-04-17 16:58:33 +02:00
lebaudantoine b927be9f16 (frontend) serialize recording key for frontend download links
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.
2025-04-17 16:58:33 +02:00
lebaudantoine 2092d586ab 🎨(backend) harmonize decorator actions to lowercase format
Standardize all method decorator actions to lowercase format following DRF
documentation conventions. Creates consistent style across codebase.
2025-04-17 11:22:34 +02:00
lebaudantoine 132a1fbac7 🩹(backend) update HasPrivilegesOnRoom permission error message
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.
2025-04-17 11:22:34 +02:00
lebaudantoine 90b4449040 (backend) add email invitation endpoint for meeting participants
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.
2025-04-17 11:22:34 +02:00
lebaudantoine 205bb3aac1 (backend) introduce configuration for app base URL
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.
2025-04-17 11:22:34 +02:00
lebaudantoine d5c9ee79f4 🩹(backend) fix email domain environment variable
Value wasn't properly set to a domain, but to an URL. Fix it.
2025-04-17 11:22:34 +02:00
lebaudantoine 1ef2bd99d8 🩹(backend) fix wrong environment variable
Oopsie, wrongly copy-pasted a Django settings leading in
using the wrong environment variable for a new setting.
I should have read my code;
2025-04-17 11:22:34 +02:00
lebaudantoine acbc5dba73 🩹(backend) fix exception messages
Oopsie, badly copy-pasted code when creating new serializer.
Not critical.
2025-04-17 11:22:34 +02:00
lebaudantoine 3438b4608c 🚸(frontend) make recording state toast clickable to reopen side panel
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.
2025-04-16 23:41:34 +02:00
lebaudantoine b4484540f7 🚸(frontend) add subtle indicator for active tools
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.
2025-04-16 23:41:34 +02:00
lebaudantoine 7021272075 🔒️(backend) remove personal data from email failure logs
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.
2025-04-16 23:41:34 +02:00
lebaudantoine d92adb7435 🚸(frontend) differentiate loading and active recording states in toast
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.
2025-04-16 23:41:34 +02:00
lebaudantoine d92c13d85a 🚸(frontend) increase toast visibility for recording status
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.
2025-04-16 23:41:34 +02:00
lebaudantoine 46d60661f1 ♻️(frontend) align RecordingStateToast i18n keys with component name
Update translation keys to match component naming convention for improved
code maintainability and clarity.
2025-04-16 23:41:34 +02:00
lebaudantoine ba20fbe3a5 🚸(frontend) add beta tags to transcript and screen recording features
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.
2025-04-16 23:41:34 +02:00
lebaudantoine f1b45af7d7 🚸(frontend) add loading spinner to recording start button
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.
2025-04-16 23:41:34 +02:00
lebaudantoine 0b6869a4dc 🚸(frontend) add loading spinner for recording save process
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.
2025-04-16 23:41:34 +02:00
lebaudantoine 7278061a80 🔧(backend) update egress worker layout for screen recording
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.
2025-04-16 23:41:34 +02:00
lebaudantoine e5eb1e9916 🔧(backend) add backend toggle for silent login feature
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.
2025-04-16 23:37:04 +02:00
lebaudantoine 4060e891f2 🚸(frontend) add reset button during meeting creation process
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.
2025-04-16 23:35:47 +02:00
lebaudantoine 314468c68d 🚸(frontend) clarify "create a link" button text
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.
2025-04-16 23:35:47 +02:00
lebaudantoine 52a7a6efab 🚸(frontend) add sound notification for lobby
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.
2025-04-16 23:34:55 +02:00
lebaudantoine 83d04c499b ⬆️ (dependencies) upgrade boto3 to more recent version
Update boto3 dependency to latest stable release to benefit from bug fixes,
performance improvements, and expanded AWS service support.
2025-04-16 12:13:42 +02:00
lebaudantoine 41c1f41ed2 (backend) add authenticated recording file access method
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.
2025-04-16 12:13:42 +02:00
lebaudantoine dc06b55693 (backend) enable retrieve viewset on recording model
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.
2025-04-16 12:13:42 +02:00
lebaudantoine 20aceb1932 (backend) add property to check if recording file is saved
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.
2025-04-16 12:13:42 +02:00
lebaudantoine 3671f2a0dd ♻️(backend) encapsulate recording key and extension logic as properties
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.
2025-04-16 12:13:42 +02:00
lebaudantoine d74dd967af ♻️(backend) replace hardcoded file extensions with Python enum
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 …
2025-04-16 12:13:42 +02:00
lebaudantoine 3a4f4e7016 (backend) add recording mode to serialized fields
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.
2025-04-16 12:13:42 +02:00
lebaudantoine b7d964db56 (backend) add email notifications for screen recordings
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.
2025-04-15 13:46:57 +02:00
lebaudantoine 88b7a7dc58 🌐(backend) generate missing translations for backend updates
Regenerate translation files to include all recent backend string changes.
Address backlog of untranslated content that accumulated during recent
development cycles.
2025-04-14 21:00:46 +02:00
lebaudantoine baca9fc001 🌐(frontend) add missing german translations
Oopsie. I forgot some keys for german, add them.
2025-04-11 11:38:21 +02:00
lebaudantoine c432524f2a 🚸(frontend) display option to user with screen recording access
Introduce a feature flag for screen recording to allow gradual
rollout of the feature.
2025-04-11 11:38:21 +02:00
lebaudantoine a079ceef71 🚸(frontend) inform user when recording is saving
Saving a recording can take a bit of time, display a clear message to
inform user it can takes few minutes.
2025-04-11 11:38:21 +02:00
lebaudantoine f0742a0978 📈(frontend) add analytics on screen recording and transcript features
Use posthog to track whether user starts transcript or screen recording.
2025-04-11 11:38:21 +02:00
lebaudantoine fc1b4d7fa7 💄(frontend) replace recording side panel title with proper header
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.
2025-04-11 11:38:21 +02:00
lebaudantoine 46f26eb493 ♻️(frontend) extract recording side panel into a dedicated folder
Extract code elements related to recording into a dedicated folder.
2025-04-11 11:38:21 +02:00
lebaudantoine ff09c3d969 ♻️(frontend) factorize notifyParticipants
Extract notifyParticipants in a proper hook to avoid duplication.
2025-04-11 11:38:21 +02:00
lebaudantoine ba9d22f6c8 ♻️(frontend) extract feature flag into a dedicated enum
Extract code elements related to feature flag into a proper enum
to avoid hardcoded literals.
2025-04-11 11:38:21 +02:00
lebaudantoine 94e71ba15d ♻️(frontend) extract recording api into a dedicated folder
Extract code elements related to recording into a dedicated folder.
2025-04-11 11:38:21 +02:00
lebaudantoine 9a1384b188 ♻️(frontend) rename RecordingStateBadge to RecordingStateToast
Rename component to match existing LiveKit naming conventions like
connectionStateToast. Improves naming consistency.
2025-04-11 11:38:21 +02:00
lebaudantoine 695ac47014 ♻️(frontend) extract recording hooks into a dedicated folder
Extract code elements related to recording into a dedicated folder.
2025-04-11 11:38:21 +02:00
lebaudantoine b3c1deeb9c 🍱(frontend) add La Suite logo
Will be necessary for email notifications, when notifying users their
recording are ready for download.
2025-04-11 11:38:21 +02:00
lebaudantoine c08c3efdbb 🩹(frontend) avoid having the two recording modes concurrently
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.
2025-04-11 11:38:21 +02:00
lebaudantoine 468d09dc3b (frontend) introde the Screen Recording side panel
Offer one new tool to user, the screen recording side panel.
2025-04-11 11:38:21 +02:00
lebaudantoine a22d052f46 ♻️(frontend) generalize recording availability hook for all types
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.
2025-04-11 11:38:21 +02:00
lebaudantoine 9734df9d5d ♻️(frontend) generalize recording state badge for all recording types
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.
2025-04-11 11:38:21 +02:00
lebaudantoine f596aae1e8 ♻️(frontend) generalize transcript notification for all recording types
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.
2025-04-11 11:38:21 +02:00
lebaudantoine 32956f495f ⚰️(frontend) remove dead code
Traces of debugging, never been useful.
2025-04-11 11:38:21 +02:00
lebaudantoine 69381a6c4b 🌐(frontend) prepare translation keys for expanded recording types
Restructure translation keys to support a more extensive set
of recording types in the future.
2025-04-11 11:38:21 +02:00
lebaudantoine d537a4449a 🔖(minor) bump release to 0.1.18
Refactoring of transcription ui + SDK
2025-04-08 23:04:24 +02:00
lebaudantoine 50c9304afe (back) remove url-normalize dependency
We have the dependency url-normalize installed but we don't use it in
our codebase.

(from @lunika on docs)
2025-04-07 21:51:54 +02:00
lebaudantoine 37fe23c0f7 🚸(frontend) enhance transcript copywritting
Simplify the instructions. Also offer a way to user to discover
the feature and register as beta users.
2025-04-04 19:11:33 +02:00
lebaudantoine 255da4bf60 ♻️(frontend) refactor the transcription side panel into a sub menu
Add a new level of nesting while handling side panel.
Code quality is quite poor, we need a better interface.
2025-04-04 19:11:33 +02:00
lebaudantoine 6dccb507d2 🎨(frontend) remove duplicated forms literals
Use a proper constant, which already exists.
2025-04-04 19:11:33 +02:00
lebaudantoine d202a025e7 🚸(frontend) share more information about transcription state
Previous toast state was too naive. Enhance message deliver to
participants.
2025-04-04 19:11:33 +02:00
lebaudantoine ac9ba0df62 💩(frontend) introduce transcription store
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
2025-04-04 19:11:33 +02:00
lebaudantoine 91562d049c ♻️(frontend) introduce a reusable tools sidepanel
tools will be added in the future, let's generalize the sidepanel
previously reserved to transcription.
2025-04-04 19:11:33 +02:00
lebaudantoine 60321296e5 (frontend) introduce a notification for transcription
Main goal: notify participant when the meeting is being recorded.
It helps understand the whole system behavior with clear
notification states.
2025-04-04 19:11:33 +02:00
lebaudantoine ae06873ff5 👔(frontend) update feedback form's URL
Gregoire reworked our framework on user feedbacks.
Update the Grist form's URL.
2025-04-04 15:57:45 +02:00
lebaudantoine 70ffb758c7 ♻️(frontend) refactor Grist forms urls in a single constants file
Consolidate all Grist forms into a single file to improve code organization
and enhance maintainability.
2025-04-04 15:57:45 +02:00
lebaudantoine 33a94da636 🩹(frontend) add a disabled style on tertiary button
Was lacking, necessary in my next jobs working on
transcript side pannel v2.
2025-04-04 15:57:45 +02:00
lebaudantoine aa6757601d 💄(frontend) force having medium font weight buttons
Improve the readability of the buttons by increasing their thickness.
2025-04-04 15:57:45 +02:00
lebaudantoine c26b1b711c (frontend) add external link support to LinkButton component
Enhanced LinkButton with target props for external link usage.
2025-04-04 15:57:45 +02:00
lebaudantoine 3ee33fc2ec ♻️(frontend) parametrize spinner size
Allow passing custom spinner size.
Needed to align the spinner height with an inline button.
2025-04-04 14:31:31 +02:00
lebaudantoine d43b2857c1 🩹(sdk) notify iframe parent when room is gathered through callback
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.
2025-04-04 13:22:12 +02:00
lebaudantoine 3b1b644ef9 ⬆️(frontend) upgrade vite dependency
Necessary for security reasons, CVE-2025-30208.
2025-04-04 11:35:38 +02:00
lebaudantoine ab7a0e1ec2 ⬆️(sdk) upgrade vite dependency in consumer and library
Necessary for security reasons.
2025-04-04 11:35:38 +02:00
renovate[bot] 86a4d68daa ⬆️(dependencies) update django to v5.1.8 [SECURITY] 2025-04-04 10:44:07 +02:00
lebaudantoine de3df889ba (frontend) move support options to menu for a clearer UI
Relocated support options to the menu to keep the interface concise
and reduce visual clutter.
2025-04-04 10:43:51 +02:00
lebaudantoine 7c9fc15359 🚸(frontend) delay tooltip appearance in lateral menu
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.
2025-04-04 10:43:51 +02:00
lebaudantoine a6a67f2752 🍱(readme) update readme to rename Visio to La Suite Meet
Visio is a MS product. In the official documentation call
our product La Suite Meet.
2025-04-03 23:34:49 +02:00
lebaudantoine 00eb52cd3f 🩹(summary) fix bold markdown syntax
Wrong syntaxt to handle bold, instead was italic.
2025-04-03 23:34:36 +02:00
lebaudantoine 6324be9fd3 🩹(frontend) fix missing notification when state is clear
Notify iframe's parent while integrating Visio when state
is cleared. Requested by Eleonore.
2025-04-03 23:33:23 +02:00
lebaudantoine 66f307b7e8 🐛(frontend) rework the calendar integration approach
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.
2025-04-02 12:31:04 +02:00
lebaudantoine 506b3978e1 🧑‍💻(frontend) move dev tool to the bottom left corner
Nothing happens in the bottom left corner.
Avoid hiding features while developing.
2025-04-02 12:31:04 +02:00
lebaudantoine db65aef56e 💄(frontend) introduc smNote text variant
Necessary for room information in calendar iframe.
2025-04-02 12:31:04 +02:00
lebaudantoine 4e1a4be650 (backend) introduce a creation callback endpoint
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.
2025-04-02 12:31:04 +02:00
lebaudantoine 1f603ce17b 🔖(minor) bump release to 0.1.17
April fool by @arnaud-robin.
2025-03-31 23:49:04 +02:00
Arnaud Robin 672ca7dfe4 🚨(frontend) fix linting errors
- Fix linting errors in FaceLandmarksProcessor
- Fix linting errors in EffectsConfiguration
- Fix linting errors in useHasFaceLandmarksAccess
2025-03-31 22:57:02 +02:00
Arnaud Robin 7405011cd2 (frontend) add french touch effect
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'.
2025-03-31 22:57:02 +02:00
Arnaud Robin 1d5aebcfdc (frontend) add mustache effects
Added functionality to display mustache effects
on detected faces. Enhanced the EffectsConfiguration
component to toggle these effects and updated
localization files for this effects.
2025-03-31 22:57:02 +02:00
Arnaud Robin 0d6881382b (frontend) add face landmarks flag
Introduced a new hook, useHasFaceLandmarksAccess
to manage access to face landmark features
based on posthog feature flags.
2025-03-31 22:57:02 +02:00
Arnaud Robin c428f39456 (frontend) add thug glasses
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.
2025-03-31 22:57:02 +02:00
Arnaud Robin cd9b80b966 (frontend) add face tracking
Implement face landmark processor
to be able to track face live.
2025-03-31 22:57:02 +02:00
Florent f80603b4bb 🐛(licence) fix the copyright years in licence
The project has started in 2024 and it is still active in 2025.
2025-03-29 20:30:32 +01:00
Berry den Hartog 3299ae7c39 📝(docs) describe environmental options for meet backend 2025-03-28 20:14:32 +01:00
Jacques ROUSSEL 93ca4f2bf4 🐛(ci) use github action for argocd webhook notification
In order to refactor this notification between alls projetcs, we
chooseto use a custom github action
2025-03-28 16:24:17 +01:00
lebaudantoine 19a4e442c5 🔖(minor) bump release to 0.1.16
Misc fixes, release diarization.
2025-03-25 23:27:41 +01:00
lebaudantoine 53f1c9c1d4 💥(summary) replace Whisper with WhisperX for transcription
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.
2025-03-25 17:09:13 +01:00
lebaudantoine 28538b63da (backend) add env variable to configure marketing service timeout
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.
2025-03-25 15:41:47 +01:00
renovate[bot] 94ae5d52c2 ⬆️(dependencies) update js dependencies
Updated the useUser hook to avoid unwrapping the query object directly,
which leads to excessive re-rendering.
2025-03-25 14:53:15 +01:00
lebaudantoine 6b38a3c996 💄(frontend) center titles in prejoin components
In non-French languages, the title may be long enough
to span two lines. Ensure the text is centered.
2025-03-25 13:38:10 +01:00
lebaudantoine 0af30ec366 (backend) notify participants only if the room exists
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.
2025-03-25 13:33:47 +01:00
lebaudantoine 33e017464f 📌(livekit) pin livekit dev version
Pin the LiveKit server version to use the same as the staging
and production environment. It's a good practice.
2025-03-25 13:18:44 +01:00
lebaudantoine 9e91bbe417 🔇(backend) reduce noisy logs in Sentry
Ignore logs from DockerflowMiddleware
and minimize unnecessary log submissions.
2025-03-25 09:42:35 +01:00
renovate[bot] e821982353 ⬆️(dependencies) update python dependencies 2025-03-24 20:04:15 +01:00
lebaudantoine 18f4a117ab 🩹(backend) invert operation order in participant handling
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.
2025-03-24 19:39:13 +01:00
lebaudantoine b5b99d4c52 🐛(frontend) fix effect menu scroll
Since refactoring, the effect side panel, was not scrollable anymore.
Fixed it.
2025-03-24 17:10:50 +01:00
lebaudantoine 8a4323aa82 🐛(license) fix reuse.software missing support in GitHub
Duplicate the MIT License, which are not yet supported by GitHub and its badges.
2025-03-24 14:54:42 +01:00
lebaudantoine 5cbac23f13 💄(frontend) adjust minor visual item
Adjust few items from the landing and the interface.
2025-03-24 14:38:27 +01:00
lebaudantoine d55810784d 🐛(frontend) fix Marianne import
The font face definition wasn't working properly. Switch to vanilla css.
2025-03-24 14:38:27 +01:00
lebaudantoine c2fdefe7b2 💄(frontend) adjust font size based on Marianne recent changes
Marianne is bigger than OpenSans, adjust admin side panel style.
2025-03-24 13:53:41 +01:00
lebaudantoine bf2474d0e1 🌐(frontend) add missing translation
The admin side panel was translated too quickly.
I forgot a title, fix it.
2025-03-24 13:53:41 +01:00
lebaudantoine 558d844ef3 ✏️(frontend) fix typos in the admin side panel
Based on Users' feedbacks. Also based on Arnaud's one, avoid
having a double negation for the public restriction.
2025-03-24 13:36:03 +01:00
lebaudantoine 94aa828d87 🌐(frontend) add missing dutch content
Oopsi, forgot some dutch content when resolving conflicts
while merging traductions. Fixed.
2025-03-21 16:59:14 +01:00
lebaudantoine 110e062e56 💄(frontend) use official Marianne font
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.
2025-03-21 16:57:33 +01:00
lebaudantoine f7c2beb30d 🚸(frontend) add screen sharing troubleshooting modal and setup guide
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.
2025-03-21 15:27:50 +01:00
lebaudantoine 5bf1456200 ⚰️(secrets) remove useless submodule
Secret are not in-use anymore in the project, dead code.
2025-03-21 15:25:37 +01:00
Ikko Eltociear Ashimine 80e5c9bb95 ✏️(frontend) update BackgroundBlurTrackProcessorJsWrapper.ts
accross -> across
2025-03-18 20:07:26 +01:00
Rust Saiargaliev 74164b8498 🗑️(backend) drop obsolete code from the initial boilerplate
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.
2025-03-18 20:05:31 +01:00
Juergen Ehrensberger 82cc2e5d17 📝(helm) correct helm chart repository URL for meet
The URL https://numerique-gouv.github.io/meet/ is not accessible.
The correct URL appears to be https://suitenumerique.github.io/meet/
2025-03-18 20:03:45 +01:00
lebaudantoine fa1503db0d 📄(legal) update legal notice following expert review
following legal team's advices, updates our legal terms.
2025-03-16 18:10:40 +01:00
lebaudantoine e106415740 🔒️(frontend) update meet-frontend image to address security vuls
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.
2025-03-16 16:36:01 +01:00
lebaudantoine 4199328a4a 📄(license) update license following expert review
following @bzg advice, updates our licenses.
2025-03-15 14:14:41 +01:00
aleb_the_flash 57715fea73 📝(readme) integrate feedbacks from open-source specialist
Clarify the license, and avoid any enterprise-like vocabulary or expression.

Thx @bzg
2025-03-15 14:02:16 +01:00
lebaudantoine c969c302bc 📝(docs) add SECURITY.md file
Created SECURITY.md document outlining security policy, vulnerability reporting
process, and responsible disclosure guidelines for the project.
2025-03-13 19:48:31 +01:00
lebaudantoine be29e193c5 📝(docs) add CODE_OF_CONDUCT.md file
Created CODE_OF_CONDUCT.md document defining acceptable behavior standards and
conflict resolution procedures for project participants.
2025-03-13 19:48:31 +01:00
lebaudantoine 53d0e9fe12 📝(docs) add CONTRIBUTING.md file
Created CONTRIBUTING.md document outlining contribution guidelines, development
setup, and code standards for new contributors.
2025-03-13 19:48:31 +01:00
Arnaud Robin e04d9a9dab 📝(doc) update README to engage users
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.
2025-03-13 19:48:31 +01:00
lebaudantoine fdb6dda65b 🔒️(frontend) update libxml2 to fix CVE-2025-27113 vulnerability
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.
2025-03-13 19:21:46 +01:00
lebaudantoine 332662d1e5 🔧(frontend) add make commands for simplified frontend setup
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.
2025-03-13 19:21:46 +01:00
lebaudantoine a8e1bbe085 🧑‍💻(frontend) enable frontend service in docker compose
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.
2025-03-13 19:21:46 +01:00
lebaudantoine 9eae98ed16 🐛(devops) fix dockerize platform compatibility for Mac M2 users
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.
2025-03-13 19:21:46 +01:00
lebaudantoine 3cae3e66c4 🔖(minor) bump release to 0.1.15
Release private rooms
2025-03-11 13:57:40 +01:00
lebaudantoine 7e463f4554 ♻️(frontend) add opensource annotation on the repo link
Add a clear explanatory text about the project's opensource nature.
This provides better context for users while maintaining transparency
about the software license.
2025-03-11 13:37:01 +01:00
lebaudantoine 1c40003c3c (frontend) introduce dedicated terms of service page
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.
2025-03-11 13:37:01 +01:00
lebaudantoine 5f07d4a88b ️(frontend) introduce dedicated accessibility page
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.
2025-03-11 13:37:01 +01:00
lebaudantoine 6cf8e23ab2 ️(frontend) introduce dedicated legal notice page
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.
2025-03-11 13:37:01 +01:00
lebaudantoine b4016ce850 (frontend) support screen titles with colorful page headers
Added support for passing screen titles that display in colorful header
components, improving page navigation context and visual hierarchy.
2025-03-11 13:37:01 +01:00
lebaudantoine 74aba2185a 💄(frontend) add technical link style to legal notice primitive
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.
2025-03-11 13:37:01 +01:00
Eric Wout van der Steen 0bbaae7c5e 🌐(frontend) add Dutch translation
Add Dutch to the language selection system, and add configuration
files with Dutch translated messages.
2025-03-07 19:12:57 +01:00
lebaudantoine fbee41f5dd ♻️(backend) avoid repeating 'service' in python modules
These modules are already stored under the 'service' folder, it was redundant.
Renamed these files based on @lunika feedbacks.
2025-03-07 18:36:30 +01:00
renovate[bot] 2503411311 ⬆️(dependencies) update django to v5.1.7 [SECURITY] 2025-03-07 17:27:37 +01:00
lebaudantoine 13944ceebd 🔧(livekit) create custom LiveKit image with nip.io CA certificate
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.
2025-03-07 17:05:06 +01:00
lebaudantoine 50719e8c25 (backend) activate LiveKit webhook event notifications
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.
2025-03-07 17:05:06 +01:00
lebaudantoine 11c2c2dea8 (backend) expose event-handler matching service via dedicated endpoint
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.
2025-03-07 17:05:06 +01:00
lebaudantoine d2f79d4524 (backend) introduce LiveKit event-handler matching service
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.
2025-03-07 17:05:06 +01:00
lebaudantoine 2168643fd4 (backend) add lobby cache clearing method for meeting conclusion
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
2025-03-07 17:05:06 +01:00
lebaudantoine 356797d326 🐛(frontend) resolve conflicting styles in SidePanel component
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.
2025-03-06 00:08:45 +01:00
lebaudantoine 19b88a2078 🐛(frontend) handle overflow for usernames in waiting participant items
Implement text truncation for excessively long usernames in waiting
participant list items to prevent layout overflow and maintain consistent UI
appearance.
2025-03-05 22:27:49 +01:00
lebaudantoine b169e57193 🔥(frontend) delete accept/deny all group actions
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
2025-03-05 22:27:49 +01:00
lebaudantoine 5d81ba1e20 🚸(frontend) enhance waiting notification with temporary quick actions
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.
2025-03-05 22:27:49 +01:00
lebaudantoine b248395cd6 (frontend) introduce usePrevious utility hook
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.
2025-03-05 22:27:49 +01:00
lebaudantoine 3eef4765df 🐛(backend) adjust throttle rate from hours to minutes for request_entry
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.
2025-03-05 22:27:49 +01:00
lebaudantoine ae920c0c9b ️(frontend) use higher contrast red for white text backgrounds
Replace current red with higher contrast variant when used as background with
white text to meet accessibility contrast requirements. Improves readability
for all users.
2025-03-05 15:10:42 +01:00
lebaudantoine 86cb10a3c7 💄(frontend) render side controls in the navigation menu earlier
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.
2025-03-05 15:10:42 +01:00
lebaudantoine 634b34f2e9 💄(frontend) make "more options" button more explicit
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.
2025-03-05 15:10:42 +01:00
lebaudantoine 33774a44d4 ️(frontend) improve switch component visual indicators per DSFR rules
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.
2025-03-05 15:10:42 +01:00
lebaudantoine ce1c3d26d2 ️(frontend) hide under construction banner icon from screen readers
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
2025-03-05 15:10:42 +01:00
lebaudantoine b5e7d7eeec ️(frontend) update footer accessibility disclaimer text
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.
2025-03-05 15:10:42 +01:00
lebaudantoine 50b9509c2c ️(frontend) update emoji hover background to meet RGAA contrast rules
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.
2025-03-05 15:10:42 +01:00
lebaudantoine aaf1163910 🚸(frontend) add login hint for unauthenticated users in lobby
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.
2025-03-05 11:26:14 +01:00
lebaudantoine 00cd4fc92a (frontend) add trusted user option in admin panel access settings
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.
2025-03-05 11:26:14 +01:00
lebaudantoine 0aa4f6389b (backend) add trusted user access level for rooms
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.
2025-03-05 11:26:14 +01:00
lebaudantoine e2f60775a9 ♻️(frontend) reduce over-mocking in lobby service unit tests
Replace excessive mocking with more realistic test scenarios to better
reflect actual code execution. Improves debuggability while maintaining
thorough test coverage.
2025-03-05 11:26:14 +01:00
lebaudantoine e20acfa5a9 🔒️(backend) limit user listing endpoint with security flag
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.
2025-03-05 10:45:50 +01:00
lebaudantoine fac9435bc7 💄(frontend) adapt entry body text to match Robin's design
Update the styling of entry body text to align with Robin's design
specifications. Ensures consistent visual language throughout the
application.
2025-03-05 10:44:41 +01:00
lebaudantoine 3e9992bae3 💄(frontend) adapt loading spinner to match Robin's design
Update loading spinner component to follow Robin's design specifications,
ensuring visual consistency with the established design system.
2025-03-05 10:44:41 +01:00
lebaudantoine 25d4ede2dd 💬(frontend) rephrase entry text as question for politeness
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.
2025-03-05 10:44:41 +01:00
lebaudantoine 6545ecf11a 🔒️(frontend) implement strict validation for user-provided metadata
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.
2025-03-04 10:12:06 +01:00
lebaudantoine b73f18419b 🔒️(frontend) add HSL color format validation in metadata
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.
2025-03-04 10:12:06 +01:00
lebaudantoine 49163eba67 🔒️(frontend) enhance notification data decoding with improved validation
Strengthen decodeNotificationDataReceived function with additional validation
to properly handle malicious input. Ensures application security when
processing potentially dangerous notification data from untrusted sources.
2025-03-04 10:12:06 +01:00
lebaudantoine 38c3776556 ⬆️(dependencies) update js dependencies 2025-03-03 23:39:58 +01:00
lebaudantoine 75e4092dad 💚(ci) add Redis requirement for backend tests
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.
2025-03-03 21:48:22 +01:00
lebaudantoine 2774d76176 (frontend) add room access configuration options
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.
2025-03-03 21:48:22 +01:00
lebaudantoine da05438f45 (frontend) add description support to radio field component
Enhance radio field component with description capability to provide
additional context and improve form accessibility and usability.
2025-03-03 21:48:22 +01:00
lebaudantoine 5d89efec78 (frontend) add admin side panel for room management
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.
2025-03-03 21:48:22 +01:00
lebaudantoine 7c46029f87 (frontend) add margin option to Text primitive component
Extend Text primitive component with new margin option to provide more
flexibility in layout spacing without requiring wrapper components.
2025-03-03 21:48:22 +01:00
lebaudantoine e535040ac6 (frontend) implement persistent notifications for waiting participants
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.
2025-03-03 21:48:22 +01:00
lebaudantoine 92851b10cc ♻️(frontend) extract notification decoding logic for reusability
Extract notification decoding functionality into a reusable module to
improve enable consistent notification handling across
the frontend application.
2025-03-03 21:48:22 +01:00
lebaudantoine ea37a3154e 🚧(frontend) add basic loading spinner from react-aria
Add raw loading spinner component from react-aria library to handle
loading states. Will refine styling and appearance after receiving design
review feedback.
2025-03-03 21:48:22 +01:00
lebaudantoine 65ddf2e2a1 (frontend) add waiting participants list for room admins
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.
2025-03-03 21:48:22 +01:00
lebaudantoine a48501bc02 (frontend) update Join component to support lobby system
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.
2025-03-03 21:48:22 +01:00
lebaudantoine 4d961ed162 🚧(backend) introduce a lobby system
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.
2025-03-03 21:48:22 +01:00
lebaudantoine 710d7964ee ♻️(backend) extract LiveKit connection info generation function
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.
2025-03-03 21:48:22 +01:00
lebaudantoine 01f4d05d6b ♻️(backend) replace is_public with access_level field
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.
2025-03-03 21:48:22 +01:00
lebaudantoine 7fad60d9a9 📝(backend) use certifi certificate for livekit-api dependency
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.
2025-03-03 21:48:22 +01:00
dependabot[bot] e9ebac46ac ⬆️ (mail) bump braces from 3.0.2 to 3.0.3 in /src/mail
Update indirect dependency braces from 3.0.2 to 3.0.3.
See changelog: https://github.com/micromatch/braces/blob/master/CHANGELOG.md
2025-03-03 17:37:04 +01:00
lebaudantoine d64e5d1923 🐛(CI) sync CI Python version with Docker image Python version
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.
2025-03-03 17:31:01 +01:00
renovate[bot] c9512004ac ⬆️(dependencies) update python dependencies 2025-03-03 17:31:01 +01:00
lebaudantoine 879cf20891 📈(frontend) add data attributes to key UI buttons
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.
2025-02-28 17:17:00 +01:00
lebaudantoine 433a3a7cdf (frontend) add email collection step for anonymous survey responses
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.
2025-02-28 17:17:00 +01:00
lebaudantoine c0bcced3c0 🐛(frontend) fix logout issues affecting support and analytics sessions
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.
2025-02-28 17:17:00 +01:00
lebaudantoine 4045662433 💄(frontend) adjust message notification size for better readability
Increase message notification size to improve text readability when
notifications appear, enhancing user experience by making content more
visible at a glance.
2025-02-28 17:17:00 +01:00
lebaudantoine e7f11194ce 📝(frontend) add technical network requirements documentation
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.
2025-02-28 09:41:54 +01:00
lebaudantoine 4955f3eea7 🔒️(frontend) validate emoji in notifications to prevent forbidden emoji
Add validation for emoji received through notifications to ensure
participants cannot send forbidden emoji characters. Improves security
by filtering potentially problematic content before display.
2025-02-28 09:23:15 +01:00
lebaudantoine c576a75660 🔥(frontend) delete dead code in emoji reaction component
Remove unused code in emoji reaction feature that was mistakenly introduced
in previous commits. Clean up codebase to improve clarity and maintenance.
2025-02-28 09:23:15 +01:00
renovate[bot] 51fa4e84e4 ⬆️(dependencies) update python dependencies 2025-02-27 11:27:22 +01:00
lebaudantoine eec6a46883 🚸(frontend) make explicit why a page is not found
Enhance the error message based on @spaccoud's feedback,
explain to the user why a page is not found.
2025-02-26 19:02:04 +01:00
lebaudantoine 19a240c63f 🩹(frontend) make "not found screen" accessible again
With the recent introduction of SDK, the route "not found screen" was broken.
Fixed it.
2025-02-26 19:02:04 +01:00
lebaudantoine 2236674849 🐛(frontend) correct Keycloak logout endpoint in tilt stack
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.
2025-02-26 18:51:26 +01:00
lebaudantoine e5fe81de4d 🐛(frontend) preserve line breaks and whitespace in chat messages
Add CSS styling to preserve return lines and whitespace in chat messages,
fixing display issues that were causing broken line formatting.
2025-02-26 18:18:09 +01:00
lebaudantoine 38ab001bcf ️(frontend) allow the reaction toolbar to be accessible by keyboard
Fix an accessibility issue. Reaction wasn't accessible using keyboard.
This fix is imperfect, the animation doesn't perflectly replicate the
menu one.
2025-02-26 18:06:08 +01:00
lebaudantoine 14885e0ffa 🔖(minor) bump release to 0.1.14
Release emoji reactions.
2025-02-24 12:33:52 +01:00
lebaudantoine 054e7ba945 ️(tilt) clean automatically old images
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.
2025-02-24 11:05:52 +01:00
lebaudantoine 25506b6a2a 🩹(frontend) fix missing key in reactions toolbar
Emojis are a constant, so the reaction index remains stable,
but using the index as a key isn't ideal.
2025-02-22 17:43:25 +01:00
lebaudantoine 0498a9e7f9 🩹(frontend) preload notifications translations to prevent flickering
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.
2025-02-21 19:19:13 +01:00
lebaudantoine 0a63270154 🚸(frontend) offer a "clear effect" option
Based on user feedbacks, allow them stopping an effect
explicitly by pressing a "no effect" option.
2025-02-21 18:14:17 +01:00
Arnaud Robin b962dddbf2 (frontend) add emoji reactions feature
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
2025-02-21 13:49:38 +01:00
lebaudantoine 16929bcc83 ♻️(frontend) allow passing placement to a menu
Props supported by react aria. Introduce it.
2025-02-21 13:49:38 +01:00
lebaudantoine 354bdd8bfe 🩹(frontend) fix screen sharing warnings browser compatibility
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.
2025-02-21 12:14:06 +01:00
Jacques ROUSSEL ccca2b9472 🔧(ci) fix argocd notification
Argocd deployment use numerique-gouv/lasuite-deploiement as source so
the webhook need to tell argocd to refresh apps that use this repos
2025-02-21 11:21:01 +01:00
lebaudantoine 9fc5681137 🩹(frontend) fix visual regression on Ratings buttons
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.
2025-02-20 19:00:46 +01:00
renovate[bot] edf29076ba ⬆️(dependencies) update vite to v5.4.12 [SECURITY] 2025-02-20 10:31:55 +01:00
lebaudantoine 337181add8 🩹(frontend) fix text overflow in message notification
Minor issue, layout overflow occurred when sharing url or
long text.
2025-02-19 22:47:49 +01:00
lebaudantoine 5af64e539d ♻️(frontend) refactor toast selection to use a switch
More extensible design. Still a poor piece of code.
Technical debt here.
2025-02-19 22:47:03 +01:00
lebaudantoine 291544bd52 (frontend) lower hand autonomously for active speakers
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.
2025-02-19 22:47:03 +01:00
lebaudantoine 13bb6acdf6 ♻️(frontend) extract notification duration in a proper file
As for notification's type, extract notification's duration in a
dedicated file.
2025-02-19 22:47:03 +01:00
lebaudantoine aa2783ae2e 🚸(frontend) auto-hide participant controls after 3s of inactivity
Auto-hides participant tile controls after 3 seconds of cursor inactivity
to reduce visual clutter. Controls reappear on cursor movement.
2025-02-19 22:37:48 +01:00
Nathan Vasse c3e4ea0fd1 🔧(ci) add sdk to workflow
Add basic jobs to handle the new sdk.
2025-02-18 16:16:07 +01:00
Nathan Vasse 183e8f6a72 (sdk) add sdk projects
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.
2025-02-18 16:16:07 +01:00
Nathan Vasse 452dbe8bba (front) add sdk related routes and logic
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.
2025-02-18 16:16:07 +01:00
Nathan Vasse 8818d12ee9 ♻️(front) add option to disable silent login
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.
2025-02-18 16:16:07 +01:00
Nathan Vasse fb0c9b766d (front) add quaternary variant to Button
This variant is needed to implement the sdk create room button.
2025-02-18 16:16:07 +01:00
Nathan Vasse ba873196c7 (front) add loader and icon props to Button
These shortcuts improve DX and will be used in the next commits.
2025-02-18 16:16:07 +01:00
Jacques ROUSSEL 48937bb7a3 ♻️(helm) fix helm chart for keycloak stack
Ingress stop working, so this commit fix it
2025-02-14 11:51:31 +01:00
lebaudantoine 6f09eb3602 🚸(frontend) add warning for full screen capture
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.
2025-02-13 16:30:22 +01:00
lebaudantoine b7fb6b1b69 🔖(patch) bump release to 0.1.13 2025-02-12 12:35:55 +01:00
Jacques ROUSSEL 2cd4a6efa8 (helm) add pdbs to deployments
In order to avoid a service interruption during a Kubernetes (k8s)
upgrade, we add a Pod Disruption Budget (PDB) to deployments.
2025-02-12 11:54:08 +01:00
lebaudantoine b5037db685 🔒️(docker) patch libssl3 and libcrypto3 to address CVE-2024-12797
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
2025-02-12 11:52:40 +01:00
lebaudantoine 19804d2e3f (frontend) add sound notification for unread messages
Add togglable audio alerts when new chat messages arrive,
allowing users to customize their notification preferences.
2025-02-12 11:52:40 +01:00
lebaudantoine a979f05549 🐛(frontend) preserve notification preferences while merging new types
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.
2025-02-12 11:52:40 +01:00
lebaudantoine 09a0496d25 ♻️(frontend) standardize toast notification durations
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.
2025-02-12 11:52:40 +01:00
lebaudantoine da95e804a0 (frontend) add toast notifications for unread chat messages
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.
2025-02-12 11:52:40 +01:00
lebaudantoine 591a3a5d8b (frontend) notify user when her was muted
Add notification system to handle user mute events. Implement extensible
design to support future notification types. Set notification duration to 3s.
2025-02-12 11:52:40 +01:00
lebaudantoine 30ed0da416 (frontend) introduce a new notification type
This notification alert the user when her was muted by another one.
Simple copywritting.
2025-02-12 11:52:40 +01:00
lebaudantoine bd4fcc2a5e (frontend) notify participant when her was muted
Make sure a participant is notified when another one muted her.
It will help display a notification to alert the participant.
2025-02-12 11:52:40 +01:00
lebaudantoine fc36ae8b49 🐛(frontend) fix useRoomData when a participant's name has changed
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.
2025-02-12 11:52:40 +01:00
lebaudantoine 87baca247b 🚨(frontend) fix warning component from uncontrolled to controlled
When the hand has never been raised yet, the value is undefined and
not false, which leads to a react aria warning.

It's a bad practice. Fix it.
2025-02-12 11:52:40 +01:00
lebaudantoine 42d3846660 ✏️(frontend) fix minor typo
Typo identified by Celine. No "e" in french.
2025-02-11 12:04:17 +01:00
lebaudantoine 2d393f9f70 (frontend) add controls for full screen screenshare
Requested by several users.
Inspired by Jitsi.

Yet imperfect implementation. Controls on video element of
a screenshare should be disabled.
2025-02-11 12:01:23 +01:00
lebaudantoine b4b4ff79d9 ♻️(frontend) refactor full screen to allow video args
useFullScreen hook is now generic, it allows passing a specific
video element to zoom in.

Needed to zoom a specific video track.
2025-02-11 12:01:23 +01:00
lebaudantoine 861244ce01 💄(frontend) update cursor on disabled button
When a button is disabled, it's misleading to show a pointer.
Update it to the default pointer.
2025-02-11 12:01:23 +01:00
lebaudantoine 6373593de3 🚸(frontend) offer additionnal controls on participant tile
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.
2025-02-11 12:01:23 +01:00
lebaudantoine 03f6e6519b 🩹(frontend) remove warning on modal without heading
The MuteAlertDialog was triggering accessibility warnings, lacking
a proper heading. Fix it.
2025-02-11 12:01:23 +01:00
lebaudantoine 716d40dd4e 🎨(frontend) avoid duplicating prefix in i18n's key
Simple enhancement. Avoid duplicating prefix.
2025-02-11 12:01:23 +01:00
lebaudantoine 17f8ec6319 🚸(frontend) refactor participant tile while being hovered
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.
2025-02-11 12:01:23 +01:00
lebaudantoine 0b74cf96f2 ♻️(frontend) extract MuteAlertDialog in a dedicated component
Will be reused in actions displayed when a participant tile
is focused.
2025-02-11 12:01:23 +01:00
Jacques ROUSSEL 723b8718f9 🔐(helm) bump chart version
Bump chart version to publish a new one with evolution
2025-02-05 22:20:49 +01:00
Nathan Vasse 07a44dab36 (front) turn on camera when using effects
We want to automatically turn on the camera if its off when
enabling a new effect.
2025-02-05 11:57:00 +01:00
Nathan Vasse e47b027bbc (front) add loading state on effects component
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.
2025-02-05 11:57:00 +01:00
Nathan Vasse d7a4f3946c (front) add Loader component
This component will be used for various purpose.
2025-02-05 11:57:00 +01:00
Jacques ROUSSEL 1b7523bbf1 💚(github) fix argocd notification
Use the right variable for webhook url
2025-02-05 11:53:56 +01:00
Jacques ROUSSEL 4326df4b6a 💚(github) fix argocd notification
Fix double simple quote issue on argocd notification job
2025-02-05 11:48:38 +01:00
Jacques ROUSSEL 564d31ab49 💚(github) remove secret fetch
The secrets are not managed in the folder anymore.
2025-02-05 11:41:37 +01:00
lebaudantoine 6e0948c696 🩹(frontend) prevent support toggle when Crisp chat is blocked
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.
2025-01-31 17:01:57 +01:00
Nathan Vasse eff0cb4afb (front) implement new ui of EffectsConfiguration
This new ui implement the new sketches and also enables the usage of
virtual background in a nice way.
2025-01-31 16:52:44 +01:00
Nathan Vasse 08c5245b48 (front) handle virtual background in custom processor
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.
2025-01-31 16:52:44 +01:00
Nathan Vasse 465bf293f0 (front) add BackgroundVirtualTrackProcessorJsWrapper
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.
2025-01-31 16:52:44 +01:00
lebaudantoine db51ca1aa5 🩹(frontend) fix border radius issue on safari
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.
2025-01-31 14:54:26 +01:00
lebaudantoine 6935001aab 🚸(frontend) disable few native html video option
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.
2025-01-31 14:54:26 +01:00
lebaudantoine bbc2b1d9f6 🚸(frontend) avoid displaying the effects option when not optimal
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.
2025-01-31 14:54:26 +01:00
lebaudantoine 12e2149b9e ♻️(frontend) extract effects-related logic in a component
Wraps all logics related to the effects on prejoin screen in a
dedicated component.
2025-01-31 14:54:26 +01:00
lebaudantoine 3bd9363879 🔍️(frontend) add link to the source code in the footer
Great idea suggested by @fflorent — totally worth it!
2025-01-31 14:30:52 +01:00
lebaudantoine b48135c3b6 🚸(frontend) replace effects icons in menu option
Align effects icon with the one from the newly refactored pre-join screen.
This new icon is stylish.
2025-01-31 14:21:48 +01:00
Nathan Vasse 206e74c645 (front) add blurring feature on join
This adds a button that opens a modal that allow user to enable
video effects on join screen.
2025-01-31 11:42:28 +01:00
Nathan Vasse 9ebfc8ea29 ♻️(front) refactor Effects
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.
2025-01-31 11:42:28 +01:00
Nathan Vasse 03796fcbb2 (front) add button white variant
This variant is gonna be used on overlay over a video element.
2025-01-31 11:42:28 +01:00
Nathan Vasse 4b6bd3d1c8 ♻️(front) enable custom size on Dialog
We want to have a Dialog that is constrained in width. Thus,
introducing this variant enables this possibility and many more
in the future.
2025-01-31 11:42:28 +01:00
Nathan Vasse d45880ab5c ♻️(front) add clone method to processors
We need to make new processor instance between pre join and room
in order to apply effects.
2025-01-31 11:42:28 +01:00
lebaudantoine 4ae3d965f9 🚸(frontend) show support toggle only if support is enabled
Avoid misleading the user, if support is not enabled, as it's optional,
avoid displaying a useless control button.

Requested by Dutch counterparts.
2025-01-29 16:12:47 +01:00
lebaudantoine 8eab45b6d5 🩹(frontend) prevent runtime error when Crisp is not initialized
Prevents runtime error when Crisp chat hasn't initialized before component mount
Previously caused crash since we assumed $crisp global was always available.
2025-01-29 16:12:47 +01:00
lebaudantoine 4347d87f33 🚸(frontend) improve prejoin UX
- 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
2025-01-29 14:14:11 +01:00
lebaudantoine 1b52d76168 ♻️(frontend) extract menu items into individual components
Each menu item is now a standalone component, improving:
- Code organization & reusability
- Maintainability by reducing OptionsMenuItems complexity

This breaks down large components.
2025-01-27 23:02:31 +01:00
lebaudantoine a44b6e8e34 (frontend) add fullscreen mode on desktop
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.
2025-01-27 23:02:31 +01:00
lebaudantoine 126de638cd 🩹(frontend) fix allowed hosts by Vite using the Tilt stack
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.
2025-01-27 22:57:51 +01:00
lebaudantoine bf28c5cb84 📱(frontend) enhance control bar responsiveness for better UX
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.
2025-01-27 22:57:24 +01:00
renovate[bot] 4f0e7d2c52 ⬆️(dependencies) update python dependencies 2025-01-27 22:18:32 +01:00
renovate[bot] 3ab5c48296 ⬆️(dependencies) update js dependencies 2025-01-27 18:12:44 +01:00
Nathan Vasse 7f1f573af8 (front) revamp join screen
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.
2025-01-27 15:31:19 +01:00
Nathan Vasse d48a18b36b (front) make ToggleDevice work outside of a room
This component is needed on the join screen thus out of a room context.
2025-01-27 15:31:19 +01:00
Nathan Vasse eac9158734 (front) add customization to Field
We want to be able to provide some custom attributes to the FieldWrapper
and its label too to manage width, alignment.
2025-01-27 15:31:19 +01:00
Nathan Vasse 994f335266 (front) add customization to SelectToggleDevice
We want to be able to change the variant of this component.
2025-01-27 15:31:19 +01:00
lebaudantoine 30bde2fe66 ♻️(frontend) use pandas utilities
Forgot how panda css is amazing. They provide all kinds of utilities,
and few for accessibility. Amazing!
2025-01-24 13:56:32 +01:00
Nathan Vasse 96c18fc627 (front) add switch camera on mobile
We want to have a more simple control bar and give the user to switch
its back / front camera from the responsive menu.
2025-01-21 15:37:59 +01:00
Nathan Vasse c380ff5e1d (front) option to hide menu on SelectToggleDevice
On mobile we want to be able to hide the chevron and menu.
2025-01-21 15:37:59 +01:00
lebaudantoine 6587863afb 💄(frontend) use dark theme for menus in the videoconference
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.
2025-01-21 11:53:12 +01:00
lebaudantoine a06daad33d 💄(frontend) fix screen-share control alignment
Oopsie, due to its (too) big icon, the height of this control was 4px bigger
than other buttons. Fixed that minor issue.
2025-01-21 11:53:12 +01:00
renovate[bot] 10c3c67d53 ⬆️(dependencies) update js dependencies 2025-01-21 11:20:29 +01:00
lebaudantoine fa85ef5690 📌(frontend) block upgrade to react v19
Many dependencies are not supported react v19 yet.
Avoid renovate to bump react to its latest major version.
2025-01-21 11:20:29 +01:00
lebaudantoine cc676cf71b ⬆️(frontend) bump react-aria-related dependencies
No major / breaking change in these few releases.
Quickly tested all features, everything seems alright
2025-01-20 19:31:55 +01:00
lebaudantoine 90df8fe5b4 ⬆️(frontend) bump react-query-related dependencies
No major / breaking change in these few releases.
Quickly tested all features, everything seems alright
2025-01-20 19:31:55 +01:00
lebaudantoine 90cfcd31c8 ⬆️(frontend) bump LiveKit-related dependencies
No major / breaking change in these few releases.
Quickly tested all features, everything seems alright
2025-01-20 19:31:55 +01:00
renovate[bot] 0ed3416ce2 ⬆️(dependencies) update python dependencies 2025-01-20 09:35:06 +01:00
lebaudantoine e47401246f ✏️(frontend) fix feedback-s
Feedback is a mass noun.
Spotted by @bvhme
2025-01-18 22:11:35 +01:00
lebaudantoine a518179efb ⬆️(frontend) bump vite to v6.0.7
Updates build configuration to support new major version.
This might introduce some breaking changes.

I've read their migration guide, everything seems okay.
2025-01-17 18:23:48 +01:00
lebaudantoine f17471dae5 🚨(frontend) resolve key prop warning in ParticipantListItem
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.
2025-01-16 18:04:20 +01:00
lebaudantoine 36ea44befc 🚨(frontend) update deprecated react-aria Section components
Section was deprecated in Novembre 2024 release, It has been replaced
by specific components for each parent collection component,
e.g. MenuSection.
2025-01-16 18:04:20 +01:00
renovate[bot] 047ef83f17 ⬆️(dependencies) update django to v5.1.5 [SECURITY] 2025-01-16 11:10:51 +01:00
Nathan Vasse e1ece8b5af (front) add posthog log for Firefox blurring
We want to be able to track device settings and versions when a user
enables this feature.
2025-01-16 10:03:18 +01:00
Nathan Vasse 56379f2d6e (front) add blurring support on Firefox
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.
2025-01-16 10:03:18 +01:00
lebaudantoine 341be37fd3 🩹(backend) remove a non-existing field on BooleanValue
I used a LLM to review my code, it introduced an hallucinated field.
Remove it.
2025-01-14 15:52:57 +01:00
lebaudantoine 4cce2e0b72 🐛(backend) fix brevo-related setting name mismatch
Error introduced while rebasing. Fixed it.
2025-01-14 15:52:57 +01:00
lebaudantoine f14536dd93 🔐(helm) configure Brevo marketing tool
Using VaultWarden, added a dev Brevo API key.
In the "dev" stack, enable Brevo to validate new users are signed-up
to the marketing emails.
2025-01-14 15:52:57 +01:00
Jacques ROUSSEL dc0e2eefb3 📝(doc) upgrade README.md
Upgrade the README.md of the helm chart meet
2025-01-14 10:15:27 +01:00
lebaudantoine a61b34400b ♻️(scripts) improve script portability
Improved script portability by switching to `/usr/bin/env bash`, ensuring
better support across environments where `bash` may not be the default shell.
2025-01-14 10:15:27 +01:00
lebaudantoine 3c8e3b9e29 (tilt) add missing certificate authority for Python
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.
2025-01-14 10:15:27 +01:00
lebaudantoine 89f2ae548e ♻️(helm) simplify generate-readme script
Spotted by @rouja, replace complex file handling with a streamlined
approach.
2025-01-14 10:15:27 +01:00
lebaudantoine 1f23bbf96e (feature) support annotations in deployment to handle external secrets
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.
2025-01-14 10:15:27 +01:00
lebaudantoine 9972692dac ♻️(helm) refactor clusterSecretStore and ExternalSecret deployments
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.
2025-01-14 10:15:27 +01:00
lebaudantoine 6d08e318a7 🐛(ci) align helm chart release process with people repository
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.
2025-01-14 10:15:27 +01:00
lebaudantoine 203f1762e7 ♻️(helm) extract make command in a script
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.
2025-01-14 10:15:27 +01:00
renovate[bot] 470390fc59 ⬆️(dependencies) update python dependencies 2025-01-13 20:30:38 +01:00
lebaudantoine fe9fe4dd90 🗃️(backend) add missing ordering migrations
While fixing some backend warnings, I forgot to generate
the associated migrations. Fixed my error.
Non-critical migrations about default ordering.
2025-01-13 13:36:23 +01:00
Jacques ROUSSEL 7ad9015a6b 👷(helm) fix typo in the ci
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'.
```
2025-01-09 18:14:41 +01:00
lebaudantoine 3e4a7058d2 ♻️(ci) merge helmfile-lint and release chart workflows
Merge both flows related to the Helmfile.
Also, make sure lint job is run before the release one.
2025-01-06 10:19:09 +01:00
Jacques ROUSSEL 25a4e2dfc6 👷(helm) improve local stack
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.
2025-01-06 10:19:09 +01:00
Jacques ROUSSEL 14e83ecaff 📝(doc) add a self-host tutorial
Add a documentation to deploy a self-hosted visio instance in a
standalone way (without AI features)
2025-01-06 10:19:09 +01:00
Jacques ROUSSEL 8bd90bd2ff 👷(helm) add a github workflow to publish a chart
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.
2025-01-06 10:19:09 +01:00
Jacques ROUSSEL b51f127872 🔧(helm) offer a standalone dev environment
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.
2025-01-06 10:19:09 +01:00
lebaudantoine 4c0230d537 (backend) post email to marketing tools while signing up new users
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.
2024-12-31 15:09:51 +01:00
lebaudantoine 7309df4115 ♻️(backend) add MarketingService protocol and Brevo implementation
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.
2024-12-31 15:09:51 +01:00
lebaudantoine 18b2dfc497 (backend) install brevo client
Brevo (ex-sendinblue) is a common solution used for marketing and
communications.
2024-12-31 15:09:51 +01:00
lebaudantoine 3282da7c56 🚨(backend) fix Django UnorderedObjectListWarning on models
Found this solution googling on Stack Overflow.

Without a default ordering on a model, Django raises a warning, that
pagination may yield inconsistent results.
2024-12-31 15:09:35 +01:00
renovate[bot] 7f8a6e8685 ⬆️(dependencies) update python dependencies 2024-12-30 13:32:37 +01:00
lebaudantoine 4232c0a303 🔖(patch) bump release to 0.1.12
Release a fix while calling Docs backend API.
2024-12-18 22:54:57 +01:00
lebaudantoine a5454e48b7 🔥(frontend) remove redundant yarn.lock file
We decided to stick to npm for dependencies management.
Having both package-lock.json and yarn.lock isn't clear for
developers, simplify the stack.
2024-12-17 18:53:55 +01:00
dependabot[bot] 591706f363 🔒️(frontend) bump nanoid from 3.3.7 to 3.3.8 in /src/frontend
3.3.8 fixed a way to break Nano ID by passing non-integer size.
Raised as a moderate severity issue by Dependabot.
2024-12-17 18:53:55 +01:00
dependabot[bot] 1ea84b6e6c 🔒️(mail) bump cross-spawn to fix a high severity issue
Bump cross-spawn from 7.0.3 to 7.0.6 in /src/mail
Alert triggered by DependaBot.
2024-12-17 16:43:54 +01:00
renovate[bot] c0d101a326 ⬆️(dependencies) update PyJWT to v2.10.1 [SECURITY] 2024-12-17 16:23:05 +01:00
lebaudantoine 64cfcb6c0f 💩(summary) fix temporarily the summary microservice
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.
2024-12-17 11:34:46 +01:00
lebaudantoine cdd69b741a 🚑️(mail) bump package version
Oopsie, I forgot to bump mail package version.
Fix it
2024-12-17 11:34:46 +01:00
Jacques ROUSSEL f5a87cc210 🔐(helm) bump secret in staging
We add a typo in secret so we bump secrets to fix it.
2024-12-17 10:19:40 +01:00
lebaudantoine 4d4ddb9ee8 🔖(patch) bump release to 0.1.11
Weekly release, responsiveness is still under construction.
2024-12-17 00:26:29 +01:00
lebaudantoine 70dbf94f7b 🩹(frontend) avoid duplicating Grist form's URL
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.
2024-12-17 00:08:53 +01:00
Jacques ROUSSEL 0ad37ee6de 🔨(tilt) improve local stack
Improve the local tilt file in order to be abble to start all thing
without any dependencies to DINUM environment
2024-12-16 23:41:09 +01:00
Jacques ROUSSEL ed4f7dcf6c 🔐(helm) add production secrets for recording and transcription
Added all missing secrets for the recording feature
and transcription microservice.
2024-12-16 23:08:04 +01:00
lebaudantoine c54773008c 🚨(backend) fix backend linter
I wrongly merged a backend pr, and broke the linter.
2024-12-16 23:08:04 +01:00
lebaudantoine 6848321bcc 🔧(helm) configure transcription microservice in production
Added one replica for the summary and Celery deployments.
Secret will be added in the upcoming commits.
2024-12-16 23:08:04 +01:00
lebaudantoine f161a5cf6a 🔧(helm) configure recording in production
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.
2024-12-16 23:08:04 +01:00
lebaudantoine 51270571bc 🔧(helm) update transcription microservice in staging
Updated the webhook URL to the definitive version in docs.

Jacques also updated the webhook secret for authentication
against Impress API. Not tested locally.
2024-12-16 23:08:04 +01:00
Nathan Vasse c6fdeaf1e9 📱(front) add responsive menu on mobile
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.
2024-12-13 15:41:54 +01:00
Nathan Vasse f1959cbb3a ♻️(front) add more customization and event handler to toggles
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.
2024-12-13 15:41:54 +01:00
Nathan Vasse 84cea2f658 (front) add description to Buttons
We want to display full description below buttons for mobile specific
displays.
2024-12-13 15:41:54 +01:00
Nathan Vasse db1fdb9871 (front) add useIsMobile hook
This hook tells whether the current browser is a mobile one or not.
2024-12-13 15:41:54 +01:00
lebaudantoine a8618239d1 🔧(frontend) enable dynacast optimizations
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!
2024-12-12 11:25:06 +01:00
lebaudantoine 0eb283b75a 🔧(frontend) enable adaptive stream optimizations
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.
2024-12-12 11:25:06 +01:00
lebaudantoine 0104cabc5e 🔧(frontend) default to vp9 for video codec
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.
2024-12-12 11:25:06 +01:00
lebaudantoine dbfba564c5 🔧(backend) fix sentry deprecated scope
`sentry_sdk.configure_scope` is deprecated and will
be removed in the next major version.

(commit taken from people by @qbey)
2024-12-10 12:00:41 +01:00
renovate[bot] 4830206bb2 ⬆️(dependencies) update python dependencies 2024-12-09 18:20:12 +01:00
lebaudantoine e4f30f926c 🩹(summary) fix configuration in staging
@rouja forgot to add the right environment variable for the celery
workers. Fixed it.
2024-12-09 18:15:47 +01:00
lebaudantoine fc61f58596 🔧(summary) update LLM and whisper endpoints
@rouja fixed the issue from OutScale load balancer.
He found the right parameter in OutScale documentation,
that was causing a request timeout.
2024-12-09 18:15:47 +01:00
lebaudantoine e0021dbb80 (frontend) introduce a notification settings
I extended Room settings with a new tab, allowing users to toggle
the sound notification they want.

Their choices will be persisted.
2024-12-09 18:14:46 +01:00
lebaudantoine 83914f8307 (frontend) add notification store for managing user preferences
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.
2024-12-09 18:14:46 +01:00
lebaudantoine be54709598 (frontend) create STORAGE_KEYS constant
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.
2024-12-09 18:14:46 +01:00
lebaudantoine 5b76ea492b (frontend) create utils function for valtio
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.
2024-12-09 18:14:46 +01:00
lebaudantoine 46934a84d1 🚚(frontend) rename NotificationType items
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.
2024-12-09 18:14:46 +01:00
lebaudantoine deb9ab1a1d (frontend) create a new primitive Switch
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.
2024-12-09 18:14:46 +01:00
renovate[bot] d0fd16d7d2 ⬆️(dependencies) update django to v5.1.4 [SECURITY] 2024-12-08 22:21:18 +01:00
lebaudantoine 0b8181e5ce ✏️(backend) fix few typos
Fix few typos in the docstring.
2024-12-06 12:46:46 +01:00
lebaudantoine 8b2365d5f9 (backend) add ODC_VERIFY_SSL configuration
Need to disable SSL while authenticating to unsecure
OIDC provider in dev environment.
2024-12-06 12:46:46 +01:00
lebaudantoine 2dd16d1f40 🩹(backend) add missing environ_prefix on OIDC_CREATE_USER
Misleading, to not have all OIDC-related settings, with environ prefix at None.
Caught myself into troubleshooting few minutes.
2024-12-06 12:46:46 +01:00
lebaudantoine fa9484b630 (frontend) introduce a recording toaster
Notify visually users that the room is being recorded.
Draft, it will be enhance the future.
2024-12-04 18:38:26 +01:00
lebaudantoine 1e0e495cd8 ♻️(frontend) refactor pulse_mic into pulse_background
Make the keyframe more generic with an explicit naming.
2024-12-04 18:38:26 +01:00
lebaudantoine c270299179 🩹(frontend) fix submit button in feedbacks page
Since recent changes in the Color palette, the button was totally
invisible… fixed it.
2024-12-04 18:38:26 +01:00
lebaudantoine d9a84e5f0f 🔥(frontend) remove transcription menu item
This menu item was replaced by a side panel.
2024-12-04 18:38:26 +01:00
lebaudantoine 0f64d3cf3a (frontend) introduce a sidepanel for AI assistant
Introduce the content for the AI assistant panel, which describes the
feature, and offers a button to start and stop a recording.
2024-12-04 18:38:26 +01:00
lebaudantoine d1e008a844 ♻️(frontend) introduce useRoomId hook
Manipulating the room's id from the react-query cache should be
encapsulated in a dedicated hook.
2024-12-04 18:38:26 +01:00
lebaudantoine 3be5a5afc6 ♻️(frontend) package checks in useHasTranscriptAccess hook
This hook will be used by the toggle and the sidepanel to make
sure the users have sufficient permissions to access the transcript
features.
2024-12-04 18:38:26 +01:00
lebaudantoine 31468a5e7c ♻️(frontend) introduce a reusable isTranscriptEnabled
Encapsulate the logic, checking if the feature is enabled in the
backend, in a proper and reusable hook.
2024-12-04 18:38:26 +01:00
lebaudantoine b342b9d526 🚩(frontend) enable transcript toggle with a feature flag
Rely on Posthog for a first iteration on the feature flag feature.
This is a pragmatic choice, relying on an external dependency might
not suitable on the longer term, however, compare to the maturity
of our product, this is the best trade off.
2024-12-04 18:38:26 +01:00
lebaudantoine f7e7c3ba22 🚚(frontend) remove wrong 'tsx' extension
The hook only uses typescript code.
2024-12-04 18:38:26 +01:00
lebaudantoine 3902b02691 📈(frontend) check if analytic is enabled
Few frontend features rely on Posthog. Posthog is not activated in
dev environment. Offer a hook that encapsulates this logic, and
return a boolean flag.
2024-12-04 18:38:26 +01:00
lebaudantoine 7ce4390740 (frontend) initialize transcript sidebar panel
Setup base structure and styling for transcript menu sidebar
2024-12-04 18:38:26 +01:00
Jacques ROUSSEL 94d18cffe4 🔐(secrets) bump secretBump secret
In order to use our openai api we need new secret
2024-12-04 10:49:17 +01:00
lebaudantoine ad0c3eea66 🩹(summary) remove temporary audio files saved
I forgot to remove temporary files downloaded from the Minio bucket.
2024-12-04 10:49:17 +01:00
lebaudantoine 459bbf65a8 🔧(summary) use our self-deployed models
Configure dev and staging environment to use our self-deployed
models (Whisper and LLM). Secrets need to be updated btw.

Because of outscale LB bug, which timeout after 60s, we need to
connect directly to the svc.
2024-12-04 10:49:17 +01:00
lebaudantoine 4b4f16e93f 🔖(patch) bump release to 0.1.10
I made a mistake, and forgot to set summary and celery
deployment to 0 replicas.
2024-12-03 02:31:10 +01:00
lebaudantoine 3e3f964ac5 🚑️(helm) set celery and summary replicas to 0
These two services are not yet needed in production. Disable them.
2024-12-03 02:25:52 +01:00
lebaudantoine bcb111defb 🔖(patch) bump release to 0.1.9
Release the new ui, the logo, the footer, etc.
2024-12-03 02:12:36 +01:00
lebaudantoine 91a3aa4033 📱(frontend) fix few layout issues
For screen between xs and xsm, Dinum typography is creating
an overflow on mobile.

minHeight 'fit-content' is not working as expected on firefox.
2024-12-03 01:59:03 +01:00
lebaudantoine 05b74365fa 🐛(frontend) fix broken animation when motion is reduced
Feedback from one of our users.
I forgot animation can be disabled for accessibility purpose.
Fix it by bypassing the animation if reduce motion is activated.
Oopsie, mybad, I learnt something.
2024-12-03 01:05:06 +01:00
lebaudantoine 4eea4d01cd 🍱(frontend) install Marianne font
Declare Marianne font. Not sure of my configuration, lmk if
my configuration feel wrong @nvasse @manuhabitela.

It's a requirement in the public sector.
2024-12-03 01:05:06 +01:00
lebaudantoine 8caa6b7820 (frontend) add a fav icon
As I introduced the logo, let's add the missing favicon.
2024-12-03 01:05:06 +01:00
lebaudantoine e7e7bb0d09 💩(frontend) introduce an official footer
Based on Florian's feedbacks, this is mandatory as the project is
getting attention.

Bad code, needs a refactor.
2024-12-03 01:05:06 +01:00
lebaudantoine 819d3784f7 🍱(frontend) update homepage assets
Robin made a new design. Update the first image with this lit
design!!
2024-12-03 01:05:06 +01:00
lebaudantoine d83ccb3d9d (frontend) add all official logos
Based on Florian and Stéphanie feedbacks, add the 'Marianne' logo,
and a beta tag on our visio's logo.

I've slightly updated the header. Its responsive is broken in certain
situations.
2024-12-03 01:05:06 +01:00
lebaudantoine a083c8cc3a 💄(frontend) align participant placeholder with recent changes
Use a blue-ish background, instead of a gray one.
We'll continue to iterate on this component.
2024-12-03 01:05:06 +01:00
lebaudantoine a299cae8e8 🩹(frontend) prevent an error if crisp is not defined
While hot reloading the stack, I got an error, Crisp not being
defined at the time of the component rendering. Prevent such issue.
I am not 100% sure this commit is useful, WDYT?
2024-12-03 01:05:06 +01:00
lebaudantoine 60b7a35ed1 💄(frontend) replace grayscale button with a new variant
Button was looking disabled. Use an appropriate contrast.
2024-12-03 01:05:06 +01:00
lebaudantoine 39fdffd9a8 🩹(frontend) harmonize toggle colors in controls
nit-picking, match colors from the central controls
and the minor ones on the right.
2024-12-03 01:05:06 +01:00
lebaudantoine e3779d9a6e 💄(frontend) update color palette
Discussed IRL with Robin and Natan. Previous iteration wasn't
appropriated for a visioconference tool.

Try a trade off between nice colors and DSFR. We will probably
continue to iterate on these.
2024-12-03 01:05:06 +01:00
lebaudantoine b74d6e72f9 🔧(helm) configure staging to notify summary service
Add the relevant configurations, to be tested when deployed.
2024-12-02 14:33:54 +01:00
lebaudantoine 9be826fd14 ⬆️(summary) upgrade openai client to 1.55.3
Got an unexpected error while instantiating the openai client
since I installed sentry deps. I've upgraded openai version
without digging much, and it worked again.
2024-12-02 14:33:54 +01:00
lebaudantoine 4fe01ae2bf 💩(backend) notify the summary service when a new recording is available
Draft a piece of code to try the feature in staging. I'll consolidate this
implementation ASAP, as soon we have a first implementation functional.

What's missing?
- when owners are multiple
- retry when the backend cannot reach the summary service
- factorize the key oneliner, duplicated from the egress service
- optimize SQL query
- unit tests
2024-12-02 14:33:54 +01:00
lebaudantoine 300756b323 🔧(backend) configure sentry in staging and production
Share the same project as the microservice one. Will see in the future
if we need a separate sentry account for the backend. Good enough
at this project stage.
2024-12-02 14:33:54 +01:00
lebaudantoine 0af79912c5 📝(helm) generate documentation for summary microservices
Run the generate-readme script to add the documentation related to
the newly introduced microservice.
2024-12-02 14:33:54 +01:00
lebaudantoine 446270c153 🩹(summary) fix Helm Readme
Oopsie, I forgot to update the Helm readme.
Fixed it.
2024-12-02 14:33:54 +01:00
lebaudantoine e6377ce182 (summary) enable sentry monitoring
Necessary to monitor how the micro service acts.
Will tweak sentry configurations later on.
2024-12-02 14:33:54 +01:00
lebaudantoine a6b6cb7787 🔧(summary) make celery max retries an env configurations
Minor tweak ! It would be useful when we'll scale or microservice.
2024-12-02 14:33:54 +01:00
lebaudantoine 50146e95f4 🩹(summary) use the right s3 env variable
I use 'url' instead of the 'endpoint' as desired.
Leading the Minio client to fail connecting to the bucket.
Fixed it!
2024-12-02 14:33:54 +01:00
lebaudantoine 35741a1bc1 ♻️(summary) reorganize API code
I totally reorganized the API code, to gain in clarity.
2024-12-02 14:33:54 +01:00
lebaudantoine b12b14b277 🔒️(summary) run image as a non-root user
Based on @rouja's comment, this is a bad practice, running a docker
image as root. Added a User instruction with a default non-root user.
2024-12-02 14:33:54 +01:00
lebaudantoine bb30f25953 ⚰️(frontend) remove dead code
Introducing Crisp, we removed the menu item for support. I forgot
to remove its i18n content. My bad
2024-11-29 21:52:28 +01:00
lebaudantoine ebbdebf444 📱(front) improve control bar responsive
We want the bottom bar to stay at the center of the screen.

Co-authored-by: Nathan Vasse <nathan.vasse@gmail.com>
2024-11-29 21:52:28 +01:00
lebaudantoine fde10e7556 🩹(helm) add missing secret for summary service
Oopsie. I forced pushed and dropped this commit.
2024-11-29 19:00:48 +01:00
lebaudantoine 0dbb256e9f 👷(summary) build and push summary image
Copy pasted from the job in charge of building and pushing
the backend image.
2024-11-29 18:39:40 +01:00
lebaudantoine 33c8a3a9e4 💩(summary) declare microservice in staging
Add the minimal extra templates and env values to deploy the micro
service.
2024-11-29 18:39:40 +01:00
lebaudantoine dd0cb61ebc 💩(summary) kubernitize the micro service
Add the micro service to the helm chart.
2024-11-29 18:39:40 +01:00
lebaudantoine e92f084afb 💩(summary) vendor a first draft
This is written in a rush, boostrap the real logic with celery
worker to process meeting recording.

Lack of unit tests is critical, I am not proud of a it. I am
totally in a hurry for the demo. Not sure we will actually keep
this microservice.
2024-11-29 18:39:40 +01:00
lebaudantoine 4a53005ae3 💩(summary) compose the summary stack
Enhance the DX offering a docker compose with reloading.
2024-11-29 18:39:40 +01:00
lebaudantoine d7d82130d9 💩(summary) dockerize FastAPI app
Add a minimal docker file to run the FastAPI server.
2024-11-29 18:39:40 +01:00
lebaudantoine 16bee00eb4 💩(summary) init a FastAPI app
Bootsrap a generic FastAPI app to kick-start the microservice.
2024-11-29 18:39:40 +01:00
Jacques ROUSSEL 0f70b544ed 🔐(secrets) bump secret
Bump secret in order to enable recording on staging
2024-11-29 17:05:29 +01:00
lebaudantoine 2903442a67 🎨(frontend) enhance few naming
I committed in a rush the transcript item, fix my dirty code.
Enhance few naming.
2024-11-29 17:05:29 +01:00
lebaudantoine be884a8ca1 🚩(frontend) display transcript item only for admin/owner
Only room admin/owner should be abble to start a transcript.
2024-11-29 17:05:29 +01:00
lebaudantoine fe70165076 🚩(frontend) display transcript items only when back is enabled
Avoid displaying the feature in the client if it's disabled
in the backend.
2024-11-29 17:05:29 +01:00
lebaudantoine 290ba4274a ⚰️(frontend) remove dead code
With chat refactoring, few lines of code was dead.
Fix it!
2024-11-29 17:05:29 +01:00
lebaudantoine d2f239e6a2 🚧(frontend) add a temporary items to interact with transcription
This is totally temporary, only to test transcription recording.
In the upcoming commits, a proper side panel with all activities
will be created.
2024-11-29 17:05:29 +01:00
lebaudantoine c61fc40671 (frontend) add API to start/stop recording
API calls to interact with backend, minimal call. Might be improved.
2024-11-29 17:05:29 +01:00
lebaudantoine 10705ca3ac 🩹(backend) fix duplication due to a bad rebase
While rebasing, I made few mistake with a settings wrongly renamed.
Oopsie fix this huge mistake.

Plus, a line was duplicated in Event authentication.
2024-11-29 17:05:29 +01:00
lebaudantoine 6b03ebb393 🔧(backend) enable recording and storage hook
Update values for dev and staging environment to enable
recording-related endpoints. A new secret need to be created.

Production values will be added in an upcoming commit.
2024-11-29 17:05:29 +01:00
Jacques ROUSSEL 0627510f10 ♻️(tilt) simplify the local stack
This commit solves few issues:
- sharing the relevant certificates with minio so when triggering the webhook
notification, the minio pod can verify our backend domain certificates.
- making sure everything spawn in the right namespace (LiveKit and the Egress)
without relying on a dirty fix in the make start-tilt.

all these fixes were made by @rouja, I don't fully understand them yet.
He simplified the stack, removing two Kind nodes to make it lightweight.

thx @rouja.
2024-11-29 15:54:24 +01:00
NathanVss f9233c8fb3 Merge pull request #245 from numerique-gouv/feat/video-conference-ui
Enhance Conference UI
2024-11-28 11:49:00 +01:00
Nathan Vasse 0b672ef8da 🚨(front) fix ui enhancement formats
Some formatting were forgotten, here is the fix.
2024-11-28 11:41:38 +01:00
Nathan Vasse 0b0efa5bab 💄(front) improve menu and select ui
We want to introduce two variant for this lists, so it was needed
to create a slot recipe.
2024-11-28 11:30:37 +01:00
Nathan Vasse 0958206057 💄(front) enhance ui first shot
Based on recent sketches, we decided to implement the new ui. This is
a first shot, more will be coming next.
2024-11-28 11:30:32 +01:00
renovate[bot] 4e13ace815 ⬆️(dependencies) update js dependencies 2024-11-25 11:44:30 +01:00
renovate[bot] 30ee0fdce3 ⬆️(dependencies) update python dependencies 2024-11-25 11:35:11 +01:00
renovate[bot] 17453a6cee ⬆️(dependencies) update aiohttp to v3.10.11 [SECURITY] 2024-11-25 10:42:02 +01:00
lebaudantoine c1e8ebc129 💬(frontend) rename Agent Connect mentions
Feedback from C Chausse. Outdated copy writting.
2024-11-25 10:36:01 +01:00
lebaudantoine a1dbf02f9c 🩹(frontend) avoid franglish copywritting
My bad, few english terms were mixed in some french ones.
Fixed it.
2024-11-25 10:35:38 +01:00
lebaudantoine c4206b4b24 🔖(patch) bump release to 0.1.8 2024-11-19 00:24:29 +01:00
lebaudantoine 732df0768c 💄(frontend) adjust home based on Sam feedbacks
Based on Samuel's feedbacks, adjust few details.
2024-11-18 13:31:26 +01:00
lebaudantoine 8a96b6939a 🐛(helm) rename bucket
Wrong copy paste. My bad, bucket's name wasn't matching our project.
2024-11-18 10:04:21 +01:00
lebaudantoine e78b8c69fe 🩹(frontend) add missing key
Fix missing warning, key props was missing on the item of the
for loop.
2024-11-18 01:22:54 +01:00
lebaudantoine 6e49ab3230 💄(frontend) narrow home layout
Avoid having too much white space around the home content.
2024-11-18 01:22:54 +01:00
lebaudantoine 200e2d3c2f 💩(frontend) introduce multistep form
Add an open feedback form step, to allow people giving us some
feedbacks on what's wrong with our product.
2024-11-18 01:22:54 +01:00
lebaudantoine 4ffef3f94a 🚸(frontend) add hover animation on rating Button
Nitpicking, enhance small interactivity with form.
2024-11-18 01:22:54 +01:00
lebaudantoine 8e62f2ecd3 🩹(frontend) fix TextArea export
Wrongly exported the TextArea primitive, mybad.
Fixed !
2024-11-18 01:22:54 +01:00
lebaudantoine d024fb1b95 (frontend) capture from with PostHog survey
Initialize logic related to PostHog, use an API survey to avoid
having element branded with PostHog logo.
2024-11-18 01:22:54 +01:00
lebaudantoine 7e49f0f661 ⬆️(frontend) update PostHog sdk
Required by PostHog app, to benefits from latest survey features.
2024-11-18 01:22:54 +01:00
lebaudantoine fb8c0fd1b5 💄(frontend) refactor feedbacks screen
Enhance initial screen. Allow user returning to the meeting.
Also, add basic and non-functional rating component to mock,
what the form would be.
2024-11-18 01:22:54 +01:00
lebaudantoine b07e4c58b4 💄(frontend) remove slider feature on small screens
Fit the slider content into small screen, by disabling all features
related to the slider. Good enough for a first draft.
2024-11-17 16:48:54 +01:00
lebaudantoine e6bbf2d3c8 💄(frontend) enhance header responsiveness
Quick fix, not optimal. Removed a useless breaking point IMO.
I won't spend too much time on the Header component, I'll
introduce new features needing a heavy layout update.
2024-11-17 16:48:54 +01:00
lebaudantoine 28899a2aaf 🚨(frontend) fix bundler warning on build
Typo while styling the homepage. Fixed it.
Minor issue.
2024-11-17 16:48:54 +01:00
lebaudantoine a5bc66a921 💄(frontend) adjust title's responsiveness
Needed for small and phone screen.
Not a huge fan of having breaking point to manage, but
made an exception for the landing page content.
2024-11-17 16:48:54 +01:00
lebaudantoine adb09410da 💄(frontend) introduce a new breaking point
Needed a trade off between xs and sm breaking points.
Introduce xsm, I am not very satisfied with this naming.
We might refactor xs in xss. Not urgent.
2024-11-17 16:48:54 +01:00
lebaudantoine 061f12e7e2 💄(frontend) update feedback button to banner with context
Refactored the feedback alert button into a more discreet and polished banner.
The banner provides additional context about Visio being under construction.
Also updated the link to the feedback form.
2024-11-17 15:29:26 +01:00
lebaudantoine 24e819a533 🩹(frontend) use browser language if no localStorage for detection
Previously, language detection was failing to read browser settings correctly.
Added explicit detection order to ensure localStorage preferences are checked
before falling back to browser language.
2024-11-17 14:56:32 +01:00
lebaudantoine 5c48ac100a (frontend) allow user register to beta feature
I've created a beta form, allowing interested visitors to
register to be a beta user.

This form is yet created with Grist, could be enhance. I'll
investigate using PostHog.
2024-11-17 01:08:13 +01:00
lebaudantoine 4434f0265d 💫(frontend) add fadein animation on home
Elements' apparition felt quite harsh.
Add an animation to fade in content.
Used a pre-defined animation in panda configs.
2024-11-17 01:08:13 +01:00
lebaudantoine 0522696842 💫(frontend) add animation on interaction with slider
Add a minimal animation to enhance micro-interaction with our app.
I've tried being minimal, please feel free to enhance or tune this
animation.
2024-11-17 01:08:13 +01:00
lebaudantoine 8516782d79 (frontend) add slide feature in the IntroSlider
Avoided installing a dependency for such small piece of code.
I've implemented a naive component, which allow users explore
the slide presenting key feature of our app.

User experience should be ok. However, I might need to optimize
image format and loading strategy. First 'raw' iteration, gonna
optimize it in the future.
2024-11-17 01:08:13 +01:00
lebaudantoine b06880be15 💄(frontend) enhance home page
I've totally rework the homepage, heavily inspired by GMeet.
Goal: make it more pro, and polished.
2024-11-17 01:08:13 +01:00
lebaudantoine 5de9cec688 (frontend) introduce learn more link component
Component providing a 'learn more' feature. Inspired by GMeet.
Naive component.
2024-11-17 01:08:13 +01:00
lebaudantoine 7dfd86873c 🚸(frontend) update A component hover animation
I found original to hide text decoration on hover. It felt wrong
to me, I proposed a new animation. Please feel free to rework it
or enhance it in the future.
2024-11-17 01:08:13 +01:00
lebaudantoine 7cee409d22 🚧(frontend) add intro slider component with feature slides
Created a component for an intro slider to showcase app features.
Each slide will include a minimal illustration and concise descriptions.

Work In Progress, Slide logic will be added in upcomming commits.
2024-11-17 01:08:13 +01:00
lebaudantoine 7ddc448c88 💄(frontend) remove bottom border on header
The bottom border on the header was unnecessary
and removed for a cleaner design.
2024-11-17 01:08:13 +01:00
lebaudantoine 6fcb69bd3c 🩹(frontend) fix horizontal scroll issue
Oooopsie while merging chat, I forgot to test horizontal scrolling.
It ended up creating a scroll issue. Fixed!

This fix might create a new issue for mobile users, I'll refactor
their layout ASAP.
2024-11-16 00:29:58 +01:00
lebaudantoine 6aed4cb751 🚸(frontend) auto-populate prejoin screen with user's default full name
Streamline user joining a room by pre-fillig name field from
their ProConnect data. Reduces friction and typos in the join flow.

This feature will be mostly used by new users. Recurrent users have
their previous choices persisted in local storage.
2024-11-16 00:29:58 +01:00
lebaudantoine f433f59d3f ♻️(frontend) prioritize full name display before email
Why? user friendly, and more human-readable identifier. Should
be enhance later on, to display both info together.
2024-11-16 00:29:58 +01:00
lebaudantoine fba9910705 (frontend) declare full and short name in APIUser type
API now serialize these two data. Save them when requestion /me.
2024-11-16 00:29:58 +01:00
lebaudantoine dcba3330f7 🛂(backend) request given and usual name scopes from ProConnect
Request the necessary scopes from ProConnect service.
Update configurations in every environments.

Note: ask given_name and usual_name scopes to get users' info.

(these scopes should be granted by default by ProConnect when
requesting a client id client secret)
2024-11-16 00:29:58 +01:00
lebaudantoine 82bb5f0f8b (backend) persist OIDC first name and last name while authenticating
Inspired by @sampaccoud's eee2003 commit on impress, adapt the code to be more
Pythonic. Add basic test coverage for user name synchronization on login. User
name fields now update automatically at each login when new data is available.

Note: current logic doesn't handle the case where a user with existing names
logs in with missing first/last names - should we clear the names then?

Removing a field that was present in the initial form is not a valid update
operation.
2024-11-15 23:38:31 +01:00
lebaudantoine 0fd06ef6c0 ♻️(backend) isolate authentication tests when dealing only with email
Refactor a test to narrow down its scope to email-related updates.
2024-11-15 23:38:31 +01:00
lebaudantoine bd4dec6f27 (backend) serialize user name-related fields
Needed in the frontend. Updated existing tests accordingly.
Names are not yet saved while logging the user, it will be
added in the upcomming commits.
2024-11-15 23:38:31 +01:00
lebaudantoine a987830fb3 🗑️(backend) remove useless methods on User
While removing analytics code in 15e922f, I forgot to remove
related code in the User model, used nowwhere else. Oopsie.
Fixed it!
2024-11-15 23:38:31 +01:00
lebaudantoine 7f09636791 (backend) add full_name short_name on User model
Following @sampaccoud's work on impress, add new fields to handle
user names in our application.

@sampaccoud preferred having a full and short names instead of
a basic first and last ones, to follow common good practices, and
avoid having frontend formating names (from my understanding).

Please see commit eee20033 on Impress.
2024-11-15 23:38:31 +01:00
lebaudantoine 3460ec8808 ✏️(backend) fix minor typo
login is a noun, the verb needs a whitespace.
2024-11-15 23:38:31 +01:00
lebaudantoine 86cda75b39 🐛(frontend) tune connection parameters for low bandwidth clients
DINUM users face connection issues in bandwidth-constrained environments.
They cannot reach their room, the peer connection timeouts while negotiating
TURN/TLS handshake (from our current understanding).

I am not sure this issue is linked to those parameters, at least try something.
2024-11-15 23:38:31 +01:00
lebaudantoine 7afa165013 (backend) offer an endpoint to save recording
I've protected this endpoint with a feature flag, and an authentication
class, as it will be exposed on the public internet.

I've tried to keep the viewset logic as minimal as possible, I've
to ship smth and will continue iterating on this piece of code.

At some point, abstracting webhook endpoint and authentication class
might be beneficial for the project. YAGNI as of today.
2024-11-13 19:36:17 +01:00
lebaudantoine e11bdc6d28 ♻️(backend) update is_savable method
A recording is savable only if it's active or stopped. In other
status (error, already saved, etc.) it won't be possible. I might
iterate on this piece of code. Let's ship it.
2024-11-13 19:36:17 +01:00
lebaudantoine 8309545ec6 (backend) add minio event parser
When a new file is uploaded to a Minio Bucket, a webhook can be
configured to notify third parties about the event. Basically,
it's a POST call with a payload providing informations on the
event that just happened.

When a recording worker will stop, it will upload its data to a Minio
bucket, which will trigger the webhook.

Try to introduce the minimalest code to parse these events, discard
them whener it's relevant, and extract the recording ID, thus we
know which recording was successfully saved to the Minio bucket.

In the longer runner, it will trigger a callback.
2024-11-13 19:36:17 +01:00
lebaudantoine 840033fcbc 🔧(frontend) get configs related to the recording feature
Get optional config related to the recording feature. RecordingMode will
be refactored as soon I start working on the recording feature.
2024-11-13 19:23:34 +01:00
lebaudantoine 28ca2d6c37 (backend) expose recording configurations to the client
Inform frontend code, if recording a room is enabled, and which recordings modes
are available. Frontend should adapt its behavior based on this data.
2024-11-13 19:23:34 +01:00
lebaudantoine 4e77458116 🚨(backend) fix Django deprecation warning in RecordingFactory
Addressed a `DeprecationWarning` in `RecordingFactory` related to the
`_after_postgeneration` method, which will stop saving the instance after
postgeneration hooks in the next major release. To resolve this,
`skip_postgeneration_save=True` was added to `RecordingFactory.Meta` to
avoid extraneous save calls. Alternatively, if instance saving is needed,
the save call can be moved to postgeneration hooks or by overriding
`after_postgeneration`.
2024-11-13 18:34:16 +01:00
lebaudantoine d4532eeb64 ♻️(backend) remove unnecessary manipulation of the room name
Avoided unnecessary manipulation of the room name to prevent issues when
starting an egress worker. Previously, hyphens were stripped from the room
name, likely inherited from the legacy setup with Jitsi in Magnify, though
the purpose of this change is unclear and might be an undesired legacy
feature.

To ensure accurate room matching during egress worker requests, this update
removes any manipulation of the room name. This approach minimizes the risk
of errors when initiating recordings and maintains the integrity of the
original room name throughout the process.
2024-11-13 18:34:16 +01:00
lebaudantoine b84628ee95 (backend) add two new endpoints to start and stop a recording
The LiveKit egress worker interactions are proxied through the backend for
security reasons. Allowing clients to directly use tokens with sufficient
grants to start recordings could lead to misuse, enabling users to spam the
egress worker API and potentially initiate a DDOS attack on the egress
service. To prevent this, only users with room-specific privileges can
initiate recordings.

We make sure only one recording at the time can be made on a room.

The requested recording mode is stored so it can be referenced later when
the recording is saved, triggering a callback action as needed.

A feature flag was also introduced for this capability; while this is a simple
approach, a more robust system for managing feature flags could be valuable
long-term. For now, KISS (Keep It Simple, Stupid) applies.

The viewset endpoints were designed to be as straightforward as possible—
let me know if anything can be improved.
2024-11-13 18:34:16 +01:00
lebaudantoine f6f1222f47 (backend) introduce general recording worker concepts
Introducing a new worker service architecture. Sorry for the long commit.
This design adheres to several key principles, primarily the  Single
Responsibility Principle. Dependency Injection and composition are
prioritized over inheritance, enhancing modularity and maintainability.

Interactions between the backend and external workers are encapsulated in
classes implementing a common `WorkerService` interface. I chose Protocol
over an abstract class for agility, aligning closely with static typing
without requiring inheritance. Each `WorkerService` implementation can
independently manage recordings according to its specific requirements.
This flexibility ensures that adding a new worker service, such as for
LiveKit, can be done without any change to existing components.

Configuration management is centralized in a single `WorkerServiceConfig`
class, which loads and provides all settings for different worker
implementations, keeping configurations organized and extensible. The worker
service class itself handles accessing relevant configurations as needed,
simplifying the configuration process.

A basic dictionary in Django settings acts as a factory, responsible for
instantiating the correct worker service based on the client's request mode.
This approach aligns with Django development conventions, emphasizing
simplicity. While a full factory class with a builder pattern could provide
future flexibility, YAGNI (You Aren't Gonna Need It) suggests deferring
such complexity until it’s necessary.

At the core of this design is the worker mediator, which decouples worker
service implementations from the Django ORM and manages database state
according to worker state. The mediator is purposefully limited in
responsibility, handling only what’s essential. It doesn’t instantiate
worker services directly; instead, services are injected via composition,
allowing the mediator to manage any object conforming to the `WorkerService`
interface. This setup preserves flexibility and maintains a clear
separation of responsibilities. The factory create worker services,
the mediator runs it.

(sorry for this long commit)
2024-11-13 18:34:16 +01:00
lebaudantoine 7278613b20 🗃️(backend) merge duplicate user accounts on email
Write the proper ORM code to sanitize the rows in db and avoid
existing users lose access to our app.

Existing duplicate user accounts are merged, and resource accesses
are transferred.
2024-11-12 16:56:58 +01:00
lebaudantoine d370a4db10 🐛(backend) harden email matching against ambiguous cases
Handle case-sensitivity and whitespace in email lookups. Detect and block
multiple matching accounts as security precaution.
2024-11-12 16:56:58 +01:00
lebaudantoine c1bc379744 🧪(backend) add test for email matching
Add test cases for email-based user matching fallback logic:
- String comparison edge cases
- Multiple users with matching email addresses
- Invalid email format handling

Fix will follow in subsequent commit.
2024-11-12 16:56:58 +01:00
lebaudantoine 5ef6359b7c 🛂(backend) fallback to email matching when OIDC sub is not found
When OIDC providers return random values in the "sub" field instead of stable
identifiers, implement email-based user matching as fallback.

Note: Current implementation needs improvement. Tests forthcoming.

Original: @sampaccoud (ff7914f) on Impress
2024-11-12 16:56:58 +01:00
lebaudantoine 04d76acce5 (backend) handle inactive user
Handle case where user is inactive.
Previously this edge case would cause unexpected behavior.

Related to previous commit that added the test coverage.
2024-11-12 16:56:58 +01:00
lebaudantoine eeb71f90bc 🧪(backend) add test for inactive user
Add failing test for case when user is inactive.
This case was highlighted by @qbey and was previously untested.
Fix will follow in subsequent commit.
2024-11-12 16:56:58 +01:00
lebaudantoine 5db4b09106 ♻️(backend) remove redundant create_user method
Remove redundant wrapper method that duplicates SUB validation logic.
Already validated in parent class, following the pattern established by
@sampaccoud in People and Impress modules.
2024-11-12 16:56:58 +01:00
lebaudantoine 11cd85d4eb (backend) handle empty subscription string
Handle case where sub value is an empty string instead of None.
Previously this edge case would cause unexpected behavior.

Related to previous commit that added the test coverage.
2024-11-12 16:56:58 +01:00
lebaudantoine ccbeeba68f 🧪(backend) add test for empty sub string
Add failing test for corner case when sub value is an empty string.
This edge case was discovered by @sampaccoud and was previously untested.
Fix will follow in subsequent commit.
2024-11-12 16:56:58 +01:00
lebaudantoine f3ea0fca71 🐛(frontend) fix missing user label in prejoin screen
Add missing hint to guide user entering their name while
joining a room.

I introduced this bug while merging @manuhabitela works on
the newly prejoin screen.
2024-11-11 21:20:08 +01:00
lebaudantoine cb4acc32e5 🗑️(backend) remove useless analytics settings
Remove useless analytics key settings as we removed tracking
data from the backend code.
2024-11-08 10:45:58 +01:00
lebaudantoine 60f5c8486b 🩹(backend) add missing Django settings for cold storage access
After configuring the cold storage infrastructure, I forgot to add Django
settings needed to access the configuration.
2024-11-08 10:45:58 +01:00
lebaudantoine ed3a26d449 (backend) enable Django Admin on Recording
Manage Recording in the Django Admin. As of today, I have not enforced
a strict policy to avoid edit on recording rows or even creating new
data point directly from the admin. Will do in the future.
2024-11-08 10:36:38 +01:00
lebaudantoine cb4c058c5d (backend) add minimal Recording viewset for room recordings
Implements routes to manage recordings within rooms, following the patterns
established in Impress. The viewset exposes targeted endpoints rather than
full CRUD operations, with recordings being created (soon) through
room-specific routes (e.g. room/123/start-recording).

The implementation draws from @sampaccoud's initial work and advices.

Review focus areas:
- Permission implementation choices
- Serializer design and structure

Credit: Initial work by @sampaccoud
2024-11-08 10:36:31 +01:00
lebaudantoine c504b5262b (backend) introduce Recording model with independent access control
The Recording model is introduced to track recording lifecycle within rooms,
while maintaining strict separation of access controls between rooms and
recordings.

Recordings follow the BaseAccess pattern (similar to Documents in Impress),
providing independent access control from room permissions. This ensures that
joining a room doesn't automatically grant access to previous recordings,
allowing for more flexible permission management.

The implementation was driven by TDD, particularly for the get_abilities
function, resulting in reduced nesting levels and improved readability.

The Recording model is deliberately kept minimal to serve as a foundation for
upcoming AI features while maintaining flexibility for future extensions.

I have avoided LiveKit-specific terminology for better abstraction.

Note: Room access control remains unchanged in this commit, pending future
refactor to use BaseAccess pattern (discussed IRL with @sampaccoud).
2024-11-07 18:06:26 +01:00
lebaudantoine 3b3816b333 ♻️(backend) rename room-specific setting in Resource class
Renames a Django setting in the Resource base class to use resource-agnostic
terminology. While rooms are currently the only resource type, keeping base
class naming generic improves clarity.
2024-11-07 18:06:26 +01:00
lebaudantoine 15e922f9df 🔥(backend) vendor analytics code
Analytics code is now useless, we mostly use
frontend tracking.
2024-11-04 17:49:15 +01:00
lebaudantoine b69f777e5a 🔧(helm) expose MinIO console via ingress
Add ingress configuration for MinIO web console access. Include Nginx proxy
buffer annotations to support large file uploads through web interface.
2024-11-04 15:24:58 +01:00
lebaudantoine 67d004fbda ♻️(backend) refactor try/except when getting a room
Be more Pythonist simplifying try except while tracking when
user is getting a room.
2024-11-04 15:21:24 +01:00
lebaudantoine 4449b578bd 🐛(config) rename hardcoded docker-compose filename
Previously, the Docker Compose filename was hardcoded in _config.sh when used
through utility scripts. In recent commits, I've renamed the filename without
updating this configuration.

Oopsie, running make commands was fine, but running bin scripts
requiring compose failed.
2024-11-04 14:17:31 +01:00
lebaudantoine 1f0d2ce335 🚨(backend) fix Pylint warning
Python module models.py raises too-many-ancestors warning, but linter
still pass, code is rated 10/10.

Inspired from @sampaccoud's commit #eee20032 on impress.
2024-11-04 14:17:31 +01:00
lebaudantoine 0d1d0662ee ♻️(compose) rename docker-compose to compose
Docker Compose now by default search for a 'compose' file.
(according to @jonathanperret).
2024-11-03 22:31:30 +01:00
lebaudantoine 0056b4cc29 🔥(compose) remove docker compose version
The version is now automatically guessed by Docker Compose. This
commit will fix the warning raised about the uselessness of this
setting.

from @sampaccoud
2024-11-03 22:31:30 +01:00
lebaudantoine d7892cde9f (backend) move freezegun to dev dependencies
Freezegun is for testing and should not be installed in the
production image. (from @sampaccoud)
2024-11-03 22:31:30 +01:00
lebaudantoine 372db49e94 🎨(docker) convert to uppercase 'as' keyword
Match 'FROM' casing, to remove a warning.
2024-11-03 22:31:30 +01:00
lebaudantoine f7ed70dc9c (livekit) add Livekit Egress
Egress is already deployed in staging. But, while
working locally on feature relying on Egress, it's not
suitable to test your development or iterate.

Especially I'll need to test the connection between the Egress
and the minio bucket in my next PR.

We faced quite a few issue while starting the whole stack.
Egress didn't want to start. Its connection with the livekit server
while the egress participant was joining the room was not successful.

The Turn part of the livekit server helm chart was activated. We needed
to update few values to in the helm configuration to enabled this turn.

Updated CoreDNS to expose Egress pod. Egress tries connecting to MinIO at
127.0.0.1, where no instance exists. Using minio.127.0.0.1.nip.io resolves
to 127.0.0.1, causing Egress to connect to itself for uploads. The CoreDNS
rewrite directs this to the Ingress IP, correctly routing to MinIO.
2024-10-28 10:26:51 +01:00
lebaudantoine 427b23ca80 (backend) add S3 objects
Inspired by Impress and @sampaccoud's work.

We use Indie Hoster’s Kubernetes objects in staging and production.
In the "dev" environment, we install the `bitnami/minio` chart to mimic
Indie Hoster’s MinIO setup.

To access the MinIO admin interface in dev, use port forwarding;
the interface runs on port 9001.
2024-10-28 10:26:51 +01:00
lebaudantoine 99a1efc538 🐛(helm) deploy livekit in 'meet' namespace
LiveKit Helm chart doesn't support namespace parameterization
like MinIO templates. Egress and server deploy to default namespace,
but frontend and backend need all components in the same namespace.

Workaround: force kubectl context to 'meet' before starting Tilt.
Future improvement needed in chart.

Issue #105 have been opened in livekit-helm repo.
2024-10-28 10:26:51 +01:00
813 changed files with 103255 additions and 9254 deletions
+8 -6
View File
@@ -4,7 +4,7 @@ __pycache__
**/__pycache__
**/*.pyc
venv
.venv
**/.venv
# System-specific files
.DS_Store
@@ -24,13 +24,15 @@ data
.cache
.circleci
.git
.vscode
.iml
.idea
db.sqlite3
.mypy_cache
.pylint.d
.pytest_cache
**/.idea
**/.vscode
**/.pytest_cache
**/.mypy_cache
**/.ruff_cache
# Frontend
node_modules
**/node_modules
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Download Crowdin files
uses: crowdin/github-action@v2
-52
View File
@@ -1,52 +0,0 @@
name: Deploy
on:
push:
tags:
- 'preprod'
- 'production'
jobs:
notify-argocd:
runs-on: ubuntu-latest
steps:
-
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: "meet,secrets"
-
name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
-
name: Load sops secrets
uses: rouja/actions-sops@main
with:
secret-file: secrets/numerique-gouv/meet/secrets.enc.env
age-key: ${{ secrets.SOPS_PRIVATE }}
-
name: Call argocd github webhook
run: |
data='{"ref": "'$GITHUB_REF'","repository": {"html_url":"'$GITHUB_SERVER_URL'/'$GITHUB_REPOSITORY'"}}'
sig=$(echo -n ${data} | openssl dgst -sha1 -hmac ''${ARGOCD_WEBHOOK_SECRET}'' | awk '{print "X-Hub-Signature: sha1="$2}')
curl -X POST -H 'X-GitHub-Event:push' -H "Content-Type: application/json" -H "${sig}" --data "${data}" $ARGOCD_WEBHOOK_URL
sig=$(echo -n ${data} | openssl dgst -sha1 -hmac ''${ARGOCD_PRODUCTION_WEBHOOK_SECRET}'' | awk '{print "X-Hub-Signature: sha1="$2}')
curl -X POST -H 'X-GitHub-Event:push' -H "Content-Type: application/json" -H "${sig}" --data "${data}" $ARGOCD_PRODUCTION_WEBHOOK_URL
start-test-on-preprod:
needs:
- notify-argocd
runs-on: ubuntu-latest
if: startsWith(github.event.ref, 'refs/tags/preprod')
steps:
-
name: Debug
run: |
echo "Start test when preprod is ready"
+183 -77
View File
@@ -14,97 +14,84 @@ on:
env:
DOCKER_USER: 1001:127
DOCKER_CONTAINER_REGISTRY_HOSTNAME: docker.io
DOCKER_CONTAINER_REGISTRY_NAMESPACE: lasuite
jobs:
build-and-push-backend:
runs-on: ubuntu-latest
steps:
-
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: "meet,secrets"
-
name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
uses: actions/checkout@v6
-
name: Load sops secrets
uses: rouja/actions-sops@main
with:
secret-file: secrets/numerique-gouv/meet/secrets.enc.env
age-key: ${{ secrets.SOPS_PRIVATE }}
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: lasuite/meet-backend
images: '${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-backend'
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
run: echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USER" --password-stdin
-
name: Run trivy scan
uses: numerique-gouv/action-trivy-cache@main
uses: docker/login-action@v3
with:
docker-build-args: '--target backend-production -f Dockerfile'
docker-image-name: 'docker.io/lasuite/meet-backend:${{ github.sha }}'
username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
# -
# name: Run trivy scan
# uses: numerique-gouv/action-trivy-cache@main
# with:
# docker-build-args: '--target backend-production -f Dockerfile'
# docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-backend:${{ github.sha }}'
-
name: Build and push
uses: docker/build-push-action@v6
with:
context: .
target: backend-production
platforms: linux/amd64,linux/arm64
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-frontend:
build-and-push-frontend-generic:
runs-on: ubuntu-latest
steps:
-
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: "meet,secrets"
-
name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
uses: actions/checkout@v6
-
name: Load sops secrets
uses: rouja/actions-sops@main
with:
secret-file: secrets/numerique-gouv/meet/secrets.enc.env
age-key: ${{ secrets.SOPS_PRIVATE }}
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: lasuite/meet-frontend
images: '${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-frontend'
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
run: echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USER" --password-stdin
-
name: Run trivy scan
uses: numerique-gouv/action-trivy-cache@main
uses: docker/login-action@v3
with:
docker-build-args: '-f src/frontend/Dockerfile --target frontend-production'
docker-image-name: 'docker.io/lasuite/meet-frontend:${{ github.sha }}'
username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
# -
# name: Run trivy scan
# uses: numerique-gouv/action-trivy-cache@main
# with:
# docker-build-args: '-f src/frontend/Dockerfile --target frontend-production'
# docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-frontend:${{ github.sha }}'
-
name: Build and push
uses: docker/build-push-action@v6
@@ -112,6 +99,143 @@ jobs:
context: .
file: ./src/frontend/Dockerfile
target: frontend-production
platforms: linux/amd64,linux/arm64
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-frontend-dinum:
runs-on: ubuntu-latest
steps:
-
name: Checkout repository
uses: actions/checkout@v6
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: '${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-frontend-dinum'
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
# -
# name: Run trivy scan
# uses: numerique-gouv/action-trivy-cache@main
# with:
# docker-build-args: '-f docker/dinum-frontend/Dockerfile --target frontend-production'
# docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-frontend-dinum:${{ github.sha }}'
-
name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/dinum-frontend/Dockerfile
target: frontend-production
platforms: linux/amd64,linux/arm64
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-summary:
runs-on: ubuntu-latest
steps:
-
name: Checkout repository
uses: actions/checkout@v6
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: '${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-summary'
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
# -
# name: Run trivy scan
# uses: numerique-gouv/action-trivy-cache@main
# continue-on-error: true
# with:
# docker-build-args: '-f src/summary/Dockerfile --target production'
# docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-summary:${{ github.sha }}'
docker-context: './src/summary'
-
name: Build and push
uses: docker/build-push-action@v6
with:
context: ./src/summary
file: ./src/summary/Dockerfile
target: production
platforms: linux/amd64,linux/arm64
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-agents:
runs-on: ubuntu-latest
steps:
-
name: Checkout repository
uses: actions/checkout@v6
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: lasuite/meet-agents
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
# -
# name: Run trivy scan
# uses: numerique-gouv/action-trivy-cache@main
# continue-on-error: true
# with:
# docker-build-args: '-f src/agents/Dockerfile --target production'
# docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-agents:${{ github.sha }}'
# docker-context: './src/agents'
-
name: Build and push
uses: docker/build-push-action@v6
with:
context: ./src/agents
file: ./src/agents/Dockerfile
target: production
platforms: linux/amd64,linux/arm64
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
@@ -119,35 +243,17 @@ jobs:
notify-argocd:
needs:
- build-and-push-frontend
- build-and-push-frontend-generic
- build-and-push-frontend-dinum
- build-and-push-backend
- build-and-push-summary
- build-and-push-agents
runs-on: ubuntu-latest
if: |
github.event_name != 'pull_request'
if: github.event_name != 'pull_request'
steps:
-
uses: actions/create-github-app-token@v1
id: app-token
- uses: numerique-gouv/action-argocd-webhook-notification@main
id: notify
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: "meet,secrets"
-
name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
-
name: Load sops secrets
uses: rouja/actions-sops@main
with:
secret-file: secrets/numerique-gouv/meet/secrets.enc.env
age-key: ${{ secrets.SOPS_PRIVATE }}
-
name: Call argocd github webhook
run: |
data='{"ref": "'$GITHUB_REF'","repository": {"html_url":"'$GITHUB_SERVER_URL'/'$GITHUB_REPOSITORY'"}}'
sig=$(echo -n ${data} | openssl dgst -sha1 -hmac ''${ARGOCD_WEBHOOK_SECRET}'' | awk '{print "X-Hub-Signature: sha1="$2}')
curl -X POST -H 'X-GitHub-Event:push' -H "Content-Type: application/json" -H "${sig}" --data "${data}" $ARGOCD_WEBHOOK_URL
deployment_repo_path: "${{ secrets.DEPLOYMENT_REPO_URL }}"
argocd_webhook_secret: "${{ secrets.ARGOCD_PREPROD_WEBHOOK_SECRET }}"
argocd_url: "${{ vars.ARGOCD_PREPROD_WEBHOOK_URL }}"
-22
View File
@@ -1,22 +0,0 @@
name: Helmfile lint
run-name: Helmfile lint
on:
pull_request:
branches:
- 'main'
jobs:
helmfile-lint:
runs-on: ubuntu-latest
container:
image: ghcr.io/helmfile/helmfile:latest
steps:
-
uses: numerique-gouv/action-helmfile-lint@main
with:
app-id: ${{ secrets.APP_ID }}
age-key: ${{ secrets.SOPS_PRIVATE }}
private-key: ${{ secrets.PRIVATE_KEY }}
helmfile-src: "src/helm"
repositories: "meet,secrets"
+192 -82
View File
@@ -7,45 +7,85 @@ on:
pull_request:
branches:
- "*"
permissions:
contents: read
jobs:
lint-git:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' # Makes sense only for pull requests
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: show
run: git log
- name: Enforce absence of print statements in code
if: always()
run: |
! git diff origin/${{ github.event.pull_request.base.ref }}..HEAD -- . ':(exclude)**/meet.yml' | grep "print("
- name: Check absence of fixup commits
if: always()
run: |
! git log | grep 'fixup!'
- name: Install gitlint
if: always()
run: pip install --user requests gitlint
- name: Lint commit messages added to main
if: always()
run: ~/.local/bin/gitlint --commits origin/${{ github.event.pull_request.base.ref }}..HEAD
check-changelog:
runs-on: ubuntu-latest
if: |
contains(github.event.pull_request.labels.*.name, 'noChangeLog') == false &&
github.event_name == 'pull_request'
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 50
- name: Check that the CHANGELOG has been modified in the current branch
run: git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.after }} | grep 'CHANGELOG.md'
lint-changelog:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Check CHANGELOG max line length
run: |
max_line_length=$(cat CHANGELOG.md | grep -Ev "^\[.*\]: https://github.com" | wc -L)
if [ $max_line_length -ge 80 ]; then
echo "ERROR: CHANGELOG has lines longer than 80 characters."
exit 1
fi
build-mails:
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: src/mail
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Install Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: "18"
- name: Restore the mail templates
uses: actions/cache@v4
uses: actions/cache@v5
id: mail-templates
with:
path: "src/backend/core/templates/mail"
@@ -65,36 +105,86 @@ jobs:
- name: Cache mail templates
if: steps.mail-templates.outputs.cache-hit != 'true'
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: "src/backend/core/templates/mail"
key: mail-templates-${{ hashFiles('src/mail/mjml') }}
lint-back:
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: src/backend
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Install Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.10"
python-version: "3.13"
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Install the project
run: uv sync --locked --all-extras
- name: Check code formatting with ruff
run: uv run ruff format . --diff
- name: Lint code with ruff
run: uv run ruff check .
- name: Lint code with pylint
run: uv run pylint meet demo core
lint-agents:
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: src/agents
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
cache: "pip"
- name: Install development dependencies
run: pip install --user .[dev]
- name: Check code formatting with ruff
run: ~/.local/bin/ruff format . --diff
- name: Lint code with ruff
run: ~/.local/bin/ruff check .
lint-summary:
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: src/summary
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
cache: "pip"
- name: Install development dependencies
run: pip install --user .[dev]
- name: Check code formatting with ruff
run: ~/.local/bin/ruff format . --diff
- name: Lint code with ruff
run: ~/.local/bin/ruff check .
- name: Lint code with pylint
run: ~/.local/bin/pylint meet demo core
test-back:
runs-on: ubuntu-latest
needs: build-mails
permissions:
contents: read
defaults:
run:
working-directory: src/backend
@@ -110,6 +200,16 @@ jobs:
- 5432:5432
# needed because the postgres container does not provide a healthcheck
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
redis:
image: redis:5
ports:
- 6379:6379
# Set health checks to wait until redis has started
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DJANGO_CONFIGURATION: Test
@@ -121,13 +221,22 @@ jobs:
DB_USER: dinum
DB_PASSWORD: pass
DB_PORT: 5432
REDIS_URL: redis://localhost:6379/1
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
LIVEKIT_API_SECRET: secret
LIVEKIT_API_KEY: devkey
AWS_S3_ENDPOINT_URL: http://localhost:9000
AWS_S3_ACCESS_KEY_ID: meet
AWS_S3_SECRET_ACCESS_KEY: password
OIDC_RS_CLIENT_ID: meet
OIDC_RS_CLIENT_SECRET: ThisIsAnExampleKeyForDevPurposeOnly
OIDC_OP_INTROSPECTION_ENDPOINT: https://oidc.example.com/introspect
OIDC_OP_URL: https://oidc.example.com
MEDIA_BASE_URL: http://localhost:8083
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Create writable /data
run: |
@@ -135,19 +244,47 @@ jobs:
sudo mkdir -p /data/static
- name: Restore the mail templates
uses: actions/cache@v4
uses: actions/cache@v5
id: mail-templates
with:
path: "src/backend/core/templates/mail"
key: mail-templates-${{ hashFiles('src/mail/mjml') }}
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Start MinIO
run: |
docker pull minio/minio
docker run -d --name minio \
-p 9000:9000 \
-e "MINIO_ACCESS_KEY=meet" \
-e "MINIO_SECRET_KEY=password" \
-v /data/media:/data \
minio/minio server --console-address :9001 /data
- name: Install development dependencies
run: pip install --user .[dev]
# Tool to wait for a service to be ready
- name: Install Dockerize
run: |
curl -sSL https://github.com/jwilder/dockerize/releases/download/v0.8.0/dockerize-linux-amd64-v0.8.0.tar.gz | sudo tar -C /usr/local/bin -xzv
- name: Wait for MinIO to be ready
run: |
dockerize -wait tcp://localhost:9000 -timeout 10s
- name: Configure MinIO
run: |
MINIO=$(docker ps | grep minio/minio | sed -E 's/.*\s+([a-zA-Z0-9_-]+)$/\1/')
docker exec ${MINIO} sh -c \
"mc alias set meet http://localhost:9000 meet password && \
mc alias ls && \
mc mb meet/meet-media-storage"
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Install the dependencies
run: uv sync --locked --all-extras
- name: Install gettext (required to compile messages)
run: |
@@ -155,16 +292,18 @@ jobs:
sudo apt-get install -y gettext
- name: Generate a MO file from strings extracted from the project
run: python manage.py compilemessages
run: uv run python manage.py compilemessages
- name: Run tests
run: ~/.local/bin/pytest -n 2
run: uv run pytest -n 2
lint-front:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Install dependencies
run: cd src/frontend/ && npm ci
@@ -175,69 +314,40 @@ jobs:
- name: Check format
run: cd src/frontend/ && npm run check
i18n-crowdin:
lint-sdk:
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: src/sdk/library
steps:
-
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: "infrastructure,secrets"
-
name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ steps.app-token.outputs.token }}
-
name: Load sops secrets
uses: rouja/actions-sops@main
with:
secret-file: secrets/numerique-gouv/meet/secrets.enc.env
age-key: ${{ secrets.SOPS_PRIVATE }}
- name: Install gettext (required to make messages)
run: |
sudo apt-get update
sudo apt-get install -y gettext
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install development dependencies
working-directory: src/backend
run: pip install --user .[dev]
- name: Generate the translation base file
run: ~/.local/bin/django-admin makemessages --keep-pot --all
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "18.x"
cache: "npm"
cache-dependency-path: src/frontend/package-lock.json
- name: Checkout repository
uses: actions/checkout@v6
- name: Install dependencies
run: cd src/frontend/ && npm ci
run: npm ci
- name: Extract the frontend translation
run: make frontend-i18n-extract
- name: Check linting
run: npm run lint
- name: Upload files to Crowdin
uses: crowdin/github-action@v2
with:
config: crowdin/config.yml
upload_sources: true
upload_translations: true
download_translations: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_BASE_PATH: ${{ github.workspace }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
- name: Check format
run: npm run check
build-sdk:
runs-on: ubuntu-latest
permissions:
contents: read
needs: lint-sdk
defaults:
run:
working-directory: src/sdk/library
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install dependencies
run: npm ci
- name: Build SDK
run: npm run build
+33
View File
@@ -0,0 +1,33 @@
name: Release Chart
run-name: Release Chart
on:
push:
paths:
- src/helm/meet/**
jobs:
release:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Cleanup
run: rm -rf ./src/helm/extra
- name: Install Helm
uses: azure/setup-helm@v4
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- name: Publish Helm charts
uses: numerique-gouv/helm-gh-pages@add-overwrite-option
with:
charts_dir: ./src/helm
linting: on
token: ${{ secrets.GITHUB_TOKEN }}
+29
View File
@@ -0,0 +1,29 @@
# /!\
# Security Note: This action is not hardened against prompt injection attacks and should only be used
# to review trusted PRs. Configure your repository with "Require approval for all external contributors"
# to ensure workflows only run after a maintainer has reviewed the PR.
name: Security Review
permissions:
pull-requests: write # Needed for leaving PR comments
contents: read
on:
pull_request:
branches:
- 'main'
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 2
- uses: anthropics/claude-code-security-review@0c6a49f1fa56a1d472575da86a94dbc1edb78eda
with:
comment-pr: true
exclude-directories: docs,gitlint,LICENSES,bin
claude-api-key: ${{ secrets.CLAUDE_API_KEY }}
+4
View File
@@ -31,6 +31,7 @@ MANIFEST
# Translations # Translations
*.pot
*.mo
# Environments
.env
@@ -79,3 +80,6 @@ db.sqlite3
# Egress output
docker/livekit/out
# LiveKit CA configuration
docker/livekit/rootCA.pem
-3
View File
@@ -1,3 +0,0 @@
[submodule "secrets"]
path = secrets
url = ../secrets
+215
View File
@@ -7,3 +7,218 @@ and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- ✨(helm) support celery with our Django backend #1124
- ✨(helm) support ingress for custom background image #1124
- ✨(backend) add authenticated user rate throttling on request-entry #1129
- ✨(backend) expose `is_active` field for Application in Django admin #1133
### Changed
- ♿️(frontend) Caption text size setting for accessibility #1062
- ♿️(frontend) sync html lang attribute with i18n for screen readers #1111
- ♿️(frontend) improve MoreLink a11y and UX on home page #1112
- ♿(frontend) improve chat toast a11y for screen readers #1109
- ♿(frontend) improve ui and aria labels for help article links #1108
- 🌐(frontend) improve German translation #1125
- 🔨(python-env) migrate meet main app to UV #1120
- ♻️(backend) align Application model field with `is_active` convention #1133
### Fixed
- 🐛(frontend) fix hand icon and queue position alignment and position #1119
- 🩹(backend) add page_size to pagination for room endpoints #1131
- 🐛(backend) refactor lobby throttling to use participant id #1129
## [1.10.0] - 2026-03-05
### Changed
- 🔒️(backend) enhance API input validation to strengthen security #1053
- 🦺(backend) strengthen API validation for recording options #1063
- ⚡️(frontend) optimize few performance caveats #1073
- 🔒️(helm) introduce a dedicated Kubernetes Ingress for webhook-livekit #1066
- ⬆️(deps) bump rollup from 4.44.2 to 4.59.0 in /src/frontend #1088
### Fixed
- 🐛(migrations) use settings in migrations #1058
- 💄(frontend) truncate pinned participant name with ellipsis on overflow #1056
- ♿(frontend) prevent focus ring clipping on invite dialog #1078
- ♿(frontend) dynamic tab title when connected to meeting #1060
- 🩹(frontend) remove incorrect reference to ProConnect on the prejoin #1080
- ✨(frontend) add Ctrl+Shift+/ to open shortcuts settings #1050
- ♿(frontend) announce selected state to screen readers #1081
- 💄(frontend) truncate long names with ellipsis in reaction overlay #1099
### Added
- ✨(backend) add file upload feature #1030
## [1.9.0] - 2026-03-02
### Added
- 👷(docker) add arm64 platform support for image builds
- ✨(summary) add localization support for transcription context text
### Changed
- ♻️(frontend) replace custom reactions toolbar with react aria popover #985
- 🔒️(frontend) uninstall curl from the frontend production image #987
- 💄(frontend) add focus ring to reaction emoji buttons
- ✨(frontend) introduce a shortcut settings tab #975
- 🚚(frontend) rename "wellknown" directory to "well-known" #1009
- 🌐(frontend) localize SR modifier labels #1010
- ⬆️(backend) update python dependencies #1011
- ♿️(frontend) fix focus ring on tab container components #1012
- ♿️(frontend) upgrade join meeting modal accessibility #1027
- ⬆️(python) bump minimal required python version to 3.13 #1033
- ♿️(frontend) improve accessibility of the IntroSlider carousel #1026
- ♿️(frontend) add skip link component for keyboard navigation #1019
- ♿️(frontend) announce mic/camera state to SR on shortcut toggle #1052
### Fixed
- 🩹(frontend) fix German language preference update #1021
## [1.8.0] - 2026-02-20
### Changed
- 🔒️(agents) uninstall pip from the agents image
- 🔒️(summary) switch to Alpine base image
- 🔒️(backend) uninstall pip in the production image
### Fixed
- 🔒️(agents) upgrade OpenSSL to address CVE-2025-15467
- 📌(agents) pin protobuf to 6.33.5 to fix CVE-2026-0994
## [1.7.0] - 2026-02-19
### Added
- ✨(frontend) expose Windows app web link #976
- ✨(frontend) support additional shortcuts to broaden accessibility
### Changed
- ✨(frontend) add clickable settings general link in idle modal #974
- ♻️(backend) refactor external API token-related items #1006
## [1.6.0] - 2026-02-10
### Added
- ✨(backend) monitor throttling rate failure through sentry #964
- 🚀(paas) add PaaS deployment scripts, tested on Scalingo #957
### Changed
- ♿️(frontend) improve spinner reducedmotion fallback #931
- ♿️(frontend) fix form labels and autocomplete wiring #932
- 🥅(summary) catch file-related exceptions when handling recording #944
- 📝(frontend) update legal terms #956
- ⚡️(backend) enhance django admin's loading performance #954
- 🌐(frontend) add missing DE translation for accessibility settings
### Fixed
- 🔐(backend) enforce object-level permission checks on room endpoint #959
- 🔒️(backend) add application validation when consuming external JWT #963
## [1.5.0] - 2026-01-28
### Changed
- ♿️(frontend) adjust visual-only tooltip a11y labels #910
- ♿️(frontend) sr pin/unpin announcements with dedicated messages #898
- ♿(frontend) adjust sr announcements for idle disconnect timer #908
- ♿️(frontend) add global screen reader announcer#922
### Fixed
- 🔒️(frontend) fix an XSS vulnerability on the recording page #911
## [1.4.0] - 2026-01-25
### Added
- ✨(frontend) add configurable redirect for unauthenticated users #904
### Changed
- ♿️(frontend) add accessible back button in side panel #881
- ♿️(frontend) improve participants toggle a11y label #880
- ♿️(frontend) make carousel image decorative #871
- ♿️(frontend) reactions are now vocalized and configurable #849
- ♿️(frontend) improve background effect announcements #879
### Fixed
- 🔒(backend) prevent automatic upgrade setuptools
- ♿(frontend) improve contrast for selected options #863
- ♿️(frontend) announce copy state in invite dialog #877
- 📝(frontend) align close dialog label in rooms locale #878
- 🩹(backend) use case-insensitive email matching in the external api #887
- 🐛(frontend) ensure transcript segments are sorted by their timestamp #899
- 🐛(frontend) scope scrollbar gutter override to video rooms #882
## [1.3.0] - 2026-01-13
### Added
- ✨(summary) add dutch and german languages
- 🔧(agents) make Silero VAD optional
- 🚸(frontend) explain to a user they were ejected
### Changed
- 📈(frontend) track new recording's modes
- ♿️(frontend) improve accessibility of the background and effects menu
- ♿️(frontend) improve SR and focus for transcript and recording #810
- 💄(frontend) adjust spacing in the recording side panels
- 🚸(frontend) remove the default comma delimiter in humanized durations
### Fixed
- 🐛(frontend) remove unexpected F2 tooltip when clicking video screen
- 🩹(frontend) icon font loading to avoid text/icon flickering
## [1.2.0] - 2026-01-05
### Added
- ✨(agent) support Kyutai client for subtitle
- ✨(all) support starting transcription and recording simultaneously
- ✨(backend) persist options on a recording
- ✨(all) support choosing the transcription language
- ✨(summary) add a download link to the audio/video file
- ✨(frontend) allow unprivileged users to request a recording
### Changed
- 🚸(frontend) remove the beta badge
- ♻️(summary) extract file handling in a robust service
- ♻️(all) manage recording state on the backend side
## [1.1.0] - 2025-12-22
### Added
- ✨(backend) enable user creation via email for external integrations
- ✨(summary) add Langfuse observability for LLM API calls
## [1.0.1] - 2025-12-17
### Changed
- ♿(frontend) improve accessibility:
- ♿️(frontend) hover controls, focus, SR #803
- ♿️(frontend) change ptt keybinding from space to v #813
- ♿(frontend) indicate external link opens in new window on feedback #816
- ♿(frontend) fix heading level in modal to maintain semantic hierarchy #815
- ♿️(frontend) Improve focus management when opening and closing chat #807
+76
View File
@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
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
https://www.contributor-covenant.org/faq
+77
View File
@@ -0,0 +1,77 @@
# Contributing to the Project
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!
Thank you for your contributions! 👍
+55 -34
View File
@@ -1,73 +1,89 @@
# Django Meet
# ---- base image to inherit from ----
FROM python:3.12.6-alpine3.20 as base
FROM python:3.13.5-alpine3.21 AS base
# Upgrade pip to its latest release to speed up dependencies installation
RUN python -m pip install --upgrade pip setuptools
RUN python -m pip install --upgrade pip
# Upgrade system packages to install security updates
RUN apk update && \
apk upgrade
# ---- Back-end builder image ----
FROM base as back-builder
FROM base AS back-builder
WORKDIR /builder
# Copy required python dependencies
COPY ./src/backend /builder
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
RUN mkdir /install && \
pip install --prefix=/install .
# Disable Python downloads, because we want to use the system interpreter
# across both images. If using a managed Python version, it needs to be
# copied from the build image into the final image;
ENV UV_PYTHON_DOWNLOADS=0
# install uv
COPY --from=ghcr.io/astral-sh/uv:0.10.9 /uv /uvx /bin/
WORKDIR /app
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=src/backend/uv.lock,target=uv.lock \
--mount=type=bind,source=src/backend/pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project --no-dev
COPY src/backend /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-dev
# ---- mails ----
FROM node:20 as mail-builder
FROM node:20 AS mail-builder
COPY ./src/mail /mail/app
WORKDIR /mail/app
RUN yarn install --frozen-lockfile && \
yarn build
yarn build
# ---- static link collector ----
FROM base as link-collector
FROM base AS link-collector
ARG MEET_STATIC_ROOT=/data/static
RUN apk add \
pango \
libmagic \
rdfind
# Copy installed python dependencies
COPY --from=back-builder /install /usr/local
# Copy Meet application (see .dockerignore)
COPY ./src/backend /app/
WORKDIR /app
# Copy the application from the builder
COPY --from=back-builder /app /app
ENV PATH="/app/.venv/bin:$PATH"
# collectstatic
RUN DJANGO_CONFIGURATION=Build DJANGO_JWT_PRIVATE_SIGNING_KEY=Dummy \
python manage.py collectstatic --noinput
python manage.py collectstatic --noinput
# Replace duplicated file by a symlink to decrease the overall size of the
# final image
RUN rdfind -makesymlinks true -followsymlinks true -makeresultsfile false ${MEET_STATIC_ROOT}
# ---- Core application image ----
FROM base as core
FROM base AS core
ENV PYTHONUNBUFFERED=1
RUN apk add \
gettext \
RUN apk --no-cache add \
cairo \
libffi-dev \
gdk-pixbuf \
gettext \
libffi-dev \
pango \
libmagic \
shared-mime-info
@@ -79,21 +95,24 @@ COPY ./docker/files/usr/local/bin/entrypoint /usr/local/bin/entrypoint
# docker user (see entrypoint).
RUN chmod g=u /etc/passwd
# Copy installed python dependencies
COPY --from=back-builder /install /usr/local
# Copy Meet application (see .dockerignore)
COPY ./src/backend /app/
# Copy the application from the builder
COPY --from=back-builder /app /app
WORKDIR /app
ENV PATH="/app/.venv/bin:$PATH"
# Generate compiled translation messages
RUN DJANGO_CONFIGURATION=Build \
python manage.py compilemessages --ignore=".venv/**/*"
# We wrap commands run in this container by the following entrypoint that
# creates a user on-the-fly with the container user ID (see USER) and root group
# ID.
ENTRYPOINT [ "/usr/local/bin/entrypoint" ]
# ---- Development image ----
FROM core as backend-development
FROM core AS backend-development
# Switch back to the root user to install development dependencies
USER root:root
@@ -101,10 +120,9 @@ USER root:root
# Install psql
RUN apk add postgresql-client
# Uninstall Meet and re-install it in editable mode along with development
# dependencies
RUN pip uninstall -y meet
RUN pip install -e .[dev]
# Install development dependencies
RUN --mount=from=ghcr.io/astral-sh/uv:0.10.9,source=/uv,target=/bin/uv \
uv sync --all-extras --locked
# Restore the un-privileged user running the application
ARG DOCKER_USER
@@ -113,13 +131,13 @@ USER ${DOCKER_USER}
# Target database host (e.g. database engine following docker compose services
# name) & port
ENV DB_HOST=postgresql \
DB_PORT=5432
DB_PORT=5432
# Run django development server
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
# ---- Production image ----
FROM core as backend-production
FROM core AS backend-production
ARG MEET_STATIC_ROOT=/data/static
@@ -127,6 +145,9 @@ ARG MEET_STATIC_ROOT=/data/static
RUN mkdir -p /usr/local/etc/gunicorn
COPY docker/files/usr/local/etc/gunicorn/meet.py /usr/local/etc/gunicorn/meet.py
# Remove pip to reduce attack surface in production
RUN pip uninstall -y pip
# Un-privileged user running the application
ARG DOCKER_USER
USER ${DOCKER_USER}
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Direction Interministérielle du Numérique - Gouvernement Français
Copyright (c) 2024-2025 DINUM/Etalab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+79
View File
@@ -0,0 +1,79 @@
# LICENCE OUVERTE 2.0/OPEN LICENCE 2.0
## 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 ladapter, la modifier, lextraire et la transformer, notamment pour créer des « Informations dérivées » ;
- de la diffuser, la redistribuer, la publier et la transmettre, de lexploiter à titre commercial, par exemple en la combinant avec dautres informations, ou en lincluant 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 ladresse (URL) renvoyant vers « lInformation » et assurant une mention effective de sa paternité.
**Par exemple :**
Dans le cas dune réutilisation de la base SIRENE de lINSEE, mentionner lURL du « Concédant » : www.insee.fr + la date de dernière mise à jour de lInformation 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 lobjet dune « 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 nest pas prévue par la présente licence. Labsence de défauts ou derreurs éventuellement contenues dans l «Information», comme la fourniture continue de l « Information » nest 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 quavec 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 lOpen 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 larticle 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** » : lutilisation de l’« Information » à dautres 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 dune combinaison de l « Information » et dautres 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 dauteur, droits voisins au droit dauteur, 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 dun cadre juridique global visant à une diffusion spontanée par les administrations de leurs informations publiques afin den 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 ladministration (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 ladministration en vertu du décret pris en application de larticle L.323-2 du CRPA.
Etalab est la mission chargée, sous lautorité du Premier ministre, douvrir 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 larticle 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 sils le souhaitent.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024-2025 DINUM/Etalab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+69 -10
View File
@@ -23,9 +23,10 @@
# ==============================================================================
# VARIABLES
BOLD := \033[1m
RESET := \033[0m
GREEN := \033[1;32m
ESC := $(shell printf '\033')
BOLD := $(ESC)[1m
RESET := $(ESC)[0m
GREEN := $(ESC)[1;32m
# -- Database
@@ -71,7 +72,8 @@ create-env-files: \
env.d/development/common \
env.d/development/crowdin \
env.d/development/postgresql \
env.d/development/kc_postgresql
env.d/development/kc_postgresql \
env.d/development/summary
.PHONY: create-env-files
bootstrap: ## Prepare Docker images for the project
@@ -84,14 +86,25 @@ bootstrap: \
demo \
back-i18n-compile \
mails-install \
mails-build
mails-build \
run
.PHONY: bootstrap
# -- Docker/compose
build: ## build the app-dev container
@$(COMPOSE) build app-dev --no-cache
build: ## build the project containers
@$(MAKE) build-backend
@$(MAKE) build-frontend
.PHONY: build
build-backend: ## build the app-dev container
@$(COMPOSE) build app-dev
.PHONY: build-backend
build-frontend: ## build the frontend container
@$(COMPOSE) build frontend
.PHONY: build-frontend
down: ## stop and remove containers, networks, images, and volumes
@$(COMPOSE) down
.PHONY: down
@@ -100,10 +113,23 @@ logs: ## display app-dev logs (follow mode)
@$(COMPOSE) logs -f app-dev
.PHONY: logs
run: ## start the wsgi (production) and development server
@$(COMPOSE) up --force-recreate -d celery-dev
run-backend: ## start only the backend application and all needed services
@$(COMPOSE) up --force-recreate -d celery-dev --remove-orphans
@$(COMPOSE) up --force-recreate -d nginx
@echo "Wait for postgresql to be up..."
@$(WAIT_DB)
.PHONY: run-backend
run-summary: ## start only the summary application and all needed services
@$(COMPOSE) up --force-recreate -d celery-summary-transcribe
@$(COMPOSE) up --force-recreate -d celery-summary-summarize
.PHONY: run-summary
run:
run: ## start the wsgi (production) and development server
@$(MAKE) run-backend
@$(MAKE) run-summary
@$(COMPOSE) up --force-recreate -d frontend
.PHONY: run
status: ## an alias for "docker compose ps"
@@ -114,6 +140,25 @@ stop: ## stop the development server using Docker
@$(COMPOSE) stop
.PHONY: stop
# -- Front
frontend-development-install: ## install the frontend locally
cd $(PATH_FRONT) && npm i
.PHONY: frontend-development-install
frontend-lint: ## run the frontend linter
cd $(PATH_FRONT) && npm run lint
.PHONY: frontend-lint
frontend-format: ## run the frontend format
cd $(PATH_FRONT) && npm run format
.PHONY: frontend-format
run-frontend-development: ## run the frontend in development mode
@$(COMPOSE) stop frontend
cd $(PATH_FRONT) && npm run dev
.PHONY: run-frontend-development
# -- Backend
demo: ## flush db then create a demo for load testing purpose
@@ -178,7 +223,7 @@ superuser: ## Create an admin superuser with password "admin"
.PHONY: superuser
back-i18n-compile: ## compile the gettext files
@$(MANAGE) compilemessages --ignore="venv/**/*"
@$(MANAGE) compilemessages --ignore=".venv/**/*"
.PHONY: back-i18n-compile
back-i18n-generate: ## create the .pot files used for i18n
@@ -211,6 +256,9 @@ env.d/development/postgresql:
env.d/development/kc_postgresql:
cp -n env.d/development/kc_postgresql.dist env.d/development/kc_postgresql
env.d/development/summary:
cp -n env.d/development/summary.dist env.d/development/summary
# -- Internationalization
env.d/development/crowdin:
@@ -301,7 +349,18 @@ build-k8s-cluster: ## build the kubernetes cluster using kind
./bin/start-kind.sh
.PHONY: build-k8s-cluster
install-external-secrets: ## install the kubernetes secrets from Vaultwarden
./bin/install-external-secrets.sh
.PHONY: build-k8s-cluster
start-tilt: ## start the kubernetes cluster using kind
tilt up -f ./bin/Tiltfile
.PHONY: build-k8s-cluster
start-tilt-keycloak: ## start the kubernetes cluster using kind, without Pro Connect for authentication, use keycloak
DEV_ENV=dev-keycloak tilt up -f ./bin/Tiltfile
.PHONY: build-k8s-cluster
start-tilt-dinum: ## start the kubernetes cluster using kind, without Pro Connect for authentication, but with DINUM styles
DEV_ENV=dev-dinum tilt up -f ./bin/Tiltfile
.PHONY: build-k8s-cluster
+2
View File
@@ -0,0 +1,2 @@
web: bin/buildpack_start.sh
postdeploy: python manage.py migrate
+118 -133
View File
@@ -1,155 +1,140 @@
# Meet
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.
<p align="center">
<img alt="meet logo" src="./docs/assets/banner-meet-fr.png" maxWidth="100%">
</p>
### Adding content
<p align="center">
<a href="https://github.com/suitenumerique/meet/stargazers/">
<img src="https://img.shields.io/github/stars/suitenumerique/meet" alt="">
</a>
<a href='http://makeapullrequest.com'><img alt='PRs Welcome' src='https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=shields'/></a>
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/suitenumerique/meet"/>
<img alt="GitHub closed issues" src="https://img.shields.io/github/issues-closed/suitenumerique/meet"/>
<a href="https://github.com/suitenumerique/meet/blob/main/LICENSE">
<img alt="GitHub closed issues" src="https://img.shields.io/github/license/suitenumerique/meet"/>
</a>
</p>
You can create a basic demo site by running:
<p align="center">
<a href="https://livekit.io/">LiveKit</a> - <a href="https://matrix.to/#/#meet-official:matrix.org">Chat with us</a> - <a href="https://github.com/orgs/suitenumerique/projects/3/views/2">Roadmap</a> - <a href="https://github.com/suitenumerique/meet/blob/main/CHANGELOG.md">Changelog</a> - <a href="https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md">Bug reports</a>
</p>
```bash
$ make demo
```
<p align="center">
<a href="https://visio.numerique.gouv.fr/">
<img src="https://github.com/user-attachments/assets/09c1faa1-de88-4848-af3a-6fbe793999bf" alt="La Suite Meet Demonstration">
</a>
</p>
Finally, you can check all available Make rules using:
## La Suite Meet: Simple Video Conferencing
```bash
$ make help
```
### Django admin
You can access the Django admin site at
[http://localhost:8071/admin](http://localhost:8071/admin).
You first need to create a superuser account:
```bash
$ make superuser
```
### Run application on local Kubernetes
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
Were 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
```
### 🚀 Major roll out to all French public servants
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.
On the 25th of January 2026, David Amiel, Frances Minister for Civil Service and State Reform, announced the full deployment of Visio—the French governments dedicated Meet platform—to all public servants. ([Source in French](https://www.latribune.fr/article/la-tribune-dimanche/politique/73157688099661/david-amiel-ministre-delegue-de-la-fonction-publique-nous-allons-sortir-de-la-dependance-aux-outils-americains))
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/`.
## Table of Contents
#### Debugging frontend
- [Get started](#get-started)
- [Docs](#docs)
- [Self-host](#self-host)
- [Contributing](#contributing)
- [Philosophy](#philosophy)
- [Open source](#open-source)
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`:
```yaml
...
## Get started
## 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🙏
| Url | Org | Access |
|---------------------------------------------------------------| --- | ------- |
| [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 |
| [mosacloud.cloud](https://mosa.cloud/) | mosa.cloud | Demo instance of mosa.cloud, a dutch company providing services around La Suite apps. |
docker_build(
'localhost:5001/meet-frontend:latest',
context='..',
dockerfile='../src/frontend/Dockerfile',
only=['./src/frontend', './docker', './.dockerignore'],
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
Were 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. Were 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).
## Contributors 🧞
<a href="https://github.com/suitenumerique/meet/graphs/contributors">
<img src="https://contrib.rocks/image?repo=suitenumerique/meet" />
</a>
## Credits
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).
+23
View File
@@ -0,0 +1,23 @@
# Security Policy
## Reporting a Vulnerability
Security is very important to us.
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.
+79 -2
View File
@@ -2,6 +2,18 @@ load('ext://uibutton', 'cmd_button', 'bool_input', 'location')
load('ext://namespace', 'namespace_create', 'namespace_inject')
namespace_create('meet')
DEV_ENV = os.getenv('DEV_ENV', 'dev')
if DEV_ENV == 'dev-dinum':
update_settings(suppress_unused_image_warnings=["localhost:5001/meet-frontend-generic:latest"])
if DEV_ENV == 'dev-keycloak':
update_settings(suppress_unused_image_warnings=["localhost:5001/meet-frontend-dinum:latest"])
def clean_old_images(image_name):
local('docker images -q %s | tail -n +2 | xargs -r docker rmi' % image_name)
docker_build(
'localhost:5001/meet-backend:latest',
context='..',
@@ -16,9 +28,22 @@ docker_build(
)
]
)
clean_old_images('localhost:5001/meet-backend')
docker_build(
'localhost:5001/meet-frontend:latest',
'localhost:5001/meet-frontend-dinum:latest',
context='..',
dockerfile='../docker/dinum-frontend/Dockerfile',
only=['./src/frontend', './docker', './.dockerignore'],
target = 'frontend-production',
live_update=[
sync('../src/frontend', '/home/frontend'),
]
)
clean_old_images('localhost:5001/meet-frontend-dinum')
docker_build(
'localhost:5001/meet-frontend-generic:latest',
context='..',
dockerfile='../src/frontend/Dockerfile',
only=['./src/frontend', './docker', './.dockerignore'],
@@ -27,8 +52,60 @@ docker_build(
sync('../src/frontend', '/home/frontend'),
]
)
clean_old_images('localhost:5001/meet-frontend-generic')
k8s_yaml(local('cd ../src/helm && helmfile -n meet -e dev template .'))
docker_build(
'localhost:5001/meet-summary:latest',
context='../src/summary',
dockerfile='../src/summary/Dockerfile',
only=['.'],
target = 'production',
live_update=[
sync('../src/summary', '/app'),
]
)
clean_old_images('localhost:5001/meet-summary')
docker_build(
'localhost:5001/meet-agents:latest',
context='../src/agents',
dockerfile='../src/agents/Dockerfile',
only=['.'],
target = 'production',
live_update=[
sync('../src/agents', '/app'),
]
)
clean_old_images('localhost:5001/meet-agents')
# Copy the mkcert root CA certificate to our Docker build context
# This is necessary because we need to inject the certificate into our LiveKit container
local_resource(
'copy-root-ca',
cmd='cp -f "$(mkcert -CAROOT)/rootCA.pem" ../docker/livekit/rootCA.pem',
deps=[], # No dependencies needed
)
# Build a custom LiveKit Docker image that includes our root CA certificate
# This allows LiveKit to trust our local development certificates
docker_build(
'localhost:5001/meet-livekit:latest',
context='../docker/livekit',
dockerfile='./../docker/livekit/Dockerfile',
only=['.'],
)
clean_old_images('localhost:5001/meet-livekit')
k8s_yaml(local('cd ../src/helm && helmfile -n meet -e ${DEV_ENV:-dev} template .'))
k8s_resource('minio-bucket', resource_deps=['minio'])
k8s_resource('meet-backend', resource_deps=['postgresql', 'minio', 'redis', 'livekit-livekit-server'])
k8s_resource('meet-celery-backend', resource_deps=['redis'])
k8s_resource('meet-celery-summarize', resource_deps=['redis'])
k8s_resource('meet-celery-transcribe', resource_deps=['redis'])
k8s_resource('meet-backend-migrate', resource_deps=['meet-backend'])
k8s_resource('livekit-livekit-server-test-connection', resource_deps=['livekit-livekit-server'])
k8s_resource('keycloak', resource_deps=['kc-postgresql'])
k8s_resource('meet-backend-createsuperuser', resource_deps=['meet-backend-migrate'])
migration = '''
set -eu
+1 -1
View File
@@ -5,7 +5,7 @@ set -eo pipefail
REPO_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd)"
UNSET_USER=0
COMPOSE_FILE="${REPO_DIR}/docker-compose.yml"
COMPOSE_FILE="${REPO_DIR}/compose.yml"
COMPOSE_PROJECT="meet"
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
set -o errexit # always exit on error
set -o pipefail # don't ignore exit codes when piping output
echo "-----> Running post-compile script"
# Cleanup
rm -rf docker docs env.d gitlint
+50
View File
@@ -0,0 +1,50 @@
#!/bin/bash
set -o errexit # always exit on error
set -o pipefail # don't ignore exit codes when piping output
echo "-----> Running post-frontend script"
# Move the frontend build to the nginx root and clean up
mkdir -p build/
mv src/frontend/dist build/frontend-out
ASSETS_DIR=build/frontend-out/assets
if [ -n "$CUSTOM_LOGO_URL" ]; then
# Ensure https
[[ ! "$CUSTOM_LOGO_URL" =~ ^https:// ]] && echo "[custom-logo] ERROR: URL must use HTTPS" >&2 && exit 1
# Prevent SSRF
HOSTNAME=$(echo "$CUSTOM_LOGO_URL" | sed -E 's|^https://([^/:]+).*|\1|')
[[ "$HOSTNAME" =~ ^(localhost|127\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|0\.0\.0\.0|\[::1\]) ]] && echo "[custom-logo] ERROR: SSRF blocked: $HOSTNAME" >&2 && exit 1
LOGO_FILE="${ASSETS_DIR}/logo.svg"
TMP_FILE=$(mktemp "${LOGO_FILE}.XXXXXX.tmp")
# Actual download
echo "[custom-logo] INFO: Downloading custom logo from: $CUSTOM_LOGO_URL"
curl -fsSL --tlsv1.2 -o "$TMP_FILE" "$CUSTOM_LOGO_URL"
# Validate filesize
FILESIZE=$(stat -c%s "$TMP_FILE" 2>/dev/null || stat -f%z "$TMP_FILE")
[[ "$FILESIZE" -eq 0 ]] && echo "[custom-logo] ERROR: empty file" >&2 && exit 1
[[ "$FILESIZE" -gt 5242880 ]] && echo "[custom-logo] ERROR: file too large (${FILESIZE}B > 5MB)" >&2 && exit 1
# Validate file type
IS_SVG=false
HEADER=$(head -c 100 "$TMP_FILE" | tr -d '\0' | tr '[:upper:]' '[:lower:]')
[[ "$HEADER" =~ ^.*"<svg".*$ ]] && IS_SVG=true
[[ "$HEADER" =~ ^.*"<?xml".*"<svg".*$ ]] && IS_SVG=true
[[ "$IS_SVG" == false ]] && echo "[custom-logo] ERROR: not a valid SVG file" >&2 && exit 1
mv -f "$TMP_FILE" "$LOGO_FILE"
echo "[custom-logo] INFO: Custom logo downloaded successfuly"
fi
mv src/backend/* ./
mv deploy/paas/* ./
echo "3.13" > .python-version
echo "." > requirements.txt
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
# Start the Django backend server
gunicorn -b 0.0.0.0:8000 meet.wsgi:application --log-file - &
# Start the Nginx server
bin/run &
# if the current shell is killed, also terminate all its children
trap "pkill SIGTERM -P $$" SIGTERM
# wait for a single child to finish,
wait -n
# then kill all the other tasks
pkill -P $$
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env bash
set -o errexit
CURRENT_DIR=$(pwd)
NAMESPACE=${1:-meet}
SECRET_NAME=${2:-bitwarden-cli-meet}
TEMP_SECRET_FILE=$(mktemp)
cleanup() {
rm -f "${TEMP_SECRET_FILE}"
}
trap cleanup EXIT
# Check if kubectl is available
check_prerequisites() {
if ! command -v kubectl &> /dev/null; then
echo "Error: kubectl is not installed or not in PATH"
exit 1
fi
}
# Check if secret already exists
check_secret_exists() {
kubectl -n "${NAMESPACE}" get secrets "${SECRET_NAME}" &> /dev/null
}
# Collect user input securely
get_user_input() {
echo "Please provide the following information:"
read -p "Enter your Vaultwarden email login: " LOGIN
read -s -p "Enter your Vaultwarden password: " PASSWORD
echo
read -p "Enter your Vaultwarden server url: " URL
}
# Create and apply the secret
create_secret() {
cat > "${TEMP_SECRET_FILE}" << EOF
apiVersion: v1
kind: Secret
metadata:
name: ${SECRET_NAME}
namespace: ${NAMESPACE}
type: Opaque
stringData:
BW_HOST: ${URL}
BW_PASSWORD: ${PASSWORD}
BW_USERNAME: ${LOGIN}
EOF
kubectl -n "${NAMESPACE}" apply -f "${TEMP_SECRET_FILE}"
}
# Install external-secrets using Helm
install_external_secrets() {
if ! kubectl get ns external-secrets &>/dev/null; then
echo "Installing external-secrets…"
helm repo add external-secrets https://charts.external-secrets.io
helm upgrade --install external-secrets \
external-secrets/external-secrets \
-n external-secrets \
--create-namespace \
--set installCRDs=true
else
echo "External secrets already deployed"
fi
}
main() {
check_prerequisites
if check_secret_exists; then
echo "Secret '${SECRET_NAME}' already present in namespace '${NAMESPACE}'"
exit 0
fi
echo -e ${TEMP_SECRET_FILE}
get_user_input
echo -e "\nCreating Vaultwarden secret…"
create_secret
install_external_secrets
echo "Secret installation completed successfully"
}
main "$@"
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
mkdir -p "$(dirname -- "${BASH_SOURCE[0]}")/../.git/hooks/"
PRE_COMMIT_FILE="$(dirname -- "${BASH_SOURCE[0]}")/../.git/hooks/pre-commit"
+160
View File
@@ -0,0 +1,160 @@
#!/bin/bash
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print colored output
print_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
# Function to update npm package version
update_npm_version() {
local component=$1
print_info "Updating $component version..."
cd "src/$component"
npm version "$VERSION" --no-git-tag-version
cd -
}
# Function to update Python project version in pyproject.toml
update_python_version() {
local component=$1
print_info "Updating $component version..."
cd "src/$component"
if [ ! -f "pyproject.toml" ]; then
print_error "pyproject.toml not found in src/$component!"
exit 1
fi
if grep -q '^version = "' pyproject.toml; then
sed -i.bak "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
rm pyproject.toml.bak
print_info "Updated pyproject.toml version to $VERSION"
else
print_error "Could not find version line in pyproject.toml"
exit 1
fi
cd -
}
# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
print_error "Not a git repository. Please run this script from the root of your project."
exit 1
fi
# Check if working directory is clean
if ! git diff-index --quiet HEAD --; then
print_error "Working directory is not clean. Please commit or stash your changes first."
exit 1
fi
# Ask user for release version number
echo ""
read -p "Enter release version number (e.g., 1.2.3): " VERSION
# Validate version format (basic semver check)
if ! [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
print_error "Invalid version format. Please use semantic versioning (e.g., 1.2.3)"
exit 1
fi
print_info "Release version: $VERSION"
# Check if branch already exists
BRANCH_NAME="release/$VERSION"
if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
print_error "Branch $BRANCH_NAME already exists!"
exit 1
fi
# Create and checkout new branch
print_info "Creating branch: $BRANCH_NAME"
git checkout -b "$BRANCH_NAME"
# Update frontend
update_npm_version "frontend"
# Update SDK
update_npm_version "sdk"
# Update mail
update_npm_version "mail"
# Update backend pyproject.toml
update_python_version "backend"
# Update summary pyproject.toml
update_python_version "summary"
# Update agents pyproject.toml
update_python_version "agents"
# Update CHANGELOG
print_info "Updating CHANGELOG..."
if [ ! -f "CHANGELOG.md" ]; then
print_error "CHANGELOG.md not found in project root!"
exit 1
fi
# Get current date in YYYY-MM-DD format
CURRENT_DATE=$(date +%Y-%m-%d)
# Replace [Unreleased] with [version number] - YYYY-MM-DD
if grep -q '\[Unreleased\]' CHANGELOG.md; then
sed -i.bak "s/\[Unreleased\]/[$VERSION] - $CURRENT_DATE/" CHANGELOG.md
# Add new [Unreleased] section after the header
# This adds it after the line containing "Semantic Versioning"
sed -i.bak "/Semantic Versioning/a\\
\\
## [Unreleased]
" CHANGELOG.md
rm CHANGELOG.md.bak
print_info "Updated CHANGELOG.md"
else
print_warning "Could not find [Unreleased] section in CHANGELOG.md"
fi
# Summary
echo ""
print_info "Release preparation complete!"
echo ""
echo "Summary:"
echo " - Branch created: $BRANCH_NAME"
echo " - Version updated to: $VERSION"
echo " - Files modified:"
echo " - src/frontend/package.json"
echo " - src/sdk/package.json"
echo " - src/mail/package.json"
echo " - src/backend/pyproject.toml"
echo " - src/summary/pyproject.toml"
echo " - src/agents/pyproject.toml"
echo " - CHANGELOG.md"
echo ""
print_warning "Next steps:"
echo " 1. Review the changes: git status"
echo " 2. Commit the changes: git add . && git commit -m 'Release $VERSION'"
echo " 3. Push the branch: git push origin $BRANCH_NAME"
echo ""
+2 -102
View File
@@ -1,103 +1,3 @@
#!/bin/sh
set -o errexit
#!/usr/bin/env bash
CURRENT_DIR=$(pwd)
echo "0. Create ca"
# 0. Create ca
mkcert -install
cd /tmp
mkcert "127.0.0.1.nip.io" "*.127.0.0.1.nip.io"
cd $CURRENT_DIR
echo "1. Create registry container unless it already exists"
# 1. Create registry container unless it already exists
reg_name='kind-registry'
reg_port='5001'
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
docker run \
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}" \
registry:2
fi
echo "2. Create kind cluster with containerd registry config dir enabled"
# 2. Create kind cluster with containerd registry config dir enabled
# TODO: kind will eventually enable this by default and this patch will
# be unnecessary.
#
# See:
# https://github.com/kubernetes-sigs/kind/issues/2875
# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration
# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
nodes:
- role: control-plane
image: kindest/node:v1.27.3
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker
image: kindest/node:v1.27.3
- role: worker
image: kindest/node:v1.27.3
EOF
echo "3. Add the registry config to the nodes"
# 3. Add the registry config to the nodes
#
# This is necessary because localhost resolves to loopback addresses that are
# network-namespace local.
# In other words: localhost in the container is not localhost on the host.
#
# We want a consistent name that works from both ends, so we tell containerd to
# alias localhost:${reg_port} to the registry container when pulling images
REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
for node in $(kind get nodes); do
docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
[host."http://${reg_name}:5000"]
EOF
done
echo "4. Connect the registry to the cluster network if not already connected"
# 4. Connect the registry to the cluster network if not already connected
# This allows kind to bootstrap the network but ensures they're on the same network
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
docker network connect "kind" "${reg_name}"
fi
echo "5. Document the local registry"
# 5. Document the local registry
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: local-registry-hosting
namespace: kube-public
data:
localRegistryHosting.v1: |
host: "localhost:${reg_port}"
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF
echo "6. Install ingress-nginx"
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl -n ingress-nginx create secret tls mkcert --key /tmp/127.0.0.1.nip.io+1-key.pem --cert /tmp/127.0.0.1.nip.io+1.pem
kubectl -n ingress-nginx patch deployments.apps ingress-nginx-controller --type 'json' -p '[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value":"--default-ssl-certificate=ingress-nginx/mkcert"}]'
curl https://raw.githubusercontent.com/numerique-gouv/tools/refs/heads/main/kind/create_cluster.sh | bash -s -- meet
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
git submodule update --init --recursive
git submodule foreach 'git fetch origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/bash
#!/usr/bin/env bash
find . -name "*.enc.*" -exec sops updatekeys -y {} \;
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -e
+140 -3
View File
@@ -1,4 +1,3 @@
version: '3.8'
services:
postgresql:
@@ -16,6 +15,52 @@ services:
ports:
- "1081:1080"
minio:
user: ${DOCKER_USER:-1000}
image: minio/minio
environment:
- MINIO_ROOT_USER=meet
- MINIO_ROOT_PASSWORD=password
ports:
- '9000:9000'
- '9001:9001'
healthcheck:
test: [ "CMD", "mc", "ready", "local" ]
interval: 1s
timeout: 20s
retries: 300
entrypoint: ""
command: minio server --console-address :9001 /data
volumes:
- ./data/media:/data
createbuckets:
image: minio/mc
depends_on:
minio:
condition: service_healthy
restart: true
entrypoint: >
sh -c "
/usr/bin/mc alias set meet http://minio:9000 meet password && \
/usr/bin/mc mb meet/meet-media-storage && \
exit 0;"
createwebhook:
image: minio/mc
depends_on:
minio:
condition: service_healthy
restart: true
entrypoint: >
sh -c "
/usr/bin/mc alias set meet http://minio:9000 meet password &&
/usr/bin/mc admin config set meet notify_webhook:meet-webhook endpoint='http://app-dev:8000/api/v1.0/recordings/storage-hook/' auth_token='Bearer password' &&
/usr/bin/mc admin service restart meet --wait --json &&
sleep 15 &&
/usr/bin/mc event add meet/meet-media-storage arn:minio:sqs::meet-webhook:webhook --event put &&
exit 0;"
app-dev:
build:
context: .
@@ -35,12 +80,19 @@ services:
volumes:
- ./src/backend:/app
- ./data/static:/data/static
- /app/.venv
depends_on:
- postgresql
- mailcatcher
- redis
- nginx
- livekit
- createbuckets
- createwebhook
extra_hosts:
- "127.0.0.1.nip.io:host-gateway"
networks:
- resource-server
- default
celery-dev:
user: ${DOCKER_USER:-1000}
@@ -54,6 +106,7 @@ services:
volumes:
- ./src/backend:/app
- ./data/static:/data/static
- /app/.venv
depends_on:
- app-dev
@@ -74,6 +127,7 @@ services:
- postgresql
- redis
- livekit
- minio
celery:
user: ${DOCKER_USER:-1000}
@@ -95,9 +149,27 @@ services:
- ./docker/files/etc/nginx/conf.d:/etc/nginx/conf.d:ro
depends_on:
- keycloak
- app-dev
networks:
- resource-server
- default
frontend:
user: "${DOCKER_USER:-1000}"
build:
context: .
dockerfile: ./src/frontend/Dockerfile
target: frontend-production
args:
VITE_API_BASE_URL: "http://localhost:8071"
VITE_APP_TITLE: "LaSuite Meet"
image: meet:frontend-development
ports:
- "3000:8080"
dockerize:
image: jwilder/dockerize
platform: linux/x86_64
crowdin:
image: crowdin/cli:4.0.0
@@ -165,7 +237,7 @@ services:
- livekit-egress
livekit-egress:
image: livekit/egress
image: livekit/egress:v1.11.0
environment:
EGRESS_CONFIG_FILE: ./livekit-egress.yaml
volumes:
@@ -173,3 +245,68 @@ services:
- ./docker/livekit/out:/out
depends_on:
- redis
redis-summary:
image: redis
ports:
- "6379:6379"
app-summary-dev:
build:
context: src/summary
target: development
args:
DOCKER_USER: ${DOCKER_USER:-1000}
user: ${DOCKER_USER:-1000}
env_file:
- env.d/development/summary
ports:
- "8001:8000"
volumes:
- ./src/summary:/app
depends_on:
- redis-summary
celery-summary-transcribe:
container_name: celery-summary-transcribe
build:
context: ./src/summary
dockerfile: Dockerfile
target: production
command: celery -A summary.core.celery_worker worker --pool=solo --loglevel=debug -Q transcribe-queue
env_file:
- env.d/development/summary
volumes:
- ./src/summary:/app
depends_on:
- redis-summary
- app-summary-dev
- minio
develop:
watch:
- action: rebuild
path: ./src/summary
celery-summary-summarize:
container_name: celery-summary-summarize
build:
context: ./src/summary
dockerfile: Dockerfile
target: production
command: celery -A summary.core.celery_worker worker --pool=solo --loglevel=debug -Q summarize-queue
env_file:
- env.d/development/summary
volumes:
- ./src/summary:/app
depends_on:
- redis-summary
- app-summary-dev
- minio
develop:
watch:
- action: rebuild
path: ./src/summary
networks:
default:
resource-server:
+52
View File
@@ -0,0 +1,52 @@
# ERB templated nginx configuration
# see https://doc.scalingo.com/platform/deployment/buildpacks/nginx
upstream backend_server {
server localhost:8000 fail_timeout=0;
}
server {
listen <%= ENV["PORT"] %>;
server_name _;
server_tokens off;
root /app/build/frontend-out;
# Django rest framework
location ^~ /api/ {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://backend_server;
}
# Django admin
location ^~ /admin/ {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://backend_server;
}
# Serve static files with caching
location ~* ^/assets/.*\.(css|js|json|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
# Serve static files
location / {
try_files $uri $uri/ /index.html;
# Add no-cache headers
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache"; # HTTP 1.0 header for backward compatibility
add_header Expires 0;
}
# Optionally, handle 404 errors by redirecting to index.html
error_page 404 =200 /index.html;
}
+405 -405
View File
File diff suppressed because it is too large Load Diff
+67
View File
@@ -0,0 +1,67 @@
# ---- Front-end image ----
FROM node:20-alpine AS frontend-deps
WORKDIR /home/frontend/
COPY ./src/frontend/package.json ./package.json
COPY ./src/frontend/package-lock.json ./package-lock.json
RUN npm ci
COPY .dockerignore ./.dockerignore
COPY ./src/frontend/ .
# ---- Front-end builder image ----
FROM frontend-deps AS meet-builder
WORKDIR /home/frontend
ENV VITE_APP_TITLE="Visio"
ENV VITE_BUILD_SOURCEMAP="true"
RUN npm run build
# Inject PostHog sourcemap metadata into the built assets
# This metadata is essential for correctly mapping errors to source maps in production
RUN set -e && \
npx @posthog/cli@0.4.8 sourcemap inject --directory ./dist/assets
COPY ./docker/dinum-frontend/dinum-styles.css \
./dist/assets/
COPY ./docker/dinum-frontend/logo.svg \
./dist/assets/logo.svg
COPY ./docker/dinum-frontend/assets/ \
./dist/assets/
COPY ./docker/dinum-frontend/fonts/ \
./dist/assets/fonts/
# ---- Front-end image ----
FROM nginxinc/nginx-unprivileged:alpine3.21 AS frontend-production
USER root
RUN apk update && apk upgrade libssl3 \
libcrypto3 \
libxml2>=2.12.7-r2 \
libxslt>=1.1.39-r2 \
libexpat>=2.7.2-r0 \
libpng>=1.6.53-r0
USER nginx
# Un-privileged user running the application
ARG DOCKER_USER
USER ${DOCKER_USER}
COPY --from=meet-builder \
/home/frontend/dist \
/usr/share/nginx/html
COPY ./src/frontend/default.conf /etc/nginx/conf.d
COPY ./docker/files/usr/local/bin/entrypoint /usr/local/bin/entrypoint
ENTRYPOINT [ "/usr/local/bin/entrypoint" ]
CMD ["nginx", "-g", "daemon off;"]
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="38.194309mm"
height="3.4877367mm"
viewBox="0 0 38.194309 3.4877367"
version="1.1"
id="svg1"
sodipodi:docname="gouvernement.svg"
inkscape:version="1.4.1 (93de688d07, 2025-03-30)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="6.1918409"
inkscape:cx="79.620909"
inkscape:cy="44.332534"
inkscape:window-width="1901"
inkscape:window-height="1037"
inkscape:window-x="5"
inkscape:window-y="5"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" />
<defs
id="defs1">
<rect
x="111.07374"
y="333.22122"
width="541.4845"
height="297.51895"
id="rect2" />
<rect
x="158.10136"
y="358.3631"
width="425.55618"
height="204.21426"
id="rect1" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-53.656101,-100.08408)">
<path
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"
id="text3"
style="font-size:4.445px;line-height:0.661464px;font-family:Marianne;-inkscape-font-specification:'Marianne, Normal';letter-spacing:0px;word-spacing:0px;display:inline;stroke:#000000;stroke-width:0.198437"
aria-label="GOUVERNEMENT" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

+70
View File
@@ -0,0 +1,70 @@
:root {
--fonts-sans: 'Marianne', ui-sans-serif, system-ui, sans-serif;
}
.Header-beforeLogo {
display: block;
}
.Header-beforeLogo::before {
content: '';
display: block;
background-image: url(/assets/marianne.svg);
background-position: 0 -0.046875rem;
background-size: 2.0625rem 0.84375rem;
height: 0.75rem;
margin-bottom: 0.1rem;
width: 2.0625rem;
}
.Header-beforeLogo::after {
content: '';
display: block;
background-image: url(/assets/gouvernement.svg), url(/assets/devise.svg);
background-repeat: no-repeat, no-repeat;
background-size: 108.8px 10px, 40px 29px;
background-position: 0 3px, 0 18.9px;
width: 108.8px;
height: 48px;
margin-top: 0.25rem;
}
@font-face {
font-family: 'Marianne';
src: url('/assets/fonts/Marianne-Regular-subset.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Marianne';
src: url('/assets/fonts/Marianne-Regular_Italic-subset.woff2') format('woff2');
font-weight: 400;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Marianne';
src: url('/assets/fonts/Marianne-Medium-subset.woff2') format('woff2');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Marianne';
src: url('/assets/fonts/Marianne-Bold-subset.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Marianne';
src: url('/assets/fonts/Marianne-ExtraBold-subset.woff2') format('woff2');
font-weight: 800;
font-style: normal;
font-display: swap;
}
+6
View File
@@ -0,0 +1,6 @@
<svg width="448" height="172" viewBox="0 0 448 172" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.61135 65.6951C5 68.832 5 72.6949 5 79.1656V94.7307C5 102.759 5 106.773 6.16756 110.366C7.20062 113.546 8.89041 116.472 11.1274 118.957C13.6555 121.765 17.1318 123.772 24.0842 127.786L37.564 135.568C43.7169 139.121 47.1472 141.101 50.4165 142.054V94.0288C50.4165 91.6281 49.1052 89.4192 46.9976 88.2696L5.61135 65.6951Z" fill="#C9191E"/>
<path d="M118.313 72.7489V97.7898C118.313 101.252 119.818 104.544 122.436 106.809L140.459 122.406C141.513 123.298 142.608 124.028 143.744 124.596C144.92 125.123 146.056 125.387 147.151 125.387C149.503 125.387 151.389 124.616 152.809 123.075C154.269 121.493 154.999 119.445 154.999 116.93V53.6577C154.999 51.1431 154.269 49.1151 152.809 47.5738C151.389 45.992 149.503 45.2011 147.151 45.2011C146.056 45.2011 144.92 45.4647 143.744 45.992C142.608 46.5193 141.513 47.2494 140.459 48.1822L122.45 63.7172C119.823 65.983 118.313 69.28 118.313 72.7489Z" fill="#000091"/>
<path d="M11.6345 56.7522C11.1333 56.4788 10.6078 56.2937 10.0757 56.1915C10.4114 55.7628 10.7622 55.3452 11.1276 54.9394C13.6558 52.1315 17.132 50.1245 24.0845 46.1105L37.5643 38.3279C44.5167 34.3139 47.993 32.3069 51.6887 31.5213C54.9587 30.8262 58.3383 30.8262 61.6083 31.5213C65.304 32.3069 68.7803 34.3139 75.7327 38.3279L89.0535 46.0187C89.1066 46.0492 89.1597 46.0798 89.2129 46.1105C96.1653 50.1245 99.6416 52.1316 102.17 54.9394C104.407 57.4238 106.096 60.3506 107.13 63.5301C108.297 67.1235 108.297 71.1375 108.297 79.1656V94.7307C108.297 102.759 108.297 106.773 107.13 110.366C106.096 113.546 104.407 116.473 102.17 118.957C99.6416 121.765 96.1655 123.772 89.2133 127.785C89.1537 127.82 89.0936 127.855 89.0341 127.889L75.7327 135.568C68.7803 139.582 65.304 141.589 61.6083 142.375C61.4564 142.407 61.3043 142.438 61.1519 142.467L61.1519 94.0288C61.1519 87.6997 57.6948 81.8761 52.1386 78.8455L11.6345 56.7522Z" fill="#000091"/>
<path d="M193.72 45.7333H211.035L234.771 108.456L258.507 45.7333H275.821L245.435 126H224.107L193.72 45.7333ZM289.019 58.1173C283.859 58.1173 279.501 53.76 279.501 48.6C279.501 43.44 283.859 39.0827 289.019 39.0827C294.179 39.0827 298.421 43.44 298.421 48.6C298.421 53.76 294.179 58.1173 289.019 58.1173ZM281.68 126V68.208H296.243V126H281.68ZM303.29 117.629L312.922 108.915C316.477 113.387 320.72 116.597 326.224 116.597C330.925 116.597 333.333 113.845 333.333 110.405C333.333 100.315 305.698 104.099 305.698 83.8027C305.698 73.5973 314.298 65.9147 326.338 65.9147C335.168 65.9147 343.194 70.1573 347.322 75.776L337.69 84.2613C334.709 80.592 330.925 77.6107 326.453 77.6107C321.866 77.6107 319.688 80.1333 319.688 83.1147C319.688 92.976 347.322 89.536 347.322 109.488C347.093 121.643 337.346 128.293 326.453 128.293C316.133 128.293 308.794 124.165 303.29 117.629ZM363.494 58.1173C358.334 58.1173 353.977 53.76 353.977 48.6C353.977 43.44 358.334 39.0827 363.494 39.0827C368.654 39.0827 372.897 43.44 372.897 48.6C372.897 53.76 368.654 58.1173 363.494 58.1173ZM356.155 126V68.208H370.718V126H356.155ZM411.115 65.9147C429.92 65.9147 442.763 79.7893 442.763 97.104C442.763 114.419 429.92 128.293 411.115 128.293C392.309 128.293 379.467 114.419 379.467 97.104C379.467 79.7893 392.309 65.9147 411.115 65.9147ZM411.344 114.533C420.632 114.533 427.627 107.08 427.627 97.104C427.627 87.0133 420.632 79.6747 411.344 79.6747C401.712 79.6747 394.603 87.0133 394.603 97.104C394.603 107.195 401.712 114.533 411.344 114.533Z" fill="#000091"/>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -4,10 +4,47 @@ server {
server_name localhost;
charset utf-8;
# Proxy auth for media
location /media/ {
# Auth request configuration
auth_request /media-auth;
auth_request_set $authHeader $upstream_http_authorization;
auth_request_set $authDate $upstream_http_x_amz_date;
auth_request_set $authContentSha256 $upstream_http_x_amz_content_sha256;
# Pass specific headers from the auth response
proxy_set_header Authorization $authHeader;
proxy_set_header X-Amz-Date $authDate;
proxy_set_header X-Amz-Content-SHA256 $authContentSha256;
# Get resource from Minio
proxy_pass http://minio:9000/meet-media-storage/;
proxy_set_header Host minio:9000;
# To use with ds_proxy
# proxy_pass http://ds-proxy:4444/upstream/meet-media-storage/;
# proxy_set_header Host ds-proxy:4444;
add_header Content-Disposition "attachment";
}
location /media-auth {
proxy_pass http://app-dev:8000/api/v1.0/files/media-auth/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Original-URL $request_uri;
# Prevent the body from being passed
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-Method $request_method;
}
location / {
proxy_pass http://keycloak:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
}
}
@@ -0,0 +1,50 @@
upstream meet_backend {
server ${BACKEND_INTERNAL_HOST}:8000 fail_timeout=0;
}
upstream meet_frontend {
server ${FRONTEND_INTERNAL_HOST}:8080 fail_timeout=0;
}
server {
listen 8083;
server_name localhost;
charset utf-8;
# Disables server version feedback on pages and in headers
server_tokens off;
proxy_ssl_server_name on;
location @proxy_to_meet_backend {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://meet_backend;
}
location @proxy_to_meet_frontend {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://meet_frontend;
}
location / {
try_files $uri @proxy_to_meet_frontend;
}
location /api {
try_files $uri @proxy_to_meet_backend;
}
location /admin {
try_files $uri @proxy_to_meet_backend;
}
location /static {
try_files $uri @proxy_to_meet_backend;
}
}
+6
View File
@@ -0,0 +1,6 @@
FROM livekit/livekit-server:v1.9.4
# We inject the nip.io certificate manually because the livekit chart doesn't support volume mounting
COPY rootCA.pem /etc/ssl/certs/
ENTRYPOINT ["/livekit-server"]
@@ -3,3 +3,8 @@ redis:
address: redis:6379
keys:
devkey: secret
webhook:
api_key: devkey
urls:
- http://app-dev:8000/api/v1.0/rooms/webhooks-livekit/
+23
View File
@@ -0,0 +1,23 @@
version: '3'
# You can add any necessary service here that will join the same docker network
# sharing keycloak. Services added to the 'meet_resource-server' network will be
# able to communicate with keycloak and the backend on that network.
services:
# busybox service is only used for testing purposes. It provides curl to test
# connectivity to the backend and keycloak services. Replace this with your
# relevant application services that need to communicate with keycloak.
busybox:
image: alpine:latest
privileged: true
command: sh -c "apk add --no-cache curl && sleep infinity"
stdin_open: true
tty: true
networks:
- default
- meet_resource-server
networks:
default: {}
meet_resource-server:
external: true
Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

+145
View File
@@ -0,0 +1,145 @@
# Getting Started
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 Tilts 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/).
-81
View File
@@ -1,81 +0,0 @@
# LiveKit Egress
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.
```bash
$ livekit-cli start-room-composite-egress --request ./docker/livekit/egress-example/room-composite-file.json
Using default project meet
EgressID: EG_XXXXXXXXXXXX Status: EGRESS_STARTING
```
You can list running Egress:
```Bash
$ livekit-cli list-egress
Using default project meet
+-----------------+---------------+----------------+--------------------------------------+--------------------------------+-------+
| EGRESSID | STATUS | TYPE | SOURCE | STARTED AT | ERROR |
+-----------------+---------------+----------------+--------------------------------------+--------------------------------+-------+
| EG_XXXXXXXXXXXX | EGRESS_ACTIVE | room_composite | your-room-name-XXXXXXXXXXX-XXXXXXXXX | 2024-07-05 18:11:37.073847924 | |
| | | | | +0200 CEST | |
+-----------------+---------------+----------------+--------------------------------------+--------------------------------+-------+
```
You can stop the Egress at any time once your recording is finished:
```Bash
$ livekit-cli stop-egress --id EG_XXXXXXXXXXXX
Using default project meet
Stopping Egress EG_XXXXXXXXXXXX
```
The Egress should be marked as completed:
```bash
$ livekit-cli list-egress
Using default project meet
+-----------------+-----------------+----------------+--------------------------------------+--------------------------------+-------+
| EGRESSID | STATUS | TYPE | SOURCE | STARTED AT | ERROR |
+-----------------+-----------------+----------------+--------------------------------------+--------------------------------+-------+
| EG_XXXXXXXXXXXX | EGRESS_COMPLETE | room_composite | your-room-name-XXXXXXXXXXX-XXXXXXXXX | 2024-07-05 18:11:37.073847924 | |
| | | | | +0200 CEST | |
+-----------------+-----------------+----------------+--------------------------------------+--------------------------------+-------+
```
Finally, you should find two new files in the `./docker/livekit/out directory`: an `.mp4` recording and its associated metadata in a `.json` file:
```bash
$ ls ./docker/livekit/out
your-room-name-YYYY-MM-DDTHHMMSS.mp4
your-room-name-YYYY-MM-DDTHHMMSS.mp4.json
```
### Resources
[Official Egress repository](https://github.com/livekit/egress)
+89
View File
@@ -0,0 +1,89 @@
services:
postgresql:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 1s
timeout: 2s
retries: 300
env_file:
- env.d/postgresql
- env.d/common
volumes:
- ./data/databases/backend:/var/lib/postgresql/data
redis:
image: redis:5
backend:
image: lasuite/meet-backend:latest
user: ${DOCKER_USER:-1000}
restart: always
env_file:
- .env
- env.d/common
- env.d/postgresql
healthcheck:
test: ["CMD", "python", "manage.py", "check"]
interval: 15s
timeout: 30s
retries: 20
start_period: 10s
depends_on:
postgresql:
condition: service_healthy
restart: true
redis:
condition: service_started
livekit:
condition: service_started
frontend:
image: lasuite/meet-frontend:latest
user: "${DOCKER_USER:-1000}"
entrypoint:
- /docker-entrypoint.sh
command: ["nginx", "-g", "daemon off;"]
env_file:
- .env
- env.d/common
# Uncomment and set your values if using our nginx proxy example
# environment:
# - VIRTUAL_HOST=${MEET_HOST} # used by nginx proxy
# - VIRTUAL_PORT=8083 # used by nginx proxy
# - LETSENCRYPT_HOST=${MEET_HOST} # used by lets encrypt to generate TLS certificate
depends_on:
backend:
condition: service_healthy
volumes:
- ./default.conf.template:/etc/nginx/templates/docs.conf.template
# Uncomment if using our nginx proxy example
# networks:
# - proxy-tier
# - default
livekit:
image: livekit/livekit-server:latest
command: --config /config.yaml
ports:
- 7881:7881/tcp
- 7882:7882/udp
volumes:
- ./livekit-server.yaml:/config.yaml
# Uncomment and set your values if using our nginx proxy example
# environment:
# - VIRTUAL_HOST=${LIVEKIT_HOST} # used by nginx proxy
# - VIRTUAL_PORT=7880 # used by nginx proxy
# - LETSENCRYPT_HOST=${LIVEKIT_HOST} # used by lets encrypt to generate TLS certificate
depends_on:
redis:
condition: service_started
# Uncomment if using our nginx proxy example
# networks:
# - proxy-tier
# - default
# Uncomment if using our nginx proxy example
#networks:
# proxy-tier:
# external: true
+92
View File
@@ -0,0 +1,92 @@
# Deploy and Configure Keycloak for Meet
## Installation
> [!CAUTION]
> We provide those instructions as an example, for production environments, you should follow the [official documentation](https://www.keycloak.org/documentation).
### Step 1: Prepare your working environment:
```bash
mkdir -p keycloak/env.d && cd keycloak
curl -o compose.yaml https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/docs/examples/compose/keycloak/compose.yaml
curl -o env.d/kc_postgresql https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/env.d/production.dist/kc_postgresql
curl -o env.d/keycloak https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/env.d/production.dist/keycloak
```
### Step 2:. Update `env.d/` files
The following variables need to be updated with your own values, others can be left as is:
```env
POSTGRES_PASSWORD=<generate postgres password>
KC_HOSTNAME=https://id.yourdomain.tld # Change with your own URL
KC_BOOTSTRAP_ADMIN_PASSWORD=<generate your password>
```
### Step 3: Expose keycloak instance on https
> [!NOTE]
> You can skip this section if you already have your own setup.
To access your Keycloak instance on the public network, it needs to be exposed on a domain with SSL termination. You can use our [example with nginx proxy and Let's Encrypt companion](../nginx-proxy/README.md) for automated creation/renewal of certificates using [acme.sh](http://acme.sh).
If following our example, uncomment the environment and network sections in compose file and update it with your values.
```yaml
version: '3'
services:
keycloak:
...
# Uncomment and set your values if using our nginx proxy example
# environment:
# - VIRTUAL_HOST=id.yourdomain.tld # used by nginx proxy
# - VIRTUAL_PORT=8080 # used by nginx proxy
# - LETSENCRYPT_HOST=id.yourdomain.tld # used by lets encrypt to generate TLS certificate
...
# Uncomment if using our nginx proxy example
# networks:
# - proxy-tier
# - default
# Uncomment if using our nginx proxy example
#networks:
# proxy-tier:
# external: true
```
### Step 4: Start the service
```bash
`docker compose up -d`
```
Your keycloak instance is now available on https://doc.yourdomain.tld
> [!CAUTION]
> Version of the images are set to latest, you should pin it to the desired version to avoid unwanted upgrades when pulling latest image. You can find available versions on [Keycloak registry](https://quay.io/repository/keycloak/keycloak?tab=tags).
```
## Creating an OIDC Client for Meet Application
### Step 1: Create a New Realm
1. Log in to the Keycloak administration console.
2. Navigate to the realm tab and click on the "Create realm" button.
3. Enter the name of the realm - `meet`.
4. Click "Create".
#### Step 2: Create a New Client
1. Navigate to the "Clients" tab.
2. Click on the "Create client" button.
3. Enter the client ID - e.g. `meet`.
4. Enable "Client authentication" option.
6. Set the "Valid redirect URIs" to the URL of your meet application suffixed with `/*` - e.g., "https://meet.example.com/*".
1. Set the "Web Origins" to the URL of your meet application - e.g. `https://meet.example.com`.
1. Click "Save".
#### Step 3: Get Client Credentials
1. Go to the "Credentials" tab.
2. Copy the client ID (`meet` in this example) and the client secret.
@@ -0,0 +1,36 @@
services:
postgresql:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 1s
timeout: 2s
retries: 300
env_file:
- env.d/kc_postgresql
volumes:
- ./data/keycloak:/var/lib/postgresql/data/pgdata
keycloak:
image: quay.io/keycloak/keycloak:latest
command: ["start"]
env_file:
- env.d/kc_postgresql
- env.d/keycloak
# Uncomment and set your values if using our nginx proxy example
# environment:
# - VIRTUAL_HOST=id.yourdomain.tld # used by nginx proxy
# - VIRTUAL_PORT=8080 # used by nginx proxy
# - LETSENCRYPT_HOST=id.yourdomain.tld # used by lets encrypt to generate TLS certificate
depends_on:
postgresql:
condition: service_healthy
restart: true
# Uncomment if using our nginx proxy example
# networks:
# - proxy-tier
# - default
#
#networks:
# proxy-tier:
# external: true
@@ -0,0 +1,39 @@
# Nginx proxy with automatic SSL certificates
> [!CAUTION]
> We provide those instructions as an example, for extended development or production environments, you should follow the [official documentation](https://github.com/nginx-proxy/acme-companion/tree/main/docs).
Nginx-proxy sets up a container running nginx and docker-gen. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.
Acme-companion is a lightweight companion container for nginx-proxy. It handles the automated creation, renewal and use of SSL certificates for proxied Docker containers through the ACME protocol.
## Installation
### Step 1: Prepare your working environment:
```bash
mkdir nginx-proxy && cd nginx-proxy
curl -o compose.yaml https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/docs/examples/compose/nginx-proxy/compose.yaml
```
### Step 2: Edit `DEFAULT_EMAIL` in the compose file.
Albeit optional, it is recommended to provide a valid default email address through the `DEFAULT_EMAIL` environment variable, so that Let's Encrypt can warn you about expiring certificates and allow you to recover your account.
### Step 3: Create docker network
Containers need share the same network for auto-discovery.
```bash
docker network create proxy-tier
```
### Step 4: Start service
```bash
docker compose up -d
```
## Usage
Once both nginx-proxy and acme-companion containers are up and running, start any container you want proxied with environment variables `VIRTUAL_HOST` and `LETSENCRYPT_HOST` both set to the domain(s) your proxied container is going to use.
@@ -0,0 +1,36 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- html:/usr/share/nginx/html
- certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- proxy-tier
acme-companion:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
environment:
- DEFAULT_EMAIL=mail@yourdomain.tld
volumes_from:
- nginx-proxy
volumes:
- certs:/etc/nginx/certs:rw
- acme:/etc/acme.sh
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- proxy-tier
networks:
proxy-tier:
external: true
volumes:
html:
certs:
acme:
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
replicaCount: 1
terminationGracePeriodSeconds: 18000
livekit:
keys:
devkey: secret
log_level: debug
rtc:
use_external_ip: false
port_range_start: 50000
port_range_end: 60000
tcp_port: 7881
redis:
address: redis-master:6379
password: pass
turn:
enabled: true
udp_port: 443
domain: livekit.127.0.0.1.nip.io
loadBalancerAnnotations: {}
loadBalancer:
type: nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
tls:
- hosts:
- livekit.127.0.0.1.nip.io
secretName: livekit-dinum-cert
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 5
targetCPUUtilizationPercentage: 60
nodeSelector: {}
resources: {}
+117
View File
@@ -0,0 +1,117 @@
image:
repository: lasuite/meet-backend
pullPolicy: Always
tag: "latest"
backend:
replicas: 1
envVars:
DJANGO_CSRF_TRUSTED_ORIGINS: https://meet.127.0.0.1.nip.io,http://meet.127.0.0.1.nip.io
DJANGO_CONFIGURATION: Production
DJANGO_ALLOWED_HOSTS: meet.127.0.0.1.nip.io
DJANGO_SECRET_KEY: ThisCouldBeAReallyGoodOrPerhapsABadKeyToUseSometimes
DJANGO_SETTINGS_MODULE: meet.settings
DJANGO_SILENCED_SYSTEM_CHECKS: security.W004, security.W008
DJANGO_SUPERUSER_PASSWORD: admin
DJANGO_EMAIL_HOST: "mailcatcher"
DJANGO_EMAIL_PORT: 1025
DJANGO_EMAIL_USE_SSL: False
OIDC_OP_JWKS_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/certs
OIDC_OP_AUTHORIZATION_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/auth
OIDC_OP_TOKEN_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/token
OIDC_OP_USER_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/userinfo
OIDC_OP_LOGOUT_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/session/end
OIDC_RP_CLIENT_ID: meet
OIDC_RP_CLIENT_SECRET: ThisIsAnExampleKeyForDevPurposeOnly
OIDC_RP_SIGN_ALGO: RS256
OIDC_RP_SCOPES: "openid email"
OIDC_REDIRECT_ALLOWED_HOSTS: https://meet.127.0.0.1.nip.io
OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}"
LOGIN_REDIRECT_URL: https://meet.127.0.0.1.nip.io
LOGIN_REDIRECT_URL_FAILURE: https://meet.127.0.0.1.nip.io
LOGOUT_REDIRECT_URL: https://meet.127.0.0.1.nip.io
DB_HOST: postgresql
DB_NAME: meet
DB_USER: dinum
DB_PASSWORD: pass
DB_PORT: 5432
REDIS_URL: redis://default:pass@redis-master:6379/1
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
LIVEKIT_API_SECRET: secret
LIVEKIT_API_KEY: devkey
LIVEKIT_API_URL: https://livekit.127.0.0.1.nip.io/
ALLOW_UNREGISTERED_ROOMS: False
FRONTEND_SILENCE_LIVEKIT_DEBUG: False
migrate:
command:
- "/bin/sh"
- "-c"
- |
python manage.py migrate --no-input &&
python manage.py create_demo --force
restartPolicy: Never
command:
- "gunicorn"
- "-c"
- "/usr/local/etc/gunicorn/meet.py"
- "meet.wsgi:application"
- "--reload"
createsuperuser:
command:
- "/bin/sh"
- "-c"
- |
python manage.py createsuperuser --email admin@example.com --password admin
restartPolicy: Never
# Extra volume to manage our local custom CA and avoid to set ssl_verify: false
extraVolumeMounts:
- name: certs
mountPath: /app/.venv/lib/python3.13/site-packages/certifi/cacert.pem
subPath: cacert.pem
# Extra volume to manage our local custom CA and avoid to set ssl_verify: false
extraVolumes:
- name: certs
configMap:
name: certifi
items:
- key: cacert.pem
path: cacert.pem
frontend:
envVars:
VITE_PORT: 8080
VITE_HOST: 0.0.0.0
VITE_API_BASE_URL: https://meet.127.0.0.1.nip.io/
replicas: 1
image:
repository: lasuite/meet-frontend
pullPolicy: Always
tag: "latest"
ingress:
enabled: true
host: meet.127.0.0.1.nip.io
ingressAdmin:
enabled: true
host: meet.127.0.0.1.nip.io
posthog:
ingress:
enabled: false
ingressAssets:
enabled: false
summary:
replicas: 0
celery:
replicas: 0
@@ -0,0 +1,7 @@
auth:
username: dinum
password: pass
database: meet
tls:
enabled: true
autoGenerated: true
+3
View File
@@ -0,0 +1,3 @@
auth:
password: pass
architecture: standalone
+22
View File
@@ -0,0 +1,22 @@
port: 7880
redis:
address: redis:6379
keys:
meet: <your livekit secret key>
# WebRTC configuration
rtc:
# # when set, LiveKit will attempt to use a UDP mux so all UDP traffic goes through
# # listed port(s). To maximize system performance, we recommend using a range of ports
# # greater or equal to the number of vCPUs on the machine.
# # port_range_start & end must not be set for this config to take effect
udp_port: 7882
# when set, LiveKit enable WebRTC ICE over TCP when UDP isn't available
# this port *cannot* be behind load balancer or TLS, and must be exposed on the node
# WebRTC transports are encrypted and do not require additional encryption
# only 80/443 on public IP are allowed if less than 1024
tcp_port: 7881
# use_external_ip should be set to true for most cloud environments where
# the host has a public IP address, but is not exposed to the process.
# LiveKit will attempt to use STUN to discover the true IP, and advertise
# that IP with its clients
use_external_ip: true
+53
View File
@@ -0,0 +1,53 @@
# Authentication (OIDC)
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 Configuration
| Option | Description | Default |
|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------------------------ |
| **Client Settings** | | |
| OIDC_RP_CLIENT_ID | OIDC client identifier registered with your provider | `meet` |
| OIDC_RP_CLIENT_SECRET | OIDC client secret (keep confidential) | — |
| 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 users full name | `["given_name", "usual_name"]` |
| OIDC_USERINFO_SHORTNAME_FIELD | OIDC claim used for the users 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_REDIRECT_ALLOWED_HOSTS | Allowed hosts for OIDC redirects | `[]` |
| OIDC_REDIRECT_FIELD_NAME | Query parameter name used for redirect after login | `returnTo` |
| OIDC_RP_SCOPES | Scopes to request during authentication | `openid email` |
| LOGIN_REDIRECT_URL | URL to redirect after successful login | — |
| LOGIN_REDIRECT_URL_FAILURE | URL to redirect after failed login | — |
| LOGOUT_REDIRECT_URL | URL to redirect after logout | — |
| ALLOW_LOGOUT_GET_METHOD | Allow logout through HTTP GET (POST is recommended for security) | `true` |
| OIDC_AUTH_REQUEST_EXTRA_PARAMS | Extra parameters to include in OIDC authentication requests | `{}` |
| **PKCE (Proof Key for Code Exchange)** | | |
| OIDC_USE_PKCE | Enable PKCE for enhanced security (**recommended**) | `false` |
| OIDC_PKCE_CODE_CHALLENGE_METHOD | Method to generate PKCE code challenge (`S256` recommended) | `S256` |
| OIDC_PKCE_CODE_VERIFIER_SIZE | Length of the random string used as PKCE code verifier (43128 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.
* Default session duration is 12 hours (`SESSION_COOKIE_AGE = 60 * 60 * 12`).
* Ensure your session policy matches your security requirements.
+6
View File
@@ -0,0 +1,6 @@
# Calendar integrations (WIP)
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.
+143
View File
@@ -0,0 +1,143 @@
# Room Recording (Beta)
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 isnt in use for these async tasks yet. Its something wed like to add, but its 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
Frontend->>Frontend: Download recording file
```
## Configuration Options
| Option | Type | Default | Description |
| --------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **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_ENABLE_STORAGE_EVENT_AUTH** | Boolean | `True` | Enable authentication for storage event webhook requests. |
| **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:
```bash
$ livekit-cli list-egress
Using default project meet
+-----------------+---------------+----------------+--------------------------------------+--------------------------------+-------+
| EGRESSID | STATUS | TYPE | SOURCE | STARTED AT | ERROR |
+-----------------+---------------+----------------+--------------------------------------+--------------------------------+-------+
| EG_XXXXXXXXXXXX | EGRESS_ACTIVE | room_composite | your-room-name-XXXXXXXXXXX-XXXXXXXXX | 2024-07-05 18:11:37.073847924 | |
| | | | | +0200 CEST | |
+-----------------+---------------+----------------+--------------------------------------+--------------------------------+-------+
```
This allows you to verify which recordings are in progress, troubleshoot egress issues, and confirm that recordings are being processed correctly.
+24
View File
@@ -0,0 +1,24 @@
# Signaling
Signaling is essential for LiveKits 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.
## Environment Variables
| Variable | Type | Default | Purpose |
| ----------------------------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `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).
+4
View File
@@ -0,0 +1,4 @@
# Live subtitles (WIP)
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.
+4
View File
@@ -0,0 +1,4 @@
# Meeting summarization (WIP)
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.
+87
View File
@@ -0,0 +1,87 @@
# Telephony SIP (Beta)
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.
## How It Works
### Room Lifecycle
```mermaid
sequenceDiagram
participant Backend
participant LiveKit as LiveKit Service
participant SIP as LiveKit SIP
participant Dispatch as SIP Dispatch
Backend->>Backend: Create new room
Backend->>Backend: Assign unique pin code to room
LiveKit-->>Backend: Webhook room_started
Backend->>Dispatch: Create LiveKit SIP dispatch rule
LiveKit-->>Backend: Webhook room_ended
Backend->>Dispatch: Clear LiveKit SIP dispatch rule
```
### Participant calling
```mermaid
sequenceDiagram
participant Caller as Caller
participant SIPProvider as SIP Trunk Provider
participant LiveKitSIP as LiveKit SIP
participant Dispatch as SIP Dispatch
participant Room as LiveKit Room
Caller->>SIPProvider: Dial phone number
SIPProvider->>LiveKitSIP: Route call to SIP server
LiveKitSIP->>Caller: Prompt for room pin code
Caller->>LiveKitSIP: Enter pin code
LiveKitSIP->>Dispatch: Check dispatch rule for pin and trunk ID
Dispatch-->>LiveKitSIP: Return room ID if found
LiveKitSIP->>Room: Connect participant to room
```
## Configuration
| Option | Type | Default | Description |
| ------------------------------ | ---------------- | ------- |-----------------------------------------------------------------------------------------------------------------|
| 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.
+92
View File
@@ -0,0 +1,92 @@
# Transcription
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
Summary->>Celery: Register task (transcribe-queue)
Celery->>MinIO: Fetch audio file
Celery->>STT: Transcribe audio (WhisperX)
STT-->>Celery: Segmented transcript
Celery->>Celery: Format transcript (text)
Celery->>Docs: POST /create-for-owner (title, content, email, sub, api token)
Docs-->>Celery: Acknowledgement
```
## Configuration Options
| Option | Type | Default | Description |
| ------------------------ | --------- |-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 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. |
| celery_broker_url | String | `"redis://redis/0"` | Celery broker URL. |
| celery_result_backend | String | `"redis://redis/0"` | Celery result backend URL. |
| celery_max_retries | Integer | `1` | Maximum number of retries for Celery tasks. |
| transcribe_queue | String | `"transcribe-queue"` | Name of the Celery queue for transcription tasks. |
| aws_storage_bucket_name | String | — | Name of the S3/MinIO bucket used for storing recordings. |
| aws_s3_endpoint_url | String | — | Endpoint URL of the S3/MinIO storage. |
| aws_s3_access_key_id | String | — | Access key for S3/MinIO. |
| aws_s3_secret_access_key | Secret | — | Secret key for S3/MinIO. |
| aws_s3_secure_access | Boolean | `True` | Use HTTPS for S3/MinIO requests. |
| whisperx_api_key | Secret | — | API key for accessing WhisperX. |
| whisperx_base_url | String | `"https://api.whisperx.com/v1"` | Base URL for the WhisperX API. |
| whisperx_asr_model | String | `"whisper-1"` | ASR model used for transcription. |
| whisperx_max_retries | Integer | `0` | Maximum number of retries for WhisperX API requests. |
| webhook_max_retries | Integer | `2` | Maximum retries for webhook requests. |
| webhook_status_forcelist | List[Int] | `[502, 503, 504]` | HTTP status codes triggering webhook retry. |
| webhook_backoff_factor | Float | `0.1` | Exponential backoff factor for webhook retries. |
| webhook_api_token | Secret | — | Token to authenticate incoming webhook requests. |
| webhook_url | String | — | URL to which webhook events are sent. |
| document_default_title | String | `"Transcription"` | Default title for generated documents. |
| document_title_template | String | `'Réunion "{room}" du {room_recording_date} à {room_recording_time}'` | Template for document title. |
| sentry_is_enabled | Boolean | `False` | Enable or disable Sentry error tracking. |
| sentry_dsn | String | `None` | DSN for Sentry integration. |
+29
View File
@@ -0,0 +1,29 @@
# Installation
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, please follow the instructions provided [here](/docs/installation/compose.md) to set up a docker compose instance.
We also provide [Docker images](https://hub.docker.com/u/lasuite?page=1&search=meet) that can be deployed using Compose.
## Scalingo
La Suite Meet can be deployed on Scalingo PaaS using the Suite Numérique buildpack. See the [Scalingo deployment guide](./scalingo.md) for detailed instructions.
## 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:
- Nix: [Packages](https://search.nixos.org/packages?channel=unstable&show=lasuite-meet&query=lasuite-meet), ⚠️ unstable
- Yunohost: [Packages](https://github.com/YunoHost-Apps/meet_ynh), ⚠️ under construction (for small instances only)
> [!TIP]
> Feel free to make a PR to add ones that are not listed above
## Cloud providers
Currently, no cloud providers are listed for deploying La Suite Meet.
> [!TIP]
> Feel free to make a PR to add ones that are not listed above
+236
View File
@@ -0,0 +1,236 @@
# Installation with docker compose
We provide a sample configuration for running Meet using Docker Compose. Please note that this configuration is experimental, and the official way to deploy Meet in production is to use [k8s](../installation/kubernetes.md).
## Requirements
All services are required to run the minimalist instance of LaSuite Meet. Click the links for ready-to-use configuration examples:
| Service | Purpose | Example Config |
|-------------------|---------|----------------------------------------------------------|
| **PostgreSQL** | Main database | [compose.yaml](../examples/compose/compose.yaml) |
| **Redis** | Cache & sessions | [compose.yaml](../examples/compose/compose.yaml) |
| **Livekit** | Real-time communication | [compose.yaml](../examples/compose/compose.yaml) |
| **OIDC Provider** | User authentication | [Keycloak setup](../examples/compose/keycloak/README.md) |
| **SMTP Service** | Email notifications | - |
> [!NOTE] Some advanced features, as Recording and transcription, require additional services (MinIO, email). See `/features` folder for details.
## Software Requirements
Ensure you have Docker Compose(v2) installed on your host server. Follow the official guidelines for a reliable setup:
Docker Compose is included with Docker Engine:
- **Docker Engine:** We suggest adhering to the instructions provided by Docker
for [installing Docker Engine](https://docs.docker.com/engine/install/).
For older versions of Docker Engine that do not include Docker Compose:
- **Docker Compose:** Install it as per the [official documentation](https://docs.docker.com/compose/install/).
> [!NOTE]
> `docker-compose` may not be supported. You are advised to use `docker compose` instead.
## Step 1: Prepare your working environment:
```bash
mkdir -p meet/env.d && cd meet
curl -o compose.yaml https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/docs/examples/compose/compose.yaml
curl -o .env https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/env.d/production.dist/hosts
curl -o env.d/common https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/env.d/production.dist/common
curl -o env.d/postgresql https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/env.d/production.dist/postgresql
curl -o livekit-server.yaml https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/docs/examples/livekit/server.yaml
curl -o default.conf.template https://raw.githubusercontent.com/suitenumerique/meet/refs/heads/main/docker/files/production/default.conf.template
```
## Step 2: Configuration
Meet configuration is achieved through environment variables. We provide a [detailed description of all variables](../../src/helm/meet/README.md).
In this example, we assume the following services:
- OIDC provider on https://id.yourdomain.tld
- Livekit server on https://livekit.yourdomain.tld
- Meet server on https://meet.yourdomain.tld
**Set your own values in `.env`**
### OIDC
Authentication in Meet is managed through Open ID Connect protocol. A functional Identity Provider implementing this protocol is required.
For guidance, refer to our [Keycloak deployment example](../examples/compose/keycloak/README.md).
If using Keycloak as your Identity Provider, in `env.d/common` set `OIDC_RP_CLIENT_ID` and `OIDC_RP_CLIENT_SECRET` variables with those of the OIDC client created for Meet. By default we have set `meet` as the realm name, if you have named your realm differently, update the value `REALM_NAME` in `.env`
For others OIDC providers, update the variables in `env.d/common`.
### Postgresql
Meet uses PostgreSQL as its database. Although an external PostgreSQL can be used, our example provides a deployment method.
If you are using the example provided, you need to generate a secure key for `DB_PASSWORD` and set it in `env.d/postgresql`.
If you are using an external service or not using our default values, you should update the variables in `env.d/postgresql`
### Redis
Meet uses Redis for caching and inter-service communication. While an external Redis can be used, our example provides a deployment method.
If you are using an external service, you need to set `REDIS_URL` environment variable in `env.d/common`.
### Livekit
[LiveKit](https://github.com/livekit/livekit) server is used as the WebRTC SFU (Selective Forwarding Unit) allowing multi-user conferencing. For more information, head to [livekit documentation](https://docs.livekit.io/home/self-hosting/).
Generate a secure key for `LIVEKIT_API_SECRET` in `env.d/common`.
We provide a minimal recommended config for production environment in `livekit-server.yaml`. Set the previously generated API secret key in the config file.
To view other customization options, see [config-sample.yaml](https://github.com/livekit/livekit/blob/master/config-sample.yaml)
> [!NOTE]
> In this example, we configured multiplexing on a single UDP port. For better performance, you can configure a range of UDP ports.
### Meet
The Meet backend is built on the Django Framework.
Generate a [secure key](https://docs.djangoproject.com/en/5.2/ref/settings/#secret-key.) for `DJANGO_SECRET_KEY` in `env.d/common`.
### Mail
The following environment variables are required in `env.d/common` for the mail service to send invitations :
```env
DJANGO_EMAIL_HOST=<smtp host>
DJANGO_EMAIL_HOST_USER=<smtp user>
DJANGO_EMAIL_HOST_PASSWORD=<smtp password>
DJANGO_EMAIL_PORT=<smtp port>
DJANGO_EMAIL_FROM=<your email address>
#DJANGO_EMAIL_USE_TLS=true # A flag to enable or disable TLS for email sending.
#DJANGO_EMAIL_USE_SSL=true # A flag to enable or disable SSL for email sending.
DJANGO_EMAIL_BRAND_NAME=<brand name used in email templates> # e.g. "La Suite Numérique"
DJANGO_EMAIL_LOGO_IMG=<logo image to use in email templates.> # e.g. "https://meet.yourdomain.tld/assets/logo-suite-numerique.png"
```
## Step 3: Configure your firewall
If you are using a firewall as it is usually recommended in a production environment you will need to allow the webservice traffic on ports 80 and 443 but also to allow UDP traffic for the WebRTC service.
The following ports will need to be opened:
- 80/tcp - for TLS issuance
- 443/tcp - for listening on HTTPS and TURN/TLS packets
- 7881/tcp - WebRTC ICE over TCP
- 7882/udp - for WebRTC multiplexing over UDP
If you are using ufw, enter the following:
```
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 443/udp
ufw allow 7881/tcp
ufw allow 7882/udp
ufw enable
```
## Step 4: Reverse proxy and SSL/TLS
> [!WARNING]
> In a production environment, configure SSL/TLS termination to run your instance on https.
If you have your own certificates and proxy setup, you can skip this part.
You can follow our [nginx proxy example](../examples/compose/nginx-proxy/README.md) with automatic generation and renewal of certificate with Let's Encrypt.
You will need to uncomment the environment and network sections in compose file and update it with your values.
```yaml
frontend:
...
# Uncomment and set your values if using our nginx proxy example
# environment:
# - VIRTUAL_HOST=${MEET_HOST} # used by nginx proxy
# - VIRTUAL_PORT=8083 # used by nginx proxy
# - LETSENCRYPT_HOST=${MEET_HOST} # used by lets encrypt to generate TLS certificate
...
# Uncomment if using our nginx proxy example
# networks:
# - proxy-tier
# - default
...
# environment:
# - VIRTUAL_HOST=${LIVEKIT_HOST} # used by nginx proxy
# - VIRTUAL_PORT=7880 # used by nginx proxy
# - LETSENCRYPT_HOST=${LIVEKIT_HOST} # used by lets encrypt to generate TLS certificate
# Uncomment if using our nginx proxy example
# networks:
# - proxy-tier
# - default
#networks:
# proxy-tier:
# external: true
```
#### Caddy Reverse Proxy
Expose the Frontend port to the host
```yaml
frontend:
ports:
- "8086:8086"
```
## Step 5: Start Meet
You are ready to start your Meet application !
```bash
docker compose up -d
```
> [!NOTE]
> Version of the images are set to latest, you should pin it to the desired version to avoid unwanted upgrades when pulling latest image.
## Step 6: Run the database migration and create Django admin user
```bash
docker compose run --rm backend python manage.py migrate
docker compose run --rm backend python manage.py createsuperuser --email <admin email> --password <admin password>
```
Replace `<admin email>` with the email of your admin user and generate a secure password.
Your Meet instance is now available on the domain you defined, https://meet.yourdomain.tld.
The admin interface is available on https://meet.yourdomain.tld/admin with the admin user you just created.
## How to upgrade your Meet application
Before running an upgrade you must check the [Upgrade document](../../UPGRADE.md) for specific procedures that might be needed.
You can also check the [Changelog](../../CHANGELOG.md) for brief summary of the changes.
### Step 1: Edit the images tag with the desired version
### Step 2: Pull the images
```bash
docker compose pull
```
### Step 3: Restart your containers
```bash
docker compose restart
```
### Step 4: Run the database migration
Your database schema may need to be updated, run:
```bash
docker compose run --rm backend python manage.py migrate
```
+369
View File
@@ -0,0 +1,369 @@
# Installation on a k8s cluster
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:
- Docker (https://docs.docker.com/desktop/)
- Kind (https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
- Mkcert (https://github.com/FiloSottile/mkcert#installation)
- Helm (https://helm.sh/docs/intro/quickstart/#install-helm)
- kubectl (https://kubernetes.io/docs/tasks/tools/)
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
secret/mkcert created
deployment.apps/ingress-nginx-controller patched
7. Setup namespace
namespace/meet created
Context "kind-visio" modified.
secret/mkcert created
$ kind get clusters
visio
$ kubectl -n ingress-nginx get po
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-jgnc9 0/1 Completed 0 2m44s
ingress-nginx-admission-patch-wrt47 0/1 Completed 0 2m44s
ingress-nginx-controller-57c548c4cd-9xwt6 1/1 Running 0 2m44s
```
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/helm directory and its contents to the location where you will be executing the helm command. Helm will look for "examples/helm/<name>values.yaml" from based on the path it is being executed.
```
$ kubectl config set-context --current --namespace=meet
$ helm install keycloak oci://registry-1.docker.io/bitnamicharts/keycloak -f examples/helm/keycloak.values.yaml
$ #wait until
$ kubectl get po
NAME READY STATUS RESTARTS AGE
keycloak-0 1/1 Running 0 6m48s
keycloak-postgresql-0 1/1 Running 0 6m48s
```
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 :
```
OIDC_OP_JWKS_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/certs
OIDC_OP_AUTHORIZATION_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/auth
OIDC_OP_TOKEN_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/token
OIDC_OP_USER_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/userinfo
OIDC_OP_LOGOUT_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/session/end
OIDC_RP_CLIENT_ID: meet
OIDC_RP_CLIENT_SECRET: ThisIsAnExampleKeyForDevPurposeOnly
OIDC_RP_SIGN_ALGO: RS256
OIDC_RP_SCOPES: "openid email"
```
You can find these values in **examples/helm/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 :
```
$ helm install redis oci://registry-1.docker.io/bitnamicharts/redis -f examples/helm/redis.values.yaml
$ kubectl get po
NAME READY STATUS RESTARTS AGE
keycloak-0 1/1 Running 0 26m
keycloak-postgresql-0 1/1 Running 0 26m
redis-master-0 1/1 Running 0 35s
```
When the redis is ready we can deploy livekit-server.
```
$ helm repo add livekit https://helm.livekit.io
$ helm repo update
$ helm install livekit livekit/livekit-server -f examples/helm/livekit.values.yaml
$ kubectl get po
NAME READY STATUS RESTARTS AGE
keycloak-0 1/1 Running 0 30m
keycloak-postgresql-0 1/1 Running 0 30m
livekit-livekit-server-5c5fb87f7f-ct6x5 1/1 Running 0 7s
redis-master-0 1/1 Running 0 4m30s
$ curl https://livekit.127.0.0.1.nip.io
OK
```
From here important information you will need are :
```
LIVEKIT_API_SECRET: secret
LIVEKIT_API_KEY: devkey
LIVEKIT_API_URL: https://livekit.127.0.0.1.nip.io/
REDIS_URL: redis://default:pass@redis-master:6379/1
CELERY_BROKER_URL: redis://default:pass@redis-master:6379/1
CELERY_RESULT_BACKEND: redis://default:pass@redis-master:6379/1
```
### Find postgresql connexion values
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:
```
$ helm install postgresql oci://registry-1.docker.io/bitnamicharts/postgresql -f examples/helm/postgresql.values.yaml
$ kubectl get po
NAME READY STATUS RESTARTS AGE
keycloak-0 1/1 Running 0 45m
keycloak-postgresql-0 1/1 Running 0 45m
livekit-livekit-server-5c5fb87f7f-ct6x5 1/1 Running 0 15m
postgresql-0 1/1 Running 0 50s
redis-master-0 1/1 Running 0 19
```
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.
```
$ helm repo add meet https://suitenumerique.github.io/meet/
$ helm repo update
$ helm install meet meet/meet -f examples/helm/meet.values.yaml
```
## Test your deployment
In order to test your deployment you have to log in to your instance. If you use exclusively our examples you can do:
```
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
keycloak <none> keycloak.127.0.0.1.nip.io localhost 80 58m
livekit-livekit-server <none> livekit.127.0.0.1.nip.io localhost 80, 443 106m
meet <none> meet.127.0.0.1.nip.io localhost 80, 443 52m
meet-admin <none> meet.127.0.0.1.nip.io localhost 80, 443 52m
```
You can use LaSuite Meet on https://meet.127.0.0.1.nip.io from the local device. The provisioning user in keycloak is meet/meet.
## All options
These are the environmental options available on meet backend.
| Option | Description | default |
|-------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| DATA_DIR | Data directory location | /data |
| DJANGO_ALLOWED_HOSTS | Hosts that are allowed | [] |
| DJANGO_SECRET_KEY | Secret key used for Django security | |
| DJANGO_SILENCED_SYSTEM_CHECKS | Silence Django system checks | [] |
| DJANGO_ALLOW_UNSECURE_USER_LISTING | Allow unsecure user listing | false |
| DB_ENGINE | Database engine used | django.db.backends.postgresql_psycopg2 |
| DB_NAME | Name of the database | meet |
| DB_USER | User used to connect to database | dinum |
| DB_PASSWORD | Password used to connect to the database | pass |
| DB_HOST | Hostname of the database | localhost |
| DB_PORT | Port to connect to database | 5432 |
| STORAGES_STATICFILES_BACKEND | Static file serving engine | whitenoise.storage.CompressedManifestStaticFilesStorage |
| AWS_S3_ENDPOINT_URL | S3 host endpoint | |
| AWS_S3_ACCESS_KEY_ID | S3 access key | |
| AWS_S3_SECRET_ACCESS_KEY | S3 secret key | |
| AWS_S3_REGION_NAME | S3 region | |
| AWS_STORAGE_BUCKET_NAME | S3 bucket name | meet-media-storage |
| DJANGO_LANGUAGE_CODE | Default language | en-us |
| REDIS_URL | Redis endpoint | redis://redis:6379/1 |
| SESSION_COOKIE_AGE | Session cookie expiration in seconds | 43200 (12 hours) |
| REQUEST_ENTRY_THROTTLE_RATES | Entry request throttle rates | 150/minute |
| CREATION_CALLBACK_THROTTLE_RATES | Creation callback throttle rates | 600/minute |
| SPECTACULAR_SETTINGS_ENABLE_DJANGO_DEPLOY_CHECK | Enable Django deploy check | false |
| 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_MANIFEST_LINK | Link to the "Learn more" button on the homepage | {} |
| FRONTEND_SILENCE_LIVEKIT_DEBUG | Silence LiveKit debug logs | false |
| FRONTEND_IS_SILENT_LOGIN_ENABLED | Enable silent login feature | true |
| FRONTEND_FEEDBACK | Frontend feedback configuration | {} |
| FRONTEND_USE_FRENCH_GOV_FOOTER | Show the French government footer in the homepage | false |
| FRONTEND_USE_PROCONNECT_BUTTON | Show a "Login with ProConnect" button in the homepage instead of a "Login" button | false |
| DJANGO_EMAIL_BACKEND | Email backend library | django.core.mail.backends.smtp.EmailBackend |
| DJANGO_EMAIL_HOST | Host of the email server | |
| DJANGO_EMAIL_HOST_USER | User to connect to the email server | |
| DJANGO_EMAIL_HOST_PASSWORD | Password to connect to the email server | |
| DJANGO_EMAIL_PORT | Port to connect to the email server | |
| DJANGO_EMAIL_USE_TLS | Enable TLS on email connection | false |
| DJANGO_EMAIL_USE_SSL | Enable SSL on email connection | false |
| DJANGO_EMAIL_FROM | Email from account | from@example.com |
| EMAIL_BRAND_NAME | Email branding name | |
| EMAIL_SUPPORT_EMAIL | Support email address | |
| EMAIL_LOGO_IMG | Email logo image | |
| EMAIL_DOMAIN | Email domain | |
| EMAIL_APP_BASE_URL | Email app base URL | |
| DJANGO_CORS_ALLOW_ALL_ORIGINS | Allow all CORS origins | false |
| DJANGO_CORS_ALLOWED_ORIGINS | Origins to allow (string list) | [] |
| DJANGO_CORS_ALLOWED_ORIGIN_REGEXES | Origins to allow (regex patterns) | [] |
| SENTRY_DSN | Sentry server DSN | |
| DJANGO_CELERY_BROKER_URL | Celery broker host | redis://redis:6379/0 |
| DJANGO_CELERY_BROKER_TRANSPORT_OPTIONS | Celery broker options | {} |
| OIDC_CREATE_USER | Create OIDC user if not exists | true |
| OIDC_VERIFY_SSL | Verify SSL for OIDC | true |
| OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION | Fallback to email for identification | false |
| OIDC_RP_SIGN_ALGO | Token verification algorithm used by OIDC | RS256 |
| OIDC_RP_CLIENT_ID | OIDC client ID | meet |
| OIDC_RP_CLIENT_SECRET | OIDC client secret | |
| OIDC_OP_JWKS_ENDPOINT | OIDC endpoint for JWKS | |
| OIDC_OP_AUTHORIZATION_ENDPOINT | OIDC endpoint for authorization | |
| OIDC_OP_TOKEN_ENDPOINT | OIDC endpoint for token | |
| OIDC_OP_USER_ENDPOINT | OIDC endpoint for user | |
| OIDC_OP_USER_ENDPOINT_FORMAT | OIDC endpoint format (AUTO, JWT, JSON) | AUTO |
| OIDC_OP_LOGOUT_ENDPOINT | OIDC endpoint for logout | |
| OIDC_AUTH_REQUEST_EXTRA_PARAMS | Extra parameters for OIDC request | {} |
| OIDC_RP_SCOPES | OIDC scopes | openid email |
| OIDC_USE_NONCE | Use nonce for OIDC | true |
| OIDC_REDIRECT_REQUIRE_HTTPS | Require HTTPS for OIDC | false |
| OIDC_REDIRECT_ALLOWED_HOSTS | Allowed redirect hosts for OIDC | [] |
| OIDC_STORE_ID_TOKEN | Store OIDC ID token | true |
| OIDC_REDIRECT_FIELD_NAME | Redirect field for OIDC | returnTo |
| OIDC_USERINFO_FULLNAME_FIELDS | Full name claim from OIDC token | ["given_name", "usual_name"] |
| OIDC_USERINFO_SHORTNAME_FIELD | Short name claim from OIDC token | given_name |
| OIDC_USERINFO_ESSENTIAL_CLAIMS | Required claims from OIDC token | [] |
| 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 |
| LIVEKIT_API_KEY | LiveKit API key | |
| LIVEKIT_API_SECRET | LiveKit API secret | |
| LIVEKIT_API_URL | LiveKit API URL | |
| LIVEKIT_VERIFY_SSL | Verify SSL for LiveKit connections | true |
| LIVEKIT_FORCE_WSS_PROTOCOL | Enables WSS protocol conversion for legacy browser compatibility (Firefox <124, Chrome <125, Edge <125) where HTTPS URLs fail in WebSocket() constructor. | false |
| LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND | Firefox-only connection warmup: pre-calls WebSocket endpoint (expecting 401) to initialize cache, resolving proxy/network connectivity issues. | false |
| RESOURCE_DEFAULT_ACCESS_LEVEL | Default resource access level for rooms | public |
| ALLOW_UNREGISTERED_ROOMS | Allow usage of unregistered rooms | true |
| RECORDING_ENABLE | Record meeting option | false |
| RECORDING_OUTPUT_FOLDER | Folder to store meetings | recordings |
| RECORDING_WORKER_CLASSES | Worker classes for recording | {"screen_recording": "core.recording.worker.services.VideoCompositeEgressService","transcript": "core.recording.worker.services.AudioCompositeEgressService"} |
| RECORDING_EVENT_PARSER_CLASS | Storage event engine for recording | core.recording.event.parsers.MinioParser |
| RECORDING_ENABLE_STORAGE_EVENT_AUTH | Enable storage event authorization | true |
| RECORDING_STORAGE_EVENT_ENABLE | Enable recording storage events | false |
| RECORDING_STORAGE_EVENT_TOKEN | Recording storage event token | |
| RECORDING_EXPIRATION_DAYS | Recording expiration in days | |
| RECORDING_MAX_DURATION | Maximum recording duration in milliseconds. Must match LiveKit Egress configuration exactly. | |
| SCREEN_RECORDING_BASE_URL | Screen recording base URL | |
| SUMMARY_SERVICE_ENDPOINT | Summary service endpoint | |
| SUMMARY_SERVICE_API_TOKEN | API token for summary service | |
| SIGNUP_NEW_USER_TO_MARKETING_EMAIL | Signup users to marketing emails | false |
| MARKETING_SERVICE_CLASS | Marketing service class | core.services.marketing.BrevoMarketingService |
| BREVO_API_KEY | Brevo API key for marketing emails | |
| BREVO_API_CONTACT_LIST_IDS | Brevo API contact list IDs | [] |
| DJANGO_BREVO_API_CONTACT_ATTRIBUTES | Brevo contact attributes | {"VISIO_USER": true} |
| BREVO_API_TIMEOUT | Brevo timeout in seconds | 1 |
| LOBBY_KEY_PREFIX | Lobby key prefix | room_lobby |
| LOBBY_WAITING_TIMEOUT | Lobby waiting timeout in seconds | 3 |
| LOBBY_DENIED_TIMEOUT | Lobby deny timeout in seconds | 5 |
| LOBBY_ACCEPTED_TIMEOUT | Lobby accept timeout in seconds | 21600 (6 hours) |
| LOBBY_NOTIFICATION_TYPE | Lobby notification types | participantWaiting |
| LOBBY_COOKIE_NAME | Lobby cookie name | lobbyParticipantId |
| ROOM_CREATION_CALLBACK_CACHE_TIMEOUT | Room creation callback cache timeout | 600 (10 minutes) |
| ROOM_TELEPHONY_ENABLED | Enable SIP telephony feature | false |
| ROOM_TELEPHONY_PIN_LENGTH | Telephony PIN length | 10 |
| ROOM_TELEPHONY_PIN_MAX_RETRIES | Telephony PIN maximum retries | 5 |
+185
View File
@@ -0,0 +1,185 @@
# Deployment on Scalingo
This guide explains how to deploy La Suite Meet on [Scalingo](https://scalingo.com/) using the [Suite Numérique buildpack](https://github.com/suitenumerique/buildpack).
## Overview
Scalingo is a Platform-as-a-Service (PaaS) that simplifies application deployment. This setup uses a custom buildpack to handle both the frontend (Vite) and backend (Django) builds, serving them through Nginx.
## Prerequisites
- A Scalingo account
- Scalingo CLI installed (optional but recommended)
- A PostgreSQL database addon
- A Redis addon (for caching and sessions)
## Step 1: Create Your App
Create a new app on Scalingo using `scalingo` cli or using the [Scalingo dashboard](https://dashboard.scalingo.com/).
## Step 2: Provision Addons
Add the required PostgreSQL and Redis services.
This will set the following environment variables automatically:
- `SCALINGO_POSTGRESQL_URL` - Database connection string
- `SCALINGO_REDIS_URL` - Redis connection string
## Step 3: Configure Environment Variables
Set the following environment variables in your Scalingo app:
### Buildpack Configuration
```bash
scalingo env-set BUILDPACK_URL="https://github.com/suitenumerique/buildpack#main"
scalingo env-set LASUITE_APP_NAME="meet"
scalingo env-set LASUITE_BACKEND_DIR="."
scalingo env-set LASUITE_FRONTEND_DIR="src/frontend/"
scalingo env-set LASUITE_NGINX_DIR="."
scalingo env-set LASUITE_SCRIPT_POSTCOMPILE="bin/buildpack_postcompile.sh"
scalingo env-set LASUITE_SCRIPT_POSTFRONTEND="bin/buildpack_postfrontend.sh"
```
### Database and Cache
```bash
scalingo env-set DATABASE_URL="\$SCALINGO_POSTGRESQL_URL"
scalingo env-set REDIS_URL="\$SCALINGO_REDIS_URL"
```
### Django Settings
```bash
scalingo env-set DJANGO_SETTINGS_MODULE="meet.settings"
scalingo env-set DJANGO_CONFIGURATION="Production"
scalingo env-set DJANGO_SECRET_KEY="<generate-a-secure-secret-key>"
scalingo env-set DJANGO_ALLOWED_HOSTS="my-meet-app.osc-fr1.scalingo.io"
```
### OIDC Authentication
Configure your OIDC provider (e.g., Keycloak, Authentik):
```bash
scalingo env-set OIDC_OP_BASE_URL="https://auth.yourdomain.com/realms/meet"
scalingo env-set OIDC_RP_CLIENT_ID="meet-client-id"
scalingo env-set OIDC_RP_CLIENT_SECRET="<your-client-secret>"
scalingo env-set OIDC_RP_SIGN_ALGO="RS256"
```
### LiveKit Configuration
Meet requires a LiveKit server for video conferencing:
```bash
scalingo env-set LIVEKIT_API_URL="wss://livekit.yourdomain.com"
scalingo env-set LIVEKIT_API_KEY="<your-livekit-api-key>"
scalingo env-set LIVEKIT_API_SECRET="<your-livekit-api-secret>"
```
### Email Configuration (Optional)
For email notifications see https://doc.scalingo.com/platform/app/sending-emails:
```bash
scalingo env-set DJANGO_EMAIL_HOST="smtp.example.org"
scalingo env-set DJANGO_EMAIL_PORT="587"
scalingo env-set DJANGO_EMAIL_HOST_USER="<smtp-user>"
scalingo env-set DJANGO_EMAIL_HOST_PASSWORD="<smtp-password>"
scalingo env-set DJANGO_EMAIL_USE_TLS="True"
scalingo env-set DJANGO_EMAIL_FROM="meet@yourdomain.com"
```
## Step 4: Deploy
Deploy your application:
```bash
git push scalingo main
```
The Procfile will automatically:
1. Build the frontend (Vite)
2. Build the backend (Django)
3. Run the post-compile script (cleanup)
4. Run the post-frontend script (move assets and prepare for deployment)
5. Start Nginx and Gunicorn
6. Run django migrations
## Step 5: Create superuser
After the first deployment, create an admin user:
```bash
scalingo run python manage.py createsuperuser
```
## Custom Domain (Optional)
To use a custom domain:
1. Add the domain in Scalingo dashboard
2. Update `DJANGO_ALLOWED_HOSTS` with your custom domain
3. Configure your DNS to point to Scalingo
```bash
scalingo domains-add meet.yourdomain.com
scalingo env-set DJANGO_ALLOWED_HOSTS="meet.yourdomain.com,my-meet-app.osc-fr1.scalingo.io"
```
## Custom Logo (Optional)
To use a custom logo, set the `CUSTOM_LOGO_URL` environment variable with an HTTPS URL pointing to an SVG item (max 5MB):
```bash
scalingo env-set CUSTOM_LOGO_URL="https://cdn.yourdomain.com/logo.svg"
```
## Troubleshooting
### Check Logs
```bash
scalingo logs --tail
```
### Common Issues
1. **Build fails**: Check that all required environment variables are set
2. **Database connection error**: Verify `DATABASE_URL` is correctly set to `$SCALINGO_POSTGRESQL_URL`
3. **Static files not served**: Ensure the buildpack post-frontend script ran successfully
4. **OIDC errors**: Verify your OIDC provider configuration and callback URLs
### Useful Commands
```bash
# Open a console
scalingo run bash
# Restart the app
scalingo restart
# Scale containers
scalingo scale web:2
# One-off command
scalingo run python manage.py shell
```
## Architecture
On Scalingo, the application runs as follows:
1. **Build Phase**: The buildpack compiles both frontend and backend
2. **Runtime**:
- Nginx serves static files and proxies to the backend
- Gunicorn runs the Django WSGI application
- Both processes are managed by the `bin/buildpack_start.sh` script
## Additional Resources
- [Scalingo Documentation](https://doc.scalingo.com/)
- [Suite Numérique Buildpack](https://github.com/suitenumerique/buildpack)
- [Meet Environment Variables](../../src/helm/meet/README.md)
- [Django Configurations Documentation](https://django-configurations.readthedocs.io/)
+474
View File
@@ -0,0 +1,474 @@
openapi: 3.0.3
info:
title: Meet External API
version: 1.0.0
description: |
External API for room management with application-delegated authentication.
#### Authentication Flow
1. Exchange application credentials for a JWT token via `/external-api/v1.0/application/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
* **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.
contact:
name: API Support
email: antoine.lebaud@mail.numerique.gouv.fr
servers:
- url: https://visio-sandbox.beta.numerique.gouv.fr/external-api/v1.0
description: Sandbox server
tags:
- name: Authentication
description: Application authentication and token generation
- name: Rooms
description: Room management operations
paths:
/application/token/:
post:
tags:
- Authentication
summary: Generate JWT token
description: |
Exchange application credentials for a scoped JWT token that allows the application
to act on behalf of a specific user.
The application must be authorized for the user's email domain.
The returned token expires after a configured duration and must be refreshed by calling this endpoint again.
operationId: generateToken
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TokenRequest'
examples:
tokenRequest:
summary: Request token for user delegation
value:
client_id: "550e8400-e29b-41d4-a716-446655440000"
client_secret: "1234567890abcdefghijklmnopqrstuvwxyz"
grant_type: "client_credentials"
scope: "user@example.com"
responses:
'200':
description: Token generated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/TokenResponse'
examples:
tokenResponse:
summary: Successful token generation
value:
access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
token_type: "Bearer"
expires_in: 3600
scope: "rooms:list rooms:retrieve rooms:create"
'401':
description: Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthError'
examples:
invalidCredentials:
summary: Invalid credentials
value:
error: "Invalid credentials"
inactiveApplication:
summary: Application is inactive
value:
error: "Application is inactive"
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthError'
examples:
userNotFound:
summary: User not found
value:
error: "User not found."
'403':
description: Access denied - cannot delegate user
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthError'
examples:
delegationDenied:
summary: Domain not authorized
value:
error: "This application is not authorized for this email domain."
/rooms:
get:
tags:
- Rooms
summary: List rooms
description: |
Returns a list of rooms accessible to the authenticated user.
Only rooms where the delegated user has access will be returned.
operationId: listRooms
security:
- BearerAuth: [rooms:list]
parameters:
- name: page
in: query
description: Page number for pagination
schema:
type: integer
minimum: 1
default: 1
- name: page_size
in: query
description: Number of items per page
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: List of accessible rooms
content:
application/json:
schema:
type: object
properties:
count:
type: integer
description: Total number of rooms
next:
type: string
nullable: true
description: URL to next page
previous:
type: string
nullable: true
description: URL to previous page
results:
type: array
items:
$ref: '#/components/schemas/Room'
examples:
roomList:
summary: Paginated room list
value:
count: 2
next: "https://visio-sandbox.beta.numerique.gouv.fr/external-api/v1.0/rooms?page=2"
previous: null
results:
- id: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
slug: "aae-erez-aaz"
access_level: "trusted"
url: "https://visio-sandbox.beta.numerique.gouv.fr/aae-erez-aaz"
telephony:
enabled: true
pin_code: "123456"
phone_number: "+1-555-0100"
default_country: "US"
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
post:
tags:
- Rooms
summary: Create a room
description: |
Creates a new room with secure defaults for external API usage.
**Restrictions:**
- Rooms are always created with `trusted` access (no public rooms via API)
- Room access_level can be updated from the webapp interface.
**Defaults:**
- Delegated user is set as owner
- Room slug auto-generated for uniqueness
- Telephony PIN auto-generated when enabled
- Creation tracked with application client_id for auditing
operationId: createRoom
security:
- BearerAuth: [rooms:create]
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/RoomCreate'
examples:
emptyBody:
summary: No parameters (default)
value: {}
responses:
'201':
description: Room created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Room'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
/rooms/{id}:
get:
tags:
- Rooms
summary: Retrieve a room
description: Get detailed information about a specific room by its ID
operationId: retrieveRoom
security:
- BearerAuth: [rooms:retrieve]
parameters:
- name: id
in: path
required: true
description: Room UUID
schema:
type: string
format: uuid
responses:
'200':
description: Room details
content:
application/json:
schema:
$ref: '#/components/schemas/Room'
examples:
room:
summary: Room details
value:
id: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
slug: "aae-erez-aaz"
access_level: "trusted"
url: "https://visio-sandbox.beta.numerique.gouv.fr/aae-erez-aaz"
telephony:
enabled: true
pin_code: "123456"
phone_number: "+1-555-0100"
default_country: "US"
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/RoomNotFoundError'
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT token obtained from the `/application/token/` endpoint.
Include in requests as: `Authorization: Bearer <token>`
schemas:
TokenRequest:
type: object
required:
- client_id
- client_secret
- grant_type
- scope
properties:
client_id:
type: string
description: Application client identifier
example: "550e8400-e29b-41d4-a716-446655440000"
client_secret:
type: string
format: password
writeOnly: true
description: Application secret key
example: "1234567890abcdefghijklmnopqrstuvwxyz"
grant_type:
type: string
enum:
- client_credentials
description: OAuth2 grant type (must be 'client_credentials')
example: "client_credentials"
scope:
type: string
format: email
description: |
Email address of the user to delegate.
The application will act on behalf of this user.
Note: This parameter is named 'scope' to align with OAuth2 conventions,
but accepts an email address to identify the user. This design allows
for future extensibility.
example: "user@example.com"
TokenResponse:
type: object
properties:
access_token:
type: string
description: JWT access token
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtZWV0LWFwaSIsImF1ZCI6Im1lZXQtY2xpZW50cyIsImlhdCI6MTcwOTQ5MTIwMCwiZXhwIjoxNzA5NDk0ODAwLCJjbGllbnRfaWQiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJzY29wZSI6InJvb21zOmxpc3Qgcm9vbXM6cmV0cmlldmUgcm9vbXM6Y3JlYXRlIiwidXNlcl9pZCI6IjdiOGQ5YzQwLTNhMmItNGVkZi04NzFjLTJmM2Q0ZTVmNmE3YiIsImRlbGVnYXRlZCI6dHJ1ZX0.signature"
token_type:
type: string
description: Token type (always 'Bearer')
example: "Bearer"
expires_in:
type: integer
description: Token lifetime in seconds
example: 3600
scope:
type: string
description: Space-separated list of granted permission scopes
example: "rooms:list rooms:retrieve rooms:create"
RoomCreate:
type: object
description: Empty object - all room properties are auto-generated
properties: {}
Room:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
description: Unique room identifier
example: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
slug:
type: string
readOnly: true
description: URL-friendly room identifier (auto-generated)
example: "aze-eere-zer"
access_level:
type: string
readOnly: true
description: Room access level (always 'trusted' for API-created rooms)
example: "trusted"
url:
type: string
format: uri
readOnly: true
description: Full URL to access the room
example: "https://visio-sandbox.beta.numerique.gouv.fr/aze-eere-zer"
telephony:
type: object
readOnly: true
description: Telephony dial-in information (if enabled)
properties:
enabled:
type: boolean
description: Whether telephony is available
example: true
pin_code:
type: string
description: PIN code for dial-in access
example: "123456"
phone_number:
type: string
description: Phone number to dial
example: "+1-555-0100"
default_country:
type: string
description: Default country code
example: "US"
OAuthError:
type: object
description: OAuth2-compliant error response
properties:
error:
type: string
description: Human-readable error description
example: "Invalid credentials"
Error:
type: object
properties:
detail:
type: string
description: Error message
example: "Invalid token."
ValidationError:
type: object
properties:
field_name:
type: array
items:
type: string
description: List of validation errors for this field
example: ["This field is required."]
responses:
UnauthorizedError:
description: Authentication required or token invalid/expired
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
invalidToken:
summary: Invalid or expired token
value:
error: "Invalid token."
tokenExpired:
summary: Token has expired
value:
error: "Token expired."
ForbiddenError:
description: Insufficient permissions for this operation
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
insufficientScope:
summary: Missing required scope
value:
detail: "Insufficient permissions. Required scope: 'rooms:xxxx'"
RoomNotFoundError:
description: Room not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
roomNotFound:
summary: Room does not exist
value:
detail: "Not found."
BadRequestError:
description: Invalid request data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
examples:
validationError:
summary: Field validation failed
value:
scope: ["Invalid email address."]
-65
View File
@@ -1,65 +0,0 @@
# Releasing a new version
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.
To publish the release you just made:
```bash
git tag --force production v4.18.1
git push --force origin production
```
+393
View File
@@ -0,0 +1,393 @@
openapi: 3.0.3
info:
title: Meet External API
version: 1.0.0
description: |
External API for room management with resource server authentication.
[[description by Oauth 2.0]](https://www.oauth.com/oauth2-servers/the-resource-server/)
#### Authentication Flow
1. Authenticate with the authorization server using your credentials
2. During authentication, request the scopes you need: `lasuite_visio` (mandatory) plus action-specific scopes
3. Receive an access token and a refresh token that includes the requested scopes
4. Use the access token in the `Authorization: Bearer <token>` header for all API requests
5. When the access token expires, use the refresh token to obtain a new access token without re-authenticating
#### Scopes
* `lasuite_visio` - **Mandatory** Base scope required for any API access
* `lasuite_visio:rooms:list` List rooms accessible to the delegated user.
* `lasuite_visio:rooms:retrieve` Retrieve details of a specific room.
* `lasuite_visio:rooms:create` Create new rooms.
* `lasuite_visio:rooms:update` **Coming soon** Update existing rooms, e.g., add attendees to a room.
* `lasuite_visio:rooms:delete` **Coming soon** Delete rooms generated by the application.
#### Upcoming Features
* **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.
contact:
name: API Support
email: antoine.lebaud@mail.numerique.gouv.fr
servers:
- url: https://visio-sandbox.beta.numerique.gouv.fr/external-api/v1.0
description: Sandbox server
tags:
- name: Rooms
description: Room management operations
paths:
/rooms:
get:
tags:
- Rooms
summary: List rooms
description: |
Returns a list of rooms accessible to the authenticated user.
Only rooms where the delegated user has access will be returned.
operationId: listRooms
security:
- BearerAuth: [rooms:list]
parameters:
- name: page
in: query
description: Page number for pagination
schema:
type: integer
minimum: 1
default: 1
- name: page_size
in: query
description: Number of items per page
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: List of accessible rooms
content:
application/json:
schema:
type: object
properties:
count:
type: integer
description: Total number of rooms
next:
type: string
nullable: true
description: URL to next page
previous:
type: string
nullable: true
description: URL to previous page
results:
type: array
items:
$ref: '#/components/schemas/Room'
examples:
roomList:
summary: Paginated room list
value:
count: 2
next: "https://visio-sandbox.beta.numerique.gouv.fr/external-api/v1.0/rooms?page=2"
previous: null
results:
- id: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
slug: "aae-erez-aaz"
access_level: "trusted"
url: "https://visio-sandbox.beta.numerique.gouv.fr/aae-erez-aaz"
telephony:
enabled: true
pin_code: "123456"
phone_number: "+1-555-0100"
default_country: "US"
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
post:
tags:
- Rooms
summary: Create a room
description: |
Creates a new room with secure defaults for external API usage.
**Restrictions:**
- Rooms are always created with `trusted` access (no public rooms via API)
- Room access_level can be updated from the webapp interface.
**Defaults:**
- Delegated user is set as owner
- Room slug auto-generated for uniqueness
- Telephony PIN auto-generated when enabled
- Creation tracked with application client_id for auditing
operationId: createRoom
security:
- BearerAuth: [rooms:create]
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/RoomCreate'
examples:
emptyBody:
summary: No parameters (default)
value: {}
responses:
'201':
description: Room created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Room'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
/rooms/{id}:
get:
tags:
- Rooms
summary: Retrieve a room
description: Get detailed information about a specific room by its ID
operationId: retrieveRoom
security:
- BearerAuth: [rooms:retrieve]
parameters:
- name: id
in: path
required: true
description: Room UUID
schema:
type: string
format: uuid
responses:
'200':
description: Room details
content:
application/json:
schema:
$ref: '#/components/schemas/Room'
examples:
room:
summary: Room details
value:
id: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
slug: "aae-erez-aaz"
access_level: "trusted"
url: "https://visio-sandbox.beta.numerique.gouv.fr/aae-erez-aaz"
telephony:
enabled: true
pin_code: "123456"
phone_number: "+1-555-0100"
default_country: "US"
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/RoomNotFoundError'
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT token obtained from the `/application/token` endpoint.
Include in requests as: `Authorization: Bearer <token>`
schemas:
TokenRequest:
type: object
required:
- client_id
- client_secret
- grant_type
- scope
properties:
client_id:
type: string
description: Application client identifier
example: "550e8400-e29b-41d4-a716-446655440000"
client_secret:
type: string
format: password
writeOnly: true
description: Application secret key
example: "1234567890abcdefghijklmnopqrstuvwxyz"
grant_type:
type: string
enum:
- client_credentials
description: OAuth2 grant type (must be 'client_credentials')
example: "client_credentials"
scope:
type: string
format: email
description: |
Email address of the user to delegate.
The application will act on behalf of this user.
Note: This parameter is named 'scope' to align with OAuth2 conventions,
but accepts an email address to identify the user. This design allows
for future extensibility.
example: "user@example.com"
TokenResponse:
type: object
properties:
access_token:
type: string
description: JWT access token
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtZWV0LWFwaSIsImF1ZCI6Im1lZXQtY2xpZW50cyIsImlhdCI6MTcwOTQ5MTIwMCwiZXhwIjoxNzA5NDk0ODAwLCJjbGllbnRfaWQiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJzY29wZSI6InJvb21zOmxpc3Qgcm9vbXM6cmV0cmlldmUgcm9vbXM6Y3JlYXRlIiwidXNlcl9pZCI6IjdiOGQ5YzQwLTNhMmItNGVkZi04NzFjLTJmM2Q0ZTVmNmE3YiIsImRlbGVnYXRlZCI6dHJ1ZX0.signature"
token_type:
type: string
description: Token type (always 'Bearer')
example: "Bearer"
expires_in:
type: integer
description: Token lifetime in seconds
example: 3600
scope:
type: string
description: Space-separated list of granted permission scopes
example: "rooms:list rooms:retrieve rooms:create"
RoomCreate:
type: object
description: Empty object - all room properties are auto-generated
properties: {}
Room:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
description: Unique room identifier
example: "7c9e6679-7425-40de-944b-e07fc1f90ae7"
slug:
type: string
readOnly: true
description: URL-friendly room identifier (auto-generated)
example: "aze-eere-zer"
access_level:
type: string
readOnly: true
description: Room access level (always 'trusted' for API-created rooms)
example: "trusted"
url:
type: string
format: uri
readOnly: true
description: Full URL to access the room
example: "https://visio-sandbox.beta.numerique.gouv.fr/aze-eere-zer"
telephony:
type: object
readOnly: true
description: Telephony dial-in information (if enabled)
properties:
enabled:
type: boolean
description: Whether telephony is available
example: true
pin_code:
type: string
description: PIN code for dial-in access
example: "123456"
phone_number:
type: string
description: Phone number to dial
example: "+1-555-0100"
default_country:
type: string
description: Default country code
example: "US"
OAuthError:
type: object
description: OAuth2-compliant error response
properties:
error:
type: string
description: Human-readable error description
example: "Invalid credentials"
Error:
type: object
properties:
detail:
type: string
description: Error message
example: "Invalid token."
ValidationError:
type: object
properties:
field_name:
type: array
items:
type: string
description: List of validation errors for this field
example: ["This field is required."]
responses:
UnauthorizedError:
description: The access token is expired, revoked, malformed, or invalid for other reasons. The client can obtain a new access token and try again.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
invalidToken:
summary: Invalid token
value:
error: "Invalid token."
ForbiddenError:
description: Insufficient scope for this operation
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
insufficientScope:
summary: Missing required scope
value:
detail: "Insufficient permissions. Required scope: 'rooms:xxxx'"
RoomNotFoundError:
description: Room not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
roomNotFound:
summary: Room does not exist
value:
detail: "Not found."
BadRequestError:
description: Invalid request data
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
examples:
validationError:
summary: Field validation failed
value:
scope: ["Invalid email address."]
+118
View File
@@ -0,0 +1,118 @@
# Theming La Suite Meet
There are two ways to customize LaSuite Meet:
- **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:
```javascript
FRONTEND_CSS_URL=https://example.com/custom-style.css
```
> [!TIP]
> 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 apps 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:
```css
@import url(https://fonts.bunny.net/css?family=Roboto:wght@400;700&display=swap);
:root {
--fonts-sans: 'Roboto', ui-sans-serif, system-ui, sans-serif;
}
```
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:
| Category | Purpose | Example Token |
| ---------- | ------------------------------- | --------------------------- |
| Primary | Brand color, buttons, links | `--colors-primary` |
| Dark Mode | Primary color in room/dark mode | `--colors-primary-dark-500` |
| Greyscale | Text, backgrounds, borders | `--colors-greyscale-500` |
| Success | Success states | `--colors-success` |
| Error | Errors and destructive actions | `--colors-error` |
| Warning | Warnings and alerts | `--colors-warning` |
| Alert | Notification backgrounds | `--colors-alert` |
| Font Sans | Main UI font | `--fonts-sans` |
| Font Serif | Alternate/reading font | `--fonts-serif` |
| Font Mono | Code or technical font | `--fonts-mono` |
### Assets (Logo, Images)
You can override built-in assets (such as the logo or images) by mounting your own files into the container.
Simply bind-mount your custom assets to the following path inside the container:
```
/usr/share/nginx/html/assets
```
Any files you mount here will **override the defaults at runtime**.
For example, to replace the images used in the landing page carousel, provide your own versions with the same filenames and paths:
```
/usr/share/nginx/html/
└── assets/intro-slider/
├── 1.png
├── 2.png
├── 3.png
└── 4.png
```
## Build-Time Theming
Some settings cannot be applied at runtime and require rebuilding the Docker image.
One key example is the **application title and name**, controlled by the `VITE_APP_TITLE` build argument.
* **Default:** `La Suite Meet`
* **Override:** supply your own value at build time
```bash
docker build \
--build-arg VITE_APP_TITLE="My Custom Meet" \
-t my-org/meet:latest .
```
```dockerfile
# Dockerfile
ARG VITE_APP_TITLE="La Suite Meet"
ENV VITE_APP_TITLE=${VITE_APP_TITLE}
```
For a real-world example, see how DINUM rebuilds the frontend to match their branding:
[DINUM Dockerfile](../docker/dinum-frontend/Dockerfile)
----
# **Footer Configuration**
The footer cannot be customized yet. This is a work in progress, and we welcome contributions — feel free to open a pull request if youd 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.
+38 -2
View File
@@ -12,18 +12,30 @@ PYTHONPATH=/app
# Mail
DJANGO_EMAIL_HOST="mailcatcher"
DJANGO_EMAIL_PORT=1025
DJANGO_EMAIL_BRAND_NAME=La Suite Numérique
DJANGO_EMAIL_SUPPORT_EMAIL=test@yopmail.com
DJANGO_EMAIL_LOGO_IMG=http://localhost:3000/assets/logo-suite-numerique.png
DJANGO_EMAIL_DOMAIN=localhost:3000
DJANGO_EMAIL_APP_BASE_URL=http://localhost:3000
# Backend url
MEET_BASE_URL="http://localhost:8072"
# Media
STORAGES_STATICFILES_BACKEND=django.contrib.staticfiles.storage.StaticFilesStorage
AWS_S3_DOMAIN_REPLACE=http://localhost:9000
AWS_S3_ENDPOINT_URL=http://minio:9000
AWS_S3_ACCESS_KEY_ID=meet
AWS_S3_SECRET_ACCESS_KEY=password
MEDIA_BASE_URL=http://localhost:8083
# OIDC
OIDC_OP_JWKS_ENDPOINT=http://nginx:8083/realms/meet/protocol/openid-connect/certs
OIDC_OP_AUTHORIZATION_ENDPOINT=http://localhost:8083/realms/meet/protocol/openid-connect/auth
OIDC_OP_TOKEN_ENDPOINT=http://nginx:8083/realms/meet/protocol/openid-connect/token
OIDC_OP_USER_ENDPOINT=http://nginx:8083/realms/meet/protocol/openid-connect/userinfo
OIDC_OP_INTROSPECTION_ENDPOINT=http://nginx:8083/realms/meet/protocol/openid-connect/token/introspect
OIDC_OP_URL=http://localhost:8083/realms/meet
OIDC_RP_CLIENT_ID=meet
OIDC_RP_CLIENT_SECRET=ThisIsAnExampleKeyForDevPurposeOnly
@@ -34,11 +46,35 @@ LOGIN_REDIRECT_URL=http://localhost:3000
LOGIN_REDIRECT_URL_FAILURE=http://localhost:3000
LOGOUT_REDIRECT_URL=http://localhost:3000
OIDC_REDIRECT_ALLOWED_HOSTS=["http://localhost:8083", "http://localhost:3000"]
OIDC_REDIRECT_ALLOWED_HOSTS=localhost:8083,localhost:3000
OIDC_AUTH_REQUEST_EXTRA_PARAMS={"acr_values": "eidas1"}
OIDC_RS_CLIENT_ID=meet
OIDC_RS_CLIENT_SECRET=ThisIsAnExampleKeyForDevPurposeOnly
# Livekit Token settings
LIVEKIT_API_SECRET=secret
LIVEKIT_API_KEY=devkey
LIVEKIT_API_URL=http://localhost:7880
LIVEKIT_API_URL=http://127.0.0.1.nip.io:7880
LIVEKIT_VERIFY_SSL=False
ALLOW_UNREGISTERED_ROOMS=False
# Recording
RECORDING_ENABLE=True
RECORDING_STORAGE_EVENT_ENABLE=True
RECORDING_STORAGE_EVENT_TOKEN=password
SUMMARY_SERVICE_ENDPOINT=http://app-summary-dev:8000/api/v1/tasks/
SUMMARY_SERVICE_API_TOKEN=password
RECORDING_DOWNLOAD_BASE_URL=http://localhost:3000/recording
# Telephony
ROOM_TELEPHONY_ENABLED=True
FRONTEND_USE_FRENCH_GOV_FOOTER=False
FRONTEND_USE_PROCONNECT_BUTTON=False
# External Applications
EXTERNAL_API_ENABLED=True
APPLICATION_JWT_AUDIENCE=http://localhost:8071/external-api/v1.0/
APPLICATION_JWT_SECRET_KEY=devKey
APPLICATION_BASE_URL=http://localhost:3000
+24
View File
@@ -0,0 +1,24 @@
APP_NAME="meet-app-summary-dev"
APP_API_TOKEN="password"
AWS_STORAGE_BUCKET_NAME="http://meet-media-storage"
AWS_S3_ENDPOINT_URL="minio:9000"
AWS_S3_SECURE_ACCESS=false
AWS_S3_ACCESS_KEY_ID="meet"
AWS_S3_SECRET_ACCESS_KEY="password"
WHISPERX_BASE_URL="https://configure-your-url.com"
WHISPERX_ASR_MODEL="large-v2"
WHISPERX_API_KEY="your-secret-key"
WHISPERX_DEFAULT_LANGUAGE="fr"
LLM_BASE_URL="https://configure-your-url.com"
LLM_API_KEY="dev-apikey"
LLM_MODEL="albert-large"
WEBHOOK_API_TOKEN="secret"
WEBHOOK_URL="https://configure-your-url.com"
POSTHOG_API_KEY="your-posthog-key"
POSTHOG_ENABLED="False"
+50
View File
@@ -0,0 +1,50 @@
# Django
DJANGO_ALLOWED_HOSTS=${MEET_HOST}
DJANGO_SECRET_KEY=<generate a secret key>
DJANGO_SETTINGS_MODULE=meet.settings
DJANGO_CONFIGURATION=Production
# Python
PYTHONPATH=/app
# Meet settings
# Mail
DJANGO_EMAIL_HOST=<smtp host>
DJANGO_EMAIL_HOST_USER=<smtp user>
DJANGO_EMAIL_HOST_PASSWORD=<smtp password>
DJANGO_EMAIL_PORT=<smtp port>
DJANGO_EMAIL_FROM=<your email address>
#DJANGO_EMAIL_USE_TLS=true # A flag to enable or disable TLS for email sending.
#DJANGO_EMAIL_USE_SSL=true # A flag to enable or disable SSL for email sending.
DJANGO_EMAIL_BRAND_NAME="La Suite Numérique"
DJANGO_EMAIL_LOGO_IMG="https://${MEET_HOST}/assets/logo-suite-numerique.png"
# Backend url
MEET_BASE_URL="https://${MEET_HOST}"
# OIDC
OIDC_OP_JWKS_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/certs
OIDC_OP_AUTHORIZATION_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/auth
OIDC_OP_TOKEN_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/token
OIDC_OP_USER_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/userinfo
OIDC_OP_LOGOUT_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/logout
OIDC_RP_CLIENT_ID=<client_id>
OIDC_RP_CLIENT_SECRET=<client secret>
OIDC_RP_SIGN_ALGO=RS256
OIDC_RP_SCOPES="openid email"
LOGIN_REDIRECT_URL=https://${MEET_HOST}
LOGIN_REDIRECT_URL_FAILURE=https://${MEET_HOST}
LOGOUT_REDIRECT_URL=https://${MEET_HOST}
OIDC_REDIRECT_ALLOWED_HOSTS=["https://${MEET_HOST}"]
# Livekit Token settings
LIVEKIT_API_SECRET=<generate a secret key>
LIVEKIT_API_KEY=meet
LIVEKIT_API_URL=https://${LIVEKIT_HOST}
ALLOW_UNREGISTERED_ROOMS=False
+7
View File
@@ -0,0 +1,7 @@
MEET_HOST=meet.domain.tld
KEYCLOAK_HOST=id.domain.tld
LIVEKIT_HOST=livekit.domain.tld
BACKEND_INTERNAL_HOST=backend
FRONTEND_INTERNAL_HOST=frontend
LIVEKIT_INTERNAL_HOST=livekit
REALM_NAME=meet
+13
View File
@@ -0,0 +1,13 @@
# Postgresql db container configuration
POSTGRES_DB=keycloak
POSTGRES_USER=keycloak
POSTGRES_PASSWORD=<generate postgres password>
PGDATA=/var/lib/postgresql/data/pgdata
# Keycloak postgresql configuration
KC_DB=postgres
KC_DB_SCHEMA=public
KC_DB_URL_HOST=postgresql
KC_DB_NAME=${POSTGRES_DB}
KC_DB_USER=${POSTGRES_USER}
KC_DB_PASSWORD=${POSTGRES_PASSWORD}
+8
View File
@@ -0,0 +1,8 @@
# Keycloak admin user
KC_BOOTSTRAP_ADMIN_USERNAME=admin
KC_BOOTSTRAP_ADMIN_PASSWORD=<generate your password>
# Keycloak configuration
KC_HOSTNAME=https://id.yourdomain.tld # Change with your own URL
KC_PROXY_HEADERS=xforwarded # in this example we are running behind an nginx proxy
KC_HTTP_ENABLED=true # in this example we are running behind an nginx proxy
+11
View File
@@ -0,0 +1,11 @@
# App database configuration
DB_HOST=postgresql
DB_NAME=meet
DB_USER=meet
DB_PASSWORD=<generate a secure password>
DB_PORT=5432
# Postgresql db container configuration
POSTGRES_DB=meet
POSTGRES_USER=meet
POSTGRES_PASSWORD=${DB_PASSWORD}
+1
View File
@@ -2,6 +2,7 @@
Gitlint extra rule to validate that the message title is of the form
"<gitmoji>(<scope>) <subject>"
"""
from __future__ import unicode_literals
import re
+29 -2
View File
@@ -3,18 +3,45 @@
"dependencyDashboard": true,
"labels": ["dependencies", "noChangeLog"],
"packageRules": [
{
"groupName": "js dependencies",
"matchManagers": ["npm"],
"schedule": ["on the first day of the month"],
"matchPackagePatterns": ["*"],
"minimumReleaseAge": "7 days",
"internalChecksFilter": "strict"
},
{
"groupName": "python dependencies",
"matchManagers": ["setup-cfg", "pep621"],
"schedule": ["on the first day of the month"],
"matchPackagePatterns": ["*"],
"minimumReleaseAge": "7 days"
},
{
"enabled": false,
"groupName": "ignored python dependencies",
"matchManagers": ["pep621"],
"matchPackageNames": []
"matchPackageNames": ["redis"]
},
{
"groupName": "allowed pylint versions",
"matchManagers": ["pep621"],
"matchPackageNames": ["pylint"],
"allowedVersions": "<4.0.0"
},
{
"groupName": "allowed django versions",
"matchManagers": ["pep621"],
"matchPackageNames": ["django"],
"allowedVersions": "<6.0.0"
},
{
"enabled": false,
"groupName": "ignored js dependencies",
"matchManagers": ["npm"],
"matchPackageNames": [
"eslint"
"eslint", "react", "react-dom", "@types/react-dom", "@types/react", "react-i18next"
]
}
]
Submodule secrets deleted from 8ef9f4513a
+35
View File
@@ -0,0 +1,35 @@
FROM python:3.13-slim AS base
# Install system dependencies required by LiveKit
RUN apt-get update && apt-get install -y \
libglib2.0-0 \
libgobject-2.0-0 \
"openssl=3.5.4-1~deb13u2" \
"libssl3t64=3.5.4-1~deb13u2" \
&& rm -rf /var/lib/apt/lists/*
FROM base AS builder
WORKDIR /builder
COPY pyproject.toml .
RUN mkdir /install && \
pip install --prefix=/install .
FROM base AS production
WORKDIR /app
# Remove pip to reduce attack surface in production
RUN pip uninstall -y pip
ARG DOCKER_USER
USER ${DOCKER_USER}
# Un-privileged user running the application
COPY --from=builder /install /usr/local
COPY . .
CMD ["python", "multi-user-transcriber.py", "start"]

Some files were not shown because too many files have changed in this diff Show More