[{"data":1,"prerenderedAt":941},["ShallowReactive",2],{"navigation":3,"\u002Fbuild\u002Fauthorization-dependencies":189,"\u002Fbuild\u002Fauthorization-dependencies-surround":936},[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":51,"body":191,"description":929,"extension":930,"links":931,"meta":932,"navigation":933,"path":52,"seo":934,"stem":53,"__hash__":935},"docs\u002F2.build\u002F3.authorization-dependencies.md",{"type":192,"value":193,"toc":920},"minimark",[194,203,217,222,270,284,287,291,395,410,414,417,541,563,567,626,648,652,662,780,783,799,803,891,895,916],[195,196,197,198,202],"p",{},"OutlabsAuth exposes FastAPI dependencies through ",[199,200,201],"code",{},"auth.deps",". They authenticate\nthe configured credential sources, apply account-state rules, and keep the\nauthorization decision inside the library.",[204,205,206],"tip",{},[195,207,208,209,212,213,216],{},"For an ordinary route, use ",[199,210,211],{},"require_auth(...)"," or ",[199,214,215],{},"require_permission(...)",".\nThe two-phase API later on this page is for infrastructure components that must\nauthenticate once and authorize several resources in one request.",[218,219,221],"h2",{"id":220},"authenticate-a-caller","Authenticate a caller",[223,224,230],"pre",{"className":225,"code":226,"filename":227,"language":228,"meta":229,"style":229},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","from fastapi import Depends\n\n\n@app.get(\"\u002Fprofile\")\nasync def profile(ctx: dict = Depends(auth.deps.require_auth())):\n    return {\"authenticated\": True, \"source\": ctx[\"source\"]}\n","routes.py","python","",[199,231,232,240,247,252,258,264],{"__ignoreMap":229},[233,234,237],"span",{"class":235,"line":236},"line",1,[233,238,239],{},"from fastapi import Depends\n",[233,241,243],{"class":235,"line":242},2,[233,244,246],{"emptyLinePlaceholder":245},true,"\n",[233,248,250],{"class":235,"line":249},3,[233,251,246],{"emptyLinePlaceholder":245},[233,253,255],{"class":235,"line":254},4,[233,256,257],{},"@app.get(\"\u002Fprofile\")\n",[233,259,261],{"class":235,"line":260},5,[233,262,263],{},"async def profile(ctx: dict = Depends(auth.deps.require_auth())):\n",[233,265,267],{"class":235,"line":266},6,[233,268,269],{},"    return {\"authenticated\": True, \"source\": ctx[\"source\"]}\n",[195,271,272,275,276,279,280,283],{},[199,273,274],{},"require_auth(active=True, verified=False, optional=False)"," accepts any\nconfigured credential source. Set ",[199,277,278],{},"verified=True"," when the route requires a\nverified user. Set ",[199,281,282],{},"optional=True"," only when the route deliberately supports an\nanonymous result.",[195,285,286],{},"The returned dictionary is an auth-owned context, not a public scope format.\nIt is safe to use identity fields for application behavior; do not grant access\nby interpreting raw permission or scope metadata from it.",[218,288,290],{"id":289},"require-permissions","Require permissions",[223,292,294],{"className":225,"code":293,"filename":227,"language":228,"meta":229,"style":229},"@app.get(\"\u002Freports\")\nasync def read_reports(\n    ctx: dict = Depends(auth.deps.require_permission(\"report:read\")),\n):\n    return {\"authorized\": True, \"source\": ctx[\"source\"]}\n\n\n@app.post(\"\u002Freports\u002Fexport\")\nasync def export_reports(\n    ctx: dict = Depends(\n        auth.deps.require_permission(\n            \"report:read\",\n            \"report:export\",\n            require_all=True,\n        )\n    ),\n):\n    ...\n",[199,295,296,301,306,311,316,321,325,330,336,342,348,354,360,366,372,378,384,389],{"__ignoreMap":229},[233,297,298],{"class":235,"line":236},[233,299,300],{},"@app.get(\"\u002Freports\")\n",[233,302,303],{"class":235,"line":242},[233,304,305],{},"async def read_reports(\n",[233,307,308],{"class":235,"line":249},[233,309,310],{},"    ctx: dict = Depends(auth.deps.require_permission(\"report:read\")),\n",[233,312,313],{"class":235,"line":254},[233,314,315],{},"):\n",[233,317,318],{"class":235,"line":260},[233,319,320],{},"    return {\"authorized\": True, \"source\": ctx[\"source\"]}\n",[233,322,323],{"class":235,"line":266},[233,324,246],{"emptyLinePlaceholder":245},[233,326,328],{"class":235,"line":327},7,[233,329,246],{"emptyLinePlaceholder":245},[233,331,333],{"class":235,"line":332},8,[233,334,335],{},"@app.post(\"\u002Freports\u002Fexport\")\n",[233,337,339],{"class":235,"line":338},9,[233,340,341],{},"async def export_reports(\n",[233,343,345],{"class":235,"line":344},10,[233,346,347],{},"    ctx: dict = Depends(\n",[233,349,351],{"class":235,"line":350},11,[233,352,353],{},"        auth.deps.require_permission(\n",[233,355,357],{"class":235,"line":356},12,[233,358,359],{},"            \"report:read\",\n",[233,361,363],{"class":235,"line":362},13,[233,364,365],{},"            \"report:export\",\n",[233,367,369],{"class":235,"line":368},14,[233,370,371],{},"            require_all=True,\n",[233,373,375],{"class":235,"line":374},15,[233,376,377],{},"        )\n",[233,379,381],{"class":235,"line":380},16,[233,382,383],{},"    ),\n",[233,385,387],{"class":235,"line":386},17,[233,388,315],{},[233,390,392],{"class":235,"line":391},18,[233,393,394],{},"    ...\n",[195,396,397,398,401,402,405,406,409],{},"Multiple permissions mean “any” by default. Pass ",[199,399,400],{},"require_all=True"," when every\npermission is required. Authentication failures return ",[199,403,404],{},"401","; authenticated\ncallers without the grant receive ",[199,407,408],{},"403",".",[218,411,413],{"id":412},"entity-and-tree-checks","Entity and tree checks",[195,415,416],{},"EnterpriseRBAC adds context-aware checks:",[223,418,420],{"className":225,"code":419,"filename":227,"language":228,"meta":229,"style":229},"@app.get(\"\u002Fentities\u002F{entity_id}\u002Fbilling\")\nasync def entity_billing(\n    entity_id: UUID,\n    ctx: dict = Depends(\n        auth.deps.require_entity_permission(\n            \"billing:read\",\n            entity_id_param=\"entity_id\",\n        )\n    ),\n):\n    ...\n\n\n@app.get(\"\u002Fentities\u002F{entity_id}\u002Fdescendants\")\nasync def descendants(\n    entity_id: UUID,\n    ctx: dict = Depends(\n        auth.deps.require_tree_permission(\n            \"entity:read_tree\",\n            \"entity_id\",\n            source=\"path\",\n        )\n    ),\n):\n    ...\n",[199,421,422,427,432,437,441,446,451,456,460,464,468,472,476,480,485,490,494,498,503,509,515,521,526,531,536],{"__ignoreMap":229},[233,423,424],{"class":235,"line":236},[233,425,426],{},"@app.get(\"\u002Fentities\u002F{entity_id}\u002Fbilling\")\n",[233,428,429],{"class":235,"line":242},[233,430,431],{},"async def entity_billing(\n",[233,433,434],{"class":235,"line":249},[233,435,436],{},"    entity_id: UUID,\n",[233,438,439],{"class":235,"line":254},[233,440,347],{},[233,442,443],{"class":235,"line":260},[233,444,445],{},"        auth.deps.require_entity_permission(\n",[233,447,448],{"class":235,"line":266},[233,449,450],{},"            \"billing:read\",\n",[233,452,453],{"class":235,"line":327},[233,454,455],{},"            entity_id_param=\"entity_id\",\n",[233,457,458],{"class":235,"line":332},[233,459,377],{},[233,461,462],{"class":235,"line":338},[233,463,383],{},[233,465,466],{"class":235,"line":344},[233,467,315],{},[233,469,470],{"class":235,"line":350},[233,471,394],{},[233,473,474],{"class":235,"line":356},[233,475,246],{"emptyLinePlaceholder":245},[233,477,478],{"class":235,"line":362},[233,479,246],{"emptyLinePlaceholder":245},[233,481,482],{"class":235,"line":368},[233,483,484],{},"@app.get(\"\u002Fentities\u002F{entity_id}\u002Fdescendants\")\n",[233,486,487],{"class":235,"line":374},[233,488,489],{},"async def descendants(\n",[233,491,492],{"class":235,"line":380},[233,493,436],{},[233,495,496],{"class":235,"line":386},[233,497,347],{},[233,499,500],{"class":235,"line":391},[233,501,502],{},"        auth.deps.require_tree_permission(\n",[233,504,506],{"class":235,"line":505},19,[233,507,508],{},"            \"entity:read_tree\",\n",[233,510,512],{"class":235,"line":511},20,[233,513,514],{},"            \"entity_id\",\n",[233,516,518],{"class":235,"line":517},21,[233,519,520],{},"            source=\"path\",\n",[233,522,524],{"class":235,"line":523},22,[233,525,377],{},[233,527,529],{"class":235,"line":528},23,[233,530,383],{},[233,532,534],{"class":235,"line":533},24,[233,535,315],{},[233,537,539],{"class":235,"line":538},25,[233,540,394],{},[195,542,543,546,547,550,551,554,555,558,559,562],{},[199,544,545],{},"require_entity_permission"," resolves the named path parameter and checks inside\nthat entity. ",[199,548,549],{},"require_tree_permission"," supports ",[199,552,553],{},"source=\"path\"",", ",[199,556,557],{},"\"query\"",", or\n",[199,560,561],{},"\"header\"","; use the path form when possible because the protected resource is\nexplicit in the route.",[218,564,566],{"id":565},"restrict-credential-types","Restrict credential types",[223,568,570],{"className":225,"code":569,"filename":227,"language":228,"meta":229,"style":229},"@app.post(\"\u002Fwebhooks\u002Fimport\")\nasync def import_webhook(\n    ctx: dict = Depends(auth.deps.require_source(\"api_key\")),\n):\n    ...\n\n\n@app.post(\"\u002Fsystem\u002Freindex\")\nasync def reindex(\n    ctx: dict = Depends(auth.deps.require_superuser()),\n):\n    ...\n",[199,571,572,577,582,587,591,595,599,603,608,613,618,622],{"__ignoreMap":229},[233,573,574],{"class":235,"line":236},[233,575,576],{},"@app.post(\"\u002Fwebhooks\u002Fimport\")\n",[233,578,579],{"class":235,"line":242},[233,580,581],{},"async def import_webhook(\n",[233,583,584],{"class":235,"line":249},[233,585,586],{},"    ctx: dict = Depends(auth.deps.require_source(\"api_key\")),\n",[233,588,589],{"class":235,"line":254},[233,590,315],{},[233,592,593],{"class":235,"line":260},[233,594,394],{},[233,596,597],{"class":235,"line":266},[233,598,246],{"emptyLinePlaceholder":245},[233,600,601],{"class":235,"line":327},[233,602,246],{"emptyLinePlaceholder":245},[233,604,605],{"class":235,"line":332},[233,606,607],{},"@app.post(\"\u002Fsystem\u002Freindex\")\n",[233,609,610],{"class":235,"line":338},[233,611,612],{},"async def reindex(\n",[233,614,615],{"class":235,"line":344},[233,616,617],{},"    ctx: dict = Depends(auth.deps.require_superuser()),\n",[233,619,620],{"class":235,"line":350},[233,621,315],{},[233,623,624],{"class":235,"line":356},[233,625,394],{},[195,627,628,631,632,635,636,639,640,643,644,647],{},[199,629,630],{},"require_source"," accepts one of the configured backend names such as ",[199,633,634],{},"jwt",",\n",[199,637,638],{},"api_key",", or ",[199,641,642],{},"service_token",". ",[199,645,646],{},"require_superuser"," authenticates first, then\nrequires the user’s superuser flag.",[218,649,651],{"id":650},"authenticate-once-authorize-several-resources","Authenticate once, authorize several resources",[195,653,654,655,554,658,661],{},"Added in ",[199,656,657],{},"0.1.0a26",[199,659,660],{},"authorize_authenticated(...)"," is the supported boundary\nfor an infrastructure component that authenticates once and then checks several\nresources. It does not re-enter a credential backend or record API-key usage a\nsecond time.",[223,663,666],{"className":225,"code":664,"filename":665,"language":228,"meta":229,"style":229},"ctx = await auth.deps.require_auth()(\n    request=request,\n    session=auth_session,\n)\n\nif auth.deps.authenticated_authorization_requires_session(ctx):\n    async with auth.session_factory() as policy_session:\n        await auth.deps.authorize_authenticated(\n            request,\n            ctx,\n            \"queue_a:run\",\n            \"queue_b:run\",\n            require_all=True,\n            session=policy_session,\n        )\nelse:\n    await auth.deps.authorize_authenticated(\n        request,\n        ctx,\n        \"queue_a:run\",\n        \"queue_b:run\",\n        require_all=True,\n    )\n","infrastructure.py",[199,667,668,673,678,683,688,692,697,702,707,712,717,722,727,731,736,740,745,750,755,760,765,770,775],{"__ignoreMap":229},[233,669,670],{"class":235,"line":236},[233,671,672],{},"ctx = await auth.deps.require_auth()(\n",[233,674,675],{"class":235,"line":242},[233,676,677],{},"    request=request,\n",[233,679,680],{"class":235,"line":249},[233,681,682],{},"    session=auth_session,\n",[233,684,685],{"class":235,"line":254},[233,686,687],{},")\n",[233,689,690],{"class":235,"line":260},[233,691,246],{"emptyLinePlaceholder":245},[233,693,694],{"class":235,"line":266},[233,695,696],{},"if auth.deps.authenticated_authorization_requires_session(ctx):\n",[233,698,699],{"class":235,"line":327},[233,700,701],{},"    async with auth.session_factory() as policy_session:\n",[233,703,704],{"class":235,"line":332},[233,705,706],{},"        await auth.deps.authorize_authenticated(\n",[233,708,709],{"class":235,"line":338},[233,710,711],{},"            request,\n",[233,713,714],{"class":235,"line":344},[233,715,716],{},"            ctx,\n",[233,718,719],{"class":235,"line":350},[233,720,721],{},"            \"queue_a:run\",\n",[233,723,724],{"class":235,"line":356},[233,725,726],{},"            \"queue_b:run\",\n",[233,728,729],{"class":235,"line":362},[233,730,371],{},[233,732,733],{"class":235,"line":368},[233,734,735],{},"            session=policy_session,\n",[233,737,738],{"class":235,"line":374},[233,739,377],{},[233,741,742],{"class":235,"line":380},[233,743,744],{},"else:\n",[233,746,747],{"class":235,"line":386},[233,748,749],{},"    await auth.deps.authorize_authenticated(\n",[233,751,752],{"class":235,"line":391},[233,753,754],{},"        request,\n",[233,756,757],{"class":235,"line":505},[233,758,759],{},"        ctx,\n",[233,761,762],{"class":235,"line":511},[233,763,764],{},"        \"queue_a:run\",\n",[233,766,767],{"class":235,"line":517},[233,768,769],{},"        \"queue_b:run\",\n",[233,771,772],{"class":235,"line":523},[233,773,774],{},"        require_all=True,\n",[233,776,777],{"class":235,"line":528},[233,778,779],{},"    )\n",[195,781,782],{},"The session helper is deliberately conservative: user and JWT identities need\na policy session; service tokens do not; integration principals may avoid one\nonly when entity traversal and ABAC are not involved. If the component already\nowns a suitable request-scoped session, it may pass that session directly.",[195,784,785,787,788,791,792,795,796,798],{},[199,786,660],{}," also accepts ",[199,789,790],{},"entity_id"," and\n",[199,793,794],{},"resource_context_provider",", matching the entity and ABAC behavior of\n",[199,797,215],{},". The authenticated context must belong to the same\nrequest; a context copied from another request is rejected.",[218,800,802],{"id":801},"choose-the-right-api","Choose the right API",[804,805,806,819],"table",{},[807,808,809],"thead",{},[810,811,812,816],"tr",{},[813,814,815],"th",{},"Need",[813,817,818],{},"Use",[820,821,822,833,842,852,862,872,882],"tbody",{},[810,823,824,828],{},[825,826,827],"td",{},"Any valid configured credential",[825,829,830],{},[199,831,832],{},"require_auth()",[810,834,835,838],{},[825,836,837],{},"One or more grants",[825,839,840],{},[199,841,215],{},[810,843,844,847],{},[825,845,846],{},"A grant inside one entity",[825,848,849],{},[199,850,851],{},"require_entity_permission(...)",[810,853,854,857],{},[825,855,856],{},"A grant across an entity subtree",[825,858,859],{},[199,860,861],{},"require_tree_permission(...)",[810,863,864,867],{},[825,865,866],{},"One credential source only",[825,868,869],{},[199,870,871],{},"require_source(...)",[810,873,874,877],{},[825,875,876],{},"A human superuser",[825,878,879],{},[199,880,881],{},"require_superuser()",[810,883,884,887],{},[825,885,886],{},"Authenticate once, authorize many resources",[825,888,889],{},[199,890,660],{},[218,892,894],{"id":893},"related","Related",[896,897,898,904,908,912],"ul",{},[899,900,901],"li",{},[902,903,5],"a",{"href":16},[899,905,906],{},[902,907,102],{"href":103},[899,909,910],{},[902,911,123],{"href":124},[899,913,914],{},[902,915,107],{"href":108},[917,918,919],"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);}",{"title":229,"searchDepth":236,"depth":242,"links":921},[922,923,924,925,926,927,928],{"id":220,"depth":242,"text":221},{"id":289,"depth":242,"text":290},{"id":412,"depth":242,"text":413},{"id":565,"depth":242,"text":566},{"id":650,"depth":242,"text":651},{"id":801,"depth":242,"text":802},{"id":893,"depth":242,"text":894},"Protect host routes with authentication, permission, entity, tree, source, and two-phase checks.","md",null,{},{"icon":54},{"title":51,"description":929},"Bxy2rXBQ8z6vznaHd_CDZXDsCjI53R4jKEADgJbz2_w",[937,939],{"title":46,"path":47,"stem":48,"description":938,"icon":49,"children":-1},"Secrets, schema, Redis, cache backends, and CLI.",{"title":56,"path":57,"stem":58,"description":940,"icon":59,"children":-1},"Operate OutlabsAuth without a UI, from a terminal or coding agent.",1787472744721]