Daniel (00:05.166) Uh, oh, we're not getting a countdown. Oh, the countdown was like, I switched, I switched windows for exactly five seconds. And that was exactly the five seconds that the countdown was. All right, cool. We have double header recording set up. So, hey, welcome to waiting for review. It's show about the majestic indie developer lifestyle. Join our scintillating hosts, Dave and Daniel. That's me. Dave (00:07.795) It's done. It's done. It's done it. Dave (00:13.267) Hehehe. Dave (00:21.587) Yep, yep, yep. Daniel (00:32.462) And let's hear about a tiny slice of their thrilling lives. Join us while waiting for review. Dave, how are you? Dave (00:40.627) I'm pretty good thank you Daniel. Yeah. Sorry about that. I hit the button as you were otherwise occupied on recording. Daniel (00:42.862) Fantastic. Daniel (00:46.732) Hehehehe It's just a high energy entry into the show that's perfect. Dave (00:54.867) Yeah, yeah. Now things are pretty good on my side. I've been pretty active over the last week or so with a few bits on my apps. But I am very, very curious because before we started hit setting record on everything, you dropped this unknown thing into our show notes, which is just tagged with Daniel has a secret new thing. Daniel (01:24.59) Daniel does indeed. All right, so what happens is that I am now finally a professional podcaster. What does that mean? I now own the thing that you have to own to be a professional podcaster. Like you can have a microphone and like you can like earn tens of thousands of bucks with sponsorship deals, but you're not a professional podcaster until you own a Synology. I recently decided that because... Dave (01:53.555) Oh. Daniel (02:02.774) The telemetry data is the most important and valuable thing that the company owns. That it really should be backed up in more than the locations that it already is backed up at. So it is in multiple cloud backups and it is reasonably safe. But just to be sure, I was like, okay, where else can I store this data? And I was like, hey, if I download it from the cloud and encrypt it locally and then just like sync it. Dave (02:09.043) Mm -hmm. Dave (02:21.299) Mm -hmm. Daniel (02:33.23) back down every day or so, I have a local copy that does not incur cloud hosting costs because with these amounts of data, that actually is a significant amount of money, especially if you want to have multiple copies. And so at first I was like, I'm just going to get another USB hard drive enclosure and add it to the Mac mini. But turns out if you want to buy hard drives that are bigger than 12 terabytes, the price per Dave (02:34.971) Mm -hmm. Daniel (03:03.246) gig or the price per terabyte gets really expensive pretty quickly. So I was like, okay, so I guess it's just going to be a bunch of disks. And I was like, okay, so what do disk enclosures for just multiple disks cost because, and then I'm just going to connect it to the Mac mini that is the local server, the load bearing Mac mini as that every company has. And then I'll be good. And it turns out that most of these, or I didn't find any Dave (03:17.521) Yep. Dave (03:22.075) Yep. Daniel (03:32.878) well -reviewed hard drive enclosures for multiple hard drives that were significantly less than $500. But the thing is, if you're spending $500 for a mediocre enclosure, and then you still have to do all the RAID and the configuration yourself, you might as well just pay $50 to $70 more and actually get a Synology. And that's... Dave (03:57.009) Right. Daniel (03:58.094) is a self -sufficient device, has better cooling and has native support for different various RAID formats. And it's even daisy chainable, which means that once this thing is full, I can add another one just behind it. And they should actually combine to a logical volume in theory. I don't know if I ever want to do that. So I recently bought a Synology DiskStation 923... Dave (04:20.977) Okay. Daniel (04:26.318) Plus I think is the name of the thing. And it has four bass. And I put in two 12 terabyte hard drives for now. So two bass are still available. And yeah, it's fun. It's very impressive how just well made this thing is, just both the hardware and the software. It is also incredibly loud because I, of course, went for like, NAS compatible server hard drives and those are like, I was like, how much louder could they be then? You know, like just regular desktop computer hard drives that we all had in our computers like in 10 years ago or so. Turns out quite a bit load. It sounds, it sounds as if there's like a firefight broken out like two streets down or something like that. Dave (05:07.505) Mm -hmm. Ha ha ha. Dave (05:16.627) Right, with all the clicky sort of sounds. Daniel (05:18.99) Yeah, the clicking is way louder and way more, I don't know, has way more oomph. Yeah. Dave (05:24.563) Right. It's, uh, I don't know if you would know the reference. It's been memed from Arrested Development, but it's like, uh, to paraphrase, um, it's a hard drive, Daniel. How much louder could it be? 12 decibels? Daniel (05:38.254) hahahaha Daniel (05:42.766) It's a banana, Michael. How much could it cost, right? Dave (05:45.651) Exactly, yeah, yeah, yeah. I apologize if that's a reference somebody doesn't get. Maybe I'll link the meme in the shy notes. But yeah, anyway, so you're... Daniel (05:57.614) Yeah, so now I have a Synology. It is slowly filling up. Like basically, I have decided to only run the sync job at night when I'm not in this office, because otherwise it is actually a bit distracting. But if it's not actually writing, then it is completely quiet, at least from the cupboard that is in right now. So you shouldn't be able to hear it on the microphone, and I really can't hear it when I work either. It is very nice. And now I am finally a professional podcaster. Thank you so much for listening to my story. Dave (06:07.507) Mm -hmm. Dave (06:26.251) So Synology is a prerequisite of the professional podcaster class, right? That's fair, that's fair. Daniel (06:31.406) Yeah. Yeah. Like, do you know, of course you like, you do know that podcast ADP, Accidental Tech podcast. I, I kinda like it, right? And one thing that is a staple on that show is that I want to say 10 years ago or so, Synology just gave the, all those, all the three hosts just gave them a Synology each and they've been using those and talking about them every other show or so. And they've even like replaced. Dave (06:39.411) Mm -hmm. Yep. Dave (06:58.035) OK. Daniel (07:00.142) their existing zonologies with new ones and whatever. And so that's like a really good advertising campaign for zonology. I should really send those guys telemetry deck accounts. Just like here, here's something for you to use, you know. Dave (07:02.865) Hmm. Dave (07:14.515) You should do and maybe a link to this show because do you know what, Daniel? I wouldn't mind being sponsored by Synology if they were so inclined. I could definitely find a use for. Yeah, yeah, because absolutely. Daniel (07:22.158) Oh yeah, oh yeah, they should definitely sponsor us. Speaking of sponsoring, I know I already had my thing to the show intro and I wanted to actually give you the spotlight, but I need to tell you one more thing, which is Telemetry Tech has sponsored the AppStories podcast. Dave (07:40.819) Hey, oh that's lovely. Daniel (07:42.062) Yeah, episode 375 at the five minute mark, John Forhees reads a two minute ad read about Telemetry Deck, and I love it. Yeah. Oh, you should. Dave (07:46.427) Yep. Dave (07:52.685) excellent. Well we will definitely link that in the show notes. I want to link from you because after we've recorded I want to check it out. So yeah definitely definitely give me that. But yeah that's fantastic Daniel. That's very good news for telemetry deck and I'm sure it's a good read as well. Daniel (08:12.526) Yeah, it was really cool. I always wondered how these work. Do the sponsors, do they pre -write everything? And it turns out, at least for that podcast, they asked me to provide a list of bullet points. And they would then, or John would then read it. And that actually works really well because it sounds very much like Flowey and in his style, but it still has all the important points that I wanted to make. And I sent you that list of bullet points before for you to double check because I really value your view on how to structure these talking points and stuff like that. And so thanks for your help. Dave (08:35.635) Yes. Dave (08:50.899) problem. That's part of what we do. Not just co -hosts, but indie dev friends. Daniel (08:57.71) All right, yeah, that was my tiny list of things that I was really excited to talk to you about. I have software news as well about telemetry deck, but I'm going to give you the microphone now. So what have you been doing? Spotlight. Dave (09:04.323) Yep. Dave (09:11.604) Oh okay put on the spot what have I been doing? Well... Dave (09:33.821) And that sort of Dave (09:38.483) took a pit stop. Dave (09:45.171) that were impacting iOS 16 only. And I got prompted by a user to say, great, camera's in. That's like, Dave (10:02.099) which is network device interface. And it's an industry standard for sending video from one piece of hardware to the other over a local Ethernet. Typically local, you can do all sorts of stuff with it to send it over the wider Internet and all of that. But really you're talking Daniel (10:14.766) streaming basically, but local local videos. Dave (10:27.475) as possible. Dave (10:31.315) from a company called Newton. They've been operating for at least 10 years in this space, if not much longer. I certainly feel like it was about 10 years ago. around the sort of video VJ scene that, you know, Go VJ is a part of that scene. And so I've been part of that for years. But yeah, the long and the short of it is that this company, NewTek, makes an SDK for almost every platform. And it allows for this very low latency transmission of video between devices. And yeah, and it's fun. Daniel (11:09.588) Fantastic. Dave (11:14.643) is that I can now send video from say an iPad. into my Mac running somebody else's app that supports NDI input. And that means we're in a position then of like people can build their video rigs however they want them to operate and Govj can fit inside of that ecosystem using this streaming network video. And yeah, I got it working. Dave (11:50.227) As you can imagine, when you're sending video over network, there's a whole process of encoding it, of trying to stick stuff on background threads and this, that, and the other as well so that you're not. UI because it's very, very easy to. Dave (12:09.683) and what I've got now. This is my node based pipeline. made two new nodes one for receiving video through NDI and one for sending video through NDI. Yeah and it's working I've got video going from one device to the other. of very obvious, they feel obvious now, but a couple of very obvious bugs just in terms of at one point I was creating creating data in a way where the pixel buffer it was being written to every time it was coming over the network from this SDK I was creating the pixel buffer every single time rather than just creating one and then writing to it and that's actually quite intensive yeah yeah Daniel (12:58.766) Okay. Yeah, that sounds inefficient. Dave (13:04.243) But this is my process, right? I'll make it work. I'll get it up and running, test it through, and then refactor. Dave (13:14.899) intuitive. you're then smoothing out the edges on and to do what you need it to do. But yeah, that's been the big story for me is I've now got it sending video from one device to the other very much. I want to say kind of like a holy grail moment for me. Like I've been dreaming for years of having video being sent in and out of my app and how it can sort of fit with all these other apps that do do the same sort of thing. And now it's doing it. So like. is a milestone for me. Daniel (13:49.33) Fantastic. Yeah, congrats. That's awesome. Dave (13:53.78) It's revealed a couple of things as well along the way. So I just wanted to touch on this because this is the sort of stuff I come up against with the video app. Daniel (13:56.294) Mm -hmm. Dave (14:07.859) At one point, not the pixel buffer issue I just mentioned, like writing every frame or so, but what happened is that the way I was doing things, it worked on newer devices and then fell apart on older devices. And so I had a situation where it was like, okay, so what's going on here? You know, like, is this an iOS 17, iOS 16 thing, for example? Absolutely possible. Is this... buried somewhere lower inside of this SDK that I'm using. Cause the SDK itself is a C plus plus base. Dave (14:49.363) So, you know, maybe something funky is going on along those. None of that, none of that. And this is when I then discovered that although things were working, the way it was working was that I was creating and writing into a buffer every frame. Daniel (15:11.438) if if if Dave (15:14.579) And it was working nicely on the newer devices. And it was quick enough that the deallocation of the data that was being written into that frame, which is something that the SDK is managing underneath the hood that I shouldn't be touching. Right. That was what was affecting the old devices. And on the newer devices, it was so quick that the data was there already as it's operating. Right. So on older devices, it sort of expressed itself as things starting to judder and then. Daniel (15:37.966) Mm -hmm. Dave (15:44.533) like a segmentation fault effectively underneath so the app would crash. So that's been a bit of an interesting one to try and isolate to be honest with you because it presents itself as well why is it not working on this this device well okay is it the iOS is it something I've done with the configuration of the SDK what is it you know I it was even Daniel (15:56.806) Yeah, I can imagine. Dave (16:11.275) exploring stuff with chat GPT and trying to see like, how are the people. Assumedly other people, you know, the base of knowledge that chat GPT is accessing is being a composite of everything it's read. I was trying to see if it had a better angle on how to work with threads with this SDK and it basically produced the same sort of code as I was writing. So I was like, okay, right. I'm probably on the right track. Anyway, long story short, Daniel, I bought a test device and that helped. Yeah. Daniel (16:41.806) haha Dave (16:46.219) Because yeah, I have the friend that we give a shout out to last week, Leon, who's been beta testing this for me. He's one of my best beta testers. He's running an iPad Pro 9 .7 inch that is mired on iOS 16. They've Apple Drop support last year with iOS 17 for it. Daniel (16:54.638) All right. OK. So you didn't even use the excuse to buy a new cool thing. You bought an old cool thing. Dave (17:12.563) And I picked up one of these from New Zealand's eBay equivalent TradeMe. Yeah. I bought an old cool thing. This is an iPad that I believe is now getting on for eight years old this year. And honestly, it's still not a slouch. Like if they'd updated it to support iOS 17, I think it would have still been a reasonable experience. Daniel (17:24.046) Mm Dave (17:46.323) better because I was able to see the memory graph and see what's being. Daniel (17:53.71) Very good. Yeah, sometimes it's really good to test on older hardware. Dave (17:54.099) the crash was and within an hour or so. Dave (18:02.707) And that's now fixed. So I'm supporting. what I've discussed. Dave (18:18.963) broadly. Daniel (18:23.662) Right. Dave (18:29.299) want to test it on both the fastest, the slowest, and maybe one in the middle in terms of the range of devices that your software will see. And yeah, I mean like making this fix, this improvement now means that the app is going to run as well as it can run on newer hardware as well, which is always good. You know, you can always use more device capacity. Yeah. Daniel (18:53.134) Yeah, it really, really helps. Because I was downloading stuff for the Synology, my internet was pretty saturated. And I don't have a hugely fast line to begin with. So everything, like requests in the browser and whatever took really long. So I actually discovered a few really weird edge cases where the telemetry web dashboard would just look wrong or behave badly, just with some Dave (18:59.211) Mm -hmm. Mm Daniel (19:22.318) times out or whatever. So yeah, sometimes you've got to use old hardware or slow connections to find these things. Dave (19:29.519) 100 % yeah and I think that's something that all of us who live and work in tech if you like can be guilty of ignoring at times because you know I mean I tend to try and have a fairly up -to -date phone a reasonably fast Mac for doing what I do you can get disconnected from the reality of your user base which is that a lot of people buy things and run them for a lot longer than we would you know just in terms of Daniel (19:44.59) Hmm. Daniel (19:51.31) Yeah. Dave (19:57.651) well I bought this iPad it's still working why would I get a new one you know and that's that's reasonable uh it's really given me a bit of food for thought though because I often sort of say oh I'm an indie dev I don't really want to support older devices um you know like I want to make sure I'm rolling uh with the latest release as much as possible uh I've kind of relaxed more to a um version minus one kind of approach. VJ because that's been been pretty healthy certainly since the iOS 12 jump. But the more I think about it the more I'm kind of querying my logic there which is that you know if iOS 18 rolls around and it's actually not too hard to keep supporting 16 then I probably should. Yeah so that's just a bit of a bit of food for thought is I'm now questioning Daniel (20:48.654) All right. Dave (20:56.349) difficult is it really for me to keep supporting backwards? Yeah. Daniel (21:00.046) If it's easy, then yeah, I'm all for it. But yeah, if you are putting in significant amounts of work, or if you're being held back from using newer and easier to use features, then it's different. I think current minus one is the way to go for most people. Just because, just looking at the telemetry data, for example, you just see that if you are using, current minus one, you are supporting at least 90 % of the devices that are really being used. So it's like, yeah, whatever. And it's probably, it's very likely that you're not going to get the last 5 % to 10 % of devices anyway. But your app might be different, of course. And especially for GoVJ, I can also imagine that if people have old devices and know that it has this NDI support, and you can send video between different devices, then people might be able to use older devices that Dave (21:42.603) Mm -hmm. Dave (21:51.411) Mm -hmm. Daniel (21:57.262) or otherwise just they were unable to use and just bring them bring them back to life. So it might be really helpful there too. Dave (21:58.935) Yep. Dave (22:04.531) There's definitely an angle there and I think that you know the one thing that occurred to me certainly as I bought this older iPad for I mean it wasn't peanuts it was it was $200 New Zealand which is what about a hundred pounds or dollars US. Just subtract 173 you'll be about there. But no. Daniel (22:22.414) Kelvin. Right, Dave (22:37.171) supporting backwards. Dave (22:41.331) potentially, right? I mean, I'd argue for a lot of apps like your one app supporting backwards isn't going to keep that user from. Dave (22:55.059) the device as a dedicated device in a performance rig. You know, so this happens with iPad audio software as well. People end up using their iPad for that one specific synth and you know then as long as that keeps working it really doesn't matter that it's no longer supported by by Apple, right? As the OS moves on. So yeah there's some food for thought for me in there in terms of like... Daniel (23:05.666) Hmm. Dave (23:24.915) people using devices as a dedicated device to run my software. And then what does that mean in terms of providing more longevity of support? I don't have a good answer yet. I think it kind of looks like maybe one or two things that sit outside of my main app. For example, a camera enabled app that sends video over the network that my app can receive. It'll make a lot of sense for that camera app if I build it to support backwards by quite a way. You know, because then you've got, well, okay, your old, old phone becomes that network camera that you're using for... Daniel (23:48.078) Oh Dave (24:05.839) a dedicated input into everything else that you're doing. Daniel (24:08.974) Yeah, totally. And especially if it's just a camera, then you don't have a complicated user interface where, because I think that's one of the complications if you want to support older devices is like the Swift UI just evolved so much over the last few years. If you can't support at least iOS 16 or so, it's actually pretty much a pain to write Swift UI these days. Dave (24:17.521) Mm -hmm. Dave (24:23.379) Yes. Dave (24:29.747) Absolutely. Yeah. Yeah. And, and, you know, I can see that, that bar continually raising as well, you know, in a, in a couple of years time, we're not going to be talking about supporting back to iOS 16. There'll be other compelling reasons for SwiftUI to keep moving on as well. Um, so yeah, it's, it's, it's food for thought. I mean, for me, I'm looking and I'm going, well, can I build it in such a way that the SwiftUI view for this perspective camera app, um, Daniel (24:39.214) Mm Dave (24:58.771) that's on my list of many apps I want to build with the video pipeline, by the way, this isn't a new idea. Daniel (25:02.526) The roadmap is far and far into the future as always. Dave (25:07.956) As always, yes. But I look at that and I go, can I build it simply enough in SwiftUI that it's probably going to survive any iOS updates reasonably well, any SwiftUI updates reasonably well? Or would it actually dictate that I'd be better off building it in UIKit and just leaving it trucking along? Daniel (25:28.302) Ooh. You want to create some programmatic constraints? Or maybe use interface builder? Oh, interface builder. Those were the days. Dave (25:29.299) Yeah. Dave (25:33.681) Mm -hmm. Dave (25:39.635) No, no, no, no, programmatic constraints, Daniel, come on. Oof, oof. Yeah, or maybe just frame coordinates, eh? Daniel (25:43.71) Springs and struts. Dave (25:54.055) No. Anyway, that's a whole rabbit hole that I'm not ready to go down just yet, but I've definitely like this whole experience of having the older iPad has definitely made me sort of go, okay, the more I do to support backwards, probably the better. Where it is not, you know, absolutely making a mess of the code base and of the mental overhead of getting into context as well. Because that's the biggie, right? Is you don't want a whole bunch of your code base to have lots and lots of if statements listed in it that you're then kind of figuring out. So it's got to be relatively contained as well. Yeah. Daniel (26:39.63) That's been my experience with generally with writing Swift UI multi -platform code to like when, for example, you want to support the Mac and iOS or iPadOS or now these days iPadOS and iPhoneOS and also VisionOS. Like if you find yourself doing more than just one if statement per file, then it's time to just duplicate the file and just use a different Dave (26:45.139) Yeah. Dave (26:54.865) Mm -hmm. Mm -hmm. Daniel (27:07.478) file for Vision OS and iOS. You'll have some code duplication, but in the end, the paradigms are different enough that you just break your head if you're keeping everything in one file. The idea of twist UI is not to be able to reuse everything, it's to be able to learn one language and then be able to write for everything. Dave (27:09.811) Yeah. Dave (27:21.971) Yeah. Dave (27:32.989) Yeah, yeah, I think that's very true, to be honest. And I've already got a little bit of this going on in the code base already. If I think about it, I had a situation where I wanted to use the SwiftUI on change, the modifier, and so to wire that up to the change of a piece of state. And what happened is that with iOS 17 we got the ability to use that with the initial value rather than just subsequent values after initialization. iOS 16 didn't have that in the same way. And so I ran immediately into a, well, do I pull support for just this? Probably not. What does that look like? And in the end I did, I made a... Daniel (28:05.07) Hmm. Dave (28:26.687) a shim effectively for iOS 16 that does much the same sort of thing. Made my own modifier. So now I have like on change and then LB for light beam apps at the end of it. And that modifier does the, is the one spot where it goes, okay, what OS am I on? I'm going to do it this way or that way inside of it. And it felt a little bit, not really happy about this, but then on reflection, it's been probably the best way of handling it. Daniel (28:30.126) Hmm. Dave (28:56.519) I've got one spot where that's made, everything's calling it in the far -flung future. I can either keep using my same modifier and it will just never execute the iOS 16 bit, or I can refactor it out really easily. So yeah, it's about finding that balance. And I think as long as you're staying relatively objective with what you're doing, Daniel (29:08.45) Yeah, sounds pretty good. Dave (29:22.129) you know, and kind of sense checking, okay, am I spending a lot of time after this? Is this making an absolute mess out of the code base and just causing me future tech debts and all of that sort of thing? Um, if your answers to those things are no, it's not, or it's, you know, enough that I'm comfortable with, I feel like I can control this. Then, you know, that, that sort of indicates to you what you need to do, I think, but it's about having that continual conversation as these things come up with yourself. Daniel (29:27.214) Yeah. Dave (29:54.131) Yeah, which is much more difficult as a solo indie dev than it is on a team. Cause at least on a team, somebody's holding you accountable. You know, you've got that back and forth. Daniel (29:56.834) Oh, yeah. Yeah. But oh well. Dave (30:06.879) Speaking of teams, Daniel, this is a very awkward segue into stuff. Awkward segue. Let me crowbar this in. Speaking of teams, I believe you've been doing some work in the telemetry deck co -base that really enables teams or is related to organizations with different types of people in them. Daniel (30:12.11) Oh, I love awkward segues. Come on, come on. Awkwardly segue me. Daniel (30:27.406) It is true. It is true. Yeah. So I think the first time I created this branch was in November of 2023. That is like December, January, February, March, like four months ago. And I finally merged it and it mostly even worked. So a surprising amount of possible customers or potential customers. Dave (30:38.483) Cool. Daniel (30:57.262) told me, hey, we cannot use telemetry deck because we need more fine -grained permissions, or we need to be able to have people join multiple organizations with one account, or we need to be able to have one organization, but then have some management of who can access which apps and which data. And... So I've been carrying around this with me for a while and then decided, OK, and something that I really wanted to do is just one of those things, which is when I count should be able to join multiple organizations. But the thing is, if you touch that part of the code, it is a refactor that basically touches every single thing because it just goes deep into the database. And the way that users are stored, the way that organizations are stored in the way that they to relate to each other just changes. And of course, that brings many problems. And so for ages, I was like, okay, I'm not going to do that because or I'm not going to do that yet, because it's just not worth it. But with these potential customers looming on the horizon, and me thinking, hey, like, every Dave (31:56.657) Mm -hmm. Daniel (32:17.006) day that I write different other code that expects the database to be the old way, I'm calcifying this more. And so finally, last November, I was like, OK, I'm going to start. So I created some diagrams, how I want the database to look like. I read a huge amount of articles, white papers, and even a book about what are different patterns of encodifying permissions, multi -users. and similar things in a database. And of course, you can make this as complicated as you want, but I finally ended up with a system where you have organizations. Then an organization has multiple roles, and then a user can belong to multiple roles again. as well. So the role object is the connection between users and organizations. And of course, multiple users can belong to a role, and also users can belong to multiple roles. So that's the end -to -end thing in there. What I then also created was a second object that's called a permission object, which kind of overwrites the rights that a role have. And I can share my diagram later. Actually, I'm going to share the I'm going to share a link to the blog post where I described this and that has the diagram. I would share it now, but about 10 minutes ago, my trackpad told me that is absolutely completely empty. So I don't have a mouse anymore and I don't have a cable. So I'm going to look this up after the recording is done. Dave (33:55.407) That's fine, that's fine. Equally, equally anybody listening in can't benefit from a screen share or anything right now. So yeah, we'll link it. It's all good. Daniel (34:09.262) Right. Right. So generally, permissions wise, you have two sets of permissions. The first one is when like, what are the things you can do with the organization itself? Like, can you change the name of the organization? Can you invite new members? Can you change the plan? Can you change billing settings? That kind of stuff. Can you create a new app? So those, I call those organization permissions and they live in the role. Dave (34:22.955) Mm -hmm. Dave (34:32.339) Right. Daniel (34:38.702) So for example, your organization might have two roles, administrators and users. And administrators can then edit billing settings and whatever. Users cannot. But users can still, for example, create a new app. And so these permissions have like four levels, basically, which are non, read, write, and administrate. So if you have administrate rights, or if your role has administrate rights on an organization, you can. Dave (35:01.907) Mm Daniel (35:08.846) I don't know, do everything. If it has right rights, then you can create a new app in that organization. But you can't, I don't know, change the bidding cycle to yearly or whatever. So yeah, and those live in the role because that makes sense so that we can have different roles. And then the other set of permissions that you need to define are what can you do with each individual app? Dave (35:15.311) Yep. Dave (35:20.243) Yep. Dave (35:25.395) Yeah. Daniel (35:36.654) And again, you have like four levels, non, read, write, administrate. If you can administrate an app, you can do everything. You can delete it. You can rename it and you can change these permissions. If you have write access, you can probably, you can like actually edit the apps, insights and dashboards and groups and queries and stuff like that. If you have read access, you can just click through, but you can't edit anything. If you have non access, you can't even see the app. And... These live inside the organization. So each organization has a thing that is called app -based permissions. So this is just the base permissions, like every app that belongs to these organizations, if it does have this level of permission for every user. And so usually, that would be set to write or administrate. But then what you can do is each role can overwrite that. Dave (36:13.019) Yep. Daniel (36:34.222) So if I create a permission object, I can say like, okay, I'm creating a permission object that connects a role with an application. And then say like, okay, members of this role can actually not even see this app or administrate that app, even though the base permissions are set to none or whatever. And so this way you can, for example, do something like you have an organization that has multiple teams. You create a role for each team and then. Dave (36:34.469) Okay. Dave (37:00.017) Mm -hmm. Daniel (37:02.286) Each team can only see and edit their own apps. Or if you are a development agency, for example, with multiple customers, you could now either create multiple organizations for like a separate organization for each of your customers and still see all your data because you can switch organizations now. Or if you don't want that because maybe you want to pay for all the data in one place, not have multiple contracts with Sentimental Deck or whatever, you could also have... Dave (37:05.491) That makes sense. Dave (37:20.571) Mm -hmm. Daniel (37:29.902) one single organization, but then have roles for each individual customer of yours so that the different customers can't see each other's data. Dave (37:40.211) That's really cool. That's really very cool. And I can see, absolutely see how that gives your customers what they're going to need and gives you the flexibility you need to meet those needs. Sounds very, very involved, Daniel. Daniel (37:52.398) Yeah. It was very, I went in there in that rabbit hole pretty deep. It was very nerdy. It was also very fun. I also tried to make this, to do this as diligently as possible. So I wrote a huge amount of tests, especially on the API side. I created this whole matrix we talked about a few episodes ago where it would. Dave (38:10.481) Mm -hmm. Daniel (38:20.236) try out every single combination of permissions and compare against the expected and allowed results. Like, OK, now I have this set of permissions. Can I write to this endpoint? I can, but I shouldn't. And the big thing I was really afraid of was two things. One, I did have to touch a lot of API endpoints because, for example, endpoints that have to do with apps. Dave (38:27.891) Mm -hmm. Daniel (38:49.326) they now need a check whether the correct permissions are met. And so I needed to touch a lot of those. And so I also decided to upgrade the version of a few API endpoints. So my current API version is three. And I had a few endpoints that were just like bumbling around at version one or two because I'd never really updated them. And so I kind of had to update them. And that, of course, introduced the possibility of some breaking changes at the client side. And the other thing that I was really, really afraid of was the migration. Because when I flip the switch, when I say, hey, now the new version of the API is on the server, I need to take my database, and I need to completely automatically rewrite my database. Because before, I had, I don't know, a few thousand Dave (39:29.811) Mm -hmm. Daniel (39:47.52) organization objects and a few thousand user objects. And they just had a direct relation to each other. And now it's like, uh -huh. And now let's cut that connection, but then surgically insert roles and permissions in there. And make sure that the connections are made properly. So I tested that with a lot of tests as well. Dave (39:53.779) Mm -hmm. Daniel (40:15.118) I wrote that, tested it on my local machine with a copy of the database, but it's actually surprisingly hard to really accurately copy a Postgres database. Or at least I don't know the, maybe I don't know the correct way. Like if you just create a dump, it's kind of hard to read it back in or whatever. That kind of worked. Then the next thing I did was I actually cloned the database that we run on Microsoft Azure, which is actually very easy because... That's just like everything just gets cloned. It just takes a few minutes and you have a perfect one -to -one copy of the database. And then I pointed my local machine at that copy and let it run the migration. That worked. Then a few days later, I created a staging API in Kubernetes and then pointed that at another copy of the database. That worked partially, but it had a crucial... How do I say, like a crucial little bug, which was that usually we're running three copies of the API server on Kubernetes because you usually do that. So it's kind of distributed among multiple machines and it doesn't really hurt you. But of course then three instances try to run the migration code at the same time so that each organization ended up with three copies of the administrator role, three copies of the user role. Dave (41:32.851) Ha ha ha ha. Daniel (41:42.446) And then each of those had a connection to the user. So it seems on that copy of the database, it kind of looks as if each user is in each organization three times. But yeah, that was also the learning was just run the migration from a controlled instance and then not automatically from the API containers. And then finally, this Monday, four days ago, five days ago almost, Dave (42:03.059) Mm -hmm. Daniel (42:12.014) I was ready. I had run it on the staging server, a few friends, or I posted that on Macedon and let it run, let that beta be available for a few days and people caught a few bugs, which was really helpful, but most of the stuff kind of worked. And so I flipped the switch. It migrated the database in about three minutes. So we had a downtime of about three minutes where people wouldn't be able to log in. Dave (42:41.523) Yep. Daniel (42:41.934) and stuff just mostly works. Like I have a few bugs here and there that people have now reported and I'm gonna fix them one by one, but mainly using telemetry deck works and it's really cool. I'm so relieved. Dave (43:01.235) That's a big payoff after all of that work and the testing that you've done and everything else, Daniel. I mean, you know, you caught stuff, you found stuff. I think this is a... Daniel (43:02.86) Yeah. Daniel (43:14.606) Yeah, I also, I touched, like, you know, when you refactor, the danger is always, it's always dangerous to be like, oh, you know what, I'm also going to clean this thing up. Oh, and I'm going to refactor this as well, just like while I'm in the code anyway. That's always very dangerous. So I didn't allow myself to do that very much, even though I really, really wanted to. But I mean, I did update a few of the APIs, and they're bit nicer. Dave (43:33.715) Yes. Daniel (43:40.544) implementation -wise because some of those were still on callback -based Swift code, and now they're all try -await or async -await. And I also included, I finally found a way to include a Swift lint and Swift format into my development lifecycle. And so I cleaned up a lot of just linting issues and code formatting issues. Dave (44:09.043) Nice, so absolutely a spring clean as it were on your side. Daniel (44:13.742) Yeah, but I want to do so much more. But yeah, it really gave me a lot of motivation to work on this stuff because this huge blocker is now removed. And there are so many new options now because everything is a bit cleaner. Everything is a bit more streamlined. There's a new platform on which I can build new stuff and work on. And also just. It's been a huge relief to just not work on server stuff for a while, by which I mean like server hosting and server administration kind of stuff on actual software. That's definitely where my comfort zone is. Dave (44:54.875) appreciate that and for me that would yeah that make a lot of sense you've been in your zone with this really your your main lane as it were as a developer that's awesome Daniel and I think yeah it's got to feel very good merging in a branch that started back in November and kind of landing all of that Daniel (45:15.662) I don't want to go that far without merging for a long time now. Also, I rendered a really pretty picture for the blog post. So go to telemetrydeck .com slash blog. I think it's currently the newest entry or the second newest. It's called Telemetry Deck V5 because version numbers are still a very good marketing tool. And yeah, that's my way of celebrating a release. Dave (45:19.827) Yep. Dave (45:37.457) Mm -hmm. Daniel (45:43.982) I improve my blender skills every time I release something. I spend an hour or two just like noodling about with blender and then it usually looks better than the previous one. Dave (45:48.083) Ha ha ha. Dave (45:53.652) I'm looking at the image now. I'm not going to give an image description. People can go and take a look, I guess. But yeah, it's looking very, very slick, very polished as an image there, Daniel. And I love seeing what you do with Blender. Daniel (46:11.47) Thank you very much. I spent like, there's a telemetry logo sticker in there. And just like, I spent about 20 minutes just like perfecting the sheen on that sticker so that it has the correct amount of like diffuse reflection. Dave (46:18.641) Mm -hmm. Dave (46:27.91) Right. Dave (46:32.083) Awesome. Awesome stuff. Well, I might be pinging you for blender advice over the next month because one of the things on my literal list of things to do for updating Govj is that I want to update the demo content that I ship with the app. And that means I need to render some nice motion graphics and pull together some video loops for people. Daniel (46:33.294) Hehehehe Daniel (46:47.182) Mm -hmm. Daniel (47:01.102) I'd be happy to, but your kid released some really, really, really, really cool animations. Wouldn't you ask them? But I'd be happy to contribute as well, of course. Dave (47:08.691) I will be, I will be asking them to don't worry. Yeah, that's appreciated. Me and Blender have a, not quite a hate -hate relationship, but I've definitely had a bit of a struggled relationship in the past. It's one of those tools that's... Daniel (47:26.382) Yeah. Like back when I was in uni, people were using Blender and it was like any of these open source tools which are incredibly powerful but have a very, very different user interface than commercial software, let's say. And I kind of bounced off that hard as well. But now that Blender version 4 is like way more user -friendly, there's way more YouTube content on how to learn stuff. And also just with the... There's so many... Dave (47:42.195) Yes. Yes, I'm. Daniel (47:56.07) systems in there where you can use a node -based interface to basically program the content that's being generated instead of just like moving and pushing individual vertices by hand or something like that. So, and that's really my jam, I think. Dave (48:08.657) Mm -hmm. Dave (48:14.579) Yeah, yeah, because then you can get things just as you want them to be. Daniel (48:19.15) Yeah, and also like just repeatable, you know. Dave (48:22.259) Yeah, that's cool. That's really cool. I feel like we could do a whole other show talking about Blender Daniel. But unfortunately, I have to go as is typical at this time of the day. Yeah. So yeah, before we go Daniel, where can people find you? Daniel (48:29.39) Mm -hmm. Daniel (48:34.318) You gotta run. Daniel (48:42.734) My Blender blog is telemetrydeck .com slash blog. I also make some release some software there, but it's mainly about the Blender images. Also, please see me post my rendered images on mastodon at daniel at social dot telemetry deck dot com. What about you Dave? Dave (48:52.529) Mm -hmm. Dave (49:02.355) Well, you can see all of my videos of me messing around with NDI and sending stuff back and forth over on the mastodons over at Dave at social light beam apps dot com. And you can also find out more about my apps on light beam apps dot com. Daniel (49:21.806) Fantastic. All right. Have a fantastic day, Dave. If you're listening to the show, please write us at contact at waitingforreview .com. Please rate us on iTunes, on YouTube. Leave comments. Rate us on where? Where can people rate us? Can people rate us on Spotify? I don't even know. Dave (49:41.427) I have no idea. I've never used podcasts on Spotify. Daniel (49:46.872) Um, yeah, but have a fantastic day and see you soon, Dave. Dave (49:50.291) Take care, Daniel. Daniel: Byeeeee! (Both wave) Daniel (49:54.38) (Waving at the camera is very important.)