[{"data":1,"prerenderedAt":464},["ShallowReactive",2],{"footer-primary":3,"footer-secondary":93,"footer-description":119,"request-review-strictness-of-api-errors":121,"request-review-strictness-of-api-errors-next":192,"sales-reps":212},{"items":4},[5,29,49,69],{"id":6,"title":7,"url":8,"page":8,"children":9},"522e608a-77b0-4333-820d-d4f44be2ade1","Solutions",null,[10,15,20,25],{"id":11,"title":12,"url":8,"page":13},"fcafe85a-a798-4710-9e7a-776fe413aae5","Headless CMS",{"permalink":14},"/solutions/headless-cms",{"id":16,"title":17,"url":8,"page":18},"79972923-93cf-4777-9e32-5c9b0315fc10","Backend-as-a-Service",{"permalink":19},"/solutions/backend-as-a-service",{"id":21,"title":22,"url":8,"page":23},"0fa8d0c1-7b64-4f6f-939d-d7fdb99fc407","Product Information",{"permalink":24},"/solutions/product-information-management",{"id":26,"title":27,"url":28,"page":8},"63946d54-6052-4780-8ff4-91f5a9931dcc","100+ Things to Build","https://directus.io/blog/100-tools-apps-and-platforms-you-can-build-with-directus",{"id":30,"title":31,"url":8,"page":8,"children":32},"8ab4f9b1-f3e2-44d6-919b-011d91fe072f","Resources",[33,37,41,45],{"id":34,"title":35,"url":36,"page":8},"f951fb84-8777-4b84-9e91-996fe9d25483","Documentation","https://docs.directus.io",{"id":38,"title":39,"url":40,"page":8},"366febc7-a538-4c08-a326-e6204957f1e3","Guides","https://docs.directus.io/guides/",{"id":42,"title":43,"url":44,"page":8},"aeb9128e-1c5f-417f-863c-2449416433cd","Community","https://directus.chat",{"id":46,"title":47,"url":48,"page":8},"da1c2ed8-0a77-49b0-a903-49c56cb07de5","Release Notes","https://github.com/directus/directus/releases",{"id":50,"title":51,"url":8,"page":8,"children":52},"d61fae8c-7502-494a-822f-19ecff3d0256","Support",[53,57,61,65],{"id":54,"title":55,"url":56,"page":8},"8c43c781-7ebd-475f-a931-747e293c0a88","Issue Tracker","https://github.com/directus/directus/issues",{"id":58,"title":59,"url":60,"page":8},"d77bb78e-cf7b-4e01-932a-514414ba49d3","Feature Requests","https://github.com/directus/directus/discussions?discussions_q=is:open+sort:top",{"id":62,"title":63,"url":64,"page":8},"4346be2b-2c53-476e-b53b-becacec626a6","Community Chat","https://discord.com/channels/725371605378924594/741317677397704757",{"id":66,"title":67,"url":68,"page":8},"26c115d2-49f7-4edc-935e-d37d427fb89d","Cloud Dashboard","https://directus.cloud",{"id":70,"title":71,"url":8,"page":8,"children":72},"49141403-4f20-44ac-8453-25ace1265812","Organization",[73,78,84,88],{"id":74,"title":75,"url":76,"page":77},"1f36ea92-8a5e-47c8-914c-9822a8b9538a","About","/about",{"permalink":76},{"id":79,"title":80,"url":81,"page":82},"b84bf525-5471-4b14-a93c-225f6c386005","Careers","#",{"permalink":83},"/careers",{"id":85,"title":86,"url":87,"page":8},"86aabc3a-433d-434b-9efa-ad1d34be0a34","Brand Assets","https://drive.google.com/drive/folders/1lBOTba4RaA5ikqOn8Ewo4RYzD0XcymG9?usp=sharing",{"id":89,"title":90,"url":8,"page":91},"8d2fa1e3-198e-4405-81e1-2ceb858bc237","Contact",{"permalink":92},"/contact",{"items":94},[95,101,107,113],{"id":96,"title":97,"url":8,"page":98,"children":100},"8a1b7bfa-429d-4ffc-a650-2a5fdcf356da","Cloud Policies",{"permalink":99},"/cloud-policies",[],{"id":102,"title":103,"url":81,"page":104,"children":106},"bea848ef-828f-4306-8017-6b00ec5d4a0c","License",{"permalink":105},"/bsl",[],{"id":108,"title":109,"url":81,"page":110,"children":112},"4e914f47-4bee-42b7-b445-3119ee4196ef","Terms",{"permalink":111},"/terms",[],{"id":114,"title":115,"url":81,"page":116,"children":118},"ea69eda6-d317-4981-8421-fcabb1826bfd","Privacy",{"permalink":117},"/privacy",[],{"description":120},"\u003Cp>A composable backend to build your Headless CMS, BaaS, and more.&nbsp;\u003C/p>",{"id":122,"slug":123,"vimeo_id":124,"description":125,"tile":126,"length":127,"resources":128,"people":8,"episode_number":132,"published":133,"title":134,"video_transcript_html":135,"video_transcript_text":136,"content":8,"status":137,"episode_people":138,"recommendations":170,"season":171,"seo":191},"243daa59-3772-4ebe-b212-c2a09a4a0b71","strictness-of-api-errors","950779919","In this recording of our live event on May 23 2024, Daniel, Jonathan, and Rick discuss making the strictness of API errors","6d44c6a0-aaa7-4ad2-bbcb-d6e0f1de2829",54,[129],{"name":130,"url":131},"Discussion","https://github.com/directus/directus/discussions/4368",8,"2024-05-30","Strictness of API errors","\u003Cp>Speaker 0: Thank you for joining for this week's, session of request review. We have a fascinating topic for you, which is a little deeper than you think from the from the title. But thanks for joining. We hope you like it. This week's topic is about the strictness of API errors.\u003C/p>\u003Cp>So what does that even mean? Let's kick off with that. Everybody knows software doesn't work always quite how you want it to work, so sometimes you will receive errors in your application, and Directus is no exception. So as you might have noticed, we are very strict as of right now. So if you do something wrong, chances are high that you're just gonna see the message forbidden.\u003C/p>\u003Cp>Like, even when the message, even when the error isn't actually that type of error. So why do we even do that? Throw throwing the, throwing the conversation ball to mister Reich over there, please.\u003C/p>\u003Cp>Speaker 1: To me? Oh, man. Why do we do that? Well, it stems from a security report back in those days in that if you, let's let's use let's use a, a a 4 zero four as an example because it's it's an easy one to think about. So let's say you're fetching a collection that doesn't exist.\u003C/p>\u003Cp>Right? So you should get a 404 because the thing doesn't exist, so there's no route for it. No endpoint. If we would return a 404 for those, you could theoretically extract what the data model looks like by brute forcing your way through the whole API and checking which things return a 404 and which things return a 403, which, you know, to some security minded folks or setups, that's an issue because you don't wanna expose what type of data that you're managing in this system for security reasons. Now this is immediately where we're kicking off with opinions.\u003C/p>\u003Cp>Speaker 0: Let's go.\u003C/p>\u003Cp>Speaker 1: Because you can definitely, you know, you you can see it from both sides. You can easily say, well, that just makes the developer experience very annoying. And that's also why I created this feature request the moment I built it in this way. But it makes sense from a security perspective. Right?\u003C/p>\u003Cp>It's a similar reason why, during login, it'll say wrong email password or account doesn't exist, but you never exposed which of the 2 it is just to make sure that people can't slate, you know, what users exist. And the same goes for, you know, individual items in records. It's like you wanna, you wanna make sure that you can't just say, okay, slash item slash xyz and just keep scraping all of the different numbers, and now you know exactly what records exist, etcetera, etcetera. Somebody rightfully called out, you know, nobody does that in this trustworthy world, which I think sort of concludes this discussion then. Just ignore it.\u003C/p>\u003Cp>Speaker 0: Lying on the Internet? What? Who does that? No. What?\u003C/p>\u003Cp>No. No. No. We don't do that. And a perfect example.\u003C/p>\u003Cp>So leaking of information is a very, very big thing. You don't want to expose stuff that you don't have to expose, but as you just said, it would be nice, for example, like the most basic, setup when you're just developing locally, it would be nice if you could actually see what went wrong. Because currently, it's just okay, forbidden. Nope. No information for you.\u003C/p>\u003Cp>So then the question comes. Oh, La Prima asked, can we go on stage? Sure thing. I think so. But let's let's first, summarize a little bit.\u003C/p>\u003Cp>So There should be\u003C/p>\u003Cp>Speaker 1: a button somewhere.\u003C/p>\u003Cp>Speaker 0: The question is. Yeah. Yeah. Exactly. So, immediately the question comes to mind.\u003C/p>\u003Cp>Okay. So if you would have multiple errors in that case, a strict one which just says forbidden and another one that has more information, Okay. How many different errors would you even like to have? So are we happy with just 2? Because, I guess this is opinion alert or something, or maybe even a useful thing for many other people.\u003C/p>\u003Cp>Like, what what do you guys think about this? Like, how many error, different error, messages would be nice, would be good. Useful.\u003C/p>\u003Cp>Speaker 1: I mean, that is very much a sliding scale, isn't it? Because you really go from, from like, just give me every single thing. It's like, oh, I was trying to read the articles collection that I don't have access to. So I'm gonna get a forbidden error that says, well, articles exist, but you can't read it. And that's because of this permission that you don't have.\u003C/p>\u003Cp>For development purposes, that's really nice. But if you go to production with that, it's tricky because now you're just exposing a bunch of information about, you know, your setup. So, yeah, I'd I'd say it it there's a large range there's a large range in in that. And even within that forbidden error, you know, we can, think about how we wanna return stuff. So one thing I've been working on recently as part of this the the rules and permissions sprint that we'll we'll ship in soon is the, is that forbidden errors now include a little bit more information as in, you know, the field x that you were trying to query, you know, you don't have access to it or it doesn't exist, but at least it's a little bit more explicit while not necessarily exposing the schema, but just exposing what part of your query is wrong.\u003C/p>\u003Cp>Right? Which is not leaking any of that information but still being a little bit more useful.\u003C/p>\u003Cp>Speaker 0: Alright. That does sound exciting, to be honest. Like, it's such a developer thing, like, normal users. I don't know if how how many people care about this, but this is such a nice thing for developers. So I gather from your answer right now maybe 3 types of messages.\u003C/p>\u003Cp>At least from your answer, it sounded like 2 in the beginning, like, one strict one with a little bit of information, but that could be counted as 3, right? Like the very strict one with nothing, a strict one with a little bit, and another one with very much information. Are we happy with 3?\u003C/p>\u003Cp>Speaker 1: No? Yes. Asterisk. There's one more tricky thing in that the output type signature of the errors themselves change between those modes Right? So for example, if you're trying to fetch a thing that doesn't exist, we want to return a 404 status code with a not found error message.\u003C/p>\u003Cp>If you then program your app around that, you know, that it on your front end, it shows, you know, something because it checks 4 Oh, it was a 404 status. Therefore, do this logic. Right? The moment you now change that option to be strict when you go to production, that messes up again. Because now it's returning a 403 with a forbidden instead of a 404 with a not found.\u003C/p>\u003Cp>Cricky.\u003C/p>\u003Cp>Speaker 0: So Let's see. May maybe maybe after we dive in a little bit deeper, we have more clarity around this. But so far, like, I personally like would like, I think, 3 modes. Let let's call them levels. Do we call them levels, modes?\u003C/p>\u003Cp>I think levels. Right?\u003C/p>\u003Cp>Speaker 1: Yeah. It depends. As per usual, it's\u003C/p>\u003Cp>Speaker 0: great.\u003C/p>\u003Cp>Speaker 1: It it depends on, you know, are we considering multiple different flavors at the same time, or is it just an on and off? Because somebody in the chat just now rightfully mentioned, maybe it's just a single production versus development flag that changes that. Right? It could also be a setting within the app. Maybe it's even a setting on a per collection basis that you wanna say, well, this collection is not as, you know, private as the other ones.\u003C/p>\u003Cp>So for this one I wanna have, you know, nice and friendly, messages. And for the rest, we wanna keep private. There's options. It's tricky. It's it's when it comes to a single sort of Boolean flag that says production yes or no, I would be a little bit worried about getting into a point where undoubtedly 3 months later, somebody will show up and be like, well, we kinda need something in between.\u003C/p>\u003Cp>You know?\u003C/p>\u003Cp>Speaker 0: Exactly. You\u003C/p>\u003Cp>Speaker 1: can't really\u003C/p>\u003Cp>Speaker 2: Or more importantly, somebody develops in development mode thinking they've got those messages, then they move that code to production, and suddenly nothing works.\u003C/p>\u003Cp>Speaker 1: Right. Which is gonna be a bit of an issue no matter what because\u003C/p>\u003Cp>Speaker 0: Agreed.\u003C/p>\u003Cp>Speaker 1: We're not talking about, you know, changing the output errors. You could consider those, part of, the the what what would you call it? The public API contract of the APIs that you're building against. Right? Because because, you know, in your intro then, you said stuff sometimes crashes, and that's just part of part of software life.\u003C/p>\u003Cp>Stuff crashes on purpose. Right? In this case, like when validation fails, it's we're still throwing an error, but it's not an unexpected error or anything else. It's, you know, we stop you from doing something on purpose, so we throw an error, which is, you know, a bit of a difference there as well, of course. Because when it comes to exposing internal server errors, it's a whole different question.\u003C/p>\u003Cp>Because right now we do a similar thing, right, where we say you just get internal server error. That's it. Like regular users don't see anything else. If you're an admin user though, that's today, that's the difference. It'll show, you know, the stack trace of the actual JavaScript error, with where in the source codes it it it happened.\u003C/p>\u003Cp>So but exposing internal server errors to non authenticated users, that's gonna be that could easily become an issue. Right? Because now you find some sort of vulnerability path or whatever that's you don't wanna expose that.\u003C/p>\u003Cp>Speaker 0: Definitely.\u003C/p>\u003Cp>Speaker 1: From the chat, somebody has a suggestion here. It says, what about setting a trusted IP address? So you can just say, okay. When I am the one from my home to do this, I get all the pretty errors and otherwise, I can't. I think you're gonna have a similar issue with, you know, def versus prod, strict versus friendly error types, and how do you handle those in your app.\u003C/p>\u003Cp>It's gonna be a tricky tricky thing to figure out. And then somebody else said, the only thing where that really isn't enough is when there's a delete constraint. Users trying to delete items, and they can be deleted because they're still a referencing item. Admins already get a little oh, yeah. That's yeah.\u003C/p>\u003Cp>Because right now that is technically, a database error that bubbles up. So it comes out as an internal server error that for admins, it'll show the the SQL error underneath. But for regular users, they just get a whoops, you know, internal server error.\u003C/p>\u003Cp>Speaker 0: Also with the IP, since currently currently, IP access, is attributed to roles. Right? You you customize that on a role with that access. So we could use that, but it does, like, sound very, very, very likely to me that you wouldn't be interested in, like, giving this to every single user of that role. You would like to have something more granular than that.\u003C/p>\u003Cp>So how about this also comes from, someone from the community. How about we attach this to permissions themselves? So let's say this user can access this and that, and that user is authorized to receive better errors than other users. For example, like, the simplest example, like admin users. Right?\u003C/p>\u003Cp>Mhmm. Like, all admin users are allowed to get the best errors that you can, But users other users get strict errors. Okay? But that, yeah. That's that, like, I I I'm not really sure how exactly complicated that would be to do at every single point in the in the code base.\u003C/p>\u003Cp>Speaker 1: Well, I mean, in in terms of implementation, how like, they currently were throwing forbidden errors all over the place, but the way this would work in implementation is right at the end where we return the error in the APIs, that's where the sort of translation layer kicks in. Right? So all over the code base, it should just throw the actual errors or the actual error types and the correct ones. So if you're trying to hit something that doesn't exist, it should throw a not found error. And then all the way at the end in the middleware stack in the error response handler, it should say, oh, if your current, you know, e n v setting for errors or if the, which I'm gonna call it, if the the error permissions or whatever you wanna call it are set to a certain state, then it translates them into a different way.\u003C/p>\u003Cp>I think that's the way that that will be implemented realistically speaking.\u003C/p>\u003Cp>Speaker 0: Yeah. That does sound quite good. Adjust intercept as a middleware. Okay. You are allowed to see this or not.\u003C/p>\u003Cp>Okay.\u003C/p>\u003Cp>Speaker 1: Yeah. Because we're doing that on a case by case. It's gonna be insane. Just trying to do it every single time that we throw an error. That's that's too much.\u003C/p>\u003Cp>We currently already do a similar thing, right, where the the error handling stack, we check was this a direct as error type or any other error and that chooses between internal server error or, sort of the the expected error output.\u003C/p>\u003Cp>Speaker 0: Very reasonable. I think, if somebody from the chat also has another recommendation or anything, please let us know. There's quite a quite a bit of action today, which is pretty nice, actually. Like, seeing the chat scroll up and down is pretty nice. Somebody says, I can't explain it in the chat, but I'll try.\u003C/p>\u003Cp>That's lovely.\u003C/p>\u003Cp>Speaker 2: Well, well, La Prema can if if you you guys are okay with it, La Prema can join us on the stage.\u003C/p>\u003Cp>Speaker 1: Yeah. I'm down. There should be a button somewhere that just says, I\u003C/p>\u003Cp>Speaker 2: can invite them or they can add they can request, but we can also do an invite.\u003C/p>\u003Cp>Speaker 1: How is that often with these?\u003C/p>\u003Cp>Speaker 2: They asked to speak earlier, so I'm inviting. Or have they does Kevin have that blocked in this event?\u003C/p>\u003Cp>Speaker 1: Oh, boy. With this guy.\u003C/p>\u003Cp>Speaker 2: Nope. Nope. There we go.\u003C/p>\u003Cp>Speaker 1: I got the invite. I got Does it work? I got\u003C/p>\u003Cp>Speaker 2: him up here.\u003C/p>\u003Cp>Speaker 3: I'm trying to\u003C/p>\u003Cp>Speaker 0: see if I wait. Weekend.\u003C/p>\u003Cp>Speaker 3: Yeah. It works. Okay.\u003C/p>\u003Cp>Speaker 1: It works. Hello. Welcome. Hello.\u003C/p>\u003Cp>Speaker 3: As always, sorry for my accent. I'm I'm Frenchy. But, like, I Don't worry.\u003C/p>\u003Cp>Speaker 1: You're you're chatting with a Dutch and a German, so we we know you need to know the guy.\u003C/p>\u003Cp>Speaker 3: Oh, yeah. But your English is better than mine. I don't know if you remember, but we used to talk to Get A Rich for about the the error management system. And at that time, I was working for a company who uses directors, but I leave them. So after, what I haven't the time to to follow the the the case of the the server management system.\u003C/p>\u003Cp>But, I think the the main problem, we had is is, dealing with the the the, yeah, the, like, the granular system of a thing. And what I proposed at the that time was, like, adding in the the collection a a new, column, like, you already have, edit and all that stuff. And, in permission, column where you will have, like, 1 or 2 level no. Mostly 2, but 2 or 3 level of, strictness of the error. Like, do do do I wanna send them all on that collection or not?\u003C/p>\u003Cp>Because, yeah, I I think that would be the I'm sorry. But because it's user related, it would be better for the companies. Because, if you if you, like, have only one private, instance of directors, I think it's not a problem to throw error to people because they are part of the company. So if they don't, respect them, their permissions, you they can have, like, legal, troubles, and this is possible. But if you have, like, an public API and also a private one, On one instances, if it's just a mode, I think it won't fit because a lot of data can be really sensitive.\u003C/p>\u003Cp>And, same goes with the developer mode. Yeah. I I totally agree with, like, developing something, in a in a development mode and then going to production, it doesn't work. That would not be a solution for me. And, as well that the the this this production and development mode would be probably used somewhere else, at another time.\u003C/p>\u003Cp>And, in a long term view, that will just lean in people active in the development, mode every time and, development searching, be thrown everywhere.\u003C/p>\u003Cp>Speaker 1: Yeah. That's right. It's such a tricky, and I I think if that, what was that nodes flag called? It node e and v or something as taught as anything is that you should not rely on a single dev and prod flag. Yeah.\u003C/p>\u003Cp>No. It's a good one. It's the the doing it on a collection level, on a permissions level for for collections, basically. It's it's a good angle. It's it raises some different interesting questions though as per usual.\u003C/p>\u003Cp>Everything does, Especially around requests that touch multiple collections at the same time, right? Where in REST, you can technically go, you know, nest it and then you end up with you could have an error that's thrown in the sort of nested layer of the same request. Or in a GraphQL request, you can technically request multiple collections at the root level at the same time. And then it gets a little interesting because now you can get, you know, a different error output from that request based on which of the data points of that request crashed, I guess, instead of, you know, the request itself,\u003C/p>\u003Cp>Speaker 3: which opens a little\u003C/p>\u003Cp>Speaker 1: bit of a different kind of words.\u003C/p>\u003Cp>Speaker 3: Yeah. But I I think in some case, that's what we want. Because, in the the app I I was working on, we we used to to to get in that kind of problem where, we have people, who had access to certain company, but not certain order. And we retrieve that data in one block. And if some points fails, the the whole, request will fail, so we'll have to deal with that.\u003C/p>\u003Cp>And, what what we can do at that point, I guess, it's when you you have the error only in one part of the query, it's just returning not an error not an error code, but just like in the API, an error, tag in, that object and not all the thing. But I I know that would be, like, a big breaking change. So it can be hard to implement for some people. But, I guess, by default, if we just disable all the error, like, the the basic settings will just be, what Direct just currently does, it won't be a problem because the people who turn the the feature on, would know what they do or or would have ways to find out.\u003C/p>\u003Cp>Speaker 1: I think that is\u003C/p>\u003Cp>Speaker 0: You're you're just assuming that people know what they do. I barely know what I'm doing. And when when I add features oh, no.\u003C/p>\u003Cp>Speaker 1: I think, it it there's a there's a new question hidden in there that we hadn't touched on yet, nor in our notes right now, which is if an error is thrown somewhere nested, let's say, you know, the let's use the GraphQL as an example because it's it's easy to reason about. Let's let's say you're requesting 5 collections of data at the same time. Right? And one of the 5 crashes. The question is, do you return an error and the whole thing failed, or do you return the data that worked and then have an additional error flag that just indicates this is the path of your query that didn't work?\u003C/p>\u003Cp>But return what you have and leave the rest.\u003C/p>\u003Cp>Speaker 3: And, I think for that opinions. Yeah. I think for that, the the the best way to to do it is just, like, throwing the error only for what phase. Because, if we use these directives, I assume it's that we just want to cut the the front end. And and so, it it would be, most of the time, like, an interactive app or a single page application on or something of of that kind.\u003C/p>\u003Cp>And those kind of errors are really easy to to treat with that method. So and and, I I think most of the time, if we activate the the feature, it's what we want because, that will lead in, less, just big crashes, like internal server error proof and nothing worse. So I don't know.\u003C/p>\u003Cp>Speaker 1: It's it's an interesting one because, somebody in Chet just now says it too. It's a rather fundamental question. But, you know, you see both in the wild, and both are kinda alright. It's it's, there's also an implicit difference between, you know, reading and write operations there as well, of course, that if you do a large nested update, you kinda want it to work as a single unit, as a single transaction to make sure that if, you know, part of the insertion doesn't work or part of the update, the whole thing shouldn't, you know, go through because otherwise you have that sort of half half done state. But for read queries, it could be different, but that really depends on, you know, what are you reading, and is it all tightly coupled, or are you reading multiple things at the same time for convenience sake?\u003C/p>\u003Cp>Because if I'm not mistaken, in in sort of the GraphQL spec, Like, it allows you to return partial data and then errors for other root fields. But I feel like if there's an error in a nested field in the query, it'll still fill that one sort of root query as a whole. But that is that is something I love to double check.\u003C/p>\u003Cp>Speaker 0: Yeah. Yeah. I'm I'm I'm not sure either. Like, my my gut feeling was, no. I I I don't wanna say something wrong right now.\u003C/p>\u003Cp>So, okay. Another another suggestion from the chat. How about hashing the error plus a UUID, I assume that is? Only admins will be able to see what the error really is. Well, I mean, I mean, you are probably talking about, like, error codes.\u003C/p>\u003Cp>Like, for example, many different other apps just say, okay this is error 3, 1,172 or something. And then you can look up internally what that exactly means, But, you would still be missing out on, like, more information, like the stack trace or which which file failed or something something that you would have to encode in that thing, but I don't think that's always possible or\u003C/p>\u003Cp>Speaker 1: even Or to just think very divergently. You know, an alternative approach is that you basically encrypt the whole error, save that to a database, and then only return the ID of the error that it was. So then the admin can log in and look up what the full stack was and and and and sort of decrypt it and see the whole the whole contents and everything else. But that that feels like a way to sort of persist to security and give more information at the same time. But it also feels like another skip and a hop and a skip for regular users to be able to just, you know, use do the errors that are output.\u003C/p>\u003Cp>Speaker 0: That's an interesting thing. I have never thought about it like that. People do that? Do their apps do that? That's interesting.\u003C/p>\u003Cp>Speaker 3: Yes. Some app does. I I used to work on one with the that. But I think it's the it's a problem because, like, most of the time, you you wanna informing in some way your user of what the error is because you don't want to to get someone just to to create a ticket to the IT support just every time they need, something, didn't work. But they just didn't have the permission in the first time.\u003C/p>\u003Cp>So, yeah, I don't think, it's a global sit solution. But maybe in some case in some case, if if we add, like, an EMV approach, that would be a a great option for some people that maybe need that.\u003C/p>\u003Cp>Speaker 1: And I could see it work like that for for internal server errors. Right? Well, that's one of those things where we wanna hide away the stack trace no matter what for for the API output and then save it elsewhere. But at the same time, you know, saving every error could easily blow up in your face too, because if you just have, you know, an unauthenticated user that tries to access some data there's no permissions for, we don't wanna save those. Right?\u003C/p>\u003Cp>Because now you could easily just blow up a database by a public malicious actor that just spams your API knowing that they're gonna get errors. So there is there is definitely a a difference between sort of expected and unexpected errors there and which ones are saved. Have AI blocked them. AI solves all of our problems.\u003C/p>\u003Cp>Speaker 0: Sure. Just do what I want. Parentheses open, parenthesis close. That should do it. Right?\u003C/p>\u003Cp>If only if only it would be that easy. K. So let's let's summarize a little bit because we have been, you know, throwing stuff out there. Maybe we should get back to reality a little bit. So, okay.\u003C/p>\u003Cp>So so let's say we have, we like to use the Moscow list. Right? The must have, should have, could have, type of stuff. So for must haves, let's let's get on the same train. Like like, what do we need?\u003C/p>\u003Cp>What what must we include? So, yeah. How granular do we make this? Oh, no. It has to be actionable, man.\u003C/p>\u003Cp>It has to be actionable. Okay.\u003C/p>\u003Cp>Speaker 3: I I think the the point where we've been stuck the the last time was reached is, like, we we both agree on the fact we need a granular system, but we both must agree, on the fact that it would be so long to to make and to think and all that stuff that maybe it would be nice to have something, before that. But,\u003C/p>\u003Cp>Speaker 1: Right. Yeah.\u003C/p>\u003Cp>Speaker 3: Yeah.\u003C/p>\u003Cp>Speaker 1: Yeah.\u003C/p>\u003Cp>Speaker 3: But, I I think, that's, my my point was, like, directors, is a tool who is proposing things like a a different way than the other, tools in the same category. Like, you you just want it to to be a little more, accessible and, and usable. And not just, like, being that's the way you should do that and, just follow it. And and so I I think that's the problem there. If we did something else, than a granular system, you would, follow a path that doesn't feels like directors to me.\u003C/p>\u003Cp>And I don't know that that's totally your point, but but, I I'm not sure if that's what people need. Otherwise, they they will lose WordPress or or something like that.\u003C/p>\u003Cp>Speaker 1: You you you sound like a team member in the sense of when the choice arises, let's do it the difficult way and make it unopinionated wherever we can. So no. I I do agree though. I do agree because it's it it is at the end of the day, this is a very opinionated thing, where for some apps, it's acceptable to have it a little looser or even want it. For some, you know, security minded folks, it's absolutely not, and we can't really make that decision for people at that global level, even though we have right now.\u003C/p>\u003Cp>Oops. Right now we are on the side of safety first, which, you know, it's it's defendable, but not ideal. Like, that's also why I created that feature request. It feels like decades ago, but it was 3 years. I think that the the main unresolved question now, and and that is sort of to answer your point, Dan, before we can really fill in the blanks for what are the must haves, is what is that ideal approach to how do you configure this?\u003C/p>\u003Cp>And then from from a developer experience first and then secondly does that make sense from an implementation perspective. Because doing it on the collection scope level makes sense for errors that are thrown on the collection scope, but not all errors are thrown within the context of a single collection. So that that that opens up, you know, new questions. And the opposite is true for doing it globally on the e and v level. Right?\u003C/p>\u003Cp>Because, you know, it's a low pretty much excellent point. It's not that black on white that you say make it insecure for the whole API. You know, you wanna do it on a case by case basis. That is a that's a that's just a statement with no no answer.\u003C/p>\u003Cp>Speaker 3: No. I don't another, I don't know what to say it in English, but, like, another thing we, think about at time was, like, just, if if we take, like, the the point, if we need the error, it's just to treat them. One, thing, which, was a a little bit, between the two option is just like, having some kind of way to tell directors just, okay. This error, I want you to to throw it, and other errors I don't want. So that would be a little bit more granular, but that would be more like, just a techy approach.\u003C/p>\u003Cp>And and then not, being, so universal.\u003C/p>\u003Cp>Speaker 0: Oh, Rike, you're muted, by the way.\u003C/p>\u003Cp>Speaker 1: I hit the wrong mute button. That's what you get when you have 2. I I muted myself here, and then I and then I muted myself to unmute on this. Oh, man. I mean, we've only been doing this remote thing for about 5 years now, so I'm I'll I'll get it.\u003C/p>\u003Cp>Yeah. Because I what what I was trying to say is that that approach to say, okay, which error types do we expose? That is something we could do on the role level or soon to be policy level, And it is a system where we can still have one translation middleware that handles that error no matter where is thrown from, which is you if you compare that to the sort of collection idea that we had earlier, that one is a little trickier to implement in that sense, because now you have to make sure that you know what the collection context is for every single function call that may or may not throw an error. And then do that sort of translation piece, in in situ of where those errors are created, That makes sense. Whereas with, you know, an approach where you say, okay, not found errors can be exposed.\u003C/p>\u003Cp>If that's your setting, we can do that on one middleware at the end of the stack to just say, okay. Was the error\u003C/p>\u003Cp>Speaker 0: Again, I'm not sure if if I can wrap my head around every single edge case, but, like, it does sound and may maybe I understood it a little incorrectly, but it does sound quite easy to mess that up. Like, it to to to bubble to bubble something up that does not get blocked then. And somehow I am exposing a random error that I have not thought about, like, on on an error level.\u003C/p>\u003Cp>Speaker 1: It's it's the difference of an allow list versus a deny list is basically what you're saying. Right? So if you have a filter where you're denying individual pieces, it's easy to miss something. Whereas we do the opposite way where it's blocked by default and you allow more and more stuff, it's you can't really accidentally expose anything because nothing is exposed by default. Which is similar to what, Andre Andre Andre Key are.\u003C/p>\u003Cp>Just gonna assume that's how you pronounce it. Just said in the chat as well as, you know, if you really want it super granular, effectively just make it a rule based system, right. Where you run a filter against the error object that is thrown. Like if the error types is XYZ and the extensions contain blah, blah, blah, collections, such and such, then expose it, which will be one way to make that super granular, but also a little harder to configure at that point. Because I could, I mean, at the end of the day, I could also imagine that, you know, for just local development, that is gonna be a pain in the ass because now you have to configure so much stuff to get the errors out.\u003C/p>\u003Cp>Speaker 3: I I think we what we could do is just like doing an EMV, variable just for real development case, then that system for the production mode. And later on, if we think it's too difficult or, then we can add the system, with the the permissions because that would make, like, stacks on top of each each other, with the the the the first step would be, like, the programmatic approach on the error throwing and all. And then, the the we could add later on just, instead of just throwing nothing if the error do not doesn't match, any case. Like, is it a permission error? Then is there a plain way to treat it?\u003C/p>\u003Cp>So it's made steps, and we have something, in between no permission management and on the other end, full thing.\u003C/p>\u003Cp>Speaker 2: What this makes me think of is the we've got a client that we're playing around within a proof of concept. They're they're actually have an error table for their front end, and they've actually got translations. So they've actually got a translations table on that so that they can have the language the errors translated to multiple languages. If we went something like that where we have, like, a direct us errors collection, right, as part of the system tables with a set of, you know, with translation, then we have native translations capabilities right there. So if you wanna adjust the error message, so we could have the defaults.\u003C/p>\u003Cp>Right? The I don't know. We've got a dozen or whatever that we have now, with some variable support maybe even there so that if you wanted collection information or you want that stack trace information to percolate up, you could. And you could determine at least in the short term, we can we can avoid the permissions for the short term, give you just control over your error messages. You wanna show something that we don't do natively by default, well, you can override the messaging as a thought.\u003C/p>\u003Cp>And I think that would actually help with things like flows as well. We have the same problem in flows. We can't percolate an error message to the user even though we're throwing and controlling the erroring of the of the workflow. Potentially, if we think about it in that context as well where we've got we could use that same error structure\u003C/p>\u003Cp>Speaker 1: Mhmm.\u003C/p>\u003Cp>Speaker 2: Idea. Not a not necessarily the solution or the right solution, but\u003C/p>\u003Cp>Speaker 1: here's the new rabbit hole, multilingual error output for the API. Oh, boy. Oh, boy. I mean, sort of it's an interesting angle to to sort of noodle on a little bit. The the general idea of errors as it stands right now is that you basically return an error code that is one of the standard sort of known error types.\u003C/p>\u003Cp>And then in whatever app that you're building, you can basically just say, you know, oh, if the error is not found, then use my own translations and my own front end and all that kind of stuff. But yeah. I mean, it it does raise I mean, we we know we need some sort of translations in the API no matter what for email templating, which has been that'll be a fun discussion for another day. But, yeah, it's it's an interesting idea to have errors as a sort of system collection that you can then modify. Although, we would have to hard code in what the keys are because otherwise, we don't know what error to throw still.\u003C/p>\u003Cp>That's a tricky one.\u003C/p>\u003Cp>Speaker 2: But we can hard set the keys. Right? And then if you create your own key or we lock the table, you're not allowed to add to it, you know, without core functionality. Or, again, you've got your hard set core pieces. Core knows what they are, and they can't be changed.\u003C/p>\u003Cp>Their primary key or whatever we wanna do around that Yeah. Gives us that level of flexibility. But then if users want to code other error messages for other applications and data, they can actually still maintain it in all in one place. I'm not smart enough to solve it. I just I just know that's an implementation I saw recently where we're for a front end application and the error messages that they wanna generate for that front end application.\u003C/p>\u003Cp>They're actually doing that in a set of tables. Kinda cool.\u003C/p>\u003Cp>Speaker 0: Oh, I think, like, lots of interesting things that we can do, but I think we're still stuck on where do we want to control this or configure this. Let's just go to the one extreme. I mean, very That would be the easiest thing.\u003C/p>\u003Cp>Speaker 1: You have\u003C/p>\u003Cp>Speaker 0: to And you get errors. Okay. Done. That's the easiest thing that we can do. That leaves a couple of things that we would like to have open.\u003C/p>\u003Cp>Right? Like, we ideally, or at least in my mind, it would be really useful if, for example, like, admins actually get no like, good, context rich errors and normal users don't, which would you know, it's not really that possible with that environment variable approach.\u003C/p>\u003Cp>Speaker 1: Yeah. So so it feels to me like out of everything that we've discussed so far, the direction where you effectively set up and allow list of errors on the role or soon policy level gives you, so far everything that we sort of want to achieve. Right? Where you can say, okay, you can allow one admin role to just see all of the errors with some sort of wild card flick, accept everything, allow everything. You could use the filter rules to be more granular that you could say, oh, if the error contains a collection, flag, then filter against that.\u003C/p>\u003Cp>So So you can you can do sort of the collection by collection, filtering. And, yeah. You you get to choose role by role, so make it admin only or make it make it, a different, you know. So the users can only see the granular errors for a a collection that's already public or something like that.\u003C/p>\u003Cp>Speaker 3: The the only problem there, it's for the flows. But, like, what do we do with them?\u003C/p>\u003Cp>Speaker 0: Mhmm. Mhmm.\u003C/p>\u003Cp>Speaker 3: For flow, that's\u003C/p>\u003Cp>Speaker 0: a grant. Like\u003C/p>\u003Cp>Speaker 3: Because I I think we could have\u003C/p>\u003Cp>Speaker 0: close the\u003C/p>\u003Cp>Speaker 3: The same system, like, in the in the settings of the flows. But is it gonna be the same way?\u003C/p>\u003Cp>Speaker 1: But we could also say that if you trigger a flow, you are a user or the public role. So therefore, the same settings of your role should still kick in.\u003C/p>\u003Cp>Speaker 3: Yeah. Yeah. Because they access the data. So that's good point. But, like, what if you want to, bypass a permission on a specific flow?\u003C/p>\u003Cp>Like, then you'll because in some case, may maybe it's the the old data you don't want to access, but just one field you want to show someone?\u003C/p>\u003Cp>Speaker 2: As long as the filtering's happening on the API level, that's still all API under you know, flows is still API under the hood. So if you uplift an operation, read CRUD, whatever, this the erroring although, I guess, it's still gonna then it would percolate to that user\u003C/p>\u003Cp>Speaker 1: type I think the the the underlying question is what if you want that error to be returned no matter what the settings are in your flow? Because your flow is effectively a custom endpoint or, you know, hook or whatever.\u003C/p>\u003Cp>Speaker 2: Yeah. That's what I think flows when you're throwing an error inside flows, that should be its own code. And if you throw a custom message back to that, then you should be able to get that custom message. That's the key thing that I always want. Right?\u003C/p>\u003Cp>Or that it the the initially, I thought was, oh, I'm gonna throw an error here and I wanna I wanna send back to the user, you know, you did x y z wrong, you know, or this this isn't allowed because you failed to give me the appropriate information instead of a internal server error, which means nothing. You know, I can't I can't tell the user what they've done wrong or what they're violating that I'm validating inside of my flow. I can't say, mister user, you must have your status in the right thing or, you know, these three fields have to be populated to be able to use this or\u003C/p>\u003Cp>Speaker 1: And and that's where the allow list approach for error filtering gets tricky again, because now you need to make sure that you allow list your custom errors from your flow in the policy or in the role, so it makes its way to the app.\u003C/p>\u003Cp>Speaker 2: Or I think, again, flows the error code or codes that are returned by flows, that there is a specific code, and you simply take the message that the user's providing out of the out of the, you know, exception. Yeah.\u003C/p>\u003Cp>Speaker 3: Yeah.\u003C/p>\u003Cp>Speaker 2: Yeah. Right. And so it's it's a known code. We know what it is. Right?\u003C/p>\u003Cp>We know\u003C/p>\u003Cp>Speaker 1: Oh, so here's here's another thing we haven't really message. Yeah. Another thing we haven't really touched on in with regards to flows is that, you know, you have a very explicit error handling path that every operation has a okay. If the error fill or if the operation fails, do something else. So maybe there should just be an explicit operation that says return the error, and otherwise it just defaults to, you know, hidden by default, but then it becomes it it no longer is a a permissions or roles thing.\u003C/p>\u003Cp>It just becomes a flow thing, where you just very exclusively have to end your flow with return the actual error. And at that point, it's up to the, you know, the admin to configure that flow and and whatever they want to return.\u003C/p>\u003Cp>Speaker 2: Love it.\u003C/p>\u003Cp>Speaker 3: Me too. Convinced. But\u003C/p>\u003Cp>Speaker 1: yeah. Yeah. Okay. Problem solved.\u003C/p>\u003Cp>Speaker 3: We would have we would have to to, like, also have a a custom error block, I think, if you if we do that that way.\u003C/p>\u003Cp>Speaker 1: Yeah. Yeah. Just an operation that says make a new error, whatever that error is.\u003C/p>\u003Cp>Speaker 3: Yeah. And you can pass the a variable or a text or something. Yeah.\u003C/p>\u003Cp>Speaker 1: Which is then a funny new completely unrelated question. But if you have a block that says create an error, is the good path the error or is the bad path the error?\u003C/p>\u003Cp>Speaker 3: I I think you can you can do this.\u003C/p>\u003Cp>Speaker 2: There is no path. You don't get to you don't get to leave. That's the end. You're finished. Termination note.\u003C/p>\u003Cp>Speaker 3: I think the I don't I don't know. Like, I think there you called it, like, grade pass and, error pass, but I think in so in some time, like, on the if call, trigger, the error pass is not really an error pass. So\u003C/p>\u003Cp>Speaker 1: Right. Yeah.\u003C/p>\u003Cp>Speaker 3: That would be sense to be both, really.\u003C/p>\u003Cp>Speaker 1: Yeah. So in the create an error operation, both both are the same. It just calls both.\u003C/p>\u003Cp>Speaker 3: Yeah. And then\u003C/p>\u003Cp>Speaker 1: Now you have oh, woah. Woah. But if it calls both, now you have a way to do parallel split paths because it's now\u003C/p>\u003Cp>Speaker 0: a trick.\u003C/p>\u003Cp>Speaker 1: That's a discussion\u003C/p>\u003Cp>Speaker 2: for the problem.\u003C/p>\u003Cp>Speaker 3: I I think that would be nice, but yeah. That would be a lot for that,\u003C/p>\u003Cp>Speaker 2: more importantly, I want merge capability. Be able to rejoin back into logic.\u003C/p>\u003Cp>Speaker 1: Oh, good lord. Now you have to wait for both to be done and oh, boy. Okay. Let's definitely not get into this.\u003C/p>\u003Cp>Speaker 2: We've got we've got very divergent. We have about 9 minutes left, folks.\u003C/p>\u003Cp>Speaker 1: Yeah. This this feels like another 6 hour discussion if we go that route.\u003C/p>\u003Cp>Speaker 2: It is a very, very long discussion. Flows 2.0. We're already doing some research on that, so figure out what that looks like long term. Okay. Back to API errors.\u003C/p>\u003Cp>Do we have an idea of what our must have\u003C/p>\u003Cp>Speaker 3: should have?\u003C/p>\u003Cp>Speaker 1: Yeah. I think my my current going direction is is basically the on the role level, there is an allow list type configuration that allows you to say there needs to be a wild card that says do everything for def purposes and otherwise you can use the sort of filter structure that we have to say these are the error types that we allow you to see, and these are the and then based on whatever the error contains, you can filter it more granularly if you want to. That's for me closer to a should have than a must have. The error types is really the main the heart must have MVP. Because then because our error objects, they are, you know, they have additional extensions is what I called them right now, which is basically, a not found error can have a collection flag that says this is the collection that was not found.\u003C/p>\u003Cp>And therefore, you can use those flags inside of the filter as well to just make it real granular. And then for for flows specific specifically, just to reiterate what we just said, is you wanna have some sort of operation that it it's almost like the end of the line operation that should that sort of allows you to say, okay. This is what we're returning now, in the output. And then that could be that can have a couple of settings like, what is the status? What is the, what is the message?\u003C/p>\u003Cp>What's the body? And then that body can be generated using a, sort of create error operation. So I think that would be a nice setup if we have 2 additional operations. 1 to create an error that this custom, but uses the direct as error format and everything else to make it system standard. Therefore, you can use it in things like manual triggers to output an error to the client.\u003C/p>\u003Cp>And then we need to have some sort of operation that you can use at the end of your chain to say return the data and then just format it in this in a certain way, to really allow you a lot of control about the request.\u003C/p>\u003Cp>Speaker 0: Okay. Rest of energetic typing.\u003C/p>\u003Cp>Speaker 3: This is satisfying.\u003C/p>\u003Cp>Speaker 1: It was very nice to listen to.\u003C/p>\u003Cp>Speaker 3: ASMR.\u003C/p>\u003Cp>Speaker 0: Now we switch to the ASMR section of the Can you just show\u003C/p>\u003Cp>Speaker 1: this video?\u003C/p>\u003Cp>Speaker 0: Everybody quiet. Everybody quiet.\u003C/p>\u003Cp>Speaker 1: Oh, no. Oh, no.\u003C/p>\u003Cp>Speaker 0: Let's not do this. Okay.\u003C/p>\u003Cp>Speaker 1: Alright. This this feels pretty good so far. Did we we I know we we chatted a little bit before we hopped on this session. Did we have any other questions that we prepared for this? I think I think we have for most of it.\u003C/p>\u003Cp>Let me pull it off here on the second screen that is off camera. Why are we returning for threes? Went through that. How many lovelies? We kinda figured that one out.\u003C/p>\u003Cp>It could be an environment variable, but you kinda just just figure that out. And then business logic existing scripts expected specific error code. Yeah. I mean yeah. I mean, I think we're gonna we've answered all the points that we sort of note note beforehand.\u003C/p>\u003Cp>Speaker 3: I I just have and I I know I think someone in the chat is just saying, like, for what about the extensions? But I think for the extensions, we can just have, like, a a JavaScript function with with the same as the one in flows and just like custom chats.\u003C/p>\u003Cp>Speaker 1: Yeah. Because we do we we haven't really documented it too properly yet because it's sort of it was a little bit in flux still, but we made that direct as error specage with a function that you can use to make a new sort of, like, error a direct as error that direct as then like, what's the right word? Recognizes as a direct as error that you can then throw to make sure that no d ep and API behave in the same way as the system would so for for custom extensions that should sort of be solved, which is good. Put that direction. Yeah.\u003C/p>\u003Cp>With that being said, I think we have a for the first time ever in one of these sessions, we left it off with a pretty clear idea of what we actually wanna do. It's usually, we go way too deep and then have a sort of couple ideas. But\u003C/p>\u003Cp>Speaker 0: But it's we're trying. This is my\u003C/p>\u003Cp>Speaker 1: No. No.\u003C/p>\u003Cp>Speaker 3: I I was going to to say it's just because it's a refurbish version of what we already think of later.\u003C/p>\u003Cp>Speaker 1: Yeah. Well, you'd you'd think that about every time we do a feature request review, and it's it's never never the case.\u003C/p>\u003Cp>Speaker 3: Like, a 2 years old idea or something. Okay. Maybe Yeah. Not 2 years, but, oh, yeah. It must be.\u003C/p>\u003Cp>Like, I I see 2022. So yeah. Kinda.\u003C/p>\u003Cp>Speaker 1: How passionate people got in the actual feature request that somebody said. It's like, this is the single worst thing about I hate it so much. My whole month is ruined because Directus' errors are too strict.\u003C/p>\u003Cp>Speaker 3: No. But, sir, seriously, like\u003C/p>\u003Cp>Speaker 0: I wish. I wish. Yeah. I wish director's errors were the worst thing in directors. Then directors would be very nice.\u003C/p>\u003Cp>Speaker 1: Yeah. That's actually a good point. Yeah. Ouch. If this is if this is the worst problem to talk about, then we're doing real well.\u003C/p>\u003Cp>Speaker 0: Then we're really golden. We're good and then.\u003C/p>\u003Cp>Speaker 1: Alright. Well, we're we're slipping a little bit, but let's call it for now. I wanna say as per use, thanks everybody for watching. This will be going live on direct TV, which is direct. Io/tv.\u003C/p>\u003Cp>If you haven't seen it yet, book market sends to your friends, your family, everybody else, Share it on LinkedIn, Twitter, x, whatever you whatever your flavor of the week is. We'll be back in, I think, 2 weeks. Am I saying that right? Uh-oh. Should have prepped this.\u003C/p>\u003Cp>Yes. We'll be back in 2 weeks exact, June 6th with another one. Oh, hello. Another one of these party full sessions. But until then, thanks for watching, and we'll see you next time.\u003C/p>\u003Cp>Speaker 2: Happy coding.\u003C/p>\u003Cp>Speaker 1: Bye. Like and subscribe. Save me from the algorithm.\u003C/p>","Thank you for joining for this week's, session of request review. We have a fascinating topic for you, which is a little deeper than you think from the from the title. But thanks for joining. We hope you like it. This week's topic is about the strictness of API errors. So what does that even mean? Let's kick off with that. Everybody knows software doesn't work always quite how you want it to work, so sometimes you will receive errors in your application, and Directus is no exception. So as you might have noticed, we are very strict as of right now. So if you do something wrong, chances are high that you're just gonna see the message forbidden. Like, even when the message, even when the error isn't actually that type of error. So why do we even do that? Throw throwing the, throwing the conversation ball to mister Reich over there, please. To me? Oh, man. Why do we do that? Well, it stems from a security report back in those days in that if you, let's let's use let's use a, a a 4 zero four as an example because it's it's an easy one to think about. So let's say you're fetching a collection that doesn't exist. Right? So you should get a 404 because the thing doesn't exist, so there's no route for it. No endpoint. If we would return a 404 for those, you could theoretically extract what the data model looks like by brute forcing your way through the whole API and checking which things return a 404 and which things return a 403, which, you know, to some security minded folks or setups, that's an issue because you don't wanna expose what type of data that you're managing in this system for security reasons. Now this is immediately where we're kicking off with opinions. Let's go. Because you can definitely, you know, you you can see it from both sides. You can easily say, well, that just makes the developer experience very annoying. And that's also why I created this feature request the moment I built it in this way. But it makes sense from a security perspective. Right? It's a similar reason why, during login, it'll say wrong email password or account doesn't exist, but you never exposed which of the 2 it is just to make sure that people can't slate, you know, what users exist. And the same goes for, you know, individual items in records. It's like you wanna, you wanna make sure that you can't just say, okay, slash item slash xyz and just keep scraping all of the different numbers, and now you know exactly what records exist, etcetera, etcetera. Somebody rightfully called out, you know, nobody does that in this trustworthy world, which I think sort of concludes this discussion then. Just ignore it. Lying on the Internet? What? Who does that? No. What? No. No. No. We don't do that. And a perfect example. So leaking of information is a very, very big thing. You don't want to expose stuff that you don't have to expose, but as you just said, it would be nice, for example, like the most basic, setup when you're just developing locally, it would be nice if you could actually see what went wrong. Because currently, it's just okay, forbidden. Nope. No information for you. So then the question comes. Oh, La Prima asked, can we go on stage? Sure thing. I think so. But let's let's first, summarize a little bit. So There should be a button somewhere. The question is. Yeah. Yeah. Exactly. So, immediately the question comes to mind. Okay. So if you would have multiple errors in that case, a strict one which just says forbidden and another one that has more information, Okay. How many different errors would you even like to have? So are we happy with just 2? Because, I guess this is opinion alert or something, or maybe even a useful thing for many other people. Like, what what do you guys think about this? Like, how many error, different error, messages would be nice, would be good. Useful. I mean, that is very much a sliding scale, isn't it? Because you really go from, from like, just give me every single thing. It's like, oh, I was trying to read the articles collection that I don't have access to. So I'm gonna get a forbidden error that says, well, articles exist, but you can't read it. And that's because of this permission that you don't have. For development purposes, that's really nice. But if you go to production with that, it's tricky because now you're just exposing a bunch of information about, you know, your setup. So, yeah, I'd I'd say it it there's a large range there's a large range in in that. And even within that forbidden error, you know, we can, think about how we wanna return stuff. So one thing I've been working on recently as part of this the the rules and permissions sprint that we'll we'll ship in soon is the, is that forbidden errors now include a little bit more information as in, you know, the field x that you were trying to query, you know, you don't have access to it or it doesn't exist, but at least it's a little bit more explicit while not necessarily exposing the schema, but just exposing what part of your query is wrong. Right? Which is not leaking any of that information but still being a little bit more useful. Alright. That does sound exciting, to be honest. Like, it's such a developer thing, like, normal users. I don't know if how how many people care about this, but this is such a nice thing for developers. So I gather from your answer right now maybe 3 types of messages. At least from your answer, it sounded like 2 in the beginning, like, one strict one with a little bit of information, but that could be counted as 3, right? Like the very strict one with nothing, a strict one with a little bit, and another one with very much information. Are we happy with 3? No? Yes. Asterisk. There's one more tricky thing in that the output type signature of the errors themselves change between those modes Right? So for example, if you're trying to fetch a thing that doesn't exist, we want to return a 404 status code with a not found error message. If you then program your app around that, you know, that it on your front end, it shows, you know, something because it checks 4 Oh, it was a 404 status. Therefore, do this logic. Right? The moment you now change that option to be strict when you go to production, that messes up again. Because now it's returning a 403 with a forbidden instead of a 404 with a not found. Cricky. So Let's see. May maybe maybe after we dive in a little bit deeper, we have more clarity around this. But so far, like, I personally like would like, I think, 3 modes. Let let's call them levels. Do we call them levels, modes? I think levels. Right? Yeah. It depends. As per usual, it's great. It it depends on, you know, are we considering multiple different flavors at the same time, or is it just an on and off? Because somebody in the chat just now rightfully mentioned, maybe it's just a single production versus development flag that changes that. Right? It could also be a setting within the app. Maybe it's even a setting on a per collection basis that you wanna say, well, this collection is not as, you know, private as the other ones. So for this one I wanna have, you know, nice and friendly, messages. And for the rest, we wanna keep private. There's options. It's tricky. It's it's when it comes to a single sort of Boolean flag that says production yes or no, I would be a little bit worried about getting into a point where undoubtedly 3 months later, somebody will show up and be like, well, we kinda need something in between. You know? Exactly. You can't really Or more importantly, somebody develops in development mode thinking they've got those messages, then they move that code to production, and suddenly nothing works. Right. Which is gonna be a bit of an issue no matter what because Agreed. We're not talking about, you know, changing the output errors. You could consider those, part of, the the what what would you call it? The public API contract of the APIs that you're building against. Right? Because because, you know, in your intro then, you said stuff sometimes crashes, and that's just part of part of software life. Stuff crashes on purpose. Right? In this case, like when validation fails, it's we're still throwing an error, but it's not an unexpected error or anything else. It's, you know, we stop you from doing something on purpose, so we throw an error, which is, you know, a bit of a difference there as well, of course. Because when it comes to exposing internal server errors, it's a whole different question. Because right now we do a similar thing, right, where we say you just get internal server error. That's it. Like regular users don't see anything else. If you're an admin user though, that's today, that's the difference. It'll show, you know, the stack trace of the actual JavaScript error, with where in the source codes it it it happened. So but exposing internal server errors to non authenticated users, that's gonna be that could easily become an issue. Right? Because now you find some sort of vulnerability path or whatever that's you don't wanna expose that. Definitely. From the chat, somebody has a suggestion here. It says, what about setting a trusted IP address? So you can just say, okay. When I am the one from my home to do this, I get all the pretty errors and otherwise, I can't. I think you're gonna have a similar issue with, you know, def versus prod, strict versus friendly error types, and how do you handle those in your app. It's gonna be a tricky tricky thing to figure out. And then somebody else said, the only thing where that really isn't enough is when there's a delete constraint. Users trying to delete items, and they can be deleted because they're still a referencing item. Admins already get a little oh, yeah. That's yeah. Because right now that is technically, a database error that bubbles up. So it comes out as an internal server error that for admins, it'll show the the SQL error underneath. But for regular users, they just get a whoops, you know, internal server error. Also with the IP, since currently currently, IP access, is attributed to roles. Right? You you customize that on a role with that access. So we could use that, but it does, like, sound very, very, very likely to me that you wouldn't be interested in, like, giving this to every single user of that role. You would like to have something more granular than that. So how about this also comes from, someone from the community. How about we attach this to permissions themselves? So let's say this user can access this and that, and that user is authorized to receive better errors than other users. For example, like, the simplest example, like admin users. Right? Mhmm. Like, all admin users are allowed to get the best errors that you can, But users other users get strict errors. Okay? But that, yeah. That's that, like, I I I'm not really sure how exactly complicated that would be to do at every single point in the in the code base. Well, I mean, in in terms of implementation, how like, they currently were throwing forbidden errors all over the place, but the way this would work in implementation is right at the end where we return the error in the APIs, that's where the sort of translation layer kicks in. Right? So all over the code base, it should just throw the actual errors or the actual error types and the correct ones. So if you're trying to hit something that doesn't exist, it should throw a not found error. And then all the way at the end in the middleware stack in the error response handler, it should say, oh, if your current, you know, e n v setting for errors or if the, which I'm gonna call it, if the the error permissions or whatever you wanna call it are set to a certain state, then it translates them into a different way. I think that's the way that that will be implemented realistically speaking. Yeah. That does sound quite good. Adjust intercept as a middleware. Okay. You are allowed to see this or not. Okay. Yeah. Because we're doing that on a case by case. It's gonna be insane. Just trying to do it every single time that we throw an error. That's that's too much. We currently already do a similar thing, right, where the the error handling stack, we check was this a direct as error type or any other error and that chooses between internal server error or, sort of the the expected error output. Very reasonable. I think, if somebody from the chat also has another recommendation or anything, please let us know. There's quite a quite a bit of action today, which is pretty nice, actually. Like, seeing the chat scroll up and down is pretty nice. Somebody says, I can't explain it in the chat, but I'll try. That's lovely. Well, well, La Prema can if if you you guys are okay with it, La Prema can join us on the stage. Yeah. I'm down. There should be a button somewhere that just says, I can invite them or they can add they can request, but we can also do an invite. How is that often with these? They asked to speak earlier, so I'm inviting. Or have they does Kevin have that blocked in this event? Oh, boy. With this guy. Nope. Nope. There we go. I got the invite. I got Does it work? I got him up here. I'm trying to see if I wait. Weekend. Yeah. It works. Okay. It works. Hello. Welcome. Hello. As always, sorry for my accent. I'm I'm Frenchy. But, like, I Don't worry. You're you're chatting with a Dutch and a German, so we we know you need to know the guy. Oh, yeah. But your English is better than mine. I don't know if you remember, but we used to talk to Get A Rich for about the the error management system. And at that time, I was working for a company who uses directors, but I leave them. So after, what I haven't the time to to follow the the the case of the the server management system. But, I think the the main problem, we had is is, dealing with the the the, yeah, the, like, the granular system of a thing. And what I proposed at the that time was, like, adding in the the collection a a new, column, like, you already have, edit and all that stuff. And, in permission, column where you will have, like, 1 or 2 level no. Mostly 2, but 2 or 3 level of, strictness of the error. Like, do do do I wanna send them all on that collection or not? Because, yeah, I I think that would be the I'm sorry. But because it's user related, it would be better for the companies. Because, if you if you, like, have only one private, instance of directors, I think it's not a problem to throw error to people because they are part of the company. So if they don't, respect them, their permissions, you they can have, like, legal, troubles, and this is possible. But if you have, like, an public API and also a private one, On one instances, if it's just a mode, I think it won't fit because a lot of data can be really sensitive. And, same goes with the developer mode. Yeah. I I totally agree with, like, developing something, in a in a development mode and then going to production, it doesn't work. That would not be a solution for me. And, as well that the the this this production and development mode would be probably used somewhere else, at another time. And, in a long term view, that will just lean in people active in the development, mode every time and, development searching, be thrown everywhere. Yeah. That's right. It's such a tricky, and I I think if that, what was that nodes flag called? It node e and v or something as taught as anything is that you should not rely on a single dev and prod flag. Yeah. No. It's a good one. It's the the doing it on a collection level, on a permissions level for for collections, basically. It's it's a good angle. It's it raises some different interesting questions though as per usual. Everything does, Especially around requests that touch multiple collections at the same time, right? Where in REST, you can technically go, you know, nest it and then you end up with you could have an error that's thrown in the sort of nested layer of the same request. Or in a GraphQL request, you can technically request multiple collections at the root level at the same time. And then it gets a little interesting because now you can get, you know, a different error output from that request based on which of the data points of that request crashed, I guess, instead of, you know, the request itself, which opens a little bit of a different kind of words. Yeah. But I I think in some case, that's what we want. Because, in the the app I I was working on, we we used to to to get in that kind of problem where, we have people, who had access to certain company, but not certain order. And we retrieve that data in one block. And if some points fails, the the whole, request will fail, so we'll have to deal with that. And, what what we can do at that point, I guess, it's when you you have the error only in one part of the query, it's just returning not an error not an error code, but just like in the API, an error, tag in, that object and not all the thing. But I I know that would be, like, a big breaking change. So it can be hard to implement for some people. But, I guess, by default, if we just disable all the error, like, the the basic settings will just be, what Direct just currently does, it won't be a problem because the people who turn the the feature on, would know what they do or or would have ways to find out. I think that is You're you're just assuming that people know what they do. I barely know what I'm doing. And when when I add features oh, no. I think, it it there's a there's a new question hidden in there that we hadn't touched on yet, nor in our notes right now, which is if an error is thrown somewhere nested, let's say, you know, the let's use the GraphQL as an example because it's it's easy to reason about. Let's let's say you're requesting 5 collections of data at the same time. Right? And one of the 5 crashes. The question is, do you return an error and the whole thing failed, or do you return the data that worked and then have an additional error flag that just indicates this is the path of your query that didn't work? But return what you have and leave the rest. And, I think for that opinions. Yeah. I think for that, the the the best way to to do it is just, like, throwing the error only for what phase. Because, if we use these directives, I assume it's that we just want to cut the the front end. And and so, it it would be, most of the time, like, an interactive app or a single page application on or something of of that kind. And those kind of errors are really easy to to treat with that method. So and and, I I think most of the time, if we activate the the feature, it's what we want because, that will lead in, less, just big crashes, like internal server error proof and nothing worse. So I don't know. It's it's an interesting one because, somebody in Chet just now says it too. It's a rather fundamental question. But, you know, you see both in the wild, and both are kinda alright. It's it's, there's also an implicit difference between, you know, reading and write operations there as well, of course, that if you do a large nested update, you kinda want it to work as a single unit, as a single transaction to make sure that if, you know, part of the insertion doesn't work or part of the update, the whole thing shouldn't, you know, go through because otherwise you have that sort of half half done state. But for read queries, it could be different, but that really depends on, you know, what are you reading, and is it all tightly coupled, or are you reading multiple things at the same time for convenience sake? Because if I'm not mistaken, in in sort of the GraphQL spec, Like, it allows you to return partial data and then errors for other root fields. But I feel like if there's an error in a nested field in the query, it'll still fill that one sort of root query as a whole. But that is that is something I love to double check. Yeah. Yeah. I'm I'm I'm not sure either. Like, my my gut feeling was, no. I I I don't wanna say something wrong right now. So, okay. Another another suggestion from the chat. How about hashing the error plus a UUID, I assume that is? Only admins will be able to see what the error really is. Well, I mean, I mean, you are probably talking about, like, error codes. Like, for example, many different other apps just say, okay this is error 3, 1,172 or something. And then you can look up internally what that exactly means, But, you would still be missing out on, like, more information, like the stack trace or which which file failed or something something that you would have to encode in that thing, but I don't think that's always possible or even Or to just think very divergently. You know, an alternative approach is that you basically encrypt the whole error, save that to a database, and then only return the ID of the error that it was. So then the admin can log in and look up what the full stack was and and and and sort of decrypt it and see the whole the whole contents and everything else. But that that feels like a way to sort of persist to security and give more information at the same time. But it also feels like another skip and a hop and a skip for regular users to be able to just, you know, use do the errors that are output. That's an interesting thing. I have never thought about it like that. People do that? Do their apps do that? That's interesting. Yes. Some app does. I I used to work on one with the that. But I think it's the it's a problem because, like, most of the time, you you wanna informing in some way your user of what the error is because you don't want to to get someone just to to create a ticket to the IT support just every time they need, something, didn't work. But they just didn't have the permission in the first time. So, yeah, I don't think, it's a global sit solution. But maybe in some case in some case, if if we add, like, an EMV approach, that would be a a great option for some people that maybe need that. And I could see it work like that for for internal server errors. Right? Well, that's one of those things where we wanna hide away the stack trace no matter what for for the API output and then save it elsewhere. But at the same time, you know, saving every error could easily blow up in your face too, because if you just have, you know, an unauthenticated user that tries to access some data there's no permissions for, we don't wanna save those. Right? Because now you could easily just blow up a database by a public malicious actor that just spams your API knowing that they're gonna get errors. So there is there is definitely a a difference between sort of expected and unexpected errors there and which ones are saved. Have AI blocked them. AI solves all of our problems. Sure. Just do what I want. Parentheses open, parenthesis close. That should do it. Right? If only if only it would be that easy. K. So let's let's summarize a little bit because we have been, you know, throwing stuff out there. Maybe we should get back to reality a little bit. So, okay. So so let's say we have, we like to use the Moscow list. Right? The must have, should have, could have, type of stuff. So for must haves, let's let's get on the same train. Like like, what do we need? What what must we include? So, yeah. How granular do we make this? Oh, no. It has to be actionable, man. It has to be actionable. Okay. I I think the the point where we've been stuck the the last time was reached is, like, we we both agree on the fact we need a granular system, but we both must agree, on the fact that it would be so long to to make and to think and all that stuff that maybe it would be nice to have something, before that. But, Right. Yeah. Yeah. Yeah. But, I I think, that's, my my point was, like, directors, is a tool who is proposing things like a a different way than the other, tools in the same category. Like, you you just want it to to be a little more, accessible and, and usable. And not just, like, being that's the way you should do that and, just follow it. And and so I I think that's the problem there. If we did something else, than a granular system, you would, follow a path that doesn't feels like directors to me. And I don't know that that's totally your point, but but, I I'm not sure if that's what people need. Otherwise, they they will lose WordPress or or something like that. You you you sound like a team member in the sense of when the choice arises, let's do it the difficult way and make it unopinionated wherever we can. So no. I I do agree though. I do agree because it's it it is at the end of the day, this is a very opinionated thing, where for some apps, it's acceptable to have it a little looser or even want it. For some, you know, security minded folks, it's absolutely not, and we can't really make that decision for people at that global level, even though we have right now. Oops. Right now we are on the side of safety first, which, you know, it's it's defendable, but not ideal. Like, that's also why I created that feature request. It feels like decades ago, but it was 3 years. I think that the the main unresolved question now, and and that is sort of to answer your point, Dan, before we can really fill in the blanks for what are the must haves, is what is that ideal approach to how do you configure this? And then from from a developer experience first and then secondly does that make sense from an implementation perspective. Because doing it on the collection scope level makes sense for errors that are thrown on the collection scope, but not all errors are thrown within the context of a single collection. So that that that opens up, you know, new questions. And the opposite is true for doing it globally on the e and v level. Right? Because, you know, it's a low pretty much excellent point. It's not that black on white that you say make it insecure for the whole API. You know, you wanna do it on a case by case basis. That is a that's a that's just a statement with no no answer. No. I don't another, I don't know what to say it in English, but, like, another thing we, think about at time was, like, just, if if we take, like, the the point, if we need the error, it's just to treat them. One, thing, which, was a a little bit, between the two option is just like, having some kind of way to tell directors just, okay. This error, I want you to to throw it, and other errors I don't want. So that would be a little bit more granular, but that would be more like, just a techy approach. And and then not, being, so universal. Oh, Rike, you're muted, by the way. I hit the wrong mute button. That's what you get when you have 2. I I muted myself here, and then I and then I muted myself to unmute on this. Oh, man. I mean, we've only been doing this remote thing for about 5 years now, so I'm I'll I'll get it. Yeah. Because I what what I was trying to say is that that approach to say, okay, which error types do we expose? That is something we could do on the role level or soon to be policy level, And it is a system where we can still have one translation middleware that handles that error no matter where is thrown from, which is you if you compare that to the sort of collection idea that we had earlier, that one is a little trickier to implement in that sense, because now you have to make sure that you know what the collection context is for every single function call that may or may not throw an error. And then do that sort of translation piece, in in situ of where those errors are created, That makes sense. Whereas with, you know, an approach where you say, okay, not found errors can be exposed. If that's your setting, we can do that on one middleware at the end of the stack to just say, okay. Was the error Again, I'm not sure if if I can wrap my head around every single edge case, but, like, it does sound and may maybe I understood it a little incorrectly, but it does sound quite easy to mess that up. Like, it to to to bubble to bubble something up that does not get blocked then. And somehow I am exposing a random error that I have not thought about, like, on on an error level. It's it's the difference of an allow list versus a deny list is basically what you're saying. Right? So if you have a filter where you're denying individual pieces, it's easy to miss something. Whereas we do the opposite way where it's blocked by default and you allow more and more stuff, it's you can't really accidentally expose anything because nothing is exposed by default. Which is similar to what, Andre Andre Andre Key are. Just gonna assume that's how you pronounce it. Just said in the chat as well as, you know, if you really want it super granular, effectively just make it a rule based system, right. Where you run a filter against the error object that is thrown. Like if the error types is XYZ and the extensions contain blah, blah, blah, collections, such and such, then expose it, which will be one way to make that super granular, but also a little harder to configure at that point. Because I could, I mean, at the end of the day, I could also imagine that, you know, for just local development, that is gonna be a pain in the ass because now you have to configure so much stuff to get the errors out. I I think we what we could do is just like doing an EMV, variable just for real development case, then that system for the production mode. And later on, if we think it's too difficult or, then we can add the system, with the the permissions because that would make, like, stacks on top of each each other, with the the the the first step would be, like, the programmatic approach on the error throwing and all. And then, the the we could add later on just, instead of just throwing nothing if the error do not doesn't match, any case. Like, is it a permission error? Then is there a plain way to treat it? So it's made steps, and we have something, in between no permission management and on the other end, full thing. What this makes me think of is the we've got a client that we're playing around within a proof of concept. They're they're actually have an error table for their front end, and they've actually got translations. So they've actually got a translations table on that so that they can have the language the errors translated to multiple languages. If we went something like that where we have, like, a direct us errors collection, right, as part of the system tables with a set of, you know, with translation, then we have native translations capabilities right there. So if you wanna adjust the error message, so we could have the defaults. Right? The I don't know. We've got a dozen or whatever that we have now, with some variable support maybe even there so that if you wanted collection information or you want that stack trace information to percolate up, you could. And you could determine at least in the short term, we can we can avoid the permissions for the short term, give you just control over your error messages. You wanna show something that we don't do natively by default, well, you can override the messaging as a thought. And I think that would actually help with things like flows as well. We have the same problem in flows. We can't percolate an error message to the user even though we're throwing and controlling the erroring of the of the workflow. Potentially, if we think about it in that context as well where we've got we could use that same error structure Mhmm. Idea. Not a not necessarily the solution or the right solution, but here's the new rabbit hole, multilingual error output for the API. Oh, boy. Oh, boy. I mean, sort of it's an interesting angle to to sort of noodle on a little bit. The the general idea of errors as it stands right now is that you basically return an error code that is one of the standard sort of known error types. And then in whatever app that you're building, you can basically just say, you know, oh, if the error is not found, then use my own translations and my own front end and all that kind of stuff. But yeah. I mean, it it does raise I mean, we we know we need some sort of translations in the API no matter what for email templating, which has been that'll be a fun discussion for another day. But, yeah, it's it's an interesting idea to have errors as a sort of system collection that you can then modify. Although, we would have to hard code in what the keys are because otherwise, we don't know what error to throw still. That's a tricky one. But we can hard set the keys. Right? And then if you create your own key or we lock the table, you're not allowed to add to it, you know, without core functionality. Or, again, you've got your hard set core pieces. Core knows what they are, and they can't be changed. Their primary key or whatever we wanna do around that Yeah. Gives us that level of flexibility. But then if users want to code other error messages for other applications and data, they can actually still maintain it in all in one place. I'm not smart enough to solve it. I just I just know that's an implementation I saw recently where we're for a front end application and the error messages that they wanna generate for that front end application. They're actually doing that in a set of tables. Kinda cool. Oh, I think, like, lots of interesting things that we can do, but I think we're still stuck on where do we want to control this or configure this. Let's just go to the one extreme. I mean, very That would be the easiest thing. You have to And you get errors. Okay. Done. That's the easiest thing that we can do. That leaves a couple of things that we would like to have open. Right? Like, we ideally, or at least in my mind, it would be really useful if, for example, like, admins actually get no like, good, context rich errors and normal users don't, which would you know, it's not really that possible with that environment variable approach. Yeah. So so it feels to me like out of everything that we've discussed so far, the direction where you effectively set up and allow list of errors on the role or soon policy level gives you, so far everything that we sort of want to achieve. Right? Where you can say, okay, you can allow one admin role to just see all of the errors with some sort of wild card flick, accept everything, allow everything. You could use the filter rules to be more granular that you could say, oh, if the error contains a collection, flag, then filter against that. So So you can you can do sort of the collection by collection, filtering. And, yeah. You you get to choose role by role, so make it admin only or make it make it, a different, you know. So the users can only see the granular errors for a a collection that's already public or something like that. The the only problem there, it's for the flows. But, like, what do we do with them? Mhmm. Mhmm. For flow, that's a grant. Like Because I I think we could have close the The same system, like, in the in the settings of the flows. But is it gonna be the same way? But we could also say that if you trigger a flow, you are a user or the public role. So therefore, the same settings of your role should still kick in. Yeah. Yeah. Because they access the data. So that's good point. But, like, what if you want to, bypass a permission on a specific flow? Like, then you'll because in some case, may maybe it's the the old data you don't want to access, but just one field you want to show someone? As long as the filtering's happening on the API level, that's still all API under you know, flows is still API under the hood. So if you uplift an operation, read CRUD, whatever, this the erroring although, I guess, it's still gonna then it would percolate to that user type I think the the the underlying question is what if you want that error to be returned no matter what the settings are in your flow? Because your flow is effectively a custom endpoint or, you know, hook or whatever. Yeah. That's what I think flows when you're throwing an error inside flows, that should be its own code. And if you throw a custom message back to that, then you should be able to get that custom message. That's the key thing that I always want. Right? Or that it the the initially, I thought was, oh, I'm gonna throw an error here and I wanna I wanna send back to the user, you know, you did x y z wrong, you know, or this this isn't allowed because you failed to give me the appropriate information instead of a internal server error, which means nothing. You know, I can't I can't tell the user what they've done wrong or what they're violating that I'm validating inside of my flow. I can't say, mister user, you must have your status in the right thing or, you know, these three fields have to be populated to be able to use this or And and that's where the allow list approach for error filtering gets tricky again, because now you need to make sure that you allow list your custom errors from your flow in the policy or in the role, so it makes its way to the app. Or I think, again, flows the error code or codes that are returned by flows, that there is a specific code, and you simply take the message that the user's providing out of the out of the, you know, exception. Yeah. Yeah. Yeah. Right. And so it's it's a known code. We know what it is. Right? We know Oh, so here's here's another thing we haven't really message. Yeah. Another thing we haven't really touched on in with regards to flows is that, you know, you have a very explicit error handling path that every operation has a okay. If the error fill or if the operation fails, do something else. So maybe there should just be an explicit operation that says return the error, and otherwise it just defaults to, you know, hidden by default, but then it becomes it it no longer is a a permissions or roles thing. It just becomes a flow thing, where you just very exclusively have to end your flow with return the actual error. And at that point, it's up to the, you know, the admin to configure that flow and and whatever they want to return. Love it. Me too. Convinced. But yeah. Yeah. Okay. Problem solved. We would have we would have to to, like, also have a a custom error block, I think, if you if we do that that way. Yeah. Yeah. Just an operation that says make a new error, whatever that error is. Yeah. And you can pass the a variable or a text or something. Yeah. Which is then a funny new completely unrelated question. But if you have a block that says create an error, is the good path the error or is the bad path the error? I I think you can you can do this. There is no path. You don't get to you don't get to leave. That's the end. You're finished. Termination note. I think the I don't I don't know. Like, I think there you called it, like, grade pass and, error pass, but I think in so in some time, like, on the if call, trigger, the error pass is not really an error pass. So Right. Yeah. That would be sense to be both, really. Yeah. So in the create an error operation, both both are the same. It just calls both. Yeah. And then Now you have oh, woah. Woah. But if it calls both, now you have a way to do parallel split paths because it's now a trick. That's a discussion for the problem. I I think that would be nice, but yeah. That would be a lot for that, more importantly, I want merge capability. Be able to rejoin back into logic. Oh, good lord. Now you have to wait for both to be done and oh, boy. Okay. Let's definitely not get into this. We've got we've got very divergent. We have about 9 minutes left, folks. Yeah. This this feels like another 6 hour discussion if we go that route. It is a very, very long discussion. Flows 2.0. We're already doing some research on that, so figure out what that looks like long term. Okay. Back to API errors. Do we have an idea of what our must have should have? Yeah. I think my my current going direction is is basically the on the role level, there is an allow list type configuration that allows you to say there needs to be a wild card that says do everything for def purposes and otherwise you can use the sort of filter structure that we have to say these are the error types that we allow you to see, and these are the and then based on whatever the error contains, you can filter it more granularly if you want to. That's for me closer to a should have than a must have. The error types is really the main the heart must have MVP. Because then because our error objects, they are, you know, they have additional extensions is what I called them right now, which is basically, a not found error can have a collection flag that says this is the collection that was not found. And therefore, you can use those flags inside of the filter as well to just make it real granular. And then for for flows specific specifically, just to reiterate what we just said, is you wanna have some sort of operation that it it's almost like the end of the line operation that should that sort of allows you to say, okay. This is what we're returning now, in the output. And then that could be that can have a couple of settings like, what is the status? What is the, what is the message? What's the body? And then that body can be generated using a, sort of create error operation. So I think that would be a nice setup if we have 2 additional operations. 1 to create an error that this custom, but uses the direct as error format and everything else to make it system standard. Therefore, you can use it in things like manual triggers to output an error to the client. And then we need to have some sort of operation that you can use at the end of your chain to say return the data and then just format it in this in a certain way, to really allow you a lot of control about the request. Okay. Rest of energetic typing. This is satisfying. It was very nice to listen to. ASMR. Now we switch to the ASMR section of the Can you just show this video? Everybody quiet. Everybody quiet. Oh, no. Oh, no. Let's not do this. Okay. Alright. This this feels pretty good so far. Did we we I know we we chatted a little bit before we hopped on this session. Did we have any other questions that we prepared for this? I think I think we have for most of it. Let me pull it off here on the second screen that is off camera. Why are we returning for threes? Went through that. How many lovelies? We kinda figured that one out. It could be an environment variable, but you kinda just just figure that out. And then business logic existing scripts expected specific error code. Yeah. I mean yeah. I mean, I think we're gonna we've answered all the points that we sort of note note beforehand. I I just have and I I know I think someone in the chat is just saying, like, for what about the extensions? But I think for the extensions, we can just have, like, a a JavaScript function with with the same as the one in flows and just like custom chats. Yeah. Because we do we we haven't really documented it too properly yet because it's sort of it was a little bit in flux still, but we made that direct as error specage with a function that you can use to make a new sort of, like, error a direct as error that direct as then like, what's the right word? Recognizes as a direct as error that you can then throw to make sure that no d ep and API behave in the same way as the system would so for for custom extensions that should sort of be solved, which is good. Put that direction. Yeah. With that being said, I think we have a for the first time ever in one of these sessions, we left it off with a pretty clear idea of what we actually wanna do. It's usually, we go way too deep and then have a sort of couple ideas. But But it's we're trying. This is my No. No. I I was going to to say it's just because it's a refurbish version of what we already think of later. Yeah. Well, you'd you'd think that about every time we do a feature request review, and it's it's never never the case. Like, a 2 years old idea or something. Okay. Maybe Yeah. Not 2 years, but, oh, yeah. It must be. Like, I I see 2022. So yeah. Kinda. How passionate people got in the actual feature request that somebody said. It's like, this is the single worst thing about I hate it so much. My whole month is ruined because Directus' errors are too strict. No. But, sir, seriously, like I wish. I wish. Yeah. I wish director's errors were the worst thing in directors. Then directors would be very nice. Yeah. That's actually a good point. Yeah. Ouch. If this is if this is the worst problem to talk about, then we're doing real well. Then we're really golden. We're good and then. Alright. Well, we're we're slipping a little bit, but let's call it for now. I wanna say as per use, thanks everybody for watching. This will be going live on direct TV, which is direct. Io/tv. If you haven't seen it yet, book market sends to your friends, your family, everybody else, Share it on LinkedIn, Twitter, x, whatever you whatever your flavor of the week is. We'll be back in, I think, 2 weeks. Am I saying that right? Uh-oh. Should have prepped this. Yes. We'll be back in 2 weeks exact, June 6th with another one. Oh, hello. Another one of these party full sessions. But until then, thanks for watching, and we'll see you next time. Happy coding. Bye. Like and subscribe. Save me from the algorithm.","published",[139,150,160],{"people_id":140},{"id":141,"first_name":142,"last_name":143,"avatar":144,"bio":145,"links":146},"07ec688d-251d-4efe-bc17-73848402d43b","Daniel","Biegler","8897b70f-c524-460a-8990-58cc5c3be886","Engineer at Directus",[147],{"url":148,"service":149},"https://directus.io/team/daniel-biegler","website",{"people_id":151},{"id":152,"first_name":153,"last_name":154,"avatar":155,"bio":156,"links":157},"0d906492-75f0-45d9-abf7-ab779bf1ed08","Jonathan","Wagner","5062e4df-a198-4b40-af47-42362d3c0551","Sales Engineering Manager at Directus",[158],{"url":159,"service":149},"https://directus.io/team/jonathan-wagner",{"people_id":161},{"id":162,"first_name":163,"last_name":164,"avatar":165,"bio":166,"links":167},"23ebcf2c-4374-4f5c-8198-f8ad497fd856","Rijk","van Zanten","7ef9652f-3835-432c-a43a-c5fe13001f31","CTO of Directus",[168],{"url":169,"service":149},"https://directus.io/team/rijk-van-zanten",[],{"id":172,"number":173,"year":174,"episodes":175,"show":188},"6aa046f1-bd53-4510-9af0-c0f3daaf4415",1,"2024",[176,177,178,179,180,181,182,122,183,184,185,186,187],"daed2c08-703a-43d6-ac97-aacac61be4c0","86fa152b-6a8b-477e-94b5-bd91e1202d21","0b5f4343-1494-455b-b41a-25811c151242","b2b01569-d8c6-49a7-adaa-429fe84f204f","b63afbe1-6418-4e9e-b1da-4890979789f0","69ad81e8-5e1d-4b85-9fa9-3b767a3a3478","5c9c888c-f527-4608-a2f7-56f156d00980","d66c1e46-cc57-49fe-a914-2e440bbc1576","12c8f72d-22fa-4ffa-a9d1-57047216fd1a","8896c934-aa2c-43b6-9342-8275682ab8b2","84c7b3ac-fd85-4539-8f39-3247118bcbf2","044b7c89-aaec-43b2-9d6d-6743a0fb5afd",{"title":189,"tile":190},"Request Review","73687d01-3734-4c28-aef7-e6fa8db4cf1e",{"title":8,"meta_description":8},{"id":183,"slug":193,"season":172,"vimeo_id":194,"description":195,"tile":196,"length":197,"resources":198,"people":8,"episode_number":201,"published":202,"title":203,"video_transcript_html":204,"video_transcript_text":205,"content":8,"seo":206,"status":137,"episode_people":207,"recommendations":211},"19659","986515873","Rijk, Jonathan and special guest Hannes discuss WYSIWYG Linking Existing Files.","4aa280eb-c685-4d24-b8d0-96477cd047d9",52,[199],{"name":130,"url":200},"https://github.com/directus/directus/discussions/19659",9,"2024-07-25","WYSIWYG Linking Existing Files","\u003Cp>Speaker 0: Welcome everybody once more. We're ready to rock. Welcome to request review. Daniel is out this week, so we got a very special guest for you here. Say hello.\u003C/p>\u003Cp>Hello. Hello. Good day.\u003C/p>\u003Cp>Speaker 1: Thomas. Welcome to the welcome to the phone.\u003C/p>\u003Cp>Speaker 2: Welcome to\u003C/p>\u003Cp>Speaker 0: the having me. So today, we're gonna be chatting about yet another feature request. And this time, Jonathan, what have we pulled up?\u003C/p>\u003Cp>Speaker 1: We have the lovely improving the way that files are injected in the WYSIWYG editors, is the discussion for today. I believe the extensions team may actually be taking this on behind the scenes in a in a short term solution. But for now, it'd be nice to understand the requirements, the the gotchas, the whys and wherefores, the way that current the way we currently add links and images and videos within a WYSIWYG field. So you can edit links, move your links, take a look at your links here. But according to the to the request, they'd like this to be a little more fully featured in the way that the tags and things are added around the HTML under the hood.\u003C/p>\u003Cp>It's my understanding. But I'm no front end expert, so let's see what we can figure out and decipher.\u003C/p>\u003Cp>Speaker 0: Alright. So this I can feel it. This is not one of those where it feels like, oh, that that should just be one button. Right? That's easy enough to do.\u003C/p>\u003Cp>Alright. So starting at the basics and pulling it up, if you seem to look enough to decide over here, by the way, I just added the same thing up, but a little bit bigger. The goal here is basically just like you can put in an image, you wanna link to a file. Right? Easy enough, you\u003C/p>\u003Cp>Speaker 1: think.\u003C/p>\u003Cp>Speaker 0: Inserting a link to a file in its purest form shouldn't be too crazy because we know what the IDs of the file. We know where you would find it slash assets. It's the same as an image. Right? Mhmm.\u003C/p>\u003Cp>Just as with an image though, the question immediately becomes permissions? Big one. Right? The user that is inserting the file has permissions to see those files and then select it to be linked. But that doesn't mean that the person on the other end that is that's seeing this HTML rendered on a website or something also has the permissions to that same file.\u003C/p>\u003Cp>Right? And we've seen this before with images.\u003C/p>\u003Cp>Speaker 2: Yeah. I was trying to say it's the same problem with images. Right? Because images share the same\u003C/p>\u003Cp>Speaker 0: properties. Yeah. So the way we do it for images right now is we do have that option where you can sort of hard code in one of the the tokens if that's the way you wanna do it. You could, of course, make permissions a little leaner for reading images. Although that way, you know, it's a little bit more than permission set up.\u003C/p>\u003Cp>Not ideal. You can have people log in, of course, on your own front end and then use that for permissions. But it feels like even with the link to files, it might get a bit worse because at least with an image, you can immediately see if it doesn't work because you get a broken image. Right? Because you get a permissions issue.\u003C/p>\u003Cp>So as the person that's implementing it, it becomes a little bit more obvious what's going on. But if you just have a link and the link doesn't work for some, but it works for others, that's tricky. That's tricky. So I think as per usual for for those who haven't seen one of these before, the way this oftentimes works is that, you know, we take the smallest feature request that that is in here. The what is the the status?\u003C/p>\u003Cp>What is the minimum viable? Then convergently think about, okay, what scope does this live in? What are all the edge cases that we have to think about? What are the problems that will come up? And then sort of take it back down to, okay, what can we actually do today?\u003C/p>\u003Cp>Right? And what is the long term plan and how do we get there? So I think to me, an important one for to make this one work as expected is all around permissions. So I'm actually very glad that you're here, Thomas, because you just work a lot on permissions as part of this, v 11 release in the RC that is out now, in the GA coming up very soon. Any immediate thoughts on the permission set up for this?\u003C/p>\u003Cp>Speaker 2: Especially with files, I do worry that giving read access to a lot of files like you suggested previously is a big foot gun for people because you might store private files. You might store exports from collections or something in your files and giving, like, real access to any of them feels wrong to do it as a blanket or something. That's like a blanket permission. We we, the best possible way would be to surface that information somehow. Like, how visible is a link or how visible is, like, something you link to, since even if you're testing out the link on your live preview or something, you still might be logged into your CMS behind the scenes.\u003C/p>\u003Cp>So for you, the link also works. So you have would have to test it in a private window or something. But then again, we could show you, hey. This is how the public what the public permissions for this file look like. Users might not be able to access it.\u003C/p>\u003Cp>On the other hand, we don't know about your setup. Right? So we don't know, are you actually just visiting those with the public public permissions? Or are you adding a token? Or are you doing some other stuff with it since we don't know really what is the implementation that relies on it.\u003C/p>\u003Cp>So it's hard to think about a catch all solution that would help people not shoot their foot. So right now with images, we do it. We basically let you do anything with it, and don't hold your hand while doing it. And I wonder if that is also the solution in this case. So just provide more functionality.\u003C/p>\u003Cp>But if stuff breaks on your end, you have to be aware of it. Seems could be a documentation issue, but then again, the people reading our documentation aren't actually the users using the product in the end maybe.\u003C/p>\u003Cp>Speaker 0: Yeah. It's a tricky one. And and to your point\u003C/p>\u003Cp>Speaker 2: of, like, where do you wanna put this education?\u003C/p>\u003Cp>Speaker 0: Right. Yeah. And and to your point, we when we had this issue for images, the conclusion was, well, you know what? Let's just make all the options available and and put the burden of setup on the the end user to make sure that they're using it right instead of on us to to try to help you with it. It did this made me, think of another feature request that we I don't think we've discussed quite yet here, but it gets come up a couple of times in the past, which is the nested relational permissions, so to speak, where you could say, files are inaccessible by default, but you can allow file reads if they are being read through another relational field.\u003C/p>\u003Cp>So for example, you could say files are off limits, but if you look up an avatar through a user, you can still access that one avatar in some of its fields, but only if you go in relationally through a user.\u003C/p>\u003Cp>Speaker 2: How does it work with the assets endpoint though?\u003C/p>\u003Cp>Speaker 0: Right. That's where it gets interesting because I'm I'm just wondering coming from. Yeah. No. Exactly.\u003C/p>\u003Cp>I'm just curious if there is an angle to that, because it made me think of this where I'm like, oh, if you assign an image or an asset into a WYSIWYG blob, maybe we can have it rely on a similar idea of permissions where it's like, okay. The things you make available within, one of those fields can be read in a certain way, but not others. Again, just convergently thinking about it.\u003C/p>\u003Cp>Speaker 1: Do you have any other issues? Sorry. Good. I I don't wanna distract you from a thought. So go ahead, Hans.\u003C/p>\u003Cp>Speaker 2: The the issue I'm seeing with that is, again, like, accessing some data of that asset, totally fine. I can see that work, how it would be set up in permissions.\u003C/p>\u003Cp>Speaker 1: I\u003C/p>\u003Cp>Speaker 2: would be able to do, like, the relational reversal of permissions or something or for items. But since the asset endpoint doesn't know about it, we are still at some point where we why would this user be able to see this? Because then we would have to look up. Are there any permissions that could allow it? And so it gets it gets really complicated on the asset end point.\u003C/p>\u003Cp>Like, the actual, like, file permissions isn't too much of a problem, but all of the metadata, but the whole, assets itself isn't too trivial to figure out Yeah. Image for that one.\u003C/p>\u003Cp>Speaker 0: Maybe. Again, divergently thinking about this. Maybe the, there's an in between where we can do kinda like what what s 3 supports and and some of those storage providers where you have, like, a signed link that is unique to where it was used. So we can know from the way the asset was accessed, what field in what collection it was accessed from. And then that way, we can do the relational permissions thingy instead of relying on having to search.\u003C/p>\u003Cp>Because to your point, if you open an asset and we have to search through every single field to see if there's any chance that you used it, that feels crazy. That feels insane. But if we make it a unique link that is unique to that collection of field combination, then that simplifies it a little bit. Because now we do know A\u003C/p>\u003Cp>Speaker 2: lot of things.\u003C/p>\u003Cp>Speaker 0: Where it was accessed from. Yeah.\u003C/p>\u003Cp>Speaker 2: Which effectively could be something like an access token for that.\u003C/p>\u003Cp>Speaker 0: Yeah. Effectively. So so it could be it's it's effectively just just a token with that connects the dots between you're trying to access this image or this asset through an HTML blob, that is on your website. And because we generated a custom link for it, we know what that blob is, and then we can also help you debug, you know, if your file got, is being accessed from sources that you didn't expect it to, we can show you. It's like, well, you got it read from your your HTML body and this and this article or something.\u003C/p>\u003Cp>Right?\u003C/p>\u003Cp>Speaker 1: Interesting. I like it. That was my thinking as well was either inherit permissions for the item, but then as Hannes noted that the asset endpoint has no idea about that currently. Now that doesn't mean that we don't enhance or find a way, kind of a unique URL or a unique identifier that indicates where this is being used. We've actually seen this.\u003C/p>\u003Cp>There's another request out there about knowing what what files are associated with which items. Right?\u003C/p>\u003Cp>Speaker 0: It's Right. Right.\u003C/p>\u003Cp>Speaker 1: We we have this problem right now without writing some very complex hook logic that track tracks through a whole set of relationals. You know, we don't because that asset endpoint is kind of independent of all of that and files kind of live independent of all of that, The way that the relational is unless you're forcing relational reverse creation, which then makes your file through, you know, direct us files gets really ugly really fast that way. We have this it's a fairly common request that we see from clients of, I wanna know what my files are associated with. Right? I wanna be able to see that and understand that.\u003C/p>\u003Cp>So This\u003C/p>\u003Cp>Speaker 0: is this is also an interesting topic in the whole security versus usability piece. Because on on from from a user experience and even a developer experience, if I have a, public HTML blob and I put an image in there, I kinda assume that that image is now also in that same public blob. Right? So I would assume it to work. At the same time, if you if if we were to make it that way where it's like, oh, whenever you put an image inside of a HTML thing, it's now public.\u003C/p>\u003Cp>You can accidentally expose a whole lot of stuff. Right? Because it's it's a little opaque under the hood. From a security perspective, it's a little tricky.\u003C/p>\u003Cp>Speaker 2: Is it though? I guess again, it's really one of those, like, what are all the different use cases Directus is used in kind of problem. And, like, who are the actual end users and who has who has been educated about that problem, caveat, whatever we wanna call it. Because I I generally like the idea like, it doesn't really have anything to do with that, feature request in general since that seems a lot more low level. But I do like the general idea of having something like a unique or signed, asset URL, which can be used to conditionally allow access to something.\u003C/p>\u003Cp>Speaker 1: And so generating something could\u003C/p>\u003Cp>Speaker 2: be go for it. Sorry.\u003C/p>\u003Cp>Speaker 1: No. No. I was just curious. So when you're generating, you know, like, this this input screen right here, so you'd have a unique URL that's being generated here, right, in some way, shape, or form, whether that's a tag on the end of the, you know, asset endpoint that gives you a question mark, you know, unique key. That has to be stored then.\u003C/p>\u003Cp>Is that stored then as part of the director's files or a relational to the director's files kind of a system table where we store those unique IDs? And not so much implementation. Just I I'm thinking about so you'd have that ID. But you'd also be able to see that here. Could you also or optionally ensure that you give, you know, an access token option here?\u003C/p>\u003Cp>So as an actual field input where you could supply an access token or even a default access token for as part of the admin configuration. Because once again, I don't necessarily want users putting in access tokens, but have a way for the administrators to get to apply an access token that has the appropriate permissions for the file.\u003C/p>\u003Cp>Speaker 0: That is the key piece there. That last that last little snippet of the sentence is the most important crucially important part that has the appropriate permissions for the files. The foot gun with the excess token is that somebody just puts in their own users' access token, YOLO it, and then it works. But now you're technically exposing that all over the place, right?\u003C/p>\u003Cp>Speaker 1: Yeah.\u003C/p>\u003Cp>Speaker 0: Because once you're, you're putting that excess token in the image and HTML, it's just a query parameter. So therefore, wherever you render it, somebody can see it. You have to consider it public.\u003C/p>\u003Cp>Speaker 2: See it. They can\u003C/p>\u003Cp>Speaker 0: So what you're effectively doing is you're not using the public role for those images. You're just using a token that you then make public. Right? So that last part is why the sort of developer or user experience or both. I mean, just the experience as a whole for using the static tokens as way to get access to those asset in a link or an image or otherwise.\u003C/p>\u003Cp>There's a couple of food guns, right, that you gotta be aware of that people may or may not be. Because again, that's one of those things where, you know, if you explain it, that makes a lot of sense. But if you don't know and you just wrongly assume you could put in any access token, you can be in a in a world of trouble. Right?\u003C/p>\u003Cp>Speaker 1: Absolutely. K.\u003C/p>\u003Cp>Speaker 2: Which makes me wonder if that is something I haven't really thought about all the ash cases, but it's something probably we can solve by using a j signed JWT or something that just scopes it to that specific item in a collection, then we don't even have to store that in the database, assuming that you have access to that. Because then in the asset endpoint, we could check, hey, does the user like, this request actually have access to that item, which is signed in the JWT? And that way, we can verify the access. And if that basically overrides whatever, like, more restrictive permissions you have, you would be good to go only for that specific item where that image is linked in.\u003C/p>\u003Cp>Speaker 0: Yeah. So we're basically saying\u003C/p>\u003Cp>Speaker 2: Linked or whatever.\u003C/p>\u003Cp>Speaker 0: Try to summarize that so I understand that we're basically saying if you attach an image or an a file, a general asset, any asset to an item in a WYSIWYG or relational interfaces, maybe even anywhere else. Well, relational interface, I guess not because then you just have a data point, not a file. But if you have an asset link inside of a Wizzywig or a block editor, some of those markdown, we use a signed link that contains what collection and item it came from. And then we can use the permissions for that item instead of the permission for files. So therefore, if you have read access to that HTML field, you defect don't have read access to the images within it.\u003C/p>\u003Cp>That feels like a very clean setup as far as I'm concerned.\u003C/p>\u003Cp>Speaker 2: Again, probably also food counts with exposing files or people linking to files, which should be internal at that point. It's more of a shooting your own foot than more, of a case where we are trying to prevent it the best we can. Yeah. But that's,\u003C/p>\u003Cp>Speaker 1: that's kind of already here anyway. Right? Because you can restrict the files and folders that this has access to. Right? In the in the actual WYSIWYG config, you can, I I think Do\u003C/p>\u003Cp>Speaker 2: the root folder or something? It's what we do. Right?\u003C/p>\u003Cp>Speaker 1: It should only be what this user has access to. Right? So if I add\u003C/p>\u003Cp>Speaker 2: Add in general. Yeah. Yeah. For sure.\u003C/p>\u003Cp>Speaker 1: If I add an image, you know, I can add or edit. I don't wanna do that.\u003C/p>\u003Cp>Speaker 2: I wanna So your your condominiums and images.\u003C/p>\u003Cp>Speaker 1: Yep. This is my my permissions restrict me to whatever I have access to, and so I shouldn't be able to technically insert something that I shouldn't be able to now. Could get a little more complex, but I like the that was my thinking and couple of notes that I took. I want a way to restrict the permissions to based on the item's permissions. Yep.\u003C/p>\u003Cp>So I like the\u003C/p>\u003Cp>Speaker 2: change that we do to go with Amazon. Yep. It's interesting. And it's it also could be something that is just a tick mark or something in that dialogue, which can say, hey. Create a signed link or create an unsigned link because people might not want to have that additional check, but just generally make stuff public or something.\u003C/p>\u003Cp>But it could be an option either for the end user to decide or for the admin setting it up to decide. I feel like that is a good way of doing it also to introduce it in a non breaking way if you ever wanna introduce it in just a feature release.\u003C/p>\u003Cp>Speaker 1: Judd's asking if we could display make it so that it's visible in the sense of you'd be able to see who has access to that data. This is not great. Can we do that? If if we're\u003C/p>\u003Cp>Speaker 2: doing it with a token, probably not.\u003C/p>\u003Cp>Speaker 1: No. But if we use, like, the scope JWT, would you be able to see so if I was in here looking at this, would I be able to see could you display here who has access? That seems crazy.\u003C/p>\u003Cp>Speaker 2: Whoever has access to, like, whatever item you're inserting this into has access to that file in or something. So it's not something where we have either this user, like, harnesses you in your file or something, or or do they do, like, color eagle? Or I don't know. So I didn't at least with the route we're planning on going or considering going, that wouldn't be the case.\u003C/p>\u003Cp>Speaker 0: Although, now I'm thinking about it. If you have the we use the permissions for the item for the asset endpoint, you still have a similar case where you could render the HTML somewhere for a person that's not logged in. Although, I guess, at that point, it's it's more expected. But you still Oh, you\u003C/p>\u003Cp>Speaker 2: mean, like, service side rendering or something where you have Yeah. Token or, like, some service level token that actually does the rendering and you still break your links?\u003C/p>\u003Cp>Speaker 0: Yep.\u003C/p>\u003Cp>Speaker 2: I mean, at that point at that point, you wanna do like, you wanna manually track what is publicly available or something, I feel like.\u003C/p>\u003Cp>Speaker 0: Yeah. I'm I'm just wondering because still divergently thinking what we can do to make this just very obvious in how it works, but still secure at the same time. Like, I'm also thinking an alternative, and this is just completely other idea. But if there is a native dedicated public folder in the file library, just a different root folder in the file library that is always public, you make it super obvious that, oh, if you wanna put a public image in your article, pull it from the public folder, right, or move it there first to make it public and then use it in your article.\u003C/p>\u003Cp>Speaker 2: Now I'm wondering if that is way too CMS specific.\u003C/p>\u003Cp>Speaker 0: It is. Although, I guess, yeah, public sharing of files, yes, no, yes, no, maybe. I don't know. Tricky. I know a lot of dams\u003C/p>\u003Cp>Speaker 2: are all public by default, which\u003C/p>\u003Cp>Speaker 0: is also a strange idea.\u003C/p>\u003Cp>Speaker 2: Lot of what? Sorry.\u003C/p>\u003Cp>Speaker 0: I know a a couple of dam providers that default to everything being public for ease of use and then you have the opposite where you can mark certain files as private instead of the other way around. But that is also\u003C/p>\u003Cp>Speaker 2: I mean, we do allow you to conf to set that up. Right? We do allow you to set up permissions. Hey. You're allowed to access files which are located within this folder\u003C/p>\u003Cp>Speaker 0: Yeah.\u003C/p>\u003Cp>Speaker 2: Through public permissions, public policies, whatever you wanna do it with. So we already have that. It's just not there by default.\u003C/p>\u003Cp>Speaker 1: We tried again, I'm kind of okay with that from, I I I don't think we have nobody complains about the ability to make something public. It's more so the one. The other thing we should make sure we come back to in this, is it's also about the way it's being embedded. I think the HTML coding that's actually being used, making it easier to con\u003C/p>\u003Cp>Speaker 2: Yeah. That is something we've glanced over so far. Right? Because\u003C/p>\u003Cp>Speaker 1: Yeah. We're more concerned. Security is to me the the first thing we should be thinking about.\u003C/p>\u003Cp>Speaker 2: Yeah. Because for an image, it's kind of there's an obvious way of how to do it. But for an a tag, I mean, there are some standard attributes we wanna put in there. Yeah. But now the question is, like, what is a standard way of linking to something?\u003C/p>\u003Cp>It's probably an a tag, but is it something that we want to make configurable if use people are using it in service side reactor ending, if you're rendering whatever? Or is that so much out of scope that we say, if you're doing this, you better use the block editor and do your custom rendering pipeline or something or use markdown and go with that? Is it something where we wanna be really open to not rendering just an a tag, but something user defined? Because in the initial request, it looks like it's the requesting only a tags or link tags, whatever. I haven't really been able to see that in the request there.\u003C/p>\u003Cp>Speaker 1: Yeah. Here. Well, that's an alternative. This is what they're doing as an alternative. They're doing some things strangely behind\u003C/p>\u003Cp>Speaker 2: the scenes. Rendered as oh, I think it's a typo. The link should be rendered as an tag. So as a tag maybe in the first sentence or the first paragraph, the motivation.\u003C/p>\u003Cp>Speaker 0: I think that's supposed to be as an as an anchor tag. Yeah.\u003C/p>\u003Cp>Speaker 2: Yeah.\u003C/p>\u003Cp>Speaker 1: So what is this considered currently when we're inserting? Because this is an h ref. Right?\u003C/p>\u003Cp>Speaker 2: It's an image.\u003C/p>\u003Cp>Speaker 0: Is it it's an anchor text. I mean, for for images, it's an image. And for for links, it's just an anchor, an a tag.\u003C/p>\u003Cp>Speaker 2: But a link is not something where we directly allow linking to any records or something. Right? It's just a insert user.\u003C/p>\u003Cp>Speaker 0: And it's just a link. Insert a link.\u003C/p>\u003Cp>Speaker 2: Yep. Yeah. Yeah. Yeah.\u003C/p>\u003Cp>Speaker 0: So so this feature request in its base in most basic form, it's just when I click add a link, allow me to choose a file instead of add a link. That's that's that's bare bones what this is saying.\u003C/p>\u003Cp>Speaker 1: So the same way that we can do image the image and media because they're applying specific tags. But if you're just adding a tag, right, so if I just say I wanna, you you know, make this a link or if I'm just creating a link, I have to specify the URL. So what they\u003C/p>\u003Cp>Speaker 0: want is the to a static file, you'd now have to type in mydirectors.com/asset/whatever the ID is. And and this is this in its simplest form, this is basically just saying, give me a link to a file.\u003C/p>\u003Cp>Speaker 1: Give me a link to a file, same as when you're doing this, where you're inserting an image and you're searching. So they want the they want this regardless of image or anything else. Got\u003C/p>\u003Cp>Speaker 0: it. It's basically the exact same flows in certain image except it pops in a link instead of an inline embed.\u003C/p>\u003Cp>Speaker 1: So you'd have another you'd have essentially another option here that's, you know, insert a direct as file or insert a file. Right? And maybe the image library filters and searches. Got it.\u003C/p>\u003Cp>Speaker 2: Yeah. Which means we immediately derailed this discussion by going, hey. What about permissions?\u003C/p>\u003Cp>Speaker 0: Exactly. That's that's the beauty of these these sessions, Thomas. Welcome aboard.\u003C/p>\u003Cp>Speaker 1: Welcome to our crazy party. I still like the idea of making this this better. Right? So making this more understandable and more usable.\u003C/p>\u003Cp>Speaker 0: Yeah. Image images within WYSIWYG are are infinitely. Because I have another topic if you wanna just derail it a little bit more on this at the other the other way, which is migrations to and from different URLs. If you change the URL of your direct installation, this technically breaks Yeah. It's paint.\u003C/p>\u003Cp>Speaker 1: Actually, I it happened on this very record. I popped this open in preparation for this this morning, and I was like, why is my image not showing up? And I right clicked and it was I'd actually migrated this from, another project, a while back.\u003C/p>\u003Cp>Speaker 2: You see.\u003C/p>\u003Cp>Speaker 1: And now my URL was just back\u003C/p>\u003Cp>Speaker 2: in just this morning.\u003C/p>\u003Cp>Speaker 1: Yep. So when I was looking at the, you know, the link here, I had to actually adjust this to my correct URL. So this is a this is a known issue when we're doing, like, data migrations and things. We've got, our support team has some scripts and things that we'll go through and find try to find and replace known values here. But it's a\u003C/p>\u003Cp>Speaker 0: It's a tricky problem to solve because it's it's by definition, the WYSIWYG one is the trickiest because it is HTML. It's not a pro like a readable format necessarily. I mean, you know.\u003C/p>\u003Cp>Speaker 2: It's something that is like easily solved in I don't know. Like, for example, our block editor or something, right?\u003C/p>\u003Cp>Speaker 0: Right. Yeah.\u003C/p>\u003Cp>Speaker 2: Image could\u003C/p>\u003Cp>Speaker 0: just be nested in JSON or something\u003C/p>\u003Cp>Speaker 2: you can even learn back. Yeah. Yeah.\u003C/p>\u003Cp>Speaker 0: Because you're also dealing with an ID and not a full link. That helps.\u003C/p>\u003Cp>Speaker 2: It's best case best case, it shouldn't even include the link. Like, I don't know what our block editor does, to be honest, but best case, it should just be a acid link or something that just includes the ID of that item you're interested in or that acid.\u003C/p>\u003Cp>Speaker 0: Right. The tricky bit is if you plop that into a browser, nothing shows up. Yeah. It doesn't\u003C/p>\u003Cp>Speaker 2: know what to do with it. Yeah. Yeah. For sure.\u003C/p>\u003Cp>Speaker 0: So you, you have very tricky, tricky setup where that is that is always an issue. And and I'm more than happy because we we have a little bit of time like Lockheed here to to try to to noodle on some ideas for ways around that. Because, you know, some some more CMS specific platforms, they use, like, short codes or something within the HTML. Right? Where it's just like bracket asset ID this and then go figure it out in in post processing.\u003C/p>\u003Cp>That is an option, but that requires the user of\u003C/p>\u003Cp>Speaker 2: the Custom.\u003C/p>\u003Cp>Speaker 0: The output to do something, or we have to have some sort of custom post processing set up for some fields where we say, oh, if you have an HTML field, we'll search through short codes and and execute them. Interesting. Or Yeah. Because custom web components.\u003C/p>\u003Cp>Speaker 2: Custom web components. We could provide a set of custom web components that is a director's image and that knows your CMS location and then just needs the ID, which is effectively what we're doing for Nuxt. Right? There is, like, a country like a Nuxt image module direct as Nuxt module, which is, like, the base URL, and then it just knows the image ID and figures the rest out.\u003C/p>\u003Cp>Speaker 0: Yeah.\u003C/p>\u003Cp>Speaker 2: So that could be an option for the WYSIWYG that it's like, hey, if you're using a custom image resolver or something, you could just insert the ID in the link.\u003C/p>\u003Cp>Speaker 0: You can't use the face tag outside of the head, could you, in HTML?\u003C/p>\u003Cp>Speaker 2: Oh, don't ask me.\u003C/p>\u003Cp>Speaker 0: I don't think so. I think base is only in the head. The for that that's just I'm not just thinking HTML brain because you were saying it should just be, like, a relative link instead of a full URL. More or less, you were talking just the ID. But I'm like, if you make it slash assets slash the ID, then it will work within Directus presumably, but it will not in your own website.\u003C/p>\u003Cp>But a base tag in HTML says, you know, graphics every single link to everything with this domain, which could be work around for that. Right? Where you just have a base tag that says, okay, make the base tag, the direct installation, and then it would just work. But I think a base\u003C/p>\u003Cp>Speaker 2: tag breaks every relative link on your Right. Right.\u003C/p>\u003Cp>Speaker 0: Right. I was gonna say breaks every relative link in your whole package. That's what I'm saying. If only there was a locally scoped base tag where you can just say only within the main tag of my Dom is the base tag something else. But, yeah, I don't think that's gonna be a good solution for this.\u003C/p>\u003Cp>Custom web component is an interesting one too because it requires, you know, a bit of custom JavaScript that needs to happen on every single website that wants to use this, and it's just just a bit of yeah. It is\u003C/p>\u003Cp>Speaker 2: one possibility. Yep.\u003C/p>\u003Cp>Speaker 0: Yeah. I think, if if we if we rely on more of a short code, based approach with some post processing, then you make the migration between projects really lightweight, assuming there's a way to skip the post processing. And then the API output could still be the full URL, but we rely on a short code in the database. So therefore, the value that we store is just like bracket asset ID with all the parameters that you want, and then we generate those into images on the fly. But it's just a bit of a I don't know.\u003C/p>\u003Cp>It's\u003C/p>\u003Cp>Speaker 2: It it doesn't feel like our responsibility necessarily. Yeah. That's kind of why I'm struggling. Same with, the public folder or something. That that feels too much like forcing one way of solving it on people.\u003C/p>\u003Cp>Speaker 0: Yeah. You're not\u003C/p>\u003Cp>Speaker 1: wrong. You're\u003C/p>\u003Cp>Speaker 0: not wrong. Tricky bum. Tricky bum. Oh, one more thing related and related, maybe a bit of both. For images, we just plop in an image tag.\u003C/p>\u003Cp>Right? That's that's what what it does. Do we want to support any other file types that are in line? Because videos images are in line, but if you link to a PDF file or something, Do we want\u003C/p>\u003Cp>Speaker 1: to It comes up. We we see that request as well as additional, like, inline viewers. Right? PDFs.\u003C/p>\u003Cp>Speaker 0: Right.\u003C/p>\u003Cp>Speaker 1: Docs, you know, spreadsheets, whatever. Being able to actually have a preview of what that looks like.\u003C/p>\u003Cp>Speaker 0: The tricky thing with those things is that they're all custom front end frameworks or plugins or libraries or web components. It's not it's not a browser standard. So if we wanna go that route, we would have to have some sort of way where you can configure what markup it spits out if you insert a PDF. Because then you get to choose between, oh, when when I'm inserting a PDF, I'm gonna insert my little HTML markup that spits out a PDF preview or something instead of just the link.\u003C/p>\u003Cp>Speaker 1: Yep. So there's that's that's another common thing that we see on those types of fields. Right? So if I go to paragraph here\u003C/p>\u003Cp>Speaker 2: Which already screams use a freaking block editor or anything other than a wizarding question.\u003C/p>\u003Cp>Speaker 0: I you're not wrong. You're not wrong.\u003C/p>\u003Cp>Speaker 1: So but, again, we support, you know, on some level. Right? Whether this is TinyMC or TipTap or name your editor. People have built their own interfaces here. There's a number of marketplace interfaces around this where the underlying libraries actually are more than we're currently exposing.\u003C/p>\u003Cp>And the question is, can we could we have interfaces have more composability or more extensibility kind of pre exposed, that you could then adapt. You can when the users, you know, when the administrators are setting these up, you could have custom, menu options. Right? So if you could actually I I know tinymc supports it because we've done it. Right?\u003C/p>\u003Cp>We've got the image and the video editor buttons that are there, and they inspect the appropriate tags. I think Tiny MC and Tiptap both support this ability to have an override or a templating option where you can adjust the configuration, add new buttons, add new drop down.\u003C/p>\u003Cp>Speaker 0: Oh, sure. Yeah. We could we could support that for, you know, file insert as well. If we have an insert button that we say, oh, if you're inserting a type of a PDF or something that we, you know, we render it in a different way. It's just so much setup that you end up having to do.\u003C/p>\u003Cp>Right? So right now, indirect is you would have to do that per field, which will be kind of annoying. So we would have to add some sort of global defaults as well for for interfaces to make that a little bit more editable.\u003C/p>\u003Cp>Speaker 1: Yep. And that's why, again, I think some of that we're actually looking at. It's for the extensions team, the the directus labs team to take a look at actually doing some tests on creating some new interfaces or modifying faces Yeah. To give us an idea of what's possible, what would what would work well, and then we can decide down the line whether we adapt that and roll that back into the core interface options as well. Yeah.\u003C/p>\u003Cp>But\u003C/p>\u003Cp>Speaker 0: Or or use a block editor. Like, there's there's, of course, you know, when it comes to and this is this is huge breaking changes and that's something we will do anytime soon, but there's also the argument to be made that is maybe we shouldn't be dealing with HTML at all. I I know it's it's the sort of easiest path to website, but from a data format perspective and for a data portability perspective and a migration perspective and, using it in non web platforms perspective, it is objectively not the right tool for the job, I think.\u003C/p>\u003Cp>Speaker 2: Yep. Yeah.\u003C/p>\u003Cp>Speaker 1: Yep.\u003C/p>\u003Cp>Speaker 0: I think markdown is slightly better. You still have to render it out yourself and you still have some of these migration problems, but at least, you know, renderers for markdown exist across, you know, output types, iOS development, web development, etcetera. But as far as I'm concerned, July 2024, you know, a block editor that returns it in in JSON is the most friendly way to actually render it out across different output vendors. Right? So there's also a world where we can say, maybe we don't concern ourselves with an HTML editor at all.\u003C/p>\u003Cp>We really focus on having one really good block editor, be it based on, tip- tab, shout out to chat, or or anything else, and then offer some utilities to have that transform to HTML, just to make your life a little bit easier, but not try to save it and manage it as HTML within directness.\u003C/p>\u003Cp>Speaker 1: So like an on the fly, the API endpoint would dynamically transform the block editor JSON format into HTML as an option parameter.\u003C/p>\u003Cp>Speaker 2: Right.\u003C/p>\u003Cp>Speaker 1: Clever. Clever.\u003C/p>\u003Cp>Speaker 0: Because that way we get around a lot of these these issues effectively all of them by just not dealing with HTML.\u003C/p>\u003Cp>Speaker 1: No.\u003C/p>\u003Cp>Speaker 2: Are there, folks are doing it as well to provide you with JavaScript libraries to convert to HTML. It doesn't even need to be server side. Though server side seems like a cool option, but, there are libraries out there for converting, like, adjacent tree to whatever, and you can have custom elements. You can render them customly within your frameworks, all of that. I've done that personally as well.\u003C/p>\u003Cp>Like, I've worked with abstract documents as a JSON and rendered them in different frameworks with different components, all of that. And it just makes it a lot nicer to handle if you're willing to spend the effort. But that is kind of the catch of it. Right? HTML is just super easy, but it doesn't give you all the nice options which you would have if you dealt with it in a more advanced way.\u003C/p>\u003Cp>Yeah. But probably it's the reason why we have Wizzy Week in the first place But it's it leaves you with certain limits. Yeah. It leaves you with certain limits.\u003C/p>\u003Cp>Speaker 1: Yeah. Yeah. No. I've got people that are, you know, they they\u003C/p>\u003Cp>Speaker 2: Which makes me always wonder, like\u003C/p>\u003Cp>Speaker 1: Go ahead.\u003C/p>\u003Cp>Speaker 2: No. Go for it.\u003C/p>\u003Cp>Speaker 1: No. I was just saying I've seen people copying and pasting in Wizzy, you know, HTML from other sources and breaking their actual web page.\u003C/p>\u003Cp>Speaker 0: Oh, yeah.\u003C/p>\u003Cp>Speaker 1: Because they've got CSS and other things that they're trying to override, and it's being overridden. And they're complaining that, oh, my fonts don't match on this thing that I copied and pasted from some third party source. Right? Think Oh,\u003C/p>\u003Cp>Speaker 0: that's a big thing. Work. Oh.\u003C/p>\u003Cp>Speaker 1: Yeah. It's I I actually dealt with this just recently for one of our and for one of our clients, one of our actually, a a legacy Ranger Studios client, that we still kind of help out and monitor and support their site. And they came complaining that the fonts weren't matching on articles that they were that they just published. And they said, sometimes it works and sometimes it doesn't. And I was initially, I'm thinking there's some I'm digging through\u003C/p>\u003Cp>Speaker 2: Some of the code on the site. Google Docs and sometimes go into And\u003C/p>\u003Cp>Speaker 1: and then I'm looking at the Wizzio, and then I happen I'm like, what are all these spans and these classes don't exist in our code.\u003C/p>\u003Cp>Speaker 0: What are yeah. And\u003C/p>\u003Cp>Speaker 1: then I real and then I started removing so and suddenly the formatting for the correct. It was picking up the correct font, but they were it was this font code for this HTML was overriding all of the underlying CSS that was configured for the site. So yeah. Yeah. It's a nightmare.\u003C/p>\u003Cp>Speaker 2: Okay. That leaves us with one more feature request after this feature request review, which is how do we get shareable, like, permission permissions baked into an asset link, which makes it easier to manage permissions for anything you link in your editor. And with the agreement that it's probably cool idea and a good idea to include a, a, an, button form, whatever in there that allows you to create an 8 anchor tag to any asset in directors.\u003C/p>\u003Cp>Speaker 0: Yeah. I think that would be a great one to have. And to your point, that's a new feature of choice.\u003C/p>\u003Cp>Speaker 2: Have anyone in the audience who wanna wants to tag on to that.\u003C/p>\u003Cp>Speaker 0: Now the good news is of this session is that all of these things that we described so far, they're all non blockers or supporting the MVP of this, which is insert link to file, which is fantastic, which means that I wanna say, okay. Let's just do it. Let's just do it. It's improvement. It's a new feature, but small one, you know, PRs are welcome.\u003C/p>\u003Cp>It's a good first issue. Let's just do it. Like, the the minimum viable of this? Sure.\u003C/p>\u003Cp>Speaker 2: Is it something we only wanna do in the week, or is it also something we wanna support in the\u003C/p>\u003Cp>Speaker 0: That is a good question. I don't think it's relevant for the block editor because, a file is filed. You can render it out as a link or an image however you want for the markdown interface though. I think it's relevant.\u003C/p>\u003Cp>Speaker 1: Yeah. Because currently, it's just a URL link. Right? You've got the add in an image. I don't see do we support video in markdown?\u003C/p>\u003Cp>I There's markdown, and that's\u003C/p>\u003Cp>Speaker 0: There's really no such yeah. There's there's no native markdown for video.\u003C/p>\u003Cp>Speaker 1: K.\u003C/p>\u003Cp>Speaker 0: So not really. There's also no HTML attributes in markdown. There's a lot of things that are in markdown.\u003C/p>\u003Cp>Speaker 1: That's okay. So, technically, we just need the file link. I'm putting a note in the ticket here in the in the discussion here. Go ahead. Go on this.\u003C/p>\u003Cp>Speaker 2: Alright. Same question for the block editor. Is it also something where we wanna support it as well? Since we might want feature parity between between all of our editor interfaces.\u003C/p>\u003Cp>Speaker 1: Agree.\u003C/p>\u003Cp>Speaker 2: I don't even know what the block editor is capable of doing right now.\u003C/p>\u003Cp>Speaker 1: So it's got image.\u003C/p>\u003Cp>Speaker 2: Like we do image and attachment. What is attachment? Is is attachment already what we're trying to do?\u003C/p>\u003Cp>Speaker 0: I think it is. Yeah.\u003C/p>\u003Cp>Speaker 2: It might be. Yeah?\u003C/p>\u003Cp>Speaker 0: Yeah. I think it is.\u003C/p>\u003Cp>Speaker 1: Already is. Yep. So the only thing we because,\u003C/p>\u003Cp>Speaker 0: the block editor natively supports that. The the library that we use for that just has it. Yep. Yep. The Wizzy tiny MCE does not doesn't have a concept of that yet, so we have to edit edit ourselves.\u003C/p>\u003Cp>Speaker 1: Yep. Yeah. So you get select the file, and I guess the the one thing that I noticed is it doesn't have video. Should block editor have video? Or is it just file as a file as a file for these guys outside of the images that have captions?\u003C/p>\u003Cp>That's a good question. Let's see. Do I have video first deal in here? It's just in some video and see what the preview or window. I don't know what that just did.\u003C/p>\u003Cp>Oh, it downloaded. No. I have a duplicate copy of that. Lovely. So should it have so for parity, does does the block editor support video?\u003C/p>\u003Cp>Speaker 2: Seems like it's just an attachment. Right?\u003C/p>\u003Cp>Speaker 0: I think it's just an attachment.\u003C/p>\u003Cp>Speaker 1: It's just doing it as an attachment right now, but should it have a video interface the same as the HTML does? No. Maybe. Or a video blank. Just for, like, again, feature parity across the where where possible.\u003C/p>\u003Cp>Speaker 0: I think there's a separate plugin for editor JS, which is what we use in the for the block editor, but we'll have to try it out. Different feature request for a different day.\u003C/p>\u003Cp>Speaker 1: All good. So we already have file, so the only place that this needs to be done is. Markdown in HTML. Right?\u003C/p>\u003Cp>Speaker 2: And I think the block edit can just treat whatever attachment the way it sees fit.\u003C/p>\u003Cp>Speaker 1: I will put a note Just\u003C/p>\u003Cp>Speaker 2: for videos in the WEEZY week, do we just insert a video tag, or how does it work?\u003C/p>\u003Cp>Speaker 1: Let's have a look.\u003C/p>\u003Cp>Speaker 0: Yeah.\u003C/p>\u003Cp>Speaker 1: I'll go test it.\u003C/p>\u003Cp>Speaker 2: Yep. K. That's what I figured. Wizardwig. Also, what kind of fan fancy collection is it that you have there, Jonathan?\u003C/p>\u003Cp>My test my test collections always have all 3 of the editors in there. You guys can actually show and hide it. That's cool.\u003C/p>\u003Cp>Speaker 1: Yeah. So I'm using the conditional rules. I use it for demos. So I have this in my Yeah.\u003C/p>\u003Cp>Speaker 2: Yeah. Yeah.\u003C/p>\u003Cp>Speaker 1: My CMS demo essentially where I've got a page a paragraph component. And then depending on, you know, if they're a WYSIWYG shop or they're a markdown shop or they're a block header, just being able to show off the different interfaces quickly and easily, but show and hide them. And it shows off the conditional rule capabilities of the app as well. So\u003C/p>\u003Cp>Speaker 0: It's cool. My my debugging instance is just one of each on every page.\u003C/p>\u003Cp>Speaker 1: Yeah. So so you do get a video player in Wizziweb. Yeah. It's yeah. I think\u003C/p>\u003Cp>Speaker 0: it's just a video tag. If you check out the raw HTML of that, it's it's literally Giant\u003C/p>\u003Cp>Speaker 2: kitchen sink collection. We everything in there.\u003C/p>\u003Cp>Speaker 1: Yep. I have including just a flat text area. So all of our kind\u003C/p>\u003Cp>Speaker 2: of Yeah. So it probably is a video. Yeah.\u003C/p>\u003Cp>Speaker 1: Yep. So it actually renders it with Under the hood. With video HTML tags accordingly. So the question is, does the block editor and or we know markdown doesn't support it, but does the block editor support something similar? Right now we're just inserting it as a file.\u003C/p>\u003Cp>But if the block editor technically supports video, it would be nice to have parity to have the equivalency where video renders nicely. So I'll just put a note.\u003C/p>\u003Cp>Speaker 0: Anyways, taking this back slightly more on track. This feature request as a whole, easy. I think it's easy easy to to accept it. That that's what I was going for. That's so much easy to implement necessarily.\u003C/p>\u003Cp>Easy to accept it. I think it's we should just do it. It's a good first issue. I think it's great for for PRs, if anybody wants to take a swing at this. I think there's a lot of new ideas and new feature requests that are worth discussing more.\u003C/p>\u003Cp>Like, I think this signed link approach to permissions is a very, very interesting one that will be very relevant for something like this. But with that being said, the eye on the clock and me also have a hard stop, unfortunately. I wanna say thank you very much for watching once more. We'll be back soon. Soon, Asia.\u003C/p>\u003Cp>It was a it was a minute since last time, but we'll be back, I believe in 2 weeks, and if not, soon. Make sure to check out this show on direct. Io/tv. Your request review. If you like doing this, somebody like having to get here.\u003C/p>","Welcome everybody once more. We're ready to rock. Welcome to request review. Daniel is out this week, so we got a very special guest for you here. Say hello. Hello. Hello. Good day. Thomas. Welcome to the welcome to the phone. Welcome to the having me. So today, we're gonna be chatting about yet another feature request. And this time, Jonathan, what have we pulled up? We have the lovely improving the way that files are injected in the WYSIWYG editors, is the discussion for today. I believe the extensions team may actually be taking this on behind the scenes in a in a short term solution. But for now, it'd be nice to understand the requirements, the the gotchas, the whys and wherefores, the way that current the way we currently add links and images and videos within a WYSIWYG field. So you can edit links, move your links, take a look at your links here. But according to the to the request, they'd like this to be a little more fully featured in the way that the tags and things are added around the HTML under the hood. It's my understanding. But I'm no front end expert, so let's see what we can figure out and decipher. Alright. So this I can feel it. This is not one of those where it feels like, oh, that that should just be one button. Right? That's easy enough to do. Alright. So starting at the basics and pulling it up, if you seem to look enough to decide over here, by the way, I just added the same thing up, but a little bit bigger. The goal here is basically just like you can put in an image, you wanna link to a file. Right? Easy enough, you think. Inserting a link to a file in its purest form shouldn't be too crazy because we know what the IDs of the file. We know where you would find it slash assets. It's the same as an image. Right? Mhmm. Just as with an image though, the question immediately becomes permissions? Big one. Right? The user that is inserting the file has permissions to see those files and then select it to be linked. But that doesn't mean that the person on the other end that is that's seeing this HTML rendered on a website or something also has the permissions to that same file. Right? And we've seen this before with images. Yeah. I was trying to say it's the same problem with images. Right? Because images share the same properties. Yeah. So the way we do it for images right now is we do have that option where you can sort of hard code in one of the the tokens if that's the way you wanna do it. You could, of course, make permissions a little leaner for reading images. Although that way, you know, it's a little bit more than permission set up. Not ideal. You can have people log in, of course, on your own front end and then use that for permissions. But it feels like even with the link to files, it might get a bit worse because at least with an image, you can immediately see if it doesn't work because you get a broken image. Right? Because you get a permissions issue. So as the person that's implementing it, it becomes a little bit more obvious what's going on. But if you just have a link and the link doesn't work for some, but it works for others, that's tricky. That's tricky. So I think as per usual for for those who haven't seen one of these before, the way this oftentimes works is that, you know, we take the smallest feature request that that is in here. The what is the the status? What is the minimum viable? Then convergently think about, okay, what scope does this live in? What are all the edge cases that we have to think about? What are the problems that will come up? And then sort of take it back down to, okay, what can we actually do today? Right? And what is the long term plan and how do we get there? So I think to me, an important one for to make this one work as expected is all around permissions. So I'm actually very glad that you're here, Thomas, because you just work a lot on permissions as part of this, v 11 release in the RC that is out now, in the GA coming up very soon. Any immediate thoughts on the permission set up for this? Especially with files, I do worry that giving read access to a lot of files like you suggested previously is a big foot gun for people because you might store private files. You might store exports from collections or something in your files and giving, like, real access to any of them feels wrong to do it as a blanket or something. That's like a blanket permission. We we, the best possible way would be to surface that information somehow. Like, how visible is a link or how visible is, like, something you link to, since even if you're testing out the link on your live preview or something, you still might be logged into your CMS behind the scenes. So for you, the link also works. So you have would have to test it in a private window or something. But then again, we could show you, hey. This is how the public what the public permissions for this file look like. Users might not be able to access it. On the other hand, we don't know about your setup. Right? So we don't know, are you actually just visiting those with the public public permissions? Or are you adding a token? Or are you doing some other stuff with it since we don't know really what is the implementation that relies on it. So it's hard to think about a catch all solution that would help people not shoot their foot. So right now with images, we do it. We basically let you do anything with it, and don't hold your hand while doing it. And I wonder if that is also the solution in this case. So just provide more functionality. But if stuff breaks on your end, you have to be aware of it. Seems could be a documentation issue, but then again, the people reading our documentation aren't actually the users using the product in the end maybe. Yeah. It's a tricky one. And and to your point of, like, where do you wanna put this education? Right. Yeah. And and to your point, we when we had this issue for images, the conclusion was, well, you know what? Let's just make all the options available and and put the burden of setup on the the end user to make sure that they're using it right instead of on us to to try to help you with it. It did this made me, think of another feature request that we I don't think we've discussed quite yet here, but it gets come up a couple of times in the past, which is the nested relational permissions, so to speak, where you could say, files are inaccessible by default, but you can allow file reads if they are being read through another relational field. So for example, you could say files are off limits, but if you look up an avatar through a user, you can still access that one avatar in some of its fields, but only if you go in relationally through a user. How does it work with the assets endpoint though? Right. That's where it gets interesting because I'm I'm just wondering coming from. Yeah. No. Exactly. I'm just curious if there is an angle to that, because it made me think of this where I'm like, oh, if you assign an image or an asset into a WYSIWYG blob, maybe we can have it rely on a similar idea of permissions where it's like, okay. The things you make available within, one of those fields can be read in a certain way, but not others. Again, just convergently thinking about it. Do you have any other issues? Sorry. Good. I I don't wanna distract you from a thought. So go ahead, Hans. The the issue I'm seeing with that is, again, like, accessing some data of that asset, totally fine. I can see that work, how it would be set up in permissions. I would be able to do, like, the relational reversal of permissions or something or for items. But since the asset endpoint doesn't know about it, we are still at some point where we why would this user be able to see this? Because then we would have to look up. Are there any permissions that could allow it? And so it gets it gets really complicated on the asset end point. Like, the actual, like, file permissions isn't too much of a problem, but all of the metadata, but the whole, assets itself isn't too trivial to figure out Yeah. Image for that one. Maybe. Again, divergently thinking about this. Maybe the, there's an in between where we can do kinda like what what s 3 supports and and some of those storage providers where you have, like, a signed link that is unique to where it was used. So we can know from the way the asset was accessed, what field in what collection it was accessed from. And then that way, we can do the relational permissions thingy instead of relying on having to search. Because to your point, if you open an asset and we have to search through every single field to see if there's any chance that you used it, that feels crazy. That feels insane. But if we make it a unique link that is unique to that collection of field combination, then that simplifies it a little bit. Because now we do know A lot of things. Where it was accessed from. Yeah. Which effectively could be something like an access token for that. Yeah. Effectively. So so it could be it's it's effectively just just a token with that connects the dots between you're trying to access this image or this asset through an HTML blob, that is on your website. And because we generated a custom link for it, we know what that blob is, and then we can also help you debug, you know, if your file got, is being accessed from sources that you didn't expect it to, we can show you. It's like, well, you got it read from your your HTML body and this and this article or something. Right? Interesting. I like it. That was my thinking as well was either inherit permissions for the item, but then as Hannes noted that the asset endpoint has no idea about that currently. Now that doesn't mean that we don't enhance or find a way, kind of a unique URL or a unique identifier that indicates where this is being used. We've actually seen this. There's another request out there about knowing what what files are associated with which items. Right? It's Right. Right. We we have this problem right now without writing some very complex hook logic that track tracks through a whole set of relationals. You know, we don't because that asset endpoint is kind of independent of all of that and files kind of live independent of all of that, The way that the relational is unless you're forcing relational reverse creation, which then makes your file through, you know, direct us files gets really ugly really fast that way. We have this it's a fairly common request that we see from clients of, I wanna know what my files are associated with. Right? I wanna be able to see that and understand that. So This is this is also an interesting topic in the whole security versus usability piece. Because on on from from a user experience and even a developer experience, if I have a, public HTML blob and I put an image in there, I kinda assume that that image is now also in that same public blob. Right? So I would assume it to work. At the same time, if you if if we were to make it that way where it's like, oh, whenever you put an image inside of a HTML thing, it's now public. You can accidentally expose a whole lot of stuff. Right? Because it's it's a little opaque under the hood. From a security perspective, it's a little tricky. Is it though? I guess again, it's really one of those, like, what are all the different use cases Directus is used in kind of problem. And, like, who are the actual end users and who has who has been educated about that problem, caveat, whatever we wanna call it. Because I I generally like the idea like, it doesn't really have anything to do with that, feature request in general since that seems a lot more low level. But I do like the general idea of having something like a unique or signed, asset URL, which can be used to conditionally allow access to something. And so generating something could be go for it. Sorry. No. No. I was just curious. So when you're generating, you know, like, this this input screen right here, so you'd have a unique URL that's being generated here, right, in some way, shape, or form, whether that's a tag on the end of the, you know, asset endpoint that gives you a question mark, you know, unique key. That has to be stored then. Is that stored then as part of the director's files or a relational to the director's files kind of a system table where we store those unique IDs? And not so much implementation. Just I I'm thinking about so you'd have that ID. But you'd also be able to see that here. Could you also or optionally ensure that you give, you know, an access token option here? So as an actual field input where you could supply an access token or even a default access token for as part of the admin configuration. Because once again, I don't necessarily want users putting in access tokens, but have a way for the administrators to get to apply an access token that has the appropriate permissions for the file. That is the key piece there. That last that last little snippet of the sentence is the most important crucially important part that has the appropriate permissions for the files. The foot gun with the excess token is that somebody just puts in their own users' access token, YOLO it, and then it works. But now you're technically exposing that all over the place, right? Yeah. Because once you're, you're putting that excess token in the image and HTML, it's just a query parameter. So therefore, wherever you render it, somebody can see it. You have to consider it public. See it. They can So what you're effectively doing is you're not using the public role for those images. You're just using a token that you then make public. Right? So that last part is why the sort of developer or user experience or both. I mean, just the experience as a whole for using the static tokens as way to get access to those asset in a link or an image or otherwise. There's a couple of food guns, right, that you gotta be aware of that people may or may not be. Because again, that's one of those things where, you know, if you explain it, that makes a lot of sense. But if you don't know and you just wrongly assume you could put in any access token, you can be in a in a world of trouble. Right? Absolutely. K. Which makes me wonder if that is something I haven't really thought about all the ash cases, but it's something probably we can solve by using a j signed JWT or something that just scopes it to that specific item in a collection, then we don't even have to store that in the database, assuming that you have access to that. Because then in the asset endpoint, we could check, hey, does the user like, this request actually have access to that item, which is signed in the JWT? And that way, we can verify the access. And if that basically overrides whatever, like, more restrictive permissions you have, you would be good to go only for that specific item where that image is linked in. Yeah. So we're basically saying Linked or whatever. Try to summarize that so I understand that we're basically saying if you attach an image or an a file, a general asset, any asset to an item in a WYSIWYG or relational interfaces, maybe even anywhere else. Well, relational interface, I guess not because then you just have a data point, not a file. But if you have an asset link inside of a Wizzywig or a block editor, some of those markdown, we use a signed link that contains what collection and item it came from. And then we can use the permissions for that item instead of the permission for files. So therefore, if you have read access to that HTML field, you defect don't have read access to the images within it. That feels like a very clean setup as far as I'm concerned. Again, probably also food counts with exposing files or people linking to files, which should be internal at that point. It's more of a shooting your own foot than more, of a case where we are trying to prevent it the best we can. Yeah. But that's, that's kind of already here anyway. Right? Because you can restrict the files and folders that this has access to. Right? In the in the actual WYSIWYG config, you can, I I think Do the root folder or something? It's what we do. Right? It should only be what this user has access to. Right? So if I add Add in general. Yeah. Yeah. For sure. If I add an image, you know, I can add or edit. I don't wanna do that. I wanna So your your condominiums and images. Yep. This is my my permissions restrict me to whatever I have access to, and so I shouldn't be able to technically insert something that I shouldn't be able to now. Could get a little more complex, but I like the that was my thinking and couple of notes that I took. I want a way to restrict the permissions to based on the item's permissions. Yep. So I like the change that we do to go with Amazon. Yep. It's interesting. And it's it also could be something that is just a tick mark or something in that dialogue, which can say, hey. Create a signed link or create an unsigned link because people might not want to have that additional check, but just generally make stuff public or something. But it could be an option either for the end user to decide or for the admin setting it up to decide. I feel like that is a good way of doing it also to introduce it in a non breaking way if you ever wanna introduce it in just a feature release. Judd's asking if we could display make it so that it's visible in the sense of you'd be able to see who has access to that data. This is not great. Can we do that? If if we're doing it with a token, probably not. No. But if we use, like, the scope JWT, would you be able to see so if I was in here looking at this, would I be able to see could you display here who has access? That seems crazy. Whoever has access to, like, whatever item you're inserting this into has access to that file in or something. So it's not something where we have either this user, like, harnesses you in your file or something, or or do they do, like, color eagle? Or I don't know. So I didn't at least with the route we're planning on going or considering going, that wouldn't be the case. Although, now I'm thinking about it. If you have the we use the permissions for the item for the asset endpoint, you still have a similar case where you could render the HTML somewhere for a person that's not logged in. Although, I guess, at that point, it's it's more expected. But you still Oh, you mean, like, service side rendering or something where you have Yeah. Token or, like, some service level token that actually does the rendering and you still break your links? Yep. I mean, at that point at that point, you wanna do like, you wanna manually track what is publicly available or something, I feel like. Yeah. I'm I'm just wondering because still divergently thinking what we can do to make this just very obvious in how it works, but still secure at the same time. Like, I'm also thinking an alternative, and this is just completely other idea. But if there is a native dedicated public folder in the file library, just a different root folder in the file library that is always public, you make it super obvious that, oh, if you wanna put a public image in your article, pull it from the public folder, right, or move it there first to make it public and then use it in your article. Now I'm wondering if that is way too CMS specific. It is. Although, I guess, yeah, public sharing of files, yes, no, yes, no, maybe. I don't know. Tricky. I know a lot of dams are all public by default, which is also a strange idea. Lot of what? Sorry. I know a a couple of dam providers that default to everything being public for ease of use and then you have the opposite where you can mark certain files as private instead of the other way around. But that is also I mean, we do allow you to conf to set that up. Right? We do allow you to set up permissions. Hey. You're allowed to access files which are located within this folder Yeah. Through public permissions, public policies, whatever you wanna do it with. So we already have that. It's just not there by default. We tried again, I'm kind of okay with that from, I I I don't think we have nobody complains about the ability to make something public. It's more so the one. The other thing we should make sure we come back to in this, is it's also about the way it's being embedded. I think the HTML coding that's actually being used, making it easier to con Yeah. That is something we've glanced over so far. Right? Because Yeah. We're more concerned. Security is to me the the first thing we should be thinking about. Yeah. Because for an image, it's kind of there's an obvious way of how to do it. But for an a tag, I mean, there are some standard attributes we wanna put in there. Yeah. But now the question is, like, what is a standard way of linking to something? It's probably an a tag, but is it something that we want to make configurable if use people are using it in service side reactor ending, if you're rendering whatever? Or is that so much out of scope that we say, if you're doing this, you better use the block editor and do your custom rendering pipeline or something or use markdown and go with that? Is it something where we wanna be really open to not rendering just an a tag, but something user defined? Because in the initial request, it looks like it's the requesting only a tags or link tags, whatever. I haven't really been able to see that in the request there. Yeah. Here. Well, that's an alternative. This is what they're doing as an alternative. They're doing some things strangely behind the scenes. Rendered as oh, I think it's a typo. The link should be rendered as an tag. So as a tag maybe in the first sentence or the first paragraph, the motivation. I think that's supposed to be as an as an anchor tag. Yeah. Yeah. So what is this considered currently when we're inserting? Because this is an h ref. Right? It's an image. Is it it's an anchor text. I mean, for for images, it's an image. And for for links, it's just an anchor, an a tag. But a link is not something where we directly allow linking to any records or something. Right? It's just a insert user. And it's just a link. Insert a link. Yep. Yeah. Yeah. Yeah. So so this feature request in its base in most basic form, it's just when I click add a link, allow me to choose a file instead of add a link. That's that's that's bare bones what this is saying. So the same way that we can do image the image and media because they're applying specific tags. But if you're just adding a tag, right, so if I just say I wanna, you you know, make this a link or if I'm just creating a link, I have to specify the URL. So what they want is the to a static file, you'd now have to type in mydirectors.com/asset/whatever the ID is. And and this is this in its simplest form, this is basically just saying, give me a link to a file. Give me a link to a file, same as when you're doing this, where you're inserting an image and you're searching. So they want the they want this regardless of image or anything else. Got it. It's basically the exact same flows in certain image except it pops in a link instead of an inline embed. So you'd have another you'd have essentially another option here that's, you know, insert a direct as file or insert a file. Right? And maybe the image library filters and searches. Got it. Yeah. Which means we immediately derailed this discussion by going, hey. What about permissions? Exactly. That's that's the beauty of these these sessions, Thomas. Welcome aboard. Welcome to our crazy party. I still like the idea of making this this better. Right? So making this more understandable and more usable. Yeah. Image images within WYSIWYG are are infinitely. Because I have another topic if you wanna just derail it a little bit more on this at the other the other way, which is migrations to and from different URLs. If you change the URL of your direct installation, this technically breaks Yeah. It's paint. Actually, I it happened on this very record. I popped this open in preparation for this this morning, and I was like, why is my image not showing up? And I right clicked and it was I'd actually migrated this from, another project, a while back. You see. And now my URL was just back in just this morning. Yep. So when I was looking at the, you know, the link here, I had to actually adjust this to my correct URL. So this is a this is a known issue when we're doing, like, data migrations and things. We've got, our support team has some scripts and things that we'll go through and find try to find and replace known values here. But it's a It's a tricky problem to solve because it's it's by definition, the WYSIWYG one is the trickiest because it is HTML. It's not a pro like a readable format necessarily. I mean, you know. It's something that is like easily solved in I don't know. Like, for example, our block editor or something, right? Right. Yeah. Image could just be nested in JSON or something you can even learn back. Yeah. Yeah. Because you're also dealing with an ID and not a full link. That helps. It's best case best case, it shouldn't even include the link. Like, I don't know what our block editor does, to be honest, but best case, it should just be a acid link or something that just includes the ID of that item you're interested in or that acid. Right. The tricky bit is if you plop that into a browser, nothing shows up. Yeah. It doesn't know what to do with it. Yeah. Yeah. For sure. So you, you have very tricky, tricky setup where that is that is always an issue. And and I'm more than happy because we we have a little bit of time like Lockheed here to to try to to noodle on some ideas for ways around that. Because, you know, some some more CMS specific platforms, they use, like, short codes or something within the HTML. Right? Where it's just like bracket asset ID this and then go figure it out in in post processing. That is an option, but that requires the user of the Custom. The output to do something, or we have to have some sort of custom post processing set up for some fields where we say, oh, if you have an HTML field, we'll search through short codes and and execute them. Interesting. Or Yeah. Because custom web components. Custom web components. We could provide a set of custom web components that is a director's image and that knows your CMS location and then just needs the ID, which is effectively what we're doing for Nuxt. Right? There is, like, a country like a Nuxt image module direct as Nuxt module, which is, like, the base URL, and then it just knows the image ID and figures the rest out. Yeah. So that could be an option for the WYSIWYG that it's like, hey, if you're using a custom image resolver or something, you could just insert the ID in the link. You can't use the face tag outside of the head, could you, in HTML? Oh, don't ask me. I don't think so. I think base is only in the head. The for that that's just I'm not just thinking HTML brain because you were saying it should just be, like, a relative link instead of a full URL. More or less, you were talking just the ID. But I'm like, if you make it slash assets slash the ID, then it will work within Directus presumably, but it will not in your own website. But a base tag in HTML says, you know, graphics every single link to everything with this domain, which could be work around for that. Right? Where you just have a base tag that says, okay, make the base tag, the direct installation, and then it would just work. But I think a base tag breaks every relative link on your Right. Right. Right. I was gonna say breaks every relative link in your whole package. That's what I'm saying. If only there was a locally scoped base tag where you can just say only within the main tag of my Dom is the base tag something else. But, yeah, I don't think that's gonna be a good solution for this. Custom web component is an interesting one too because it requires, you know, a bit of custom JavaScript that needs to happen on every single website that wants to use this, and it's just just a bit of yeah. It is one possibility. Yep. Yeah. I think, if if we if we rely on more of a short code, based approach with some post processing, then you make the migration between projects really lightweight, assuming there's a way to skip the post processing. And then the API output could still be the full URL, but we rely on a short code in the database. So therefore, the value that we store is just like bracket asset ID with all the parameters that you want, and then we generate those into images on the fly. But it's just a bit of a I don't know. It's It it doesn't feel like our responsibility necessarily. Yeah. That's kind of why I'm struggling. Same with, the public folder or something. That that feels too much like forcing one way of solving it on people. Yeah. You're not wrong. You're not wrong. Tricky bum. Tricky bum. Oh, one more thing related and related, maybe a bit of both. For images, we just plop in an image tag. Right? That's that's what what it does. Do we want to support any other file types that are in line? Because videos images are in line, but if you link to a PDF file or something, Do we want to It comes up. We we see that request as well as additional, like, inline viewers. Right? PDFs. Right. Docs, you know, spreadsheets, whatever. Being able to actually have a preview of what that looks like. The tricky thing with those things is that they're all custom front end frameworks or plugins or libraries or web components. It's not it's not a browser standard. So if we wanna go that route, we would have to have some sort of way where you can configure what markup it spits out if you insert a PDF. Because then you get to choose between, oh, when when I'm inserting a PDF, I'm gonna insert my little HTML markup that spits out a PDF preview or something instead of just the link. Yep. So there's that's that's another common thing that we see on those types of fields. Right? So if I go to paragraph here Which already screams use a freaking block editor or anything other than a wizarding question. I you're not wrong. You're not wrong. So but, again, we support, you know, on some level. Right? Whether this is TinyMC or TipTap or name your editor. People have built their own interfaces here. There's a number of marketplace interfaces around this where the underlying libraries actually are more than we're currently exposing. And the question is, can we could we have interfaces have more composability or more extensibility kind of pre exposed, that you could then adapt. You can when the users, you know, when the administrators are setting these up, you could have custom, menu options. Right? So if you could actually I I know tinymc supports it because we've done it. Right? We've got the image and the video editor buttons that are there, and they inspect the appropriate tags. I think Tiny MC and Tiptap both support this ability to have an override or a templating option where you can adjust the configuration, add new buttons, add new drop down. Oh, sure. Yeah. We could we could support that for, you know, file insert as well. If we have an insert button that we say, oh, if you're inserting a type of a PDF or something that we, you know, we render it in a different way. It's just so much setup that you end up having to do. Right? So right now, indirect is you would have to do that per field, which will be kind of annoying. So we would have to add some sort of global defaults as well for for interfaces to make that a little bit more editable. Yep. And that's why, again, I think some of that we're actually looking at. It's for the extensions team, the the directus labs team to take a look at actually doing some tests on creating some new interfaces or modifying faces Yeah. To give us an idea of what's possible, what would what would work well, and then we can decide down the line whether we adapt that and roll that back into the core interface options as well. Yeah. But Or or use a block editor. Like, there's there's, of course, you know, when it comes to and this is this is huge breaking changes and that's something we will do anytime soon, but there's also the argument to be made that is maybe we shouldn't be dealing with HTML at all. I I know it's it's the sort of easiest path to website, but from a data format perspective and for a data portability perspective and a migration perspective and, using it in non web platforms perspective, it is objectively not the right tool for the job, I think. Yep. Yeah. Yep. I think markdown is slightly better. You still have to render it out yourself and you still have some of these migration problems, but at least, you know, renderers for markdown exist across, you know, output types, iOS development, web development, etcetera. But as far as I'm concerned, July 2024, you know, a block editor that returns it in in JSON is the most friendly way to actually render it out across different output vendors. Right? So there's also a world where we can say, maybe we don't concern ourselves with an HTML editor at all. We really focus on having one really good block editor, be it based on, tip- tab, shout out to chat, or or anything else, and then offer some utilities to have that transform to HTML, just to make your life a little bit easier, but not try to save it and manage it as HTML within directness. So like an on the fly, the API endpoint would dynamically transform the block editor JSON format into HTML as an option parameter. Right. Clever. Clever. Because that way we get around a lot of these these issues effectively all of them by just not dealing with HTML. No. Are there, folks are doing it as well to provide you with JavaScript libraries to convert to HTML. It doesn't even need to be server side. Though server side seems like a cool option, but, there are libraries out there for converting, like, adjacent tree to whatever, and you can have custom elements. You can render them customly within your frameworks, all of that. I've done that personally as well. Like, I've worked with abstract documents as a JSON and rendered them in different frameworks with different components, all of that. And it just makes it a lot nicer to handle if you're willing to spend the effort. But that is kind of the catch of it. Right? HTML is just super easy, but it doesn't give you all the nice options which you would have if you dealt with it in a more advanced way. Yeah. But probably it's the reason why we have Wizzy Week in the first place But it's it leaves you with certain limits. Yeah. It leaves you with certain limits. Yeah. Yeah. No. I've got people that are, you know, they they Which makes me always wonder, like Go ahead. No. Go for it. No. I was just saying I've seen people copying and pasting in Wizzy, you know, HTML from other sources and breaking their actual web page. Oh, yeah. Because they've got CSS and other things that they're trying to override, and it's being overridden. And they're complaining that, oh, my fonts don't match on this thing that I copied and pasted from some third party source. Right? Think Oh, that's a big thing. Work. Oh. Yeah. It's I I actually dealt with this just recently for one of our and for one of our clients, one of our actually, a a legacy Ranger Studios client, that we still kind of help out and monitor and support their site. And they came complaining that the fonts weren't matching on articles that they were that they just published. And they said, sometimes it works and sometimes it doesn't. And I was initially, I'm thinking there's some I'm digging through Some of the code on the site. Google Docs and sometimes go into And and then I'm looking at the Wizzio, and then I happen I'm like, what are all these spans and these classes don't exist in our code. What are yeah. And then I real and then I started removing so and suddenly the formatting for the correct. It was picking up the correct font, but they were it was this font code for this HTML was overriding all of the underlying CSS that was configured for the site. So yeah. Yeah. It's a nightmare. Okay. That leaves us with one more feature request after this feature request review, which is how do we get shareable, like, permission permissions baked into an asset link, which makes it easier to manage permissions for anything you link in your editor. And with the agreement that it's probably cool idea and a good idea to include a, a, an, button form, whatever in there that allows you to create an 8 anchor tag to any asset in directors. Yeah. I think that would be a great one to have. And to your point, that's a new feature of choice. Have anyone in the audience who wanna wants to tag on to that. Now the good news is of this session is that all of these things that we described so far, they're all non blockers or supporting the MVP of this, which is insert link to file, which is fantastic, which means that I wanna say, okay. Let's just do it. Let's just do it. It's improvement. It's a new feature, but small one, you know, PRs are welcome. It's a good first issue. Let's just do it. Like, the the minimum viable of this? Sure. Is it something we only wanna do in the week, or is it also something we wanna support in the That is a good question. I don't think it's relevant for the block editor because, a file is filed. You can render it out as a link or an image however you want for the markdown interface though. I think it's relevant. Yeah. Because currently, it's just a URL link. Right? You've got the add in an image. I don't see do we support video in markdown? I There's markdown, and that's There's really no such yeah. There's there's no native markdown for video. K. So not really. There's also no HTML attributes in markdown. There's a lot of things that are in markdown. That's okay. So, technically, we just need the file link. I'm putting a note in the ticket here in the in the discussion here. Go ahead. Go on this. Alright. Same question for the block editor. Is it also something where we wanna support it as well? Since we might want feature parity between between all of our editor interfaces. Agree. I don't even know what the block editor is capable of doing right now. So it's got image. Like we do image and attachment. What is attachment? Is is attachment already what we're trying to do? I think it is. Yeah. It might be. Yeah? Yeah. I think it is. Already is. Yep. So the only thing we because, the block editor natively supports that. The the library that we use for that just has it. Yep. Yep. The Wizzy tiny MCE does not doesn't have a concept of that yet, so we have to edit edit ourselves. Yep. Yeah. So you get select the file, and I guess the the one thing that I noticed is it doesn't have video. Should block editor have video? Or is it just file as a file as a file for these guys outside of the images that have captions? That's a good question. Let's see. Do I have video first deal in here? It's just in some video and see what the preview or window. I don't know what that just did. Oh, it downloaded. No. I have a duplicate copy of that. Lovely. So should it have so for parity, does does the block editor support video? Seems like it's just an attachment. Right? I think it's just an attachment. It's just doing it as an attachment right now, but should it have a video interface the same as the HTML does? No. Maybe. Or a video blank. Just for, like, again, feature parity across the where where possible. I think there's a separate plugin for editor JS, which is what we use in the for the block editor, but we'll have to try it out. Different feature request for a different day. All good. So we already have file, so the only place that this needs to be done is. Markdown in HTML. Right? And I think the block edit can just treat whatever attachment the way it sees fit. I will put a note Just for videos in the WEEZY week, do we just insert a video tag, or how does it work? Let's have a look. Yeah. I'll go test it. Yep. K. That's what I figured. Wizardwig. Also, what kind of fan fancy collection is it that you have there, Jonathan? My test my test collections always have all 3 of the editors in there. You guys can actually show and hide it. That's cool. Yeah. So I'm using the conditional rules. I use it for demos. So I have this in my Yeah. Yeah. Yeah. My CMS demo essentially where I've got a page a paragraph component. And then depending on, you know, if they're a WYSIWYG shop or they're a markdown shop or they're a block header, just being able to show off the different interfaces quickly and easily, but show and hide them. And it shows off the conditional rule capabilities of the app as well. So It's cool. My my debugging instance is just one of each on every page. Yeah. So so you do get a video player in Wizziweb. Yeah. It's yeah. I think it's just a video tag. If you check out the raw HTML of that, it's it's literally Giant kitchen sink collection. We everything in there. Yep. I have including just a flat text area. So all of our kind of Yeah. So it probably is a video. Yeah. Yep. So it actually renders it with Under the hood. With video HTML tags accordingly. So the question is, does the block editor and or we know markdown doesn't support it, but does the block editor support something similar? Right now we're just inserting it as a file. But if the block editor technically supports video, it would be nice to have parity to have the equivalency where video renders nicely. So I'll just put a note. Anyways, taking this back slightly more on track. This feature request as a whole, easy. I think it's easy easy to to accept it. That that's what I was going for. That's so much easy to implement necessarily. Easy to accept it. I think it's we should just do it. It's a good first issue. I think it's great for for PRs, if anybody wants to take a swing at this. I think there's a lot of new ideas and new feature requests that are worth discussing more. Like, I think this signed link approach to permissions is a very, very interesting one that will be very relevant for something like this. But with that being said, the eye on the clock and me also have a hard stop, unfortunately. I wanna say thank you very much for watching once more. We'll be back soon. Soon, Asia. It was a it was a minute since last time, but we'll be back, I believe in 2 weeks, and if not, soon. Make sure to check out this show on direct. Io/tv. Your request review. If you like doing this, somebody like having to get here.","e668e4c9-da13-438e-b855-95afe8a9e24c",[208,209,210],"6a0ed408-e558-4d6a-b647-0ad0ebe976f9","1205f141-ef72-462f-9515-e073fd888720","daf59fdc-7852-4d6b-abb0-47c605254e9e",[],{"reps":213},[214,270],{"name":215,"sdr":8,"link":216,"countries":217,"states":219},"John Daniels","https://meet.directus.io/meetings/john2144/john-contact-form-meeting",[218],"United States",[220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269],"Michigan","Indiana","Ohio","West Virginia","Kentucky","Virginia","Tennessee","North Carolina","South Carolina","Georgia","Florida","Alabama","Mississippi","New York","MI","IN","OH","WV","KY","VA","TN","NC","SC","GA","FL","AL","MS","NY","Connecticut","CT","Delaware","DE","Maine","ME","Maryland","MD","Massachusetts","MA","New Hampshire","NH","New Jersey","NJ","Pennsylvania","PA","Rhode Island","RI","Vermont","VT","Washington DC","DC",{"name":271,"link":272,"countries":273},"Michelle Riber","https://meetings.hubspot.com/mriber",[274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,251,462,463],"Albania","ALB","Algeria","DZA","Andorra","AND","Angola","AGO","Austria","AUT","Belgium","BEL","Benin","BEN","Bosnia and Herzegovina","BIH","Botswana","BWA","Bulgaria","BGR","Burkina Faso","BFA","Burundi","BDI","Cameroon","CMR","Cape Verde","CPV","Central African Republic","CAF","Chad","TCD","Comoros","COM","Côte d'Ivoire","CIV","Croatia","HRV","Czech Republic","CZE","Democratic Republic of Congo","COD","Denmark","DNK","Djibouti","DJI","Egypt","EGY","Equatorial Guinea","GNQ","Eritrea","ERI","Estonia","EST","Eswatini","SWZ","Ethiopia","ETH","Finland","FIN","France","FRA","Gabon","GAB","Gambia","GMB","Ghana","GHA","Greece","GRC","Guinea","GIN","Guinea-Bissau","GNB","Hungary","HUN","Iceland","ISL","Ireland","IRL","Italy","ITA","Kenya","KEN","Latvia","LVA","Lesotho","LSO","Liberia","LBR","Libya","LBY","Liechtenstein","LIE","Lithuania","LTU","Luxembourg","LUX","Madagascar","MDG","Malawi","MWI","Mali","MLI","Malta","MLT","Mauritania","MRT","Mauritius","MUS","Moldova","MDA","Monaco","MCO","Montenegro","MNE","Morocco","MAR","Mozambique","MOZ","Namibia","NAM","Niger","NER","Nigeria","NGA","North Macedonia","MKD","Norway","NOR","Poland","POL","Portugal","PRT","Republic of Congo","COG","Romania","ROU","Rwanda","RWA","San Marino","SMR","São Tomé and Príncipe","STP","Senegal","SEN","Serbia","SRB","Seychelles","SYC","Sierra Leone","SLE","Slovakia","SVK","Slovenia","SVN","Somalia","SOM","South Africa","ZAF","South Sudan","SSD","Spain","ESP","Sudan","SDN","Sweden","SWE","Tanzania","TZA","Togo","TGO","Tunisia","TUN","Uganda","UGA","United Kingdom","GBR","Vatican City","VAT","Zambia","ZMB","Zimbabwe","ZWE","UK","Germany","Netherlands","Switzerland","CH","NL",1773850448967]