<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: kevin heidt</title>
    <description>The latest articles on DEV Community by kevin heidt (@kevin_heidt_d73c1752454fb).</description>
    <link>https://dev.to/kevin_heidt_d73c1752454fb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1570812%2F4cadbdc8-3e5d-42e0-b0d5-76bcdeec28bd.jpg</url>
      <title>DEV Community: kevin heidt</title>
      <link>https://dev.to/kevin_heidt_d73c1752454fb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kevin_heidt_d73c1752454fb"/>
    <language>en</language>
    <item>
      <title>AWS Global SQS with Multi-Region Availability</title>
      <dc:creator>kevin heidt</dc:creator>
      <pubDate>Mon, 05 May 2025 16:54:59 +0000</pubDate>
      <link>https://dev.to/kevin_heidt_d73c1752454fb/aws-global-sqs-with-multi-region-availability-4a48</link>
      <guid>https://dev.to/kevin_heidt_d73c1752454fb/aws-global-sqs-with-multi-region-availability-4a48</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aws-amazon-q-v2025-04-30"&gt;Amazon Q Developer "Quack The Code" Challenge&lt;/a&gt;: Exploring the Possibilities&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;h3&gt;
  
  
  AWS Global SQS with Multi-Region Availability
&lt;/h3&gt;

&lt;p&gt;This project demonstrates how to create a .NET application that sends messages to Amazon SQS with multi-region capabilities, allowing it to be agnostic about which regional SQS endpoint the message is being sent to. The routing is controlled via Amazon Route53 weighted routing rules, enabling seamless failover between regions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Power of Global Availability for SQS
&lt;/h3&gt;

&lt;p&gt;Amazon SQS is a regional service, but many applications require multi-region resilience. This project demonstrates how to achieve global availability for SQS, similar to what AWS has already implemented for services like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon S3 Global Accelerator&lt;/strong&gt;: Provides global endpoints that route to the nearest regional bucket&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon EventBridge Global Endpoints&lt;/strong&gt;: Enables multi-region event routing with automatic failover&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Global Accelerator&lt;/strong&gt;: Provides static IP addresses that route traffic to the optimal AWS endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By implementing a similar pattern for SQS, we gain several benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Increased Availability&lt;/strong&gt;: If one region experiences issues, messages automatically route to another region&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Latency&lt;/strong&gt;: Messages can be processed in the region closest to the consumer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disaster Recovery&lt;/strong&gt;: Automatic failover ensures business continuity during regional outages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Architecture&lt;/strong&gt;: Producers don't need to know which region they're sending to&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2qx1x4m808eo4e73uh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2qx1x4m808eo4e73uh7.png" alt="Architecture diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Innovation: Decoupling Producers from Regional Awareness
&lt;/h3&gt;

