<?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: Auth By Example</title>
    <description>The latest articles on DEV Community by Auth By Example (@authbyexample1).</description>
    <link>https://dev.to/authbyexample1</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4129486%2F81de18e5-31aa-4a61-8180-8828f484068b.png</url>
      <title>DEV Community: Auth By Example</title>
      <link>https://dev.to/authbyexample1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/authbyexample1"/>
    <language>en</language>
    <item>
      <title>An engineering checklist for Australia's APP 1.7, which starts on 10 December 2026</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Sun, 01 Nov 2026 09:06:04 +0000</pubDate>
      <link>https://dev.to/authbyexample1/an-engineering-checklist-for-australias-app-17-which-starts-on-10-december-2026-1ng6</link>
      <guid>https://dev.to/authbyexample1/an-engineering-checklist-for-australias-app-17-which-starts-on-10-december-2026-1ng6</guid>
      <description>&lt;p&gt;I work at Permit, and this is adapted from a checklist our CEO published on our blog, so keep that in mind. It isn't legal advice either. Your privacy counsel decides whether APP 1.7 applies to you and what the policy says.&lt;/p&gt;

&lt;p&gt;Some background first. APP 1.7 to 1.9 start on 10 December 2026 under the Privacy and Other Legislation Amendment Act 2024. If an APP entity arranges for a computer program to use personal information to make a decision, or to substantially and directly assist with one, and that decision could reasonably be expected to significantly affect someone's rights or interests, the privacy policy has to say so. APP 1.8 lists what goes in: the kinds of personal information used, the kinds of decisions the program makes on its own, and the kinds of decisions it substantially and directly assists.&lt;/p&gt;

&lt;p&gt;Legal writes those sentences, but engineering is the one who can tell whether they're true. The checklist splits that work into four areas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enforcement
&lt;/h2&gt;

&lt;p&gt;Find every place where software decides, routes, ranks, approves, denies, recommends or escalates using personal information. That includes APIs, workflow engines, background jobs, rules services and model gateways, so it's a wider list than the AI feature. Eligibility checks, fraud scoring, account restrictions, pricing and triage can all count. For each one, write down the owner, the decision type, what personal information it can see, and what happens downstream.&lt;/p&gt;

&lt;h2&gt;
  
  
  Granularity
&lt;/h2&gt;

&lt;p&gt;A line like "financial information may be used in eligibility decisions" only holds up if you know which attributes which service reads, for which action, in which product or tenant. Map personal information categories to resources, actions and tenants, and mark each path as a solely automated decision, an assisted one, or probably out of scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Realtime
&lt;/h2&gt;

&lt;p&gt;A policy statement that's accurate today can go stale after a new model, a feature flag, a new data source, or a workflow that moves from human review to auto-approval. Decide which changes trigger a re-review, and make sure revoking access reaches the code that actually enforces it, so the change isn't only recorded in a spreadsheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audit and export
&lt;/h2&gt;

&lt;p&gt;For each decision category, the logs should show what happened, whether it was solely automated or assisted, the kinds of personal information used or available, the resource, action and tenant, and the policy, model or rules version. Deny logs help too, because they show what was blocked and why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The working list
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;List the services, workflows, APIs, models, rules, prompts and jobs that make or substantially assist significant decisions.&lt;/li&gt;
&lt;li&gt;Find the enforcement point for each one.&lt;/li&gt;
&lt;li&gt;Classify each path as solely automated, substantially and directly assisted, or likely out of scope.&lt;/li&gt;
&lt;li&gt;Map kinds of personal information to resources, actions, tenants, products and decision categories.&lt;/li&gt;
&lt;li&gt;Note which attributes are required, optional, inferred, or just accessible.&lt;/li&gt;
&lt;li&gt;Document who can change access, routing rules, model deployments, prompts and thresholds.&lt;/li&gt;
&lt;li&gt;Define how revocation and sync work when access or decision logic changes.&lt;/li&gt;
&lt;li&gt;Log decision context, data category, policy version, resource, action, tenant and outcome.&lt;/li&gt;
&lt;li&gt;Export evidence in a format your privacy and legal people can work from.&lt;/li&gt;
&lt;li&gt;Re-review the disclosure wording whenever any of the above changes in a material way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full version, with a table mapping each area to the question it answers, is here: &lt;a href="https://www.permit.io/blog/four-pillars-app17-checklist?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=four-pillars-app17-checklist&amp;amp;utm_content=authbyexample-article" rel="noopener noreferrer"&gt;https://www.permit.io/blog/four-pillars-app17-checklist?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=four-pillars-app17-checklist&amp;amp;utm_content=authbyexample-article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We build authorization tooling (enforcement points in the app, a hybrid decision point, and OPAL for syncing policy and data), which is why we care about this topic. None of that makes anyone Privacy Act compliant by itself.&lt;/p&gt;

