[{"data":1,"prerenderedAt":743},["ShallowReactive",2],{"navigation":3,"\u002Fauth\u002Fabac":189,"\u002Fauth\u002Fabac-surround":738},[4,34,60,116,137,153],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":33},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,18,23,28],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":5,"path":16,"stem":17,"icon":6},"\u002Fgetting-started\u002Fgetting-started","1.getting-started\u002F2.getting-started",{"title":19,"path":20,"stem":21,"icon":22},"Choosing a Preset","\u002Fgetting-started\u002Fchoosing-a-preset","1.getting-started\u002F3.choosing-a-preset","i-lucide-git-branch",{"title":24,"path":25,"stem":26,"icon":27},"Deployment","\u002Fgetting-started\u002Fdeployment","1.getting-started\u002F4.deployment","i-lucide-cloud",{"title":29,"path":30,"stem":31,"icon":32},"Background Maintenance","\u002Fgetting-started\u002Fbackground-maintenance","1.getting-started\u002F5.background-maintenance","i-lucide-timer-reset",false,{"title":35,"icon":36,"path":37,"stem":38,"children":39,"page":33},"Build","i-lucide-wrench","\u002Fbuild","2.build",[40,45,50,55],{"title":41,"path":42,"stem":43,"icon":44},"Routers & Prefixes","\u002Fbuild\u002Frouters-and-prefixes","2.build\u002F1.routers-and-prefixes","i-lucide-route",{"title":46,"path":47,"stem":48,"icon":49},"Configuration","\u002Fbuild\u002Fconfiguration","2.build\u002F2.configuration","i-lucide-settings",{"title":51,"path":52,"stem":53,"icon":54},"Authorization Dependencies","\u002Fbuild\u002Fauthorization-dependencies","2.build\u002F3.authorization-dependencies","i-lucide-shield-check",{"title":56,"path":57,"stem":58,"icon":59},"Command Line","\u002Fbuild\u002Fcli","2.build\u002F4.cli","i-lucide-terminal",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":33},"Auth","i-lucide-lock","\u002Fauth","3.auth",[66,71,76,81,86,91,96,101,106,111],{"title":67,"path":68,"stem":69,"icon":70},"OAuth & Social Login","\u002Fauth\u002Foauth-and-social-login","3.auth\u002F1.oauth-and-social-login","i-lucide-log-in",{"title":72,"path":73,"stem":74,"icon":75},"Multi-Frontend Support","\u002Fauth\u002Fmulti-frontend","3.auth\u002F10.multi-frontend","i-lucide-layout-grid",{"title":77,"path":78,"stem":79,"icon":80},"Sessions & Audit","\u002Fauth\u002Fsessions-and-audit","3.auth\u002F2.sessions-and-audit","i-lucide-monitor-smartphone",{"title":82,"path":83,"stem":84,"icon":85},"Passwordless & Messaging","\u002Fauth\u002Fpasswordless-and-messaging","3.auth\u002F3.passwordless-and-messaging","i-lucide-mail",{"title":87,"path":88,"stem":89,"icon":90},"JWT Tokens","\u002Fauth\u002Fjwt-tokens","3.auth\u002F4.jwt-tokens","i-lucide-key-round",{"title":92,"path":93,"stem":94,"icon":95},"User Management API","\u002Fauth\u002Fuser-management-api","3.auth\u002F5.user-management-api","i-lucide-users",{"title":97,"path":98,"stem":99,"icon":100},"User Invitations","\u002Fauth\u002Fuser-invitations","3.auth\u002F6.user-invitations","i-lucide-send",{"title":102,"path":103,"stem":104,"icon":105},"Roles & Permissions","\u002Fauth\u002Froles-and-permissions","3.auth\u002F7.roles-and-permissions","i-lucide-shield",{"title":107,"path":108,"stem":109,"icon":110},"ABAC","\u002Fauth\u002Fabac","3.auth\u002F8.abac","i-lucide-filter",{"title":112,"path":113,"stem":114,"icon":115},"User Status","\u002Fauth\u002Fuser-status","3.auth\u002F9.user-status","i-lucide-user-cog",{"title":117,"icon":118,"path":119,"stem":120,"children":121,"page":33},"Enterprise","i-lucide-building-2","\u002Fenterprise","4.enterprise",[122,127,132],{"title":123,"path":124,"stem":125,"icon":126},"Core Authorization Concepts","\u002Fenterprise\u002Fcore-authorization-concepts","4.enterprise\u002F1.core-authorization-concepts","i-lucide-network",{"title":128,"path":129,"stem":130,"icon":131},"Entities","\u002Fenterprise\u002Fentities","4.enterprise\u002F2.entities","i-lucide-folder-tree",{"title":133,"path":134,"stem":135,"icon":136},"Entity Memberships","\u002Fenterprise\u002Fentity-memberships","4.enterprise\u002F3.entity-memberships","i-lucide-user-plus",{"title":138,"icon":139,"path":140,"stem":141,"children":142,"page":33},"Integrations","i-lucide-plug","\u002Fintegrations","5.integrations",[143,148],{"title":144,"path":145,"stem":146,"icon":147},"API Keys","\u002Fintegrations\u002Fapi-keys","5.integrations\u002F1.api-keys","i-lucide-key",{"title":149,"path":150,"stem":151,"icon":152},"OutlabsAuth UI","\u002Fintegrations\u002Foutlabsauth-ui","5.integrations\u002F2.outlabsauth-ui","i-lucide-layout-dashboard",{"title":154,"icon":155,"path":156,"stem":157,"children":158,"page":33},"Reference","i-lucide-book-marked","\u002Freference","6.reference",[159,164,169,174,179,184],{"title":160,"path":161,"stem":162,"icon":163},"Data Models","\u002Freference\u002Fdata-models","6.reference\u002F1.data-models","i-lucide-database",{"title":165,"path":166,"stem":167,"icon":168},"Activity Tracking","\u002Freference\u002Factivity-tracking","6.reference\u002F2.activity-tracking","i-lucide-activity",{"title":170,"path":171,"stem":172,"icon":173},"Testing","\u002Freference\u002Ftesting","6.reference\u002F3.testing","i-lucide-flask-conical",{"title":175,"path":176,"stem":177,"icon":178},"Observability","\u002Freference\u002Fobservability","6.reference\u002F4.observability","i-lucide-eye",{"title":180,"path":181,"stem":182,"icon":183},"Metrics Reference","\u002Freference\u002Fmetrics-reference","6.reference\u002F5.metrics-reference","i-lucide-chart-bar",{"title":185,"path":186,"stem":187,"icon":188},"Log Events Reference","\u002Freference\u002Flog-events-reference","6.reference\u002F6.log-events-reference","i-lucide-scroll-text",{"id":190,"title":107,"body":191,"description":731,"extension":732,"links":733,"meta":734,"navigation":735,"path":108,"seo":736,"stem":109,"__hash__":737},"docs\u002F3.auth\u002F8.abac.md",{"type":192,"value":193,"toc":722},"minimark",[194,201,228,231,236,298,357,376,378,382,390,448,513,520,522,526,536,547,549,556,580,649,652,654,658,687,689,693,718],[195,196,197],"note",{},[198,199,200],"p",{},"Opt-in attribute conditions on top of RBAC.",[198,202,203,204,208,209,212,213,217,218,217,221,217,224,227],{},"ABAC adds ",[205,206,207],"strong",{},"conditions"," (attribute + operator + value) to roles and\u002For\npermissions. At check time, RBAC must still grant the permission ",[205,210,211],{},"and","\nconditions must pass against a context (",[214,215,216],"code",{},"user",", ",[214,219,220],{},"resource",[214,222,223],{},"env",[214,225,226],{},"time",").",[229,230],"hr",{},[232,233,235],"h2",{"id":234},"enable","Enable",[237,238,239,252],"table",{},[240,241,242],"thead",{},[243,244,245,249],"tr",{},[246,247,248],"th",{},"Surface",[246,250,251],{},"Behavior",[253,254,255,272,286],"tbody",{},[243,256,257,263],{},[258,259,260],"td",{},[214,261,262],{},"EnterpriseRBAC(..., enable_abac=True)",[258,264,265,266],{},"Opt-in; ",[205,267,268,269],{},"default ",[214,270,271],{},"False",[243,273,274,283],{},[258,275,276,279,280],{},[214,277,278],{},"OutlabsAuth"," \u002F ",[214,281,282],{},"AuthConfig.enable_abac",[258,284,285],{},"Same flag",[243,287,288,293],{},[258,289,290],{},[214,291,292],{},"SimpleRBAC",[258,294,295],{},[205,296,297],{},"Forced off",[299,300,305],"pre",{"className":301,"code":302,"language":303,"meta":304,"style":304},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","auth = EnterpriseRBAC(\n    database_url=...,\n    secret_key=...,\n    enable_abac=True,\n    # Prefer server-derived context; keep this False unless you know why:\n    # trust_resource_context_header=False,\n)\nauth.instrument_fastapi(app, include_resource_context=True)  # when using request-state merge\n","python","",[214,306,307,315,321,327,333,339,345,351],{"__ignoreMap":304},[308,309,312],"span",{"class":310,"line":311},"line",1,[308,313,314],{},"auth = EnterpriseRBAC(\n",[308,316,318],{"class":310,"line":317},2,[308,319,320],{},"    database_url=...,\n",[308,322,324],{"class":310,"line":323},3,[308,325,326],{},"    secret_key=...,\n",[308,328,330],{"class":310,"line":329},4,[308,331,332],{},"    enable_abac=True,\n",[308,334,336],{"class":310,"line":335},5,[308,337,338],{},"    # Prefer server-derived context; keep this False unless you know why:\n",[308,340,342],{"class":310,"line":341},6,[308,343,344],{},"    # trust_resource_context_header=False,\n",[308,346,348],{"class":310,"line":347},7,[308,349,350],{},")\n",[308,352,354],{"class":310,"line":353},8,[308,355,356],{},"auth.instrument_fastapi(app, include_resource_context=True)  # when using request-state merge\n",[198,358,359,360,363,364,367,368,371,372,375],{},"Do ",[205,361,362],{},"not"," trust client ",[214,365,366],{},"X-Resource-Context"," unless you set\n",[214,369,370],{},"trust_resource_context_header=True",". Prefer a\n",[214,373,374],{},"resource_context_provider"," that loads attributes from your DB.",[229,377],{},[232,379,381],{"id":380},"where-conditions-attach","Where conditions attach",[198,383,384,385,389],{},"Same shape on both catalogs (",[386,387,388],"a",{"href":103},"25","):",[237,391,392,404],{},[240,393,394],{},[243,395,396,399,402],{},[246,397,398],{},"Attach point",[246,400,401],{},"Paths",[246,403,61],{},[253,405,406,428],{},[243,407,408,411,420],{},[258,409,410],{},"Permission",[258,412,413,416,417],{},[214,414,415],{},"\u002Fv1\u002Fpermissions\u002F{id}\u002Fcondition-groups"," + ",[214,418,419],{},"\u002Fconditions",[258,421,422,279,425],{},[214,423,424],{},"permission:read",[214,426,427],{},"permission:update",[243,429,430,433,440],{},[258,431,432],{},"Role",[258,434,435,416,438],{},[214,436,437],{},"\u002Fv1\u002Froles\u002F{id}\u002Fcondition-groups",[214,439,419],{},[258,441,442,279,445],{},[214,443,444],{},"role:read",[214,446,447],{},"role:update",[198,449,450,453,454,453,457,460,461,464,465,468,453,471,474,475,478,479,481,482,217,485,217,488,491,492,217,495,481,498,460,501,460,504,460,507,460,510,227],{},[205,451,452],{},"Group:"," ",[214,455,456],{},"operator",[214,458,459],{},"AND"," | ",[214,462,463],{},"OR",", optional description.",[466,467],"br",{},[205,469,470],{},"Condition:",[214,472,473],{},"attribute"," (dot path, e.g. ",[214,476,477],{},"resource.status","), ",[214,480,456],{},"\n(",[214,483,484],{},"equals",[214,486,487],{},"in",[214,489,490],{},"matches",", …), ",[214,493,494],{},"value",[214,496,497],{},"value_type",[214,499,500],{},"string",[214,502,503],{},"integer",[214,505,506],{},"float",[214,508,509],{},"boolean",[214,511,512],{},"list",[198,514,515,516,519],{},"Evaluation shape: ungrouped conditions AND together; within a group use the\ngroup operator; ",[205,517,518],{},"groups AND together",". Empty conditions → RBAC-only for that\nattach point.",[229,521],{},[232,523,525],{"id":524},"evaluation-at-check-time","Evaluation at check time",[198,527,528,531,532,535],{},[214,529,530],{},"auth.deps.require_permission(..., resource_context_provider=...)"," builds a\ncontext, then ",[214,533,534],{},"PermissionService.check_permission(..., resource_context=...)",".",[198,537,538,539,542,543,546],{},"When ABAC is on and condition rows exist: for each candidate grant, ",[205,540,541],{},"role\nconditions must pass",", then ",[205,544,545],{},"at least one matching permission’s conditions\nmust pass",". Superusers short-circuit before ABAC. If the flag is on but no\nconditions exist, the cheaper non-ABAC path runs.",[229,548],{},[232,550,552,553],{"id":551},"example-abac_cookbook","Example: ",[214,554,555],{},"abac_cookbook",[198,557,558,559,562,563,565,566,453,569,572,575,576,579],{},"Editors may ",[214,560,561],{},"document:update"," only when ",[214,564,477],{}," is ",[214,567,568],{},"draft",[205,570,571],{},"or",[214,573,574],{},"review",", using a ",[205,577,578],{},"server-derived"," context (client cannot forge status).",[299,581,586],{"className":582,"code":583,"filename":584,"language":585,"meta":304,"style":304},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","cd examples\u002Fabac_cookbook\nuv run python reset_test_env.py\nuv run uvicorn main:app --host 127.0.0.1 --port 8005\nuv run python ..\u002F..\u002Fscripts\u002Fsmoke_abac_cookbook.py\n","Terminal","bash",[214,587,588,598,613,638],{"__ignoreMap":304},[308,589,590,594],{"class":310,"line":311},[308,591,593],{"class":592},"s2Zo4","cd",[308,595,597],{"class":596},"sfazB"," examples\u002Fabac_cookbook\n",[308,599,600,604,607,610],{"class":310,"line":317},[308,601,603],{"class":602},"sBMFI","uv",[308,605,606],{"class":596}," run",[308,608,609],{"class":596}," python",[308,611,612],{"class":596}," reset_test_env.py\n",[308,614,615,617,619,622,625,628,632,635],{"class":310,"line":323},[308,616,603],{"class":602},[308,618,606],{"class":596},[308,620,621],{"class":596}," uvicorn",[308,623,624],{"class":596}," main:app",[308,626,627],{"class":596}," --host",[308,629,631],{"class":630},"sbssI"," 127.0.0.1",[308,633,634],{"class":596}," --port",[308,636,637],{"class":630}," 8005\n",[308,639,640,642,644,646],{"class":310,"line":329},[308,641,603],{"class":602},[308,643,606],{"class":596},[308,645,609],{"class":596},[308,647,648],{"class":596}," ..\u002F..\u002Fscripts\u002Fsmoke_abac_cookbook.py\n",[198,650,651],{},"Smoke: configure permission conditions as admin → editor updates draft (200) \u002F\npublished (403).",[229,653],{},[232,655,657],{"id":656},"caveats","Caveats",[659,660,661,672,681,684],"ul",{},[662,663,664,667,668,671],"li",{},[205,665,666],{},"Not a row-level ACL product"," — your host loads resource attributes and\npasses them via ",[214,669,670],{},"resource_context"," \u002F provider.",[662,673,674,677,678,535],{},[205,675,676],{},"Principal \u002F system API keys"," are RBAC-only: if ABAC is on and the required\npermission has conditions, those keys are denied — see\n",[386,679,680],{"href":145},"API Key Host Integration",[662,682,683],{},"ABAC can disable some permission-cache fast paths; keep conditions focused.",[662,685,686],{},"Client resource-context headers stay off by default on purpose.",[229,688],{},[232,690,692],{"id":691},"related","Related",[659,694,695,699,703,707],{},[662,696,697],{},[386,698,46],{"href":47},[662,700,701],{},[386,702,102],{"href":103},[662,704,705],{},[386,706,123],{"href":124},[662,708,709,710],{},"Live demo: ",[386,711,715],{"href":712,"rel":713},"https:\u002F\u002Fgithub.com\u002Foutlabsio\u002FoutlabsAuth\u002Ftree\u002Fmain\u002Fexamples\u002Fabac_cookbook\u002F",[714],"nofollow",[214,716,717],{},"examples\u002Fabac_cookbook\u002F",[719,720,721],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":304,"searchDepth":311,"depth":317,"links":723},[724,725,726,727,729,730],{"id":234,"depth":317,"text":235},{"id":380,"depth":317,"text":381},{"id":524,"depth":317,"text":525},{"id":551,"depth":317,"text":728},"Example: abac_cookbook",{"id":656,"depth":317,"text":657},{"id":691,"depth":317,"text":692},"Attribute conditions on roles and permissions.","md",null,{},{"icon":110},{"title":107,"description":731},"BZS-7ykGgxRFImVTt53uzRmgYYo8JGgFFLFUbgbFC1s",[739,741],{"title":102,"path":103,"stem":104,"description":740,"icon":105,"children":-1},"Permission catalog and role definitions.",{"title":112,"path":113,"stem":114,"description":742,"icon":115,"children":-1},"Active, invited, suspended, banned, deleted.",1787472745731]