&lt;p&gt;The most powerful aspect of this implementation is the complete decoupling of the producer from any regional awareness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The producer sends messages to a single endpoint (sqs-global.example.com)&lt;/li&gt;
&lt;li&gt;Route53 weighted routing determines which regional SQS endpoint receives the message&lt;/li&gt;
&lt;li&gt;The producer continues functioning even during regional failovers&lt;/li&gt;
&lt;li&gt;No code changes or redeployments are needed to handle region changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern enables true "write anywhere, read anywhere" capabilities for SQS, similar to globally distributed databases, but for messaging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;In the below image, you can see that the producer (left side) is posting messages to a route53 url rather than a region specific generic AWS SQS endpoint. The consumer (right side) pulls messages from both regions, calling out which region the message was pulled from. Due to the route53 records being weighted, some messages went to us-east-1 (green), some went to us-west-2 (blue).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funnqshabgldy7nof5oz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funnqshabgldy7nof5oz1.png" alt="client screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a failover scenario, it would be simple to change the weights of either region to 0, forcing all messages to go to the other region. This is important because failing over to a specific region may be due to an application issue with the consumer, and doesn't have to necessarily be an AWS outage. If the consumer application is having trouble in east, it may want messages to end up in the west where it becomes the active instance. Meanwhile, if a producer was posting to east with a failback to west if the east SQS was down, it wouldn't know that it needed to switch if it was strictly based on the health of the SQS service. In an enterprise scenario, with lots of distributed computing, it's important to be as decoupled as possible, removing rigidity wherever feasible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Repository
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kaheidt" rel="noopener noreferrer"&gt;
        kaheidt
      &lt;/a&gt; / &lt;a href="https://github.com/kaheidt/aws-global-sqs" rel="noopener noreferrer"&gt;
        aws-global-sqs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Demonstrates the ability to make your SQS producers regionally agnostic when it comes to posting to SQS endpoints
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AWS Global SQS with Multi-Region Availability&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;This project demonstrates how to create a .NET application that sends messages to Amazon SQS with multi-region capabilities, allowing it to be agnostic about which regional SQS endpoint the message is being sent to. The routing is controlled via Amazon Route53 weighted routing rules, enabling seamless failover between regions.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architecture&lt;/h2&gt;
&lt;/div&gt;

  &lt;div class="js-render-enrichment-target"&gt;
    &lt;div class="render-plaintext-hidden"&gt;
      &lt;pre&gt;graph TB
    subgraph "Producer Application"
        A[Message Producer] --&amp;gt; B[SQS Client]
    end
    
    B --&amp;gt;|"Send to sqs-global.example.com"| C[Route53 DNS]
    
    C --&amp;gt;|"90% Weight"| D[SQS us-east-1]
    C --&amp;gt;|"10% Weight"| E[SQS us-west-2]
    
    subgraph "Consumer Application"
        F[Message Consumer] --&amp;gt; G[Monitor us-east-1]
        F --&amp;gt; H[Monitor us-west-2]
    end
    
    G --&amp;gt; D
    H --&amp;gt; E
    
    subgraph "Route53 Failover Control"
        I[Failover Toggle] --&amp;gt; C
    end
&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;span class="js-render-enrichment-loader d-flex flex-justify-center flex-items-center width-full"&gt;
    &lt;span&gt;
  
    
    
    &lt;span class="sr-only"&gt;Loading&lt;/span&gt;
&lt;/span&gt;
  &lt;/span&gt;


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The Power of Global Availability for SQS&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Amazon SQS is a regional service, but many applications require multi-region resilience. This project demonstrates how to achieve global availability for SQS, similar to what AWS has already implemented for services…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kaheidt/aws-global-sqs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Used Amazon Q Developer
&lt;/h2&gt;

&lt;p&gt;I typically use Github Copilot with Claude 3.7 Sonnet for my AI vibe coding, but I was pleasantly surprised to see how well Amazon Q did from a coding perspective, especially given that I'm using the free tier. This entire project was handled via Amazon Q, and was created in less than a day. I exported the entire conversation with Amazon Q, which you can read &lt;a href="https://github.com/kaheidt/aws-global-sqs/blob/main/conversation.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;. And now for the writeup that Amazon Q produced in regards to how it was used in this project...&lt;/p&gt;

&lt;p&gt;This project was built with significant assistance from Amazon Q Developer, which helped with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Architecture Design&lt;/strong&gt;: Suggesting the Route53-based approach for multi-region routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Generation&lt;/strong&gt;: Creating the complete .NET solution with proper structure and patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Integration&lt;/strong&gt;: Implementing AWS SDK integration with best practices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Troubleshooting&lt;/strong&gt;: Resolving build errors and runtime issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature Enhancement&lt;/strong&gt;: Adding color-coded console output for better visualization&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Amazon Q Developer was instrumental in exploring this innovative approach to SQS global availability, helping to implement a solution that isn't documented in standard AWS patterns.&lt;/p&gt;

&lt;p&gt;Created by &lt;a class="mentioned-user" href="https://dev.to/kevin_heidt_d73c1752454fb"&gt;@kevin_heidt_d73c1752454fb&lt;/a&gt; &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>awschallenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AutoSecure API Gateway: Permissions Redefined</title>
      <dc:creator>kevin heidt</dc:creator>
      <pubDate>Sun, 04 May 2025 17:11:48 +0000</pubDate>
      <link>https://dev.to/kevin_heidt_d73c1752454fb/autosecure-api-gateway-permissions-redefined-4i7i</link>
      <guid>https://dev.to/kevin_heidt_d73c1752454fb/autosecure-api-gateway-permissions-redefined-4i7i</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/permit_io"&gt;Permit.io Authorization Challenge&lt;/a&gt;: Permissions Redefined&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Created by &lt;a class="mentioned-user" href="https://dev.to/kevin_heidt_d73c1752454fb"&gt;@kevin_heidt_d73c1752454fb&lt;/a&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;AutoSecure API Gateway&lt;/strong&gt;, an innovative authorization solution for the automotive industry that tackles the complex web of permissions unique to dealership networks, service centers, and connected vehicle ecosystems.&lt;/p&gt;