&lt;p&gt;If you're already doing APP 1.7 prep, I'm curious whether you started from the system inventory or from the draft policy wording, and how that went.&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>compliance</category>
      <category>authorization</category>
    </item>
    <item>
      <title>Your CSV export might include the columns your UI hides</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Sun, 01 Nov 2026 09:05:35 +0000</pubDate>
      <link>https://dev.to/authbyexample1/your-csv-export-might-include-the-columns-your-ui-hides-1bc5</link>
      <guid>https://dev.to/authbyexample1/your-csv-export-might-include-the-columns-your-ui-hides-1bc5</guid>
      <description>&lt;p&gt;I keep running into the same bug. The app hides salary, cost, or internal notes from some roles. The frontend leaves the column out and the detail API strips the field for those users. Then someone adds "Export to CSV", and the export builds rows straight from the ORM model. Every column lands in the file for anyone who can click the button.&lt;/p&gt;

&lt;p&gt;The field rules usually live in the serializer for one endpoint. The export is a separate code path written later, often by someone else, and often as a background job that writes a file, so it never goes through that serializer.&lt;/p&gt;

&lt;p&gt;What has worked for me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put the decision "which fields can this user see on this record type" in one function, and have both the API serializer and the export call it. The export asks for the allowed columns before it writes the header row.&lt;/li&gt;
&lt;li&gt;Run the export as the user who asked for it. If it runs as a job, pass the requesting user's id and check again when the job actually runs, since their role may have changed while it sat in the queue.&lt;/li&gt;
&lt;li&gt;Reuse the list endpoint's row filter so the export only pulls records the user could already see in the list.&lt;/li&gt;
&lt;li&gt;Add a test per role that exports a fixture and asserts the header row. It's cheap, and it catches the next column someone adds to the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scheduled reports and "email me this view" links have the same problem. Anything that turns records into a file tends to skip the response layer where the field rules were written.&lt;/p&gt;

&lt;p&gt;How do you handle it? Do you have one field-permission function, or does each output format carry its own rules?&lt;/p&gt;

</description>
      <category>security</category>
      <category>authorization</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Soft delete adds a trash page and a restore button. Do they get the same permission checks as the rest of your API?</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Sat, 31 Oct 2026 09:07:12 +0000</pubDate>
      <link>https://dev.to/authbyexample1/soft-delete-adds-a-trash-page-and-a-restore-button-do-they-get-the-same-permission-checks-as-the-1n19</link>
      <guid>https://dev.to/authbyexample1/soft-delete-adds-a-trash-page-and-a-restore-button-do-they-get-the-same-permission-checks-as-the-1n19</guid>
      <description>&lt;p&gt;Most apps I've worked on move to soft delete at some point. A &lt;code&gt;deleted_at&lt;/code&gt; column goes on the table, the default scope hides those rows, and a sprint later someone adds a Trash page with a restore button. That last step is where I keep finding authorization gaps.&lt;/p&gt;

&lt;p&gt;The first one is the tenant filter. The normal read path goes through a scope that filters by tenant and hides deleted rows. The trash page needs the deleted rows, so someone reaches for &lt;code&gt;Document.unscoped&lt;/code&gt; (or whatever your ORM calls it). In Rails, &lt;code&gt;unscoped&lt;/code&gt; drops every default scope, so if the tenant filter lived in the same &lt;code&gt;default_scope&lt;/code&gt; as &lt;code&gt;deleted_at IS NULL&lt;/code&gt;, it's gone too. The trash list now shows deleted documents from every tenant, and nobody notices because in dev there's only one.&lt;/p&gt;

&lt;p&gt;The second one is restore. It usually gets a role check like "editors can restore", which says nothing about whether this editor could ever see this document. Per-record checks are awkward here, because the sharing or folder lookups often skip deleted rows, so the check fails and someone removes it to make restore work.&lt;/p&gt;

&lt;p&gt;What I do now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep the tenant filter apart from the soft-delete filter, so dropping one can't drop the other. If you use Postgres row-level security, the tenant policy shouldn't mention &lt;code&gt;deleted_at&lt;/code&gt; at all.&lt;/li&gt;
&lt;li&gt;Keep the owner, folder and shares on the row when it's soft deleted, and run the same per-record check for viewing trash and for restore that you run for edit.&lt;/li&gt;
&lt;li&gt;Add the trash and restore endpoints to the test that walks every route as a user from another tenant and expects a 404.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do you handle it? Is restore its own permission in your model, or does it ride on delete?&lt;/p&gt;

