[QUESTION] AXIS P3354 Fixed Dome Network Camera with KVS configuration

I see that here: https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/system-requirements.html
Kinesis video streams has been tested with "AXIS P3354 Fixed Dome Network Camera". I am looking to setup Kinesis SDK on an AXIS encoder (P7304) but am looking for resources that could help me figure out what steps would be needed here. It would be very helpful if you could share the details of how you setup Kinesis video streams with the AXIS P3354 - thank you!
Kind Regards,

My company uses Axis cameras as well but unfortunately there is no "onboard" integration directly to AWS Kinesis Video streams like there is for Vivotek cameras ( and a few others ). Hence, you will either need to write this integration yourself and load it onto the camera using ACAP. Here are some github examples.  We are in the process of creating an integration but it will not be publicly available unfortunately. Your second option is to run the producer from a system on the same network as the camera producing the feed. I would suggest a server running docker and you can run the producer in a container. The producer will then capture the stream and shuffle it up to AWS. You may run into an issue of dealing with passwords. A quick and dirty fix is to clone the c++ sdk here and edit the kvs gstreamer file and modify the rtspsrc to include a hardcoded username and password. This is mentioned here #501
g_object_set(G_OBJECT (source),
                 "location", data->rtsp_url.c_str(),
                 "short-header", true, // Necessary for target camera
                 "user-id", "",
                 "user-pw", "",
                 NULL);

This will be easiest if you have the necessary software to compile the library and then include it in a docker container. Hopefully this helps at least a little

My company uses Axis cameras as well but unfortunately there is no "onboard" integration directly to AWS Kinesis Video streams like there is for Vivotek cameras ( and a few others ). Hence, you will either need to write this integration yourself and load it onto the camera using ACAP. Here are some github examples. We are in the process of creating an integration but it will not be publicly available unfortunately. Your second option is to run the producer from a system on the same network as the camera producing the feed. I would suggest a server running docker and you can run the producer in a container. The producer will then capture the stream and shuffle it up to AWS. You may run into an issue of dealing with passwords. A quick and dirty fix is to clone the c++ sdk here and edit the kvs gstreamer file and modify the rtspsrc to include a hardcoded username and password. This is mentioned here #501
g_object_set(G_OBJECT (source),
                 "location", data->rtsp_url.c_str(),
                 "short-header", true, // Necessary for target camera
                 "user-id", "",
                 "user-pw", "",
                 NULL);

The url for an axis camera will end up looking like this.
<EMAIL_ADDRESS>This will be easiest if you have the necessary software to compile the library and then include it in a docker container. Hopefully this helps at least a little

Thanks that's very helpful. I'd be interested to hear how your company gets on with writing the integration, our company is discussing whether its worth investing the time in this, but its hard to gauge how many man-hours it might consume. There might be some scope for collaboration between our companies if we were to decide Kinesis is the way forward.
Currently we are using the SMB encrypted file transfer to send video from the camera to the cloud; but I can imagine Kinesis would be more easy to scale to thousands of cameras. We are also investigating HTTPS for video clip transfers but even the AXIS support seems to have little idea how this works.  We can access the RTMP stream from a local device and could take this approach if needed; but one our goals is to remove local hardware where possible, so installing Kinesis SDK on the device itself seems ideal.

Great discussion here. The main issue with the device integration is the platform openness. I am not really familiar with this platform and it’s capabilities but I would assume it runs a sort of embedded Linux. The integrator only needs access to the media pipeline as the rest is generic. If the device supports gstreamer then there is a plugin that the integrator could use.
Unfortunately, KVS team does not own the platform so we support generic media pipeline which is GStreamer

@bml1g12 One thing I would strongly recommend is to try out using the producer through docker and understand the end to end flow as much as possible. There are many settings to tweak and it can make a difference in cost/overhead/maintenance. If you already have well defined processes around processing for use cases like ML and associated tasks like retention than great but I would at least get to a level of experience with the client and it's settings where you can do "napkin math" and estimate properly based on your end state. At the end of the day it doesn't really matter whether the producer is on the cameras or not but it does make rollout and maintenance somewhat easier.

Unfortunately, KVS team does not own the platform so we support generic media pipeline which is GStreamer

I understand, but it sounds like the KVS team have already tested it on AXIS P3354 (at least based on https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/system-requirements.html) so I wonder if it would be possible to share the code used for this; even if its not officially supported.

@bml1g12 One thing I would strongly recommend is to try out using the producer through docker and understand the end to end flow as much as possible. There are many settings to tweak and it can make a difference in cost/overhead/maintenance. If you already have well defined processes around processing for use cases like ML and associated tasks like retention than great but I would at least get to a level of experience with the client and it's settings where you can do "napkin math" and estimate properly based on your end state. At the end of the day it doesn't really matter whether the producer is on the cameras or not but it does make rollout and maintenance somewhat easier.

Thanks for the advice. We want to avoid installing servers into the network aside the cameras themselves; so if we were to put the producer elsewhere it would need to be outside of the network (e.g. an EC2 instance) - but then this would then presumably means we would need to try and tunnel through the firewall surrounding the cameras; which would be problematic as we are likely not permitted to allow inbound traffic on the router settings for security reasons.