&lt;p&gt;The automotive industry presents distinctive authorization challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dealership staff may work across multiple locations with varying permission levels&lt;/li&gt;
&lt;li&gt;Service technicians need temporary access to vehicle systems based on work orders&lt;/li&gt;
&lt;li&gt;Fleet managers require different access levels based on vehicle ownership arrangements&lt;/li&gt;
&lt;li&gt;Vehicle owners expect granular control over who can access their vehicle data&lt;/li&gt;
&lt;li&gt;High employee turnover requires immediate permission revocation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AutoSecure addresses these challenges by implementing API-first authorization through Permit.io and NGINX, allowing centralized policy management while maintaining high-performance gateway-level enforcement.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Try the live demo: &lt;a href="http://nginx-permitio-dev-alb-4vmsoywl-419828416.us-east-1.elb.amazonaws.com/docs" rel="noopener noreferrer"&gt;AutoSecure API Gateway&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Credentials&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin: &lt;code&gt;admin&lt;/code&gt; / &lt;code&gt;2025DEVChallenge&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Regular User: &lt;code&gt;newuser&lt;/code&gt; / &lt;code&gt;2025DEVChallenge&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interactive Swagger UI demonstrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vehicle ownership validation (users can only access vehicles they own)&lt;/li&gt;
&lt;li&gt;Role-based access differentiation (fleet managers vs. service technicians)&lt;/li&gt;
&lt;li&gt;Dealership-specific permissions (access to service records only at authorized locations)&lt;/li&gt;
&lt;li&gt;Temporal authorization (time-limited access for service appointments)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Project Repo
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kaheidt" rel="noopener noreferrer"&gt;
        kaheidt
      &lt;/a&gt; / &lt;a href="https://github.com/kaheidt/nginx-permitio" rel="noopener noreferrer"&gt;
        nginx-permitio
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Demonstrate API First Development with utilization of permit.io
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AutoSecure API Gateway: API-First Authorization for Automotive Industry&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;An innovative API gateway solution leveraging NGINX and Permit.io to implement fine-grained authorization for automotive industry applications.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;LIVE DEMO&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Try it out &lt;a href="http://nginx-permitio-dev-alb-4vmsoywl-419828416.us-east-1.elb.amazonaws.com/docs" rel="nofollow noopener noreferrer"&gt;LIVE HERE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/docs/images/Autosecure_Gateway.jpeg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdocs%2Fimages%2FAutosecure_Gateway.jpeg" alt="Autosecure Gateway: API First"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Project Overview&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;AutoSecure API Gateway demonstrates how API-First authorization principles can be applied to modern automotive industry services. It showcases how authorization can be externalized from application code and enforced at the gateway layer using Permit.io's integration with NGINX.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Use Case: Connected Vehicle Services Platform&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;This project implements a Connected Vehicle Services Platform API with the following components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Vehicle Telemetry API&lt;/strong&gt; - Access to real-time vehicle data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance Services API&lt;/strong&gt; - Schedule and manage service appointments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fleet Management API&lt;/strong&gt; - Monitor and manage vehicle fleets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Driver Behavior Analytics API&lt;/strong&gt; - Access to driving behavior data&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each API has different access control requirements based on user roles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vehicle Owner&lt;/strong&gt; - Access to their own vehicle data and services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service&lt;/strong&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kaheidt/nginx-permitio" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The repository includes comprehensive documentation on how the project models and enforces the complex authorization relationships in the automotive industry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="//docs/architecture.md"&gt;Architecture design&lt;/a&gt; with gateway-level enforcement&lt;/li&gt;
&lt;li&gt;
&lt;a href="//docs/authorization-model.md"&gt;Authorization model&lt;/a&gt; for automotive industry relationships&lt;/li&gt;
&lt;li&gt;
&lt;a href="//docs/api.md"&gt;API documentation&lt;/a&gt; showing permission requirements for endpoints&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Understanding Automotive Access Control Challenges
&lt;/h3&gt;