</description>
      <category>security</category>
      <category>authorization</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>APP 1.7 starts on 10 December 2026. Here is the engineering evidence an automated-decision disclosure needs</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Sat, 31 Oct 2026 09:06:46 +0000</pubDate>
      <link>https://dev.to/authbyexample1/app-17-starts-on-10-december-2026-here-is-the-engineering-evidence-an-automated-decision-2a1h</link>
      <guid>https://dev.to/authbyexample1/app-17-starts-on-10-december-2026-here-is-the-engineering-evidence-an-automated-decision-2a1h</guid>
      <description>&lt;p&gt;I work at Permit, and this is based on a post our CEO wrote for our blog, so read it with that in mind. It's also not legal advice. Privacy counsel decides the wording and the scope.&lt;/p&gt;

&lt;p&gt;From 10 December 2026, APP 1.7 under Australia's Privacy Act changes what some privacy policies have to say. It applies when an APP entity arranges for a computer program to make a decision, or to do something substantially and directly related to making one, where the decision could significantly affect a person's rights or interests and personal information about that person is used in the program. In that case the privacy policy has to describe the kinds of personal information used and the kinds of decisions involved, split into decisions the program makes on its own and decisions it substantially assists.&lt;/p&gt;

&lt;p&gt;A few details from APP 1.9 and the OAIC that engineers tend to miss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refusing or failing to make a decision counts as making one.&lt;/li&gt;
&lt;li&gt;It applies whether the outcome is good or bad for the person.&lt;/li&gt;
&lt;li&gt;It isn't limited to AI. Rules engines, scoring systems, workflow automation and agents can all be in scope.&lt;/li&gt;
&lt;li&gt;It covers decisions made from 10 December 2026, no matter when the system was built or the data was collected.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this lands on engineering
&lt;/h2&gt;

&lt;p&gt;Legal writes the policy, but they can only describe what you can show them. If nobody knows which services and agents read which personal data on a decision path, "the kinds of personal information used" ends up as a guess.&lt;/p&gt;

&lt;p&gt;The post's homework list, shortened:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inventory every program, workflow and agent that makes, refuses, routes or substantially assists a significant decision. Include rules engines and fraud workflows along with models. Record the owner, whether it decides alone or assists, what personal information it uses, and how it's enforced and logged today.&lt;/li&gt;
&lt;li&gt;Map kinds of personal information to concrete resources and actions, like &lt;code&gt;transactions.read&lt;/code&gt; or &lt;code&gt;service_access.refuse&lt;/code&gt;. "The risk service can read customer data" is too vague to disclose against.&lt;/li&gt;
&lt;li&gt;Put enforcement points in two places: before anything reads personal information, and before a system approves, refuses, routes or escalates.&lt;/li&gt;
&lt;li&gt;Write policy at that level. Can this workflow use data for triage but not for a refusal? Can this model recommend a review but not decide?&lt;/li&gt;
&lt;li&gt;Keep authorization data in sync. When an agent gets a new tool or a workflow adds a data source, slow permission updates mean your evidence describes an older system.&lt;/li&gt;
&lt;li&gt;Keep decision logs with identity, resource, action, policy, tenant, time and result, so the policy statement rests on production facts instead of interviews.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's also a section on APRA's April 2026 letter on AI, which raises related themes (IAM for agents and other non-human actors, privileged access to tools and models, AI inventories). That's parallel pressure for APRA-regulated entities. APP 1.7 itself isn't an APRA requirement.&lt;/p&gt;

&lt;p&gt;The full post has a 90/60/30-day countdown to 10 December and covers where Permit fits: &lt;a href="https://www.permit.io/blog/au-app17-apra-deadline?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=au-app17-apra-deadline&amp;amp;utm_content=authbyexample-article" rel="noopener noreferrer"&gt;10 December 2026: APP 1.7 and the authorization evidence behind automated decisions&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>compliance</category>
      <category>authorization</category>
    </item>
    <item>
      <title>401 or 403? The status code shows whether your app keeps login and permissions apart</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Sat, 31 Oct 2026 09:06:19 +0000</pubDate>
      <link>https://dev.to/authbyexample1/401-or-403-the-status-code-shows-whether-your-app-keeps-login-and-permissions-apart-5dob</link>
      <guid>https://dev.to/authbyexample1/401-or-403-the-status-code-shows-whether-your-app-keeps-login-and-permissions-apart-5dob</guid>
      <description>&lt;p&gt;I work at Permit, and this is based on a post on our blog, so read it with that in mind. Most of it applies whatever you use for authorization.&lt;/p&gt;

&lt;p&gt;The short version: authentication (AuthN) establishes who the caller is. Authorization (AuthZ) decides what that caller can do with a specific resource. A user can be fully logged in and still not be allowed to export an invoice from another tenant.&lt;/p&gt;

