diff --git a/README.md b/README.md index 8ac32d80..510b7c76 100644 --- a/README.md +++ b/README.md @@ -192,11 +192,6 @@ To use it, create a local config by, e.g., The `config.devenv.json` config should work with the backend development environment as outlined in the next section out of box. -> [!NOTE] -> Be aware, that this `config.devenv.json` is exposing a deprecated fallback -> LiveKit config key. If the homeserver advertises SFU backend via -> `.well-known/matrix/client` this has precedence. - You're now ready to launch the development server: ```sh @@ -212,12 +207,20 @@ See also: A docker compose file `dev-backend-docker-compose.yml` is provided to start the whole stack of components which is required for a local development environment: -- Minimum Synapse Setup (servername: `synapse.localhost`) -- LiveKit JWT Service (Note requires Federation API and hence a TLS reverse proxy) -- Minimum TLS reverse proxy (servername: `synapse.localhost`) Note certificates - are valid for at least 10 years from now +- Minimum Synapse Setup (servername: `synapse.m.localhost`) +- LiveKit Authorization Service (Note requires Federation API and hence a TLS reverse proxy) - Minimum LiveKit SFU Setup using dev defaults for config - Redis db for completeness +- Minimum `localhost` Certificate Authority (CA) for Transport Layer Security (TLS) + - Hostnames: `m.localhost`, `*.m.localhost` + - Add [./backend/dev_tls_local-ca.crt](./backend/dev_tls_local-ca.crt) to your web browsers trusted + certificates +- Minimum TLS reverse proxy for + - Synapse homeserver: `synapse.m.localhost` + - MatrixRTC backend: `matrix-rtc.m.localhost` + - Local Element Call development `call.m.localhost` via `yarn dev --host ` + - Element Web `app.m.localhost` + - Note certificates will expire on Thu, 03 May 2035 10:32:02 GMT These use a test 'secret' published in this repository, so this must be used only for local development and **_never be exposed to the public Internet._** @@ -230,6 +233,16 @@ yarn backend # podman-compose -f dev-backend-docker-compose.yml up ``` +> [!NOTE] +> To ensure your local development frontend functions properly, you’ll need to +> add certificate exceptions in your browser for `https://localhost:3000`, +> `https://matrix-rtc.m.localhost/livekit/jwt/healthz` and +> `https://synapse.m.localhost/.well-known/matrix/client`. This can be either +> done by adding the minimum localhost CA +> ([./backend/dev_tls_local-ca.crt](./backend/dev_tls_local-ca.crt)) to your web +> browsers trusted certificates or by simply copying and pasting each URL into +> your browser’s address bar and follow the prompts to add the exception. + ### Playwright tests Our Playwright tests run automatically as part of our CI along with our other diff --git a/backend/dev_homeserver.yaml b/backend/dev_homeserver.yaml index 5697c32e..eab4e698 100644 --- a/backend/dev_homeserver.yaml +++ b/backend/dev_homeserver.yaml @@ -1,5 +1,5 @@ -server_name: "synapse.localhost" -public_baseurl: http://synapse.localhost:8008/ +server_name: "synapse.m.localhost" +public_baseurl: https://synapse.m.localhost/ pid_file: /data/homeserver.pid diff --git a/backend/dev_nginx.conf b/backend/dev_nginx.conf new file mode 100644 index 00000000..59a25ba0 --- /dev/null +++ b/backend/dev_nginx.conf @@ -0,0 +1,155 @@ +# Synapse reverse proxy including .well-known/matrix/client +server { + listen 80; + listen [::]:80; + listen 443 ssl; + listen 8448 ssl; + listen [::]:443 ssl; + listen [::]:8448 ssl; + server_name synapse.m.localhost; + ssl_certificate /root/ssl/cert.pem; + ssl_certificate_key /root/ssl/key.pem; + + # well-known config adding rtc_foci backend + # Note well-known is currently not effective due to: + # https://spec.matrix.org/v1.12/client-server-api/#well-known-uri the spec + # says it must be at https://$server_name/... (implied port 443) Hence, we + # currently rely for local development environment on deprecated config.json + # setting for livekit_service_url + location /.well-known/matrix/client { + add_header Access-Control-Allow-Origin *; + return 200 '{"m.homeserver": {"base_url": "https://synapse.m.localhost"}, "org.matrix.msc4143.rtc_foci": [{"type": "livekit", "livekit_service_url": "https://matrix-rtc.m.localhost/livekit/jwt"}]}'; + default_type application/json; + } + + # Reverse proxy for Matrix Synapse Homeserver + # This is also required for development environment. + # Reason: the lk-jwt-service uses the federation API for the openid token + # verification, which requires TLS + location / { + proxy_pass "http://homeserver:8008"; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + + error_page 500 502 503 504 /50x.html; + +} + +# MatrixRTC reverse proxy +# - MatrixRTC Authorization Service +# - LiveKit SFU websocket signaling connection +server { + listen 80; + listen [::]:80; + listen 443 ssl; + listen [::]:443 ssl; + listen 8448 ssl; + listen [::]:8448 ssl; + server_name matrix-rtc.m.localhost; + ssl_certificate /root/ssl/cert.pem; + ssl_certificate_key /root/ssl/key.pem; + + + location ^~ /livekit/jwt/ { + + 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; + + # JWT Service running at port 8080 + proxy_pass http://auth-server:8080/; + } + + location ^~ /livekit/sfu/ { + 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_send_timeout 120; + proxy_read_timeout 120; + proxy_buffering off; + + proxy_set_header Accept-Encoding gzip; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # LiveKit SFU websocket connection running at port 7880 + proxy_pass http://livekit-sfu:7880/; + } + + error_page 500 502 503 504 /50x.html; + +} + +# Convenience reverse proxy for the call.m.localhost domain to yarn dev --host +server { + listen 80; + listen [::]:80; + server_name call.m.localhost; + + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name call.m.localhost; + ssl_certificate /root/ssl/cert.pem; + ssl_certificate_key /root/ssl/key.pem; + + + location ^~ / { + + 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_pass https://host.docker.internal:3000; + proxy_ssl_verify off; + + } + + error_page 500 502 503 504 /50x.html; + +} + +# Convenience reverse proxy app.m.localhost for element web +server { + listen 80; + listen [::]:80; + server_name app.m.localhost; + + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name app.m.localhost; + ssl_certificate /root/ssl/cert.pem; + ssl_certificate_key /root/ssl/key.pem; + + + location ^~ / { + + 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_pass http://element-web:81; + proxy_ssl_verify off; + + } + + error_page 500 502 503 504 /50x.html; + +} \ No newline at end of file diff --git a/backend/dev_tls_local-ca.crt b/backend/dev_tls_local-ca.crt new file mode 100644 index 00000000..9c8ee3d7 --- /dev/null +++ b/backend/dev_tls_local-ca.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGjCCAgKgAwIBAgIUGdiFHhH4KL2pqBjMQHQ+PVIkSV8wDQYJKoZIhvcNAQEL +BQAwHjEcMBoGA1UEAwwTRWxlbWVudCBDYWxsIERldiBDQTAeFw0yNTA1MDUxMDMy +MDJaFw0zNTA1MDMxMDMyMDJaMB4xHDAaBgNVBAMME0VsZW1lbnQgQ2FsbCBEZXYg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA2y0hjmNn1vRsVSdy +8IOfo8N1q9UgkhQWpGKXzPh+D5d1fnuJEmHIVwtDEtS/PwQ43LTmegChPtKH9jdT +tG0IihW9Ja5YNG+9xAwaoA/sB3CGCBYsz+2/XjVUpXoBJXIPoFBWsn+K0oeFw9fw +eRO1z9abM4cl+LjKzMNM8CCyu9uI1MaGjYez2YIWvG854VucLxX7HSlMJxZNWnie +Ui7fMakuJhB2+aiIQjdKxy4E5RHNhzYG/LXhvP+wBYBDPNRsP3rtzEaE9HAveL9K +FGqd3R4cBia6r1WIXmpAzyu5RGP5Eou0TZlGkal96/bF0I7q/pKlL23Jt1BLPiQU +KGKrAgMBAAGjUDBOMB0GA1UdDgQWBBQJqBjMu61c1p24txw/y+kv3D+V6DAfBgNV +HSMEGDAWgBQJqBjMu61c1p24txw/y+kv3D+V6DAMBgNVHRMEBTADAQH/MA0GCSqG +SIb3DQEBCwUAA4IBAQB8m2YfFGLugNt5vAAOvNxVqDA8c72yCVYr3CBCpmTIEY5Z +d3qVGhG9//ux6+J8ntkSwd9nV5GJyYXHukCG1VavnAWolWdNF/WAllf0jhLuz7kD +/cJnuI1By4tBsBmSz851i6HJ4t5k99Be+6GQVzi0e7zzfxTHZE4xP2J6Ox8QbPsP +n0m76nIp/WbWaJqzvIIjJhmUUPPv+4wN+eOArgjiGLzptM2qTtGZtd0c9nS5gvep ++mEbSUN9zkhAroZf80wf+hEvy+fJ94VbZ9QjTzTg7odZLrsXGIe8DaG63EYRQ25b +W5iYBAreln5fGSt7qHsGfqwZibTEk/Lx3dydO1Kg +-----END CERTIFICATE----- diff --git a/backend/dev_tls_local-ca.key b/backend/dev_tls_local-ca.key new file mode 100644 index 00000000..c6de05c4 --- /dev/null +++ b/backend/dev_tls_local-ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDA2y0hjmNn1vRs +VSdy8IOfo8N1q9UgkhQWpGKXzPh+D5d1fnuJEmHIVwtDEtS/PwQ43LTmegChPtKH +9jdTtG0IihW9Ja5YNG+9xAwaoA/sB3CGCBYsz+2/XjVUpXoBJXIPoFBWsn+K0oeF +w9fweRO1z9abM4cl+LjKzMNM8CCyu9uI1MaGjYez2YIWvG854VucLxX7HSlMJxZN +WnieUi7fMakuJhB2+aiIQjdKxy4E5RHNhzYG/LXhvP+wBYBDPNRsP3rtzEaE9HAv +eL9KFGqd3R4cBia6r1WIXmpAzyu5RGP5Eou0TZlGkal96/bF0I7q/pKlL23Jt1BL +PiQUKGKrAgMBAAECggEAAPX2kxi5AQ7ul82SzT1KgpSXyDHLdYaUyAoYnaX9RO+B +8ylmpyeqygs4+KQS4EMJm9jpo85Oy37bIKdG3kljU6wQcKlL5Y+ZUOo1nzpV6fid +hGVs6ts8VXw8KshKQ9AyccZ8L/pirUfgOffgTwfjY7/90zceAL/s98GuZWc62nkX +55joQv/OikqYfAGP/U6Bp2Zyf23DwJB09Z3B6NnZj/ZyAbDrDEHuA15LhCOcCczp +IU/mFEywBPHT9Tg4w4Beq78PeAETvku2UalYRLhP3RLlXr2oEbwUtINRVt2QjZ85 +Esps4uCqL/mgQluIebtudD9HL/YMlNPXue1mDXFxJQKBgQDgZZY4yJBcf488T1V6 +HNm06b/LvVGj253pKgw14hpY1xQu3Ymgzv1GEqzhSYdzxhpmj0tMUNHxAp+YdGQu +SZ0wcPKhw0aYVkIjDRYDC3Wn5GJhyIEYHGYMo/n4l49UzHRBPOTDzp49DkHTKBgh +XgIIazYT3CkjTIMRrkUv+qfIPQKBgQDcBGu/mqbjxs4sN3zqPS4aB21o6t6W0sXs +ZP9w6RlTPQi5U2oRbftjZtYc0bbEgkMUImB1HwYPQT5pJ+MyC414xDvSc2exBr5d +To6yyPIy78Tf5PHM12fpKV92nSvoz/pSjYcGxxDtKfPqu+t8mOJfjCV1lLLA+xuB +DDaE4p8dBwKBgQCdAne6A5v/HMH8UQZeCxHJpESvKiiVnnU/UEx651nID7XvlNNX +0X0mKqsMd4ZvW43ddSYan/JF0LAa3FW8jYWO/3jF9vzOWoysOdvNBZetgf/Uq5ao +aDZ/YbzmVCXWD7jIbPMkjs3pqrAkL0mzDzQc7+dGviWKrV6IYIfIqnn7gQKBgDCz +vdIk/qpO+JZrFfiX4Fucp0hhLTJ/p5ZDaRPqVVPKn+K+Jy2ChfIj8mNgvK9VEloj +nexvGJ1J2PHYBX+vdPp1nbRhHWPfVUY8PHQw7QP/dToGaMvqJrNDGEGeWvjnCMc7 +UtdaO1H0Rm0AegkTopB56lTTvJnhO95eALd7nrMDAoGAEPdzJtWoKafp49svhSj0 +hiXQv2SPBwVUN4LZ4SOWiXUcmYYm80aNpYKLkBxYjrfqFWhE7NUHLGp8YorQWKY2 +acD9AReHk/xku0ABy6jeYmSCmCxASxst5liKD+l12sk0gB0rk5MBxB4Uu1MIbQZ2 +aCASX3AVD2/XyC2MKkzc8Eg= +-----END PRIVATE KEY----- diff --git a/backend/dev_tls_m.localhost.crt b/backend/dev_tls_m.localhost.crt new file mode 100644 index 00000000..5d6251a9 --- /dev/null +++ b/backend/dev_tls_m.localhost.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIUXizLjwkdqepX0bh0K3abeJxj68IwDQYJKoZIhvcNAQEL +BQAwHjEcMBoGA1UEAwwTRWxlbWVudCBDYWxsIERldiBDQTAeFw0yNTA1MDUxMzU5 +MTFaFw0zNTA1MDMxMzU5MTFaMBgxFjAUBgNVBAMMDSoubS5sb2NhbGhvc3QwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrzGSScSgaQuZdELGFYiLiYRwr +LKyUdNr0rsPcOo0bvbeZ3zQMeUMRNlA69zGFdarumiDRXUoAmZI39WmH95aX3d+A +U7EFnWev7xpWSVhSYj8T0d4rke8HjGk3LpaffJ93tbJuagBIH1ouuN6AOdzWs8hp +RYIomWleEeeuVnnfaMwaXOdc+ihJJ6wzm2hwQSfdpjZPWBDd/DFft1ZXxIZOCjDs +rEIiI7uU8iZPLB3QEM/tgxSSAOxrcKvQvxZokk+FD7aMJFP71IfieLCEzMTP1VXa +tP7UTAKAqB2NyDJ8m3IHbOINiqcdFvFR3R1D9bXOYE4oRynNvYZrQUGnL2RtAgMB +AAGjgaIwgZ8wHwYDVR0jBBgwFoAUCagYzLutXNaduLccP8vpL9w/legwCQYDVR0T +BAIwADALBgNVHQ8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwMAYDVR0RBCkw +J4IJbG9jYWxob3N0ggttLmxvY2FsaG9zdIINKi5tLmxvY2FsaG9zdDAdBgNVHQ4E +FgQUfdh1p52ZgWyZcBgBXGwKi4EnUE0wDQYJKoZIhvcNAQELBQADggEBAKrHEuB6 +33j8+EwSHw3zrvt/DRXK2BDHI1Ir9JcztSunaKAjZXVvf/dvZp0Xs1dEdJIdnv6G +iZYhBbOqDqpQZbf2h/h0kuu5yZSBUdnQXnYNxlhp2UaC/UEgw5iZT/p1rm7RjVie +y4Dp2WytV5iZOLmLj6xDvd3DXazgJPWIRX8p8qJZbKTkwCjTr7nDIj8jjG1sVFf7 +1RJBO5/6WSnImrpDmlLUrvjiKvbxcdseDJyBOhTwdRdSk4S2M+s5tR5j2I1gXLOq +J5ioN76+SCrTY0K0WKRy9oOXWO1/X3+VYcekp+0F3SGkd5w17jylCv1XIGHAdEsQ +v2z2/aMI/7sAD2Q= +-----END CERTIFICATE----- diff --git a/backend/dev_tls_m.localhost.key b/backend/dev_tls_m.localhost.key new file mode 100644 index 00000000..73d89ce4 --- /dev/null +++ b/backend/dev_tls_m.localhost.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrzGSScSgaQuZd +ELGFYiLiYRwrLKyUdNr0rsPcOo0bvbeZ3zQMeUMRNlA69zGFdarumiDRXUoAmZI3 +9WmH95aX3d+AU7EFnWev7xpWSVhSYj8T0d4rke8HjGk3LpaffJ93tbJuagBIH1ou +uN6AOdzWs8hpRYIomWleEeeuVnnfaMwaXOdc+ihJJ6wzm2hwQSfdpjZPWBDd/DFf +t1ZXxIZOCjDsrEIiI7uU8iZPLB3QEM/tgxSSAOxrcKvQvxZokk+FD7aMJFP71Ifi +eLCEzMTP1VXatP7UTAKAqB2NyDJ8m3IHbOINiqcdFvFR3R1D9bXOYE4oRynNvYZr +QUGnL2RtAgMBAAECggEAJaFQii8U/KOYt9vXNoMnZvSkaeSQLLhn2V6Kciu1CtWE +aMTWLsFE6nk+G5xXkYcTmM3T0GghtH3u5CjyI6EcsEkeEorCZJt0wbmayDmqiekR +LfMzOdHuTHX5+edPgMGYYG1BFyRKyYFsjH1b5zRFZhXdGQnrl5760GsVlz9D1KZQ +iHcT+q1S2tmZeoUukQnADENKXUMCyTGM5FCddgNtsWnGDsTDayh7hUdvDkB+mW4G +lSp+BZuc3PCwpbD6qkXvfugWs6CUAAtXoV3ceWgxQ+TEnNlwxaG1AyugfgNUBolk +8xgeZt4r5QId03jsHDf7hpBAofcaCd5EMIIQYFvWoQKBgQDlbAvAzEFPTZZn2nRV +Xagw4xjqVc1LLEKLCWq0N5rEkwn0h90Dz5N7/3NuonP/sIDsDHCbyiOYBI1Ck6Xi +0WuB+OyKDh+xeF2mekN9G9ywPahdK5lT/TVsxXFyZlwtVv1x/6KBO4yv5URizxqU +gyAPDDxfD/KcNjkOBaodWEwQGQKBgQC/s2gPDBtQkjLwkHXchBomLww5eLlVrac1 +WK4UX6uSdOgrjJ375OOgMTxe8NVZdOuAKytGXRWDwgH3nVWvuZhe7dGlX3JMuSer +e9VwDpBESrvqcR4ruL6wm8wej6BXyjH0wD3FHb0S5HfuBDxTn+4bDwrbRzOUMNgy +lSppuflxdQKBgQDiZcIfazFT8evn5nMAvuC4BZNTxIJHmZC9JfjPiUPIkpWzYtOe +7BvNtKOT3Op9uw8uYYRKqKqBXJSNy6ha8XCXHS9HeXKbLn20SFkLQBCDNwVLlDfF +40zyXtF6JDr4XyzSb4NM5pgKCER5AYloXxGm59s3sEQpFXUuOjbKqJS/GQKBgAoI +c7vF4HAZFr1sch62cz/oWnVvkhOf4Q5zs7ixQSOLJtOQqnwSgK9TpFs7s47ZBbJR +kBRAru2Ua9Hv1Bo8VnMxczV6h1roneDlvEf/GyHX33nnrbKQGrrXjJlU3wl5NaAf +p5v3cHvapUQ5yIZ/6lBUOzc6xMJOxCHxmKSr7Rg5AoGAbEE4lt6Xh2dnBPJ81eNI +IDrw/3ITY53qAY4Bx88CByIFuu8CEUdUZprh98jSl6ic1tMinZfUhRMwABLrUD51 +DGst8iGLPD9u83iMcUHI/L+p7AbxrKLvWXZrF5UZm440c9mSWqfhPaTBosPtNDsG +LfETwH1flKXMTXd2xA9RTE4= +-----END PRIVATE KEY----- diff --git a/backend/dev_tls_setup b/backend/dev_tls_setup new file mode 100644 index 00000000..8a778dc8 --- /dev/null +++ b/backend/dev_tls_setup @@ -0,0 +1,38 @@ +#!/bin/bash + +# Step 1: Create a Root CA key and cert +openssl genrsa -out dev_tls_local-ca.key 2048 +openssl req -x509 -new -nodes \ + -days 3650 \ + -subj "/CN=Element Call Dev CA" \ + -key dev_tls_local-ca.key \ + -out dev_tls_local-ca.crt \ + -sha256 -addext "basicConstraints=CA:TRUE" + +# Step 2: Create a private key and CSR for *.m.localhost +openssl req -new -nodes -newkey rsa:2048 \ + -keyout dev_tls_m.localhost.key \ + -out dev_tls_m.localhost.csr \ + -subj "/CN=*.m.localhost" + +# Step 3: Sign the CSR with your CA +openssl x509 \ + -req -in dev_tls_m.localhost.csr \ + -CA dev_tls_local-ca.crt -CAkey dev_tls_local-ca.key \ + -CAcreateserial \ + -out dev_tls_m.localhost.crt \ + -days 3650 \ + -sha256 \ + -extfile <( cat < { @@ -24,7 +24,6 @@ export default defineConfig(({ mode, packageType }) => { process.env.VITE_PACKAGE = packageType ?? "full"; const plugins = [ react(), - basicSsl(), svgrPlugin({ svgrOptions: { // This enables ref forwarding on SVGR components, which is needed, for @@ -84,6 +83,10 @@ export default defineConfig(({ mode, packageType }) => { server: { port: 3000, fs: { allow }, + https: { + key: fs.readFileSync("./backend/dev_tls_m.localhost.key"), + cert: fs.readFileSync("./backend/dev_tls_m.localhost.crt"), + }, }, build: { sourcemap: true, diff --git a/yarn.lock b/yarn.lock index 394e81a7..ef372359 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5127,15 +5127,6 @@ __metadata: languageName: node linkType: hard -"@vitejs/plugin-basic-ssl@npm:^1.0.1": - version: 1.2.0 - resolution: "@vitejs/plugin-basic-ssl@npm:1.2.0" - peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 - checksum: 10c0/0d360fcca01f91ade6e451edbea09a107ff9e95cd3c3766c7a069d1a168709df92d96c0bd1eccc66e2739a153e07c75a45321ec487450c0da942606200d8441d - languageName: node - linkType: hard - "@vitejs/plugin-react@npm:^4.0.1": version: 4.3.4 resolution: "@vitejs/plugin-react@npm:4.3.4" @@ -6968,7 +6959,6 @@ __metadata: "@use-gesture/react": "npm:^10.2.11" "@vector-im/compound-design-tokens": "npm:^3.0.0" "@vector-im/compound-web": "npm:^7.2.0" - "@vitejs/plugin-basic-ssl": "npm:^1.0.1" "@vitejs/plugin-react": "npm:^4.0.1" "@vitest/coverage-v8": "npm:^3.0.0" babel-plugin-transform-vite-meta-env: "npm:^1.0.3"