@bml1g12 Yes I can help you with that!  There are a couple different approaches you can take, as suggested by @dfcarpenter you can become part of Axis' ACAP program and have access to their embedded SDK (and their provided toolchain) so you get access to the media pipeline and can feed frames to our system.
There is another way.  Most Axis camera's I'm aware of have a proper gstreamer installation.  You can verify this by sshing onto your camera (or in this case your encoder) and at the terminal type:
gst-inspect-1.0 --version
If gst-inspect-1.0 is on the machine (should already be in path) it will print out the version.  Now you can build our kvssink plugin and as a test you can provide a pipeline via gst-launch-1.0 directly on the command line sending video frames to KVS (not your production solution but it's a good test to verify things are working).
The work is all in having the toolchain set up and building pre req's for kvssink and then the plugin itself.  I have tested with the following toolchain:  https://packages.ubuntu.com/xenial/g++-5-arm-linux-gnueabihf
Yes you'll need an Ubuntu 16.04 box for this (I tested on an EC2 instance) to use this toolchain, a newer compiler should work fine too, but make sure its "arm-linux-gnueabihf", an on an Ubuntu box.  If you need more assistance on this part let me know.
Once you have your toolchain set up, the proceed with building ssl/curl and other dependences.   Note the kvssink plugin is useful to test with the gstreamer installation already on the camera on the command line, but then once you've verified it works you can use ACAP to actually create an application which build the same pipeline (in C), Axis provided source plugin is artpecsrc which already goes through the hardware encoder and produces an h264 encoded frame, so the pipeline is super simple, something like (properties need to be specified for kvssink):
gst-launch-1.0 artpecsrc ! video/x-h264,height=720,width=1280,framerate=30/1 ! kvssink
Let me know if you need more help with this or how far you're able to get and we can go from there.

@hassanctech nice! Folks, any further info you need? Please resolve if not

Thank you @hassanctech  and @dfcarpenter - unfortunately it will probably be at least a few weeks until we get the time to do much experimentation on this, so if @MushMal  I am happy to close if that is the expected procedure in this case.
As I have not used gstreamer or compiled an ACAP before, its hard for me to comment much more until I get the time to do the reading and experimentation into this, but the notes you shared here sound like a great point of reference; I hope if we run into any problems I can reopen this ticket and clarify.
Thank you!

@bml1g12 the reason we try to not keep the issues open/non-transacted is so we can properly prioritize our effort in engaging with them. It's absolutely fine to re-open or cut a new issue and reference the older for more info

@bml1g12 Yes I can help you with that! There are a couple different approaches you can take, as suggested by @dfcarpenter you can become part of Axis' ACAP program and have access to their embedded SDK (and their provided toolchain) so you get access to the media pipeline and can feed frames to our system.
There is another way. Most Axis camera's I'm aware of have a proper gstreamer installation. You can verify this by sshing onto your camera (or in this case your encoder) and at the terminal type:
gst-inspect-1.0 --version
If gst-inspect-1.0 is on the machine (should already be in path) it will print out the version. Now you can build our kvssink plugin and as a test you can provide a pipeline via gst-launch-1.0 directly on the command line sending video frames to KVS (not your production solution but it's a good test to verify things are working).
The work is all in having the toolchain set up and building pre req's for kvssink and then the plugin itself. I have tested with the following toolchain: https://packages.ubuntu.com/xenial/g++-5-arm-linux-gnueabihf
Yes you'll need an Ubuntu 16.04 box for this (I tested on an EC2 instance) to use this toolchain, a newer compiler should work fine too, but make sure its "arm-linux-gnueabihf", an on an Ubuntu box. If you need more assistance on this part let me know.
Once you have your toolchain set up, the proceed with building ssl/curl and other dependences. Note the kvssink plugin is useful to test with the gstreamer installation already on the camera on the command line, but then once you've verified it works you can use ACAP to actually create an application which build the same pipeline (in C), Axis provided source plugin is artpecsrc which already goes through the hardware encoder and produces an h264 encoded frame, so the pipeline is super simple, something like (properties need to be specified for kvssink):
gst-launch-1.0 artpecsrc ! video/x-h264,height=720,width=1280,framerate=30/1 ! kvssink
Let me know if you need more help with this or how far you're able to get and we can go from there.

@hassanctech  thank you for your assistance, really appreciated. We setup the AWS Producer SDK on a separate machine to the encoder, and can successfully pull an AXIS rtsp stream into the Producer and send it Kinesis Video Streams. So now it is just a case of getting it working on the encoder itself.

If gst-inspect-1.0 is on the machine (should already be in path) it will print out the version.

We can ssh onto the encoder, and can access gstreamer interactively.

Now you can build our kvssink plugin and as a test you can provide a pipeline via gst-launch-1.0 directly on the command line sending video frames to KVS (not your production solution but it's a good test to verify things are working).

I wanted to clarify on this point, are you suggesting here building a gstreamer on that specific flavour of linux/compilers because it is the same OS as that used on the AXIS encoder; and thus we could build externally using an EC2 instance setup like that (or presumably just a Docker container setup like that) and then use a tool like scp to transfer the built gstreamer plugin code onto the encoder ready for use?

gst-launch-1.0 directly on the command line sending video frames to KVS (not your production solution but it's a good test to verify things are working).

I also wanted to clarify why you say this would not be production worthy?
If we are using the encoder's native gstreamer install, I presume it would have access to any hardware acceleration from the encoder itself (i.e. their artpecsrc plugin) by default. Is it not production worthy because we have no way of restarting automatically on connection interruptions; something which is managed intelligently by the callbacks such as in the AWS provided gstreamer sample code here?
In general, we were wondering the best way to ensure that the stream will infinitely try to reconnect in case of internet failure- as we would like the producer to require little manual intervention once setup on a camera/encoder.

@bml1g12 Yes I can help you with that! There are a couple different approaches you can take, as suggested by @dfcarpenter you can become part of Axis' ACAP program and have access to their embedded SDK (and their provided toolchain) so you get access to the media pipeline and can feed frames to our system.
There is another way. Most Axis camera's I'm aware of have a proper gstreamer installation. You can verify this by sshing onto your camera (or in this case your encoder) and at the terminal type:
gst-inspect-1.0 --version
If gst-inspect-1.0 is on the machine (should already be in path) it will print out the version. Now you can build our kvssink plugin and as a test you can provide a pipeline via gst-launch-1.0 directly on the command line sending video frames to KVS (not your production solution but it's a good test to verify things are working).
The work is all in having the toolchain set up and building pre req's for kvssink and then the plugin itself. I have tested with the following toolchain: https://packages.ubuntu.com/xenial/g++-5-arm-linux-gnueabihf
Yes you'll need an Ubuntu 16.04 box for this (I tested on an EC2 instance) to use this toolchain, a newer compiler should work fine too, but make sure its "arm-linux-gnueabihf", an on an Ubuntu box. If you need more assistance on this part let me know.
Once you have your toolchain set up, the proceed with building ssl/curl and other dependences. Note the kvssink plugin is useful to test with the gstreamer installation already on the camera on the command line, but then once you've verified it works you can use ACAP to actually create an application which build the same pipeline (in C), Axis provided source plugin is artpecsrc which already goes through the hardware encoder and produces an h264 encoded frame, so the pipeline is super simple, something like (properties need to be specified for kvssink):
gst-launch-1.0 artpecsrc ! video/x-h264,height=720,width=1280,framerate=30/1 ! kvssink
Let me know if you need more help with this or how far you're able to get and we can go from there.

@hassanctech  thank you for your assistance, really appreciated. We setup the AWS Producer SDK on a separate machine to the encoder, and can successfully pull an AXIS rtsp stream into the Producer and send it Kinesis Video Streams. So now it is just a case of getting it working on the encoder itself.

If gst-inspect-1.0 is on the machine (should already be in path) it will print out the version.

We can ssh onto the encoder, and can access gstreamer interactively.

Now you can build our kvssink plugin and as a test you can provide a pipeline via gst-launch-1.0 directly on the command line sending video frames to KVS (not your production solution but it's a good test to verify things are working).

I wanted to clarify on this point, are you suggesting here building a gstreamer on that specific flavour of linux/compilers because it is the same OS as that used on the AXIS encoder; and thus we could build externally using an EC2 instance setup like that (or presumably just a Docker container setup like that) and then use a tool like scp to transfer the built gstreamer plugin code onto the encoder ready for use?

gst-launch-1.0 directly on the command line sending video frames to KVS (not your production solution but it's a good test to verify things are working).

I also wanted to clarify why you say this would not be production worthy?
If we are using the encoder's native gstreamer install, I presume it would have access to any hardware acceleration from the encoder itself (i.e. their artpecsrc plugin) by default. Is it not production worthy because we have no way of restarting automatically on connection interruptions; something which is managed intelligently by the callbacks such as in the AWS provided gstreamer sample code here?
In general, we were wondering the best way to ensure that the stream will infinitely try to reconnect in case of internet failure- as we would like the producer to require little manual intervention once setup on a camera/encoder.

Some answers below.

You will need to cross-compile and then copy the libraries to your target platform
Production readiness depends on various criteria. I don't see any reasons why not but you will need to work with the hardware platform manufacturer to get your questions answered.
ContinuousCallbackProvider which is the default provider will attempt to re-connect and re-stream.

I am not sure if @hassanctech will have more info on this but we would try to keep the discussion to KVS specifics as we might not have the latest or most precise answers regarding Axis

Some answers below.

You will need to cross-compile and then copy the libraries to your target platform
Production readiness depends on various criteria. I don't see any reasons why not but you will need to work with the hardware platform manufacturer to get your questions answered.
ContinuousCallbackProvider which is the default provider will attempt to re-connect and re-stream.

I am not sure if @hassanctech will have more info on this but we would try to keep the discussion to KVS specifics as we might not have the latest or most precise answers regarding Axis

Some answers below.

You will need to cross-compile and then copy the libraries to your target platform

I see, I understand now, thank you.

Production readiness depends on various criteria. I don't see any reasons why not but you will need to work with the hardware platform manufacturer to get your questions answered.

One thing I am trying to understand is the distinction between sending a Kinesis stream via gstreamer directly:
A)
gst-launch-1.0 rtspsrc location=$YOUR_RTSP_STREAM short-header=TRUE user-id=$CCTV_USERNAME user-pw=$CCTV_PASSWORD ! rtph264depay ! h264parse ! kvssink stream-name=$AWS_VIDEO_STREAM_NAME access-key=$AWS_ACCESS_KEY secret-key=$AWS_ACCESS_SECRET_KEY aws-region=$AWS_REGION

and via the sample application:
B)
AWS_DEFAULT_REGION=$AWS_REGION ./kvs_gstreamer_sample $AWS_VIDEO_STREAM_NAME $YOUR_RTSP_STREAM

As both result in a stream to Kinesis. If I understand correctly, one difference is that the sample app includes various mechanisms to improve stream robustness in various cases, such as network failure? I am unclear whether @hassanctech  was also alluding to a benefit here for Method 2 with regards to hardware encoding capability.

ContinuousCallbackProvider which is the default provider will attempt to re-connect and re-stream.

I see this sounds like exactly what we would need; does this mean that even if the internet cut out for a very long time (e.g. hours or days), the sample application should restart indefinitely? Sorry if it is a foolish question, but I tried searching on github and AWS Kinesis docs for the strings ContinuousCallbackProvider and ContinuousCallback but could not find any docs or references to this string, so unsure where to look for documentation on how to ensure the stream will reconnect as best as it can indefinately.

I am not sure if @hassanctech will have more info on this but we would try to keep the discussion to KVS specifics as we might not have the latest or most precise answers regarding Axis

To give a bit of context on why I think this is relevant to this forum: We wish to scale our product using amazon web services to hundreds of facilities across the company, and currently, the blocker for this is a scalable way to get our video into the cloud. If we cannot install KVS Producer on the encoder; we would need to manage many EC2 instances to run the Producer, which would not be scalable and defeat most of the benefit of using KVS; and indeed we would need to look to non-AWS solutions.
AWS KVS staff have successfully tested KVS Producer SDK on an AXIS P3354 Fixed Dome Network Camera before,  and I understand that information might be precise or up-to-date, but its a great help to understand how this was achieved as it's likely to be very transferable to our case. I have already reached out to AXIS but as the questions, we have at the moment are mainly about understanding how KVS would link in with the hardware of the encoder; and given AXIS do not know anything about KVS, their unlikely to able to support here.
Very grateful for your support.

Some answers below.

You will need to cross-compile and then copy the libraries to your target platform

I see, I understand now, thank you.

Production readiness depends on various criteria. I don't see any reasons why not but you will need to work with the hardware platform manufacturer to get your questions answered.

One thing I am trying to understand is the distinction between sending a Kinesis stream via gstreamer directly:
A)
gst-launch-1.0 rtspsrc location=$YOUR_RTSP_STREAM short-header=TRUE user-id=$CCTV_USERNAME user-pw=$CCTV_PASSWORD ! rtph264depay ! h264parse ! kvssink stream-name=$AWS_VIDEO_STREAM_NAME access-key=$AWS_ACCESS_KEY secret-key=$AWS_ACCESS_SECRET_KEY aws-region=$AWS_REGION

and via the sample application:
B)
AWS_DEFAULT_REGION=$AWS_REGION ./kvs_gstreamer_sample $AWS_VIDEO_STREAM_NAME $YOUR_RTSP_STREAM

As both result in a stream to Kinesis. If I understand correctly, one difference is that the sample app includes various mechanisms to improve stream robustness in various cases, such as network failure? I am unclear whether @hassanctech  was also alluding to a benefit here for Method 2 with regards to hardware encoding capability.

ContinuousCallbackProvider which is the default provider will attempt to re-connect and re-stream.

I see this sounds like exactly what we would need; does this mean that even if the internet cut out for a very long time (e.g. hours or days), the sample application should restart indefinitely? Sorry if it is a foolish question, but I tried searching on github and AWS Kinesis docs for the strings ContinuousCallbackProvider and ContinuousCallback but could not find any docs or references to this string, so unsure where to look for documentation on how to ensure the stream will reconnect as best as it can indefinately.

I am not sure if @hassanctech will have more info on this but we would try to keep the discussion to KVS specifics as we might not have the latest or most precise answers regarding Axis

To give a bit of context on why I think this is relevant to this forum: We wish to scale our product using amazon web services to hundreds of facilities across the company, and currently, the blocker for this is a scalable way to get our video into the cloud. If we cannot install KVS Producer on the encoder; we would need to manage many EC2 instances to run the Producer, which would not be scalable and defeat most of the benefit of using KVS; and indeed we would need to look to non-AWS solutions.
AWS KVS staff have successfully tested KVS Producer SDK on an AXIS P3354 Fixed Dome Network Camera before,  and I understand that information might be precise or up-to-date, but its a great help to understand how this was achieved as it's likely to be very transferable to our case. I have already reached out to AXIS but as the questions, we have at the moment are mainly about understanding how KVS would link in with the hardware of the encoder; and given AXIS do not know anything about KVS, their unlikely to able to support here.
Very grateful for your support.

GStreamer is a framework. gst-launch-1.0 application is just that - an application that allows construction and execution of pipelines.
The difference between a full application and a gst-launch based solution is that in application you are free to do anything you want whereas in gst-launch you can only "fire and forget" pretty much.
Regarding the continuous retry. I would simply suggest running the sample and turning off the network, after a while, turn it back on. It should pick up and stream. There will be dropped frames as the buffer gets overflown.
Installing KVS producer solution on Axis is not something we directly support but I hope that people in the community could help.

GStreamer is a framework. gst-launch-1.0 application is just that - an application that allows construction and execution of pipelines.
The difference between a full application and a gst-launch based solution is that in application you are free to do anything you want whereas in gst-launch you can only "fire and forget" pretty much.
Regarding the continuous retry. I would simply suggest running the sample and turning off the network, after a while, turn it back on. It should pick up and stream. There will be dropped frames as the buffer gets overflown.
Installing KVS producer solution on Axis is not something we directly support but I hope that people in the community could help.

@bml1g12 I can definitely assist and getting an application running on the encoder which will stream to KVS.  First question is is your company able to join:  https://www.axis.com/support/developer-support/axis-camera-application-platform.
Once you do this you'll have access to their Axis SDK and cross compile tool chain.  Certain Axis models (yours included) support program installation via this program.  They actually make it very easy for you to build applications for their platform and provide a way for you to programmatically (via the VAPIX web API's that Axis encoders/cameras provide) to install the software on the camera/encoder and to set parameters relative to your application and to start/stop the applications.
You are correct artpecsrc will use the hardware encoder, that was not a concern of mine for using GStreamer.
gst-launch provides a way to construct a pipeline on the fly but it's limited, for example you may want a callback function for a particular element, you cannot do this on the command line you would actually need write a C program, there are a plethora of examples out there and I can guide you to some if you need help with this.
The embedded SDK will allow you to access the encoded frame which you can then send to KVS back-end via our Producer C SDK (https://github.com/awslabs/amazon-kinesis-video-streams-producer-c), no GStreamer required, you will have to set up callbacks yourself but you can pretty much copy the callback implementations from what the kvssink plugin does.  The real benefit to this is in the case Axis decides one day to remove GStreamer from their cameras/encoders, you will not all of a sudden be out of a solution (it could happen one day when you decided to upgrade your firmware to take in a security patch for example, Axis provides no guarantees that GStreamer will be on there).  However if you wish to take that as an acceptable risk to deal with that when the problem comes (i.e. GStreamer suddenly removed from their cameras), then you would need to compile the kvssink plugin and put it on the camera/encoder and load it into your application and construct a simple pipeline.

@bml1g12 I can definitely assist and getting an application running on the encoder which will stream to KVS.  First question is is your company able to join:  https://www.axis.com/support/developer-support/axis-camera-application-platform.
Once you do this you'll have access to their Axis SDK and cross compile tool chain.  Certain Axis models (yours included) support program installation via this program.  They actually make it very easy for you to build applications for their platform and provide a way for you to programmatically (via the VAPIX web API's that Axis encoders/cameras provide) to install the software on the camera/encoder and to set parameters relative to your application and to start/stop the applications.
You are correct artpecsrc will use the hardware encoder, that was not a concern of mine for using GStreamer.
gst-launch provides a way to construct a pipeline on the fly but it's limited, for example you may want a callback function for a particular element, you cannot do this on the command line you would actually need write a C program, there are a plethora of examples out there and I can guide you to some if you need help with this.
The embedded SDK will allow you to access the encoded frame which you can then send to KVS back-end via our Producer C SDK (https://github.com/awslabs/amazon-kinesis-video-streams-producer-c), no GStreamer required, you will have to set up callbacks yourself but you can pretty much copy the callback implementations from what the kvssink plugin does.  The real benefit to this is in the case Axis decides one day to remove GStreamer from their cameras/encoders, you will not all of a sudden be out of a solution (it could happen one day when you decided to upgrade your firmware to take in a security patch for example, Axis provides no guarantees that GStreamer will be on there).  However if you wish to take that as an acceptable risk to deal with that when the problem comes (i.e. GStreamer suddenly removed from their cameras), then you would need to compile the kvssink plugin and put it on the camera/encoder and load it into your application and construct a simple pipeline.

Thank you for your support.

The difference between a full application and a gst-launch based solution is that in application you are free to do anything you want whereas in gst-launch you can only "fire and forget" pretty much.

I see yes, it does seem like calling gstreamer directly would be problematic in that it would not auto-recover from internet downtime; and as I understand also has no native support for sending multiple streams to kinesis (as we have an encoder with 4 cameras attached). So we'll look into Producer SDK as the more robust solution.

First question is is your company able to join: https://www.axis.com/support/developer-support/axis-camera-application-platform.

Yes we have joined this, although it will take us a few weeks to gain familiarity with the ACAP SDK.

You can then send to KVS back-end via our Producer C
Would the AWS C++ flavour of the producer SDK be equally suitable here? Ah but I see AXIS recommend C for ACAP, so that's probably why you suggested C here.

As this will now become mostly a C/C++ programming exercise, a colleague of mine (@huysc0ville) who is more familiar with the language will likely be taking us this task over the following weeks.

you would actually need write a C program, there are a plethora of examples out there and I can guide you to some if you need help with this.

Yes please, are you referring to this and this for example?
As we have 4 cameras per AXIS encoder, it sounds like the multistream example here would be suitable for us, is there an official sample application for the C producer SDK for dealing with multiple streams? We have so far setup a Dockerfile that runs the Producer using the C++ sample, but I notice the samples in the C repo look a little different.

The embedded SDK will allow you to access the encoded frame which you can then send to KVS back-end via our Producer C SDK

I personally don't yet have a clear picture in my head how we would pass the AXIS SDK frame into KVS backend Producer SDK, but part of this may be that I am not a confident C developer, and haven't yet studied the AXIS SDK in detail.
Would it, as an example, be a case of feeding frames from this AXIS demo  into this AWS Producer SDK sample?

Thank you for your support.

The difference between a full application and a gst-launch based solution is that in application you are free to do anything you want whereas in gst-launch you can only "fire and forget" pretty much.

I see yes, it does seem like calling gstreamer directly would be problematic in that it would not auto-recover from internet downtime; and as I understand also has no native support for sending multiple streams to kinesis (as we have an encoder with 4 cameras attached). So we'll look into Producer SDK as the more robust solution.

First question is is your company able to join: https://www.axis.com/support/developer-support/axis-camera-application-platform.

Yes we have joined this, although it will take us a few weeks to gain familiarity with the ACAP SDK.

You can then send to KVS back-end via our Producer C
Would the AWS C++ flavour of the producer SDK be equally suitable here? Ah but I see AXIS recommend C for ACAP, so that's probably why you suggested C here.

As this will now become mostly a C/C++ programming exercise, a colleague of mine (@huysc0ville) who is more familiar with the language will likely be taking us this task over the following weeks.

you would actually need write a C program, there are a plethora of examples out there and I can guide you to some if you need help with this.

Yes please, are you referring to this and this for example?
As we have 4 cameras per AXIS encoder, it sounds like the multistream example here would be suitable for us, is there an official sample application for the C producer SDK for dealing with multiple streams? We have so far setup a Dockerfile that runs the Producer using the C++ sample, but I notice the samples in the C repo look a little different.

The embedded SDK will allow you to access the encoded frame which you can then send to KVS back-end via our Producer C SDK

I personally don't yet have a clear picture in my head how we would pass the AXIS SDK frame into KVS backend Producer SDK, but part of this may be that I am not a confident C developer, and haven't yet studied the AXIS SDK in detail.
Would it, as an example, be a case of feeding frames from this AXIS demo  into this AWS Producer SDK sample?

Are you currently able to extract 4 separate streams from the Axis SDK?

We have yet to start much development on the AXIS side; but I have already inquired to AXIS if they have an example of this we could work from. If they are unclear, I can imagine it would be viable for us to start with an "application" or process running for each camera given the low CPU footprint usage of the current code, although less clear on memory footprint.
Thanks, it sounds like we aught to developing with the AWS Kinesis C SDK but so far have only used C++ one; do you have a sample code for that for use with RTSP stream input? (I appreciate it's not the same code we would need on the AXIS encoder; but before we try and run it on the AXIS encoder, would be good to get the AWS C Kinesis SDK running on a separate machine as we have already done using the C++ SDK.). I think this sample is based on reading from frames on disk if I understand correctly.

Are you currently able to extract 4 separate streams from the Axis SDK?

We have yet to start much development on the AXIS side; but I have already inquired to AXIS if they have an example of this we could work from. If they are unclear, I can imagine it would be viable for us to start with an "application" or process running for each camera given the low CPU footprint usage of the current code, although less clear on memory footprint.
Thanks, it sounds like we aught to developing with the AWS Kinesis C SDK but so far have only used C++ one; do you have a sample code for that for use with RTSP stream input? (I appreciate it's not the same code we would need on the AXIS encoder; but before we try and run it on the AXIS encoder, would be good to get the AWS C Kinesis SDK running on a separate machine as we have already done using the C++ SDK.). I think this sample is based on reading from frames on disk if I understand correctly.

@bml1g12 ,
You are correct, the sample is based on reading from frames on disk. Unfortunately, we do not have a C producer sample with RTSP camera.

OK that's a shame, thank you for this information. I will close this issue for now.


[eng] dashed pronunciations

The English data contains roughly 300-400 entries where the pronunciation is given incompletely, with a dash at the beginning, middle, or end of the entry (usually indicating that we're supposed to fill in the rest of the pronunciation ourselves). Some examples:
arabica ə - ɹ ă b ĭ - k ə
observer    ɒ b -
fornicatory - t o ʊ ɹ i

I would propose that we should remove all these punctuations and can do so on a language-independent basis.

If we want to remove the dashes we could do it as a post-processing step or we could expand yield_pron() to do so. yield_pron() already removes parentheses.

To be very clear, we should remove any entries that contain dashes on the graphemic side---not merely remove the dash.


Polygon outlineWidth property is ignored

While running this code:
Cesium.Math.setRandomNumberSeed(1234);

var viewer = new Cesium.Viewer('cesiumContainer', { infoBox : false });
var entities = viewer.entities;
var positions = Cesium.Cartesian3.fromDegreesArray([
            -107.0, 31.0,
            -107.0, 39.0,
            -97.0, 39.0,
            -97.0, 31.0
        ]);

entities.add({
    polygon : {
        height: 0,
        hierarchy : new Cesium.PolygonHierarchy(positions),
        material : Cesium.Color.BLUE,
        outline: true,
        outlineColor: Cesium.Color.RED,
        outlineWidth: 50
    }
});

viewer.zoomTo(viewer.entities);

Note the outlineWidth set to 50, which should draw a fairly thick outline.
But the outline is fairly thin, and doesn't change if you modify the value to something else, say 1, or 200.

Hello @pierotofy,
Sorry, but line width is something that is dependent on the browser's WebGL implementation, so it's a little beyond our control.
I believe a wider line is currently only supported on Safari?  I'm not quite sure.

Should this be mentioned somewhere in the docs?

See this post: http://stackoverflow.com/a/25405483/3191039  It's a limitation of the WebGL implementations on Windows (but is completely in spec).  It works on standard OpenGL implementations (which means phones, Linux, Mac, and etc.)
The maximum value on the current system is documented and exposed via scene.maximumAliasedLineWidth and this limitations is also mentioned in our Visualizing Spatial Data tutorial.

Ok! Thanks to both for the info!


grunt: cleanup no-edge targets

edge_sdp.js moved out into the sdp module quite a while ago.

LGTM


Update Lab_16_UsingAzureKeyVaultForManagedIdentities.md

multiple changes, Update steps to Task 5 - Access data with Key Vault secret with PowerShell for clarity
Module: 00
Lab/Demo: 00
Fixes # .
Changes proposed in this pull request:

Made updates to change this lab separate, but this should be fixed.


BIGTOP-3537. Fix puppetize.sh to work with the latest CentOS 8 Docker image (addendum).

https://issues.apache.org/jira/browse/BIGTOP-3537

I'm going to merge this since the preceding PR (#771) was incomplete.


feat: arm64 cloud releases

@yangky11, your comment in #7 lead me to realize there already is a way to augment the name of a cloud release, so LeanInfer can just support arm64 releases directly!

Great! I'll try. Thanks!


feat: family wallet

What does this PR do and why?
Provide a description of what this PR does. Link to any relevant GitHub issues, Notion tasks or Discord discussions.
Screenshots or screen recordings
If applicable, provide screenshots or screen recordings to demonstrate the changes.
Acceptance checklist

[ ] I have evaluated the Approval Guidelines for this PR.
[ ] (if relevant) I have tested this PR in all supported browsers.
[ ] (if relevant) I have tested this PR in dark mode and light mode (if applicable).

Current dependencies on/for this PR:

main

PR #4000

PR #3997

PR #4001

PR #4002

PR #3998

PR #3999

PR #4004   👈

This comment was auto-generated by Graphite.

Closing for now, Web3-onboard recently supports wagmi, so we should be able to stick with it: https://www.blocknative.com/blog/announcing-wagmi-support-in-web3-onboard-elevating-your-dapps-wallet-experience


Add Vault Cache and Exponential Backoff for Login

Add a cache to the Vault credentials manager. The cache is flagable
and defaults to off. The cache uses the vault set lease duration and
re-fetches secrets halfway to the expiration time.
Add an exponential backoff for login and renewal of vault credentials.
This slows down spam to vault in the event of a bad configuration or
during heavy load. This backoff starts at 1 second and max's out at 64
seconds. This is currently not configurable.
As part of the change refactor so to test both the cache and the retry
strategies. Add unit tests to this effect. It also adds more comments
in the code and cleanups up some go naming stuff.
This change has not been tested with a full deployment yet (I think the  PR will do that for me? ;p)
This is needed because if a user configures secrets in to be passed as params to a check resource it
is trivial to inadvertently attack your own secrets infrastructure.
I considered trying to add a "meta" credentials cache, but I'm not sure that a single caching strategy/manager will be able to correctly abstract all possible credential stores expected caching behaviors. For example k8s already has a  sophisticated caching mechanism available in its standard library.

@rfliam Please sign the Contributor License Agreement!
Click here to manually synchronize the status of this Pull Request.
See the FAQ for frequently asked questions.

@rfliam Thank you for signing the Contributor License Agreement!

Adding caching at the application level may be masking the issue. It seems your vault deployment might need to be scaled out to handle the traffic coming into it. Though concourse is causing the load, delegating a caching layer just for vault doesn't seem right to me.
What have you tried actually scaling out vault?

Our vault instance could handle the load, it is just completely unnecessary. The vault API is designed to use caching. That is why lease_duration exists. Most vault clients feature it.
Concourse is doing the "wrong thing" by not caching a secret that is intended to be cached.

/cc @eugenMayer - this PR would probably make you happy
also ref. https://github.com/hashicorp/vault/issues/3651
Kind of a bummer that there's no blessed Go client that implements this kind of functionality; I was hesitant to implement it ourselves because caching credentials sounds like a bad idea if there's no precedent or strong need for it. But it sounds like there's a means for it via Vault's API, and precedent in other popular libraries, though it's still kind of a bummer that we have to implement the caching ourselves.
Given that, I want to be super careful about this and make sure we're taking into consideration any "gotchas" with the implementation (e.g. accidentally using an expired credential after it's been rotated, etc.), and any security risks involved (e.g. holding all the secrets in the ATC's head). I say this having not yet reviewed the code in detail.
Are there other Go consumers of Vault we can look to as an example? Have other projects run into this pain point?

Agreed on the go client not having caching being a bit of a bummer. But on the other hand the nature of the cache is probably use case specific anyways. Concourse for example is a read mostly cache. Requests for previously un-requested secrets are going to be very low.
Hence having a cache focused on fast reads and low memory overhead for concourse makes sense. We could use golang-lru from hashicorp but it doesn't actively purge records and does cache eviction on the main thread.
The cache I implemented is very efficient for this use case, only performing maintenance when keys expire. However it does not have a strict upper bounds in memory size. This is a complicated matter for vault secrets as they are of arbitrary size so having a max number of secrets only helps some in preventing large memory footprints.
It's also worth mentioning it looks like the original code re-implemented renewer and I followed suite. So that should probably be changed out.

Hi there,
A long while back Vault did in fact issue leases for the generic (now kv) backend but we took that out because it was causing problems with exactly the kind of behavior that Concourse displays -- refreshing from each client once a second was a really great way to generate a massive number of leases and bring Vault crashing down. We kept the ability for the writer to round-trip a lease duration, with the idea that the writer often knows how often they're going to write new values, so it can use that value as an expected lifetime hint for readers.
What we usually see is that people will set a value for the lease duration that is significantly less than the actual expiration, but large enough to not cause high load. For example, let's say you rotate a credential every 12 hours and keep the old one active for 2 hours to allow clients to adjust. The writer of the credential may set the lease duration to 90 minutes, which should be enough time for all clients to retrieve the new value (with 5399 less reads from Vault per client in the interim compared to checking every second :-D ).
Although the API could do local caching, you'd need to know how long the cache should hold that value anyways, and still be capable of retrieving new values when outside the caching period. So a built-in cache doesn't buy you much other than the ability to continue checking every second instead of simply setting your timer to check at the interval given by the secret.
Eventually we hope to add an eventing API, but it's not going to appear in a "soon" timeframe. If your underlying data store supports an eventing API you could do some mapping of Vault storage to data store storage and use an event on the underlying data store path to trigger a re-read from Vault clients, but I would generally avoid that unless absolutely necessary for your use-case.

@jefferai Thanks for helping us figure this out!
I think there's one thing to clarify: Concourse doesn't ever explicitly refresh anything or do anything special with leases, let alone refresh once a second. We fetch a credential any time we need it, and throw it away when we're done with it.
Here's what's happening on Concourse's side:

Say a user has configured a resource in their Concourse pipeline (resources are just YAML config representing an integration point, i.e. a Git repo or an S3 bucket). Say this resource has a configuration pointing to ((private_key)).
Concourse periodically performs a check operation on every pipeline resource, by default once per minute. This is to discover things like new commits to said Git repo.
If a resource has a ((parameter)), every time we check we'll resolve those parameters by fetching them from Vault.
We run the resource's check script, passing it the resource's configuration, with the parameterized credentials filled with the values fetched from Vault.

After running the check script, we don't do anything with the credentials - in fact, they're out of the ATC's head as soon as we've started running the script. Once the checking interval fires again, we'll just fetch the credentials anew. If they're rotated, we'll have the new values. Or, a user may have reconfigured the pipeline in the meantime, and we may be fetching a new set of credentials. Who knows!
So from Concourse's perspective, these credentials are short-lived. They aren't used throughout the duration of the Concourse server running, for example. The stack is stateless, so we don't have any 'refreshing' mechanism, we just don't use the credentials for very long in the first place.
Considering that, and given the existence of lease durations as a way for the credential writer to convey a safe validity window (separate from expiry), this feels like a generic client-side cache. I'm just worried about us being the ones to write it. ;)
...And quite worried that this may result in a single process that contains literally all of the credentials for all of the pipelines and all of the teams in its head. Not as a question of memory usage, but as a question of risk, and to what extent that defeats the point of using Vault in the first place.

Hi @vito
Thanks for the explanation, that helps me understand what Concourse is doing here.
Not going in order:

...And quite worried that this may result in a single process that contains literally all of the credentials for all of the pipelines and all of the teams in its head. Not as a question of memory usage, but as a question of risk, and to what extent that defeats the point of using Vault in the first place.

I can't really help you assess whether that risk is acceptable or not, but it's certainly a better stance than persisting to disk. Using Vault helps sort out the "not persisting to disk in plaintext" part of the equation (and a lot of other functionality), so even if you are caching things on the client side you're still getting benefit.

The stack is stateless, so we don't have any 'refreshing' mechanism, we just don't use the credentials for very long in the first place.

Between this and the other discussion of client side caching, I'm a bit confused -- do you keep your API clients around? If so that's not really stateless, but if not, I don't really see how caching in the clients will help.

@jefferai

I can't really help you assess whether that risk is acceptable or not, but it's certainly a better stance than persisting to disk. Using Vault helps sort out the "not persisting to disk in plaintext" part of the equation (and a lot of other functionality), so even if you are caching things on the client side you're still getting benefit.

We're still getting a lot of benefit from Vault in plenty of ways, I'm just wary of any step back we may make in security.  Either way it's on us to characterize the risk involved and figure out what we can/should do.

Between this and the other discussion of client side caching, I'm a bit confused -- do you keep your API clients around? If so that's not really stateless, but if not, I don't really see how caching in the clients will help.

Sorry, all I meant by stateless was that the credentials themselves aren't e.g. stashed in an object somewhere in need of periodic refreshing. They're fetched and then thrown away. Though I guess that's how a lot of Vault consumers work anyway. We do probably have a single API client, so caching would be fine.

Hi @vito,
Thanks for the explanation. If you do work on a caching system I'd love for it to be in the API client since I think others could benefit. I have a couple thoughts around it:

One way might be to allow the Renewer function in the API to work on secrets that don't have a lease ID by providing a function that can be run to generate a new Secret. That way the renewer can look at the lease duration and know that after e.g. 95% of the duration has expired, run the function to fetch a new one. (It would also allow the renewer to fetch new secrets generally, rather than only renew them.)

Much of Consul-Template got pulled into a library a while back, which is how it's embedded into Nomad. Based on a template it knows how to fetch (and appropriately handle refetching) for a large variety of Vault secrets. The downside is that templates have to be written to use it.

Probably the first option would be the way to go for now. I do think there should be controls around disabling caching, perhaps on a per-secret (or per-path?) basis, in case the duration that comes back can't be trusted (or some secret shouldn't be kept around in memory).

Some Design Thoughts:
Current Security Model and Risks
Currently concourse keeps secrets for all team accessible by a single login managed in the ATC. If an attacker achieves some sort of "escalation" he can pull that token, clieky key, and client cert and access all secrets for all teams. While this information is not kept in memory, the token is, and it would still be readily available.
Escalation for this token is somewhat difficult as it requires attacking the ATC. The "exploit vector" here is largely through the ATC API. The most common methodology here would be to dump the heap or the configuration of the ATC.
Exploits that escalate using containers in pipeline steps are prevented from attacking the ATC if it is run on physically isolated nodes (this is probably a best practice for the future). However, privilege escalations on a worker could be used to attack other pipelines secrets that happen to be local. If the ATC is local this could also be attacked.
The Impact of Caching
Maintaining secrets in memory offers an increased risk in "timeliness" of attack. If the client certificate is ip addressed pinned or the ATC but not the secrets back end is accessible this voids some of its benefits. With a cache a user must only dump the heap to access the secrets as opposed to dumping the heap repeatedly, as secrets are in flight.
In practice this additional risk is low as most heap dumps are the result of existing remote code execution which can be crafted to attack these secrets directly.
Possible Changes
Per-Pipeline Secrets Management
Maintaining a per team or per pipeline login to vault could help reduce the magnitude of any breach. The secrets configuration could be set on the pipeline rather then globally for the ATC. The trade off is this information would have to be persisted. However, the secrets back-end could be used for this. The ATC would be configured with a secrets back-end in which to store and access the pipeline specific secrets config.
Changing Where and How Secrets Access Works
Another increase in security would be from "splitting" the secrets access and decryption. In this model the access to the secret would reside with the ATC or Pipeline, but the secret itself would be further [encrypted with the private key of the worker]. The ATC would access the secret and forward it the worker which would then decrypt the secret for use. This adds some security as it requires a working exploit on both the worker and the atc.
Add Build Signing
One thing I would love to see is the addition of a build singing infrastructure. In this infrastructure tasks could request that concourse sign a resource with it's private keys so traceable builds could be used. Another usage would be requiring deployments to come from the build infrastructure itself, signing deployment requests with the build infrastructures private keys.
[1] More correctly the secret would be stored with a randomly generated AES encryption key, and that key would be encrypted with the workers public key.
Proposals
Add the Cache (in the Vault Code)
Compared to today's model the cache is only a minor increase in risk. However, it is nearly required for most secrets backends. As evidenced by #233 and vault#3651 secrets without caching can cause significant problems.
I very much like jefferai's suggestion to disable caching on a per path basis.
Future
Look towards per-pipeline secrets and build signing first IMO. But that's up to you guys.

A couple of comments:

The trade off is this information would have to be persisted. However, the secrets back-end could be used for this. The ATC would be configured with a secrets back-end in which to store and access the pipeline specific secrets config.

You may want to think about using transit for this -- either directly for encryption/decryption or to allow dissemination of an encrypted data key that a worker can decrypt via transit and hold locally in memory.

One thing I would love to see is the addition of a build singing infrastructure. In this infrastructure tasks could request that concourse sign a resource with it's private keys so traceable builds could be used. Another usage would be requiring deployments to come from the build infrastructure itself, signing deployment requests with the build infrastructures private keys.

Just in case you haven't seen it, transit also has three different key types that can be used for signing (rsa, ed25519, ecdsa-p256) :-)

BTW, I just mention the signing since the text discusses workers' private keys; I'm not sure how those are disseminated/stored, but if they already have a Vault token, then you could just keep the keys in Vault and guard access to it.

Another thought here:
The cache can use memguard to help prevent buffer overflow attacks.

Be careful with that line of thinking -- Go already prevents such attacks (subject to things working the way they're supposed to) by taking memory management out of your hands. memguard needs to advertise buffer overflow protection because it works around Go's memory management, which opens it up to a host of potential attacks that it then needs to mitigate.
I've been watching memguard for a while, and while I think it's an interesting library, as far as I can tell the main use of memguard is if you are concerned about values living for long periods in memory after you've given them up and don't want to try mitigating by periodically triggering garbage collections in Go. It won't stop someone that has root from getting your memory -- it will just make it harder via obfuscation.
Unless you feel super strongly about needing memguard, I'd just use something that supports expiry and/or running functions on eviction like https://github.com/patrickmn/go-cache or similar.

I considered trying to add a "meta" credentials cache, but I'm not sure that a single caching strategy/manager will be able to correctly abstract all possible credential stores expected caching behaviors. For example k8s already has a sophisticated caching mechanism available in its standard library.

I'm a k8s user. I'd be happy with a simple caching strategy that applied to all credential managers, with a configurable TTL defaulting to 60 seconds. k8s secrets don't convey anything around expiry, and giving watch or list permissions to implement anything fancier for caching should be avoided:
https://kubernetes.io/docs/concepts/configuration/secret/#best-practices

For these reasons watch and list requests for secrets within a namespace are extremely powerful capabilities and should be avoided, since listing secrets allows the clients to inspect the values if all secrets are in that namespace. The ability to watch and list all secrets in a cluster should be reserved for only the most privileged, system-level components.

There is also a PR to fix the k8s secret lookup so that access to all secrets in a namespace isn't assumed: https://github.com/concourse/atc/pull/233.

Just chiming in to say we haven't forgotten about this, we're just working on getting 3.9 out the door before merging this in as it's already pretty huge. Thanks for your patience!

Addressed comments from code reviews. Added that flagable max lease duration for the cache per @EugenMayer .

Added.

Seems like this is causing 3 TopGun tests to fail consistently:

https://ci.concourse-ci.org/teams/main/pipelines/main/jobs/topgun/builds/1187
https://ci.concourse-ci.org/teams/main/pipelines/main/jobs/topgun/builds/1188
https://ci.concourse-ci.org/teams/main/pipelines/main/jobs/topgun/builds/1190
https://ci.concourse-ci.org/teams/main/pipelines/main/jobs/topgun/builds/1191

Will take a closer look.

Found a couple problems.
First problem: code was blocking on <-loggedIn in the variables factory, because this channel would only  be written to upon logging in. I've changed this to a channel that's closed the first time we successfully log in, so these channel reads will never block again.
Second problem: when copying the Vault client and setting a token, I observed a deadlock in the stack that happened because copying the client also copies its mutexes (they're non-pointer values, relying on the struct), and it happened to copy it while the mutex was locked. I'm gonna find a better way to do this since it already had a TODO with a warning on it. The warning was right!

Use https://godoc.org/github.com/hashicorp/vault/api#Client.Clone instead of copying a client.

Can I ask -- is there a reason you wrote ReAuther instead of using https://godoc.org/github.com/hashicorp/vault/api#Renewer ?


Add EKS-D to the resources page

Add EKS-D in the related resources page - https://aws-otel.github.io/resources

Closing this issue because changes are reflected in https://github.com/aws-otel/aws-otel.github.io/pull/43.


Add sctp support for network performance test

The SCTP protocol can be tested using the same iperf3 client command line as the TCP protocol with the addition of a single parameter (--sctp).  The test parameters and output are otherwise the same as the TCP protocol.
Changed the Dockerfile definition to pull and rebuild and the latest stable version of iperf-3.1, because the current iperf-3.0 does not support SCTP.

/assign @timothysc

/ok-to-test
/lgtm
/approve


v4: menu: menu closes when taping in an higher component

Bug Report
Ionic Info
Run ionic info from a terminal/cmd prompt and paste the output below.
Ionic:

   ionic (Ionic CLI)          : 4.0.0-rc.11 (C:\Users\nico9\AppData\Roaming\npm\node_modules\ionic)
   Ionic Framework            : @ionic/angular 4.0.0-alpha.11
   @angular-devkit/core       : 0.7.0-rc.3
   @angular-devkit/schematics : 0.7.0-rc.3
   @angular/cli               : 6.0.8
   @ionic/ng-toolkit          : 1.0.0-rc.11
   @ionic/schematics-angular  : 1.0.0-rc.11

System:

   NodeJS : v10.3.0 (D:\Program Files\nodejs\node.exe)
   npm    : 6.1.0
   OS     : Windows 10

Describe the Bug
When clicking in an action sheet(like the dialog of ion-select) or popover opened from menu, the menu closes when taping inside the alert.
Steps to Reproduce
Steps to reproduce the behavior:

Create new blank starter project with following page template:

<ion-menu side="start" swipeEnabled="false" contentId="menuContent">

  <ion-header>
      <ion-toolbar color="primary">
          <ion-title>The menu</ion-title>
      </ion-toolbar>
  </ion-header>

  <ion-content id="menuContent">
      <ion-list>
          <ion-item lines="full">
              <ion-label style="color: black">Language</ion-label>
              <ion-select>
                <ion-select-option>EN</ion-select-option>
                <ion-select-option>DE</ion-select-option>
              </ion-select>
          </ion-item>
      </ion-list>
  </ion-content>
</ion-menu>
<ion-header>
  <ion-toolbar>
    <ion-menu-button slot="start"></ion-menu-button>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  The world is your oyster.

If you get lost, the docs will be your guide.

</ion-content>

Open the menu and click on the select item "language"
Tap inside the displayed alert

As you can see the menu closes and the alert don`t respond to the tap.
Related Code
/core/src/components/menu/menu.tsx  line 190
...
 @Listen('body:click', { enabled: false, capture: true })
  onBackdropClick(ev: any) {
    const path = ev.path;
    if (path && **!path.includes(this.menuInnerEl)** && this.lastOnEnd < ev.timeStamp - 100) {
      ev.preventDefault();
      ev.stopPropagation();
      this.close();
    }
  }
...

The marked condition should check if the backdropElement of the menu is included in the path, to ensure it wont fire when the user interacts with "higher" components(modals, popovers, alerts etc.) than the menu.
Expected Behavior
When interacting with an "higher" component the menu should stop fire its backdrop click.
Additional Context
I´ll add a pull request.

+1

This Happens to me too, please fix this issue, it happens when pressing on toast, alert, and modal..

+1

I closed my pr for this since there were a lot of changes to ionic. Is this still an issue for you @Dasone  @maziTR  @charlesj1 or can i close this issue?

@tntwist It got resolved with the last update 👍

Yep, all better now. Thanks for raising the issue @tntwist


Important Notice About PRs and Issues

Due to this being a submission to GMTK Game Jam 2022, pull requests will not be merged and issues will not be patched until the one week rating period is over. Please feel free to submit PRs and issues anyway, they will be merged/patched at some point.

Issues will now be fixed and PRs will be merged.


Nonexistent Passage warning Quickfix

It would be nice to use some existing simple text similarity algorithm to make so if the user types an incorrect passage, we can provide an option to correct it to what they probably meant.
Ex: User writes <<goto "island">> when what they meant was to use their passage named "Island". This case is simple case insensitive checking and would be easier to implement.
But typos are also common, so I think a text similarity library should be used to provide the best results. Possibly allow multiple results, if possible, though I'd limit it to like three or so.
This would make using it better, since then they don't have to scan for where in the name they made the error, and just use ctrl + . and correct it.
This would probably be unique to sugarcube-2, but it would be nice to make it generic enough to work for Harlowe and other formats if we ever properly add passage validity checking to them.

👺 force lower case passage names.
I like the idea of the extension being smart about passage names but I do wonder if it will slow it all down.

japanese_goblin force lower case passage names.
I like the idea of the extension being smart about passage names but I do wonder if it will slow it all down.
Not sure if less resource hogging but can't we give a list of all passages in a drop down if misspelled passage name? or a create passage feature.. .

Showing all passages in the dropdown would be slow and also not that useful. I'm not even sure if VSCode even supports over a hundred entries in the quickfix dropdown.
It might cause some slow down on large projects (because then it has to do the text similarity algo on every single passage name), but for a lot of projects it would be perfectly fine. Though, like other features which take some processing to do, this would be behind a setting that allows you to disable it if it is a problem.


Add Pergamon Agora

Showcase addition

Name: Pergamon Agora
Description: An on-chain auction house for Cardano NFTs
Link:   https://beta.pergamon.app
Source:
Tags:

metadata
nativetoken
nft

Hi there @katomm,

I cannot understand what you mean with "traction" would you mind elaborating? There is no indication that contributions need to do anything in terms of traction
This is a dApp, not a token. What made you think we are talking about a token?


Always fail in feature gate

Hi, I am using NextJs and adopting feature gate with react-sdk. However, my gate value is always fail although my setting has 50% fail rate. I suspect this is related to my asynchronous init of StatsigProvider. Can you verify my implementation is alright?
_app.js
function MyApp(props) {

  const [userID, setUserID] = useState('')
  useEffect(()=>{
    let u = localStorage.getItem('take-app-user-id') || ''
    if (!u) {
      u = Math.random().toString(36)
      localStorage.setItem('take-app-user-id', u)
    }
    setUserID(u)
    console.log(u)
  }, [])

...

  return (
    <React.Fragment key="react_fragment">
      <StatsigProvider
        sdkKey={process.env.NEXT_PUBLIC_STATSIG_CLIENT}
        user={{
          userID,
        }}
      >
  ...
)

Main.js
export default function Shop(props) {
    ...
    const statsig = useStatsig();
    useEffect(()=>{
        statsig.logEvent("page_view", shop_name)
    })

   ...

    const gate = useGate('adsense2');
    const [showAdsense, setShowAdsense] = useState(true)
    useEffect(()=>{
        setShowAdsense(gate.value)
    }, [gate])

In this example, showAdsense value is always false

@youminkim - you're right this could be due to the async initialization.  We will debug this; @jkw-statsig understands your requirements, so we'll respond with a solution that fits your needs in the morning.

On the provider:
<StatsigProvider
        sdkKey={process.env.NEXT_PUBLIC_STATSIG_CLIENT}
        user={{
          userID,
        }}
      >

You should specify the waitForInitialization=true property if you want to only render the remainder of the app after Statsig has initialized.  The other option is to not wait for initialization at the root, and instead use fetchGate to await asynchronously at the callsite.

waitForInitialization=true means blocking the website rendering?
fetchGate may I know how to use?
I am not sure if this is possible but I prefer the way to update userID. For example, a customer who initially did not login can login in the website and we need to update userID

@youminkim is there a way for you to set a generate a unique id on server side and set it as a cookie so subsequent requests from the client would carry that same id?

@youminkim if you do not want to wait for initialization in StatsigProvider, you can set the value to be false there so that it does not block rendering, and replace your current useGate call with fetchGate, because fetchGate is async, you should call it within useEffect like this:
    const [showAdsense, setShowAdsense] = useState(true)
    useEffect(()=>{
        fetchGate('adsense2').then((gate) => setShowAdsense(gate.value))
    })

Regarding your question about updating userID, I think there are 3 scenarios and here are my thoughts:

user A (new user) visits your site while logged out, and then registers during the session - ideally you use the same user ID you generated for them before & after registration.

user A (returning user) visits your site while logged out, then logs in, and the IDs are different - you can call updateUser to switch the user and we will log future events under the new ID. However, currently there isn't a way to associate events from the previous ID with the new ID. We have plans in place to introduce an API to do that so you can associate events from two different IDs together.

user A visits your site, then switches to user B. In this case you can just use updateUser mentioned above.

Is #2 the scenario you are talking about here? We'll provide an update once we have that feature implemented.
Hope this helps! Let us know if you have any more questions.

We have discovered an issue with the SDK when you do not pass waitForInitialization=true and we are working on a fix

Published SDK version v0.3.0 this afternoon.  This removes the fetchGate/fetchConfig/fetchExperiment parameters.  I am updating the documentation now, but my suggestion is:
If you dont want to use waitForInitialization=true to render your entire app once the sdk is initialized, you can instead leave that off and still add useGate('gate_name') in the component where you want to check a gate value.
That will initialially give you false, until the SDK initialization completes, and then will trigger a re-render of the component because the value has changed.
Hope this helps!  I'll keep this issue open until you can verify this is working for your use case

My suggestion, based on your initial code:
Leave the provider untouched.
Then, in your Shop component
export default function Shop(props) {
    ...
    const statsig = useStatsig();
    useEffect(()=>{
        statsig.logEvent("page_view", shop_name)
    })

   ...

    const showAddSenseGate = useGate('adsense2');

then in your component:
{showAdSenseGate.value ? <Ad /> : null }

This is in line with what @jkw-statsig suggested as well - leave the default for the gate off, and once the value is set to true, the ad will be rendered

Thanks all for helping this.
@tore-statsig

I updated the react sdk but still same result. In the original code, I am not sure my updated userID state is applied or not. Is there way to check current userID?

Should I call explicitly call statsig.updateUser function to update userID?

Are you still always getting false with const showAddSenseGate = useGate('adsense2');?
You shouldn't need to manually call updateUser yourself, unless some time in the session a new user logs in.
Would be great if there is a way for us to see more of your code to help with debugging, e.g. if your code is on GitHub we can take a look. In the meantime one thing you can try is hardcoding the userID in StatsigProvider call with a bunch of different values, e.g. 1 - 20, and if you get true sometimes. If so, then it's probably related to how you are setting the userID, but if you are still only getting false, it's likely related to other part of the code.

Hi, yes still getting false.
I just created a test code but same https://codesandbox.io/s/lively-wind-759uw?file=/pages/_app.js

Thanks for sharing @youminkim! That was helpful and I was able to find out the issues you have in your code. Here is my fork that fixed those issues and it's working so you can give it a try first https://codesandbox.io/s/recursing-wright-yy91s?file=/pages/_app.js . Here are some tips/recommendations:

The main problem is with how you were setting userID. As is, your code always passed an empty string as the userID to StatsigProvider, and later the userID is updated by useEffect. You were right earlier about needing to use updateUser when you want to change userID after the initialization, but I recommend using the correct userID for the initial rendering.

Because window.localStorage is not always immediately available during your initial rendering (it won't take long though), I suggest that you wait for it to become available, get userID from it, then return StatsigProvider (do something similar to my code above). This should not delay your initial rendering by much at all.

Math.random generates a "pseudo random" number that uses your computer's time, so when you test locally by refreshing at a fast speed, you can get many consecutive "false" in a row, so you might have to try 10+ times to get a true if you are unlucky (I did and thought something was wrong :) ). I would recommend using something like uuid to generate IDs for users in the future.

Hope this helps!

Thank you @jkw-statsig for detailed explanation.

needing to use updateUser when you want to change userID after the initialization
Can we explore this more? I tried with useStatsig but seems not working https://codesandbox.io/s/crimson-rgb-6vzrw?file=/pages/_app.js

In your example, I need to wait until useEffect execution meaning I cannot use pre-rendering anymore. In same reason, I could not use  waitForInitialization=true. Attaching NextJS pre-rendering details https://nextjs.org/learn/basics/data-fetching/pre-rendering

Hmm I'm not very sure about the requirement for pre-rendering, but if your goal is to only render a static page on the first rendering and update to use user-specific values (gates) later, there is actually no reason to use StatsigProvider in the very initial rendering. You can make a small adjustment to the code I shared earlier and make it work the way you want:
if (userID != null) {
    return (
      <StatsigProvider
        sdkKey={...}
        user={{
          userID
        }}
      >
        <Component {...pageProps} />
      </StatsigProvider>
    );
  } else {
    return <Component {...pageProps} />;
  }

Hope this works for you!
Meanwhile we'll look into the issue with updateUser separately, and potentially make changes to allow the user be updated by simply calling StatsigProvider again with a different userID.

Without StatsigProvider provider, I am not sure how my child component's useGate hook works. I may need to manually check if the context exists which is not ideal.
I believe the best way is that StatsigProvider accepts user changes. Otherwise, in my context, calling functions directly from JS SDK would be more straightforward.

@youminkim in the case where StatsigProvider isn't called yet, calling useGate will simply return false, which is actually better than providing a placeholder userID first only to switch it soon after. I think there are 3 good solutions for you:
1. If you need/prefer to provide your own userID, so that you can use it for other purposes:
You can do what I suggested above and return your child component first without StatsigProvider until you retrieve the userID from localStorage. useGate will simply return false until StatsigProvider is initialized later, no context needed from you. Give it a try :).
if (userID != null) {
    return (
      <StatsigProvider
        sdkKey={...}
        user={{
          userID
        }}
        waitForInitialization={true}
      >
        <Component {...pageProps} />
      </StatsigProvider>
    );
  } else {
    return <Component {...pageProps} />;
  }

2. If you do not need to create your own userID for any reason:
You can simply wrap StatsigProvider around your child component during the initial rendering, and provide no userID at all. Statsig SDK creates a "stableID" that is stored in the localStorage and will use it whenever you do not provide a userID. So if you don't need your own userID for anything else, you can simply rely on Statsig.
  return (
    <StatsigProvider
      sdkKey={...}
    >
      <Component {...pageProps} />
    </StatsigProvider>
  );

NOTE: when you test this, your gate value on your device will be consistent across sessions, so you will always get either false or true. You need to clear your local storage to try to get a different value if you wish.

If you don't like any of the above options, you can simply use pure JavaScript SDK like you did before. Though I believe either option above is better.

We think the first two options should work for your scenario, depending on whether you need to create your own userID or not, #2 is slightly simpler than #1. We'd be happy to chat about this via a VC call if you still have issues or questions. Feel free to ping me on Slack if that's needed!

Sorry for the late reply! Busy with other feature launch. Let me try soon the recommended path

No worries Youmin - let us know what works, we want to make sure the SDK fits your needs.

Hi @jkw-statsig I am also facing the same issue. Refer https://stackoverflow.com/questions/69113756/statsig-how-to-get-true-value-from-feature-gate. Can u help me out for this issue asap?

@rshruthir, could you post the entire file?  One of our engineers will be up in a few hours to help you debug.
Meanwhile, please also feel free to join our slack channel: https://statsig.com/slack

I think this is very out of date, and is being referenced by more folks for unrelated issues.  I'd recommend trying v1.0.0 of the react SDK.  Feel free to open a new issue or ask in slack if there are additional problems using the SDK. @youminkim if you feel this was closed before your issue was resolved, feel free to reopen with the latest status, but first I would try the latest version of the SDK.
Thanks!


feat: add transceiver getter to downtrack

Transceiver getter adds more flexibility to downtrack API, e.g. track Mid can be retrieved from downtrack. Also, transceiver setter is already present.

At least 1 approving review is required by reviewers with write access

I guess I'm not an "approving reviewer"? I thought I was, but I changed jobs and haven't used ion-sfu in many months.

I also suspect the golangci-lint check is broken, has been broken for a while, so you may not be able to merge even with a review.
This project might be abandoned. Maybe ask in the Pion Slack?

I'm not part of the organization either. I can't help sorry.


Search data attribute in parent elements

Pull Request Template
Fixes issue #1 .
Description
I will add more details soon.
Type of change

[x] Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?
I've used breakpoints while running the unpacked extension, as well as successfully recorded a lot of tests with the proper data attributes.
I'll try to add a unit test to cover this and will update this PR soon.
Checklist:

[ ] My code follows the style guidelines of this project. npm run lint passes with no errors.
[ ] I have made corresponding changes to the documentation
[ ] I have added tests that prove my fix is effective or that my feature works
[ ] New and existing unit tests pass locally with my changes. npm run test passes with no errors.

I can't run linting. Blocked by issue https://github.com/oscartavarez/cypress-recorder/issues/5

@fmoliveira Hi, I am very much looking for your PR to be merged and available in the plugin. Is there any way I could help?

@wolfi3b Sure thing! Thanks for coming in!
This PR is currently blocked because I can't tick all the checklist in the Pull Request Template. It has a lot of linting errors, but all those errors also happen on master! I'm wondering if I just have issues with my setup, or if we actually have those lint errors to solve. I've opened an issue at #5
Could you please checkout the repository in the master branch, install the dependencies with npm installand runnpm run lint` to confirm the issue #5 ?
If that issue is confirmed, then we can work on getting the linting issues fixed, and unblock the PR checklist. :)

No problem. So I run it and got ton of lint errors as well so I would say something is not right here.

Well if I run it with --fix than only 40 remains :-)

@wolfi3b Awesome!! I haven't tried the auto fix, very good to hear that!!
Would you open a PR with these fixes? I can help you fixing the remaining ones if you'd like. :)

@oscartavarez Could you please confirm if the linting settings are properly committed to the repository? Do you have the same errors on your environment as well, or may the repository be missing a file with your linting settings?

@fmoliveira Well The think is ..I don't know if I should. I mean for all I know the issues are here because the author forgot to commit linting settings. It would be strange he did not run lint on his code.
If we run it as
npm run lint -- --fix
it will fix all but those 40. Which most are simple to fix from what I checked. So if we get green from @oscartavarez to go for that it should be easy and I have no problem to create PR for all of those.
But correct me if I am wrong he does need to confirm the PR am I right? So we still need him to check our comments.

@wolfi3b Yeah, you're right! I thought about the settings afterwards!
I've pinged @oscartavarez in the linting issue as well, which is shorter, let's wait for an answer - as you've said, he will have to confirm the PR anyway before we can merge this fix. 🙃

@fmoliveira hmmm...do you know if it is possible to check somewhere if anyone else than @oscartavarez has write access to confirm PR's? I mean...his last activity is more than 2 months ago (if I did not missed anything) suggesting he is pretty busy and may not have the time or opportunity to check here anytime soon.

@wolfi3b We can see the list of contributors, but I think it's not possible to see list of maintainers.
@tnolet Do you think you could help us? We would like to confirm whether the repository is missing the proper lint settings (because it has hundreds of lint errors), and afterwards, we would want to get a couple of pull requests reviewed and merged (they are both blocked by the lint issue).

@fmoliveira was not aware of this "fork" of Puppeteer Recorder. Cool!
I had 5 lint errors in Puppeteer Recorder. Also, I was not checking for this in the Travis CI build. I just  pushed a small update. I have no time to comb through the differences between this and my repo.

@tnolet Sweet, I wasn't aware of the Puppeteer Recorder either, I will definitely have a look on it! Since this repo is not tagged as a fork (probably it was cloned and pushed instead), I imagined you were an original contributor here.
Thanks for your answer! 😃

@tnolet Sweet, I wasn't aware of the Puppeteer Recorder either, I will definitely have a look on it! Since this repo is not tagged as a fork (probably it was cloned and pushed instead), I imagined you were an an early member of this project.
Thanks for your answer! 😃

That is strange ...I had a quick look and the config files looks pretty the same with the pupeteer repo. So is it possible the author of this "fork" just did not run lint?

@wolfi3b Yes, I don't doubt that! The CONTRIBUTING.md and PULL_REQUEST_TEMPLATE.md only had the word Pupeeteer replaced for Cypress and it's all the same.

Hey guys, just check the Puppeteer Recorder Travis build.
https://travis-ci.org/checkly/puppeteer-recorder
It's green and runs npm run lint. Maybe there some hint there.

@tnolet Nice, I'll take a look! Thanks!! 🙌

@fmoliveira  hi, I just got back...any luck/update?

Hi @wolfi3b !
No news! But given this repository is a fork from puppeteer-recorder and the former has the same PR template, but there are lots of lint errors here, I believe linting wasn't really taken into account on this repository. We could either fix everything or just forget it and merge anyway.
In any case, we need your help @oscartavarez ! Could you please take a look here or at least add some of us as maintainers and publishers so we could keep improving this tool?

Hi @wolfi3b !
No news! But given this repository is a fork from puppeteer-recorder and the former has the same PR template, but there are lots of lint errors here, I believe linting wasn't really taken into account on this repository. We could either fix everything or just forget it and merge anyway.
In any case, we need your help @oscartavarez ! Could you please take a look here or at least add some of us as maintainers and publishers so we could keep improving this tool? Thanks a lot, mate!

Sorry guys for the delay, this weekend i will take a look at it. really sorry guys @fmoliveira @wolfi3b.

@oscartavarez Hi did you have any time to check it out? Or if you could make one of us able to approve we would very much appreciate it.


Fix App following security Audit

Fix Security Audit finding, and few other pending issues

Fix Security Audit issue OPGP-#01 (buffer overflow in pinentry)
Fix screen message buffer overwrite
Replace memset by explicit_bzero
Replace memmove by strlcpy
Clean magic numbers with define constants
Cleanup / comment dead code
Clear return buffer in case of error
Fix Name display
Remove useless TODO comments
Fix #80: set 'URL of public key' on each slot

Checklist

[X] App update process has been followed
[X] Target branch is develop
[X] Application version has been bumped

Codecov Report
Attention: Patch coverage is 25.00000% with 3 lines in your changes are missing coverage. Please review.

Project coverage is 27.01%. Comparing base (43e5945) to head (546523a).

Files
Patch %
Lines

src/gpg_io.c
25.00%
3 Missing :warning:

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #100      +/-   ##
===========================================
- Coverage    27.27%   27.01%   -0.26%
===========================================
  Files            1        1
  Lines          209      211       +2
===========================================
  Hits            57       57
- Misses         152      154       +2

Flag
Coverage Δ

unittests
27.01% <25.00%> (-0.26%)
:arrow_down:

Flags with carried forward coverage won't be shown. Click here to find out more.

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.


How do I install curl?

The package manager seems to lack permissions and I've tried a lot of different things

In the case you're not specifying the root user when running this image, you're running as nonroot user so that you don't have rights to install packages (which is expected).
Either you're running this image with docker or docker compose, you can use the --user flag to request accessing your container with the root user.

Hello @AndrewCharlesHay, as @zedtux pointed out correctly this container image is not intended to be run as root by default.
It uses a "nonroot" (as seen here) user that you should be able to override if required at container runtime, depending on the Container Runtime your are using.
I'm closing this issue if you don't mind 😉

Thanks!


Why does react-dates need @babel/runtime and react-with-direction?

react-dates version
<EMAIL_ADDRESS>Describe the bug
The documentation states that if you run the following command:
(
  export PKG=react-dates;
  npm info "$PKG" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g; s/ *//g' | xargs npm install --save "$PKG"
)

It will result in the following:
npm install --save react-dates<EMAIL_ADDRESS><EMAIL_ADDRESS><EMAIL_ADDRESS>
However, it also installs react-with-direction and @babel/runtime as dependencies. Why does this happen? Are these dependencies even needed?

Yes, they’re all listed peer deps, which is why the command is helpful. The readme example just hasn’t been updated with the new ones.

@ljharb thanks for response.
So I'm building a React UI kit and one of the components in there is using the SingleDatePicker component from the react-dates library.
For now I've only specified react-dates and moment as peer dependencies of my UI kit. I'm using an instance of a Create React App to test if my UI kit is working.
While I only install react-dates and moment in my CRA the date picker component I build is still working. Is this because those dependencies only get used in certain cases or?

If npm ls returns nonzero, then your entire dep graph is invalid and can't be relied upon to work properly. Everything that's a peer dep must be installed, always, full stop.
Certainly there may be code paths where some of those deps aren't used; they also might be accidentally installed already due to npm's dep hoisting - but you still should always explicitly specify them.

Note that if your package is published, all those peer deps should be both peer and dev deps, to pass on the requirement to consumers.

Thanks, will add them as peer dependencies!
I think @babel/runtime is already installed as a CRA dependency and react-with-direction will probably only be used in certain use cases which I didn't encounter yet.

It still needs to always be installed, no matter what.


[WIP] Add support for ocp installation

Not yet tested. Also, we can divide it into sub playbooks if needed.


Ignore selection

I added a setting to ignore selections so that file based runs will always be performed.  The reason that I added is because I usually select lines of code, comment them out, and then use the run script keyboard shortcut -- only to find that it tried to run the commented code even though I want to run the entire file.  All that this does is remove an extra step in clearing the selection before running.  I thought that this might be a minor convenience for other like-minded users of this package.

Glad it's an option, not a default. I love selecting text.

Thank you! When I get to my laptop again I'll add you on as a maintainer.


Practice handwriting project gradle build error

I have downloaded the Practice Handwriting project. But after importing project gradle file could not be build because of some HTTP Proxy error. I am very new to android development. So appologies if its a very silly mistake. Here is the error I am getting
Error:Unknown host 'proxy.iiit.ac.in: Name or service not known'. You may need to adjust the proxy settings in Gradle. Enable Gradle 'offline mode' and sync project. Learn about configuring HTTP proxies in Gradle</a>

Me too I faced the same issue so what I did ?
1- in gradle-wrapper.properties set distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
2- in build.gradle(project) add or modifier dependencies {         classpath 'com.android.tools.build:gradle:2.3.0'     }


Update author/reviewer wording

X authors added to -> contributed to
X reviewers added to -> contributed to

I think I explicitly word it that way to indicate that someone not appearing on that list can still be a contributor. The people on the list are just ones that added with code or reviews. But thinking about it "added" doesn't make more sense in that regard than "contributed". Happy to change it.


Is this call to setModified necessary

Hello is the call to Composite.setModified necessary here
https://github.com/liabru/matter-js/blob/e909b0466cea2051267bab92a38ccaa9bf7f154e/src/body/Composite.js#L238
since Composite.removeAt calls setModified anyway? I noticed that removeComposite has an extra call too while removeConstraint does not

Good catch, possibly not though I'd have to investigate so marked have this, thanks!

It think this one was resolved here so closing, thanks again.


⚠ Bofrost.es has degraded performance

In 0a32ca1, Bofrost.es (https://www.bofrost.es) experienced degraded performance:

HTTP code: 200
Response time: 1587 ms

Resolved: Bofrost.es performance has improved in ba6830d after 13 minutes.