&lt;h2&gt;
  
  
  The status code mix-up
&lt;/h2&gt;

&lt;p&gt;HTTP made this confusing by naming 401 "Unauthorized". In practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;401 means the request isn't authenticated: missing token, expired session, bad API key. The client should log in again or refresh.&lt;/li&gt;
&lt;li&gt;403 means the caller is known and policy says no. The client should show access denied or offer a way to request access.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Getting these right helps more than the client. "We don't know who this is" and "we know who this is and they're not allowed" are different events in your logs and during an incident. If both come out as 401, or both as 403, you lose that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your IdP doesn't answer the second question
&lt;/h2&gt;

&lt;p&gt;Okta, Auth0, Entra ID and the rest handle login, SSO, MFA and user lifecycle, and you shouldn't rebuild any of that. They can also tell you Alice is in the Finance group. They can't tell you whether Alice may export invoice:987 in tenant:acme on the current plan, because that depends on your product's resources, actions, tenants and workflow state.&lt;/p&gt;

&lt;p&gt;So most apps start with something like &lt;code&gt;if user.role == "admin": allow()&lt;/code&gt;. That holds up until you add tenants, custom roles, delegated admins and audit requirements. Then the checks spread across endpoints, UI components and background jobs, and nobody can say in one place who can do what.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask why, as well as allow or deny
&lt;/h2&gt;

&lt;p&gt;The post also argues that a decision should be explainable after the fact: which policy applied, and which role or attribute produced the result. Support and auditors will ask, and "the code returned false" doesn't answer them.&lt;/p&gt;

&lt;p&gt;A quick check you can run on your own API: pick an endpoint, call it with no token, then with a valid token for a user who lacks the permission. You should get 401 and then 403, and the second call should leave a log line saying which rule denied it.&lt;/p&gt;

&lt;p&gt;The full post has a table of the two codes, more on the IdP split, and how we approach it at Permit (a policy decision point running next to the app): &lt;a href="https://www.permit.io/blog/authn-vs-authz?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=authn-vs-authz&amp;amp;utm_content=authbyexample-article" rel="noopener noreferrer"&gt;What's the difference between authentication and authorization?&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>api</category>
      <category>authorization</category>
    </item>
    <item>
      <title>Your background job checked permissions when it was queued. Who is it acting for when it runs?</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Fri, 30 Oct 2026 09:10:35 +0000</pubDate>
      <link>https://dev.to/authbyexample1/your-background-job-checked-permissions-when-it-was-queued-who-is-it-acting-for-when-it-runs-4o4i</link>
      <guid>https://dev.to/authbyexample1/your-background-job-checked-permissions-when-it-was-queued-who-is-it-acting-for-when-it-runs-4o4i</guid>
      <description>&lt;p&gt;A pattern I keep running into: the API handler checks that the user can export the report, delete the project or send the invoices, then drops a job on a queue and returns 202. The worker picks it up later and does the work with a service account that can touch everything.&lt;/p&gt;

&lt;p&gt;That check happened at enqueue time. If the job sits in the queue for an hour, or retries over a day, the user could have been removed from the org, lost the admin role, or had the project moved to another workspace in the meantime. The worker never asks again, so the action still goes through.&lt;/p&gt;

&lt;p&gt;A few things that have helped on teams I've worked with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put the acting user ID and tenant ID in the job payload, never only the object ID. A job without an actor is impossible to audit later.&lt;/li&gt;
&lt;li&gt;Re-check the permission in the worker right before the side effect, using current data. The handler check stays for fast feedback; the worker check is the one that counts.&lt;/li&gt;
&lt;li&gt;Decide what a failed re-check means. Usually it's "drop the job and log it", not "retry", or you get a retry loop that keeps hitting a 403.&lt;/li&gt;
&lt;li&gt;Scope the worker's credentials per tenant where you can, so a bad payload can't reach another customer's rows.&lt;/li&gt;
&lt;li&gt;For scheduled jobs (nightly exports, recurring emails), store who created the schedule and check that person still has access on each run. Schedules outlive the people who set them up more often than you'd think.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The test I like: create the job, revoke the user's role, then run the worker. If the export still lands in their inbox, the queue is acting with more permission than the user has.&lt;/p&gt;

&lt;p&gt;How do you handle this? Do your workers re-check per job, or do you trust the enqueue-time check and keep queues short?&lt;/p&gt;

</description>
      <category>security</category>
      <category>authorization</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Your GET /docs/:id has a permission check. Does GET /docs?</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Fri, 30 Oct 2026 09:10:16 +0000</pubDate>
      <link>https://dev.to/authbyexample1/your-get-docsid-has-a-permission-check-does-get-docs-38lm</link>
      <guid>https://dev.to/authbyexample1/your-get-docsid-has-a-permission-check-does-get-docs-38lm</guid>
      <description>&lt;p&gt;Most apps I've looked at guard single-object routes fine. You fetch the document, check the user can read it, return 403 or 404 if not. The list endpoint is where things slip.&lt;/p&gt;

