[{"data":1,"prerenderedAt":7025},["ShallowReactive",2],{"topic-ai-trust-and-ethics":3},[4,171,516,759,955,1809,2472,4907,5816,6005,6366,6619,6991],{"id":5,"title":6,"body":7,"date":152,"description":153,"extension":154,"image":155,"imageAuthor":156,"imageLicense":157,"imageSource":158,"meta":159,"navigation":160,"path":161,"published":160,"seo":162,"slug":163,"stem":164,"tags":165,"__hash__":170},"articles\u002Farticles\u002Fbuilding-platforms-for-vendor-led-enterprises.md","Building Platforms For Vendor-Led Enterprises",{"type":8,"value":9,"toc":143},"minimark",[10,17,20,23,28,31,34,37,40,43,47,56,63,66,69,73,76,82,85,88,92,95,101,107,113,117,120,137,140],[11,12,13],"p",{},[14,15,16],"em",{},"A lot of my customers don't build their own integrations. They hire someone who does, for the length of a project, and then that someone leaves.",[11,18,19],{},"I keep running into the same customer shape. A business team with no technical know-how of its own, running a project on a vendor's time and a vendor's keyboard. The vendor ships the integration, invoices the last milestone, and moves on to their next engagement. What they leave behind becomes the customer's problem the moment something breaks.",[11,21,22],{},"In this article I want to unpack why that model quietly erodes integration quality, what I believe a platform aimed at this specific situation needs to assume about its users, and which capabilities actually move the needle rather than just adding another policy document nobody reads.",[24,25,27],"h2",{"id":26},"the-vendor-leaves-the-business-team-stays","The Vendor Leaves, The Business Team Stays",[11,29,30],{},"This is the part that's easy to miss if you've never sat inside one of these organisations. The people making the decision to integrate a new system are, quite reasonably, not the people who know how to integrate a new system. So they fly in the expertise: a systems integrator, a boutique vendor, a freelance specialist, whoever is \"behind the keyboard\" for the duration of the project.",[11,32,33],{},"That's not a bad model on its own. Specialisation exists for a reason.",[11,35,36],{},"Though the trouble starts the moment the project ends and the vendor's access is revoked. The customer's own integration team — the people who actually have to run this thing in production — gets pulled in two directions at once. During the project, they're fielding ad-hoc requests from a vendor who needs an endpoint, a credential or a decision made by end of day. After the project, they inherit whatever was built, with whatever documentation the vendor felt like leaving behind.",[11,38,39],{},"For better or worse.",[11,41,42],{},"I've seen \"for better\" plenty of times. I've also seen a canonical model quietly bypassed because nobody on the vendor side knew it existed, an API shipped without a single validation rule because nobody enforced one, and a support inbox that fills up six months after go-live because the person who understood the integration is now working for a different customer entirely.",[24,44,46],{"id":45},"governance-belongs-in-tooling-not-in-a-slide-deck","Governance Belongs In Tooling, Not In A Slide Deck",[11,48,49,50,55],{},"The reflex response to this is more governance. Write the principles down, hold a review board, make vendors sign off on an architecture document before they start. I understand the instinct — it's the same instinct I described when ",[51,52,54],"a",{"href":53},"\u002Farticles\u002Fautomate-api-governance","writing about API governance execution"," more broadly. But a PowerPoint has no opinion about the API description a vendor actually ships. It can't fail a build. It can't reject a pull request.",[11,57,58,62],{},[59,60,61],"strong",{},"Enterprise architecture that lives exclusively in slides is enterprise architecture that vendors will never open."," They have their own deadline, their own tooling, and precisely zero incentive to read your governance document before they start writing code.",[11,64,65],{},"What I believe instead is that the principles and patterns you want enforced need to be executable, and that expertise needs to sit at the edge of the estate rather than centralised in a review committee three approval steps away. A federated operating model — where the platform itself carries the know-how instead of a person who has to be pinged for it — is what makes this workable at the pace vendors actually operate on.",[11,67,68],{},"This is the difference between a rule that says \"APIs must follow our naming conventions\" and a rule that fails the pipeline when they don't. One is a hope. The other is enforcement that happens whether or not anyone remembers to check.",[24,70,72],{"id":71},"zero-ticket-integration-is-the-actual-goal","Zero-Ticket Integration Is The Actual Goal",[11,74,75],{},"Here's where I think most governance efforts stop too early. Enforcement alone gets you compliance, and compliance alone doesn't get vendors to like your platform — it gets them to route around it.",[11,77,78,81],{},[59,79,80],{},"The platform has to be worth using on its own merits, not just on pain of rejection."," If the fastest way for a vendor to integrate with your estate is also the way that keeps your architecture principles intact, you've won without a single review meeting. If the fastest way is to skip your platform and ask a human for a shortcut, you've lost regardless of what the governance document says.",[11,83,84],{},"That's what I mean by zero-ticket development. A vendor should never need to open a support ticket to understand what's available, how to consume it, or how their data maps onto your canonical model. The moment they do, you've reintroduced the ad-hoc overload this whole thing was supposed to prevent.",[11,86,87],{},"So the angle can't only be policy enforcement. It has to be facilitation and speed, delivered well enough that vendors don't want anything else.",[24,89,91],{"id":90},"what-the-capabilities-actually-need-to-do","What The Capabilities Actually Need To Do",[11,93,94],{},"I keep coming back to three things a platform like this needs to nail, in this order.",[11,96,97,100],{},[59,98,99],{},"It needs to make the customer's own business team want it."," Adoption doesn't start with vendors — it starts with the people who feel the benefit first. If a business team experiences what it's like to onboard a vendor without the usual chaos, they'll insist on the platform the next time a new vendor walks in. That's a stronger enforcement mechanism than any mandate from architecture.",[11,102,103,106],{},[59,104,105],{},"It needs to do the heavy lifting for the vendor, not just watch them."," SDK generation from the API description. Validation of that description before a single line of integration code gets written. A unified API surface so a vendor isn't reverse-engineering which of your seventeen internal systems they're actually supposed to talk to. Data mapping onto your canonical model, so the vendor's payload becomes your shape automatically instead of by convention nobody checks.",[11,108,109,112],{},[59,110,111],{},"It needs to lower the barrier to entry relentlessly."," A vendor who has never seen your estate before should be able to find what's available, read documentation that actually explains it, and see a diagram that makes the topology click — fast. Every hour a vendor spends guessing is an hour your integration team spends answering questions that a platform should have already answered.",[24,114,116],{"id":115},"closing-thoughts","Closing Thoughts",[11,118,119],{},"In an environment where you own the whole stack, governance can afford to be a conversation. In a vendor-led environment, I don't think it can:",[121,122,123,131],"ul",{},[124,125,126,127,130],"li",{},"A ",[59,128,129],{},"conversation-based approach"," assumes continuity — the same people, the same context, over time",[124,132,126,133,136],{},[59,134,135],{},"vendor-led environment"," guarantees the opposite — new people, no context, every project",[11,138,139],{},"Though the fix isn't to fight the vendor-led model. It's to build a platform that assumes it from the start — one that enforces what matters, facilitates what's tedious, and gets out of the way for everything else.",[11,141,142],{},"If a vendor never wants to leave your platform for their old way of working, you've built the right thing.",{"title":144,"searchDepth":145,"depth":145,"links":146},"",2,[147,148,149,150,151],{"id":26,"depth":145,"text":27},{"id":45,"depth":145,"text":46},{"id":71,"depth":145,"text":72},{"id":90,"depth":145,"text":91},{"id":115,"depth":145,"text":116},"2026-08-20","Why customers whose integration work is delivered by external vendors need a platform, not more governance meetings, to stop quality drifting away the moment the vendor leaves.","md","\u002Farticles\u002Fbuilding-platforms-for-vendor-led-enterprises\u002Fcover.png",null,"Public Domain","https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Original_Blueprint_of_United_States_National_Agricultural_Library.jpg",{},true,"\u002Farticles\u002Fbuilding-platforms-for-vendor-led-enterprises",{"title":6,"description":153},"building-platforms-for-vendor-led-enterprises","articles\u002Fbuilding-platforms-for-vendor-led-enterprises",[166,167,168,169],"governance","api","developer experience","maturity-model","YED0MGgB7v6Z4ze4rI_hkQgYnAoUeg_A5OoXsr7mmrQ",{"id":172,"title":173,"body":174,"date":502,"description":503,"extension":154,"image":504,"imageAuthor":505,"imageLicense":506,"imageSource":507,"meta":508,"navigation":160,"path":509,"published":160,"seo":510,"slug":511,"stem":512,"tags":513,"__hash__":515},"articles\u002Farticles\u002Fazure-native-service-bus-publishing-with-api-management.md","Azure: Native Service Bus Publishing With API Management",{"type":8,"value":175,"toc":493},[176,179,182,186,189,192,195,198,202,210,213,216,220,223,226,229,242,411,414,418,421,424,427,431,434,441,448,451,455,458,461,465,489],[11,177,178],{},"For platform engineers and developers working within the Azure ecosystem, the line between synchronous and asynchronous services often requires building extra connective tissue — typically in the form of an Azure Function or a Logic App — just to put a message onto a Service Bus. This adds complexity, cost, and another component to manage.",[11,180,181],{},"That's why the introduction of the native Service Bus message publishing policy in Azure API Management (APIM) is a significant development. This new policy, announced in preview on October 19, 2025, promises to streamline this asynchronous messaging directly into the API gateway.",[24,183,185],{"id":184},"why-a-native-service-bus-policy","Why A Native Service Bus Policy?",[11,187,188],{},"The primary driver behind this feature is simplification.",[11,190,191],{},"Previously, if you wanted an HTTP-based API call in APIM to trigger an asynchronous backend process, you commonly used a Logic App or Azure Function component to work as a channel adapter. This component's sole job was to take the message, perhaps apply some transformation and publish it to a Service Bus.",[11,193,194],{},"The new policy eliminates the need for this individual entirely. By allowing APIM to publish messages directly to a Service Bus queue or topic, you can decouple your frontend APIs from your backend event consumers with a single policy.",[11,196,197],{},"This reduces usage costs, the number of required components and it consolidates messaging concerns into APIM, all while improving maintainability at the gateway level. This shift further simplifies the topology of integrations on Azure, allowing APIM to serve as a unified gateway for both synchronous and asynchronous communication.",[24,199,201],{"id":200},"what-is-the-native-publishing-policy","What Is The Native Publishing Policy?",[11,203,204,205,209],{},"The built-in policy named ",[206,207,208],"code",{},"\u003Csend-service-bus-message>",", currently in preview, empowers you to configure an APIM operation to send a message to Service Bus as part of its inbound or outbound processing flow.",[11,211,212],{},"The communication is secured using Managed Identities, which is a best practice that removes the need to store Service Bus connection strings as secrets within APIM. You enable a system- or user-assigned managed identity on your APIM instance and grant it the \"Azure Service Bus Data Sender\" role on the target queue or topic. The policy itself is then configured with the details of the Service Bus namespace and the payload you wish to send.",[11,214,215],{},"With this in place, APIM handles the authentication and message publishing natively, reducing what used to be a multi-step, code-driven process into a few lines of declarative XML.",[24,217,219],{"id":218},"how-to-implement-native-service-bus-publishing","How To Implement Native Service Bus Publishing",[11,221,222],{},"The main advice for implementation is to start with a \"fire-and-forget\" mindset. The most powerful use case is to accept an HTTP request, immediately queue it for backend processing, and return a 201 Created or 202 Accepted response to the client.",[11,224,225],{},"This makes the API highly responsive while ensuring the workload is safely queued.",[11,227,228],{},"Implementation is straightforward.",[230,231,232,235],"ol",{},[124,233,234],{},"Ensure your APIM instance has a managed identity enabled and has been granted the Azure Service Bus Data Sender role on the target Service Bus resource.",[124,236,237,238,241],{},"Within your API operation's ",[206,239,240],{},"\u003Cinbound>"," policy, you would add the following:",[243,244,248],"pre",{"className":245,"code":246,"language":247,"meta":144,"style":144},"language-xml shiki shiki-themes github-dark-default","\u003C!--\n  send-service-bus-message Policy XML\n-->\n\u003Cpolicies>\n    \u003Cinbound>\n        \u003Cbase \u002F>\n        \u003Csend-service-bus-message\n            namespace=\"your-namespace.servicebus.windows.net\"\n            queue-name=\"your-queue-name\"\n            ignore-error=\"false\">\n            \u003Cpayload>@(context.Request.Body.As\u003Cstring>(preserveContent: true))\u003C\u002Fpayload>\n        \u003C\u002Fsend-service-bus-message>\n\n        \u003Creturn-response>\n            \u003Cset-status code=\"201\" reason=\"Created\" \u002F>\n            \u003Cset-body>Message queued successfully.\u003C\u002Fset-body>\n        \u003C\u002Freturn-response>\n    \u003C\u002Finbound>\n    \u003Cbackend>\n        \u003C\u002Fbackend>\n    \u003Coutbound>\n        \u003Cbase \u002F>\n    \u003C\u002Foutbound>\n    \u003Con-error>\n        \u003Cbase \u002F>\n    \u003C\u002Fon-error>\n\u003C\u002Fpolicies>\n","xml",[206,249,250,258,263,269,275,281,287,293,299,305,311,317,323,329,335,341,347,353,359,365,371,377,382,388,394,399,405],{"__ignoreMap":144},[251,252,255],"span",{"class":253,"line":254},"line",1,[251,256,257],{},"\u003C!--\n",[251,259,260],{"class":253,"line":145},[251,261,262],{},"  send-service-bus-message Policy XML\n",[251,264,266],{"class":253,"line":265},3,[251,267,268],{},"-->\n",[251,270,272],{"class":253,"line":271},4,[251,273,274],{},"\u003Cpolicies>\n",[251,276,278],{"class":253,"line":277},5,[251,279,280],{},"    \u003Cinbound>\n",[251,282,284],{"class":253,"line":283},6,[251,285,286],{},"        \u003Cbase \u002F>\n",[251,288,290],{"class":253,"line":289},7,[251,291,292],{},"        \u003Csend-service-bus-message\n",[251,294,296],{"class":253,"line":295},8,[251,297,298],{},"            namespace=\"your-namespace.servicebus.windows.net\"\n",[251,300,302],{"class":253,"line":301},9,[251,303,304],{},"            queue-name=\"your-queue-name\"\n",[251,306,308],{"class":253,"line":307},10,[251,309,310],{},"            ignore-error=\"false\">\n",[251,312,314],{"class":253,"line":313},11,[251,315,316],{},"            \u003Cpayload>@(context.Request.Body.As\u003Cstring>(preserveContent: true))\u003C\u002Fpayload>\n",[251,318,320],{"class":253,"line":319},12,[251,321,322],{},"        \u003C\u002Fsend-service-bus-message>\n",[251,324,326],{"class":253,"line":325},13,[251,327,328],{"emptyLinePlaceholder":160},"\n",[251,330,332],{"class":253,"line":331},14,[251,333,334],{},"        \u003Creturn-response>\n",[251,336,338],{"class":253,"line":337},15,[251,339,340],{},"            \u003Cset-status code=\"201\" reason=\"Created\" \u002F>\n",[251,342,344],{"class":253,"line":343},16,[251,345,346],{},"            \u003Cset-body>Message queued successfully.\u003C\u002Fset-body>\n",[251,348,350],{"class":253,"line":349},17,[251,351,352],{},"        \u003C\u002Freturn-response>\n",[251,354,356],{"class":253,"line":355},18,[251,357,358],{},"    \u003C\u002Finbound>\n",[251,360,362],{"class":253,"line":361},19,[251,363,364],{},"    \u003Cbackend>\n",[251,366,368],{"class":253,"line":367},20,[251,369,370],{},"        \u003C\u002Fbackend>\n",[251,372,374],{"class":253,"line":373},21,[251,375,376],{},"    \u003Coutbound>\n",[251,378,380],{"class":253,"line":379},22,[251,381,286],{},[251,383,385],{"class":253,"line":384},23,[251,386,387],{},"    \u003C\u002Foutbound>\n",[251,389,391],{"class":253,"line":390},24,[251,392,393],{},"    \u003Con-error>\n",[251,395,397],{"class":253,"line":396},25,[251,398,286],{},[251,400,402],{"class":253,"line":401},26,[251,403,404],{},"    \u003C\u002Fon-error>\n",[251,406,408],{"class":253,"line":407},27,[251,409,410],{},"\u003C\u002Fpolicies>\n",[11,412,413],{},"This configuration captures the incoming request body, sends it to the specified queue, and immediately sends a 201 response to the client, preventing the caller from having to wait for any backend processing.",[24,415,417],{"id":416},"how-this-enhances-cloud-integration","How This Enhances Cloud Integration",[11,419,420],{},"This policy solidifies APIM's role as the central hub for modern cloud integrations. It's no longer just a gateway for synchronous REST or SOAP APIs; it is now also a first-class citizen in an event-driven architecture (EDA). Platform engineers can now design systems where IoT devices, partners, or mobile clients can send data via a standard, secured, and rate-limited HTTP POST, and have that data seamlessly fanned out to multiple microservices via Service Bus topics.",[11,422,423],{},"This capability bridges the gap between the synchronous, request-response integration style and the asynchronous, event-based integration style. It allows developers to build more scalable and resilient systems, as the API gateway can absorb traffic spikes by queuing requests, protecting backend services from being overwhelmed.",[11,425,426],{},"This direct integration simplifies governance, as all communication — whether sync or async — is now managed, secured, and observed from the single pane of glass that APIM provides.",[24,428,430],{"id":429},"when-to-be-cautious","When To Be Cautious",[11,432,433],{},"It is crucial to understand that this policy is purpose-built for one-way message publishing. It is not designed for synchronous request-reply scenarios.",[11,435,436,437,440],{},"If your client sends a request and needs to wait for a specific response generated by the backend consumer of that message, this policy is not the right tool. In that scenario, you would still use a traditional ",[206,438,439],{},"\u003Cforward-request>"," to a backend that can perform the work and return a synchronous response.",[11,442,443,444,447],{},"The ",[206,445,446],{},"send-service-bus-message"," policy is for \"fire-and-forget\" patterns. The client's request is acknowledged, but the client does not receive a response from the eventual processor.",[11,449,450],{},"Using it for the wrong pattern will lead to a disconnected client and an architecture that doesn't meet its requirements.",[24,452,454],{"id":453},"get-started-and-share-your-thoughts","Get Started And Share Your Thoughts",[11,456,457],{},"The new native Service Bus publishing policy in Azure API Management is a powerful tool for simplifying event-driven setups. It reduces complexity, lowers operational overhead, and empowers developers and platform engineers to build more resilient, decoupled systems.",[11,459,460],{},"What are your thoughts? How do you see this new policy changing your implementation patterns on Azure?",[24,462,464],{"id":463},"links","Links",[121,466,467,475,482],{},[124,468,469],{},[51,470,474],{"href":471,"rel":472},"https:\u002F\u002Ftechcommunity.microsoft.com\u002Fblog\u002Fintegrationsonazureblog\u002Fintroducing-native-service-bus-message-publishing-from-azure-api-management-prev\u002F4462644",[473],"nofollow","Introducing native Service Bus message publishing from Azure API Management (preview)",[124,476,477],{},[51,478,481],{"href":479,"rel":480},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fapi-management\u002Fsend-service-bus-message-policy",[473],"Send Service Bus message policy — Microsoft Learn",[124,483,484],{},[51,485,488],{"href":486,"rel":487},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fapi-management\u002Fapi-management-howto-send-service-bus",[473],"How to send a message to a Service Bus queue or topic — Microsoft Learn",[490,491,492],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":144,"searchDepth":145,"depth":145,"links":494},[495,496,497,498,499,500,501],{"id":184,"depth":145,"text":185},{"id":200,"depth":145,"text":201},{"id":218,"depth":145,"text":219},{"id":416,"depth":145,"text":417},{"id":429,"depth":145,"text":430},{"id":453,"depth":145,"text":454},{"id":463,"depth":145,"text":464},"2025-10-30","Azure API Management can now publish directly to Service Bus with a native policy, cutting the Function or Logic App you used to need just to bridge sync and async traffic.","\u002Farticles\u002Fazure-native-service-bus-publishing-with-api-management\u002Fcover.png","André Karwath aka Aka","CC BY-SA 2.5","https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Lightning_cloud_to_cloud_(aka).jpg",{},"\u002Farticles\u002Fazure-native-service-bus-publishing-with-api-management",{"title":173,"description":503},"azure-native-service-bus-publishing-with-api-management","articles\u002Fazure-native-service-bus-publishing-with-api-management",[167,514],"cloud-integration","zSyR4oy-Q3OLWSiTZ9Pu3MYiOn9iT4Mcr998BD-n0Es",{"id":517,"title":518,"body":519,"date":746,"description":747,"extension":154,"image":748,"imageAuthor":749,"imageLicense":750,"imageSource":751,"meta":752,"navigation":160,"path":753,"published":160,"seo":754,"slug":755,"stem":756,"tags":757,"__hash__":758},"articles\u002Farticles\u002Fmaturity-models-and-tech.md","What Should We Do Next? Ask a Focus Area Maturity Model",{"type":8,"value":520,"toc":739},[521,526,529,532,540,543,546,549,552,556,559,562,565,571,574,577,580,584,587,590,593,596,599,602,606,609,612,615,625,628,631,637,640,644,647,650,653,656,659,662,665,669,672,675,702,705,728,731,734],[11,522,523],{},[14,524,525],{},"A look at how a maturity model turns \"what should we do next?\" from a matter of taste into something you can put on a table.",[11,527,528],{},"I've worked within a lot of different organisations, each with their own stage of \"technological maturity\". Depending on the management, the people, the culture and the technology stack, every one of them sits somewhere on a spectrum between rudimentary and advanced.",[11,530,531],{},"And in nearly every one of them, someone eventually asks me the same question.",[533,534,535],"blockquote",{},[11,536,537],{},[14,538,539],{},"\"So what should we do next?\"",[11,541,542],{},"It usually comes from a management position. I get it more often these days now that I'm specialising in integration.",[11,544,545],{},"The people asking are rarely clueless. There's normally a decent grasp of the different capabilities and practices within the domain. But knowing the parts of a domain and knowing which part to touch next turn out to be very different things.",[11,547,548],{},"This is where a maturity model comes into play.",[11,550,551],{},"In this post I'll go into why the honest answer to that question is so hard to give, what a maturity model does about it, why the \"focus area\" variety fits a messy technology landscape better than the classic ladder, and how requirements let you describe the state of a solution without falling back on opinion.",[24,553,555],{"id":554},"everybody-has-an-answer-and-thats-the-problem","Everybody has an answer, and that's the problem",[11,557,558],{},"Ask five people in an organisation what to do next and you will get five different answers.",[11,560,561],{},"The platform engineer wants a service mesh. The security officer wants the gateway locked down. And somebody who read something on a flight wants an API marketplace by the third quarter.",[11,563,564],{},"None of them are being unreasonable. They're each looking at the domain through the part of it they own — and from there, their answer genuinely is the most urgent thing.",[11,566,567,570],{},[59,568,569],{},"The trouble is that a manager asking \"what should we do next?\" has no way of weighing those answers against each other."," They're being handed five conclusions with no shared scale underneath them, and the one that wins tends to be the one argued most confidently.",[11,572,573],{},"Is that really how a budget should get spent?",[11,575,576],{},"What the question really asks for is a way to compare things that don't look comparable. How do you put \"we have no naming conventions\" next to \"we have no runtime monitoring\" and say something defensible about which one comes first?",[11,578,579],{},"Preferably without needing to be an engineer to follow the reasoning.",[24,581,583],{"id":582},"a-map-of-the-domain-not-a-ladder","A map of the domain, not a ladder",[11,585,586],{},"The main premise of a maturity model is to weigh the different capabilities and practices within a domain against each other.",[11,588,589],{},"It gives you two things at once. First a vocabulary for the domain, so that everyone is at least naming the same things the same way. Then a sense of what \"further along\" actually means for each of those things.",[11,591,592],{},"Think of a house that needs work.",[11,594,595],{},"You can have a beautiful kitchen and a roof that leaks at the same time. Nobody would call that house \"60% renovated\", and nobody sensible would spend the next budget on the kitchen. The rooms are at different stages, and the ones you do first are the ones holding the others back.",[11,597,598],{},"Technology landscapes are the same. Organisations are rarely uniformly mature. They're advanced in the corner someone cared about and rudimentary everywhere else, and the interesting question is never \"what's our score\" but \"which room is the roof\".",[11,600,601],{},"A maturity model is the floor plan that lets you ask that question in the first place.",[24,603,605],{"id":604},"why-focus-areas-beat-a-five-level-ladder","Why focus areas beat a five-level ladder",[11,607,608],{},"The models most people have met are the ladder kind. Five levels, the whole organisation sits on one of them, and you climb.",[11,610,611],{},"They're easy to communicate and they make for a very satisfying slide in a steering committee. They're also a poor fit for the thing we just described, because they force one number onto a landscape that is genuinely uneven.",[11,613,614],{},"A focus area maturity model goes about it differently.",[11,616,617,618,621,622],{},"Instead of one ladder for everything, the domain gets broken into ",[59,619,620],{},"focus areas",", coherent chunks of the domain that are able to advance on their own. Something like API design, versioning, security, documentation, lifecycle management — the practices someone could plausibly own. Each focus area then gets its own progression, and this is the part that matters: ",[59,623,624],{},"they don't all have the same number of steps.",[11,626,627],{},"Some focus areas are basically done after two moves, whilst others have six meaningfully different stages worth distinguishing.",[11,629,630],{},"Those progressions are then laid out against each other on a matrix, so you can read off not just where each focus area sits, but the order things should sensibly happen in across the whole domain. Getting documentation to its second stage might depend on design conventions reaching their third.",[11,632,633,636],{},[59,634,635],{},"The result is less like a ladder and more like a route."," It doesn't tell you that you're a Level 3 organisation — a number that never survived a conversation with anyone doing the work anyway. It tells you that these four things are the next reasonable moves, and that this one unlocks two others.",[11,638,639],{},"Which, conveniently, is the shape of the question that was asked.",[24,641,643],{"id":642},"requirements-are-where-the-objectivity-comes-from","Requirements are where the objectivity comes from",[11,645,646],{},"None of this helps if deciding where a focus area sits is still a matter of opinion. A model that produces a confident number from a vague conversation has just laundered the guesswork.",[11,648,649],{},"So where does the placement come from, if not from judgement? It comes from requirements.",[11,651,652],{},"Each stage within a focus area is defined by an explicit list of requirements, which are concrete and checkable statements about what must be true for that stage to count. Not \"API design is mature\" but something you can actually hold an organisation against and get a yes or a no.",[11,654,655],{},"A capability sits at a given stage when the requirements for that stage are met, and not a moment before.",[11,657,658],{},"This is what makes the outcome defensible rather than persuasive. When someone disagrees with a placement, and they will, the disagreement has somewhere to go. You're no longer arguing about whether the API practice is \"good\". You're pointing at a requirement and asking whether it's met.",[11,660,661],{},"That tends to be a much shorter argument, and it is one a non-technical stakeholder can follow all the way down.",[11,663,664],{},"It also means the model produces its own backlog. The requirements you don't meet at the next stage are, quite literally, the list of things to do next.",[24,666,668],{"id":667},"what-it-costs-you","What it costs you",[11,670,671],{},"I don't want to oversell any of this though.",[11,673,674],{},"In theory a focus area maturity model gives you a lot:",[121,676,677,683,690,696],{},[124,678,126,679,682],{},[59,680,681],{},"shared vocabulary"," for a domain, which alone resolves a surprising number of arguments",[124,684,685,686,689],{},"An ",[59,687,688],{},"ordering"," that respects dependencies instead of treating every gap as equally urgent",[124,691,126,692,695],{},[59,693,694],{},"defensible position"," that survives contact with someone who disagrees",[124,697,126,698,701],{},[59,699,700],{},"backlog"," that falls out of the assessment rather than being negotiated",[11,703,704],{},"Though in the trenches of reality it asks something back:",[121,706,707,714,721],{},[124,708,709,710,713],{},"Somebody has to ",[59,711,712],{},"actually assess it",", which means interviews, reading, and hours of cross-referencing what people said against a long list of requirements",[124,715,716,717,720],{},"The requirements need to ",[59,718,719],{},"fit the organisation",", and a model borrowed wholesale from elsewhere will describe a domain nobody there recognises",[124,722,723,724,727],{},"The whole thing goes ",[59,725,726],{},"stale",", because the landscape moves while the assessment sits in a document",[11,729,730],{},"That last set is the reason this doesn't get done as often as it probably should. The value is clear enough to most people I speak to. It's the effort of getting there that quietly kills it.",[11,732,733],{},"That effort is exactly the part I've been trying to automate, and it's what I want to write about next.",[11,735,736],{},[59,737,738],{},"But first: is the answer you're currently giving to \"what should we do next?\" one you could defend, or just one you argued well?",{"title":144,"searchDepth":145,"depth":145,"links":740},[741,742,743,744,745],{"id":554,"depth":145,"text":555},{"id":582,"depth":145,"text":583},{"id":604,"depth":145,"text":605},{"id":642,"depth":145,"text":643},{"id":667,"depth":145,"text":668},"2025-04-15","Every engagement eventually produces the same question from management. A maturity model turns it from a matter of opinion into something you can point at.","\u002Farticles\u002Fmaturity-models-and-tech\u002Fcover.png","Basile Morin","CC BY-SA 4.0","https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Wooden_staircase_steps_in_the_forest_of_Hallasan_Park_Eorimok_Trail_at_dusk_on_Jeju_Island_in_South_Korea.jpg",{},"\u002Farticles\u002Fmaturity-models-and-tech",{"title":518,"description":747},"maturity-models-and-tech","articles\u002Fmaturity-models-and-tech",[169,166],"hI3FKKBUmGn4sBohMTwdFkLYDvA5_KILuXb8MRkBVaU",{"id":760,"title":761,"body":762,"date":941,"description":942,"extension":154,"image":943,"imageAuthor":156,"imageLicense":156,"imageSource":156,"meta":944,"navigation":160,"path":945,"published":160,"seo":946,"slug":947,"stem":948,"tags":949,"__hash__":954},"articles\u002Farticles\u002Ftrust-in-ai.md","Trust in AI? A Reshaping of Our Social Contract",{"type":8,"value":763,"toc":936},[764,769,772,792,795,799,802,807,810,815,818,822,825,828,831,834,837,841,844,847,858,861,881,884,889,895,898,906,912,917,920],[11,765,766],{},[14,767,768],{},"“A dive into how AI is reshaping the frontier of our social contract”",[11,770,771],{},"Due to recent events in my life as well as the rampant emergence of AI have made me start to reflect on trust. It plays a vital role throughout my whole personal and professional life.",[533,773,774,777,780,783,786,789],{},[11,775,776],{},"“Am I able to trust this contractor with my money and — more importantly — my valuable home?”",[11,778,779],{},"“Am I able to trust the developers within my team to tell me when they’re stuck, so we can find a solution together?”",[11,781,782],{},"“Am I able to trust the bank with my savings during periods of uncertainty?”",[11,784,785],{},"“Is the customer able to trust me to design, develop and implement a solution that will solve their problems?”",[11,787,788],{},"“Do I trust whatever results I get from a search engine?”",[11,790,791],{},"“Do I trust whatever result I get from an LLM?”",[11,793,794],{},"With this post I put my thoughts into words so that I can share, learn and reflect out in public instead of within the confines of my head.",[24,796,798],{"id":797},"trust-as-cost-benefit-mechanism","Trust, as cost-benefit mechanism",[11,800,801],{},"Trust is a central part in the interactions we have throughout our everyday lives. It helps us determine whether or not to rely on others in order to achieve something, to help us solve a problem. We tend to do things ourselves whenever there is more trust in ourselves than in the other, given certain conditions. This can be costs, risks, consequences, capabilities, constraints, etc. This is why DIY is a thing. Especially for people who’ve increased the trust in themselves enough through practice in order for it to cross a certain threshold.",[533,803,804],{},[11,805,806],{},"“I trust myself enough to paint this wall. It’s not worth it to pay a painter for just one wall.”",[11,808,809],{},"Compared to:",[533,811,812],{},[11,813,814],{},"“I don’t trust myself enough to paint the exterior of my house. I trust a painter more and they’ll do a better and safer job.”",[11,816,817],{},"Sometimes we have no choice but to trust another party because they provide something we can hardly get ourselves. I can choose to get my own drinking water if I don’t trust our regional provider, but I would have to perform miracles to get there disregarding the practicality of achieving it.",[24,819,821],{"id":820},"trust-a-life-without-it","Trust, a life without it",[11,823,824],{},"If trust is simply part of our lives, will we ever not require it? Like many of these questions the answer starts with: “it depends”.",[11,826,827],{},"Take financial networks for example. We can find a well-known solution there in the form of distributed ledger technology. In particular Bitcoin eliminates trust within its protocol by facilitating transactions between two parties that have to follow a strict set of rules that others are incentivised to follow.",[11,829,830],{},"Since there’s no owner of the network, the code is open-source and maintainers work on it — mainly — out of their own virtue. You have a solution that in principle is able to work without trust. Another example of a concept eliminating trust is a zero-knowledge proof.",[11,832,833],{},"This is an algorithm that’s able to determine the validity of a statement without sharing any details relating to the proof. Therefore, there is no longer a need to unwillingly trust third parties with your personal details in theory. This would mean that in order to prove you are of an eligible age, you would no longer need to provide the exact details of your date of birth.",[11,835,836],{},"These tools can help us in a way. But how far are we willing to go in relying in technology to eliminate trust?",[24,838,840],{"id":839},"trust-the-freedom-of-ai","Trust, the freedom of AI",[11,842,843],{},"This brings me to AI.",[11,845,846],{},"With the increase of agency we appoint to AI we will come to a point where we have to delegate larger amounts of trust to these actors within our society.",[121,848,849,852,855],{},[124,850,851],{},"What would this look like?",[124,853,854],{},"How will it impact our own sense of agency?",[124,856,857],{},"What will be the impact on our social contract when we dedicate such a vital and humane part of what we are to a system?",[11,859,860],{},"A thought experiment where we fast forward into the future…",[533,862,863,866,869,872,875,878],{},[11,864,865],{},"You have had a hard time lately when come across an advertisement relating to summer trips during your break. Dreaming about getting out of here you ask your AI assistant to schedule a trip for the upcoming summer.",[11,867,868],{},"As your AI assistant has access to virtually any information like your agenda, your mental wellbeing — through an app like Apple’s Health — , your banking information, it is more than capable of booking this trip for you.",[11,870,871],{},"When booking the trip according to your preferences the assistant encounters a problem: Insufficient Funds on the spending account…",[11,873,874],{},"You have set a policy to not go into debt. But the assistant infers from the different sources that you’re having a hard time and are at risk of burning out if you don’t take a break soon.",[11,876,877],{},"It determines to transfer the required funds from your savings account and continues to book the trip for you.",[11,879,880],{},"When in Italy that summer you sip on your drink as you throw your legs up during your well-deserved break.",[11,882,883],{},"This may seem like an irrelevant case of booking a vacation in which our protagonist even had a happy ending.",[11,885,886],{},[59,887,888],{},"But haven’t we crossed some worrying lines along the way?",[11,890,891,894],{},[59,892,893],{},"Don’t get me wrong. I see myself as a tech-optimist and I see a bright future ahead of us with all the ongoing developments",", especially in the field of AI and the added capabilities that quantum computing may provide as well.",[11,896,897],{},"But we do have to be aware of our trust shifting, and whether it might be misplaced at certain times.",[121,899,900,903],{},[124,901,902],{},"Will we always be fully checking the results to our prompt?",[124,904,905],{},"Will we always keep fact-checking if an AI is hallucinating?",[11,907,908,911],{},[59,909,910],{},"As with many technological advancements being aware of whatever lies at the core tends to become a commodity."," The majority no longer wants to know where their drinking water comes from, how it gets to their house and how it is cleaned after they’ve used it. I am curious to see how our trust will be shifting in the coming years.",[11,913,914],{},[59,915,916],{},"How far would you go in trusting an AI?",[11,918,919],{},"More on this topic 👇",[121,921,922,929],{},[124,923,924],{},[51,925,928],{"href":926,"rel":927},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=rAEqP9VEhe8",[473],"Computerphile on Generative AI’s Greatest Flaw",[124,930,931],{},[51,932,935],{"href":933,"rel":934},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=4GLSzuYXh6w&t=3035s",[473],"Satya Nadella (Microsoft CEO) on Legal barriers to AI",{"title":144,"searchDepth":145,"depth":145,"links":937},[938,939,940],{"id":797,"depth":145,"text":798},{"id":820,"depth":145,"text":821},{"id":839,"depth":145,"text":840},"2025-02-28","As AI becomes more integrated into everything we do, we need to reflect on the trust we place in it. How far are we willing to go in trusting AI?","\u002Farticles\u002Ftrust-in-ai\u002Fcover.png",{},"\u002Farticles\u002Ftrust-in-ai",{"title":761,"description":942},"trust-in-ai","articles\u002Ftrust-in-ai",[950,951,952,953],"ai","social contract","technology","ethics","tuvSEqKyms01ybGXvN-QxncqyLEklXEC-AhBJOMSdY4",{"id":956,"title":957,"body":958,"date":1798,"description":1799,"extension":154,"image":1800,"imageAuthor":156,"imageLicense":156,"imageSource":156,"meta":1801,"navigation":160,"path":1802,"published":160,"seo":1803,"slug":1804,"stem":1805,"tags":1806,"__hash__":1808},"articles\u002Farticles\u002Fcapture-api-changes-with-overlay.md","Capture API Changes with Overlay",{"type":8,"value":959,"toc":1791},[960,971,974,977,993,996,999,1003,1006,1009,1014,1017,1021,1028,1031,1051,1135,1138,1141,1160,1163,1166,1170,1173,1176,1179,1182,1196,1201,1574,1577,1582,1589,1594,1602,1639,1645,1648,1654,1657,1661,1664,1684,1687,1691,1694,1699,1702,1705,1726,1729,1750,1753,1756,1759,1788],[11,961,962,963,966,967,970],{},"In Dutch, we have a saying: ",[14,964,965],{},"“Aan de weg timmeren,”"," which literally translates to ",[14,968,969],{},"“Carpeting the road.”"," It’s used to describe someone who makes consistent progress. This phrase comes to mind whenever I see posts from the OpenAPI Initiative or those involved with the organisation.",[11,972,973],{},"Whatever your opinion on their OpenAPI Specifications might be, it can’t be denied that it has become the most common way of describing RESTful APIs. If you’re even slightly into the API space, you’ve probably noticed an increase in buzz surrounding these specifications as well.",[11,975,976],{},"I’ve already covered developments on their other two specifications;",[121,978,979,986],{},[124,980,981],{},[51,982,985],{"href":983,"rel":984},"https:\u002F\u002Fbrandon-verzuu.medium.com\u002Feverything-you-need-to-know-about-openapi-version-4-f605b99ac443",[473],"OpenAPI, and API description specification (v4 “Moonwalk”)",[124,987,988],{},[51,989,992],{"href":990,"rel":991},"https:\u002F\u002Fbrandon-verzuu.medium.com\u002Farazzo-specification-for-api-workflows-9306e7819fb6",[473],"Arazzo, a workflow specification (v1)",[11,994,995],{},"Now I’ve finally made it around to covering their other specification: Overlay.",[11,997,998],{},"In this post, I’ll dissect the use case for it, explain the components, create an implementation I think is applicable to the real world and list my final thoughts!",[24,1000,1002],{"id":1001},"use-case-for-overlay","Use case for Overlay",[11,1004,1005],{},"The Overlay Specification can be used to create a document-based overlay for the descriptions in your OpenAPI Specification. To continue this accidental series on the different OpenAPI Initiative specifications, we’ll be taking a look at the currently final available specification called Overlay.",[11,1007,1008],{},"The name is quite fitting when looking at the specification. Overlay is intended to function as an actual overlay to an API description, making it easier to apply changes throughout the development cycle.",[11,1010,1011],{},[59,1012,1013],{},"I expect Overlay to be used in the automation of protocols during the API lifecycle, for example, applying a “deprecation protocol” when a deprecation flag is added to an endpoint in the API description.",[11,1015,1016],{},"Before we dive into more detail on the uses of Overlay, let’s first examine the available components.",[24,1018,1020],{"id":1019},"components-of-overlay","Components of Overlay",[11,1022,1023,1024,1027],{},"An Overlay Specification is only relevant when there is an API Specification. Overlay allows its writer to target a piece of OpenAPI Specification using an ",[59,1025,1026],{},"Action Object",".",[11,1029,1030],{},"The Action Object describes a change that needs to be applied. This is done using these properties:",[121,1032,1033,1039,1045],{},[124,1034,1035,1038],{},[59,1036,1037],{},"target",": A JSONPath query describing the component that will undergo the described action.\ndescription: An explanation of the action in natural language",[124,1040,1041,1044],{},[59,1042,1043],{},"update",": An object containing the structure to apply to an API description",[124,1046,1047,1050],{},[59,1048,1049],{},"remove",": A flag that describes if the target needs to be removed from the API description",[243,1052,1056],{"className":1053,"code":1054,"language":1055,"meta":144,"style":144},"language-yaml shiki shiki-themes github-dark-default","# an overlay file can contain more of actions\n- target: $.info\n    description: Always replace info object with customer-facing details\n    update:\n       contact:\n        email: support@acme.com\n        name: ACME\n        url: 'https:\u002F\u002Fwww.acme.com'\n","yaml",[206,1057,1058,1064,1080,1090,1098,1105,1115,1125],{"__ignoreMap":144},[251,1059,1060],{"class":253,"line":254},[251,1061,1063],{"class":1062},"sH3jZ","# an overlay file can contain more of actions\n",[251,1065,1066,1070,1073,1076],{"class":253,"line":145},[251,1067,1069],{"class":1068},"sZEs4","- ",[251,1071,1037],{"class":1072},"sPWt5",[251,1074,1075],{"class":1068},": ",[251,1077,1079],{"class":1078},"s9uIt","$.info\n",[251,1081,1082,1085,1087],{"class":253,"line":265},[251,1083,1084],{"class":1072},"    description",[251,1086,1075],{"class":1068},[251,1088,1089],{"class":1078},"Always replace info object with customer-facing details\n",[251,1091,1092,1095],{"class":253,"line":271},[251,1093,1094],{"class":1072},"    update",[251,1096,1097],{"class":1068},":\n",[251,1099,1100,1103],{"class":253,"line":277},[251,1101,1102],{"class":1072},"       contact",[251,1104,1097],{"class":1068},[251,1106,1107,1110,1112],{"class":253,"line":283},[251,1108,1109],{"class":1072},"        email",[251,1111,1075],{"class":1068},[251,1113,1114],{"class":1078},"support@acme.com\n",[251,1116,1117,1120,1122],{"class":253,"line":289},[251,1118,1119],{"class":1072},"        name",[251,1121,1075],{"class":1068},[251,1123,1124],{"class":1078},"ACME\n",[251,1126,1127,1130,1132],{"class":253,"line":295},[251,1128,1129],{"class":1072},"        url",[251,1131,1075],{"class":1068},[251,1133,1134],{"class":1078},"'https:\u002F\u002Fwww.acme.com'\n",[11,1136,1137],{},"The change describes that the info object of an API description will be updated with the information.",[11,1139,1140],{},"JSON Path can be used instead of a hardcoded value for the target property. This allows for large manipulations using wildcards (*) and JSON Path Expressions.",[243,1142,1144],{"className":1053,"code":1143,"language":1055,"meta":144,"style":144},"# This expression will result in a list of ALL responses in an API description.\ntarget: $.paths.*.*.responses\n",[206,1145,1146,1151],{"__ignoreMap":144},[251,1147,1148],{"class":253,"line":254},[251,1149,1150],{"class":1062},"# This expression will result in a list of ALL responses in an API description.\n",[251,1152,1153,1155,1157],{"class":253,"line":145},[251,1154,1037],{"class":1072},[251,1156,1075],{"class":1068},[251,1158,1159],{"class":1078},"$.paths.*.*.responses\n",[11,1161,1162],{},"This is the basics of what is possible with the specification.",[11,1164,1165],{},"Let’s take a problem I have encountered numerous times and see how we could offer a solution for it with Overlay.",[24,1167,1169],{"id":1168},"creating-a-universal-deprecation-overlay","Creating a universal deprecation overlay",[11,1171,1172],{},"Throughout the lifecycle of an API we try to make sure the documentation doesn’t drift from its implementation.",[11,1174,1175],{},"As change is inevitable, we want to be able to deprecate APIs if we’re designing a new iteration of it. The process of deprecating an API is a prime example where I’d consistently need to change the API implementation and description in the same way.",[11,1177,1178],{},"I want to add deprecation headers to the API and I want to make sure these deprecation headers are described and implemented similarly.",[11,1180,1181],{},"Here’s an over-simplified implementation:",[230,1183,1184,1187,1190,1193],{},[124,1185,1186],{},"An endpoint (or API) gets the deprecated annotation (either within the interface code or directly in the API description)",[124,1188,1189],{},"Processes API description in pipeline",[124,1191,1192],{},"Apply the Deprecation Protocol to the responses of all deprecated endpoints that have deprecation flag",[124,1194,1195],{},"Publish the final API description to the developer portal",[11,1197,1198],{},[59,1199,1200],{},"First, we create the overlay in order to define the change we want to apply universally.",[243,1202,1204],{"className":1053,"code":1203,"language":1055,"meta":144,"style":144},"# protocol-deprecation.overlay.yaml\noverlay: 1.0.0\ninfo:\n  title: Deprecation Protocol\n  description: The deprecation protocol ensures all required information is added to the API description to ensure consistent deprecation throughout the APIs\n  version: 1.0.0\nextends: .\u002Fpetstore.openapi.yaml\nactions:\n  - target: $.components\n    update:\n      parameters:\n        HeaderDeprecation:\n          name: Deprecation\n          in: header\n          description: RFC xxxx - A deprecation header is metadata describing the date and time when the endpoint is considered deprecated.\n          schema:\n            type: string\n            format: timestamp\n            example: \"@1737722995\"\n        HeaderSunset:\n          name: Sunset\n          in: header\n          description: RFC 8594 - A Sunset header is metadata describing the date and time when the endpoint fully stops service.\n          schema:\n            type: string\n            example: Thu, 31 Dec 2026 23:59:59 CET\n        HeaderDeprecationLink:\n          name: Link\n          in: header\n          description: RFC 8288 - A Link header is a relation type that points to a related resource\n          schema:\n            type: string\n            example: '\u003Chttps:\u002F\u002Fdeveloper.acme.com\u002Fdeprecation>; rel=\"deprecation\"; type=\"text\u002Fhtml\"'\n  - target: $.paths.*[?(@.deprecated == true)].responses.*\n    update:\n      headers:\n        Deprecation:\n          $ref: \"#\u002Fcomponents\u002Fparameters\u002FHeaderDeprecation\"\n        Sunset:\n          $ref: \"#\u002Fcomponents\u002Fparameters\u002FHeaderSunset\"\n        Link:\n          $ref: \"#\u002Fcomponents\u002Fparameters\u002FHeaderDeprecationLink\"\n",[206,1205,1206,1211,1222,1229,1239,1249,1258,1268,1275,1287,1293,1300,1307,1317,1327,1337,1344,1354,1364,1374,1381,1390,1398,1407,1413,1421,1430,1437,1447,1456,1466,1473,1482,1492,1504,1511,1519,1527,1538,1546,1556,1564],{"__ignoreMap":144},[251,1207,1208],{"class":253,"line":254},[251,1209,1210],{"class":1062},"# protocol-deprecation.overlay.yaml\n",[251,1212,1213,1216,1218],{"class":253,"line":145},[251,1214,1215],{"class":1072},"overlay",[251,1217,1075],{"class":1068},[251,1219,1221],{"class":1220},"sFSAA","1.0.0\n",[251,1223,1224,1227],{"class":253,"line":265},[251,1225,1226],{"class":1072},"info",[251,1228,1097],{"class":1068},[251,1230,1231,1234,1236],{"class":253,"line":271},[251,1232,1233],{"class":1072},"  title",[251,1235,1075],{"class":1068},[251,1237,1238],{"class":1078},"Deprecation Protocol\n",[251,1240,1241,1244,1246],{"class":253,"line":277},[251,1242,1243],{"class":1072},"  description",[251,1245,1075],{"class":1068},[251,1247,1248],{"class":1078},"The deprecation protocol ensures all required information is added to the API description to ensure consistent deprecation throughout the APIs\n",[251,1250,1251,1254,1256],{"class":253,"line":283},[251,1252,1253],{"class":1072},"  version",[251,1255,1075],{"class":1068},[251,1257,1221],{"class":1220},[251,1259,1260,1263,1265],{"class":253,"line":289},[251,1261,1262],{"class":1072},"extends",[251,1264,1075],{"class":1068},[251,1266,1267],{"class":1078},".\u002Fpetstore.openapi.yaml\n",[251,1269,1270,1273],{"class":253,"line":295},[251,1271,1272],{"class":1072},"actions",[251,1274,1097],{"class":1068},[251,1276,1277,1280,1282,1284],{"class":253,"line":301},[251,1278,1279],{"class":1068},"  - ",[251,1281,1037],{"class":1072},[251,1283,1075],{"class":1068},[251,1285,1286],{"class":1078},"$.components\n",[251,1288,1289,1291],{"class":253,"line":307},[251,1290,1094],{"class":1072},[251,1292,1097],{"class":1068},[251,1294,1295,1298],{"class":253,"line":313},[251,1296,1297],{"class":1072},"      parameters",[251,1299,1097],{"class":1068},[251,1301,1302,1305],{"class":253,"line":319},[251,1303,1304],{"class":1072},"        HeaderDeprecation",[251,1306,1097],{"class":1068},[251,1308,1309,1312,1314],{"class":253,"line":325},[251,1310,1311],{"class":1072},"          name",[251,1313,1075],{"class":1068},[251,1315,1316],{"class":1078},"Deprecation\n",[251,1318,1319,1322,1324],{"class":253,"line":331},[251,1320,1321],{"class":1072},"          in",[251,1323,1075],{"class":1068},[251,1325,1326],{"class":1078},"header\n",[251,1328,1329,1332,1334],{"class":253,"line":337},[251,1330,1331],{"class":1072},"          description",[251,1333,1075],{"class":1068},[251,1335,1336],{"class":1078},"RFC xxxx - A deprecation header is metadata describing the date and time when the endpoint is considered deprecated.\n",[251,1338,1339,1342],{"class":253,"line":343},[251,1340,1341],{"class":1072},"          schema",[251,1343,1097],{"class":1068},[251,1345,1346,1349,1351],{"class":253,"line":349},[251,1347,1348],{"class":1072},"            type",[251,1350,1075],{"class":1068},[251,1352,1353],{"class":1078},"string\n",[251,1355,1356,1359,1361],{"class":253,"line":355},[251,1357,1358],{"class":1072},"            format",[251,1360,1075],{"class":1068},[251,1362,1363],{"class":1078},"timestamp\n",[251,1365,1366,1369,1371],{"class":253,"line":361},[251,1367,1368],{"class":1072},"            example",[251,1370,1075],{"class":1068},[251,1372,1373],{"class":1078},"\"@1737722995\"\n",[251,1375,1376,1379],{"class":253,"line":367},[251,1377,1378],{"class":1072},"        HeaderSunset",[251,1380,1097],{"class":1068},[251,1382,1383,1385,1387],{"class":253,"line":373},[251,1384,1311],{"class":1072},[251,1386,1075],{"class":1068},[251,1388,1389],{"class":1078},"Sunset\n",[251,1391,1392,1394,1396],{"class":253,"line":379},[251,1393,1321],{"class":1072},[251,1395,1075],{"class":1068},[251,1397,1326],{"class":1078},[251,1399,1400,1402,1404],{"class":253,"line":384},[251,1401,1331],{"class":1072},[251,1403,1075],{"class":1068},[251,1405,1406],{"class":1078},"RFC 8594 - A Sunset header is metadata describing the date and time when the endpoint fully stops service.\n",[251,1408,1409,1411],{"class":253,"line":390},[251,1410,1341],{"class":1072},[251,1412,1097],{"class":1068},[251,1414,1415,1417,1419],{"class":253,"line":396},[251,1416,1348],{"class":1072},[251,1418,1075],{"class":1068},[251,1420,1353],{"class":1078},[251,1422,1423,1425,1427],{"class":253,"line":401},[251,1424,1368],{"class":1072},[251,1426,1075],{"class":1068},[251,1428,1429],{"class":1078},"Thu, 31 Dec 2026 23:59:59 CET\n",[251,1431,1432,1435],{"class":253,"line":407},[251,1433,1434],{"class":1072},"        HeaderDeprecationLink",[251,1436,1097],{"class":1068},[251,1438,1440,1442,1444],{"class":253,"line":1439},28,[251,1441,1311],{"class":1072},[251,1443,1075],{"class":1068},[251,1445,1446],{"class":1078},"Link\n",[251,1448,1450,1452,1454],{"class":253,"line":1449},29,[251,1451,1321],{"class":1072},[251,1453,1075],{"class":1068},[251,1455,1326],{"class":1078},[251,1457,1459,1461,1463],{"class":253,"line":1458},30,[251,1460,1331],{"class":1072},[251,1462,1075],{"class":1068},[251,1464,1465],{"class":1078},"RFC 8288 - A Link header is a relation type that points to a related resource\n",[251,1467,1469,1471],{"class":253,"line":1468},31,[251,1470,1341],{"class":1072},[251,1472,1097],{"class":1068},[251,1474,1476,1478,1480],{"class":253,"line":1475},32,[251,1477,1348],{"class":1072},[251,1479,1075],{"class":1068},[251,1481,1353],{"class":1078},[251,1483,1485,1487,1489],{"class":253,"line":1484},33,[251,1486,1368],{"class":1072},[251,1488,1075],{"class":1068},[251,1490,1491],{"class":1078},"'\u003Chttps:\u002F\u002Fdeveloper.acme.com\u002Fdeprecation>; rel=\"deprecation\"; type=\"text\u002Fhtml\"'\n",[251,1493,1495,1497,1499,1501],{"class":253,"line":1494},34,[251,1496,1279],{"class":1068},[251,1498,1037],{"class":1072},[251,1500,1075],{"class":1068},[251,1502,1503],{"class":1078},"$.paths.*[?(@.deprecated == true)].responses.*\n",[251,1505,1507,1509],{"class":253,"line":1506},35,[251,1508,1094],{"class":1072},[251,1510,1097],{"class":1068},[251,1512,1514,1517],{"class":253,"line":1513},36,[251,1515,1516],{"class":1072},"      headers",[251,1518,1097],{"class":1068},[251,1520,1522,1525],{"class":253,"line":1521},37,[251,1523,1524],{"class":1072},"        Deprecation",[251,1526,1097],{"class":1068},[251,1528,1530,1533,1535],{"class":253,"line":1529},38,[251,1531,1532],{"class":1072},"          $ref",[251,1534,1075],{"class":1068},[251,1536,1537],{"class":1078},"\"#\u002Fcomponents\u002Fparameters\u002FHeaderDeprecation\"\n",[251,1539,1541,1544],{"class":253,"line":1540},39,[251,1542,1543],{"class":1072},"        Sunset",[251,1545,1097],{"class":1068},[251,1547,1549,1551,1553],{"class":253,"line":1548},40,[251,1550,1532],{"class":1072},[251,1552,1075],{"class":1068},[251,1554,1555],{"class":1078},"\"#\u002Fcomponents\u002Fparameters\u002FHeaderSunset\"\n",[251,1557,1559,1562],{"class":253,"line":1558},41,[251,1560,1561],{"class":1072},"        Link",[251,1563,1097],{"class":1068},[251,1565,1567,1569,1571],{"class":253,"line":1566},42,[251,1568,1532],{"class":1072},[251,1570,1075],{"class":1068},[251,1572,1573],{"class":1078},"\"#\u002Fcomponents\u002Fparameters\u002FHeaderDeprecationLink\"\n",[11,1575,1576],{},"Within the overlay I’ve decided to implement some HTTP headers that relate to deprecation in a generic way. In theory this will allow for the implementation of this overlay on virtually any API description that implements the deprecation flag but lacks any of these headers.",[11,1578,1579],{},[59,1580,1581],{},"Second, we add the deprecation flag to the endpoint within our API description.",[11,1583,1584],{},[1585,1586],"img",{"alt":1587,"src":1588},"OpenAPI Specification with deprecation flags","\u002Farticles\u002Fcapture-api-changes-with-overlay\u002Fopenapi-with-deprecation.jpg",[11,1590,1591],{},[59,1592,1593],{},"Third, we apply the overlay to the specification using a CLI tool.",[11,1595,1596],{},[14,1597,1598,1601],{},[59,1599,1600],{},"Important",": currently there’s a limited amount of tools that offer support for Overlay. I’ve randomly picked bump-cli (by Bump.sh) as it is listed as one of the supporting tools within the maintenance repository for Overlay.",[243,1603,1607],{"className":1604,"code":1605,"language":1606,"meta":144,"style":144},"language-bash shiki shiki-themes github-dark-default","# overlay command for bump-cli with arguments\n$ bump overlay spec.openapi.yaml spec.overlay.yaml > final.openapi.yaml\n","bash",[206,1608,1609,1614],{"__ignoreMap":144},[251,1610,1611],{"class":253,"line":254},[251,1612,1613],{"class":1062},"# overlay command for bump-cli with arguments\n",[251,1615,1616,1620,1623,1626,1629,1632,1636],{"class":253,"line":145},[251,1617,1619],{"class":1618},"sQhOw","$",[251,1621,1622],{"class":1078}," bump",[251,1624,1625],{"class":1078}," overlay",[251,1627,1628],{"class":1078}," spec.openapi.yaml",[251,1630,1631],{"class":1078}," spec.overlay.yaml",[251,1633,1635],{"class":1634},"suJrU"," >",[251,1637,1638],{"class":1078}," final.openapi.yaml\n",[11,1640,1641],{},[1585,1642],{"alt":1643,"src":1644},"Resulting OpenAPI Specification","\u002Farticles\u002Fcapture-api-changes-with-overlay\u002Fresulting-openapi-spec.jpg",[11,1646,1647],{},"Finally, we end up with a rendered specification that clearly describes the headers that will be returned from the deprecated endpoint.",[11,1649,1650],{},[1585,1651],{"alt":1652,"src":1653},"Rendered OpenAPI Specification","\u002Farticles\u002Fcapture-api-changes-with-overlay\u002Frendered-openapi-spec.jpg",[11,1655,1656],{},"Conclusion? Pretty neat! 🎉",[24,1658,1660],{"id":1659},"limitations","Limitations",[11,1662,1663],{},"But there are some limitations I’ve run into when creating this implementation;",[230,1665,1666,1672,1678],{},[124,1667,1668,1671],{},[59,1669,1670],{},"Overlay is not aware of the OpenAPI Schema."," As you describe changes in the Overlay you won’t get feedback if the structure will be valid within the target",[124,1673,1674,1677],{},[59,1675,1676],{},"JSON Path implementation."," Overlay has support for expressions according to RFC 9535. Not all operators from other implementations can be used (e.g. find all properties with “x-” in their key)",[124,1679,1680,1683],{},[59,1681,1682],{},"Tooling support."," Overlay is purely a specification and depends on third-party development for support. This allows for differences in how the specification will be supported eventually — like with OpenAPI.",[11,1685,1686],{},"I was going back and forth a lot to see how my overlay impacted the API description. Even though I have experience with the OpenAPI Specification, I still had to reference its documentation more often than not to remember the exact structure of the Parameter Object. As well as the exact level at which to target the overlay to achieve the desired result.",[24,1688,1690],{"id":1689},"take-aways","Take-aways",[11,1692,1693],{},"I would summarise overlay like this: “A specification to capture universal and consistent changes for API descriptions”.",[533,1695,1696],{},[11,1697,1698],{},"In theory I really like the idea behind the overlay specification and I look forward to try and adopt this specification in actual projects.",[11,1700,1701],{},"But I don’t think we’re out of the woods yet…",[11,1703,1704],{},"In an ideal and fully structured environment I see its positives:",[121,1706,1707,1713,1719],{},[124,1708,126,1709,1712],{},[59,1710,1711],{},"powerful governance"," tool for integration teams",[124,1714,685,1715,1718],{},[59,1716,1717],{},"artefact"," in automated\u002Fautonomous API description generation regardless of chosen format",[124,1720,1721,1722,1725],{},"A key component to ",[59,1723,1724],{},"limiting API drift"," from happening",[11,1727,1728],{},"Though, in the trenches of reality I fear for:",[121,1730,1731,1737,1743],{},[124,1732,1733,1736],{},[59,1734,1735],{},"Slight differences"," in implementation that require manual overhead to fix",[124,1738,1739,1742],{},[59,1740,1741],{},"Inconsistent support"," and implementation by vendors",[124,1744,1745,1746,1749],{},"“How do I get my ",[59,1747,1748],{},"JSON Path expression"," to work?” questions from developers",[11,1751,1752],{},"As with most specifications I foresee that Overlay will require governance and guidelines to ensure its implementation benefits the organisation.",[11,1754,1755],{},"I look forward to the changes to come!",[11,1757,1758],{},"Want to read more on Overlay other relevant topics I’ve used? Here’s some additional reading material:",[121,1760,1761,1768,1775],{},[124,1762,1763],{},[51,1764,1767],{"href":1765,"rel":1766},"https:\u002F\u002Fgithub.com\u002FOAI\u002FOverlay-Specification",[473],"Overlay Specification Public Repository",[124,1769,1770],{},[51,1771,1774],{"href":1772,"rel":1773},"https:\u002F\u002Fdatatracker.ietf.org\u002Fdoc\u002Fdraft-ietf-httpapi-deprecation-header\u002F09\u002F",[473],"HTTP Deprecation Header RFC",[124,1776,1777,1782,1783],{},[51,1778,1781],{"href":1779,"rel":1780},"https:\u002F\u002Flornajane.net\u002Fposts\u002F2023\u002Foverlay-improvements-to-openapi",[473],"Lorna Jane on Overlay early ’23"," and ",[51,1784,1787],{"href":1785,"rel":1786},"https:\u002F\u002Flornajane.net\u002Fposts\u002F2024\u002Fopenapi-overlays-to-avoid-api-oversharing",[473],"on handling Deprecation",[490,1789,1790],{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}",{"title":144,"searchDepth":145,"depth":145,"links":1792},[1793,1794,1795,1796,1797],{"id":1001,"depth":145,"text":1002},{"id":1019,"depth":145,"text":1020},{"id":1168,"depth":145,"text":1169},{"id":1659,"depth":145,"text":1660},{"id":1689,"depth":145,"text":1690},"2025-01-27","A practical example of using Overlay Specification to automate your API governance. All with the goal of ensuring consistently applying predicatable changes to API descriptions.","\u002Farticles\u002Fcapture-api-changes-with-overlay\u002Fcover.png",{},"\u002Farticles\u002Fcapture-api-changes-with-overlay",{"title":957,"description":1799},"capture-api-changes-with-overlay","articles\u002Fcapture-api-changes-with-overlay",[1215,1807,167,166],"openapi","EAWO5F3LhDsmN8MVS8PgZmj2ZqKqbJ6nCrQZA2wM9RI",{"id":1810,"title":1811,"body":1812,"date":2462,"description":2463,"extension":154,"image":2464,"imageAuthor":156,"imageLicense":156,"imageSource":156,"meta":2465,"navigation":160,"path":53,"published":160,"seo":2466,"slug":2467,"stem":2468,"tags":2469,"__hash__":2471},"articles\u002Farticles\u002Fautomate-api-governance.md","Automate Your API Governance In 15 Minutes",{"type":8,"value":1813,"toc":2455},[1814,1823,1828,1831,1835,1838,1841,1854,1858,1874,1877,1880,1883,1887,1890,1893,1896,1913,1916,1919,1930,1933,1936,1945,1948,1957,1961,1966,1971,1974,1977,1996,2002,2007,2014,2021,2027,2034,2172,2179,2189,2195,2198,2201,2204,2228,2233,2239,2242,2245,2406,2409,2412,2418,2421,2424,2427,2429,2432,2435,2438,2441,2444,2447,2452],[11,1815,1816,1817,1822],{},"There’s a quote from Arnaud Lauret — author of The Design of Web APIs — during his ",[51,1818,1821],{"href":1819,"rel":1820},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=EMLCNqx80W4&t=1s&pp=ygUSbm9yZGljIGFwaXMgYXJuYXVk",[473],"talk on API Governance at Nordic APIs"," that has stuck with me for a while now:",[533,1824,1825],{},[11,1826,1827],{},"“Ideally governance enables developers to be as autonomous as possible and as expert as needed.”",[11,1829,1830],{},"In this article I demonstrate one of the many ways you can improve consistency in applying governance policies by writing a rule to apply on your API description in order to make developers more autonomous.",[24,1832,1834],{"id":1833},"api-governance-execution-is-hard","API Governance Execution Is Hard",[11,1836,1837],{},"Many organisations use governance to enforce rules onto their developers. Resulting in a plethora of authorities, review committees and additional processes to ensure policies are developed, maintained and applied.",[11,1839,1840],{},"Many meetings are held, and decisions tend to be made, documented and then partially or fully forgotten by the time teams come around to implement them.",[11,1842,1843,1844,1849,1850,1853],{},"According to ",[51,1845,1848],{"href":1846,"rel":1847},"https:\u002F\u002Fwww.postman.com\u002Fstate-of-api\u002F2024\u002F#:~:text=74%25%20of%20respondents%20are%20API,up%20from%2066%25%20in%202023.&text=APIs%20are%20no%20longer%20an,and%20boosting%20efficiency%20across%20teams.",[473],"the Postman State of API 2024 report","; ",[14,1851,1852],{},"58% of developers rely on internal documentation, but 39% say inconsistent docs are the biggest roadblock."," Which in part will be attributed to documents that have been created as a way capture agreements and rules on API development.",[24,1855,1857],{"id":1856},"beware-a-dangerously-large-number-of-apis-ahead","Beware! A Dangerously Large Number of APIs Ahead",[11,1859,1860,1861,1868,1869],{},"Whilst API governance remains an area of improvement for many, the number of APIs is on the same steady rise they’ve been on for the last years. Organisations are ",[14,1862,1863,1864,1867],{},"“juggling an average of 421 APIs ",[251,1865,1866],{},"…"," expected to grow by at least 10% in the next two years alone”"," according to ",[51,1870,1873],{"href":1871,"rel":1872},"https:\u002F\u002Fwww.f5.com\u002Fresources\u002Freports\u002Fstate-of-application-strategy-report",[473],"F5’s State of Application Strategy report.",[11,1875,1876],{},"As APIs can offer tremendous value to an organisation. This means that you’ll be looking for ways to maximize this API-enable value whilst eliminating any risks on a sprawl of technical debt and inconsistent implementations.",[11,1878,1879],{},"The mandate from management — sometimes hardly obtained — to do “something with API strategy and governance” give you the green light to change something. But actually “doing the something” is the hardest part.",[11,1881,1882],{},"Let’s look at different types of decisions, how they tie into governance and what we can do with some example policies.",[24,1884,1886],{"id":1885},"design-decisions-vs-implementation-decisions","Design Decisions vs. Implementation Decisions",[11,1888,1889],{},"Chances are likely you are dealing with more than one developer. We know for a fact that not every policy will be considered evenly important by everyone.",[11,1891,1892],{},"Therefore, you want to automate policies that are easily supported through existing tooling.",[11,1894,1895],{},"Example of decisions you do want to automate:",[121,1897,1898,1901,1904,1907,1910],{},[124,1899,1900],{},"How do I formulate a description?",[124,1902,1903],{},"What casing do we use throughout the organisation?",[124,1905,1906],{},"What responses do I add to an API description?",[124,1908,1909],{},"How do I structure an API description?",[124,1911,1912],{},"What features should I use from a specification standard?",[11,1914,1915],{},"You want to automate these decisions to keep developers going in a steady pace without having to resort to using random placeholder values, skip on easily addable information or be forced to contact an integration\u002FAPI team.",[11,1917,1918],{},"Example of decisions you don’t want to automate:",[121,1920,1921,1924,1927],{},[124,1922,1923],{},"What operations do I support with my API?",[124,1925,1926],{},"What parameters do I support with my API?",[124,1928,1929],{},"What endpoints do I expose?",[11,1931,1932],{},"Decisions are clearly distinguished into design-related and implementation-related. Both types of decisions need to be made to develop successful APIs though the implementation-related decisions are easier and safer to automate.",[11,1934,1935],{},"Validating an implementation according to a standard or a specification is a rather binary decision to make:",[11,1937,1938],{},[14,1939,1940,1941,1944],{},"Naming must be in CamelCase: ",[206,1942,1943],{},"home-address"," is not in CamelCase.",[11,1946,1947],{},"Whilst validating a design is a combination of concepts and evaluations that rather appear on a spectrum.",[11,1949,1950],{},[14,1951,1952,1953,1956],{},"API must be secured: ",[206,1954,1955],{},"OAuth implemented",". This only contributes partly to a secure API design.",[24,1958,1960],{"id":1959},"lets-setup-some-automated-rules","Let’s Setup Some Automated Rules",[11,1962,1963],{},[14,1964,1965],{},"Note: Throughout this example we’ll be using the Pet Store 3.1.0 specification example.",[11,1967,1968],{},[14,1969,1970],{},"Usually, I’m not too keen on using this example since it’s hardly representative of API descriptions you’ll encounter in real-life projects. Since we’re looking at implementing tooling to an API description and not the description itself, we’re fine using this.",[11,1972,1973],{},"We’ll be using npm and Spectral to create two custom rules we’ll apply to the Pet Store specification.",[11,1975,1976],{},"Assuming you haven’t worked with Spectral before we’ll start with a global install so we can use the CLI on our local machine.",[243,1978,1980],{"className":1604,"code":1979,"language":1606,"meta":144,"style":144},"npm i -g @stoplight\u002Fspectral-cli\n",[206,1981,1982],{"__ignoreMap":144},[251,1983,1984,1987,1990,1993],{"class":253,"line":254},[251,1985,1986],{"class":1618},"npm",[251,1988,1989],{"class":1078}," i",[251,1991,1992],{"class":1220}," -g",[251,1994,1995],{"class":1078}," @stoplight\u002Fspectral-cli\n",[11,1997,1998],{},[1585,1999],{"alt":2000,"src":2001},"Installing Spectral CLI globally","\u002Farticles\u002Fautomate-api-governance\u002Fspectral-1.jpg",[11,2003,2004],{},[14,2005,2006],{},"Reference spectral documentation for CICD integration or other setups.",[11,2008,2009,2010,2013],{},"After installing we can start writing a custom rule. In our working directory we only have our ",[59,2011,2012],{},"petstore.openapi.yml"," API specification.",[11,2015,2016,2017,2020],{},"Running the ",[206,2018,2019],{},"spectral lint"," command will clarify we need to provide a ruleset to apply.",[11,2022,2023],{},[1585,2024],{"alt":2025,"src":2026},"Running the lint command","\u002Farticles\u002Fautomate-api-governance\u002Fspectral-2.jpg",[11,2028,2029,2030,2033],{},"Let’s create a custom ruleset called ",[59,2031,2032],{},"object-policies.spectral.json"," in which we’ll define our custom rule.",[243,2035,2039],{"className":2036,"code":2037,"language":2038,"meta":144,"style":144},"language-json shiki shiki-themes github-dark-default","{\n  \"description\": \"Object policies\",\n  \"rules\": {\n    \"object-policies:required-description\": {\n      \"description\": \"Object must have a description\",\n      \"message\": \"Object must have a description\",\n      \"given\": [\"$..schemas[*]\"],\n      \"severity\": \"error\",\n      \"then\": {\n        \"field\": \"description\",\n        \"function\": \"truthy\"\n      }\n    }\n  }\n}\n","json",[206,2040,2041,2046,2059,2067,2074,2086,2097,2111,2123,2130,2142,2152,2157,2162,2167],{"__ignoreMap":144},[251,2042,2043],{"class":253,"line":254},[251,2044,2045],{"class":1068},"{\n",[251,2047,2048,2051,2053,2056],{"class":253,"line":145},[251,2049,2050],{"class":1072},"  \"description\"",[251,2052,1075],{"class":1068},[251,2054,2055],{"class":1078},"\"Object policies\"",[251,2057,2058],{"class":1068},",\n",[251,2060,2061,2064],{"class":253,"line":265},[251,2062,2063],{"class":1072},"  \"rules\"",[251,2065,2066],{"class":1068},": {\n",[251,2068,2069,2072],{"class":253,"line":271},[251,2070,2071],{"class":1072},"    \"object-policies:required-description\"",[251,2073,2066],{"class":1068},[251,2075,2076,2079,2081,2084],{"class":253,"line":277},[251,2077,2078],{"class":1072},"      \"description\"",[251,2080,1075],{"class":1068},[251,2082,2083],{"class":1078},"\"Object must have a description\"",[251,2085,2058],{"class":1068},[251,2087,2088,2091,2093,2095],{"class":253,"line":283},[251,2089,2090],{"class":1072},"      \"message\"",[251,2092,1075],{"class":1068},[251,2094,2083],{"class":1078},[251,2096,2058],{"class":1068},[251,2098,2099,2102,2105,2108],{"class":253,"line":289},[251,2100,2101],{"class":1072},"      \"given\"",[251,2103,2104],{"class":1068},": [",[251,2106,2107],{"class":1078},"\"$..schemas[*]\"",[251,2109,2110],{"class":1068},"],\n",[251,2112,2113,2116,2118,2121],{"class":253,"line":295},[251,2114,2115],{"class":1072},"      \"severity\"",[251,2117,1075],{"class":1068},[251,2119,2120],{"class":1078},"\"error\"",[251,2122,2058],{"class":1068},[251,2124,2125,2128],{"class":253,"line":301},[251,2126,2127],{"class":1072},"      \"then\"",[251,2129,2066],{"class":1068},[251,2131,2132,2135,2137,2140],{"class":253,"line":307},[251,2133,2134],{"class":1072},"        \"field\"",[251,2136,1075],{"class":1068},[251,2138,2139],{"class":1078},"\"description\"",[251,2141,2058],{"class":1068},[251,2143,2144,2147,2149],{"class":253,"line":313},[251,2145,2146],{"class":1072},"        \"function\"",[251,2148,1075],{"class":1068},[251,2150,2151],{"class":1078},"\"truthy\"\n",[251,2153,2154],{"class":253,"line":319},[251,2155,2156],{"class":1068},"      }\n",[251,2158,2159],{"class":253,"line":325},[251,2160,2161],{"class":1068},"    }\n",[251,2163,2164],{"class":253,"line":331},[251,2165,2166],{"class":1068},"  }\n",[251,2168,2169],{"class":253,"line":337},[251,2170,2171],{"class":1068},"}\n",[11,2173,2174,2175,2178],{},"The goal of this rule is to enforce developers to include a ",[206,2176,2177],{},"description"," property for all schemas they define.",[11,2180,2181,2184,2185,2188],{},[59,2182,2183],{},"Important!"," Take into consideration the intent of the policy within the development process. ",[59,2186,2187],{},"Why"," should a developer be enforced to add a property as this is a seemingly added technical constraint.",[11,2190,2191,2194],{},[59,2192,2193],{},"Our rationale here is to enforce a description to be present because we want to make sure a functional description is added."," Because we want to ensure our API descriptions will be easily understood by external developers.",[11,2196,2197],{},"Part of writing the rule is to determine the severity. This can strongly impact the development process depending on how and where the linting is done.",[11,2199,2200],{},"Decide together with all related teams what is important enough to halt the pipeline and what should be considered a warning or hint.",[11,2202,2203],{},"To apply the rule, we’ve written to the specification we execute",[243,2205,2207],{"className":1604,"code":2206,"language":1606,"meta":144,"style":144},"$ spectral lint petstore.openapi.yml --ruleset object-policies.spectral.json\n",[206,2208,2209],{"__ignoreMap":144},[251,2210,2211,2213,2216,2219,2222,2225],{"class":253,"line":254},[251,2212,1619],{"class":1618},[251,2214,2215],{"class":1078}," spectral",[251,2217,2218],{"class":1078}," lint",[251,2220,2221],{"class":1078}," petstore.openapi.yml",[251,2223,2224],{"class":1220}," --ruleset",[251,2226,2227],{"class":1078}," object-policies.spectral.json\n",[11,2229,2230],{},[14,2231,2232],{},"For this example, I’ve decided to create a dedicated file to contain all policies related to object validation. When you simply create a file called “.spectral.json”, Spectral will automatically apply these rule without the explicit “ — ruleset” flag.",[11,2234,2235],{},[1585,2236],{"alt":2237,"src":2238},"Running the lint command with ruleset","\u002Farticles\u002Fautomate-api-governance\u002Fspectral-3.jpg",[11,2240,2241],{},"Let’s add an additional rule. Our goal is to improve the readability of the API description with the emphasis of having a clear description for Schema Components.",[11,2243,2244],{},"Now we validate if the description property is present, we’ll check if our agreed upon template is used to formulate the functional description.",[243,2246,2248],{"className":2036,"code":2247,"language":2038,"meta":144,"style":144},"{\n  \"description\": \"Object policies\",\n  \"rules\": {\n    \"object-policies:preferred-description-template\": {\n      \"description\": \"Object description must implement template\",\n      \"message\": \"Should contain 'A ... is a ... that ...' template\",\n      \"given\": [\"$..schemas[*].description\"],\n      \"severity\": \"warn\",\n      \"then\": {\n        \"function\": \"pattern\",\n        \"functionOptions\": {\n          \"match\": \"(A|An)\\\\s.+\\\\sis\\\\sa\\\\s.+\\\\sthat\\\\s.+\"\n        }\n      }\n    }\n  }\n}\n",[206,2249,2250,2254,2264,2270,2277,2288,2299,2310,2321,2327,2338,2345,2385,2390,2394,2398,2402],{"__ignoreMap":144},[251,2251,2252],{"class":253,"line":254},[251,2253,2045],{"class":1068},[251,2255,2256,2258,2260,2262],{"class":253,"line":145},[251,2257,2050],{"class":1072},[251,2259,1075],{"class":1068},[251,2261,2055],{"class":1078},[251,2263,2058],{"class":1068},[251,2265,2266,2268],{"class":253,"line":265},[251,2267,2063],{"class":1072},[251,2269,2066],{"class":1068},[251,2271,2272,2275],{"class":253,"line":271},[251,2273,2274],{"class":1072},"    \"object-policies:preferred-description-template\"",[251,2276,2066],{"class":1068},[251,2278,2279,2281,2283,2286],{"class":253,"line":277},[251,2280,2078],{"class":1072},[251,2282,1075],{"class":1068},[251,2284,2285],{"class":1078},"\"Object description must implement template\"",[251,2287,2058],{"class":1068},[251,2289,2290,2292,2294,2297],{"class":253,"line":283},[251,2291,2090],{"class":1072},[251,2293,1075],{"class":1068},[251,2295,2296],{"class":1078},"\"Should contain 'A ... is a ... that ...' template\"",[251,2298,2058],{"class":1068},[251,2300,2301,2303,2305,2308],{"class":253,"line":289},[251,2302,2101],{"class":1072},[251,2304,2104],{"class":1068},[251,2306,2307],{"class":1078},"\"$..schemas[*].description\"",[251,2309,2110],{"class":1068},[251,2311,2312,2314,2316,2319],{"class":253,"line":295},[251,2313,2115],{"class":1072},[251,2315,1075],{"class":1068},[251,2317,2318],{"class":1078},"\"warn\"",[251,2320,2058],{"class":1068},[251,2322,2323,2325],{"class":253,"line":301},[251,2324,2127],{"class":1072},[251,2326,2066],{"class":1068},[251,2328,2329,2331,2333,2336],{"class":253,"line":307},[251,2330,2146],{"class":1072},[251,2332,1075],{"class":1068},[251,2334,2335],{"class":1078},"\"pattern\"",[251,2337,2058],{"class":1068},[251,2339,2340,2343],{"class":253,"line":313},[251,2341,2342],{"class":1072},"        \"functionOptions\"",[251,2344,2066],{"class":1068},[251,2346,2347,2350,2352,2355,2358,2361,2363,2366,2368,2371,2373,2375,2377,2380,2382],{"class":253,"line":319},[251,2348,2349],{"class":1072},"          \"match\"",[251,2351,1075],{"class":1068},[251,2353,2354],{"class":1078},"\"(A|An)",[251,2356,2357],{"class":1634},"\\\\",[251,2359,2360],{"class":1078},"s.+",[251,2362,2357],{"class":1634},[251,2364,2365],{"class":1078},"sis",[251,2367,2357],{"class":1634},[251,2369,2370],{"class":1078},"sa",[251,2372,2357],{"class":1634},[251,2374,2360],{"class":1078},[251,2376,2357],{"class":1634},[251,2378,2379],{"class":1078},"sthat",[251,2381,2357],{"class":1634},[251,2383,2384],{"class":1078},"s.+\"\n",[251,2386,2387],{"class":253,"line":325},[251,2388,2389],{"class":1068},"        }\n",[251,2391,2392],{"class":253,"line":331},[251,2393,2156],{"class":1068},[251,2395,2396],{"class":253,"line":337},[251,2397,2161],{"class":1068},[251,2399,2400],{"class":253,"line":343},[251,2401,2166],{"class":1068},[251,2403,2404],{"class":253,"line":349},[251,2405,2171],{"class":1068},[11,2407,2408],{},"We use a built-in function to apply a Regex to the content of the description property of each available Schema.",[11,2410,2411],{},"The intention of this validation rule is to give warnings to developers that their Schema description is lacking a functional description template that recommend to use to achieve consistent definitions that are more likely to be understood by external developers.",[11,2413,2414],{},[1585,2415],{"alt":2416,"src":2417},"Running lint command with output","\u002Farticles\u002Fautomate-api-governance\u002Fspectral-4.jpg",[11,2419,2420],{},"If we run the linter again, we’ll see the new finding listed as a warning within the result.",[11,2422,2423],{},"That’s it!",[11,2425,2426],{},"There are many tools to choose from, each with their own quirks, positives and negatives. As well as a million different rules you could import, write and implement.",[24,2428,116],{"id":115},[11,2430,2431],{},"Governance is hard.",[11,2433,2434],{},"Finding the balance between enforcing, reviewing, coaching and guiding will be different for each team, department or organisation. Unfortunately, there’s no single approach that works everywhere.",[11,2436,2437],{},"Though every time we’ve found it worthwhile to involve those involved and come to a collaborative approach for solving a part of the governance puzzle.",[11,2439,2440],{},"Start with a pilot that applies the most important — and easily implemented — policy the teams agree on and go from there.",[11,2442,2443],{},"Eventually, especially within larger organisations you’ll eventually be setting up a center of enablement or expert team on this topic. With the sole purpose to facilitate others in maximizing API-enable value. They shouldn’t become a regulatory bottleneck instead; they focus on alleviating impediments and constraints for other.",[11,2445,2446],{},"Engineers should be as autonomous as possible and as expert as needed.",[11,2448,2449],{},[14,2450,2451],{},"For more on Spectral and its capabilities and limitations reference their documentation. It’s worth noting that there are other viable options: API-fiddle, Vacuum, Optic amongst others. Don’t fret too much on WHAT tool to use, focus on IF and WHY such a tool might be needed.",[490,2453,2454],{},"html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}",{"title":144,"searchDepth":145,"depth":145,"links":2456},[2457,2458,2459,2460,2461],{"id":1833,"depth":145,"text":1834},{"id":1856,"depth":145,"text":1857},{"id":1885,"depth":145,"text":1886},{"id":1959,"depth":145,"text":1960},{"id":115,"depth":145,"text":116},"2025-01-02","A practical example of using linting tooling to automate your API governance. Free developers from having to remember each individual convention and design rule by automating the process.","\u002Farticles\u002Fautomate-api-governance\u002Fcover.png",{},{"title":1811,"description":2463},"automate-api-governance","articles\u002Fautomate-api-governance",[166,2470],"linting","zY9ofpRDhNA1eqAaEo5IgRnC0gQU7xyXqxhZsPLh2uY",{"id":2473,"title":2474,"body":2475,"date":4897,"description":4898,"extension":154,"image":4899,"imageAuthor":156,"imageLicense":156,"imageSource":156,"meta":4900,"navigation":160,"path":4901,"published":160,"seo":4902,"slug":4903,"stem":4904,"tags":4905,"__hash__":4906},"articles\u002Farticles\u002Feverything-about-openapi-4.md","Everything you need to know about OpenAPI version 4",{"type":8,"value":2476,"toc":4880},[2477,2480,2483,2486,2491,2495,2498,2501,2505,2508,2513,2516,2519,2522,2525,2531,2534,2612,2615,2619,2624,2631,2634,2637,3027,3030,3342,3345,3349,3354,3357,3360,3366,3369,3373,3378,3385,3388,3391,3545,3549,3554,3557,3560,3563,3569,3573,3576,3580,3583,3586,3589,3593,3596,3599,3602,3605,3700,3703,3887,3890,4435,4442,4767,4770,4773,4777,4780,4783,4786,4792,4796,4799,4806,4812,4815,4818,4830,4833,4838,4843,4846,4848,4877],[11,2478,2479],{},"OpenAPI version 4 — named ‘Moonwalk’ — is scheduled to for release by the end of 2024. Are there plans related to #LLMs? Is there a complete overhaul? What will become of our beloved #OpenAPISpecification?",[11,2481,2482],{},"Since everything is available to the public, I dove in to take a look at the general outline of this new version.",[11,2484,2485],{},"Here’s everything you need to know about the future of version 4 so far…",[533,2487,2488],{},[11,2489,2490],{},"This post regards a specification in active development. Topics covered, their implementation and examples are subject to change.",[24,2492,2494],{"id":2493},"the-efforts-of-the-openapi-initiative","The efforts of the OpenAPI Initiative",[11,2496,2497],{},"The OpenAPI Initiative (OAI) has a Special Interest Group (SIG) that is shaping the latest version of the OpenAPI Specification. At the moment of writing there is no official specification available yet.",[11,2499,2500],{},"But the guiding principles of Moonwalk are clearly outlined with a couple of examples spread throughout the repository. There’s also a feature branch we can take a quick look at to get an idea of what’s coming 👀",[24,2502,2504],{"id":2503},"overhauling-openapi","Overhauling OpenAPI",[11,2506,2507],{},"These guiding principles of Moonwalk are outlined during an announcement post at the end of 2023. Let’s take a look at the five guiding principles that will determine the way Moonwalk turns out and apply from them what we can.",[2509,2510,2512],"h3",{"id":2511},"semantics","Semantics",[11,2514,2515],{},"“Semantics provide purpose, whether the consumer is a human or an AI.”",[11,2517,2518],{},"This is a big one.",[11,2520,2521],{},"Not only because it describes a fundamental change to the specification but it also strengthens my point about the OAI’s positioning towards generative AI and specifically Large Language Models (LLMs) — as discussed in my article about Arazzo",[11,2523,2524],{},"OAI understands the importance of the traction that AI has within the space and has decided to act on it by incorporating a design constraint for it within the new major version of OpenAPI.",[11,2526,2527],{},[1585,2528],{"alt":2529,"src":2530},"General structure outline of OpenAPI Specification version 4","\u002Farticles\u002Feverything-about-openapi-4\u002Fopenapi-4-structure-outline.jpg",[11,2532,2533],{},"Besides this new structure, this version will allow for name spacing to create a OpenAPI Description (OAD) that adds the aforementioned purposeful semantics.",[243,2535,2537],{"className":1053,"code":2536,"language":1055,"meta":144,"style":144},"# SUBJECT TO CHANGE\nopenapi: 4.0.0\nself: https:\u002F\u002Fexample.com\u002Fpetstore\nimports:\n  - namespace: inventory\n    href: https:\u002F\u002Fexample.com\u002Fdomains\u002Finventory-objects.yml\n  - namespace: sales\n    href: https:\u002F\u002Fexample.com\u002Fdomains\u002Fsales-objects.yml\n",[206,2538,2539,2544,2553,2563,2570,2582,2592,2603],{"__ignoreMap":144},[251,2540,2541],{"class":253,"line":254},[251,2542,2543],{"class":1062},"# SUBJECT TO CHANGE\n",[251,2545,2546,2548,2550],{"class":253,"line":145},[251,2547,1807],{"class":1072},[251,2549,1075],{"class":1068},[251,2551,2552],{"class":1220},"4.0.0\n",[251,2554,2555,2558,2560],{"class":253,"line":265},[251,2556,2557],{"class":1072},"self",[251,2559,1075],{"class":1068},[251,2561,2562],{"class":1078},"https:\u002F\u002Fexample.com\u002Fpetstore\n",[251,2564,2565,2568],{"class":253,"line":271},[251,2566,2567],{"class":1072},"imports",[251,2569,1097],{"class":1068},[251,2571,2572,2574,2577,2579],{"class":253,"line":277},[251,2573,1279],{"class":1068},[251,2575,2576],{"class":1072},"namespace",[251,2578,1075],{"class":1068},[251,2580,2581],{"class":1078},"inventory\n",[251,2583,2584,2587,2589],{"class":253,"line":283},[251,2585,2586],{"class":1072},"    href",[251,2588,1075],{"class":1068},[251,2590,2591],{"class":1078},"https:\u002F\u002Fexample.com\u002Fdomains\u002Finventory-objects.yml\n",[251,2593,2594,2596,2598,2600],{"class":253,"line":289},[251,2595,1279],{"class":1068},[251,2597,2576],{"class":1072},[251,2599,1075],{"class":1068},[251,2601,2602],{"class":1078},"sales\n",[251,2604,2605,2607,2609],{"class":253,"line":295},[251,2606,2586],{"class":1072},[251,2608,1075],{"class":1068},[251,2610,2611],{"class":1078},"https:\u002F\u002Fexample.com\u002Fdomains\u002Fsales-objects.yml\n",[11,2613,2614],{},"With the support for importing and leveraging namespaces it should become possible to further implement the usage of natural language.",[2509,2616,2618],{"id":2617},"signatures","Signatures",[533,2620,2621],{},[11,2622,2623],{},"“An API operation is identifiable by its signature, which can be based on any aspect of HTTP mechanics”",[11,2625,2626,2627,2630],{},"Current OpenAPI Specifications only allows for ",[59,2628,2629],{},"one operation per HTTP method"," which is an artificial constraint made by the specification.",[11,2632,2633],{},"Moonwalk wants to pivot to be more client-oriented by offering API functions by their signature. This allows for descriptions that bundle a set of functions that can be mapped to HTTP mechanics instead of the other way around.",[11,2635,2636],{},"This means we’ll be going from this:",[243,2638,2640],{"className":1053,"code":2639,"language":1055,"meta":144,"style":144},"# HTTP as starting point\nopenapi: 3.0.0\ninfo:\nservers:\ntags:\npaths:\n  '\u002Fpets':\n    post: # HTTP mechanic as starting point\n      requestBody:\n        content:\n          application\u002Fjson: # Content Type as structure\n            schema:\n              $ref: '#\u002Fcomponents\u002Fschemas\u002FPet'\n      responses:\n        201:\n          description: created\n        404:\n          description: notFound\n          content:\n            application\u002Fhttp-problem: {}\n        5XX:\n          description: serverError\n          content:\n            application\u002Fhttp-problem: {}\n    get:\n      responses:\n        200:\n          description: ok\n          content:\n            application\u002Fjson:\n              type: object\n              properties:\n                data:\n                  type: array\n                  items:\n                    $ref: '#\u002Fcomponents\u002Fschemas\u002FPet'\n        404:\n          description: notFound\n          content:\n            application\u002Fhttp-problem: {}\n        5XX:\n          description: serverError\n          content:\n            application\u002Fhttp-problem: {}\ncomponents:\n  Pet:\n    type: object\n    properties:\n      name:\n        type: string\n        ...\n",[206,2641,2642,2647,2656,2662,2669,2676,2683,2690,2700,2707,2714,2724,2731,2741,2748,2755,2764,2771,2780,2787,2795,2802,2811,2817,2823,2830,2836,2843,2852,2858,2865,2875,2882,2889,2899,2906,2915,2921,2929,2935,2941,2947,2955,2962,2969,2977,2985,2995,3003,3011,3021],{"__ignoreMap":144},[251,2643,2644],{"class":253,"line":254},[251,2645,2646],{"class":1062},"# HTTP as starting point\n",[251,2648,2649,2651,2653],{"class":253,"line":145},[251,2650,1807],{"class":1072},[251,2652,1075],{"class":1068},[251,2654,2655],{"class":1220},"3.0.0\n",[251,2657,2658,2660],{"class":253,"line":265},[251,2659,1226],{"class":1072},[251,2661,1097],{"class":1068},[251,2663,2664,2667],{"class":253,"line":271},[251,2665,2666],{"class":1072},"servers",[251,2668,1097],{"class":1068},[251,2670,2671,2674],{"class":253,"line":277},[251,2672,2673],{"class":1072},"tags",[251,2675,1097],{"class":1068},[251,2677,2678,2681],{"class":253,"line":283},[251,2679,2680],{"class":1072},"paths",[251,2682,1097],{"class":1068},[251,2684,2685,2688],{"class":253,"line":289},[251,2686,2687],{"class":1078},"  '\u002Fpets'",[251,2689,1097],{"class":1068},[251,2691,2692,2695,2697],{"class":253,"line":295},[251,2693,2694],{"class":1072},"    post",[251,2696,1075],{"class":1068},[251,2698,2699],{"class":1062},"# HTTP mechanic as starting point\n",[251,2701,2702,2705],{"class":253,"line":301},[251,2703,2704],{"class":1072},"      requestBody",[251,2706,1097],{"class":1068},[251,2708,2709,2712],{"class":253,"line":307},[251,2710,2711],{"class":1072},"        content",[251,2713,1097],{"class":1068},[251,2715,2716,2719,2721],{"class":253,"line":313},[251,2717,2718],{"class":1072},"          application\u002Fjson",[251,2720,1075],{"class":1068},[251,2722,2723],{"class":1062},"# Content Type as structure\n",[251,2725,2726,2729],{"class":253,"line":319},[251,2727,2728],{"class":1072},"            schema",[251,2730,1097],{"class":1068},[251,2732,2733,2736,2738],{"class":253,"line":325},[251,2734,2735],{"class":1072},"              $ref",[251,2737,1075],{"class":1068},[251,2739,2740],{"class":1078},"'#\u002Fcomponents\u002Fschemas\u002FPet'\n",[251,2742,2743,2746],{"class":253,"line":331},[251,2744,2745],{"class":1072},"      responses",[251,2747,1097],{"class":1068},[251,2749,2750,2753],{"class":253,"line":337},[251,2751,2752],{"class":1220},"        201",[251,2754,1097],{"class":1068},[251,2756,2757,2759,2761],{"class":253,"line":343},[251,2758,1331],{"class":1072},[251,2760,1075],{"class":1068},[251,2762,2763],{"class":1078},"created\n",[251,2765,2766,2769],{"class":253,"line":349},[251,2767,2768],{"class":1220},"        404",[251,2770,1097],{"class":1068},[251,2772,2773,2775,2777],{"class":253,"line":355},[251,2774,1331],{"class":1072},[251,2776,1075],{"class":1068},[251,2778,2779],{"class":1078},"notFound\n",[251,2781,2782,2785],{"class":253,"line":361},[251,2783,2784],{"class":1072},"          content",[251,2786,1097],{"class":1068},[251,2788,2789,2792],{"class":253,"line":367},[251,2790,2791],{"class":1072},"            application\u002Fhttp-problem",[251,2793,2794],{"class":1068},": {}\n",[251,2796,2797,2800],{"class":253,"line":373},[251,2798,2799],{"class":1072},"        5XX",[251,2801,1097],{"class":1068},[251,2803,2804,2806,2808],{"class":253,"line":379},[251,2805,1331],{"class":1072},[251,2807,1075],{"class":1068},[251,2809,2810],{"class":1078},"serverError\n",[251,2812,2813,2815],{"class":253,"line":384},[251,2814,2784],{"class":1072},[251,2816,1097],{"class":1068},[251,2818,2819,2821],{"class":253,"line":390},[251,2820,2791],{"class":1072},[251,2822,2794],{"class":1068},[251,2824,2825,2828],{"class":253,"line":396},[251,2826,2827],{"class":1072},"    get",[251,2829,1097],{"class":1068},[251,2831,2832,2834],{"class":253,"line":401},[251,2833,2745],{"class":1072},[251,2835,1097],{"class":1068},[251,2837,2838,2841],{"class":253,"line":407},[251,2839,2840],{"class":1220},"        200",[251,2842,1097],{"class":1068},[251,2844,2845,2847,2849],{"class":253,"line":1439},[251,2846,1331],{"class":1072},[251,2848,1075],{"class":1068},[251,2850,2851],{"class":1078},"ok\n",[251,2853,2854,2856],{"class":253,"line":1449},[251,2855,2784],{"class":1072},[251,2857,1097],{"class":1068},[251,2859,2860,2863],{"class":253,"line":1458},[251,2861,2862],{"class":1072},"            application\u002Fjson",[251,2864,1097],{"class":1068},[251,2866,2867,2870,2872],{"class":253,"line":1468},[251,2868,2869],{"class":1072},"              type",[251,2871,1075],{"class":1068},[251,2873,2874],{"class":1078},"object\n",[251,2876,2877,2880],{"class":253,"line":1475},[251,2878,2879],{"class":1072},"              properties",[251,2881,1097],{"class":1068},[251,2883,2884,2887],{"class":253,"line":1484},[251,2885,2886],{"class":1072},"                data",[251,2888,1097],{"class":1068},[251,2890,2891,2894,2896],{"class":253,"line":1494},[251,2892,2893],{"class":1072},"                  type",[251,2895,1075],{"class":1068},[251,2897,2898],{"class":1078},"array\n",[251,2900,2901,2904],{"class":253,"line":1506},[251,2902,2903],{"class":1072},"                  items",[251,2905,1097],{"class":1068},[251,2907,2908,2911,2913],{"class":253,"line":1513},[251,2909,2910],{"class":1072},"                    $ref",[251,2912,1075],{"class":1068},[251,2914,2740],{"class":1078},[251,2916,2917,2919],{"class":253,"line":1521},[251,2918,2768],{"class":1220},[251,2920,1097],{"class":1068},[251,2922,2923,2925,2927],{"class":253,"line":1529},[251,2924,1331],{"class":1072},[251,2926,1075],{"class":1068},[251,2928,2779],{"class":1078},[251,2930,2931,2933],{"class":253,"line":1540},[251,2932,2784],{"class":1072},[251,2934,1097],{"class":1068},[251,2936,2937,2939],{"class":253,"line":1548},[251,2938,2791],{"class":1072},[251,2940,2794],{"class":1068},[251,2942,2943,2945],{"class":253,"line":1558},[251,2944,2799],{"class":1072},[251,2946,1097],{"class":1068},[251,2948,2949,2951,2953],{"class":253,"line":1566},[251,2950,1331],{"class":1072},[251,2952,1075],{"class":1068},[251,2954,2810],{"class":1078},[251,2956,2958,2960],{"class":253,"line":2957},43,[251,2959,2784],{"class":1072},[251,2961,1097],{"class":1068},[251,2963,2965,2967],{"class":253,"line":2964},44,[251,2966,2791],{"class":1072},[251,2968,2794],{"class":1068},[251,2970,2972,2975],{"class":253,"line":2971},45,[251,2973,2974],{"class":1072},"components",[251,2976,1097],{"class":1068},[251,2978,2980,2983],{"class":253,"line":2979},46,[251,2981,2982],{"class":1072},"  Pet",[251,2984,1097],{"class":1068},[251,2986,2988,2991,2993],{"class":253,"line":2987},47,[251,2989,2990],{"class":1072},"    type",[251,2992,1075],{"class":1068},[251,2994,2874],{"class":1078},[251,2996,2998,3001],{"class":253,"line":2997},48,[251,2999,3000],{"class":1072},"    properties",[251,3002,1097],{"class":1068},[251,3004,3006,3009],{"class":253,"line":3005},49,[251,3007,3008],{"class":1072},"      name",[251,3010,1097],{"class":1068},[251,3012,3014,3017,3019],{"class":253,"line":3013},50,[251,3015,3016],{"class":1072},"        type",[251,3018,1075],{"class":1068},[251,3020,1353],{"class":1078},[251,3022,3024],{"class":253,"line":3023},51,[251,3025,3026],{"class":1220},"        ...\n",[11,3028,3029],{},"To something that looks more like this:",[243,3031,3033],{"className":1053,"code":3032,"language":1055,"meta":144,"style":144},"# SUBJECT TO CHANGE\n# API functionality as starting point\nopenapi: 4.0.0\n...\nimports:\n  - namespace: inventory\n    href: \u002Fdomains\u002Finventory.yml\npaths:\n  \"pets\":\n    requests:\n      createPet: # API function as starting point\n        method: post\n        # Content Type as property of API function\n        contentType: application\u002Fjson\n        contentSchema: inventory:Pet\n        responses:\n          created:\n            status: 201\n      getPets:\n        method: get\n        # Responses with the API function as scope\n        responses:\n          ok:\n            status: 200\n            contentType: application\u002Fjson\n            contentSchema:\n              type: object\n              properties:\n                data:\n                  type: array\n                  items: inventory:Pet\n    # Responses with the path as scope\n    pathResponses:\n      notFound:\n        status: 404\n        contentType: application\u002Fhttp-problem\n# Responses with the API as scope\napiResponses:\n  serverError:\n    status: 5xx\n    contentType: application\u002Fhttp-problem\n",[206,3034,3035,3039,3044,3052,3057,3063,3073,3082,3088,3095,3102,3112,3122,3127,3137,3147,3154,3161,3171,3178,3187,3192,3198,3205,3214,3223,3230,3238,3244,3250,3258,3266,3271,3278,3285,3295,3304,3309,3316,3323,3333],{"__ignoreMap":144},[251,3036,3037],{"class":253,"line":254},[251,3038,2543],{"class":1062},[251,3040,3041],{"class":253,"line":145},[251,3042,3043],{"class":1062},"# API functionality as starting point\n",[251,3045,3046,3048,3050],{"class":253,"line":265},[251,3047,1807],{"class":1072},[251,3049,1075],{"class":1068},[251,3051,2552],{"class":1220},[251,3053,3054],{"class":253,"line":271},[251,3055,3056],{"class":1220},"...\n",[251,3058,3059,3061],{"class":253,"line":277},[251,3060,2567],{"class":1072},[251,3062,1097],{"class":1068},[251,3064,3065,3067,3069,3071],{"class":253,"line":283},[251,3066,1279],{"class":1068},[251,3068,2576],{"class":1072},[251,3070,1075],{"class":1068},[251,3072,2581],{"class":1078},[251,3074,3075,3077,3079],{"class":253,"line":289},[251,3076,2586],{"class":1072},[251,3078,1075],{"class":1068},[251,3080,3081],{"class":1078},"\u002Fdomains\u002Finventory.yml\n",[251,3083,3084,3086],{"class":253,"line":295},[251,3085,2680],{"class":1072},[251,3087,1097],{"class":1068},[251,3089,3090,3093],{"class":253,"line":301},[251,3091,3092],{"class":1078},"  \"pets\"",[251,3094,1097],{"class":1068},[251,3096,3097,3100],{"class":253,"line":307},[251,3098,3099],{"class":1072},"    requests",[251,3101,1097],{"class":1068},[251,3103,3104,3107,3109],{"class":253,"line":313},[251,3105,3106],{"class":1072},"      createPet",[251,3108,1075],{"class":1068},[251,3110,3111],{"class":1062},"# API function as starting point\n",[251,3113,3114,3117,3119],{"class":253,"line":319},[251,3115,3116],{"class":1072},"        method",[251,3118,1075],{"class":1068},[251,3120,3121],{"class":1078},"post\n",[251,3123,3124],{"class":253,"line":325},[251,3125,3126],{"class":1062},"        # Content Type as property of API function\n",[251,3128,3129,3132,3134],{"class":253,"line":331},[251,3130,3131],{"class":1072},"        contentType",[251,3133,1075],{"class":1068},[251,3135,3136],{"class":1078},"application\u002Fjson\n",[251,3138,3139,3142,3144],{"class":253,"line":337},[251,3140,3141],{"class":1072},"        contentSchema",[251,3143,1075],{"class":1068},[251,3145,3146],{"class":1078},"inventory:Pet\n",[251,3148,3149,3152],{"class":253,"line":343},[251,3150,3151],{"class":1072},"        responses",[251,3153,1097],{"class":1068},[251,3155,3156,3159],{"class":253,"line":349},[251,3157,3158],{"class":1072},"          created",[251,3160,1097],{"class":1068},[251,3162,3163,3166,3168],{"class":253,"line":355},[251,3164,3165],{"class":1072},"            status",[251,3167,1075],{"class":1068},[251,3169,3170],{"class":1220},"201\n",[251,3172,3173,3176],{"class":253,"line":361},[251,3174,3175],{"class":1072},"      getPets",[251,3177,1097],{"class":1068},[251,3179,3180,3182,3184],{"class":253,"line":367},[251,3181,3116],{"class":1072},[251,3183,1075],{"class":1068},[251,3185,3186],{"class":1078},"get\n",[251,3188,3189],{"class":253,"line":373},[251,3190,3191],{"class":1062},"        # Responses with the API function as scope\n",[251,3193,3194,3196],{"class":253,"line":379},[251,3195,3151],{"class":1072},[251,3197,1097],{"class":1068},[251,3199,3200,3203],{"class":253,"line":384},[251,3201,3202],{"class":1072},"          ok",[251,3204,1097],{"class":1068},[251,3206,3207,3209,3211],{"class":253,"line":390},[251,3208,3165],{"class":1072},[251,3210,1075],{"class":1068},[251,3212,3213],{"class":1220},"200\n",[251,3215,3216,3219,3221],{"class":253,"line":396},[251,3217,3218],{"class":1072},"            contentType",[251,3220,1075],{"class":1068},[251,3222,3136],{"class":1078},[251,3224,3225,3228],{"class":253,"line":401},[251,3226,3227],{"class":1072},"            contentSchema",[251,3229,1097],{"class":1068},[251,3231,3232,3234,3236],{"class":253,"line":407},[251,3233,2869],{"class":1072},[251,3235,1075],{"class":1068},[251,3237,2874],{"class":1078},[251,3239,3240,3242],{"class":253,"line":1439},[251,3241,2879],{"class":1072},[251,3243,1097],{"class":1068},[251,3245,3246,3248],{"class":253,"line":1449},[251,3247,2886],{"class":1072},[251,3249,1097],{"class":1068},[251,3251,3252,3254,3256],{"class":253,"line":1458},[251,3253,2893],{"class":1072},[251,3255,1075],{"class":1068},[251,3257,2898],{"class":1078},[251,3259,3260,3262,3264],{"class":253,"line":1468},[251,3261,2903],{"class":1072},[251,3263,1075],{"class":1068},[251,3265,3146],{"class":1078},[251,3267,3268],{"class":253,"line":1475},[251,3269,3270],{"class":1062},"    # Responses with the path as scope\n",[251,3272,3273,3276],{"class":253,"line":1484},[251,3274,3275],{"class":1072},"    pathResponses",[251,3277,1097],{"class":1068},[251,3279,3280,3283],{"class":253,"line":1494},[251,3281,3282],{"class":1072},"      notFound",[251,3284,1097],{"class":1068},[251,3286,3287,3290,3292],{"class":253,"line":1506},[251,3288,3289],{"class":1072},"        status",[251,3291,1075],{"class":1068},[251,3293,3294],{"class":1220},"404\n",[251,3296,3297,3299,3301],{"class":253,"line":1513},[251,3298,3131],{"class":1072},[251,3300,1075],{"class":1068},[251,3302,3303],{"class":1078},"application\u002Fhttp-problem\n",[251,3305,3306],{"class":253,"line":1521},[251,3307,3308],{"class":1062},"# Responses with the API as scope\n",[251,3310,3311,3314],{"class":253,"line":1529},[251,3312,3313],{"class":1072},"apiResponses",[251,3315,1097],{"class":1068},[251,3317,3318,3321],{"class":253,"line":1540},[251,3319,3320],{"class":1072},"  serverError",[251,3322,1097],{"class":1068},[251,3324,3325,3328,3330],{"class":253,"line":1548},[251,3326,3327],{"class":1072},"    status",[251,3329,1075],{"class":1068},[251,3331,3332],{"class":1078},"5xx\n",[251,3334,3335,3338,3340],{"class":253,"line":1558},[251,3336,3337],{"class":1072},"    contentType",[251,3339,1075],{"class":1068},[251,3341,3303],{"class":1078},[11,3343,3344],{},"Besides a more functional approach it also allows for more descriptive power with fewer lines!",[2509,3346,3348],{"id":3347},"inclusion","Inclusion",[533,3350,3351],{},[11,3352,3353],{},"“Moonwalk aims to describe all HTTP-based APIs while remaining neutral regarding any specific design debate.”",[11,3355,3356],{},"Recently I was working on an implementation of one of Google’s services and I encountered very developer-unfriendly specification of its APIs.",[11,3358,3359],{},"On one hand there’s the resource-oriented system design of my customer and on the other hand there is an API describing a set of HTTP-based RPC functions. Since I’ve been working on the description of all APIs provided by my customer, the request was to also describe the APIs offered by Google with the OpenAPI specification.",[11,3361,3362,3365],{},[59,3363,3364],{},"The distinct factor between the calls was the content of the payload that determined what functionality was executed."," This led to a convoluted API description since they all were expected to be using the POST method which makes it harder to describe since OpenAPI v3 is more resource-oriented in its specification.",[11,3367,3368],{},"Well no more! 🙏",[2509,3370,3372],{"id":3371},"seperation-of-concerns","Seperation of Concerns",[533,3374,3375],{},[11,3376,3377],{},"“Modularization will keep the scope of Moonwalk manageable with loose coupling among concerns such as HTTP interfaces (“API shapes”), deployment configuration, and content schema formats”",[11,3379,3380,3381,3384],{},"An example of the current tight coupling between the API description and deployment configuration is ",[59,3382,3383],{},"a difference in security implementation within each environment."," Sandbox or testing environments can have other — or no — means of securing APIs for a spectrum of reasons.",[11,3386,3387],{},"Version 3 has no way of dealing with this difference between environments other than having to specify all possible security schemes or even worse, having an API description dedicated to each environment.",[11,3389,3390],{},"With Moonwalk it’s possible to specify deployments using a few properties. These deployments can be included within an OpenAPI Specification or isolated in a dedicated specification referencing separate other files.",[243,3392,3394],{"className":1053,"code":3393,"language":1055,"meta":144,"style":144},"# SUBJECT TO CHANGE\nopenapi: 4.0.0\nnamespace: self\ndeployments:\n  default:\n    title: PROD\n    location: https:\u002F\u002Fapi.example.com\n    security:\n      - oauth: []\n    clientRegistration: https:\u002F\u002Fdevelopers.example\u002Flet-me-in\n    apiPaths: self\n  sandbox:\n    title: SBX\n    location: https:\u002F\u002Fapi-sbx.example.com\n    security:\n      - basic: []\n    clientRegistration: https:\u002F\u002Fdevelopers.example\u002Flet-me-in\n    apiPaths: sandbox\n",[206,3395,3396,3400,3408,3417,3424,3431,3441,3451,3458,3469,3479,3488,3495,3504,3513,3519,3528,3536],{"__ignoreMap":144},[251,3397,3398],{"class":253,"line":254},[251,3399,2543],{"class":1062},[251,3401,3402,3404,3406],{"class":253,"line":145},[251,3403,1807],{"class":1072},[251,3405,1075],{"class":1068},[251,3407,2552],{"class":1220},[251,3409,3410,3412,3414],{"class":253,"line":265},[251,3411,2576],{"class":1072},[251,3413,1075],{"class":1068},[251,3415,3416],{"class":1078},"self\n",[251,3418,3419,3422],{"class":253,"line":271},[251,3420,3421],{"class":1072},"deployments",[251,3423,1097],{"class":1068},[251,3425,3426,3429],{"class":253,"line":277},[251,3427,3428],{"class":1072},"  default",[251,3430,1097],{"class":1068},[251,3432,3433,3436,3438],{"class":253,"line":283},[251,3434,3435],{"class":1072},"    title",[251,3437,1075],{"class":1068},[251,3439,3440],{"class":1078},"PROD\n",[251,3442,3443,3446,3448],{"class":253,"line":289},[251,3444,3445],{"class":1072},"    location",[251,3447,1075],{"class":1068},[251,3449,3450],{"class":1078},"https:\u002F\u002Fapi.example.com\n",[251,3452,3453,3456],{"class":253,"line":295},[251,3454,3455],{"class":1072},"    security",[251,3457,1097],{"class":1068},[251,3459,3460,3463,3466],{"class":253,"line":301},[251,3461,3462],{"class":1068},"      - ",[251,3464,3465],{"class":1072},"oauth",[251,3467,3468],{"class":1068},": []\n",[251,3470,3471,3474,3476],{"class":253,"line":307},[251,3472,3473],{"class":1072},"    clientRegistration",[251,3475,1075],{"class":1068},[251,3477,3478],{"class":1078},"https:\u002F\u002Fdevelopers.example\u002Flet-me-in\n",[251,3480,3481,3484,3486],{"class":253,"line":313},[251,3482,3483],{"class":1072},"    apiPaths",[251,3485,1075],{"class":1068},[251,3487,3416],{"class":1078},[251,3489,3490,3493],{"class":253,"line":319},[251,3491,3492],{"class":1072},"  sandbox",[251,3494,1097],{"class":1068},[251,3496,3497,3499,3501],{"class":253,"line":325},[251,3498,3435],{"class":1072},[251,3500,1075],{"class":1068},[251,3502,3503],{"class":1078},"SBX\n",[251,3505,3506,3508,3510],{"class":253,"line":331},[251,3507,3445],{"class":1072},[251,3509,1075],{"class":1068},[251,3511,3512],{"class":1078},"https:\u002F\u002Fapi-sbx.example.com\n",[251,3514,3515,3517],{"class":253,"line":337},[251,3516,3455],{"class":1072},[251,3518,1097],{"class":1068},[251,3520,3521,3523,3526],{"class":253,"line":343},[251,3522,3462],{"class":1068},[251,3524,3525],{"class":1072},"basic",[251,3527,3468],{"class":1068},[251,3529,3530,3532,3534],{"class":253,"line":349},[251,3531,3473],{"class":1072},[251,3533,1075],{"class":1068},[251,3535,3478],{"class":1078},[251,3537,3538,3540,3542],{"class":253,"line":355},[251,3539,3483],{"class":1072},[251,3541,1075],{"class":1068},[251,3543,3544],{"class":1078},"sandbox\n",[2509,3546,3548],{"id":3547},"mechanical-upgrading","Mechanical Upgrading",[533,3550,3551],{},[11,3552,3553],{},"“An automated upgrade process from 3.x to 4.0 will be developed as part of the Moonwalk effort”",[11,3555,3556],{},"This speaks for itself. The threshold to get people from older versions to newer versions should be as low as possible. Ensuring automated upgrades are possible is more than welcome and hopefully allows for a higher adoption rate of the new version.",[11,3558,3559],{},"Based on the statistics from APIstic — which has statistics based on a total of 1.437.832 API specifications — only roughly 15.560 (~1,08%) of the registered specifications are on version 3. Hopefully this is either a miscalculation on my side or a dataset that’s not representative of the market.",[11,3561,3562],{},"Even if it is a remote representation then that would still leave a lot of room for improvement — and work… — for the majority out there.",[11,3564,3565],{},[1585,3566],{"alt":3567,"src":3568},"Graph depicting OpenAPI major version usage by APIstic","\u002Farticles\u002Feverything-about-openapi-4\u002Fapistic-major-version-usage-graph.jpg",[24,3570,3572],{"id":3571},"predictions","Predictions",[11,3574,3575],{},"What can we conclude from this? There are three major opportunities that come to my mind.",[2509,3577,3579],{"id":3578},"opportunity-1-full-embrace-of-generative-ai","Opportunity #1: Full embrace of generative AI",[11,3581,3582],{},"Regardless of your opinion on generative AI in general, you should understand that having “nothing” in between the implementation code behind an API and the added value to customers of the API consumer’s business is the ultimate goal.",[11,3584,3585],{},"It’s why web-based APIs have become successful in the first place. They the means for any disparate organisations to collaborate by exchanging data and functionality.",[11,3587,3588],{},"For now it seems generative AI is the most feasible tool that will get us another step closer to achieving this without too much friction.",[2509,3590,3592],{"id":3591},"opportunity-2-rise-of-openapi-description-oad-repositories","Opportunity #2: Rise of OpenAPI Description (OAD) repositories",[11,3594,3595],{},"The combination of specifications in development at OAI start to form an ecosystem for tech-agnostic API description. Especially when Arazzo, OpenAPI and Overlay (more on this in a future post) are combined it leads to a collection of resources that is able to fully describe an API and its intended implementation.",[11,3597,3598],{},"Here’s my first attempt:",[11,3600,3601],{},"We’ll draft out what we’ll need for the OpenAPI Description for our feature.",[11,3603,3604],{},"The amount and separation should be based on the functional design of the system:",[243,3606,3608],{"className":1053,"code":3607,"language":1055,"meta":144,"style":144},"# conceptual overview of relevant resources\nresources:\n  - workflowDescription: https:\u002F\u002Fapi.example.com\u002Fworkflows\u002Fpetstore.arazzo.yml\n  - apiDescriptions:\n      - petstore-api: https:\u002F\u002Fapi.example.com\u002Fapi-specifications\u002Fpetstore.openapi.yml\n      - ...\n  - domainDescriptions:\n      - sales: https:\u002F\u002Fexample.com\u002Fdomains\u002Fsales.yml\n      - inventory: https:\u002F\u002Fexample.com\u002Fdomains\u002Finventory.yml\n      - ...\n",[206,3609,3610,3615,3622,3634,3643,3655,3661,3670,3682,3694],{"__ignoreMap":144},[251,3611,3612],{"class":253,"line":254},[251,3613,3614],{"class":1062},"# conceptual overview of relevant resources\n",[251,3616,3617,3620],{"class":253,"line":145},[251,3618,3619],{"class":1072},"resources",[251,3621,1097],{"class":1068},[251,3623,3624,3626,3629,3631],{"class":253,"line":265},[251,3625,1279],{"class":1068},[251,3627,3628],{"class":1072},"workflowDescription",[251,3630,1075],{"class":1068},[251,3632,3633],{"class":1078},"https:\u002F\u002Fapi.example.com\u002Fworkflows\u002Fpetstore.arazzo.yml\n",[251,3635,3636,3638,3641],{"class":253,"line":271},[251,3637,1279],{"class":1068},[251,3639,3640],{"class":1072},"apiDescriptions",[251,3642,1097],{"class":1068},[251,3644,3645,3647,3650,3652],{"class":253,"line":277},[251,3646,3462],{"class":1068},[251,3648,3649],{"class":1072},"petstore-api",[251,3651,1075],{"class":1068},[251,3653,3654],{"class":1078},"https:\u002F\u002Fapi.example.com\u002Fapi-specifications\u002Fpetstore.openapi.yml\n",[251,3656,3657,3659],{"class":253,"line":283},[251,3658,3462],{"class":1068},[251,3660,3056],{"class":1220},[251,3662,3663,3665,3668],{"class":253,"line":289},[251,3664,1279],{"class":1068},[251,3666,3667],{"class":1072},"domainDescriptions",[251,3669,1097],{"class":1068},[251,3671,3672,3674,3677,3679],{"class":253,"line":295},[251,3673,3462],{"class":1068},[251,3675,3676],{"class":1072},"sales",[251,3678,1075],{"class":1068},[251,3680,3681],{"class":1078},"https:\u002F\u002Fexample.com\u002Fdomains\u002Fsales.yml\n",[251,3683,3684,3686,3689,3691],{"class":253,"line":301},[251,3685,3462],{"class":1068},[251,3687,3688],{"class":1072},"inventory",[251,3690,1075],{"class":1068},[251,3692,3693],{"class":1078},"https:\u002F\u002Fexample.com\u002Fdomains\u002Finventory.yml\n",[251,3695,3696,3698],{"class":253,"line":307},[251,3697,3462],{"class":1068},[251,3699,3056],{"class":1220},[11,3701,3702],{},"First we create the definitions of our functional domains and their resources:",[243,3704,3706],{"className":1053,"code":3705,"language":1055,"meta":144,"style":144},"# sales.yml\ncomponents:\n  schemas:\n    Invoice:\n      type: object\n      properties: ...\n    Order:\n      type: object\n      properties: ...\n    OrderLines:\n      type: object\n      properties: ...\n\n# inventory.yml\ncomponents:\n  schemas:\n    Product:\n      type: object\n      properties: ...\n    Pet:\n      type: object\n      properties: ...\n    Food:\n      type: object\n      properties: ...\n",[206,3707,3708,3713,3719,3726,3733,3742,3751,3758,3766,3774,3781,3789,3797,3801,3806,3812,3818,3825,3833,3841,3848,3856,3864,3871,3879],{"__ignoreMap":144},[251,3709,3710],{"class":253,"line":254},[251,3711,3712],{"class":1062},"# sales.yml\n",[251,3714,3715,3717],{"class":253,"line":145},[251,3716,2974],{"class":1072},[251,3718,1097],{"class":1068},[251,3720,3721,3724],{"class":253,"line":265},[251,3722,3723],{"class":1072},"  schemas",[251,3725,1097],{"class":1068},[251,3727,3728,3731],{"class":253,"line":271},[251,3729,3730],{"class":1072},"    Invoice",[251,3732,1097],{"class":1068},[251,3734,3735,3738,3740],{"class":253,"line":277},[251,3736,3737],{"class":1072},"      type",[251,3739,1075],{"class":1068},[251,3741,2874],{"class":1078},[251,3743,3744,3747,3749],{"class":253,"line":283},[251,3745,3746],{"class":1072},"      properties",[251,3748,1075],{"class":1068},[251,3750,3056],{"class":1220},[251,3752,3753,3756],{"class":253,"line":289},[251,3754,3755],{"class":1072},"    Order",[251,3757,1097],{"class":1068},[251,3759,3760,3762,3764],{"class":253,"line":295},[251,3761,3737],{"class":1072},[251,3763,1075],{"class":1068},[251,3765,2874],{"class":1078},[251,3767,3768,3770,3772],{"class":253,"line":301},[251,3769,3746],{"class":1072},[251,3771,1075],{"class":1068},[251,3773,3056],{"class":1220},[251,3775,3776,3779],{"class":253,"line":307},[251,3777,3778],{"class":1072},"    OrderLines",[251,3780,1097],{"class":1068},[251,3782,3783,3785,3787],{"class":253,"line":313},[251,3784,3737],{"class":1072},[251,3786,1075],{"class":1068},[251,3788,2874],{"class":1078},[251,3790,3791,3793,3795],{"class":253,"line":319},[251,3792,3746],{"class":1072},[251,3794,1075],{"class":1068},[251,3796,3056],{"class":1220},[251,3798,3799],{"class":253,"line":325},[251,3800,328],{"emptyLinePlaceholder":160},[251,3802,3803],{"class":253,"line":331},[251,3804,3805],{"class":1062},"# inventory.yml\n",[251,3807,3808,3810],{"class":253,"line":337},[251,3809,2974],{"class":1072},[251,3811,1097],{"class":1068},[251,3813,3814,3816],{"class":253,"line":343},[251,3815,3723],{"class":1072},[251,3817,1097],{"class":1068},[251,3819,3820,3823],{"class":253,"line":349},[251,3821,3822],{"class":1072},"    Product",[251,3824,1097],{"class":1068},[251,3826,3827,3829,3831],{"class":253,"line":355},[251,3828,3737],{"class":1072},[251,3830,1075],{"class":1068},[251,3832,2874],{"class":1078},[251,3834,3835,3837,3839],{"class":253,"line":361},[251,3836,3746],{"class":1072},[251,3838,1075],{"class":1068},[251,3840,3056],{"class":1220},[251,3842,3843,3846],{"class":253,"line":367},[251,3844,3845],{"class":1072},"    Pet",[251,3847,1097],{"class":1068},[251,3849,3850,3852,3854],{"class":253,"line":373},[251,3851,3737],{"class":1072},[251,3853,1075],{"class":1068},[251,3855,2874],{"class":1078},[251,3857,3858,3860,3862],{"class":253,"line":379},[251,3859,3746],{"class":1072},[251,3861,1075],{"class":1068},[251,3863,3056],{"class":1220},[251,3865,3866,3869],{"class":253,"line":384},[251,3867,3868],{"class":1072},"    Food",[251,3870,1097],{"class":1068},[251,3872,3873,3875,3877],{"class":253,"line":390},[251,3874,3737],{"class":1072},[251,3876,1075],{"class":1068},[251,3878,2874],{"class":1078},[251,3880,3881,3883,3885],{"class":253,"line":396},[251,3882,3746],{"class":1072},[251,3884,1075],{"class":1068},[251,3886,3056],{"class":1220},[11,3888,3889],{},"Then we’ll offer an API description based on the functionality and data we’re offering:",[243,3891,3893],{"className":1053,"code":3892,"language":1055,"meta":144,"style":144},"# SUBJECT TO CHANGE\n# petstore.openapi.yml\nopenapi: 4.0.0\n...\nimports:\n  - namespace: inventory\n    href: \u002Fdomains\u002Finventory.yml\npaths:\n  \"pets\":\n    requests:\n      createPet: # API function as starting point\n        method: post\n        # Content Type as property of API function\n        contentType: application\u002Fjson\n        contentSchema: inventory:Pet\n        responses:\n          created:\n            status: 201\n      getPets:\n        method: get\n        responses:\n          ok:\n            status: 200\n            contentType: application\u002Fjson\n            contentSchema:\n              type: object\n              properties:\n                data:\n                  type: array\n                  items: inventory:Pet\n    pathResponses:\n      notFound:\n        status: 404\n        contentType: application\u002Fhttp-problem\napiResponses:\n  serverError:\n    status: 5xx\n    contentType: application\u002Fhttp-problem\n...\n# sales.openapi.yml\nopenapi: 4.0.0\n...\nimports:\n  - namespace: sales\n    href: \u002Fdomains\u002Fsales.yml\npaths:\n  \"pets\":\n    requests:\n      createOrder:\n        method: post\n        contentType: application\u002Fjson\n        contentSchema: sales:Order\n        responses:\n          created:\n            status: 201\n      getOrders:\n        method: get\n        responses:\n          ok:\n            status: 200\n            contentType: application\u002Fjson\n            contentSchema:\n              type: object\n              properties:\n                data:\n                  type: array\n                  items: sales:Order\n    pathResponses:\n      notFound:\n        status: 404\n        contentType: application\u002Fhttp-problem\napiResponses:\n  serverError:\n    status: 5xx\n    contentType: application\u002Fhttp-problem\n",[206,3894,3895,3899,3904,3912,3916,3922,3932,3940,3946,3952,3958,3966,3974,3978,3986,3994,4000,4006,4014,4020,4028,4034,4040,4048,4056,4062,4070,4076,4082,4090,4098,4104,4110,4118,4126,4132,4138,4146,4154,4158,4163,4171,4175,4181,4191,4200,4206,4212,4218,4225,4233,4241,4251,4258,4265,4274,4282,4291,4298,4305,4314,4323,4330,4339,4346,4353,4362,4371,4378,4385,4394,4403,4410,4417,4426],{"__ignoreMap":144},[251,3896,3897],{"class":253,"line":254},[251,3898,2543],{"class":1062},[251,3900,3901],{"class":253,"line":145},[251,3902,3903],{"class":1062},"# petstore.openapi.yml\n",[251,3905,3906,3908,3910],{"class":253,"line":265},[251,3907,1807],{"class":1072},[251,3909,1075],{"class":1068},[251,3911,2552],{"class":1220},[251,3913,3914],{"class":253,"line":271},[251,3915,3056],{"class":1220},[251,3917,3918,3920],{"class":253,"line":277},[251,3919,2567],{"class":1072},[251,3921,1097],{"class":1068},[251,3923,3924,3926,3928,3930],{"class":253,"line":283},[251,3925,1279],{"class":1068},[251,3927,2576],{"class":1072},[251,3929,1075],{"class":1068},[251,3931,2581],{"class":1078},[251,3933,3934,3936,3938],{"class":253,"line":289},[251,3935,2586],{"class":1072},[251,3937,1075],{"class":1068},[251,3939,3081],{"class":1078},[251,3941,3942,3944],{"class":253,"line":295},[251,3943,2680],{"class":1072},[251,3945,1097],{"class":1068},[251,3947,3948,3950],{"class":253,"line":301},[251,3949,3092],{"class":1078},[251,3951,1097],{"class":1068},[251,3953,3954,3956],{"class":253,"line":307},[251,3955,3099],{"class":1072},[251,3957,1097],{"class":1068},[251,3959,3960,3962,3964],{"class":253,"line":313},[251,3961,3106],{"class":1072},[251,3963,1075],{"class":1068},[251,3965,3111],{"class":1062},[251,3967,3968,3970,3972],{"class":253,"line":319},[251,3969,3116],{"class":1072},[251,3971,1075],{"class":1068},[251,3973,3121],{"class":1078},[251,3975,3976],{"class":253,"line":325},[251,3977,3126],{"class":1062},[251,3979,3980,3982,3984],{"class":253,"line":331},[251,3981,3131],{"class":1072},[251,3983,1075],{"class":1068},[251,3985,3136],{"class":1078},[251,3987,3988,3990,3992],{"class":253,"line":337},[251,3989,3141],{"class":1072},[251,3991,1075],{"class":1068},[251,3993,3146],{"class":1078},[251,3995,3996,3998],{"class":253,"line":343},[251,3997,3151],{"class":1072},[251,3999,1097],{"class":1068},[251,4001,4002,4004],{"class":253,"line":349},[251,4003,3158],{"class":1072},[251,4005,1097],{"class":1068},[251,4007,4008,4010,4012],{"class":253,"line":355},[251,4009,3165],{"class":1072},[251,4011,1075],{"class":1068},[251,4013,3170],{"class":1220},[251,4015,4016,4018],{"class":253,"line":361},[251,4017,3175],{"class":1072},[251,4019,1097],{"class":1068},[251,4021,4022,4024,4026],{"class":253,"line":367},[251,4023,3116],{"class":1072},[251,4025,1075],{"class":1068},[251,4027,3186],{"class":1078},[251,4029,4030,4032],{"class":253,"line":373},[251,4031,3151],{"class":1072},[251,4033,1097],{"class":1068},[251,4035,4036,4038],{"class":253,"line":379},[251,4037,3202],{"class":1072},[251,4039,1097],{"class":1068},[251,4041,4042,4044,4046],{"class":253,"line":384},[251,4043,3165],{"class":1072},[251,4045,1075],{"class":1068},[251,4047,3213],{"class":1220},[251,4049,4050,4052,4054],{"class":253,"line":390},[251,4051,3218],{"class":1072},[251,4053,1075],{"class":1068},[251,4055,3136],{"class":1078},[251,4057,4058,4060],{"class":253,"line":396},[251,4059,3227],{"class":1072},[251,4061,1097],{"class":1068},[251,4063,4064,4066,4068],{"class":253,"line":401},[251,4065,2869],{"class":1072},[251,4067,1075],{"class":1068},[251,4069,2874],{"class":1078},[251,4071,4072,4074],{"class":253,"line":407},[251,4073,2879],{"class":1072},[251,4075,1097],{"class":1068},[251,4077,4078,4080],{"class":253,"line":1439},[251,4079,2886],{"class":1072},[251,4081,1097],{"class":1068},[251,4083,4084,4086,4088],{"class":253,"line":1449},[251,4085,2893],{"class":1072},[251,4087,1075],{"class":1068},[251,4089,2898],{"class":1078},[251,4091,4092,4094,4096],{"class":253,"line":1458},[251,4093,2903],{"class":1072},[251,4095,1075],{"class":1068},[251,4097,3146],{"class":1078},[251,4099,4100,4102],{"class":253,"line":1468},[251,4101,3275],{"class":1072},[251,4103,1097],{"class":1068},[251,4105,4106,4108],{"class":253,"line":1475},[251,4107,3282],{"class":1072},[251,4109,1097],{"class":1068},[251,4111,4112,4114,4116],{"class":253,"line":1484},[251,4113,3289],{"class":1072},[251,4115,1075],{"class":1068},[251,4117,3294],{"class":1220},[251,4119,4120,4122,4124],{"class":253,"line":1494},[251,4121,3131],{"class":1072},[251,4123,1075],{"class":1068},[251,4125,3303],{"class":1078},[251,4127,4128,4130],{"class":253,"line":1506},[251,4129,3313],{"class":1072},[251,4131,1097],{"class":1068},[251,4133,4134,4136],{"class":253,"line":1513},[251,4135,3320],{"class":1072},[251,4137,1097],{"class":1068},[251,4139,4140,4142,4144],{"class":253,"line":1521},[251,4141,3327],{"class":1072},[251,4143,1075],{"class":1068},[251,4145,3332],{"class":1078},[251,4147,4148,4150,4152],{"class":253,"line":1529},[251,4149,3337],{"class":1072},[251,4151,1075],{"class":1068},[251,4153,3303],{"class":1078},[251,4155,4156],{"class":253,"line":1540},[251,4157,3056],{"class":1220},[251,4159,4160],{"class":253,"line":1548},[251,4161,4162],{"class":1062},"# sales.openapi.yml\n",[251,4164,4165,4167,4169],{"class":253,"line":1558},[251,4166,1807],{"class":1072},[251,4168,1075],{"class":1068},[251,4170,2552],{"class":1220},[251,4172,4173],{"class":253,"line":1566},[251,4174,3056],{"class":1220},[251,4176,4177,4179],{"class":253,"line":2957},[251,4178,2567],{"class":1072},[251,4180,1097],{"class":1068},[251,4182,4183,4185,4187,4189],{"class":253,"line":2964},[251,4184,1279],{"class":1068},[251,4186,2576],{"class":1072},[251,4188,1075],{"class":1068},[251,4190,2602],{"class":1078},[251,4192,4193,4195,4197],{"class":253,"line":2971},[251,4194,2586],{"class":1072},[251,4196,1075],{"class":1068},[251,4198,4199],{"class":1078},"\u002Fdomains\u002Fsales.yml\n",[251,4201,4202,4204],{"class":253,"line":2979},[251,4203,2680],{"class":1072},[251,4205,1097],{"class":1068},[251,4207,4208,4210],{"class":253,"line":2987},[251,4209,3092],{"class":1078},[251,4211,1097],{"class":1068},[251,4213,4214,4216],{"class":253,"line":2997},[251,4215,3099],{"class":1072},[251,4217,1097],{"class":1068},[251,4219,4220,4223],{"class":253,"line":3005},[251,4221,4222],{"class":1072},"      createOrder",[251,4224,1097],{"class":1068},[251,4226,4227,4229,4231],{"class":253,"line":3013},[251,4228,3116],{"class":1072},[251,4230,1075],{"class":1068},[251,4232,3121],{"class":1078},[251,4234,4235,4237,4239],{"class":253,"line":3023},[251,4236,3131],{"class":1072},[251,4238,1075],{"class":1068},[251,4240,3136],{"class":1078},[251,4242,4244,4246,4248],{"class":253,"line":4243},52,[251,4245,3141],{"class":1072},[251,4247,1075],{"class":1068},[251,4249,4250],{"class":1078},"sales:Order\n",[251,4252,4254,4256],{"class":253,"line":4253},53,[251,4255,3151],{"class":1072},[251,4257,1097],{"class":1068},[251,4259,4261,4263],{"class":253,"line":4260},54,[251,4262,3158],{"class":1072},[251,4264,1097],{"class":1068},[251,4266,4268,4270,4272],{"class":253,"line":4267},55,[251,4269,3165],{"class":1072},[251,4271,1075],{"class":1068},[251,4273,3170],{"class":1220},[251,4275,4277,4280],{"class":253,"line":4276},56,[251,4278,4279],{"class":1072},"      getOrders",[251,4281,1097],{"class":1068},[251,4283,4285,4287,4289],{"class":253,"line":4284},57,[251,4286,3116],{"class":1072},[251,4288,1075],{"class":1068},[251,4290,3186],{"class":1078},[251,4292,4294,4296],{"class":253,"line":4293},58,[251,4295,3151],{"class":1072},[251,4297,1097],{"class":1068},[251,4299,4301,4303],{"class":253,"line":4300},59,[251,4302,3202],{"class":1072},[251,4304,1097],{"class":1068},[251,4306,4308,4310,4312],{"class":253,"line":4307},60,[251,4309,3165],{"class":1072},[251,4311,1075],{"class":1068},[251,4313,3213],{"class":1220},[251,4315,4317,4319,4321],{"class":253,"line":4316},61,[251,4318,3218],{"class":1072},[251,4320,1075],{"class":1068},[251,4322,3136],{"class":1078},[251,4324,4326,4328],{"class":253,"line":4325},62,[251,4327,3227],{"class":1072},[251,4329,1097],{"class":1068},[251,4331,4333,4335,4337],{"class":253,"line":4332},63,[251,4334,2869],{"class":1072},[251,4336,1075],{"class":1068},[251,4338,2874],{"class":1078},[251,4340,4342,4344],{"class":253,"line":4341},64,[251,4343,2879],{"class":1072},[251,4345,1097],{"class":1068},[251,4347,4349,4351],{"class":253,"line":4348},65,[251,4350,2886],{"class":1072},[251,4352,1097],{"class":1068},[251,4354,4356,4358,4360],{"class":253,"line":4355},66,[251,4357,2893],{"class":1072},[251,4359,1075],{"class":1068},[251,4361,2898],{"class":1078},[251,4363,4365,4367,4369],{"class":253,"line":4364},67,[251,4366,2903],{"class":1072},[251,4368,1075],{"class":1068},[251,4370,4250],{"class":1078},[251,4372,4374,4376],{"class":253,"line":4373},68,[251,4375,3275],{"class":1072},[251,4377,1097],{"class":1068},[251,4379,4381,4383],{"class":253,"line":4380},69,[251,4382,3282],{"class":1072},[251,4384,1097],{"class":1068},[251,4386,4388,4390,4392],{"class":253,"line":4387},70,[251,4389,3289],{"class":1072},[251,4391,1075],{"class":1068},[251,4393,3294],{"class":1220},[251,4395,4397,4399,4401],{"class":253,"line":4396},71,[251,4398,3131],{"class":1072},[251,4400,1075],{"class":1068},[251,4402,3303],{"class":1078},[251,4404,4406,4408],{"class":253,"line":4405},72,[251,4407,3313],{"class":1072},[251,4409,1097],{"class":1068},[251,4411,4413,4415],{"class":253,"line":4412},73,[251,4414,3320],{"class":1072},[251,4416,1097],{"class":1068},[251,4418,4420,4422,4424],{"class":253,"line":4419},74,[251,4421,3327],{"class":1072},[251,4423,1075],{"class":1068},[251,4425,3332],{"class":1078},[251,4427,4429,4431,4433],{"class":253,"line":4428},75,[251,4430,3337],{"class":1072},[251,4432,1075],{"class":1068},[251,4434,3303],{"class":1078},[11,4436,4437,4438,4441],{},"Lastly we ",[59,4439,4440],{},"add business context by offering a workflow description"," that describes the intended implementation of the API functions combined:",[243,4443,4445],{"className":1053,"code":4444,"language":1055,"meta":144,"style":144},"# SUBJECT TO CHANGE\n# petstore.arazzo.yml\narazzo: 1.0.0\n...\nsourceDescriptions:\n  - name: petstore-api\n    url: .\u002Fdescriptions\u002Fpetstore.openapi.yml\n    type: openapi\n  - name: sales-api\n    url: .\u002Fdescriptions\u002Fsales.openapi.yml\n    type: openapi\nworkflows:\n  - workflowId: OrderingPets\n    summary: Workflow for ordering Pets at Example\n    inputs:\n      type:\n    steps:\n      - stepId: listAvailablePets\n        description: Show Pet offering to Customer\n        operationId: $sourceDescriptions.petstore-api.getPets\n        outputs:\n          potentialPetId: $response.body.pets[x].id\n      - stepId: getPetInformation\n        description: Show Pet information to Customer\n        operationId: $sourceDescriptions.petstore-api.getPet\n        parameters:\n          - name: pet_id\n            in: query\n            value: $steps.listsPets.outputs.petId\n      - stepId: orderPet\n        description: Create an Order for a Pet\n        operationId: $sourceDescriptions.sales-api.createOrder\n        ...\n      - stepId: findOrderForPet\n        description: Show Order details to Customer related to Pet\n        operationId: $sourceDescriptions.sales-api.getOrder\n        ...\n",[206,4446,4447,4451,4456,4465,4469,4476,4488,4498,4507,4518,4527,4535,4542,4554,4564,4571,4577,4584,4596,4606,4616,4623,4633,4644,4653,4662,4669,4681,4691,4701,4712,4721,4730,4734,4745,4754,4763],{"__ignoreMap":144},[251,4448,4449],{"class":253,"line":254},[251,4450,2543],{"class":1062},[251,4452,4453],{"class":253,"line":145},[251,4454,4455],{"class":1062},"# petstore.arazzo.yml\n",[251,4457,4458,4461,4463],{"class":253,"line":265},[251,4459,4460],{"class":1072},"arazzo",[251,4462,1075],{"class":1068},[251,4464,1221],{"class":1220},[251,4466,4467],{"class":253,"line":271},[251,4468,3056],{"class":1220},[251,4470,4471,4474],{"class":253,"line":277},[251,4472,4473],{"class":1072},"sourceDescriptions",[251,4475,1097],{"class":1068},[251,4477,4478,4480,4483,4485],{"class":253,"line":283},[251,4479,1279],{"class":1068},[251,4481,4482],{"class":1072},"name",[251,4484,1075],{"class":1068},[251,4486,4487],{"class":1078},"petstore-api\n",[251,4489,4490,4493,4495],{"class":253,"line":289},[251,4491,4492],{"class":1072},"    url",[251,4494,1075],{"class":1068},[251,4496,4497],{"class":1078},".\u002Fdescriptions\u002Fpetstore.openapi.yml\n",[251,4499,4500,4502,4504],{"class":253,"line":295},[251,4501,2990],{"class":1072},[251,4503,1075],{"class":1068},[251,4505,4506],{"class":1078},"openapi\n",[251,4508,4509,4511,4513,4515],{"class":253,"line":301},[251,4510,1279],{"class":1068},[251,4512,4482],{"class":1072},[251,4514,1075],{"class":1068},[251,4516,4517],{"class":1078},"sales-api\n",[251,4519,4520,4522,4524],{"class":253,"line":307},[251,4521,4492],{"class":1072},[251,4523,1075],{"class":1068},[251,4525,4526],{"class":1078},".\u002Fdescriptions\u002Fsales.openapi.yml\n",[251,4528,4529,4531,4533],{"class":253,"line":313},[251,4530,2990],{"class":1072},[251,4532,1075],{"class":1068},[251,4534,4506],{"class":1078},[251,4536,4537,4540],{"class":253,"line":319},[251,4538,4539],{"class":1072},"workflows",[251,4541,1097],{"class":1068},[251,4543,4544,4546,4549,4551],{"class":253,"line":325},[251,4545,1279],{"class":1068},[251,4547,4548],{"class":1072},"workflowId",[251,4550,1075],{"class":1068},[251,4552,4553],{"class":1078},"OrderingPets\n",[251,4555,4556,4559,4561],{"class":253,"line":331},[251,4557,4558],{"class":1072},"    summary",[251,4560,1075],{"class":1068},[251,4562,4563],{"class":1078},"Workflow for ordering Pets at Example\n",[251,4565,4566,4569],{"class":253,"line":337},[251,4567,4568],{"class":1072},"    inputs",[251,4570,1097],{"class":1068},[251,4572,4573,4575],{"class":253,"line":343},[251,4574,3737],{"class":1072},[251,4576,1097],{"class":1068},[251,4578,4579,4582],{"class":253,"line":349},[251,4580,4581],{"class":1072},"    steps",[251,4583,1097],{"class":1068},[251,4585,4586,4588,4591,4593],{"class":253,"line":355},[251,4587,3462],{"class":1068},[251,4589,4590],{"class":1072},"stepId",[251,4592,1075],{"class":1068},[251,4594,4595],{"class":1078},"listAvailablePets\n",[251,4597,4598,4601,4603],{"class":253,"line":361},[251,4599,4600],{"class":1072},"        description",[251,4602,1075],{"class":1068},[251,4604,4605],{"class":1078},"Show Pet offering to Customer\n",[251,4607,4608,4611,4613],{"class":253,"line":367},[251,4609,4610],{"class":1072},"        operationId",[251,4612,1075],{"class":1068},[251,4614,4615],{"class":1078},"$sourceDescriptions.petstore-api.getPets\n",[251,4617,4618,4621],{"class":253,"line":373},[251,4619,4620],{"class":1072},"        outputs",[251,4622,1097],{"class":1068},[251,4624,4625,4628,4630],{"class":253,"line":379},[251,4626,4627],{"class":1072},"          potentialPetId",[251,4629,1075],{"class":1068},[251,4631,4632],{"class":1078},"$response.body.pets[x].id\n",[251,4634,4635,4637,4639,4641],{"class":253,"line":384},[251,4636,3462],{"class":1068},[251,4638,4590],{"class":1072},[251,4640,1075],{"class":1068},[251,4642,4643],{"class":1078},"getPetInformation\n",[251,4645,4646,4648,4650],{"class":253,"line":390},[251,4647,4600],{"class":1072},[251,4649,1075],{"class":1068},[251,4651,4652],{"class":1078},"Show Pet information to Customer\n",[251,4654,4655,4657,4659],{"class":253,"line":396},[251,4656,4610],{"class":1072},[251,4658,1075],{"class":1068},[251,4660,4661],{"class":1078},"$sourceDescriptions.petstore-api.getPet\n",[251,4663,4664,4667],{"class":253,"line":401},[251,4665,4666],{"class":1072},"        parameters",[251,4668,1097],{"class":1068},[251,4670,4671,4674,4676,4678],{"class":253,"line":407},[251,4672,4673],{"class":1068},"          - ",[251,4675,4482],{"class":1072},[251,4677,1075],{"class":1068},[251,4679,4680],{"class":1078},"pet_id\n",[251,4682,4683,4686,4688],{"class":253,"line":1439},[251,4684,4685],{"class":1072},"            in",[251,4687,1075],{"class":1068},[251,4689,4690],{"class":1078},"query\n",[251,4692,4693,4696,4698],{"class":253,"line":1449},[251,4694,4695],{"class":1072},"            value",[251,4697,1075],{"class":1068},[251,4699,4700],{"class":1078},"$steps.listsPets.outputs.petId\n",[251,4702,4703,4705,4707,4709],{"class":253,"line":1458},[251,4704,3462],{"class":1068},[251,4706,4590],{"class":1072},[251,4708,1075],{"class":1068},[251,4710,4711],{"class":1078},"orderPet\n",[251,4713,4714,4716,4718],{"class":253,"line":1468},[251,4715,4600],{"class":1072},[251,4717,1075],{"class":1068},[251,4719,4720],{"class":1078},"Create an Order for a Pet\n",[251,4722,4723,4725,4727],{"class":253,"line":1475},[251,4724,4610],{"class":1072},[251,4726,1075],{"class":1068},[251,4728,4729],{"class":1078},"$sourceDescriptions.sales-api.createOrder\n",[251,4731,4732],{"class":253,"line":1484},[251,4733,3026],{"class":1220},[251,4735,4736,4738,4740,4742],{"class":253,"line":1494},[251,4737,3462],{"class":1068},[251,4739,4590],{"class":1072},[251,4741,1075],{"class":1068},[251,4743,4744],{"class":1078},"findOrderForPet\n",[251,4746,4747,4749,4751],{"class":253,"line":1506},[251,4748,4600],{"class":1072},[251,4750,1075],{"class":1068},[251,4752,4753],{"class":1078},"Show Order details to Customer related to Pet\n",[251,4755,4756,4758,4760],{"class":253,"line":1513},[251,4757,4610],{"class":1072},[251,4759,1075],{"class":1068},[251,4761,4762],{"class":1078},"$sourceDescriptions.sales-api.getOrder\n",[251,4764,4765],{"class":253,"line":1521},[251,4766,3026],{"class":1220},[11,4768,4769],{},"The result is a layered description that aligns with OAI’s purposeful semantics principle. With the goal to describe “what (… does this do?) and the why (… does this matter?) to the how (… does this work?)”.",[11,4771,4772],{},"I expect that it’ll be just a matter of time before tool developers will offer support for the visualisation of these specifications individually as well as their combined power.",[2509,4774,4776],{"id":4775},"opportunity-3-api-led-customer-journeys","Opportunity #3: API-led Customer Journeys",[11,4778,4779],{},"As you might’ve seen throughout the code snippets above I’ve implemented domain-oriented imports that contain resource descriptions.",[11,4781,4782],{},"I strongly believe in the benefits of a resource-oriented approach for understandability. Add to this clearly separated domain definitions — as described within Domain Driven Design — and it is foreseeable that more of the concepts from this design approach can be applied here.",[11,4784,4785],{},"This adds a tremendous boost to the readability of API descriptions as well as the audience they can be shared with. Especially with a more visual representation I expect API descriptions to become more common throughout business departments\u002Fteams within an organisation.",[11,4787,4788,4789],{},"This will in turn move these specifications towards being used when determining customer journeys. ",[59,4790,4791],{},"Further extending the API-first approach into business development.",[24,4793,4795],{"id":4794},"in-conclusion","In conclusion",[11,4797,4798],{},"I’m very interested in the direction OAI is heading with their new multi-specification approach.",[11,4800,4801,4802,4805],{},"There’s still a lot of room for improvement within the market, especially for ",[59,4803,4804],{},"projects and organisations that are removed further away from the “bleeding edge”."," This world still struggles with consistent API design as well as getting clear API description in the hands of their consumers.",[11,4807,4808,4811],{},[59,4809,4810],{},"For those that are close to the “bleeding edge”, the combination of the specifications offered seem to be a gateway into a whole new era of API-led innovation"," and development with immens potential for those able to leverage it.",[11,4813,4814],{},"Though I’m almost evangelic in my outings, I doubt the scheduled release for Moonwalk will be met by the end of the year. Looking at the latest version available in both branches there is only one real design decision registered.",[11,4816,4817],{},"Additionally, it can become difficult for OAI to keep up with pace of the market now they are spread resources and their interests from one specification to multiple.",[11,4819,4820,4821,4826,4827,1027],{},"So, if you’re interested there are ",[51,4822,4825],{"href":4823,"rel":4824},"https:\u002F\u002Fcalendar.google.com\u002Fcalendar\u002Fu\u002F0\u002Fembed?src=c_fue82vsncog6ahhjvuokjo8qsk%40group.calendar.google.com",[473],"open meetings you can join on every Thursday"," and the ",[14,4828,4829],{},"Moonwalk SIG has a meeting every Tuesday",[11,4831,4832],{},"As with all open source projects all contributions are welcome, so check their website if this sounds interesting and you feel like pitching in!",[11,4834,4835],{},[59,4836,4837],{},"Thanks for reading!",[11,4839,4840],{},[59,4841,4842],{},"Please share your thoughts with me and everyone else in the comments below and feel free to share with your network.",[11,4844,4845],{},"Let’s bring the web together! 🚀",[24,4847,464],{"id":463},[121,4849,4850,4857,4864,4871],{},[124,4851,4852],{},[51,4853,4856],{"href":4854,"rel":4855},"https:\u002F\u002Fwww.openapis.org\u002Fblog\u002F2023\u002F12\u002F06\u002Fopenapi-moonwalk-2024",[473],"Announcement post",[124,4858,4859],{},[51,4860,4863],{"href":4861,"rel":4862},"https:\u002F\u002Fgithub.com\u002FOAI\u002Fsig-moonwalk\u002Ftree\u002Fspecification",[473],"Moonwalk (openapi v4) repository",[124,4865,4866],{},[51,4867,4870],{"href":4868,"rel":4869},"http:\u002F\u002Fopenapi.inf.usi.ch\u002F",[473],"APIstic data overview",[124,4872,4873],{},[51,4874,4876],{"href":4823,"rel":4875},[473],"OpenAPI Initiative technical meeting calendar",[490,4878,4879],{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":144,"searchDepth":145,"depth":145,"links":4881},[4882,4883,4890,4895,4896],{"id":2493,"depth":145,"text":2494},{"id":2503,"depth":145,"text":2504,"children":4884},[4885,4886,4887,4888,4889],{"id":2511,"depth":265,"text":2512},{"id":2617,"depth":265,"text":2618},{"id":3347,"depth":265,"text":3348},{"id":3371,"depth":265,"text":3372},{"id":3547,"depth":265,"text":3548},{"id":3571,"depth":145,"text":3572,"children":4891},[4892,4893,4894],{"id":3578,"depth":265,"text":3579},{"id":3591,"depth":265,"text":3592},{"id":4775,"depth":265,"text":4776},{"id":4794,"depth":145,"text":4795},{"id":463,"depth":145,"text":464},"2024-07-09","OpenAPI version 4 codenamed Moonwalk is scheduled in development. I'll be covering everything you need to know about this new major version.","\u002Farticles\u002Feverything-about-openapi-4\u002Fcover.png",{},"\u002Farticles\u002Feverything-about-openapi-4",{"title":2474,"description":4898},"everything-about-openapi-4","articles\u002Feverything-about-openapi-4",[1807,4460],"6fjozlxzlr-x_9MujdwEFCmAW-vCrKmV0G3xT2bQ0PA",{"id":4908,"title":4909,"body":4910,"date":5806,"description":5807,"extension":154,"image":5808,"imageAuthor":156,"imageLicense":156,"imageSource":156,"meta":5809,"navigation":160,"path":5810,"published":160,"seo":5811,"slug":5812,"stem":5813,"tags":5814,"__hash__":5815},"articles\u002Farticles\u002Fimproving-dx-with-arazzo.md","Improving Developer Experience with OpenAPI's Arazzo Workflow Specification",{"type":8,"value":4911,"toc":5796},[4912,4917,4921,4924,4927,4932,4937,4940,4943,4946,4950,4953,4956,5017,5020,5023,5120,5123,5126,5129,5133,5136,5139,5145,5148,5177,5180,5184,5187,5332,5335,5338,5341,5345,5348,5351,5354,5622,5625,5628,5632,5635,5638,5641,5644,5728,5731,5741,5745,5748,5751,5754,5757,5761,5764,5767,5770,5793],[11,4913,4914],{},[14,4915,4916],{},"We explore how OpenAPI’s Arazzo Specification attempts to redefine API documentation by clarifying call sequences and dependencies improving Developer Experience.",[24,4918,4920],{"id":4919},"the-ongoing-quest-for-language-agnostic-specifications","The ongoing quest for language-agnostic specifications",[11,4922,4923],{},"The OpenAPI Initiative (OAI) is known for the OpenAPI Specification (OAS) standard which we can consider the de facto standard for describing HTTP APIs. Whether you’re a proponent or not, you can’t deny the global presence and adoption of this specification standard.",[11,4925,4926],{},"This standard isn’t perfect by any means but it offers many benefits when implemented consistently within an organisation.",[11,4928,4929],{},[59,4930,4931],{},"Within API development there is a growing need for a more extensive way to describe and manage workflows.",[11,4933,4934],{},[59,4935,4936],{},"The increasing complexity of the underlying business processes as well as the number of available APIs can be detrimental to the developer experience on the consumer side.",[11,4938,4939],{},"API specifications struggle to express the dependencies between sequences of calls to get specific outcomes. The Arazzo Specification fills this gap by offering a method to define workflows in formats readable by both humans and machines.",[11,4941,4942],{},"This specification improves the developer experience by providing clearer, more comprehensive API documentation. It helps developers grasp and handle complex interactions within an API, making API descriptions more usable and efficient, thus streamlining development processes.",[11,4944,4945],{},"Let’s take a brief look at the OpenAPI Specification first",[24,4947,4949],{"id":4948},"shortcomings-of-openapi","Shortcomings of OpenAPI",[11,4951,4952],{},"Besides the margin for implementation inconsistencies and design fallicies does the standard have no way of expressing context. Operations within APIs are rarely used in isolation or any other context. A true REST API should be stateless in it technical implementation but that doesn’t eliminate the presence of business context.",[11,4954,4955],{},"Consider our beloved Pet Store.",[243,4957,4959],{"className":1053,"code":4958,"language":1055,"meta":144,"style":144},"# pet-api-specification.yaml\npaths:\n  \u002Fv1\u002Fpets:\n    get:\n  \u002Fv1\u002Forders:\n    get:\n    post:\n  \u002Fv1\u002Fcoupons:\n    get:\n",[206,4960,4961,4966,4972,4979,4985,4992,4998,5004,5011],{"__ignoreMap":144},[251,4962,4963],{"class":253,"line":254},[251,4964,4965],{"class":1062},"# pet-api-specification.yaml\n",[251,4967,4968,4970],{"class":253,"line":145},[251,4969,2680],{"class":1072},[251,4971,1097],{"class":1068},[251,4973,4974,4977],{"class":253,"line":265},[251,4975,4976],{"class":1072},"  \u002Fv1\u002Fpets",[251,4978,1097],{"class":1068},[251,4980,4981,4983],{"class":253,"line":271},[251,4982,2827],{"class":1072},[251,4984,1097],{"class":1068},[251,4986,4987,4990],{"class":253,"line":277},[251,4988,4989],{"class":1072},"  \u002Fv1\u002Forders",[251,4991,1097],{"class":1068},[251,4993,4994,4996],{"class":253,"line":283},[251,4995,2827],{"class":1072},[251,4997,1097],{"class":1068},[251,4999,5000,5002],{"class":253,"line":289},[251,5001,2694],{"class":1072},[251,5003,1097],{"class":1068},[251,5005,5006,5009],{"class":253,"line":295},[251,5007,5008],{"class":1072},"  \u002Fv1\u002Fcoupons",[251,5010,1097],{"class":1068},[251,5012,5013,5015],{"class":253,"line":301},[251,5014,2827],{"class":1072},[251,5016,1097],{"class":1068},[11,5018,5019],{},"Interpreting how to create an Order for a Pet using a Coupon using the description above could be done intuitively. Though in practice it turns out intuitive and readable specifications are not that common.",[11,5021,5022],{},"Consider the following API description.",[243,5024,5026],{"className":1053,"code":5025,"language":1055,"meta":144,"style":144},"# created with the intend to aggrevate readers\npaths:\n  \u002Fpet\u002FgetPet:\n    get:\n  \u002Fpets:\n    get:\n  \u002Forders:\n    post:\n  \u002Forders\u002ForderPet:\n    post:\n  \u002Fdiscounts:\n    get: # \u003C- you need to call this endpoint\n  \u002Fdiscounts\u002Fcoupons:\n    post:\n",[206,5027,5028,5033,5039,5046,5052,5059,5065,5072,5078,5085,5091,5098,5107,5114],{"__ignoreMap":144},[251,5029,5030],{"class":253,"line":254},[251,5031,5032],{"class":1062},"# created with the intend to aggrevate readers\n",[251,5034,5035,5037],{"class":253,"line":145},[251,5036,2680],{"class":1072},[251,5038,1097],{"class":1068},[251,5040,5041,5044],{"class":253,"line":265},[251,5042,5043],{"class":1072},"  \u002Fpet\u002FgetPet",[251,5045,1097],{"class":1068},[251,5047,5048,5050],{"class":253,"line":271},[251,5049,2827],{"class":1072},[251,5051,1097],{"class":1068},[251,5053,5054,5057],{"class":253,"line":277},[251,5055,5056],{"class":1072},"  \u002Fpets",[251,5058,1097],{"class":1068},[251,5060,5061,5063],{"class":253,"line":283},[251,5062,2827],{"class":1072},[251,5064,1097],{"class":1068},[251,5066,5067,5070],{"class":253,"line":289},[251,5068,5069],{"class":1072},"  \u002Forders",[251,5071,1097],{"class":1068},[251,5073,5074,5076],{"class":253,"line":295},[251,5075,2694],{"class":1072},[251,5077,1097],{"class":1068},[251,5079,5080,5083],{"class":253,"line":301},[251,5081,5082],{"class":1072},"  \u002Forders\u002ForderPet",[251,5084,1097],{"class":1068},[251,5086,5087,5089],{"class":253,"line":307},[251,5088,2694],{"class":1072},[251,5090,1097],{"class":1068},[251,5092,5093,5096],{"class":253,"line":313},[251,5094,5095],{"class":1072},"  \u002Fdiscounts",[251,5097,1097],{"class":1068},[251,5099,5100,5102,5104],{"class":253,"line":319},[251,5101,2827],{"class":1072},[251,5103,1075],{"class":1068},[251,5105,5106],{"class":1062},"# \u003C- you need to call this endpoint\n",[251,5108,5109,5112],{"class":253,"line":325},[251,5110,5111],{"class":1072},"  \u002Fdiscounts\u002Fcoupons",[251,5113,1097],{"class":1068},[251,5115,5116,5118],{"class":253,"line":331},[251,5117,2694],{"class":1072},[251,5119,1097],{"class":1068},[11,5121,5122],{},"This API description becomes murkier and harder to grasp without reaching for documentation or fellow developer.",[11,5124,5125],{},"Sure, we all have an idea on intuitive API design but reality is that especially over time the implementations and descriptions we have to deal with a far from ideal. This makes it more important to be able to understand the context.",[11,5127,5128],{},"This context usually results in a dependency between specific calls in order to achieve a particular goal. The OAS contains no specification to describe this behavior. The OpenAPI Initiative has been developing the Arazzo Specification for this specific use case to which I’ll be giving an introduction within this post.",[24,5130,5132],{"id":5131},"compensating-features-of-arazzo","Compensating features of Arazzo",[11,5134,5135],{},"Arazzo is intended to be implemented using an OpenAPI Specification. I’m not too keen on the design choice of adding a specification alongside the OAS file. Though considering expanding the already broad OAS with more capabilities doesn’t seem to be the superior choice either.",[11,5137,5138],{},"The specification prescribes a file structure similar to an OAS:",[11,5140,5141],{},[1585,5142],{"alt":5143,"src":5144},"OAI Arazzo Structure","https:\u002F\u002Fgithub.com\u002FOAI\u002FArazzo-Specification\u002Fraw\u002Fmain\u002Fimages\u002FArazzo-Specification-Structure.png",[11,5146,5147],{},"Core components of an Arazzo Specification are:",[121,5149,5150,5153,5156,5159,5162,5165,5168,5171,5174],{},[124,5151,5152],{},"sourceDescription: used to import OpenAPI specifications or other Arazzo specifications to implement components of other files",[124,5154,5155],{},"workflows: core component of Arazzo describing a specific use case",[124,5157,5158],{},"inputs: JSON schema representing input parameters",[124,5160,5161],{},"parameters: parameters applicable throughout the whole workflow",[124,5163,5164],{},"success actions: Object describing the action to execute when successful",[124,5166,5167],{},"failure actions: Object describing the action to execute when a failure occurs",[124,5169,5170],{},"steps: Object containing individual activities within a workflow",[124,5172,5173],{},"components: Object containing reusable Arazzo Components",[124,5175,5176],{},"criterion: Object offering the main support for business logic-related implementations. Supports simple, regex and JSONPath expressions",[11,5178,5179],{},"You get a grasp of the intent with Arazzo given these object. Lets take a look at three of the features Arazzo offers.",[24,5181,5183],{"id":5182},"leverage-existing-specifications-with-sourcedescriptions","Leverage existing specifications with sourceDescriptions",[11,5185,5186],{},"Arazzo intends to leverage the API and workflow specifications you already have. Albeit limited to specifications using their own standards (‘arazzo’ and ‘openapi’). This feature enables arbitrary naming of external sources and referencing existing Components using their identifiers.",[243,5188,5190],{"className":1053,"code":5189,"language":1055,"meta":144,"style":144},"# openapi.yaml\npaths:\n  \u002Fv1\u002Fpets\u002F{id}:\n    get:\n      operationId: getSpecificPet\n\n# arazzo.yaml\narazzo: 1.0.0\nsourceDescriptions:\n  - name: apiDescription\n    url: https:\u002F\u002F\u003Cdomain>\u002Fapi\u002Fpetstore\u002Fopenapi.yaml\n    type: openapi\nworkflows:\n  - workflowId: retrieveAndOrderPet\n    summary: Workflow to retrieve and order a specific Pet\n    steps:\n      - stepId: retrievePet\n        operationId: apiDescription.getSpecificPet # referencing sources\n",[206,5191,5192,5197,5203,5210,5216,5226,5230,5235,5243,5249,5260,5269,5277,5283,5294,5303,5309,5320],{"__ignoreMap":144},[251,5193,5194],{"class":253,"line":254},[251,5195,5196],{"class":1062},"# openapi.yaml\n",[251,5198,5199,5201],{"class":253,"line":145},[251,5200,2680],{"class":1072},[251,5202,1097],{"class":1068},[251,5204,5205,5208],{"class":253,"line":265},[251,5206,5207],{"class":1072},"  \u002Fv1\u002Fpets\u002F{id}",[251,5209,1097],{"class":1068},[251,5211,5212,5214],{"class":253,"line":271},[251,5213,2827],{"class":1072},[251,5215,1097],{"class":1068},[251,5217,5218,5221,5223],{"class":253,"line":277},[251,5219,5220],{"class":1072},"      operationId",[251,5222,1075],{"class":1068},[251,5224,5225],{"class":1078},"getSpecificPet\n",[251,5227,5228],{"class":253,"line":283},[251,5229,328],{"emptyLinePlaceholder":160},[251,5231,5232],{"class":253,"line":289},[251,5233,5234],{"class":1062},"# arazzo.yaml\n",[251,5236,5237,5239,5241],{"class":253,"line":295},[251,5238,4460],{"class":1072},[251,5240,1075],{"class":1068},[251,5242,1221],{"class":1220},[251,5244,5245,5247],{"class":253,"line":301},[251,5246,4473],{"class":1072},[251,5248,1097],{"class":1068},[251,5250,5251,5253,5255,5257],{"class":253,"line":307},[251,5252,1279],{"class":1068},[251,5254,4482],{"class":1072},[251,5256,1075],{"class":1068},[251,5258,5259],{"class":1078},"apiDescription\n",[251,5261,5262,5264,5266],{"class":253,"line":313},[251,5263,4492],{"class":1072},[251,5265,1075],{"class":1068},[251,5267,5268],{"class":1078},"https:\u002F\u002F\u003Cdomain>\u002Fapi\u002Fpetstore\u002Fopenapi.yaml\n",[251,5270,5271,5273,5275],{"class":253,"line":319},[251,5272,2990],{"class":1072},[251,5274,1075],{"class":1068},[251,5276,4506],{"class":1078},[251,5278,5279,5281],{"class":253,"line":325},[251,5280,4539],{"class":1072},[251,5282,1097],{"class":1068},[251,5284,5285,5287,5289,5291],{"class":253,"line":331},[251,5286,1279],{"class":1068},[251,5288,4548],{"class":1072},[251,5290,1075],{"class":1068},[251,5292,5293],{"class":1078},"retrieveAndOrderPet\n",[251,5295,5296,5298,5300],{"class":253,"line":337},[251,5297,4558],{"class":1072},[251,5299,1075],{"class":1068},[251,5301,5302],{"class":1078},"Workflow to retrieve and order a specific Pet\n",[251,5304,5305,5307],{"class":253,"line":343},[251,5306,4581],{"class":1072},[251,5308,1097],{"class":1068},[251,5310,5311,5313,5315,5317],{"class":253,"line":349},[251,5312,3462],{"class":1068},[251,5314,4590],{"class":1072},[251,5316,1075],{"class":1068},[251,5318,5319],{"class":1078},"retrievePet\n",[251,5321,5322,5324,5326,5329],{"class":253,"line":355},[251,5323,4610],{"class":1072},[251,5325,1075],{"class":1068},[251,5327,5328],{"class":1078},"apiDescription.getSpecificPet",[251,5330,5331],{"class":1062}," # referencing sources\n",[11,5333,5334],{},"Using sourceDescriptions enables developers to focus on specifying the workflow and not on the details of the API itself.",[11,5336,5337],{},"Though it begs the question: “How resilient is this added specification to change over time?”",[11,5339,5340],{},"Since the Arazzo specification now depends on the structure and content of the API description we have yet another document to validate before implementing changes. The identifiers of components are presumably stable, but when the Arazzo specification relies on request or response body structures this stability is lesser.",[24,5342,5344],{"id":5343},"deterministic-sequences-with-workflows","Deterministic sequences with workflows",[11,5346,5347],{},"Usually I am not a particular fan of the PetStore example. Mainly because it tends to over simplify specifications and use cases encountered “out in the field”.",[11,5349,5350],{},"For example the implementation of security-related endpoints for authentication and authorization. Even though OAuth 2.0 and OpenID connect have a formal specification on how to be implemented, in practice small deviations and interpretations tend to sneak in.",[11,5352,5353],{},"The core feature Arazzo offers drastically helps improve the Developer Experience when it comes to actually consuming the specified APIs. Let’s take a look at an example from the OAI repository that describes how to obtain a token from an OAuth 2.0 and OpenID Connect authorization server.",[243,5355,5357],{"className":1053,"code":5356,"language":1055,"meta":144,"style":144},"arazzo: 1.0.0\nworkflows:\n  - workflowId: OIDC-authorize-AuthzCode-PAR\n    summary: Getting an Access Token using a PAR and Authorization Code\n    inputs:\n        ... # list of inputs\n    steps:\n      - stepId: executePushedAuthorizationRequest\n        description: Pushed Authorization Request\n        operationId: $sourceDescriptions.auth-api.PAR\n        ...\n        requestBody:\n          payload: $inputs.PARrequestBody\n        successCriteria:\n          # assertions to determine step was successful\n          - condition: $statusCode == 200\n        ...\n      - stepId: getAuthorizationCode\n        description: OIDC Authorization code request\n        operationId: $sourceDescriptions.auth-api.Authorization\n        ...\n        successCriteria:\n          # assertions to determine step was successful\n          - condition: $statusCode == 302\n      - stepId: exchangeAuthorizationCodeForToken\n        description: Get token from the OIDC Token endpoint\n        ...\n        successCriteria:\n          # assertions to determine step was successful\n          - condition: $statusCode == 200\n        outputs:\n          tokenResponse: $response.body\n    outputs:\n      access_token: $steps.TokenStep.outputs.tokenResponse\n",[206,5358,5359,5367,5373,5384,5393,5399,5407,5413,5424,5433,5442,5446,5453,5463,5470,5475,5487,5491,5502,5511,5520,5524,5530,5534,5545,5556,5565,5569,5575,5579,5589,5595,5605,5612],{"__ignoreMap":144},[251,5360,5361,5363,5365],{"class":253,"line":254},[251,5362,4460],{"class":1072},[251,5364,1075],{"class":1068},[251,5366,1221],{"class":1220},[251,5368,5369,5371],{"class":253,"line":145},[251,5370,4539],{"class":1072},[251,5372,1097],{"class":1068},[251,5374,5375,5377,5379,5381],{"class":253,"line":265},[251,5376,1279],{"class":1068},[251,5378,4548],{"class":1072},[251,5380,1075],{"class":1068},[251,5382,5383],{"class":1078},"OIDC-authorize-AuthzCode-PAR\n",[251,5385,5386,5388,5390],{"class":253,"line":271},[251,5387,4558],{"class":1072},[251,5389,1075],{"class":1068},[251,5391,5392],{"class":1078},"Getting an Access Token using a PAR and Authorization Code\n",[251,5394,5395,5397],{"class":253,"line":277},[251,5396,4568],{"class":1072},[251,5398,1097],{"class":1068},[251,5400,5401,5404],{"class":253,"line":283},[251,5402,5403],{"class":1220},"        ...",[251,5405,5406],{"class":1062}," # list of inputs\n",[251,5408,5409,5411],{"class":253,"line":289},[251,5410,4581],{"class":1072},[251,5412,1097],{"class":1068},[251,5414,5415,5417,5419,5421],{"class":253,"line":295},[251,5416,3462],{"class":1068},[251,5418,4590],{"class":1072},[251,5420,1075],{"class":1068},[251,5422,5423],{"class":1078},"executePushedAuthorizationRequest\n",[251,5425,5426,5428,5430],{"class":253,"line":301},[251,5427,4600],{"class":1072},[251,5429,1075],{"class":1068},[251,5431,5432],{"class":1078},"Pushed Authorization Request\n",[251,5434,5435,5437,5439],{"class":253,"line":307},[251,5436,4610],{"class":1072},[251,5438,1075],{"class":1068},[251,5440,5441],{"class":1078},"$sourceDescriptions.auth-api.PAR\n",[251,5443,5444],{"class":253,"line":313},[251,5445,3026],{"class":1220},[251,5447,5448,5451],{"class":253,"line":319},[251,5449,5450],{"class":1072},"        requestBody",[251,5452,1097],{"class":1068},[251,5454,5455,5458,5460],{"class":253,"line":325},[251,5456,5457],{"class":1072},"          payload",[251,5459,1075],{"class":1068},[251,5461,5462],{"class":1078},"$inputs.PARrequestBody\n",[251,5464,5465,5468],{"class":253,"line":331},[251,5466,5467],{"class":1072},"        successCriteria",[251,5469,1097],{"class":1068},[251,5471,5472],{"class":253,"line":337},[251,5473,5474],{"class":1062},"          # assertions to determine step was successful\n",[251,5476,5477,5479,5482,5484],{"class":253,"line":343},[251,5478,4673],{"class":1068},[251,5480,5481],{"class":1072},"condition",[251,5483,1075],{"class":1068},[251,5485,5486],{"class":1078},"$statusCode == 200\n",[251,5488,5489],{"class":253,"line":349},[251,5490,3026],{"class":1220},[251,5492,5493,5495,5497,5499],{"class":253,"line":355},[251,5494,3462],{"class":1068},[251,5496,4590],{"class":1072},[251,5498,1075],{"class":1068},[251,5500,5501],{"class":1078},"getAuthorizationCode\n",[251,5503,5504,5506,5508],{"class":253,"line":361},[251,5505,4600],{"class":1072},[251,5507,1075],{"class":1068},[251,5509,5510],{"class":1078},"OIDC Authorization code request\n",[251,5512,5513,5515,5517],{"class":253,"line":367},[251,5514,4610],{"class":1072},[251,5516,1075],{"class":1068},[251,5518,5519],{"class":1078},"$sourceDescriptions.auth-api.Authorization\n",[251,5521,5522],{"class":253,"line":373},[251,5523,3026],{"class":1220},[251,5525,5526,5528],{"class":253,"line":379},[251,5527,5467],{"class":1072},[251,5529,1097],{"class":1068},[251,5531,5532],{"class":253,"line":384},[251,5533,5474],{"class":1062},[251,5535,5536,5538,5540,5542],{"class":253,"line":390},[251,5537,4673],{"class":1068},[251,5539,5481],{"class":1072},[251,5541,1075],{"class":1068},[251,5543,5544],{"class":1078},"$statusCode == 302\n",[251,5546,5547,5549,5551,5553],{"class":253,"line":396},[251,5548,3462],{"class":1068},[251,5550,4590],{"class":1072},[251,5552,1075],{"class":1068},[251,5554,5555],{"class":1078},"exchangeAuthorizationCodeForToken\n",[251,5557,5558,5560,5562],{"class":253,"line":401},[251,5559,4600],{"class":1072},[251,5561,1075],{"class":1068},[251,5563,5564],{"class":1078},"Get token from the OIDC Token endpoint\n",[251,5566,5567],{"class":253,"line":407},[251,5568,3026],{"class":1220},[251,5570,5571,5573],{"class":253,"line":1439},[251,5572,5467],{"class":1072},[251,5574,1097],{"class":1068},[251,5576,5577],{"class":253,"line":1449},[251,5578,5474],{"class":1062},[251,5580,5581,5583,5585,5587],{"class":253,"line":1458},[251,5582,4673],{"class":1068},[251,5584,5481],{"class":1072},[251,5586,1075],{"class":1068},[251,5588,5486],{"class":1078},[251,5590,5591,5593],{"class":253,"line":1468},[251,5592,4620],{"class":1072},[251,5594,1097],{"class":1068},[251,5596,5597,5600,5602],{"class":253,"line":1475},[251,5598,5599],{"class":1072},"          tokenResponse",[251,5601,1075],{"class":1068},[251,5603,5604],{"class":1078},"$response.body\n",[251,5606,5607,5610],{"class":253,"line":1484},[251,5608,5609],{"class":1072},"    outputs",[251,5611,1097],{"class":1068},[251,5613,5614,5617,5619],{"class":253,"line":1494},[251,5615,5616],{"class":1072},"      access_token",[251,5618,1075],{"class":1068},[251,5620,5621],{"class":1078},"$steps.TokenStep.outputs.tokenResponse\n",[11,5623,5624],{},"Naming of some components aside — the workflow immediately becomes more understandable and accessible for developers. At least the intend from the producer side is conveyed explicitly.",[11,5626,5627],{},"Especially the ability to be able to convey your intend as a producer with the workflow specification is a huge improvement to the Developer Experience on the consumer side.",[24,5629,5631],{"id":5630},"natural-language-as-gateway-to-http-apis-for-large-language-models-llms","Natural Language as gateway to HTTP APIs for Large Language Models (LLMs)",[11,5633,5634],{},"Introducing a specification that explains the intended implementation of APIs using natural language indicates a shift to emphasize machine-readability. Which shouldn’t come as a shock to most as the majority of the industry is determining if they want to do anything AI-related and if so, in what that should be.",[11,5636,5637],{},"The OpenAPI Initiative clearly takes a pre-emptive move towards embracing LLMs as part of the integration industry with the exploration of this workflow specification standard.",[11,5639,5640],{},"With the introduction of custom GPTs at OpenAI they promote the usage of the OpenAPI Specification to document your API in order for a pretrained model to ‘understand’ it. It is even possible to extend the OAS with x-openai-isConsequential.",[11,5642,5643],{},"This flag indicates that any model MUST prompt the user for confirmation before calling the endpoint.",[243,5645,5647],{"className":1053,"code":5646,"language":1055,"meta":144,"style":144},"paths:\n  \u002Ftodo:\n    get:\n      operationId: getTODOs\n      description: Fetches items in a TODO list from the API.\n      security: []\n    post:\n      operationId: updateTODOs\n      description: Mutates the TODO list.\n      x-openai-isConsequential: true\n",[206,5648,5649,5655,5662,5668,5677,5687,5694,5700,5709,5718],{"__ignoreMap":144},[251,5650,5651,5653],{"class":253,"line":254},[251,5652,2680],{"class":1072},[251,5654,1097],{"class":1068},[251,5656,5657,5660],{"class":253,"line":145},[251,5658,5659],{"class":1072},"  \u002Ftodo",[251,5661,1097],{"class":1068},[251,5663,5664,5666],{"class":253,"line":265},[251,5665,2827],{"class":1072},[251,5667,1097],{"class":1068},[251,5669,5670,5672,5674],{"class":253,"line":271},[251,5671,5220],{"class":1072},[251,5673,1075],{"class":1068},[251,5675,5676],{"class":1078},"getTODOs\n",[251,5678,5679,5682,5684],{"class":253,"line":277},[251,5680,5681],{"class":1072},"      description",[251,5683,1075],{"class":1068},[251,5685,5686],{"class":1078},"Fetches items in a TODO list from the API.\n",[251,5688,5689,5692],{"class":253,"line":283},[251,5690,5691],{"class":1072},"      security",[251,5693,3468],{"class":1068},[251,5695,5696,5698],{"class":253,"line":289},[251,5697,2694],{"class":1072},[251,5699,1097],{"class":1068},[251,5701,5702,5704,5706],{"class":253,"line":295},[251,5703,5220],{"class":1072},[251,5705,1075],{"class":1068},[251,5707,5708],{"class":1078},"updateTODOs\n",[251,5710,5711,5713,5715],{"class":253,"line":301},[251,5712,5681],{"class":1072},[251,5714,1075],{"class":1068},[251,5716,5717],{"class":1078},"Mutates the TODO list.\n",[251,5719,5720,5723,5725],{"class":253,"line":307},[251,5721,5722],{"class":1072},"      x-openai-isConsequential",[251,5724,1075],{"class":1068},[251,5726,5727],{"class":1220},"true\n",[11,5729,5730],{},"Who knows how long it will take to get a scarily reasonable answer to prompts like this:",[533,5732,5733],{},[11,5734,5735,5736,5740],{},"“Create an end-to-end implementation for a Pet ordering feature within my Vuetify webapp. Find a suiting API specification at ",[51,5737,5738],{"href":5738,"rel":5739},"https:\u002F\u002Fmy-company\u002Fapis\u002Fdiscovery",[473]," that is able to provide the right data and functionality. Use the workspace context to determine the Pet and Order representation within our application. Ensure that our model stays separated from the domain of whatever source system you integrate with and handle mapping within the intended mechanic Vue offers.”",[24,5742,5744],{"id":5743},"arazzo-the-be-all-and-end-all-of-api-descriptions","Arazzo, the be-all and end-all of API descriptions?",[11,5746,5747],{},"Arazzo’s ambitious attempt to improve the Developer Experience and machine-readability of API descriptions is very promising in theory.",[11,5749,5750],{},"I do think that it answers the need developers can have for contextual information and producer intent.",[11,5752,5753],{},"Although I have major concerns on the maintainability of the implementation over time as well as the still present wiggle-room within the specification itself. Similarly to the OpenAPI Specification, it leaves too much room for inconsistency and small errors to pop-up. Which will lead to the never expanding need for additional tooling to lint, check or validate the contents of yet another file in yet another way.",[11,5755,5756],{},"I’ll definitely be keeping an eye out for the further development and implementation of Arazzo in the near future.",[24,5758,5760],{"id":5759},"further-reading-and-resources","Further reading and resources",[11,5762,5763],{},"Do you struggle with leveraging the full potential of APIs within your organisation? “I happen to be something of an API architect myself”.",[11,5765,5766],{},"Reach out to me or one of my colleagues if you’re interested and be sure to leave your opinion and insights on the development of the industry as well.",[11,5768,5769],{},"Not done reading? Here’s some more in-depth and interesting stuff to catch up on:",[121,5771,5772,5779,5786],{},[124,5773,5774],{},[51,5775,5778],{"href":5776,"rel":5777},"https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Factions\u002Fgetting-started",[473],"OpenAI getting started with Actions",[124,5780,5781],{},[51,5782,5785],{"href":5783,"rel":5784},"https:\u002F\u002Fspec.openapis.org\u002Farazzo\u002Flatest.html#arazzo-specification",[473],"OpenAPI’s Arazzo Specification Github",[124,5787,5788],{},[51,5789,5792],{"href":5790,"rel":5791},"https:\u002F\u002Fappythings.com\u002Fai-is-changing-the-api-game.html",[473],"My colleague on generative AI",[490,5794,5795],{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}",{"title":144,"searchDepth":145,"depth":145,"links":5797},[5798,5799,5800,5801,5802,5803,5804,5805],{"id":4919,"depth":145,"text":4920},{"id":4948,"depth":145,"text":4949},{"id":5131,"depth":145,"text":5132},{"id":5182,"depth":145,"text":5183},{"id":5343,"depth":145,"text":5344},{"id":5630,"depth":145,"text":5631},{"id":5743,"depth":145,"text":5744},{"id":5759,"depth":145,"text":5760},"2024-06-17","Arazzo is a new open-source project that aims to improve developer experience by providing a specification for workflows using OpenAPI. In this article, we will explore the key features and benefits of Arazzo, and how it can help developers create better workflows in their applications.","\u002Farticles\u002Fimproving-dx-with-arazzo\u002Fcover.png",{},"\u002Farticles\u002Fimproving-dx-with-arazzo",{"title":4909,"description":5807},"improving-dx-with-arazzo","articles\u002Fimproving-dx-with-arazzo",[1807,4460,167,168],"Nwz0J21ATF9-HqQDiDjuCYru3p8OSdmS6IIhUiodPtM",{"id":5817,"title":5818,"body":5819,"date":5989,"description":5990,"extension":154,"image":5991,"imageAuthor":5992,"imageLicense":750,"imageSource":5993,"meta":5994,"navigation":160,"path":5995,"published":160,"seo":5996,"slug":5997,"stem":5998,"tags":5999,"__hash__":6004},"articles\u002Farticles\u002Fblockchain-in-afrika.md","Blockchain in Afrika",{"type":8,"value":5820,"toc":5982},[5821,5824,5827,5830,5833,5842,5850,5854,5863,5866,5869,5872,5875,5878,5882,5885,5890,5893,5896,5904,5908,5911,5916,5919,5927,5933,5937,5940,5943,5946,5949,5952,5957,5961,5964,5967,5970,5973,5976,5979],[11,5822,5823],{},"In mijn tweede post heb ik geschreven over het brede spectrum aan verschillende crypto die tegenwoordig bestaan. Hierbij lag de nadruk op de waarde van deze crypto.",[11,5825,5826],{},"Dit is vaak het enige waar mensen aan denken wanneer ze crypto, bitcoin of blockchain horen. Voor een overgroot deel van de projecten is dit ook het doel. Zo is Bitcoin in het leven geroepen als digitale vorm van cash dat gebruikt kan worden om betalingen te doen.",[11,5828,5829],{},"Vooral met de aanwas van nieuwe mensen die interesse hebben in het verdienen van geld met crypto zien we een wildgroei aan allerlei projecten die hier enkel op inspelen.",[11,5831,5832],{},"In deze blogpost leg ik de nadruk op één van de vele voorbeelden van projecten die een ander doel hebben dan uitsluitend transacties mogelijk maken.",[11,5834,5835,5836,5841],{},"Dit platform heet ",[51,5837,5840],{"href":5838,"rel":5839},"https:\u002F\u002Fcardano.org",[473],"Cardano",". Het heeft ook een eigen valuta genaamd ADA wat gebruikt wordt om handelingen uit te voeren, het Cardano netwerk te beveiligen, transacties te doen en meer.",[11,5843,5844,5845,1027],{},"De reden dat ik stil wil staan bij dit project is vanwege de ontwikkelingen in de afgelopen maand. Cardano gaat gebruikt worden om een poging te doen de wereld voor een deel van de ",[51,5846,5849],{"href":5847,"rel":5848},"https:\u002F\u002Fafrica.cardano.org",[473],"Afrikaanse jeugd volledig te veranderen",[24,5851,5853],{"id":5852},"digitale-wereld-met-meer-gelijke-kansen","Digitale wereld met meer gelijke kansen",[11,5855,5856,5857,5862],{},"De bedenker en ontwikkelaar van Cardano, Charles Hoskinson, is al jaren bezig met de strijd voor gelijke kansen op de wereld. Zo sprak hij jaren geleden al op ",[51,5858,5861],{"href":5859,"rel":5860},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=97ufCT6lQcY",[473],"TED"," over de verschillen tussen eerste en derde wereldlanden en de oorsprong van deze verschillen.",[11,5864,5865],{},"Voor iedereen die geen 13 minuten heeft om de bovenstaande video te kijken: Hoskinson spreekt over de impact van bankieren en documentatie op de kwaliteit van leven.",[11,5867,5868],{},"De eerste wereldlanden - lees VS en EU - hebben alle voorzieningen om hun geldzaken te regelen, kadasters en registers waarin eigendom wordt bijgehouden en meer.",[11,5870,5871],{},"Maar in een groot deel van de wereld is dit niet hetzelfde geval. Zo is het voor de inwoners van Soedan niet vanzelfsprekend dat hun identiteit, financiële geschiedenis en eigendom vastgelegd is of blijft.",[11,5873,5874],{},"Hoe toon je aan dat iets van jou is? Wat kun je doen als een corrupte overheid ervoor zorgt dat gegevens niet meer beschikbaar zijn of niet meer bestaan?",[11,5876,5877],{},"Een nog schrikwekkendere vraag: hoe toon je aan wie je bent?",[24,5879,5881],{"id":5880},"eigendom-en-identificatie","Eigendom en identificatie",[11,5883,5884],{},"De impact van deze onderwerpen is gigantisch. Het hindert niet alleen de mogelijkheden en ontwikkelingen van inwoners van deze landen. Het beperkt daarnaast ook de kansen en mogelijkheden van deze mensen in andere landen.",[11,5886,5887],{},[59,5888,5889],{},"Iedereen in deze situatie heeft problemen met zijn of haar economische identiteit en er is geen sprake van financiële inclusiviteit.",[11,5891,5892],{},"Jouw economische identiteit moet je in staat stellen aan te tonen wat je bezit en zorgt voor de beschikking over financiële middelen.",[11,5894,5895],{},"Financiële inclusiviteit betekent dat iedereen dezelfde mate van toegang heeft tot financiële middelen. Dit betekent niet zozeer dat geld lenen direct mogelijk is, maar dan het mogelijk moet zijn om überhaupt het gesprek te voeren hierover.",[11,5897,5898,5903],{},[51,5899,5902],{"href":5900,"rel":5901},"https:\u002F\u002Fwww.dnb.nl\u002Factuele-economische-vraagstukken\u002Fhypotheekschuld\u002F#:~:text=De%20meeste%20Nederlanders%20sluiten%20hiervoor,van%20de%20hele%20Europese%20Unie.&text=Half%202020%20hadden%20Nederlandse%20huishoudens%20samen%20ruim%20EUR%20740%20miljard%20aan%20hypotheekschuld.",[473],"In Nederland heeft een overgroot deel van de huiseigenaren een hypotheek"," gebruikt om aan dat huis te komen. Wat betekent dat een groot deel van het leven dat wij leiden mede mogelijk gemaakt wordt door de toegang die we hebben tot financiële middelen.",[24,5905,5907],{"id":5906},"de-rol-van-een-blockchain","De rol van een blockchain",[11,5909,5910],{},"De situatie in Afrika is grimmiger dan die wij kennen in Nederland. De kans op een burgeroorlog of grootschalige corruptie is daar vele malen groter en realistischer dan hier.",[11,5912,5913],{},[59,5914,5915],{},"Maar wat kan een blockchain hierin betekenen?",[11,5917,5918],{},"De oprichters en groot deel van de ontwikkelaars achter Cardano zijn een project gestart met de Ethiopische overheid om een systeem te ontwikkelen dat kan integreren met Cardano.",[11,5920,5921,5926],{},[51,5922,5925],{"href":5923,"rel":5924},"https:\u002F\u002Fatalaprism.io\u002Fapp\u002Fcredentials",[473],"Dit systeem"," moet het mogelijk maken om de identiteit van studenten en hun behaalde resultaten op een toekomst bestendige manier te documenteren. Voor veel mensen in Afrika worden de mogelijkheden beperkt door de gebrekkige infrastructuur die daar momenteel aanwezig is.",[11,5928,5929,5930],{},"Gegevens kunnen niet teruggevonden worden waardoor kansen, ook in het buitenland, beperkt worden. Deze oplossing moet het ook mogelijk maken dat ",[59,5931,5932],{},"iedereen eigenaar wordt van zijn of haar digitale identiteit.",[24,5934,5936],{"id":5935},"een-volgende-stap-voor-iedereen","Een volgende stap voor iedereen?",[11,5938,5939],{},"Dat laatste is een heel interessant onderwerp. Eigenaar zijn van jouw digitale identiteit. Dat is iets wat momenteel nergens het geval is.",[11,5941,5942],{},"Al kennen we in Nederland een oplossing voor het digitaal beschikbaar stellen van persoonsgevens in de vorm van DigiD. Het probleem daarbij is dat jij hier geen eigenaar van bent.",[11,5944,5945],{},"Tegenwoordig worden bijna elke week nieuwe datalekken gemeld waarbij persoonsgegevens van mensen op straat komen te liggen. Dit is opzich niet verassend aangezien elke partij die NAW gegevens nodig heeft, zelf moet zorgen voor de beveiliging van die gegevens.",[11,5947,5948],{},"Doordat deze partijen zelf bepalen hoe zij hiermee omgaan, is de kans groot dat vroeg of laat jouw gegevens op straat komen te liggen.",[11,5950,5951],{},"Omdat we steeds meer digitaal doen, wordt het alsmaar belangrijker dat je bewust omgaat met jouw gegevens. Het is nog maar de vraag of het nog van deze tijd is dat al jouw gegevens verspreid zijn over verschillende partijen.",[11,5953,5954],{},[59,5955,5956],{},"Wat als jouw gegevens, jouw identiteit in een digitale kluis zouden liggen waarvan jij kunt bepalen wie toegang krijgt?",[24,5958,5960],{"id":5959},"zoveel-meer-dan-bitcoin","Zoveel meer dan Bitcoin",[11,5962,5963],{},"Dit soort vraagstukken kunnen beantwoord worden met blockchain technologie. Of Cardano ook écht gaat leiden tot een digitale revolutie in Afrika is nog maar de vraag.",[11,5965,5966],{},"Er zijn veel meer goede initiatieven gestart in Afrika die door de huidige gang van zaken stranden en niet afgerond worden.",[11,5968,5969],{},"Daarnaast heeft Cardano nog geen ondersteuning van Smart Contracts op het netwerk. Waardoor een deel van de oplossing zal opgevangen moeten worden in een laag die tegen het Cardano netwerk aangebouwd wordt.",[11,5971,5972],{},"Maar dat het geprobeerd wordt en mogelijk is in theorie om dit te doen is geweldig.",[11,5974,5975],{},"Als ik nu mensen spreek over blockchain projecten dan gaat dit altijd over handelen, speculatie en geld verdienen. Dit begrijp ik ergens wel. Voor Nederlanders is er geen noodzaak om blockchain voor iets anders te gebruiken of als iets anders te zien.",[11,5977,5978],{},"Het is echter een zonde dat de meeste gebruikers van deze technologie niet verder kijken dan zijn of haar portemonnee lang is. Blockchain technologie gaat het fundament zijn voor een nieuwe digitale wereld.",[11,5980,5981],{},"Één waarin eigendom, identiteit én geld een nieuwe vorm gaan krijgen.",{"title":144,"searchDepth":145,"depth":145,"links":5983},[5984,5985,5986,5987,5988],{"id":5852,"depth":145,"text":5853},{"id":5880,"depth":145,"text":5881},{"id":5906,"depth":145,"text":5907},{"id":5935,"depth":145,"text":5936},{"id":5959,"depth":145,"text":5960},"2021-04-29","Een ander doel voor blockchain naast financiële doeleneinden","\u002Farticles\u002Fblockchain-in-afrika\u002Fcover.png","Saliousoft","https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Mobile_Money_kiosk.jpg",{},"\u002Farticles\u002Fblockchain-in-afrika",{"title":5818,"description":5990},"blockchain-in-afrika","articles\u002Fblockchain-in-afrika",[6000,6001,6002,6003],"blockchain","crypto","finance","africa","5vj5eaZ6aFU7SFf1zsy0zfUhKQbW8tNwooGAN4feHkM",{"id":6006,"title":6007,"body":6008,"date":6353,"description":6354,"extension":154,"image":6355,"imageAuthor":6356,"imageLicense":6357,"imageSource":6358,"meta":6359,"navigation":160,"path":6360,"published":160,"seo":6361,"slug":6362,"stem":6363,"tags":6364,"__hash__":6365},"articles\u002Farticles\u002Fde-waarde-van-een-blockchain.md","De waarde van een blockchain",{"type":8,"value":6009,"toc":6347},[6010,6022,6028,6031,6034,6037,6040,6046,6057,6061,6067,6073,6076,6085,6091,6094,6098,6110,6113,6125,6158,6165,6184,6191,6203,6209,6216,6220,6223,6244,6251,6262,6269,6276,6282,6289,6300,6303,6308,6332,6336,6339,6342],[11,6011,6012,6013,6021],{},"Je ziet duizelingwekkende bedragen als je op een website zoals ",[51,6014,6018],{"href":6015,"rel":6016,"title":6017},"https:\u002F\u002Fcoinmarketcap.com\u002F",[473],"CoinMarketCap",[59,6019,6020],{},"Coinmarketcap"," kijkt. Hier vind je een overzicht van de totale waarde die momenteel geïnvesteerd is per digitale valuta.",[11,6023,6024,6025],{},"Beter gezegd; de prijs keer de voorraad die in omloop is. Voor sommige digitale valuta leidt dit tot ",[59,6026,6027],{},"bizarre bedragen.",[11,6029,6030],{},"Wat bezielt iedereen toch om zoveel fiat valuta (euro's, dollars, etc.) om te zetten naar een digitale valuta?",[11,6032,6033],{},"Is het mogelijk om te bepalen wat de waarde is van een digitale valuta op basis van de onderliggende blockchain?",[11,6035,6036],{},"Maakt dit überhaupt een verschil?",[11,6038,6039],{},"Of willen mensen alleen maar snel rijk kunnen worden met behulp van een \"hippe trend\" waar steeds meer mensen aan mee doen?",[11,6041,6042,6043],{},"In deze blogpost sta ik stil bij de monetaire zijde van blockchains. ",[59,6044,6045],{},"Kunnen we deze technologie als geld zien?",[533,6047,6048],{},[11,6049,6050,6053,6054],{},[59,6051,6052],{},"Disclaimer"," ",[14,6055,6056],{},"in geen enkele vorm is dit bedoeld als financieel advies. In deze post geef ik mijn visie en som ik gedachten en feiten op om uitleg te geven over de ontwikkelingen op financieel gebied.",[24,6058,6060],{"id":6059},"geloof-en-waarde","Geloof en waarde",[11,6062,6063,6066],{},[59,6064,6065],{},"Elk geldsysteem is gebaseerd op geloof."," Het feit dat wij allemaal waarde zien in de valuta waar wij mee omgaan. Deels wordt dit geloof geforceerd door de overheid, zo betaal je immers belasting in euro's, doe je dit niet dan kom je in de problemen.",[11,6068,6069,6070,1027],{},"Maar we hebben een hele tijd ook zonder geld geleefd. Waarbij transacties bestonden uit het wisselen van goederen. Als je meer leest over het ontstaan van geld dan wordt er voornamelijk aangegeven dat geld is ontstaan vanwege ",[59,6071,6072],{},"problemen bij het vastleggen en bijhouden van waarde",[11,6074,6075],{},"Brood kunnen ruilen voor iets anders is goed te doen, maar het sparen van brood langer dan een week is - letterlijk - niet lucratief meer. In dat geval ga je er zelfs op achteruit omdat je dat brood beter aan de eenden kan voeren.",[11,6077,6078,6079,1027],{},"Zo zijn er allerlei verschillende middelen geweest om dit te doen. Van kralen tot kerven in stenen en van schelpen tot ",[51,6080,6084],{"href":6081,"rel":6082,"title":6083},"https:\u002F\u002Fdecorrespondent.nl\u002F2978\u002Fwie-begrijpt-hoe-ons-geld-werkt-komt-morgen-in-opstand\u002F114489210-2868dc45",[473],"De Correspondent","één grote massieve steen",[11,6086,6087,6088],{},"Maar de waarde van ",[59,6089,6090],{},"geld is niet altijd grotendeels gebaseerd geweest op het geloof erin.",[11,6092,6093],{},"We hebben dus ook andere tijden gekend.",[24,6095,6097],{"id":6096},"het-verdwijnen-van-tastbare-waarde","Het verdwijnen van tastbare waarde",[11,6099,6100,6101,6109],{},"Hier opperen mensen vaak het argument van de ",[51,6102,6106],{"href":6103,"rel":6104,"title":6105},"https:\u002F\u002Fwww.thebalance.com\u002Fwhat-is-the-history-of-the-gold-standard-3306136",[473],"The Balance",[59,6107,6108],{},"gouden standaard",". Een manier om waarde van een geldsysteem te bepalen door een vaste hoeveelheid goud in beheer te hebben hiervoor.",[11,6111,6112],{},"In een dergelijk systeem kan geld ingewisseld worden voor een bepaalde hoeveelheid goud waar de beheerder garant voor staat.",[11,6114,6115,6116,6124],{},"In begin jaren 30 veranderde dit echter in de tijd van ",[51,6117,6121],{"href":6118,"rel":6119,"title":6120},"https:\u002F\u002Fwww.britannica.com\u002Fevent\u002FGreat-Depression",[473],"Britannica",[59,6122,6123],{},"De Grote Depressie",". De volgende gebeurtenissen - met uitzondering van de laatste - vonden allemaal in het jaar 1933 plaats:",[230,6126,6127,6134,6140,6146,6152],{},[124,6128,6129,6130,6133],{},"In ",[59,6131,6132],{},"Maart",": Roosevelt schort alle betalingsverplichtingen van banken op",[124,6135,6129,6136,6139],{},[59,6137,6138],{},"April",": Roosevelt bevelt dat alle goudmunten en -certificaten ingeruild moeten worden voor een andere vorm van geld",[124,6141,6129,6142,6145],{},[59,6143,6144],{},"Mei",": de overheid heeft $300M aan goudmunten en $470M aan goudcertificaten verzameld",[124,6147,6129,6148,6151],{},[59,6149,6150],{},"Juni",": Roosevelt \"pauzeert\" gouden standaard",[124,6153,6129,6154,6157],{},[59,6155,6156],{},"1934",": De overheid verhoogt de goudprijs",[11,6159,6160,6161,6164],{},"Dit resulteerde in een ",[59,6162,6163],{},"enorme waardevolle hoeveelheid goud"," in het bezit van de Amerikaanse overheid. Uiteindelijk is dit gebruikt als middel om meer geld te introduceren in de maatschappij om daarmee De Grote Depressie te bestrijden.",[11,6166,6129,6167,6170,6171,6179,6180,6183],{},[59,6168,6169],{},"1944"," hebben \"de meest ontwikkelde\" landen een ",[51,6172,6176],{"href":6173,"rel":6174,"title":6175},"https:\u002F\u002Fwww.investopedia.com\u002Fterms\u002Fb\u002Fbrettonwoodsagreement.asp",[473],"Investopedia",[59,6177,6178],{},"akkoord"," gesloten waarbij ",[59,6181,6182],{},"hun valuta te koppelen aan de dollar",". Dit omdat de VS de grootste goudreserves had op dat moment. Zo werd het mogelijk om dat goud vervolgens als basis van de dollar aan te houden.",[11,6185,6186,6187,6190],{},"Begin ",[59,6188,6189],{},"jaren 70"," leidde dit tot problemen toen steeds meer landen - als gevolg van lokale inflatie - goud eisten in ruil voor de dollars die zij in bezit hadden.",[11,6192,6193,6194,6202],{},"De toenmalige president van de VS nam een drastische maatregel in 1971, ookwel de ",[51,6195,6199],{"href":6196,"rel":6197,"title":6198},"https:\u002F\u002Fisgeschiedenis.nl\u002Fnieuws\u002Fde-nixon-shock-america-first-in-de-jaren-70",[473],"Is Geschiedenis",[59,6200,6201],{},"Nixon shock"," genoemd, om geen dollars meer te wisselen tegen een vaste waarde in goud.",[11,6204,6205,6206,1027],{},"Hiermee nam de VS volledig afstand van de gouden standaard met als resultaat een ",[59,6207,6208],{},"dollar als wereldvaluta zonder een achterliggende waarde in goud",[11,6210,6211,6212,6215],{},"De geschiedenis laat ons zien wat gevolgen zijn van beslissingen genomen door ",[59,6213,6214],{},"centrale partijen"," die proberen in te grijpen in complexe systemen zoals de economie, met de intentie deze te redden.",[24,6217,6219],{"id":6218},"polariserende-wereldbeelden","Polariserende wereldbeelden",[11,6221,6222],{},"Ook ons huidige systeem zit vol met centrale partijen. Zo zijn er:",[121,6224,6225,6231,6237],{},[124,6226,6227,6230],{},[59,6228,6229],{},"commerciële banken"," die geld voor inwoners beheren en reguleren",[124,6232,6233,6236],{},[59,6234,6235],{},"De Nederlandsche Bank"," (DNB) die zich bezighoudt met de nationale rentevoet",[124,6238,6239,6240,6243],{},"De ",[59,6241,6242],{},"Europees Centrale Bank"," (ECB) die zich op Europees niveau over geldzaken ontfermt.",[11,6245,6246,6247,6250],{},"Deze laatste partij is ook verantwoordelijk voor het bepalen van de hoeveelheid euro's die in omloop zijn. Ookwel het ",[59,6248,6249],{},"monetair beleid"," genoemd. Uiteraard komt er nog veel meer kijken bij het financiële ecosysteem in Europa.",[11,6252,6253,6254,6257,6258,6261],{},"Maar het feit dat één centrale partij besluit over deze valuta is het punt waarop ",[59,6255,6256],{},"fiat valuta"," en ",[59,6259,6260],{},"digitale valuta"," verschillen als dag en nacht.",[11,6263,6264,6265,6268],{},"Zoals je wellicht gelezen hebt in mijn vorige blogpost, is een blockchain ",[59,6266,6267],{},"decentraal"," van aard. Er is geen één partij die verantwoordelijk is voor het draaiend houden van het netwerk.",[11,6270,6271,6272,6275],{},"Dit betekent dat de code van een decentrale blockchain openbaar beschikbaar is. Hierin zitten de regels die gelden op het netwerk. ",[59,6273,6274],{},"Dit betekent dat niet alleen het beleid, maar ook de uitvoering ervan"," inzichtelijk is. Dit creëert een omgeving waarin vertrouwen niet relevant is omdat inzichtelijk is wat er gebeurd en waarom.",[11,6277,6278,6279],{},"Zo komt er geen centrale partij aan te pas die zich moet bezighouden van het reguleren van het netwerk. Nog belangrijker, ",[59,6280,6281],{},"het is dus niet mogelijk eigenschappen van het systeem te reguleren, als dit niet vastgelegd staat in de code.",[11,6283,6284,6285,6288],{},"In theorie kunnen de concepten elkaar vervangen, fiat- en digitale valuta. Ik zeg bewust in theorie omdat tot nu toe nog ",[59,6286,6287],{},"geen één enkele blokchain alle facetten"," van het huidige stelsel optimaal kan vervangen. Het gevolg hiervan is dat er vol overtuiging door beide partijen gelooft wordt in een toekomst waarin de één het aflegt tegen de ander.",[11,6290,6291,6292,1027],{},"Enerzijds hebben we een groep die vastzit in een huidige denkwijze, waarbij steeds een overtreffende trap toegepast wordt van bestaande manieren van ingrijpen, zie bijvoorbeeld het ",[51,6293,6297],{"href":6294,"rel":6295,"title":6296},"https:\u002F\u002Fwww.ecb.europa.eu\u002Fexplainers\u002Fshow-me\u002Fhtml\u002Fapp_infographic.nl.html",[473],"ECB",[59,6298,6299],{},"kwantitatieve verruimingsbeleid van de ECB",[11,6301,6302],{},"Anderzijds hebben we een nieuwe technologie die - alhoewel zeer veel belovend - nog niet volwassen genoeg is om te gebruiken als een volledige vervanger op globaal niveau.",[11,6304,6305],{},[59,6306,6307],{},"Één ding dat zeker is; ons huidige systeem moet veranderen.",[11,6309,6310,6311,6318,6319,6327,6328,6331],{},"Wat dat gaat zijn? Misschien een door de ",[51,6312,6315],{"href":6313,"rel":6314,"title":6296},"https:\u002F\u002Fwww.ecb.europa.eu\u002Fhome\u002Fsearch\u002Fhtml\u002Fcentral_bank_digital_currencies_cbdc.en.html",[473],[59,6316,6317],{},"ECB beheerde valuta",", een ",[51,6320,6324],{"href":6321,"rel":6322,"title":6323},"https:\u002F\u002Fwww.forbes.com\u002Fsites\u002Fphilippsandner\u002F2021\u002F02\u002F22\u002Fdecentralized-finance-will-change-your-understanding-of-financial-systems\u002F?sh=30378d675b52",[473],"Forbes",[59,6325,6326],{},"ecosysteem aan verschillende decentrale platformen"," die in combinatie gebruikt kunnen worden of ",[59,6329,6330],{},"één valuta"," die wereldwijd geaccepteerd en gebruikt gaat worden?",[24,6333,6335],{"id":6334},"van-een-oud-naar-een-nieuw-standaard","Van een oud naar een nieuw standaard",[11,6337,6338],{},"Als de vereiste is dat mensen moeten geloven in één middel zodat het mogelijk is om daarmee waarde over te brengen.",[11,6340,6341],{},"Er daarnaast geen direct gekoppelde fysieke weerspiegeling hoeft te zijn om deze waarde te garanderen, zoals met de dollar.",[11,6343,6344],{},[59,6345,6346],{},"Waarom zouden we dan technologie niet als geld kunnen gaan zien?",{"title":144,"searchDepth":145,"depth":145,"links":6348},[6349,6350,6351,6352],{"id":6059,"depth":145,"text":6060},{"id":6096,"depth":145,"text":6097},{"id":6218,"depth":145,"text":6219},{"id":6334,"depth":145,"text":6335},"2021-02-23","Een betoog over de zoektocht naar de waarde van iets van nature digitaal","\u002Farticles\u002Fde-waarde-van-een-blockchain\u002Fcover.png","Stevebidmead","CC0","https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Gold_bullion_bars.jpg",{},"\u002Farticles\u002Fde-waarde-van-een-blockchain",{"title":6007,"description":6354},"de-waarde-van-een-blockchain","articles\u002Fde-waarde-van-een-blockchain",[6000,6001,6002],"l2f_CvXueJ5cncNE1weXdYTQbTcBVH64NThbg71z2DM",{"id":6367,"title":6368,"body":6369,"date":6606,"description":6607,"extension":154,"image":6608,"imageAuthor":6609,"imageLicense":750,"imageSource":6610,"meta":6611,"navigation":160,"path":6612,"published":160,"seo":6613,"slug":6614,"stem":6615,"tags":6616,"__hash__":6618},"articles\u002Farticles\u002Fbegrijp-jij-bitcoin.md","Begrijp jij bitcoin?",{"type":8,"value":6370,"toc":6599},[6371,6374,6377,6380,6384,6391,6396,6399,6410,6413,6420,6423,6426,6430,6439,6446,6458,6468,6471,6475,6478,6481,6491,6501,6511,6515,6518,6533,6546,6552,6555,6562,6564,6567],[11,6372,6373],{},"Je moet aardig je best hebben gedaan om in de afgelopen 10 jaar (!) nog niets over bitcoin gehoord te hebben. Misschien heb je al eens wat erover gelezen. Die ene - rare - neef overhoort op een verjaardag. Of misschien heb je een mailtje gehad met daarin een bekende Nederlander die dé investeringstrategie heeft waarmee je gegarandeerd miljonair gaat worden.",[11,6375,6376],{},"Maar wat weet je er nu écht over?",[11,6378,6379],{},"In deze blog ga ik je wat vertellen over de basis van bitcoin. Omdat er veel over bitcoin te vertellen is, behandel ik in deze blog alleen de technische kant van bitcoin.",[24,6381,6383],{"id":6382},"het-netwerk-en-de-valuta","Het netwerk en de valuta",[11,6385,6386,6387,6390],{},"In 2009 publiceerde ",[59,6388,6389],{},"Satoshi Nakamoto"," (anoniem pseudoniem) een whitepaper waarin een publiekelijk toegankelijk betalingssysteem wordt omschreven. Dit betalingssysteem zou moeten werken zonder één centrale partij die alles beheert. Waarbij mensen gebruik kunnen maken van een netwerk om een digitale valuta over te kunnen maken. De technologie gebruikt voor dit netwerk?",[11,6392,6393,1027],{},[59,6394,6395],{},"Blockchain",[11,6397,6398],{},"Dit is de naam van de technologie waar bitcoin gebruik van maakt. Bitcoin is een eerste generatie blockchain en is geboren vanuit het verlangen om ook los van financiële instituten betalingen in de digitale wereld mogelijk te maken.",[11,6400,6401,6402,6405,6406,6409],{},"De valuta bitcoin is echter vele malen bekender dat het netwerk dat ervoor nodig is. Dat bitcoin baanbrekende en innoverende technologie is, heeft niet zozeer te maken met het feit dat er ",[59,6403,6404],{},"maximaal 21 miljoen bitcoin"," zullen zijn. Of dat elk van deze bitcoin op te delen is in ",[59,6407,6408],{},"100.000.000 kleinere deeltjes"," vernoemd naar de oprichter, Satoshi's (of sats).",[11,6411,6412],{},"Het is de blockchain technologie eronder dat oplossing biedt voor een probleem waarmee computertechnologie al vanaf het begin te maken heeft:",[533,6414,6415],{},[11,6416,6417],{},[14,6418,6419],{},"Hoe maak je iets aantoonbaar uniek in een digitale wereld waar alles te kopiëren is?",[11,6421,6422],{},"Er bestond namelijk nog geen geld in de digitale wereld. Alhoewel internetbankieren dichtbij lijkt te komen, is dit niet anders dan een getal dat voor jou beheert wordt door een bank. Als het goed is kun jij er vanuit gaan dat dit getal dan ook een hoeveelheid geld vertegenwoordigd die beschikbaar gehouden wordt door de bank.",[11,6424,6425],{},"Met nadruk op: \"Als het goed is...\"",[24,6427,6429],{"id":6428},"hét-cruciale-probleem","Hét cruciale probleem",[11,6431,6432,6433,6438],{},"Deze technologie lost ",[51,6434,6437],{"href":6435,"rel":6436},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FDouble-spending",[473],"het bovenstaande probleem"," op. Het is niet mogelijk om 1 bitcoin dubbel uit te geven. Het is niet mogelijk om vals te spelen. Hiervoor zijn een aantal slimme oplossingen gecombineerd om dit te garanderen.",[11,6440,6441,6442,6445],{},"De belangrijkste hiervan verklaart ook de naam van de technologie: ",[59,6443,6444],{},"een blokkenketen"," - ookwel blockchain in het Engels.",[11,6447,6448,6449,6457],{},"Als metafoor voor blockchain wordt vaak een grootboek gebruikt. Het is met deze technologie namelijk mogelijk om ",[59,6450,6451,6452],{},"alle transacties op het netwerk in te kunnen ",[51,6453,6456],{"href":6454,"rel":6455},"https:\u002F\u002Fwww.blockchain.com\u002Fexplorer",[473],"zien",". Net zoals een grootboek dat je kunt openslaan kun je in de blockchain onder bitcoin zien waar elke bitcoin (zelfs elke Satoshi!) naartoe gaat.",[11,6459,6460,6461,6464,6465,1027],{},"Alle transacties worden openlijk geregistreerd. Dit wordt niet per transactie gedaan maar gegroepeerd in ",[59,6462,6463],{},"blokken",". De grootte van deze blokken ligt vast in de code en wordt gemeten in een hoeveelheid data (1MB om precies te zijn - op het moment van schrijven). Als er een nieuw blok geregistreerd wordt dan komen hier zoveel mogelijk transacties in, zonder het limiet aan data te overschreiden. Dit nieuwe blok wordt vervolgens ",[59,6466,6467],{},"toegevoegd aan de bestaande keten van blokken",[11,6469,6470],{},"Dit betekent dat de keten in de blockchain steeds langer en langer wordt. Elke keer wordt er een nieuw blok gemaakt, gevuld met transactie en achteraan de keten toegevoegd. Zo ontstaat er één groot archief met alle transacties.",[24,6472,6474],{"id":6473},"samenwerken-aan-een-veilig-netwerk","Samenwerken aan een veilig netwerk",[11,6476,6477],{},"In werkelijkheid zitten hier wat meer haken en ogen aan maar voor nu heb je een globaal beeld van de werking van zo'n netwerk. Dit hele proces wordt mogelijk gemaakt doordat mensen met een of meerdere computers kunnen deelnemen aan dit netwerk.",[11,6479,6480],{},"In een blockchain komen de volgende nodes voor:",[11,6482,6483,6486,6487,6490],{},[59,6484,6485],{},"Mijner (Mining) node",": Hiervoor is tegenwoordig ontzettend veel rekenkracht nodig. Deze leden van het netwerk zijn bezig met het ",[59,6488,6489],{},"raden van het volgende blok",". Ze ontvangen een beloning voor het vinden van het nieuwe blok én krijgen daarbij de kosten van alle transacties die ze hierin kunnen verwerken.",[11,6492,6493,6496,6497,6500],{},[59,6494,6495],{},"Volledige (Full) node",": Deze nodes zijn bezig met het controleren van transacties die gedaan worden. Elk van deze nodes heeft ",[59,6498,6499],{},"een volledige kopie"," van de hele keten (het grootboek) en kunnen daarmee dus controleren of iemand een transactie wel kan doen.",[11,6502,6503,6506,6507,6510],{},[59,6504,6505],{},"Kleine (Light) node",": Dit kunnen zelfs telefoons zijn. Ze hebben niet een volledige kopie van de hele keten beschikbaar maar vragen dit op bij een volledige node als dat nodig is. Dit maakt het mogelijk om ",[59,6508,6509],{},"enkel transacties te doen"," zonder hiervoor een volledige computer nodig te hebben.",[24,6512,6514],{"id":6513},"de-eindstreep","De eindstreep?",[11,6516,6517],{},"Zijn we er dan? Is bitcoin de toekomst en kunnen we onze papieren geld en semi-digitale euro's ritueel verbranden? Dat lijkt me nog erg voorbarig. Voor een valuta is 10 jaar nog wel heel jong. Toch ziet het er alsnog goed uit voor de nabije toekomst.",[11,6519,6520,6521,6524,6525,6528,6529,6532],{},"Er zijn nog wel wat hordes die genomen moeten worden. Bitcoin staat in de ",[59,6522,6523],{},"crypto scene"," bekend als een dino. Vooral wanneer de drukte toeneemt op het netwerk gaan de ",[59,6526,6527],{},"transactiekosten omhoog"," en de ",[59,6530,6531],{},"transactiesnelheid omlaag",". Dit is niet ideaal. Vooral niet voor een betalingsmiddel dat je wil gebruiken als je boodschappen gaat doen of snel een drankje wil afrekenen.",[11,6534,6535,6536,6539,6540,6545],{},"Daarom wordt bitcoin ookwel het ",[59,6537,6538],{},"digitale goud"," genoemd. Het wordt nu veelal gebruikt door mensen om hun vermogen te beschermen. Ondanks dat het zeker mogelijk is om ",[51,6541,6544],{"href":6542,"rel":6543},"https:\u002F\u002Fshop.btcdirect.eu\u002Fnl-nl\u002Fproducts\u002Fde-bitcoin-standaard\u002F",[473],"spullen te kopen met bitcoin",", is dit eerder een uitzondering dan een gegeven.",[11,6547,6548,6549],{},"Er zijn steeds meer mensen betrokken de ontwikkelingen op het gebied van blockchain en crypto (de valuta's). Er komen ook steeds meer oplossingen waardoor deze technologie zich op een razend tempo blijft ontwikkelen. ",[59,6550,6551],{},"Naast bitcoin is er een hele wereld ontstaan aan nieuwe platformen, concepten en oplossingen die ons een kijkje geven in de mogelijke toekomst van de digitale wereld.",[11,6553,6554],{},"We zijn er nog niet maar als iets duidelijk wordt op basis van het afgelopen decennia dan is het dat we een revolutie voor de boeg hebben. Waar de toekomst ons precies brengt weet ik niet maar ik geloof erin dat bitcoin de eerste stap was waarop nog vele gaan volgen.",[533,6556,6557],{},[11,6558,6559],{},[14,6560,6561],{},"Geïnteresseerd in nog meer informatie over bitcoin, blockchain en andere veranderingen die gaande zijn op financieel en technisch gebied? Hou dan zeker mijn blog in de gaten.",[24,6563,464],{"id":463},[11,6565,6566],{},"Ben je nu al nieuwsgierig naar meer informatie? Hieronder nog wat links voor meer lees- en luistermateriaal.",[121,6568,6569,6577,6585,6592],{},[124,6570,6571,6576],{},[51,6572,6575],{"href":6573,"rel":6574},"https:\u002F\u002Flekkercryptisch.nl\u002F",[473],"LekkerCryptisch.nl - Wat is bitcoin?"," (NL)",[124,6578,6579,6584],{},[51,6580,6583],{"href":6581,"rel":6582},"https:\u002F\u002Fdecrypt.co\u002Fcollections\u002Fbitcoin-basics-get-started",[473],"Decrypt.co - Bitcoin Basics"," (EN)",[124,6586,6587,6576],{},[51,6588,6591],{"href":6589,"rel":6590},"https:\u002F\u002Fwww.bnr.nl\u002Fpodcast\u002Fcryptocast",[473],"Cryptocast BNR",[124,6593,6594,6584],{},[51,6595,6598],{"href":6596,"rel":6597},"https:\u002F\u002Fbitcoin.org\u002Fbitcoin.pdf",[473],"Bitcoin whitepaper",{"title":144,"searchDepth":145,"depth":145,"links":6600},[6601,6602,6603,6604,6605],{"id":6382,"depth":145,"text":6383},{"id":6428,"depth":145,"text":6429},{"id":6473,"depth":145,"text":6474},{"id":6513,"depth":145,"text":6514},{"id":463,"depth":145,"text":464},"2021-01-31","Er is geen ontkomen meer aan onderhand. Wat weet jij van bitcoin?","\u002Farticles\u002Fbegrijp-jij-bitcoin\u002Fcover.png","Tiberiandusk","https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Physical_Bitcoin_2011_Casascius_1_Bitcoin_Coin_Token.png",{},"\u002Farticles\u002Fbegrijp-jij-bitcoin",{"title":6368,"description":6607},"begrijp-jij-bitcoin","articles\u002Fbegrijp-jij-bitcoin",[6617,6000,6001,6002],"bitcoin","qvA-VaVZA5PyFp9DLIM34EAVM5E0rzglKZGFOE3CdCw",{"id":6620,"title":6621,"body":6622,"date":6976,"description":6977,"extension":154,"image":6978,"imageAuthor":6979,"imageLicense":6980,"imageSource":6981,"meta":6982,"navigation":160,"path":6983,"published":160,"seo":6984,"slug":6985,"stem":6986,"tags":6987,"__hash__":6990},"articles\u002Farticles\u002Fthe-serverless-site-my-customer-needed.md","The serverless site my customer needed",{"type":8,"value":6623,"toc":6971},[6624,6627,6634,6637,6644,6651,6654,6659,6663,6673,6676,6683,6686,6697,6700,6718,6723,6729,6746,6749,6764,6773,6792,6795,6808,6811,6817,6824,6828,6831,6834,6837,6857,6860,6912,6915,6922,6925,6928,6931],[11,6625,6626],{},"Not long ago I published a new version of my website that no longer used a HTML one-page template. I had written both HTML and CSS files myself and I quickly felt content. The site displayed summarized \"about me\" information with some contact details.",[11,6628,6629,6630,6633],{},"Almost immediately after I put the website live, I asked myself: ",[14,6631,6632],{},"\"What if I wanted to share content?\"",". Surely I could use an existing platform to scribble down my thoughts, but could it be possible to put this content on my site without a hassle and without worrying about maintaining components like a Content Management System (CMS) or even the webserver itself?",[11,6635,6636],{},"So yeah, I meant myself when writing about \"my customer\" and yes, I think that's disgusting too. But hear me out. ",[11,6638,6639,6640,6643],{},"The point is; ",[59,6641,6642],{},"I delivered a product without actually understanding and\u002For observing what the customer needed."," If I would have sat down for longer then 20 minutes and drafted up some ideas maybe I could've avoided this. Right? I see this phenomenon happening around me all the time. Sadly I even contribut to it more then I'd like to commit. So this made me wonder:",[533,6645,6646],{},[11,6647,6648],{},[14,6649,6650],{},"Can I be more mindful in my development process? And if so, could I find a solution that actually fulfills my needs?",[11,6652,6653],{},"In order to answer this question I got urged myself to delve into the origin of design thinking. And boy, did I fall down the rabbit hole.",[11,6655,6656],{},[14,6657,6658],{},"If you don't feel like finding out more about the history of design and how it got into software development, you'd better skip to the part where I talk about the development of my site.",[24,6660,6662],{"id":6661},"the-human-part-of-design","The human part of design",[11,6664,6665,6668,6669,6672],{},[59,6666,6667],{},"Design"," is a term broadly used throughout all kinds of industries with most of them having their own definition associated with it. I could devote a series of posts to the differences in definition and both the use and misuse of the word. The same accounts for the way ",[59,6670,6671],{},"\"design as a way of thinking\""," has been used in the last decade.",[11,6674,6675],{},"The design thinking movement, like many trends before, has made its delayed way into business environments. Especially those where IT and business seem to meet. With the main point boiling down to:",[533,6677,6678],{},[11,6679,6680],{},[14,6681,6682],{},"Using a designers approach to solve managerial or software related problems",[11,6684,6685],{},"Though it originates from something much more elaborate:",[11,6687,6688,6689,6696],{},"As far as I could trace back, it started in 1964 when Ken Garland published ",[59,6690,6691],{},[51,6692,6695],{"href":6693,"rel":6694},"https:\u002F\u002Fbit.ly\u002F2BzkSdK",[473],"\"The First Things First\" manifesto"," as response to the ever increasing pressure on designers to contribute to the production of mainstream advertising. Depriving the concept of design from its essence by moving it from being centered around humans to instead be driven by corporate goals and metrics. Designers have fought to prevent their craftsmanship from sliding into this inhuman oblivion ever since.",[11,6698,6699],{},"The developing technology didn't help either as it introduced increasingly more complex problems at the time. In attempt to solve these problems people tried to turn to design, as a method of solving problems, into a form of science.",[11,6701,6702,6703,6706,6707,6717],{},"The late 1960's are the origin of the ",[59,6704,6705],{},"Wicked Problems"," firstly mentioned by Horst Rittel, a design theorist and professor at the Ulm School of Design in Germany. He stated that these wicked problems are a",[6708,6709,6710],"sup",{},[51,6711,6716],{"href":6712,"ariaDescribedBy":6713,"dataFootnoteRef":144,"id":6715},"#user-content-fn-1",[6714],"footnote-label","user-content-fnref-1","1",":",[533,6719,6720],{},[11,6721,6722],{},"\"class of social system problems which are ill-formulated, where the information is confusing, where there are many clients and decision makers with conflicting values, and where the ramifications in the whole system are thoroughly confusing.\"",[11,6724,6725,6726,1027],{},"That roughly translates to: ",[14,6727,6728],{},"Wicked problems are unclear in the way how they should be solved, a lot of people are involved but they don't agree with each other and it's unknown what is and isn't relevant... It's actually quite a mess",[11,6730,6731,6732,1782,6735,6738,6739,1782,6742,6745],{},"Rittel claimed that although these problems are so complex, they have a underlying pattern consisting of two phases: ",[59,6733,6734],{},"problem definition",[59,6736,6737],{},"problem solution",". He pleaded for the importance of human experience and perception in design as opposed to others in this period. This is were the ",[59,6740,6741],{},"problem space",[59,6743,6744],{},"solution space"," phases are derived from in diagrams about design thinking.",[11,6747,6748],{},"This sparked the interest of many, since it strives to solve a problem that's relevant throughout different industries because of its abstract nature. Causing designers and other highly creative people to become subjects of studies in order to determine how they would come up with ideas and solutions. This research led to the use of creative thinking techniques like brainstorming across other professions as we know and use today.",[11,6750,6751,6752,6755,6756,6717],{},"After this periode a lot more happened on which I could elaborate more, but one of the key events related to design thinking was the 1992 publication of Richard Buchanan's ",[59,6753,6754],{},"\"Wicked Problems in Design Thinking\""," in which he portrait design and its role in solving problems. Stating",[6708,6757,6758],{},[51,6759,6763],{"href":6760,"ariaDescribedBy":6761,"dataFootnoteRef":144,"id":6762},"#user-content-fn-2",[6714],"user-content-fnref-2","2",[533,6765,6766],{},[11,6767,6768,6769,6772],{},"\"The subject matter of design is potentially ",[14,6770,6771],{},"universal"," in scope,\nbecause design thinking may be applied to any area of human experience\"",[11,6774,6775,6776,6783,6784,6791],{},"Somewhere around 2015 business trend outlets like the ",[51,6777,6780],{"href":6778,"rel":6779},"https:\u002F\u002Fbit.ly\u002F3176Uus",[473],[59,6781,6782],{},"Harvard Business Review",", ",[51,6785,6788],{"href":6786,"rel":6787},"https:\u002F\u002Fwww.thoughtworks.com\u002Finsights\u002Fblog\u002Fbusiness-design-and-technology-joining-forces-truly-competitive-advantage",[473],[59,6789,6790],{},"Thoughtworks"," and others picked up on a \"way of putting design much closer to the center of the enterprise\" for it being a way of \"joining forces for a truly competitive advantage\".",[11,6793,6794],{},"You might be wondering why I'm lecturing you on the history of design. But the crucial takeaway from this are the similarities popping-up in software development nowadays and that explains the increase in need for something like design thinking (or other trends).",[11,6796,6797,6798,6783,6801,6783,6804,6807],{},"The emphasis is more and more put on ",[59,6799,6800],{},"time-to-market",[59,6802,6803],{},"reducing lead times",[59,6805,6806],{},"delivering on more new features"," and other metrics. Sure, times have changed and technology enables us to deliver on these promises. But it beckons the question whether or not these demands are slowly and steadily crossing a line causing a shift of focus in software development towards metrics, leading to disconnection from human aspects.",[11,6809,6810],{},"Regardless of your position or role within the development process, you're creating something to be used by humans in one way or another. Whether its a mission statement, a performance report, a piece of software or even test documentation.",[11,6812,6813,6814,1027],{},"Make sure to ask yourself the question whether or not you're being pushed forward plagued by assumptions, metrics and deadlines instead of ",[59,6815,6816],{},"being guided by the challenge to determine and solve the actual problems of the customer",[11,6818,6819,6820,6823],{},"Take into account the human part of the development; ",[59,6821,6822],{},"do you know if the problem you think you're solving, is even close to the actual problem?",". This will serve you greatly in the long run.",[24,6825,6827],{"id":6826},"spaces-of-problems-and-solutions","Spaces of problems and solutions",[11,6829,6830],{},"So after being distracted for hours about the roots of design thinking, I got back to the problem I was dealing with. What do I want? What do I think I want? What do I think I want but is it actually something I don't need?",[11,6832,6833],{},"You get the point.",[11,6835,6836],{},"I've spent a couple of days drafting out ideas, listing constraints and hardships I've experienced and visited other sites to experience what I was looking for. This helped me coming up with the following design principles I wanted to keep in mind creating my website and selecting the tooling to get there. I choose principles instead of distilled requirements so I would have set the context for the solution I want without restraining my freedom during the process.",[121,6838,6839,6845,6851],{},[124,6840,6841,6844],{},[59,6842,6843],{},"Effortless",": I want there to be no impediments when it comes to maintaining or updating the website. Whether or not I'd like to admit it, I do procrastinate from time to time. Everything can become an excuse to not do something.",[124,6846,6847,6850],{},[59,6848,6849],{},"Simple",": Since I only want to post an occasional blog and some personal information there is no need for an elaborate CMS or fancy features. This will not only enable the effortless principle but will reduce distraction while writing by unnecessary features.",[124,6852,6853,6856],{},[59,6854,6855],{},"Sustainable",": Both in infrastructure and related costs I want the most ideal match between the features I need and the related costs. Static web content shouldn't be needing a 24\u002F7 up and running webserver when there is no traffic. To reduce my (digital) footprint and also my costs.",[11,6858,6859],{},"As a solution I decided to go with:",[121,6861,6862,6872,6882,6892,6902],{},[124,6863,6864,6871],{},[59,6865,6866],{},[51,6867,6870],{"href":6868,"rel":6869},"https:\u002F\u002Faws.amazon.com\u002Fs3\u002F",[473],"AWS Static Storage Server (S3)",": the static storage service from Amazon offers a lot within the free tier. Using this service eliminates the need to maintain my own server. It is also accessible from almost everywhere using the AWS-CLI or online console.",[124,6873,6874,6881],{},[59,6875,6876],{},[51,6877,6880],{"href":6878,"rel":6879},"https:\u002F\u002Faws.amazon.com\u002Froute53\u002F",[473],"AWS Route53",": since I decided to go with the S3 service I wanted to use the AWS Domain Name Service as well. This way I would have everything in one place with no need to do custom DNS configuration and at the same time reducing the hassle of configuring the S3 service to work with my domain name.",[124,6883,6884,6891],{},[59,6885,6886],{},[51,6887,6890],{"href":6888,"rel":6889},"https:\u002F\u002Fgithub.com\u002F",[473],"GitHub",": instead of versioning my content within a CSM, which I'd have to practice, I can store it within GitHub. Making me able to use a tool of which I already have some know-how.",[124,6893,6894,6901],{},[59,6895,6896],{},[51,6897,6900],{"href":6898,"rel":6899},"https:\u002F\u002Fgohugo.io\u002Fabout\u002Fwhat-is-hugo\u002F",[473],"HUGO",": a Static Site Generator (SSG) written in Go. This software aligns with the principles since it's open source, uses npm and GitHub and the generated content can be deployed to Amazons S3 service. HUGO uses HTML templating to generate HTML and CSS files based on content written using Markdown (.md) files.",[124,6903,6904,6911],{},[59,6905,6906],{},[51,6907,6910],{"href":6908,"rel":6909},"https:\u002F\u002Fwww.markdownguide.org\u002F",[473],"Markdown",": one that seems rather peculiar, but I prefer writing my content in a simple text editor so I'll be less likely to be distracted by styling and formatting. Markdown restricts its users in this by offering a simple syntax for only the essentials.",[11,6913,6914],{},"Everything you see on the site is actually written in .md files and HUGO does the rest. There are multiple SSG alternatives but I went with HUGO because of the low rendering times when opening HTML files so visitors have the quickest load times I could offer out of the box. This made developing the site much more effortless since I could change everything on the fly. I had a blast \"creating\" my website this time because everything just seemed to \"click\" once I have found something that aligned with the principles I created based on my needs.",[11,6916,6917,6918,1027],{},"Curious about the content of the website? Checkout my repository for the site on ",[51,6919,6890],{"href":6920,"rel":6921},"https:\u002F\u002Fgithub.com\u002Fbrand0new\u002Fbrandonverzuu.com",[473],[11,6923,6924],{},"At the time of writing I've already changed my theme twice because of accessibility and readability. So will I ever be done with my site?",[11,6926,6927],{},"I guess that's the beauty of this way of developing.",[11,6929,6930],{},"Laying out design principles which I incorporate throughout the development process, from tool and language selection all the way to implementation and styling. This, combined with the effort to try and reduce constraints and hardships as much as possible. Enabled me to focus on experimentation, prototyping and testing to find the solution that I needed.",[6932,6933,6936,6941],"section",{"className":6934,"dataFootnotes":144},[6935],"footnotes",[24,6937,6940],{"className":6938,"id":6714},[6939],"sr-only","Footnotes",[230,6942,6943,6958],{},[124,6944,6946,6053,6951],{"id":6945},"user-content-fn-1",[51,6947,6950],{"href":6948,"rel":6949},"https:\u002F\u002Fbit.ly\u002F37Tu1dt",[473],"C. West Churchman, \"Wicked Problems,\" Management Science, (December 1967), vol. 4, no.14, B-141-42",[51,6952,6957],{"href":6953,"ariaLabel":6954,"className":6955,"dataFootnoteBackref":144},"#user-content-fnref-1","Back to reference 1",[6956],"data-footnote-backref","↩",[124,6959,6961,6053,6966],{"id":6960},"user-content-fn-2",[51,6962,6965],{"href":6963,"rel":6964},"https:\u002F\u002Fbit.ly\u002F3hUsOqL",[473],"Buchanan, Richard. \"Wicked problems in design thinking.\" Design issues 8.2 (1992): 5-21.",[51,6967,6957],{"href":6968,"ariaLabel":6969,"className":6970,"dataFootnoteBackref":144},"#user-content-fnref-2","Back to reference 2",[6956],{"title":144,"searchDepth":145,"depth":145,"links":6972},[6973,6974,6975],{"id":6661,"depth":145,"text":6662},{"id":6826,"depth":145,"text":6827},{"id":6714,"depth":145,"text":6940},"2020-06-25","A short story on diving in head first","\u002Farticles\u002Fthe-serverless-site-my-customer-needed\u002Fcover.png","Robert Scoble","CC BY 2.0","https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Centaur_server_room_(2293424530).jpg",{},"\u002Farticles\u002Fthe-serverless-site-my-customer-needed",{"title":6621,"description":6977},"the-serverless-site-my-customer-needed","articles\u002Fthe-serverless-site-my-customer-needed",[6988,6989],"design","web-development","s-6fCH1xi9srHAzZbat8OhbXaSHHPZmk9ZZoR7dkHCY",{"id":6992,"title":6993,"body":6994,"date":7012,"description":7013,"extension":154,"image":7014,"imageAuthor":7015,"imageLicense":6357,"imageSource":7016,"meta":7017,"navigation":160,"path":7018,"published":160,"seo":7019,"slug":7020,"stem":7021,"tags":7022,"__hash__":7024},"articles\u002Farticles\u002Ffirst-post.md","Why create a personal website?",{"type":8,"value":6995,"toc":7009},[6996,6999,7003,7006],[11,6997,6998],{},"I used to have a personal webpage containing nothing more than the content of the about page. In order to have a place where I can write content of whatever comes to mind I decided to go with my own platform. This minimal approach lets me focus on content rather then get distracted by all the possibilities other platforms out there have to offer.",[24,7000,7002],{"id":7001},"so-what-can-we-expect-on-here","So what can we expect on here?",[11,7004,7005],{},"To be honest, I am not sure. I am far from having a strict \"writing schedule\" so this means there is no set amount of blog posts I want to write. Subjects will likely be related to technology.",[11,7007,7008],{},"Anyway, thanks for taking the time to have a look around on my website!",{"title":144,"searchDepth":145,"depth":145,"links":7010},[7011],{"id":7001,"depth":145,"text":7002},"2020-06-05","My reason for creating a site","\u002Farticles\u002Ffirst-post\u002Fcover.png","Alejandro Escamilla","https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Man_typing_on_laptop_(Unsplash).jpg",{},"\u002Farticles\u002Ffirst-post",{"title":6993,"description":7013},"why-create-a-personal-website","articles\u002Ffirst-post",[7023],"personal","mVYhRhpXexHsQJZk5ZMgOd9JVvfsEw8tnYXUrDc9BG0",1787253748841]