&lt;p&gt;My first challenge was modeling the complex relationships in automotive dealership networks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relationship Complexity&lt;/strong&gt;: A service technician might work at multiple dealerships but have different certification levels and access rights at each location. For example, a technician certified for Brand A at Dealership X might only have basic access at Dealership Y.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Employee Turnover&lt;/strong&gt;: The automotive industry experiences high turnover rates (15-20% annually for service technicians). Traditional role-based authorization creates security risks when deprovisioning is delayed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-tenant Hierarchies&lt;/strong&gt;: Dealership groups operate multiple locations, with regional managers needing cross-location access while location managers need limited access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connected Vehicle Data&lt;/strong&gt;: Modern vehicles generate telematics data that may need to be shared selectively with service centers only during authorized repair visits.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Implementation Breakthroughs
&lt;/h3&gt;

&lt;p&gt;The key breakthrough came when I realized traditional role-based authorization fails to address these complexities. Instead, I needed to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Model Relationships, Not Just Roles&lt;/strong&gt;: Using Permit.io's flexible policy model, I created relationship-based rules like:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Service tech can only access vehicles at their current assigned dealership &lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;service_technician&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current_dealership_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assigned_dealership_id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Implement Time-bound Access&lt;/strong&gt;: For service appointments, access is granted only during scheduled service windows:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Service tech can access vehicle diagnostic data only during scheduled &lt;/span&gt;
&lt;span class="nx"&gt;appointment&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appointment_start_time&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appointment_end_time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use NGINX As The Enforcement Layer&lt;/strong&gt;: By moving authorization to the API gateway with Permit.io's NGINX integration, I eliminated inconsistent enforcement across microservices.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Technical Challenges Overcome
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Performance Concerns&lt;/strong&gt;: Authorization checks for every API call could create latency. I solved this with:&lt;/li&gt;
&lt;li&gt;Local PDP sidecar for low-latency decisions&lt;/li&gt;
&lt;li&gt;Intelligent caching of authorization decisions&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimized JWT processing in NGINX&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex Authorization Logic&lt;/strong&gt;: Automotive relationship modeling required intricate policies. I addressed this by:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating a hierarchy of policies from simple to complex&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Building reusable policy components with Permit.io&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Separating base role permissions from contextual rules&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Using Permit.io for Authorization
&lt;/h2&gt;

&lt;p&gt;Permit.io transformed how I approached automotive industry authorization in several key ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Context-Aware Authorization
&lt;/h3&gt;

&lt;p&gt;The automotive industry requires authorization decisions based on multiple contexts that traditional RBAC can't handle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A dealership can only access vehicles that were purchased there OR&lt;/span&gt;
&lt;span class="c1"&gt;// are currently being serviced there OR have a valid service agreement&lt;/span&gt;
&lt;span class="nx"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;view&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vehicle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;dealership_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dealership_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;purchase_location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vehicle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;purchase_dealership_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;service_location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vehicle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current_service_location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;service_agreements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vehicle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active_service_agreements&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Relationship-Based Authorization
&lt;/h3&gt;

&lt;p&gt;Using Permit.io's flexible policy model, I created relationship-based rules that reflect the real automotive industry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Regional manager can access data across multiple dealerships&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;regional_manager&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dealership&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region_id&lt;/span&gt;

&lt;span class="c1"&gt;// Service technician access depends on certification level&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;service_technician&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;certification_level&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required_certification_level&lt;/span&gt;

&lt;span class="c1"&gt;// Parts department can view vehicle history only for parts ordering&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;department&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;view_history&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Dynamic Permission Adjustments
&lt;/h3&gt;

&lt;p&gt;Employee roles in automotive often change temporarily (covering shifts, special assignments). Permit.io enabled dynamic permission adjustments without code changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Tech temporarily assigned to another dealership&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;service_technician&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assigned_dealership_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dealership_id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temporary_assignments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dealership_id&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Multi-Brand Dealership Groups
&lt;/h3&gt;

&lt;p&gt;Many dealership groups represent multiple brands, each with different access requirements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Brand-specific certification is required for diagnostics&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;service_technician&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;certifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vehicle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;brand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run_diagnostics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By leveraging Permit.io's flexible policy engine at the NGINX gateway level, AutoSecure provides a comprehensive solution to the automotive industry's unique authorization challenges—finally bringing structured, consistent access control to an industry that has long struggled with it.&lt;/p&gt;