&lt;p&gt;A common version: the list query filters by tenant_id and nothing else. Inside one tenant, everybody sees every row, including private drafts, HR folders, or a project they were removed from last week. Another version: the list does filter, but search, export, autocomplete, and the "recent items" widget each run their own query, and only one of them got the filter.&lt;/p&gt;

&lt;p&gt;A few things that have worked for me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Put the permission filter in one function that returns a query, and make every list-shaped endpoint call it. Search, export, and counts included.&lt;/li&gt;
&lt;li&gt;Don't load everything and then drop rows in application code. Pagination breaks (page 1 comes back with 3 items out of 20), and totals leak how many hidden rows exist.&lt;/li&gt;
&lt;li&gt;Write one test per list endpoint with two users in the same tenant who should see different things. Assert on the IDs returned, and on the total count.&lt;/li&gt;
&lt;li&gt;Watch the count badges. "You have 14 documents" next to a list of 9 tells people something.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For simple role checks, a WHERE clause is enough. Once sharing and nested folders come in ("can see it because they can see the parent folder"), the filter gets harder to express in SQL, and that's usually when teams start thinking about a separate authorization layer that can answer "which IDs can this user see?" as well as yes/no questions.&lt;/p&gt;

&lt;p&gt;How do you handle list filtering when permissions are inherited through folders or teams?&lt;/p&gt;

</description>
      <category>security</category>
      <category>authorization</category>
      <category>webapp</category>
      <category>backend</category>
    </item>
    <item>
      <title>Give your AI ops agent read access to prod, and make every write ask first</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Fri, 30 Oct 2026 09:09:51 +0000</pubDate>
      <link>https://dev.to/authbyexample1/give-your-ai-ops-agent-read-access-to-prod-and-make-every-write-ask-first-m98</link>
      <guid>https://dev.to/authbyexample1/give-your-ai-ops-agent-read-access-to-prod-and-make-every-write-ask-first-m98</guid>
      <description>&lt;p&gt;I work at Permit, and this comes from a post on our blog about governing AI ops agents, so keep the bias in mind. Nothing below depends on our product.&lt;/p&gt;

&lt;p&gt;Incident agents are getting good at pulling logs, metrics and Kubernetes events together and suggesting a root cause. The post deals with what happens when the same agent can also restart a service or edit RBAC. Investigating production and changing it are separate permissions, and they should be granted separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Group tools by what they do
&lt;/h2&gt;

&lt;p&gt;The post sorts operations into four tiers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;T0, inspect and read: list, get, log and metric queries, config fetches. Allowed in prod for approved agent identities, with full logging.&lt;/li&gt;
&lt;li&gt;T1, diagnose and test: profiling, dry runs, diff checks, policy simulation. Allowed with limits on rate, scope and data.&lt;/li&gt;
&lt;li&gt;T2, ticket or draft change: open an incident, draft a PR or a remediation plan. Allowed, with attribution and a reviewer assigned.&lt;/li&gt;
&lt;li&gt;T3, restart, modify, deploy, delete, change permissions: needs step-up, explicit approval, or a deny, depending on environment and policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tiers attach to individual operations. One Microsoft Graph or Azure MCP server can expose a harmless read and a role assignment side by side, so trusting a whole server at one level doesn't work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The check on each call
&lt;/h2&gt;

&lt;p&gt;Every tool call gets evaluated on four inputs: the agent's identity, the person who delegated the task, the stated intent, and the target environment. The answer is allow, step-up, or deny.&lt;/p&gt;

&lt;p&gt;Two rules from the post I'd copy. Delegation shouldn't raise the ceiling, so a low-trust assistant working for an SRE stays at T1 in production even though the SRE could do T3 work directly. And an approval button in chat is just UI. The step-up is the policy confirming the approver has the right role, authenticated recently (the example uses 15 minutes), and has a change ticket.&lt;/p&gt;

&lt;h2&gt;
  
  
  The audit trail
&lt;/h2&gt;

&lt;p&gt;A chat transcript won't be enough after an incident. The post lists the evidence the agent used (sources, query windows), every tool call with its parameters, the hypothesis tree with confidence changes, each policy decision with its reason, who approved what under which incident or change ID, and the outcome with rollback notes. Without parameters you can't tell "listed pods in namespace X" from "deleted a deployment in namespace X".&lt;/p&gt;

