1"use strict";(self.webpackChunkpartners=self.webpackChunkpartners||[]).push([[36940],{15680:(e,a,t)=>{t.d(a,{xA:()=>c,yg:()=>u});var r=t(96540);function n(e,a,t){return a in e?Object.defineProperty(e,a,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[a]=t,e}function s(e,a){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);a&&(r=r.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var a=1;a<arguments.length;a++){var t=null!=arguments[a]?arguments[a]:{};a%2?s(Object(t),!0).forEach((function(a){n(e,a,t[a])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):s(Object(t)).forEach((function(a){Object.defineProperty(e,a,Object.getOwnPropertyDescriptor(t,a))}))}return e}function o(e,a){if(null==e)return{};var t,r,n=function(e,a){if(null==e)return{};var t,r,n={},s=Object.keys(e);for(r=0;r<s.length;r++)t=s[r],a.indexOf(t)>=0||(n[t]=e[t]);return n}(e,a);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r<s.length;r++)t=s[r],a.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(n[t]=e[t])}return n}var i=r.createContext({}),p=function(e){var a=r.useContext(i),t=a;return e&&(t="function"==typeof e?e(a):l(l({},a),e)),t},c=function(e){var a=p(e.components);return r.createElement(i.Provider,{value:a},e.children)},m="mdxType",g={inlineCode:"code",wrapper:function(e){var a=e.children;return r.createElement(r.Fragment,{},a)}},d=r.forwardRef((function(e,a){var t=e.components,n=e.mdxType,s=e.originalType,i=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),m=p(t),d=n,u=m["".concat(i,".").concat(d)]||m[d]||g[d]||s;return t?r.createElement(u,l(l({ref:a},c),{},{components:t})):r.createElement(u,l({ref:a},c))}));function u(e,a){var t=arguments,n=a&&a.mdxType;if("string"==typeof e||n){var s=t.length,l=new Array(s);l[0]=d;var o={};for(var i in a)hasOwnProperty.call(a,i)&&(o[i]=a[i]);o.originalType=e,o[m]="string"==typeof e?e:n,l[1]=o;for(var p=2;p<s;p++)l[p]=t[p];return r.createElement.apply(null,l)}return r.createElement.apply(null,t)}d.displayName="MDXCreateElement"},11639:(e,a,t)=>{t.r(a),t.d(a,{assets:()=>i,contentTitle:()=>l,default:()=>g,frontMatter:()=>s,metadata:()=>o,toc:()=>p});var r=t(58168),n=(t(96540),t(15680));const s={title:"Role-Based Access Control",sidebar_label:"Overview",description:"Learn how PactFlow manages access through users, teams, roles, and permissions."},l="Role-Based Access Control",o={unversionedId:"docs/permissions/rbac",id:"docs/permissions/rbac",title:"Role-Based Access Control",description:"Learn how PactFlow manages access through users, teams, roles, and permissions.",source:"@site/docs/docs/permissions/rbac.md",sourceDirName:"docs/permissions",slug:"/docs/permissions/rbac",permalink:"/docs/permissions/rbac",draft:!1,editUrl:"https://github.com/pactflow/docs.pactflow.io/edit/master/website/docs/docs/permissions/rbac.md",tags:[],version:"current",lastUpdatedBy:"Matt Fellows",lastUpdatedAt:1751582794,formattedLastUpdatedAt:"Jul 3, 2025",frontMatter:{title:"Role-Based Access Control",sidebar_label:"Overview",description:"Learn how PactFlow manages access through users, teams, roles, and permissions."},sidebar:"docs",previous:{title:"Stubs",permalink:"/docs/stubs"},next:{title:"Predefined roles",permalink:"/docs/permissions/predefined-roles"}},i={},p=[{value:"Core concepts",id:"core-concepts",level:2},{value:"How it works",id:"how-it-works",level:2},{value:"Special case: Team Administrator",id:"special-case-team-administrator",level:3},{value:"Conceptual Model",id:"conceptual-model",level:3},{value:"Example: Team-based access",id:"example-team-based-access",level:2},{value:"Team structure",id:"team-structure",level:3},{value:"User access and roles",id:"user-access-and-roles",level:3},{value:"More Information",id:"more-information",level:2}],c={toc:p},m="wrapper";function g(e){let{components:a,...s}=e;return(0,n.yg)(m,(0,r.A)({},c,s,{components:a,mdxType:"MDXLayout"}),(0,n.yg)("h1",{id:"role-based-access-control"},"Role-Based Access Control"),(0,n.yg)("p",null,"PactFlow uses a flexible team-based Role-Based Access Control (RBAC) model to manage access to contracts, applications, and features. This ensures users can only interact with resources in ways allowed by their assigned roles and team membership."),(0,n.yg)("p",null,"This model supports simple team structures and scales to complex organizations."),(0,n.yg)("h2",{id:"core-concepts"},"Core concepts"),(0,n.yg)("ul",null,(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Users"),": Individuals who interact with PactFlow via the UI, API, or CLI."),(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Roles"),": Global collections of permissions assigned to users."),(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Permissions"),": Actions a user can perform. Some may be scoped to specific teams or resources."),(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Teams"),": Logical groups of users that own applications and resources."),(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Applications"),": Team-owned services that participate in contract testing."),(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Contracts"),": The data generated from interactions between applications."),(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Resources"),": Include secrets, webhooks, test results, and other team-scoped assets.")),(0,n.yg)("h2",{id:"how-it-works"},"How it works"),(0,n.yg)("p",null,"PactFlow uses a flexible RBAC model where:"),(0,n.yg)("ul",null,(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Users are assigned one or more global roles")),(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Roles grant a set of permissions")),(0,n.yg)("li",{parentName:"ul"},(0,n.yg)("strong",{parentName:"li"},"Some permissions are scoped to specific teams or resources"))),(0,n.yg)("p",null,"While roles are assigned globally to a user, many permissions are evaluated in context \u2014 particularly when scoped to a team."),(0,n.yg)("p",null,"For example:"),(0,n.yg)("ul",null,(0,n.yg)("li",{parentName:"ul"},"A user with the ",(0,n.yg)("inlineCode",{parentName:"li"},"contract_data:manage:team")," permission can modify contract data ",(0,n.yg)("strong",{parentName:"li"},"only")," for applications owned by teams they belong to."),(0,n.yg)("li",{parentName:"ul"},"A user with ",(0,n.yg)("inlineCode",{parentName:"li"},"user:invite")," (no scope) can invite users across the entire organization.")),(0,n.yg)("p",null,"A user's ",(0,n.yg)("strong",{parentName:"p"},"effective permissions")," are therefore a combination of:"),(0,n.yg)("ul",null,(0,n.yg)("li",{parentName:"ul"},"Their globally assigned roles"),(0,n.yg)("li",{parentName:"ul"},"The permissions granted by those roles"),(0,n.yg)("li",{parentName:"ul"},"The team or resource scope (if applicable) of those permissions"),(0,n.yg)("li",{parentName:"ul"},"The teams they are a member of (when a permission is team-scoped)")),(0,n.yg)("h3",{id:"special-case-team-administrator"},"Special case: Team Administrator"),(0,n.yg)("p",null,"The ",(0,n.yg)("strong",{parentName:"p"},"Team Administrator")," is a special permission-based role assigned to a user ",(0,n.yg)("em",{parentName:"p"},"for a specific team"),". It is implemented using a scoped permission like:"),(0,n.yg)("pre",null,(0,n.yg)("code",{parentName:"pre"},"team:manage:{team_uuid}\n")),(0,n.yg)("p",null,"This allows for delegated administration of a team without giving the user global administrative rights."),(0,n.yg)("blockquote",null,(0,n.yg)("p",{parentName:"blockquote"},(0,n.yg)("strong",{parentName:"p"},"Note:")," Roles are additive \u2014 there are no negated permissions in PactFlow.")),(0,n.yg)("h3",{id:"conceptual-model"},"Conceptual Model"),(0,n.yg)("p",null,(0,n.yg)("img",{alt:"Diagram",src:t(80818).A,width:"3669",height:"3840"})),(0,n.yg)("h2",{id:"example-team-based-access"},"Example: Team-based access"),(0,n.yg)("p",null,"This guide walks y
1ou through an example with two teams, three applications, and three users, one of whom is a platform administrator."),(0,n.yg)("h3",{id:"team-structure"},"Team structure"),(0,n.yg)("table",null,(0,n.yg)("thead",{parentName:"table"},(0,n.yg)("tr",{parentName:"thead"},(0,n.yg)("th",{parentName:"tr",align:null},(0,n.yg)("strong",{parentName:"th"},"Team")),(0,n.yg)("th",{parentName:"tr",align:null},(0,n.yg)("strong",{parentName:"th"},"Applications")),(0,n.yg)("th",{parentName:"tr",align:null},(0,n.yg)("strong",{parentName:"th"},"Users")))),(0,n.yg)("tbody",{parentName:"table"},(0,n.yg)("tr",{parentName:"tbody"},(0,n.yg)("td",{parentName:"tr",align:null},"A"),(0,n.yg)("td",{parentName:"tr",align:null},"ProductService, OrderService"),(0,n.yg)("td",{parentName:"tr",align:null},"Sally")),(0,n.yg)("tr",{parentName:"tbody"},(0,n.yg)("td",{parentName:"tr",align:null},"B"),(0,n.yg)("td",{parentName:"tr",align:null},"OrderService, AuthService"),(0,n.yg)("td",{parentName:"tr",align:null},"Billy")))),(0,n.yg)("h3",{id:"user-access-and-roles"},"User access and roles"),(0,n.yg)("table",null,(0,n.yg)("thead",{parentName:"table"},(0,n.yg)("tr",{parentName:"thead"},(0,n.yg)("th",{parentName:"tr",align:null},(0,n.yg)("strong",{parentName:"th"},"User")),(0,n.yg)("th",{parentName:"tr",align:null},(0,n.yg)("strong",{parentName:"th"},"Team")),(0,n.yg)("th",{parentName:"tr",align:null},(0,n.yg)("strong",{parentName:"th"},"Role")),(0,n.yg)("th",{parentName:"tr",align:null},(0,n.yg)("strong",{parentName:"th"},"Access Rights")))),(0,n.yg)("tbody",{parentName:"table"},(0,n.yg)("tr",{parentName:"tbody"},(0,n.yg)("td",{parentName:"tr",align:null},"Sally"),(0,n.yg)("td",{parentName:"tr",align:null},"A"),(0,n.yg)("td",{parentName:"tr",align:null},"Test Maintainer"),(0,n.yg)("td",{parentName:"tr",align:null},"ProductService, OrderService")),(0,n.yg)("tr",{parentName:"tbody"},(0,n.yg)("td",{parentName:"tr",align:null},"Billy"),(0,n.yg)("td",{parentName:"tr",align:null},"B"),(0,n.yg)("td",{parentName:"tr",align:null},"Test Maintainer"),(0,n.yg)("td",{parentName:"tr",align:null},"OrderService, AuthService")),(0,n.yg)("tr",{parentName:"tbody"},(0,n.yg)("td",{parentName:"tr",align:null},"Kevin"),(0,n.yg)("td",{parentName:"tr",align:null},"-"),(0,n.yg)("td",{parentName:"tr",align:null},"Administrator"),(0,n.yg)("td",{parentName:"tr",align:null},"All")))),(0,n.yg)("ul",null,(0,n.yg)("li",{parentName:"ul"},"Sally and Billy can only act on applications owned by their assigned teams."),(0,n.yg)("li",{parentName:"ul"},"Kevin, as an Administrator, can access and manage any application or contract in the system.")),(0,n.yg)("p",null,"If Sally attempts to publish a contract for an application not owned by her team (for example, ",(0,n.yg)("inlineCode",{parentName:"p"},"AuthService"),"), she will receive a permissions error."),(0,n.yg)("p",null,"Example error:"),(0,n.yg)("pre",null,(0,n.yg)("code",{parentName:"pre"},"Failed to tag versions due to error: PactBroker::Client::Error \u2013 Authorization failed (403)\nOne or more pacts failed to be published\n")),(0,n.yg)("p",null,"This demonstrates how access is enforced based on both ownership and role-based permissions."),(0,n.yg)("blockquote",null,(0,n.yg)("p",{parentName:"blockquote"},(0,n.yg)("strong",{parentName:"p"},"Note:")," See ",(0,n.yg)("a",{parentName:"p",href:"/docs/permissions/predefined-roles"},"Predefined Roles")," for more details on role capabilities.")),(0,n.yg)("h2",{id:"more-information"},"More Information"),(0,n.yg)("ul",null,(0,n.yg)("li",{parentName:"ul"},"For a list of the default roles, visit the ",(0,n.yg)("a",{parentName:"li",href:"/docs/permissions/predefined-roles"},"Roles Overview"),"."),(0,n.yg)("li",{parentName:"ul"},"For a list of supported permissions, visit the ",(0,n.yg)("a",{parentName:"li",href:"/docs/permissions"},"Permissions Overview"),".")))}g.isMDXComponent=!0},80818:(e,a,t)=>{t.d(a,{A:()=>r});const r=t.p+"assets/images/rbac-5be6f563b758a741dbe98d95ab6f78e3.png"}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.