&lt;p&gt;Thank you for considering my submission! I hope AutoSecure API Gateway demonstrates how Permit.io can transform authorization in complex multi-relationship environments like the automotive industry.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>permitchallenge</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>AutoSecure API Gateway: API-First Authorization Reimagined</title>
      <dc:creator>kevin heidt</dc:creator>
      <pubDate>Sun, 04 May 2025 16:55:31 +0000</pubDate>
      <link>https://dev.to/kevin_heidt_d73c1752454fb/autosecure-api-gateway-api-first-authorization-reimagined-21k2</link>
      <guid>https://dev.to/kevin_heidt_d73c1752454fb/autosecure-api-gateway-api-first-authorization-reimagined-21k2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/permit_io"&gt;Permit.io Authorization Challenge&lt;/a&gt;: API-First Authorization Reimagined&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Created by &lt;a class="mentioned-user" href="https://dev.to/kevin_heidt_d73c1752454fb"&gt;@kevin_heidt_d73c1752454fb&lt;/a&gt; 
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;AutoSecure API Gateway&lt;/strong&gt;, a robust API gateway solution for the automotive industry that implements API-first authorization principles. By leveraging &lt;a href="https://docs.permit.io/integrations/gateways/nginx/" rel="noopener noreferrer"&gt;Permit.io's NGINX integration&lt;/a&gt;, the project externalizes authorization logic from application code and enforces fine-grained access control at the gateway layer. This ensures consistent, centralized, and declarative policy enforcement across all APIs.&lt;/p&gt;

&lt;p&gt;The project demonstrates real-world use cases, such as managing vehicle telemetry, fleet operations, and driver analytics, while supporting multiple roles like vehicle owners, service technicians, and fleet managers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Try the live demo: &lt;a href="http://nginx-permitio-dev-alb-4vmsoywl-419828416.us-east-1.elb.amazonaws.com/docs" rel="noopener noreferrer"&gt;AutoSecure API Gateway&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Admin Credentials&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Username: &lt;code&gt;admin&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Password: &lt;code&gt;2025DEVChallenge&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Credentials&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Username: &lt;code&gt;newuser&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Password: &lt;code&gt;2025DEVChallenge&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repo is also easy to implement locally for modification and testing as desired. Take a look at the &lt;a href="https://github.com/kaheidt/nginx-permitio/tree/main?tab=readme-ov-file#getting-started" rel="noopener noreferrer"&gt;Quick Start&lt;/a&gt; for more info. Almost everything is scripted for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Repo
&lt;/h2&gt;

&lt;p&gt;Check out the full project repository here: &lt;a href="https://github.com/kaheidt/nginx-permitio" rel="noopener noreferrer"&gt;GitHub - nginx-permitio&lt;/a&gt; &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kaheidt" rel="noopener noreferrer"&gt;
        kaheidt
      &lt;/a&gt; / &lt;a href="https://github.com/kaheidt/nginx-permitio" rel="noopener noreferrer"&gt;
        nginx-permitio
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Demonstrate API First Development with utilization of permit.io
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AutoSecure API Gateway: API-First Authorization for Automotive Industry&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;An innovative API gateway solution leveraging NGINX and Permit.io to implement fine-grained authorization for automotive industry applications.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;LIVE DEMO&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Try it out &lt;a href="http://nginx-permitio-dev-alb-4vmsoywl-419828416.us-east-1.elb.amazonaws.com/docs" rel="nofollow noopener noreferrer"&gt;LIVE HERE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/docs/images/Autosecure_Gateway.jpeg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdocs%2Fimages%2FAutosecure_Gateway.jpeg" alt="Autosecure Gateway: API First"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Project Overview&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;AutoSecure API Gateway demonstrates how API-First authorization principles can be applied to modern automotive industry services. It showcases how authorization can be externalized from application code and enforced at the gateway layer using Permit.io's integration with NGINX.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Use Case: Connected Vehicle Services Platform&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;This project implements a Connected Vehicle Services Platform API with the following components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Vehicle Telemetry API&lt;/strong&gt; - Access to real-time vehicle data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance Services API&lt;/strong&gt; - Schedule and manage service appointments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fleet Management API&lt;/strong&gt; - Monitor and manage vehicle fleets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Driver Behavior Analytics API&lt;/strong&gt; - Access to driving behavior data&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each API has different access control requirements based on user roles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vehicle Owner&lt;/strong&gt; - Access to their own vehicle data and services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service&lt;/strong&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kaheidt/nginx-permitio" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The repository includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A detailed &lt;a href="https://github.com/kaheidt/nginx-permitio/blob/main/README.md" rel="noopener noreferrer"&gt;README&lt;/a&gt; with setup instructions&lt;/li&gt;
&lt;li&gt;Documentation on &lt;a href="//docs/architecture.md"&gt;architecture&lt;/a&gt;, &lt;a href="//docs/authorization-model.md"&gt;authorization model&lt;/a&gt;, and &lt;a href="//docs/aws-deployment.md"&gt;AWS deployment&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Journey
&lt;/h2&gt;