&lt;p&gt;Full post, with a sample policy and per-tool examples for Azure, Entra ID, GitHub, CI/CD and Kubernetes: &lt;a href="https://www.permit.io/blog/read-only-trust-level-ai-ops-agents?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=read-only-trust-level-ai-ops-agents&amp;amp;utm_content=authbyexample-article" rel="noopener noreferrer"&gt;https://www.permit.io/blog/read-only-trust-level-ai-ops-agents?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=read-only-trust-level-ai-ops-agents&amp;amp;utm_content=authbyexample-article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run an ops agent against production, where did you draw the line between what it does alone and what needs a person?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>security</category>
      <category>mcp</category>
    </item>
    <item>
      <title>A better spec won't stop a coding agent from deploying to prod</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Wed, 28 Oct 2026 16:07:58 +0000</pubDate>
      <link>https://dev.to/authbyexample1/a-better-spec-wont-stop-a-coding-agent-from-deploying-to-prod-5dae</link>
      <guid>https://dev.to/authbyexample1/a-better-spec-wont-stop-a-coding-agent-from-deploying-to-prod-5dae</guid>
      <description>&lt;p&gt;I work at Permit, and this is from a post our CEO wrote on zero standing permissions for coding and automation agents. We sell authorization, so keep the bias in mind. The ideas work in any stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specs help accuracy. They don't limit access.
&lt;/h2&gt;

&lt;p&gt;A detailed PRD makes an agent's output better, with fewer retries and fewer surprise changes. Say the spec reads "update deployment config in staging only". If the agent holds a token that can deploy to production, the spec is just a request. Whatever the credential allows is what can happen.&lt;/p&gt;

&lt;p&gt;The post suggests using the spec as input to a permission check. Pull the intended resource, action, environment and risk level out of it, and have a policy decide whether a given tool call fits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with nothing
&lt;/h2&gt;

&lt;p&gt;Zero standing permissions means the agent holds no lasting authority between tasks. When someone approves a task (a ticket, a PR comment, a chat command), the runtime works out what it needs, sorts each tool call by risk (read, write, deploy, notify, money, sensitive data) and asks a policy whether it's allowed. If it is, it mints a short-lived credential for only those actions. Going from staging to production needs another approval. High-risk steps get checked again when they happen, and the grant is revoked if the task drifts or times out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credential options, roughly from worst to best
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Static API keys: easy to set up, but long-lived, hard to rotate, over-scoped, and hard to trace back to a person.&lt;/li&gt;
&lt;li&gt;Service accounts for the agent: kept apart from human identities, which helps, but still risky when the permissions are broad and permanent. Fine for narrow jobs like indexing docs or scheduled read-only checks.&lt;/li&gt;
&lt;li&gt;OAuth delegated access: good when the action happens in a user's context and you want a grant you can revoke. Scopes are often coarse.&lt;/li&gt;
&lt;li&gt;Runtime policy plus short-lived tokens: least privilege per task, at the cost of building or buying the policy layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the audit log should answer
&lt;/h2&gt;

&lt;p&gt;Which person approved this deploy, which agent and version ran it, under which policy version, with which token (scopes, issue time, expiry), and what changed? The post's schema also has the ticket or spec reference, the MCP tool and resource, the policy decision and its reason, the environment, and timestamps for request, decision and execution, so you can rebuild the order of events afterward.&lt;/p&gt;

&lt;p&gt;It also notes that Cursor and Claude MCP setups shouldn't differ much here. Either way: no copied human tokens, a policy check per tool call, and credentials minted per task.&lt;/p&gt;

&lt;p&gt;Full post: &lt;a href="https://www.permit.io/blog/zero-standing-permissions-coding-automation-agents?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=zero-standing-permissions-coding-automation-agents&amp;amp;utm_content=authbyexample-article" rel="noopener noreferrer"&gt;https://www.permit.io/blog/zero-standing-permissions-coding-automation-agents?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=zero-standing-permissions-coding-automation-agents&amp;amp;utm_content=authbyexample-article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do your coding agents hold standing tokens today? If you moved to per-task credentials, I'd like to know what broke first.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>devops</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Shared agent memory needs a permission check on every read</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Wed, 28 Oct 2026 16:07:35 +0000</pubDate>
      <link>https://dev.to/authbyexample1/shared-agent-memory-needs-a-permission-check-on-every-read-20g9</link>
      <guid>https://dev.to/authbyexample1/shared-agent-memory-needs-a-permission-check-on-every-read-20g9</guid>
      <description>&lt;p&gt;I work at Permit. One of our AI engineers wrote a post about shared memory for coding agents, and since we sell authorization, read the framing with that in mind. I think the problem it describes holds up either way.&lt;/p&gt;