&lt;p&gt;Building this project was an exciting challenge that required balancing innovation with real-world practicality. You read a full write-up in my &lt;a href="https://github.com/kaheidt/nginx-permitio/blob/main/docs/development-journal.md" rel="noopener noreferrer"&gt;development journal&lt;/a&gt;, but here are some key highlights:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Challenges Faced&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Designing a scalable and secure architecture for API-first authorization.&lt;/li&gt;
&lt;li&gt;Ensuring low-latency authorization decisions while maintaining high availability.&lt;/li&gt;
&lt;li&gt;Integrating Permit.io's NGINX Lua module seamlessly with backend services.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solutions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implemented a &lt;strong&gt;local PDP sidecar&lt;/strong&gt; for fast, reliable policy decisions.&lt;/li&gt;
&lt;li&gt;Used &lt;strong&gt;Terraform&lt;/strong&gt; to automate AWS infrastructure deployment.&lt;/li&gt;
&lt;li&gt;Designed a &lt;strong&gt;multi-tenant architecture&lt;/strong&gt; to support diverse user roles and organizations.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Externalized authorization simplifies API design and improves security.&lt;/li&gt;
&lt;li&gt;Declarative policies enable real-time updates without service disruptions.&lt;/li&gt;
&lt;li&gt;Permit.io's integration with NGINX is a powerful tool for enforcing access control at scale.&lt;/li&gt;
&lt;li&gt;When in doubt, go native. Switching from JS module to Lua made auth subcalls much easier in nginx.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  API-First Authorization
&lt;/h2&gt;

&lt;p&gt;This project embraces API-first principles by externalizing all authorization logic to Permit.io. Key features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Centralized Policy Management&lt;/strong&gt;: Policies are managed in Permit.io's Policy Administration Point (PAP) and synced to the local PDP sidecar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarative Rules&lt;/strong&gt;: Authorization is defined using declarative policies, not hardcoded logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gateway-Level Enforcement&lt;/strong&gt;: NGINX acts as the Policy Enforcement Point (PEP), ensuring consistent access control across all APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Updates&lt;/strong&gt;: Policy changes are applied instantly without requiring service restarts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fine-Grained Access Control&lt;/strong&gt;: Combines RBAC and ABAC to support complex automotive use cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a detailed explanation of the architecture and authorization model, see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="//docs/architecture.md"&gt;Architecture Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="//docs/authorization-model.md"&gt;Authorization Model Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thank you for considering my submission! I hope this project inspires others to explore API-first authorization with Permit.io.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>permitchallenge</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Roboverse!</title>
      <dc:creator>kevin heidt</dc:creator>
      <pubDate>Mon, 21 Apr 2025 16:21:42 +0000</pubDate>
      <link>https://dev.to/kevin_heidt_d73c1752454fb/roboverse-3dac</link>
      <guid>https://dev.to/kevin_heidt_d73c1752454fb/roboverse-3dac</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://int.alibabacloud.com/m/1000402443/" rel="noopener noreferrer"&gt;Alibaba Cloud&lt;/a&gt; Challenge: &lt;a href="https://dev.to/challenges/alibaba"&gt;Build a Web Game&lt;/a&gt;.&lt;/em&gt;*&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;RoboVerse is an innovative 3D robot-themed web game that combines creative building mechanics with strategic battle gameplay. Players can design their own unique robots through an intuitive customization system, selecting different heads, bodies, arms, and legs - each affecting the robot's capabilities in battle.&lt;/p&gt;