&lt;p&gt;Shared team memory for coding agents is handy. One agent figures out a repo's quirks, and the next person's agent gets that context for free. Those entries can also hold architecture details, internal file paths, hints about credentials and old decisions. Once memory outlives a session and spans users, every retrieval is an agent being handed access to that knowledge on someone's behalf.&lt;/p&gt;

&lt;h2&gt;
  
  
  The revocation gap
&lt;/h2&gt;

&lt;p&gt;Say someone loses access to a repo at 2:00 PM. If memory access was decided at onboarding, or got cached high in the stack, their agent can still pull what it learned about that repo at 2:01 PM. Reads and writes need a check at the time they happen, against current state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redaction and encryption don't decide who reads what
&lt;/h2&gt;

&lt;p&gt;Redaction strips known-sensitive bits before they're stored. It helps, but it depends on patterns and misses secrets that don't look like secrets. Encryption protects the data at rest and in transit. Neither one says whether this person should see this plaintext once it's decrypted. That's an authorization decision, and it has to be made per request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modeling it as relationships
&lt;/h2&gt;

&lt;p&gt;The post uses ReBAC. A human operates or delegates to an agent, the agent works in a team context, the team belongs to a project, and memory entries hang off the project, optionally scoped by repo and path. A rule then reads like this: the agent can read an entry if it acts for an active project member, the team can see the repo, and the current task scope matches the entry's tags. Remove one relationship and everything downstream of it stops resolving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Whose permissions does the memory server use?
&lt;/h2&gt;

&lt;p&gt;Picking just one source causes trouble. Inheriting the human's permissions overexposes memory when agents juggle several tasks or async jobs. Project-level inheritance is too broad for repos with mixed sensitivity. Agent-level inheritance lets long-lived agents build up standing privilege. The post lands on the intersection of the human's rights, project policy and the agent's scope for the current task, all evaluated at decision time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to log
&lt;/h2&gt;

&lt;p&gt;For each retrieval decision the post wants human, agent, project, query, memory entry, decision and outcome, plus a timestamp, the policy version and a correlation ID. Without those you can't explain why an agent saw something, or whether a revocation took effect in time.&lt;/p&gt;

&lt;p&gt;The full post also has an FAQ on team vs. project scoping and on Claude Code and Codex team memory: &lt;a href="https://www.permit.io/blog/shared-agent-memory-is-a-permissions-problem?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=shared-agent-memory-is-a-permissions-problem&amp;amp;utm_content=authbyexample-article" rel="noopener noreferrer"&gt;https://www.permit.io/blog/shared-agent-memory-is-a-permissions-problem?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=shared-agent-memory-is-a-permissions-problem&amp;amp;utm_content=authbyexample-article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run shared memory for agents today, where does your check sit: inside the memory server, or in front of it?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>authorization</category>
      <category>mcp</category>
    </item>
    <item>
      <title>EN 18286 is out. What would an auditor ask about your AI agents?</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Wed, 28 Oct 2026 16:07:13 +0000</pubDate>
      <link>https://dev.to/authbyexample1/en-18286-is-out-what-would-an-auditor-ask-about-your-ai-agents-3p23</link>
      <guid>https://dev.to/authbyexample1/en-18286-is-out-what-would-an-auditor-ask-about-your-ai-agents-3p23</guid>
      <description>&lt;p&gt;I work at Permit. Our VP of R&amp;amp;D wrote up what EN 18286:2026 means for teams shipping AI agents. We sell authorization, so read this with that bias in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the standard is
&lt;/h2&gt;

&lt;p&gt;EN 18286:2026 is the first harmonised standard under the EU AI Act. It turns the Article 17 quality management system requirements for providers of high-risk AI systems into processes an auditor can check. CEN approved it on 12 July 2026, and its reference was published in the Official Journal around October 14. Following it gives you a presumption of conformity for the Article 17 requirements it covers. It's meant to sit on top of a QMS you may already have, like ISO/IEC 42001 or ISO 9001.&lt;/p&gt;

&lt;p&gt;It doesn't mention AI agents, authorization or MCP anywhere. It also only applies to high-risk systems, and most agents won't be classified that way. I still think agent teams should read about it, because the processes it asks for (risk management, human oversight, data quality, cybersecurity) are the same things enterprise security reviews already ask about agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  The questions it leads to
&lt;/h2&gt;

&lt;p&gt;Once an agent can call tools, change data or send messages, those processes turn into pretty concrete questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the agent allowed to do, and where is that written down?&lt;/li&gt;
&lt;li&gt;How do you manage risk when it acts for a user?&lt;/li&gt;
&lt;li&gt;Who approves the sensitive actions before they run?&lt;/li&gt;
&lt;li&gt;What record shows it stayed inside policy?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why "it uses the user's token" is a weak answer
&lt;/h2&gt;