&lt;p&gt;This was my introduction to vibecoding, letting copilot do most of the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://roboverse.humanless.app/" rel="noopener noreferrer"&gt;https://roboverse.humanless.app/&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kaheidt" rel="noopener noreferrer"&gt;
        kaheidt
      &lt;/a&gt; / &lt;a href="https://github.com/kaheidt/alibaba-robots" rel="noopener noreferrer"&gt;
        alibaba-robots
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;RoboVerse&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A 3D robot-themed web game built with React, Three.js, and Alibaba Cloud services.&lt;/p&gt;
&lt;p&gt;See it live: &lt;a href="https://roboverse.humanless.app/" rel="nofollow noopener noreferrer"&gt;https://roboverse.humanless.app/&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Interactive 3D robot building and customization&lt;/li&gt;
&lt;li&gt;Real-time robot battles with physics&lt;/li&gt;
&lt;li&gt;Cloud-based save system using Alibaba Cloud OSS&lt;/li&gt;
&lt;li&gt;Global leaderboards powered by ApsaraDB&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Prerequisites&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Node.js (compatible with React 19)&lt;/li&gt;
&lt;li&gt;Docker and Docker Compose&lt;/li&gt;
&lt;li&gt;Terraform (optional, for cloud deployment)&lt;/li&gt;
&lt;li&gt;MySQL 8.0 (automatically handled by Docker)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Clone the repository&lt;/li&gt;
&lt;li&gt;Install dependencies:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in the root directory with your database and server configuration:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-dotenv notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; API Server Config&lt;/span&gt;
&lt;span class="pl-v"&gt;PORT&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;3001&lt;/span&gt;

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Frontend Config&lt;/span&gt;
&lt;span class="pl-v"&gt;VITE_API_URL&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;http://localhost:3001/api&lt;/span&gt;

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Database Config (Docker)&lt;/span&gt;
&lt;span class="pl-v"&gt;DB_HOST&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;localhost&lt;/span&gt;
&lt;span class="pl-v"&gt;DB_USER&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;root&lt;/span&gt;
&lt;span class="pl-v"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;rootpassword&lt;/span&gt;
&lt;span class="pl-v"&gt;DB_NAME&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;roboverse&lt;/span&gt;
&lt;span class="pl-v"&gt;DB_PORT&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;3306&lt;/span&gt;

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Alibaba Cloud Config (Server-side only)&lt;/span&gt;
&lt;span class="pl-v"&gt;ALIBABA_OSS_REGION&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;your-region&lt;/span&gt;
&lt;span class="pl-v"&gt;ALIBABA_OSS_BUCKET&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;your-bucket&lt;/span&gt;
&lt;span class="pl-v"&gt;ALIBABA_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;your-access-key&lt;/span&gt;
&lt;span class="pl-v"&gt;ALIBABA_ACCESS_KEY_SECRET&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;your-secret-key&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="4"&gt;
&lt;li&gt;Start the MySQL database with Docker:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;docker-compose up -d&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The database will be automatically initialized…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kaheidt/alibaba-robots" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Alibaba Cloud Services Implementation
&lt;/h2&gt;