&lt;p&gt;A lot of agents authenticate as the user and run with everything that user can do. If an auditor asks which actions the agent was authorized to take, the honest answer is all of them. Why was a given action allowed? Because the user could have done it. What oversight happened first? None was required.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the post suggests instead
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Give the agent its own identity and credentials, even when it acts for a user, so the delegation is explicit.&lt;/li&gt;
&lt;li&gt;Run a policy check before every tool call, looking at the user, the agent, the resource, the action and the context.&lt;/li&gt;
&lt;li&gt;Block sensitive actions until a human approves, and store the approval with the decision.&lt;/li&gt;
&lt;li&gt;Log the authorization decision along with the tool output: who acted, for whom, on what, under which policy version, with what result.&lt;/li&gt;
&lt;li&gt;Put scope in policy. A prompt telling the agent to stay away from something can't enforce it.&lt;/li&gt;
&lt;li&gt;If agent A calls agent B, check and log each hop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post also covers where Permit fits. It says plainly that the standard doesn't prescribe any vendor, and that EN 18286 covers Article 17 only, so it won't make you AI Act compliant on its own.&lt;/p&gt;

&lt;p&gt;Full write-up: &lt;a href="https://www.permit.io/blog/en-18286-qms-eu-ai-act-agent-authorization?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=en-18286&amp;amp;utm_content=authbyexample-article" rel="noopener noreferrer"&gt;https://www.permit.io/blog/en-18286-qms-eu-ai-act-agent-authorization?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=en-18286&amp;amp;utm_content=authbyexample-article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Is anyone here getting asked about EN 18286 yet, either by a notified body or by enterprise customers?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>authorization</category>
      <category>compliance</category>
    </item>
    <item>
      <title>Moving off Oso Cloud? Sort your Polar rules into three piles first</title>
      <dc:creator>Auth By Example</dc:creator>
      <pubDate>Sun, 18 Oct 2026 08:14:23 +0000</pubDate>
      <link>https://dev.to/authbyexample1/moving-off-oso-cloud-sort-your-polar-rules-into-three-piles-first-4kkb</link>
      <guid>https://dev.to/authbyexample1/moving-off-oso-cloud-sort-your-polar-rules-into-three-piles-first-4kkb</guid>
      <description>&lt;p&gt;Oso Cloud was acquired by Tiny, and the deal closed on October 1. Oso says Cloud keeps running as usual, and most of the team has joined Temporal. If production authorization runs through it, it is reasonable to want a migration plan on paper before you actually need one. This is the order I would work in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sort your Polar into three piles
&lt;/h2&gt;

&lt;p&gt;Most policies mix three patterns, and each one moves differently.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Role blocks, like "read" if "viewer"; inside a resource block. That is plain RBAC, and it maps to roles and permissions in almost any system.&lt;/li&gt;
&lt;li&gt;Roles derived through relations, like "reader" if "member" on "organization";. That is ReBAC. Whatever you move to needs relationship tuples and role derivation, so a simple roles table will not cover it.&lt;/li&gt;
&lt;li&gt;Attribute rules, like allow(user: User, "view", doc: Document) if user.clearance_level &amp;gt;= doc.classification;. These become conditions in Rego, Cedar or whatever you pick, and the attributes have to be available when the check runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Count what lands in each pile. A codebase that is mostly role blocks moves quickly. One built on nested relations needs real modeling time first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get your facts out
&lt;/h2&gt;

&lt;p&gt;The rules are only half of it. Every has_role and has_relation fact you have sent to Oso Cloud is data your app depends on. Find every place your code writes facts and make sure you can rebuild all of them from your own database. If you cannot, fix that before anything else, because it is the hardest piece to reconstruct later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find your list queries
&lt;/h2&gt;

&lt;p&gt;Single checks like authorize(user, "read", doc) port easily. "Show me every document this user can read" is harder. Look for every list call and every spot where you use local authorization to filter in SQL, then confirm the new system can answer the same question at your data size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run both side by side
&lt;/h2&gt;

&lt;p&gt;Before you cut over, call the new engine next to Oso on real traffic. Keep enforcing Oso's answer and log every disagreement. The mismatches usually point straight at a derived role or an attribute you mapped wrong.&lt;/p&gt;

&lt;p&gt;I work at Permit, so I am biased about where you end up. We wrote up how each of these Polar patterns maps to Permit, with code for each: &lt;a href="https://www.permit.io/blog/migrate-from-oso-to-permit?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=oso-migration&amp;amp;utm_content=gabriel-post" rel="noopener noreferrer"&gt;https://www.permit.io/blog/migrate-from-oso-to-permit?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=oso-migration&amp;amp;utm_content=gabriel-post&lt;/a&gt;&lt;/p&gt;

</description>
      <category>authorization</category>
      <category>security</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