&lt;p&gt;Originally designed to run on ECS using an autoscaling group, I shifted the architecture to instead use SAE in an effort to optimize costs, based on the understanding that I didn't need instances running all the time as users would be inconsistent. All architecture is implemented via IAC using terraform, so that it's easy stand-up in another account as needed. Some challenges I had included activating each individual service before I was able to use it via terraform, but the support staff was very quick to help me resolve any issues. I had a little trouble with getting my custom domain to work with the CDN because of some built in blacklisting they have, and also because Cloudflare offers up edge tls for free, but only if you use it as a proxy and not a straight cname dns. This made things a little wonky with domain validation for the CDN, and I didn't want to have to pay for https traffic through the CDN, so I had to do a couple steps to resolve that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxw9pk6ybv9ylbd3obcy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxw9pk6ybv9ylbd3obcy.png" alt="SAE Cloud arch diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SAE System Components
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Content Delivery Network (CDN)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Global distribution of static assets&lt;/li&gt;
&lt;li&gt;Reduced latency for textures, models and scripts&lt;/li&gt;
&lt;li&gt;Optimized caching policies for different file types&lt;/li&gt;
&lt;li&gt;HTTPS and HTTP/2 support&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Serverless App Engine (SAE)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-scaling Node.js applications&lt;/li&gt;
&lt;li&gt;Built-in load balancing&lt;/li&gt;
&lt;li&gt;Zero infrastructure management&lt;/li&gt;
&lt;li&gt;Pay-per-use model&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Object Storage Service (OSS)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Game assets storage&lt;/li&gt;
&lt;li&gt;Player save data&lt;/li&gt;
&lt;li&gt;Origin server for CDN&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ApsaraDB RDS (MySQL)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Player profiles&lt;/li&gt;
&lt;li&gt;Leaderboard data&lt;/li&gt;
&lt;li&gt;Game statistics&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Container Registry&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application container images&lt;/li&gt;
&lt;li&gt;Automated deployment pipeline&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Security Components&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RAM for access control&lt;/li&gt;
&lt;li&gt;VPC security groups&lt;/li&gt;
&lt;li&gt;SSL/TLS encryption&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  SAE Monthly Cost Estimation (100 Active Users)
&lt;/h3&gt;

&lt;p&gt;Based on Alibaba Cloud pricing in US West 1 region (Silicon Valley):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Serverless App Engine&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vCPU usage: $25.20/month (0.5 vCPU × 720 hours)&lt;/li&gt;
&lt;li&gt;Memory usage: $12.60/month (1GB × 720 hours)&lt;/li&gt;
&lt;li&gt;Request processing: ~$8/month&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ApsaraDB RDS (MySQL)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RDS.MySQL.s1.small: $34.50/month&lt;/li&gt;
&lt;li&gt;Storage (20GB): $2.76/month&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Object Storage&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storage (estimated 50GB): $1.15/month&lt;/li&gt;
&lt;li&gt;Requests and bandwidth: ~$3/month&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Container Registry&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic instance: Free&lt;/li&gt;
&lt;li&gt;Storage: ~$1/month&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Transfer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal: Free&lt;/li&gt;
&lt;li&gt;Internet outbound: ~$10/month&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Total Estimated Monthly Cost: $98.21&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: This represents approximately 29% cost savings compared to the ECS-based architecture. Costs may vary based on actual usage patterns, data transfer, and storage needs. The serverless model ensures you only pay for actual resource consumption.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost Optimization Tips
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Use reserved instances for the base ECS instance to save 30%&lt;/li&gt;
&lt;li&gt;Implement proper caching to reduce database load&lt;/li&gt;
&lt;li&gt;Configure auto-scaling thresholds carefully&lt;/li&gt;
&lt;li&gt;Use OSS lifecycle rules to manage storage costs&lt;/li&gt;
&lt;li&gt;Monitor and optimize data transfer patterns&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fknfiy843rgnbma70691a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fknfiy843rgnbma70691a.png" alt="Original cloud arch diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Game Development Highlights
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Interactive 3D robot building and customization&lt;/li&gt;
&lt;li&gt;Real-time robot battles with physics&lt;/li&gt;
&lt;li&gt;Cloud-based save system using Alibaba Cloud OSS&lt;/li&gt;
&lt;li&gt;Global leaderboards powered by ApsaraDB&lt;/li&gt;
&lt;li&gt;Preloading of sound assets from CDN&lt;/li&gt;
&lt;li&gt;Scalability using Serverless App Engine (SAE)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm80u09a0pxe48kajrfvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm80u09a0pxe48kajrfvm.png" alt="screenshot of game"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz139m5w55jq3e8p6y83n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz139m5w55jq3e8p6y83n.png" alt="screenshot of game"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx85xr0wb9objf7x1zlgy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx85xr0wb9objf7x1zlgy.png" alt="screenshot of game"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92hcwyxj589sd38cv95c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92hcwyxj589sd38cv95c.png" alt="screenshot of game"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Created by Kevin Heidt &lt;a href="https://dev.to/kevin_heidt_d73c1752454fb"&gt;@kevin_heidt_d73c1752454fb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>alibabachallenge</category>
      <category>devchallenge</category>
      <category>gamedev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
