[{"data":1,"prerenderedAt":3025},["ShallowReactive",2],{"navigation_docs":3,"-modules-identity-authorization":587,"-modules-identity-authorization-surround":3020},[4,50,155,441,504],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":49},"Get Started","i-lucide-rocket","\u002Fget-started","1.get-started",[10,15,20,25,30,35,40,45],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fget-started\u002Fintroduction","1.get-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fget-started\u002Finstallation","1.get-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Project structure","\u002Fget-started\u002Fproject-structure","1.get-started\u002F3.project-structure","i-lucide-folder-tree",{"title":26,"path":27,"stem":28,"icon":29},"Configuration","\u002Fget-started\u002Fconfiguration","1.get-started\u002F4.configuration","i-lucide-settings",{"title":31,"path":32,"stem":33,"icon":34},"Authentication","\u002Fget-started\u002Fauthentication","1.get-started\u002F5.authentication","i-lucide-lock",{"title":36,"path":37,"stem":38,"icon":39},"Adding modules","\u002Fget-started\u002Fadding-modules","1.get-started\u002F6.adding-modules","i-lucide-puzzle",{"title":41,"path":42,"stem":43,"icon":44},"Database","\u002Fget-started\u002Fdatabase","1.get-started\u002F7.database","i-lucide-database",{"title":46,"path":47,"stem":48,"icon":6},"Deployment","\u002Fget-started\u002Fdeployment","1.get-started\u002F8.deployment",false,{"title":51,"icon":52,"path":53,"stem":54,"children":55,"page":49},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[56,90,115,125],{"title":57,"icon":49,"path":58,"stem":59,"children":60,"page":49},"Concepts","\u002Fguide\u002Fconcepts","2.guide\u002F1.concepts",[61,66,71,76,80,85],{"title":62,"path":63,"stem":64,"icon":65},"Architecture","\u002Fguide\u002Fconcepts\u002Farchitecture","2.guide\u002F1.concepts\u002F1.architecture","i-lucide-blocks",{"title":67,"path":68,"stem":69,"icon":70},"Access control","\u002Fguide\u002Fconcepts\u002Fauth-and-scopes","2.guide\u002F1.concepts\u002F2.auth-and-scopes","i-lucide-shield-check",{"title":72,"path":73,"stem":74,"icon":75},"Extension points","\u002Fguide\u002Fconcepts\u002Fextension-points","2.guide\u002F1.concepts\u002F3.extension-points","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":44},"Database extensions","\u002Fguide\u002Fconcepts\u002Fdatabase-extensions","2.guide\u002F1.concepts\u002F4.database-extensions",{"title":81,"path":82,"stem":83,"icon":84},"Identity","\u002Fguide\u002Fconcepts\u002Fidentity","2.guide\u002F1.concepts\u002F5.identity","i-lucide-fingerprint",{"title":86,"path":87,"stem":88,"icon":89},"Glossary","\u002Fguide\u002Fconcepts\u002Fglossary","2.guide\u002F1.concepts\u002F6.glossary","i-lucide-book-a",{"title":91,"icon":49,"path":92,"stem":93,"children":94,"page":49},"UX patterns","\u002Fguide\u002Fux-patterns","2.guide\u002F2.ux-patterns",[95,100,105,110],{"title":96,"path":97,"stem":98,"icon":99},"Layouts and navigation","\u002Fguide\u002Fux-patterns\u002Flayouts-and-navigation","2.guide\u002F2.ux-patterns\u002F1.layouts-and-navigation","i-lucide-layout-template",{"title":101,"path":102,"stem":103,"icon":104},"Pages","\u002Fguide\u002Fux-patterns\u002Fpages","2.guide\u002F2.ux-patterns\u002F2.pages","i-lucide-table",{"title":106,"path":107,"stem":108,"icon":109},"Forms and actions","\u002Fguide\u002Fux-patterns\u002Fforms-and-actions","2.guide\u002F2.ux-patterns\u002F3.forms-and-actions","i-lucide-square-pen",{"title":111,"path":112,"stem":113,"icon":114},"Text and formatting","\u002Fguide\u002Fux-patterns\u002Ftext-and-formatting","2.guide\u002F2.ux-patterns\u002F4.text-and-formatting","i-lucide-type",{"title":116,"icon":49,"path":117,"stem":118,"children":119,"page":49},"Best practices","\u002Fguide\u002Fbest-practices","2.guide\u002F3.best-practices",[120],{"title":121,"path":122,"stem":123,"icon":124},"HTTP routes","\u002Fguide\u002Fbest-practices\u002Fhttp-routes","2.guide\u002F3.best-practices\u002F1.http-routes","i-lucide-route",{"title":126,"icon":49,"path":127,"stem":128,"children":129,"page":49},"Going further","\u002Fguide\u002Fgoing-further","2.guide\u002F4.going-further",[130,135,140,145,150],{"title":131,"path":132,"stem":133,"icon":134},"Use your own OAuth server","\u002Fguide\u002Fgoing-further\u002Fown-oauth-server","2.guide\u002F4.going-further\u002F1.own-oauth-server","i-lucide-key-round",{"title":136,"path":137,"stem":138,"icon":139},"Create an OAuth application","\u002Fguide\u002Fgoing-further\u002Foauth-application","2.guide\u002F4.going-further\u002F2.oauth-application","i-lucide-app-window",{"title":141,"path":142,"stem":143,"icon":144},"Signing keys","\u002Fguide\u002Fgoing-further\u002Fsigning-keys","2.guide\u002F4.going-further\u002F3.signing-keys","i-lucide-key-square",{"title":146,"path":147,"stem":148,"icon":149},"Stripe setup","\u002Fguide\u002Fgoing-further\u002Fstripe-setup","2.guide\u002F4.going-further\u002F4.stripe-setup","i-lucide-credit-card",{"title":151,"path":152,"stem":153,"icon":154},"Migrate to the permission model","\u002Fguide\u002Fgoing-further\u002Fmigrate-access-control","2.guide\u002F4.going-further\u002F5.migrate-access-control","i-lucide-arrow-right-left",{"title":156,"icon":157,"path":158,"stem":159,"children":160},"Modules","i-lucide-boxes","\u002Fmodules","3.modules",[161,163,244,273,320,375],{"title":156,"path":158,"stem":162},"3.modules\u002Findex",{"title":81,"icon":49,"path":164,"stem":165,"children":166,"page":49},"\u002Fmodules\u002Fidentity","3.modules\u002F1.identity",[167,190,194,198,220,224,240],{"title":168,"path":169,"stem":170,"children":171},"Auth","\u002Fmodules\u002Fidentity\u002Fauth","3.modules\u002F1.identity\u002F1.auth\u002Findex",[172,174,178,182,186],{"title":173,"path":169,"stem":170},"Overview",{"title":175,"path":176,"stem":177},"Server API","\u002Fmodules\u002Fidentity\u002Fauth\u002Fserver","3.modules\u002F1.identity\u002F1.auth\u002F2.server",{"title":179,"path":180,"stem":181},"Reference","\u002Fmodules\u002Fidentity\u002Fauth\u002Freference","3.modules\u002F1.identity\u002F1.auth\u002F3.reference",{"title":183,"path":184,"stem":185},"Client mode","\u002Fmodules\u002Fidentity\u002Fauth\u002Fclient-mode","3.modules\u002F1.identity\u002F1.auth\u002F4.client-mode",{"title":187,"path":188,"stem":189},"OAuth providers","\u002Fmodules\u002Fidentity\u002Fauth\u002Foauth-providers","3.modules\u002F1.identity\u002F1.auth\u002F5.oauth-providers",{"title":191,"path":192,"stem":193},"Users","\u002Fmodules\u002Fidentity\u002Fusers","3.modules\u002F1.identity\u002F2.users",{"title":195,"path":196,"stem":197},"Account","\u002Fmodules\u002Fidentity\u002Faccount","3.modules\u002F1.identity\u002F3.account",{"title":199,"path":200,"stem":201,"children":202},"Authorization","\u002Fmodules\u002Fidentity\u002Fauthorization","3.modules\u002F1.identity\u002F4.authorization\u002Findex",[203,204,208,212,216],{"title":173,"path":200,"stem":201},{"title":205,"path":206,"stem":207},"Roles and requirements","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Froles-and-requirements","3.modules\u002F1.identity\u002F4.authorization\u002F2.roles-and-requirements",{"title":209,"path":210,"stem":211},"Policies","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fpolicies","3.modules\u002F1.identity\u002F4.authorization\u002F3.policies",{"title":213,"path":214,"stem":215},"Client","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fclient","3.modules\u002F1.identity\u002F4.authorization\u002F4.client",{"title":217,"path":218,"stem":219},"Admin","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fadmin","3.modules\u002F1.identity\u002F4.authorization\u002F5.admin",{"title":221,"path":222,"stem":223},"Preferences","\u002Fmodules\u002Fidentity\u002Fpreferences","3.modules\u002F1.identity\u002F5.preferences",{"title":225,"path":226,"stem":227,"children":228},"OAuth Server","\u002Fmodules\u002Fidentity\u002Foauth-server","3.modules\u002F1.identity\u002F6.oauth-server\u002Findex",[229,230,233,237],{"title":173,"path":226,"stem":227},{"title":175,"path":231,"stem":232},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fserver","3.modules\u002F1.identity\u002F6.oauth-server\u002F2.server",{"title":234,"path":235,"stem":236},"Hooks","\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fhooks","3.modules\u002F1.identity\u002F6.oauth-server\u002F3.hooks",{"title":179,"path":238,"stem":239},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Froutes-and-clients","3.modules\u002F1.identity\u002F6.oauth-server\u002F4.routes-and-clients",{"title":241,"path":242,"stem":243},"OAuth Resource","\u002Fmodules\u002Fidentity\u002Foauth-resource","3.modules\u002F1.identity\u002F8.oauth-resource",{"title":245,"icon":49,"path":246,"stem":247,"children":248,"page":49},"Commerce","\u002Fmodules\u002Fcommerce","3.modules\u002F2.commerce",[249,253,257],{"title":250,"path":251,"stem":252},"Stripe","\u002Fmodules\u002Fcommerce\u002Fstripe","3.modules\u002F2.commerce\u002F1.stripe",{"title":254,"path":255,"stem":256},"Payments","\u002Fmodules\u002Fcommerce\u002Fpayments","3.modules\u002F2.commerce\u002F2.payments",{"title":258,"path":259,"stem":260,"children":261},"Subscriptions","\u002Fmodules\u002Fcommerce\u002Fsubscriptions","3.modules\u002F2.commerce\u002F3.subscriptions\u002Findex",[262,263,266,270],{"title":173,"path":259,"stem":260},{"title":175,"path":264,"stem":265},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fserver","3.modules\u002F2.commerce\u002F3.subscriptions\u002F2.server",{"title":267,"path":268,"stem":269},"App","\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fapp","3.modules\u002F2.commerce\u002F3.subscriptions\u002F3.app",{"title":179,"path":271,"stem":272},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Freference","3.modules\u002F2.commerce\u002F3.subscriptions\u002F4.reference",{"title":274,"icon":49,"path":275,"stem":276,"children":277,"page":49},"Features","\u002Fmodules\u002Ffeatures","3.modules\u002F3.features",[278,293,312,316],{"title":279,"path":280,"stem":281,"children":282},"Events","\u002Fmodules\u002Ffeatures\u002Fevents","3.modules\u002F3.features\u002F1.events\u002Findex",[283,284,287,290],{"title":173,"path":280,"stem":281},{"title":175,"path":285,"stem":286},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fserver","3.modules\u002F3.features\u002F1.events\u002F2.server",{"title":267,"path":288,"stem":289},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fapp","3.modules\u002F3.features\u002F1.events\u002F3.app",{"title":179,"path":291,"stem":292},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Freference","3.modules\u002F3.features\u002F1.events\u002F4.reference",{"title":294,"path":295,"stem":296,"children":297},"Forms","\u002Fmodules\u002Ffeatures\u002Fforms","3.modules\u002F3.features\u002F2.forms\u002Findex",[298,299,303,306,309],{"title":173,"path":295,"stem":296},{"title":300,"path":301,"stem":302},"Definition","\u002Fmodules\u002Ffeatures\u002Fforms\u002Fdefinition","3.modules\u002F3.features\u002F2.forms\u002F2.definition",{"title":175,"path":304,"stem":305},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fserver","3.modules\u002F3.features\u002F2.forms\u002F3.server",{"title":267,"path":307,"stem":308},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fapp","3.modules\u002F3.features\u002F2.forms\u002F4.app",{"title":179,"path":310,"stem":311},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Freference","3.modules\u002F3.features\u002F2.forms\u002F5.reference",{"title":313,"path":314,"stem":315},"Cookie Consent","\u002Fmodules\u002Ffeatures\u002Fcookie-consent","3.modules\u002F3.features\u002F3.cookie-consent",{"title":317,"path":318,"stem":319},"MCP","\u002Fmodules\u002Ffeatures\u002Fmcp","3.modules\u002F3.features\u002F4.mcp",{"title":321,"icon":49,"path":322,"stem":323,"children":324,"page":49},"Interface","\u002Fmodules\u002Finterface","3.modules\u002F4.interface",[325,350,353,357,361],{"title":326,"path":327,"stem":328,"children":329},"UI","\u002Fmodules\u002Finterface\u002Fui","3.modules\u002F4.interface\u002F1.ui\u002Findex",[330,331,335,339,343,347],{"title":173,"path":327,"stem":328},{"title":332,"path":333,"stem":334},"Page components","\u002Fmodules\u002Finterface\u002Fui\u002Fpage-components","3.modules\u002F4.interface\u002F1.ui\u002F2.page-components",{"title":336,"path":337,"stem":338},"App shell","\u002Fmodules\u002Finterface\u002Fui\u002Fapp-shell","3.modules\u002F4.interface\u002F1.ui\u002F3.app-shell",{"title":340,"path":341,"stem":342},"Form inputs","\u002Fmodules\u002Finterface\u002Fui\u002Fform-inputs","3.modules\u002F4.interface\u002F1.ui\u002F4.form-inputs",{"title":344,"path":345,"stem":346},"Composables and helpers","\u002Fmodules\u002Finterface\u002Fui\u002Fcomposables","3.modules\u002F4.interface\u002F1.ui\u002F5.composables",{"title":179,"path":348,"stem":349},"\u002Fmodules\u002Finterface\u002Fui\u002Freference","3.modules\u002F4.interface\u002F1.ui\u002F6.reference",{"title":217,"path":351,"stem":352},"\u002Fmodules\u002Finterface\u002Fadmin","3.modules\u002F4.interface\u002F2.admin",{"title":354,"path":355,"stem":356},"Menu","\u002Fmodules\u002Finterface\u002Fmenu","3.modules\u002F4.interface\u002F3.menu",{"title":358,"path":359,"stem":360},"Widget","\u002Fmodules\u002Finterface\u002Fwidget","3.modules\u002F4.interface\u002F4.widget",{"title":362,"path":363,"stem":364,"children":365},"Mobile","\u002Fmodules\u002Finterface\u002Fmobile","3.modules\u002F4.interface\u002F5.mobile\u002Findex",[366,367,371],{"title":173,"path":363,"stem":364},{"title":368,"path":369,"stem":370},"CLI and devices","\u002Fmodules\u002Finterface\u002Fmobile\u002Fcli-and-devices","3.modules\u002F4.interface\u002F5.mobile\u002F2.cli-and-devices",{"title":372,"path":373,"stem":374},"Splash screen","\u002Fmodules\u002Finterface\u002Fmobile\u002Fsplash-screen","3.modules\u002F4.interface\u002F5.mobile\u002F3.splash-screen",{"title":376,"icon":49,"path":377,"stem":378,"children":379,"page":49},"Platform","\u002Fmodules\u002Fplatform","3.modules\u002F5.platform",[380,402,406,423],{"title":381,"path":382,"stem":383,"children":384},"Module Kit","\u002Fmodules\u002Fplatform\u002Fmodule-kit","3.modules\u002F5.platform\u002F1.module-kit\u002Findex",[385,386,390,394,398],{"title":173,"path":382,"stem":383},{"title":387,"path":388,"stem":389},"Server toolkit","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fserver-toolkit","3.modules\u002F5.platform\u002F1.module-kit\u002F2.server-toolkit",{"title":391,"path":392,"stem":393},"Registries and menus","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fregistries-and-menus","3.modules\u002F5.platform\u002F1.module-kit\u002F3.registries-and-menus",{"title":395,"path":396,"stem":397},"Translations","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fi18n","3.modules\u002F5.platform\u002F1.module-kit\u002F4.i18n",{"title":399,"path":400,"stem":401},"Database helpers","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fdatabase","3.modules\u002F5.platform\u002F1.module-kit\u002F5.database",{"title":403,"path":404,"stem":405},"Notify","\u002Fmodules\u002Fplatform\u002Fnotify","3.modules\u002F5.platform\u002F2.notify",{"title":407,"path":408,"stem":409,"children":410},"Email Templates","\u002Fmodules\u002Fplatform\u002Femail-templates","3.modules\u002F5.platform\u002F3.email-templates\u002Findex",[411,412,416,419],{"title":173,"path":408,"stem":409},{"title":413,"path":414,"stem":415},"Email components","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fcomponents","3.modules\u002F5.platform\u002F3.email-templates\u002F2.components",{"title":175,"path":417,"stem":418},"\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fserver","3.modules\u002F5.platform\u002F3.email-templates\u002F3.server",{"title":420,"path":421,"stem":422},"Module emails","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fmodule-emails","3.modules\u002F5.platform\u002F3.email-templates\u002F4.module-emails",{"title":424,"path":425,"stem":426,"children":427},"Base Layer","\u002Fmodules\u002Fplatform\u002Fbase-layer","3.modules\u002F5.platform\u002F4.base-layer\u002Findex",[428,429,433,437],{"title":173,"path":425,"stem":426},{"title":430,"path":431,"stem":432},"Content collections","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcontent-collections","3.modules\u002F5.platform\u002F4.base-layer\u002F2.content-collections",{"title":434,"path":435,"stem":436},"Layouts and routing","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Flayouts-and-routing","3.modules\u002F5.platform\u002F4.base-layer\u002F3.layouts-and-routing",{"title":438,"path":439,"stem":440},"Composables and utils","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcomposables-and-utils","3.modules\u002F5.platform\u002F4.base-layer\u002F4.composables-and-utils",{"title":442,"icon":443,"path":444,"stem":445,"children":446,"page":49},"Examples","i-lucide-code-xml","\u002Fexamples","4.examples",[447,466,476],{"title":448,"icon":49,"path":449,"stem":450,"children":451,"page":49},"Starters","\u002Fexamples\u002Fstarters","4.examples\u002F1.starters",[452,456,461],{"title":453,"path":454,"stem":455,"icon":6},"Workspace starter","\u002Fexamples\u002Fstarters\u002Fworkspace","4.examples\u002F1.starters\u002F1.workspace",{"title":457,"path":458,"stem":459,"icon":460},"Mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile","4.examples\u002F1.starters\u002F2.mobile","i-lucide-smartphone",{"title":462,"path":463,"stem":464,"icon":465},"Standalone mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile-standalone","4.examples\u002F1.starters\u002F3.mobile-standalone","i-lucide-tablet-smartphone",{"title":467,"icon":49,"path":468,"stem":469,"children":470,"page":49},"Apps","\u002Fexamples\u002Fapps","4.examples\u002F2.apps",[471],{"title":472,"path":473,"stem":474,"icon":475},"Frigear website app","\u002Fexamples\u002Fapps\u002Ffrigear-nu-website","4.examples\u002F2.apps\u002F1.frigear-nu-website","i-lucide-layout-dashboard",{"title":477,"icon":49,"path":478,"stem":479,"children":480,"page":49},"Tasks","\u002Fexamples\u002Ftasks","4.examples\u002F3.tasks",[481,485,489,494,499],{"title":482,"path":483,"stem":484,"icon":70},"Protect a route","\u002Fexamples\u002Ftasks\u002Fprotect-a-route","4.examples\u002F3.tasks\u002F1.protect-a-route",{"title":486,"path":487,"stem":488,"icon":475},"Add an admin page","\u002Fexamples\u002Ftasks\u002Fadd-an-admin-page","4.examples\u002F3.tasks\u002F2.add-an-admin-page",{"title":490,"path":491,"stem":492,"icon":493},"Sell event tickets","\u002Fexamples\u002Ftasks\u002Fsell-event-tickets","4.examples\u002F3.tasks\u002F3.sell-event-tickets","i-lucide-ticket",{"title":495,"path":496,"stem":497,"icon":498},"Build a form","\u002Fexamples\u002Ftasks\u002Fbuild-a-form","4.examples\u002F3.tasks\u002F4.build-a-form","i-lucide-clipboard-list",{"title":500,"path":501,"stem":502,"icon":503},"Send an email","\u002Fexamples\u002Ftasks\u002Fsend-an-email","4.examples\u002F3.tasks\u002F5.send-an-email","i-lucide-mail",{"title":505,"icon":506,"path":507,"stem":508,"children":509,"page":49},"Contribute","i-lucide-git-pull-request","\u002Fcontribute","5.contribute",[510,513,518,544,549,552,556,571],{"title":173,"path":511,"stem":512,"icon":506},"\u002Fcontribute\u002Foverview","5.contribute\u002F1.overview",{"title":514,"path":515,"stem":516,"icon":517},"Local development","\u002Fcontribute\u002Flocal-development","5.contribute\u002F2.local-development","i-lucide-terminal",{"title":519,"icon":49,"path":520,"stem":521,"children":522,"page":49},"Writing a module","\u002Fcontribute\u002Fwriting-a-module","5.contribute\u002F3.writing-a-module",[523,527,532,536,541],{"title":524,"path":525,"stem":526,"icon":39},"Scaffold a module","\u002Fcontribute\u002Fwriting-a-module\u002Fscaffold","5.contribute\u002F3.writing-a-module\u002F1.scaffold",{"title":528,"path":529,"stem":530,"icon":531},"Setup checklist","\u002Fcontribute\u002Fwriting-a-module\u002Fsetup-checklist","5.contribute\u002F3.writing-a-module\u002F2.setup-checklist","i-lucide-list-checks",{"title":533,"path":534,"stem":535,"icon":44},"Database tables","\u002Fcontribute\u002Fwriting-a-module\u002Fdatabase-tables","5.contribute\u002F3.writing-a-module\u002F3.database-tables",{"title":537,"path":538,"stem":539,"icon":540},"Testing","\u002Fcontribute\u002Fwriting-a-module\u002Ftesting","5.contribute\u002F3.writing-a-module\u002F4.testing","i-lucide-flask-conical",{"title":67,"path":542,"stem":543,"icon":70},"\u002Fcontribute\u002Fwriting-a-module\u002Faccess-control","5.contribute\u002F3.writing-a-module\u002F5.access-control",{"title":545,"path":546,"stem":547,"icon":548},"Publishing","\u002Fcontribute\u002Fpublishing","5.contribute\u002F4.publishing","i-lucide-package-check",{"title":448,"path":550,"stem":551,"icon":6},"\u002Fcontribute\u002Fstarters","5.contribute\u002F5.starters",{"title":553,"path":554,"stem":555,"icon":52},"Documentation","\u002Fcontribute\u002Fdocumentation","5.contribute\u002F6.documentation",{"title":557,"icon":49,"path":558,"stem":559,"children":560,"page":49},"Tooling","\u002Fcontribute\u002Ftooling","5.contribute\u002F7.tooling",[561,566],{"title":562,"path":563,"stem":564,"icon":565},"CLI","\u002Fcontribute\u002Ftooling\u002Fcli","5.contribute\u002F7.tooling\u002F1.cli","i-lucide-square-terminal",{"title":567,"path":568,"stem":569,"icon":570},"ESLint config","\u002Fcontribute\u002Ftooling\u002Feslint-config","5.contribute\u002F7.tooling\u002F2.eslint-config","i-lucide-spell-check",{"title":572,"icon":49,"path":573,"stem":574,"children":575},"Decisions","\u002Fcontribute\u002Fdecisions","5.contribute\u002F8.decisions\u002Findex",[576,578,583],{"title":572,"path":573,"stem":574,"icon":577},"i-lucide-scale",{"title":579,"path":580,"stem":581,"icon":582},"Session lifetimes per OAuth client","\u002Fcontribute\u002Fdecisions\u002Foauth-token-lifetimes","5.contribute\u002F8.decisions\u002F1.oauth-token-lifetimes","i-lucide-timer",{"title":584,"path":585,"stem":586,"icon":70},"One permission model","\u002Fcontribute\u002Fdecisions\u002Fpermission-model","5.contribute\u002F8.decisions\u002F2.permission-model",{"id":588,"title":199,"body":589,"description":3013,"extension":3014,"links":3015,"meta":3016,"navigation":3017,"path":200,"seo":3018,"stem":201,"__hash__":3019},"docs\u002F3.modules\u002F1.identity\u002F4.authorization\u002Findex.md",{"type":590,"value":591,"toc":2998},"minimark",[592,625,635,651,656,729,733,787,803,807,1540,1567,1571,1578,1714,1737,1750,2509,2516,2536,2539,2546,2603,2619,2623,2641,2785,2788,2846,2863,2866,2873,2938,2952,2956,2994],[593,594,595,596,600,601,605,606,609,610,613,614,613,617,620,621,624],"p",{},"Authorization decides what a signed-in user may do. Modules and your app register ",[597,598,599],"strong",{},"permissions"," such as\n",[602,603,604],"code",{},"events:update",". You bundle them into ",[597,607,608],{},"roles"," (",[602,611,612],{},"admin",", ",[602,615,616],{},"coordinator",[602,618,619],{},"member","), give users roles, and write a\n",[597,622,623],{},"policy"," where a rule depends on the record, for example \"only the author may edit a post\". Then you check the one\npermission on the server, in route rules and in the interface.",[593,626,627,628,631,632,634],{},"Install it when your app has more than \"signed in\" and \"admin\". Who the user is comes from\n",[629,630,168],"a",{"href":169},", which also owns the engine that decides. This module adds the roles, where they are\nstored, the admin pages for them, and what the browser may show. The vocabulary and the order of a check are in\n",[629,633,67],{"href":68},".",[593,636,637,638,641,642,645,646,650],{},"The package is ",[602,639,640],{},"@frigear-nu\u002Fauthorization",". It works in both ",[629,643,644],{"href":169},"modes of Auth",". In\n",[629,647,649],{"href":648},"\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fclient#client-mode","client mode"," the same composables only decide what the app shows.",[652,653,655],"h2",{"id":654},"what-you-get","What you get",[657,658,659,671,681,696,718],"ul",{},[660,661,662,609,665,668,669,634],"li",{},[597,663,664],{},"Roles from config",[602,666,667],{},"authorization.roles",") merged with the roles modules ship, with inheritance, requirements and\nautomatic roles. See ",[629,670,205],{"href":206},[660,672,673,676,677,680],{},[597,674,675],{},"Role assignment",": a user holds several roles, stored in ",[602,678,679],{},"authorization_user_roles",", with a hard-coded escalation\nrule.",[660,682,683,685,686,689,690,693,694,634],{},[597,684,209],{},": ",[602,687,688],{},"definePolicy"," on the server and ",[602,691,692],{},"defineSharedPolicy"," for the server and the client. See\n",[629,695,209],{"href":210},[660,697,698,685,701,613,704,707,708,711,712,715,716,634],{},[597,699,700],{},"The client",[602,702,703],{},"useAuthorization()",[602,705,706],{},"\u003CCan>"," and ",[602,709,710],{},"\u003CCannot>",", route rules and ",[602,713,714],{},"definePageMeta({ authorize })",", and\nfiltered menus, tabs and widgets. See ",[629,717,213],{"href":214},[660,719,720,723,724,726,727,634],{},[597,721,722],{},"Roles admin"," (needs ",[629,725,217],{"href":351},"): read-only role pages and a \"Roles and permissions\" tab\non the admin user page. See ",[629,728,217],{"href":218},[730,731],"module-runtime",{":client":732,":mobile":732,":server":732},"true",[734,735,736,757,766],"note",{},[593,737,738,741,742,613,745,750,751,756],{},[597,739,740],{},"Installed for you:"," ",[602,743,744],{},"@frigear-nu\u002Fmodule-kit",[629,746,747],{"href":169},[602,748,749],{},"@frigear-nu\u002Fauth"," and\n",[629,752,753],{"href":192},[602,754,755],{},"@frigear-nu\u002Fusers"," (client mode: Module Kit and Auth only).",[593,758,759,741,762,765],{},[597,760,761],{},"You add:",[602,763,764],{},"@nuxthub\u002Fcore"," in server mode.",[593,767,768,741,771,613,776,750,781,786],{},[597,769,770],{},"Optional:",[629,772,773],{"href":351},[602,774,775],{},"@frigear-nu\u002Fadmin",[629,777,778],{"href":355},[602,779,780],{},"@frigear-nu\u002Fmenu",[629,782,783],{"href":359},[602,784,785],{},"@frigear-nu\u002Fwidget"," for the admin pages, menu filtering and the user tab.",[788,789,790,791,794,795,798,799,802],"warning",{},"Without Authorization, only ",[602,792,793],{},"implicit"," permissions apply (the self-service ones modules register, such as\n",[602,796,797],{},"tickets:read","), plus whatever your ",[602,800,801],{},"authorization:before"," hook allows. Nothing else is allowed. Auth's route rules are\nstill enforced.",[652,804,806],{"id":805},"quick-setup","Quick setup",[808,809,810,815,843,847,858,1212,1236,1240,1253,1265,1274,1278,1281,1462,1465,1524],"steps",{},[811,812,814],"h3",{"id":813},"install-authorization","Install Authorization",[816,817,822],"pre",{"className":818,"code":819,"language":820,"meta":821,"style":821},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @frigear-nu\u002Fauthorization @nuxthub\u002Fcore\n","bash","",[602,823,824],{"__ignoreMap":821},[825,826,829,833,837,840],"span",{"class":827,"line":828},"line",1,[825,830,832],{"class":831},"sBMFI","pnpm",[825,834,836],{"class":835},"sfazB"," add",[825,838,839],{"class":835}," @frigear-nu\u002Fauthorization",[825,841,842],{"class":835}," @nuxthub\u002Fcore\n",[811,844,846],{"id":845},"define-your-roles","Define your roles",[593,848,849,850,853,854,857],{},"Modules register their permissions. You decide which role holds which. This closes ",[602,851,852],{},"\u002Fadmin\u002F**"," to everyone without\nthe ",[602,855,856],{},"admin:access"," permission, and sends visitors to the sign-in page:",[816,859,864],{"className":860,"code":861,"filename":862,"language":863,"meta":821,"style":821},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { defineRoles } from '@frigear-nu\u002Fauth\u002Faccess'\n\nexport default defineNuxtConfig({\n  modules: ['@nuxthub\u002Fcore', '@frigear-nu\u002Fusers', '@frigear-nu\u002Fauthorization'],\n  routeRules: {\n    '\u002Fadmin\u002F**': { permission: 'admin:access' },\n    '\u002Fapi\u002Fadmin\u002F**': { permission: 'admin:access' },\n  },\n  authorization: {\n    defaultRoles: ['user'], \u002F\u002F every signed-in user holds these\n    roles: defineRoles({\n      admin: { label: 'Admin', grant: ['*'] },\n      user: { label: 'User', grant: ['events:read'] },\n    }),\n    redirectTo: '\u002Flogin', \u002F\u002F unauthenticated page visits; client mode defaults to the login path\n  },\n})\n","nuxt.config.ts","ts",[602,865,866,895,902,921,964,975,1003,1029,1035,1045,1070,1084,1127,1167,1178,1198,1203],{"__ignoreMap":821},[825,867,868,872,876,880,883,886,889,892],{"class":827,"line":828},[825,869,871],{"class":870},"s7zQu","import",[825,873,875],{"class":874},"sMK4o"," {",[825,877,879],{"class":878},"sTEyZ"," defineRoles",[825,881,882],{"class":874}," }",[825,884,885],{"class":870}," from",[825,887,888],{"class":874}," '",[825,890,891],{"class":835},"@frigear-nu\u002Fauth\u002Faccess",[825,893,894],{"class":874},"'\n",[825,896,898],{"class":827,"line":897},2,[825,899,901],{"emptyLinePlaceholder":900},true,"\n",[825,903,905,908,911,915,918],{"class":827,"line":904},3,[825,906,907],{"class":870},"export",[825,909,910],{"class":870}," default",[825,912,914],{"class":913},"s2Zo4"," defineNuxtConfig",[825,916,917],{"class":878},"(",[825,919,920],{"class":874},"{\n",[825,922,924,928,931,934,937,939,941,944,946,948,950,952,954,956,958,961],{"class":827,"line":923},4,[825,925,927],{"class":926},"swJcz","  modules",[825,929,930],{"class":874},":",[825,932,933],{"class":878}," [",[825,935,936],{"class":874},"'",[825,938,764],{"class":835},[825,940,936],{"class":874},[825,942,943],{"class":874},",",[825,945,888],{"class":874},[825,947,755],{"class":835},[825,949,936],{"class":874},[825,951,943],{"class":874},[825,953,888],{"class":874},[825,955,640],{"class":835},[825,957,936],{"class":874},[825,959,960],{"class":878},"]",[825,962,963],{"class":874},",\n",[825,965,967,970,972],{"class":827,"line":966},5,[825,968,969],{"class":926},"  routeRules",[825,971,930],{"class":874},[825,973,974],{"class":874}," {\n",[825,976,978,981,983,985,987,989,992,994,996,998,1000],{"class":827,"line":977},6,[825,979,980],{"class":874},"    '",[825,982,852],{"class":926},[825,984,936],{"class":874},[825,986,930],{"class":874},[825,988,875],{"class":874},[825,990,991],{"class":926}," permission",[825,993,930],{"class":874},[825,995,888],{"class":874},[825,997,856],{"class":835},[825,999,936],{"class":874},[825,1001,1002],{"class":874}," },\n",[825,1004,1006,1008,1011,1013,1015,1017,1019,1021,1023,1025,1027],{"class":827,"line":1005},7,[825,1007,980],{"class":874},[825,1009,1010],{"class":926},"\u002Fapi\u002Fadmin\u002F**",[825,1012,936],{"class":874},[825,1014,930],{"class":874},[825,1016,875],{"class":874},[825,1018,991],{"class":926},[825,1020,930],{"class":874},[825,1022,888],{"class":874},[825,1024,856],{"class":835},[825,1026,936],{"class":874},[825,1028,1002],{"class":874},[825,1030,1032],{"class":827,"line":1031},8,[825,1033,1034],{"class":874},"  },\n",[825,1036,1038,1041,1043],{"class":827,"line":1037},9,[825,1039,1040],{"class":926},"  authorization",[825,1042,930],{"class":874},[825,1044,974],{"class":874},[825,1046,1048,1051,1053,1055,1057,1060,1062,1064,1066],{"class":827,"line":1047},10,[825,1049,1050],{"class":926},"    defaultRoles",[825,1052,930],{"class":874},[825,1054,933],{"class":878},[825,1056,936],{"class":874},[825,1058,1059],{"class":835},"user",[825,1061,936],{"class":874},[825,1063,960],{"class":878},[825,1065,943],{"class":874},[825,1067,1069],{"class":1068},"sHwdD"," \u002F\u002F every signed-in user holds these\n",[825,1071,1073,1076,1078,1080,1082],{"class":827,"line":1072},11,[825,1074,1075],{"class":926},"    roles",[825,1077,930],{"class":874},[825,1079,879],{"class":913},[825,1081,917],{"class":878},[825,1083,920],{"class":874},[825,1085,1087,1090,1092,1094,1097,1099,1101,1103,1105,1107,1110,1112,1114,1116,1119,1121,1124],{"class":827,"line":1086},12,[825,1088,1089],{"class":926},"      admin",[825,1091,930],{"class":874},[825,1093,875],{"class":874},[825,1095,1096],{"class":926}," label",[825,1098,930],{"class":874},[825,1100,888],{"class":874},[825,1102,217],{"class":835},[825,1104,936],{"class":874},[825,1106,943],{"class":874},[825,1108,1109],{"class":926}," grant",[825,1111,930],{"class":874},[825,1113,933],{"class":878},[825,1115,936],{"class":874},[825,1117,1118],{"class":835},"*",[825,1120,936],{"class":874},[825,1122,1123],{"class":878},"] ",[825,1125,1126],{"class":874},"},\n",[825,1128,1130,1133,1135,1137,1139,1141,1143,1146,1148,1150,1152,1154,1156,1158,1161,1163,1165],{"class":827,"line":1129},13,[825,1131,1132],{"class":926},"      user",[825,1134,930],{"class":874},[825,1136,875],{"class":874},[825,1138,1096],{"class":926},[825,1140,930],{"class":874},[825,1142,888],{"class":874},[825,1144,1145],{"class":835},"User",[825,1147,936],{"class":874},[825,1149,943],{"class":874},[825,1151,1109],{"class":926},[825,1153,930],{"class":874},[825,1155,933],{"class":878},[825,1157,936],{"class":874},[825,1159,1160],{"class":835},"events:read",[825,1162,936],{"class":874},[825,1164,1123],{"class":878},[825,1166,1126],{"class":874},[825,1168,1170,1173,1176],{"class":827,"line":1169},14,[825,1171,1172],{"class":874},"    }",[825,1174,1175],{"class":878},")",[825,1177,963],{"class":874},[825,1179,1181,1184,1186,1188,1191,1193,1195],{"class":827,"line":1180},15,[825,1182,1183],{"class":926},"    redirectTo",[825,1185,930],{"class":874},[825,1187,888],{"class":874},[825,1189,1190],{"class":835},"\u002Flogin",[825,1192,936],{"class":874},[825,1194,943],{"class":874},[825,1196,1197],{"class":1068}," \u002F\u002F unauthenticated page visits; client mode defaults to the login path\n",[825,1199,1201],{"class":827,"line":1200},16,[825,1202,1034],{"class":874},[825,1204,1206,1209],{"class":827,"line":1205},17,[825,1207,1208],{"class":874},"}",[825,1210,1211],{"class":878},")\n",[593,1213,1214,1217,1218,1221,1222,1225,1226,1228,1229,1232,1233,634],{},[602,1215,1216],{},"defineRoles"," returns the roles unchanged and types them: once ",[602,1219,1220],{},"nuxi prepare"," has generated the app's types, a grant\nthat names no registered permission (",[602,1223,1224],{},"'events:raed'",") or an unknown parent role fails typecheck, right in\n",[602,1227,862],{},". The build checks the same at ",[602,1230,1231],{},"modules:done",". See\n",[629,1234,205],{"href":1235},"\u002Fmodules\u002Fidentity\u002Fauthorization\u002Froles-and-requirements#type-your-roles",[811,1237,1239],{"id":1238},"generate-the-migration","Generate the migration",[788,1241,1242,1243,1246,1247,707,1249,1252],{},"Without a ",[629,1244,1245],{"href":87},"migration",", role assignment fails: the database lacks the\n",[602,1248,679],{},[602,1250,1251],{},"authorization_meta"," tables.",[816,1254,1256],{"className":818,"code":1255,"language":820,"meta":821,"style":821},"pnpm db:generate\n",[602,1257,1258],{"__ignoreMap":821},[825,1259,1260,1262],{"class":827,"line":828},[825,1261,832],{"class":831},[825,1263,1264],{"class":835}," db:generate\n",[593,1266,1267,1268,1271,1272,634],{},"Module authors do the same in every ",[629,1269,1270],{"href":87},"test fixture"," that installs it. See\n",[629,1273,77],{"href":78},[811,1275,1277],{"id":1276},"check-a-permission","Check a permission",[593,1279,1280],{},"On the server, authorize before loading, then again with the record:",[816,1282,1285],{"className":860,"code":1283,"filename":1284,"language":863,"meta":821,"style":821},"import { intIdParams } from '@frigear-nu\u002Fmodule-kit\u002Fserver'\n\nexport default defineEventHandler(async (event) => {\n  await authorize(event, 'posts:update') \u002F\u002F 401 or 403 before anything is loaded\n  const { id } = await getValidatedRouterParams(event, intIdParams().parse)\n  const post = await findPost(id) \u002F\u002F 404 only now\n  await authorize(event, 'posts:update', post) \u002F\u002F policies see the record\n})\n","server\u002Fapi\u002Fposts\u002F[id].put.ts",[602,1286,1287,1307,1311,1339,1366,1405,1429,1456],{"__ignoreMap":821},[825,1288,1289,1291,1293,1296,1298,1300,1302,1305],{"class":827,"line":828},[825,1290,871],{"class":870},[825,1292,875],{"class":874},[825,1294,1295],{"class":878}," intIdParams",[825,1297,882],{"class":874},[825,1299,885],{"class":870},[825,1301,888],{"class":874},[825,1303,1304],{"class":835},"@frigear-nu\u002Fmodule-kit\u002Fserver",[825,1306,894],{"class":874},[825,1308,1309],{"class":827,"line":897},[825,1310,901],{"emptyLinePlaceholder":900},[825,1312,1313,1315,1317,1320,1322,1326,1328,1332,1334,1337],{"class":827,"line":904},[825,1314,907],{"class":870},[825,1316,910],{"class":870},[825,1318,1319],{"class":913}," defineEventHandler",[825,1321,917],{"class":878},[825,1323,1325],{"class":1324},"spNyl","async",[825,1327,609],{"class":874},[825,1329,1331],{"class":1330},"sHdIc","event",[825,1333,1175],{"class":874},[825,1335,1336],{"class":1324}," =>",[825,1338,974],{"class":874},[825,1340,1341,1344,1347,1349,1351,1353,1355,1358,1360,1363],{"class":827,"line":923},[825,1342,1343],{"class":870},"  await",[825,1345,1346],{"class":913}," authorize",[825,1348,917],{"class":926},[825,1350,1331],{"class":878},[825,1352,943],{"class":874},[825,1354,888],{"class":874},[825,1356,1357],{"class":835},"posts:update",[825,1359,936],{"class":874},[825,1361,1362],{"class":926},") ",[825,1364,1365],{"class":1068},"\u002F\u002F 401 or 403 before anything is loaded\n",[825,1367,1368,1371,1373,1376,1378,1381,1384,1387,1389,1391,1393,1395,1398,1400,1403],{"class":827,"line":966},[825,1369,1370],{"class":1324},"  const",[825,1372,875],{"class":874},[825,1374,1375],{"class":878}," id",[825,1377,882],{"class":874},[825,1379,1380],{"class":874}," =",[825,1382,1383],{"class":870}," await",[825,1385,1386],{"class":913}," getValidatedRouterParams",[825,1388,917],{"class":926},[825,1390,1331],{"class":878},[825,1392,943],{"class":874},[825,1394,1295],{"class":913},[825,1396,1397],{"class":926},"()",[825,1399,634],{"class":874},[825,1401,1402],{"class":878},"parse",[825,1404,1211],{"class":926},[825,1406,1407,1409,1412,1414,1416,1419,1421,1424,1426],{"class":827,"line":977},[825,1408,1370],{"class":1324},[825,1410,1411],{"class":878}," post",[825,1413,1380],{"class":874},[825,1415,1383],{"class":870},[825,1417,1418],{"class":913}," findPost",[825,1420,917],{"class":926},[825,1422,1423],{"class":878},"id",[825,1425,1362],{"class":926},[825,1427,1428],{"class":1068},"\u002F\u002F 404 only now\n",[825,1430,1431,1433,1435,1437,1439,1441,1443,1445,1447,1449,1451,1453],{"class":827,"line":1005},[825,1432,1343],{"class":870},[825,1434,1346],{"class":913},[825,1436,917],{"class":926},[825,1438,1331],{"class":878},[825,1440,943],{"class":874},[825,1442,888],{"class":874},[825,1444,1357],{"class":835},[825,1446,936],{"class":874},[825,1448,943],{"class":874},[825,1450,1411],{"class":878},[825,1452,1362],{"class":926},[825,1454,1455],{"class":1068},"\u002F\u002F policies see the record\n",[825,1457,1458,1460],{"class":827,"line":1031},[825,1459,1208],{"class":874},[825,1461,1211],{"class":878},[593,1463,1464],{},"In the app, show the button only to users who may use it:",[816,1466,1470],{"className":1467,"code":1468,"language":1469,"meta":821,"style":821},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003CCan permission=\"posts:update\" :record=\"post\">\n  \u003Cbutton>Edit\u003C\u002Fbutton>\n\u003C\u002FCan>\n","vue",[602,1471,1472,1510,1515],{"__ignoreMap":821},[825,1473,1474,1477,1480,1482,1485,1488,1490,1492,1495,1498,1500,1502,1505,1507],{"class":827,"line":828},[825,1475,1476],{"class":874},"\u003C",[825,1478,1479],{"class":926},"Can",[825,1481,991],{"class":1324},[825,1483,1484],{"class":874},"=",[825,1486,1487],{"class":874},"\"",[825,1489,1357],{"class":835},[825,1491,1487],{"class":874},[825,1493,1494],{"class":874}," :",[825,1496,1497],{"class":1324},"record",[825,1499,1484],{"class":874},[825,1501,1487],{"class":874},[825,1503,1504],{"class":878},"post",[825,1506,1487],{"class":874},[825,1508,1509],{"class":874},">\n",[825,1511,1512],{"class":827,"line":897},[825,1513,1514],{"class":878},"  \u003Cbutton>Edit\u003C\u002Fbutton>\n",[825,1516,1517,1520,1522],{"class":827,"line":904},[825,1518,1519],{"class":874},"\u003C\u002F",[825,1521,1479],{"class":926},[825,1523,1509],{"class":874},[593,1525,1526,707,1529,1532,1533,1535,1536,1539],{},[602,1527,1528],{},"findPost",[602,1530,1531],{},"Post"," stand for your own code, and ",[602,1534,1357],{}," has to be registered with ",[602,1537,1538],{},"addPermission"," first.",[1541,1542,1545,1548,1549,1552,1553,1555,1556,1559,1560,1562,1563,1566],"callout",{"color":1543,"icon":1544},"success","i-lucide-check",[597,1546,1547],{},"What you should see:"," a visitor who opens a page under ",[602,1550,1551],{},"\u002Fadmin\u002F"," lands on ",[602,1554,1190],{},", with the page in ",[602,1557,1558],{},"?redirect=",".\nA signed-in user without ",[602,1561,856],{}," gets a ",[602,1564,1565],{},"403"," there.",[652,1568,1570],{"id":1569},"options","Options",[593,1572,1573,1574,1577],{},"Options go under the ",[602,1575,1576],{},"authorization"," key.",[1579,1580,1581,1600],"table",{},[1582,1583,1584],"thead",{},[1585,1586,1587,1591,1594,1597],"tr",{},[1588,1589,1590],"th",{},"Option",[1588,1592,1593],{},"Type",[1588,1595,1596],{},"Default",[1588,1598,1599],{},"Purpose",[1601,1602,1603,1625,1649,1676,1697],"tbody",{},[1585,1604,1605,1610,1615,1620],{},[1606,1607,1608],"td",{},[602,1609,608],{},[1606,1611,1612],{},[602,1613,1614],{},"Record\u003Cstring, RoleDefinition>",[1606,1616,1617],{},[602,1618,1619],{},"{}",[1606,1621,1622,1623,634],{},"The app's roles. Merged with the roles modules ship. See ",[629,1624,205],{"href":206},[1585,1626,1627,1632,1637,1642],{},[1606,1628,1629],{},[602,1630,1631],{},"defaultRoles",[1606,1633,1634],{},[602,1635,1636],{},"string[]",[1606,1638,1639],{},[602,1640,1641],{},"[]",[1606,1643,1644,1645,1648],{},"Roles every signed-in user holds. They cannot be assigned, and cannot be ",[602,1646,1647],{},"auto"," roles.",[1585,1650,1651,1656,1661,1667],{},[1606,1652,1653],{},[602,1654,1655],{},"policies.shared",[1606,1657,1658],{},[602,1659,1660],{},"string | false",[1606,1662,1663,1666],{},[602,1664,1665],{},"shared\u002Fpolicies.ts"," when it exists",[1606,1668,1669,1670,1672,1673,634],{},"The file of ",[602,1671,692],{}," exports, run on the server and in the client's ",[602,1674,1675],{},"can()",[1585,1677,1678,1683,1687,1692],{},[1606,1679,1680],{},[602,1681,1682],{},"policies.server",[1606,1684,1685],{},[602,1686,1660],{},[1606,1688,1689,1666],{},[602,1690,1691],{},"server\u002Fpolicies.ts",[1606,1693,1669,1694,1696],{},[602,1695,688],{}," exports, run on the server only.",[1585,1698,1699,1704,1708,1711],{},[1606,1700,1701],{},[602,1702,1703],{},"redirectTo",[1606,1705,1706],{},[602,1707,1660],{},[1606,1709,1710],{},"client mode: Auth's sign-in path",[1606,1712,1713],{},"Where an unauthenticated page visit goes.",[593,1715,1716,1720,1721,1723,1724,1728,1729,1732,1733,1736],{},[597,1717,1718,634],{},[602,1719,1703],{}," The requested page goes along in ",[602,1722,1558],{},", checked by the shared\n",[629,1725,1727],{"href":1726},"\u002Fmodules\u002Fidentity\u002Fauth\u002Freference#redirects","redirect rule",". In server mode without the option, or with ",[602,1730,1731],{},"false",", a\n",[602,1734,1735],{},"401"," error is shown instead.",[593,1738,1739,1745,1746,1749],{},[597,1740,1741,707,1743,634],{},[602,1742,608],{},[602,1744,1631],{}," A role's definition is\n",[602,1747,1748],{},"{ label?, labelKey?, description?, descriptionKey?, grant?, inherit?, requirements?, auto?, assignable?, replace? }",".\nAll of it is explained on the next page. The formatted example below is a complete host configuration:",[816,1751,1753],{"className":860,"code":1752,"filename":862,"language":863,"meta":821,"style":821},"export default defineNuxtConfig({\n  authorization: {\n    defaultRoles: ['user'],\n    roles: {\n      admin: {\n        label: 'Admin',\n        labelKey: 'authorization.roles.admin',\n        grant: ['*'], \u002F\u002F '*' never covers sensitive (:pii) permissions: grant those by name\n      },\n      manager: {\n        label: 'Coordinator',\n        labelKey: 'authorization.roles.manager',\n        grant: ['forms:*', 'users:read', 'users:list'],\n        inherit: ['eventmanager', 'crew'],\n      },\n      eventmanager: {\n        label: 'Event Manager',\n        grant: ['events:*'],\n        inherit: ['user'],\n      },\n      crew: {\n        label: 'Crew',\n        grant: ['events:read'],\n        inherit: ['user'],\n      },\n      member: {\n        label: 'Member',\n        grant: ['member-area:view'],\n        requirements: { subscription: '*' }, \u002F\u002F counts only while every requirement holds\n        auto: true, \u002F\u002F held by everyone meeting the requirements; not assignable\n        inherit: ['user'],\n      },\n      user: {\n        label: 'User',\n        grant: ['events:read'],\n      },\n    },\n  },\n  oauthServer: {\n    scopes: [\n      \u002F\u002F a named scope is a group of permissions (never sensitive or sessionOnly ones)\n      { name: 'tickets', label: 'Your tickets', permissions: ['tickets:read', 'tickets:write'] },\n    ],\n    settings: {\n      roleScopes: { \u002F\u002F the most each role may grant to a client\n        admin: ['*'],\n        user: ['openid', 'profile', 'profile:read', 'profile:write', 'tickets:read', 'tickets:write'],\n      },\n    },\n  },\n})\n",[602,1754,1755,1767,1775,1793,1801,1809,1824,1840,1862,1867,1876,1891,1906,1943,1972,1976,1985,2000,2020,2039,2044,2054,2070,2089,2108,2113,2123,2139,2159,2186,2203,2222,2227,2236,2251,2270,2275,2281,2286,2296,2307,2313,2372,2380,2390,2403,2423,2487,2492,2497,2502],{"__ignoreMap":821},[825,1756,1757,1759,1761,1763,1765],{"class":827,"line":828},[825,1758,907],{"class":870},[825,1760,910],{"class":870},[825,1762,914],{"class":913},[825,1764,917],{"class":878},[825,1766,920],{"class":874},[825,1768,1769,1771,1773],{"class":827,"line":897},[825,1770,1040],{"class":926},[825,1772,930],{"class":874},[825,1774,974],{"class":874},[825,1776,1777,1779,1781,1783,1785,1787,1789,1791],{"class":827,"line":904},[825,1778,1050],{"class":926},[825,1780,930],{"class":874},[825,1782,933],{"class":878},[825,1784,936],{"class":874},[825,1786,1059],{"class":835},[825,1788,936],{"class":874},[825,1790,960],{"class":878},[825,1792,963],{"class":874},[825,1794,1795,1797,1799],{"class":827,"line":923},[825,1796,1075],{"class":926},[825,1798,930],{"class":874},[825,1800,974],{"class":874},[825,1802,1803,1805,1807],{"class":827,"line":966},[825,1804,1089],{"class":926},[825,1806,930],{"class":874},[825,1808,974],{"class":874},[825,1810,1811,1814,1816,1818,1820,1822],{"class":827,"line":977},[825,1812,1813],{"class":926},"        label",[825,1815,930],{"class":874},[825,1817,888],{"class":874},[825,1819,217],{"class":835},[825,1821,936],{"class":874},[825,1823,963],{"class":874},[825,1825,1826,1829,1831,1833,1836,1838],{"class":827,"line":1005},[825,1827,1828],{"class":926},"        labelKey",[825,1830,930],{"class":874},[825,1832,888],{"class":874},[825,1834,1835],{"class":835},"authorization.roles.admin",[825,1837,936],{"class":874},[825,1839,963],{"class":874},[825,1841,1842,1845,1847,1849,1851,1853,1855,1857,1859],{"class":827,"line":1031},[825,1843,1844],{"class":926},"        grant",[825,1846,930],{"class":874},[825,1848,933],{"class":878},[825,1850,936],{"class":874},[825,1852,1118],{"class":835},[825,1854,936],{"class":874},[825,1856,960],{"class":878},[825,1858,943],{"class":874},[825,1860,1861],{"class":1068}," \u002F\u002F '*' never covers sensitive (:pii) permissions: grant those by name\n",[825,1863,1864],{"class":827,"line":1037},[825,1865,1866],{"class":874},"      },\n",[825,1868,1869,1872,1874],{"class":827,"line":1047},[825,1870,1871],{"class":926},"      manager",[825,1873,930],{"class":874},[825,1875,974],{"class":874},[825,1877,1878,1880,1882,1884,1887,1889],{"class":827,"line":1072},[825,1879,1813],{"class":926},[825,1881,930],{"class":874},[825,1883,888],{"class":874},[825,1885,1886],{"class":835},"Coordinator",[825,1888,936],{"class":874},[825,1890,963],{"class":874},[825,1892,1893,1895,1897,1899,1902,1904],{"class":827,"line":1086},[825,1894,1828],{"class":926},[825,1896,930],{"class":874},[825,1898,888],{"class":874},[825,1900,1901],{"class":835},"authorization.roles.manager",[825,1903,936],{"class":874},[825,1905,963],{"class":874},[825,1907,1908,1910,1912,1914,1916,1919,1921,1923,1925,1928,1930,1932,1934,1937,1939,1941],{"class":827,"line":1129},[825,1909,1844],{"class":926},[825,1911,930],{"class":874},[825,1913,933],{"class":878},[825,1915,936],{"class":874},[825,1917,1918],{"class":835},"forms:*",[825,1920,936],{"class":874},[825,1922,943],{"class":874},[825,1924,888],{"class":874},[825,1926,1927],{"class":835},"users:read",[825,1929,936],{"class":874},[825,1931,943],{"class":874},[825,1933,888],{"class":874},[825,1935,1936],{"class":835},"users:list",[825,1938,936],{"class":874},[825,1940,960],{"class":878},[825,1942,963],{"class":874},[825,1944,1945,1948,1950,1952,1954,1957,1959,1961,1963,1966,1968,1970],{"class":827,"line":1169},[825,1946,1947],{"class":926},"        inherit",[825,1949,930],{"class":874},[825,1951,933],{"class":878},[825,1953,936],{"class":874},[825,1955,1956],{"class":835},"eventmanager",[825,1958,936],{"class":874},[825,1960,943],{"class":874},[825,1962,888],{"class":874},[825,1964,1965],{"class":835},"crew",[825,1967,936],{"class":874},[825,1969,960],{"class":878},[825,1971,963],{"class":874},[825,1973,1974],{"class":827,"line":1180},[825,1975,1866],{"class":874},[825,1977,1978,1981,1983],{"class":827,"line":1200},[825,1979,1980],{"class":926},"      eventmanager",[825,1982,930],{"class":874},[825,1984,974],{"class":874},[825,1986,1987,1989,1991,1993,1996,1998],{"class":827,"line":1205},[825,1988,1813],{"class":926},[825,1990,930],{"class":874},[825,1992,888],{"class":874},[825,1994,1995],{"class":835},"Event Manager",[825,1997,936],{"class":874},[825,1999,963],{"class":874},[825,2001,2003,2005,2007,2009,2011,2014,2016,2018],{"class":827,"line":2002},18,[825,2004,1844],{"class":926},[825,2006,930],{"class":874},[825,2008,933],{"class":878},[825,2010,936],{"class":874},[825,2012,2013],{"class":835},"events:*",[825,2015,936],{"class":874},[825,2017,960],{"class":878},[825,2019,963],{"class":874},[825,2021,2023,2025,2027,2029,2031,2033,2035,2037],{"class":827,"line":2022},19,[825,2024,1947],{"class":926},[825,2026,930],{"class":874},[825,2028,933],{"class":878},[825,2030,936],{"class":874},[825,2032,1059],{"class":835},[825,2034,936],{"class":874},[825,2036,960],{"class":878},[825,2038,963],{"class":874},[825,2040,2042],{"class":827,"line":2041},20,[825,2043,1866],{"class":874},[825,2045,2047,2050,2052],{"class":827,"line":2046},21,[825,2048,2049],{"class":926},"      crew",[825,2051,930],{"class":874},[825,2053,974],{"class":874},[825,2055,2057,2059,2061,2063,2066,2068],{"class":827,"line":2056},22,[825,2058,1813],{"class":926},[825,2060,930],{"class":874},[825,2062,888],{"class":874},[825,2064,2065],{"class":835},"Crew",[825,2067,936],{"class":874},[825,2069,963],{"class":874},[825,2071,2073,2075,2077,2079,2081,2083,2085,2087],{"class":827,"line":2072},23,[825,2074,1844],{"class":926},[825,2076,930],{"class":874},[825,2078,933],{"class":878},[825,2080,936],{"class":874},[825,2082,1160],{"class":835},[825,2084,936],{"class":874},[825,2086,960],{"class":878},[825,2088,963],{"class":874},[825,2090,2092,2094,2096,2098,2100,2102,2104,2106],{"class":827,"line":2091},24,[825,2093,1947],{"class":926},[825,2095,930],{"class":874},[825,2097,933],{"class":878},[825,2099,936],{"class":874},[825,2101,1059],{"class":835},[825,2103,936],{"class":874},[825,2105,960],{"class":878},[825,2107,963],{"class":874},[825,2109,2111],{"class":827,"line":2110},25,[825,2112,1866],{"class":874},[825,2114,2116,2119,2121],{"class":827,"line":2115},26,[825,2117,2118],{"class":926},"      member",[825,2120,930],{"class":874},[825,2122,974],{"class":874},[825,2124,2126,2128,2130,2132,2135,2137],{"class":827,"line":2125},27,[825,2127,1813],{"class":926},[825,2129,930],{"class":874},[825,2131,888],{"class":874},[825,2133,2134],{"class":835},"Member",[825,2136,936],{"class":874},[825,2138,963],{"class":874},[825,2140,2142,2144,2146,2148,2150,2153,2155,2157],{"class":827,"line":2141},28,[825,2143,1844],{"class":926},[825,2145,930],{"class":874},[825,2147,933],{"class":878},[825,2149,936],{"class":874},[825,2151,2152],{"class":835},"member-area:view",[825,2154,936],{"class":874},[825,2156,960],{"class":878},[825,2158,963],{"class":874},[825,2160,2162,2165,2167,2169,2172,2174,2176,2178,2180,2183],{"class":827,"line":2161},29,[825,2163,2164],{"class":926},"        requirements",[825,2166,930],{"class":874},[825,2168,875],{"class":874},[825,2170,2171],{"class":926}," subscription",[825,2173,930],{"class":874},[825,2175,888],{"class":874},[825,2177,1118],{"class":835},[825,2179,936],{"class":874},[825,2181,2182],{"class":874}," },",[825,2184,2185],{"class":1068}," \u002F\u002F counts only while every requirement holds\n",[825,2187,2189,2192,2194,2198,2200],{"class":827,"line":2188},30,[825,2190,2191],{"class":926},"        auto",[825,2193,930],{"class":874},[825,2195,2197],{"class":2196},"sfNiH"," true",[825,2199,943],{"class":874},[825,2201,2202],{"class":1068}," \u002F\u002F held by everyone meeting the requirements; not assignable\n",[825,2204,2206,2208,2210,2212,2214,2216,2218,2220],{"class":827,"line":2205},31,[825,2207,1947],{"class":926},[825,2209,930],{"class":874},[825,2211,933],{"class":878},[825,2213,936],{"class":874},[825,2215,1059],{"class":835},[825,2217,936],{"class":874},[825,2219,960],{"class":878},[825,2221,963],{"class":874},[825,2223,2225],{"class":827,"line":2224},32,[825,2226,1866],{"class":874},[825,2228,2230,2232,2234],{"class":827,"line":2229},33,[825,2231,1132],{"class":926},[825,2233,930],{"class":874},[825,2235,974],{"class":874},[825,2237,2239,2241,2243,2245,2247,2249],{"class":827,"line":2238},34,[825,2240,1813],{"class":926},[825,2242,930],{"class":874},[825,2244,888],{"class":874},[825,2246,1145],{"class":835},[825,2248,936],{"class":874},[825,2250,963],{"class":874},[825,2252,2254,2256,2258,2260,2262,2264,2266,2268],{"class":827,"line":2253},35,[825,2255,1844],{"class":926},[825,2257,930],{"class":874},[825,2259,933],{"class":878},[825,2261,936],{"class":874},[825,2263,1160],{"class":835},[825,2265,936],{"class":874},[825,2267,960],{"class":878},[825,2269,963],{"class":874},[825,2271,2273],{"class":827,"line":2272},36,[825,2274,1866],{"class":874},[825,2276,2278],{"class":827,"line":2277},37,[825,2279,2280],{"class":874},"    },\n",[825,2282,2284],{"class":827,"line":2283},38,[825,2285,1034],{"class":874},[825,2287,2289,2292,2294],{"class":827,"line":2288},39,[825,2290,2291],{"class":926},"  oauthServer",[825,2293,930],{"class":874},[825,2295,974],{"class":874},[825,2297,2299,2302,2304],{"class":827,"line":2298},40,[825,2300,2301],{"class":926},"    scopes",[825,2303,930],{"class":874},[825,2305,2306],{"class":878}," [\n",[825,2308,2310],{"class":827,"line":2309},41,[825,2311,2312],{"class":1068},"      \u002F\u002F a named scope is a group of permissions (never sensitive or sessionOnly ones)\n",[825,2314,2316,2319,2322,2324,2326,2329,2331,2333,2335,2337,2339,2342,2344,2346,2349,2351,2353,2355,2357,2359,2361,2363,2366,2368,2370],{"class":827,"line":2315},42,[825,2317,2318],{"class":874},"      {",[825,2320,2321],{"class":926}," name",[825,2323,930],{"class":874},[825,2325,888],{"class":874},[825,2327,2328],{"class":835},"tickets",[825,2330,936],{"class":874},[825,2332,943],{"class":874},[825,2334,1096],{"class":926},[825,2336,930],{"class":874},[825,2338,888],{"class":874},[825,2340,2341],{"class":835},"Your tickets",[825,2343,936],{"class":874},[825,2345,943],{"class":874},[825,2347,2348],{"class":926}," permissions",[825,2350,930],{"class":874},[825,2352,933],{"class":878},[825,2354,936],{"class":874},[825,2356,797],{"class":835},[825,2358,936],{"class":874},[825,2360,943],{"class":874},[825,2362,888],{"class":874},[825,2364,2365],{"class":835},"tickets:write",[825,2367,936],{"class":874},[825,2369,1123],{"class":878},[825,2371,1126],{"class":874},[825,2373,2375,2378],{"class":827,"line":2374},43,[825,2376,2377],{"class":878},"    ]",[825,2379,963],{"class":874},[825,2381,2383,2386,2388],{"class":827,"line":2382},44,[825,2384,2385],{"class":926},"    settings",[825,2387,930],{"class":874},[825,2389,974],{"class":874},[825,2391,2393,2396,2398,2400],{"class":827,"line":2392},45,[825,2394,2395],{"class":926},"      roleScopes",[825,2397,930],{"class":874},[825,2399,875],{"class":874},[825,2401,2402],{"class":1068}," \u002F\u002F the most each role may grant to a client\n",[825,2404,2406,2409,2411,2413,2415,2417,2419,2421],{"class":827,"line":2405},46,[825,2407,2408],{"class":926},"        admin",[825,2410,930],{"class":874},[825,2412,933],{"class":878},[825,2414,936],{"class":874},[825,2416,1118],{"class":835},[825,2418,936],{"class":874},[825,2420,960],{"class":878},[825,2422,963],{"class":874},[825,2424,2426,2429,2431,2433,2435,2438,2440,2442,2444,2447,2449,2451,2453,2456,2458,2460,2462,2465,2467,2469,2471,2473,2475,2477,2479,2481,2483,2485],{"class":827,"line":2425},47,[825,2427,2428],{"class":926},"        user",[825,2430,930],{"class":874},[825,2432,933],{"class":878},[825,2434,936],{"class":874},[825,2436,2437],{"class":835},"openid",[825,2439,936],{"class":874},[825,2441,943],{"class":874},[825,2443,888],{"class":874},[825,2445,2446],{"class":835},"profile",[825,2448,936],{"class":874},[825,2450,943],{"class":874},[825,2452,888],{"class":874},[825,2454,2455],{"class":835},"profile:read",[825,2457,936],{"class":874},[825,2459,943],{"class":874},[825,2461,888],{"class":874},[825,2463,2464],{"class":835},"profile:write",[825,2466,936],{"class":874},[825,2468,943],{"class":874},[825,2470,888],{"class":874},[825,2472,797],{"class":835},[825,2474,936],{"class":874},[825,2476,943],{"class":874},[825,2478,888],{"class":874},[825,2480,2365],{"class":835},[825,2482,936],{"class":874},[825,2484,960],{"class":878},[825,2486,963],{"class":874},[825,2488,2490],{"class":827,"line":2489},48,[825,2491,1866],{"class":874},[825,2493,2495],{"class":827,"line":2494},49,[825,2496,2280],{"class":874},[825,2498,2500],{"class":827,"line":2499},50,[825,2501,1034],{"class":874},[825,2503,2505,2507],{"class":827,"line":2504},51,[825,2506,1208],{"class":874},[825,2508,1211],{"class":878},[593,2510,2511,2512,2515],{},"Every grant has to name a registered permission, and every role in ",[602,2513,2514],{},"inherit"," has to exist: the build stops\notherwise.",[734,2517,2518,2519,613,2522,613,2525,2528,2529,2532,2533,634],{},"Removed options: ",[602,2520,2521],{},"rbac",[602,2523,2524],{},"abilities",[602,2526,2527],{},"resolvers",", and ",[602,2530,2531],{},"roles.{hierarchy, inherits, revoke, labels, descriptions, definitions, defaultRole}",". See ",[629,2534,2535],{"href":152},"Migrate access control",[652,2537,234],{"id":2538},"hooks",[593,2540,2541,2542,2545],{},"Your app answers these Nitro hooks from a server plugin (",[602,2543,2544],{},"server\u002Fplugins\u002F*.ts",").",[1579,2547,2548,2564],{},[1582,2549,2550],{},[1585,2551,2552,2555,2558,2561],{},[1588,2553,2554],{},"Hook",[1588,2556,2557],{},"Package",[1588,2559,2560],{},"When",[1588,2562,2563],{},"Payload",[1601,2565,2566,2583],{},[1585,2567,2568,2572,2574,2577],{},[1606,2569,2570],{},[602,2571,801],{},[1606,2573,168],{},[1606,2575,2576],{},"A permission check passes the credential's own limits",[1606,2578,2579,2582],{},[602,2580,2581],{},"{ event, principal, user, permission, record, allow(), deny() }",". The single host override.",[1585,2584,2585,2590,2592,2595],{},[1606,2586,2587],{},[602,2588,2589],{},"authorization:roles",[1606,2591,168],{},[1606,2593,2594],{},"A user's roles are resolved, once per request",[1606,2596,2597,2600,2601,634],{},[602,2598,2599],{},"{ event, user, roles }",". Push to or remove from ",[602,2602,608],{},[593,2604,2605,2609,2610,2612,2613,2615,2616,634],{},[629,2606,2608],{"href":2607},"\u002Fguide\u002Fconcepts\u002Fauth-and-scopes#the-before-hook","The before hook"," explains ",[602,2611,801],{},".\n",[602,2614,2589],{}," is on ",[629,2617,205],{"href":2618},"\u002Fmodules\u002Fidentity\u002Fauthorization\u002Froles-and-requirements#where-a-users-roles-come-from",[652,2620,2622],{"id":2621},"routes","Routes",[593,2624,2625,2626,2629,2630,2633,2634,2637,2638,634],{},"Routes the module registers, and who may call them. Paths come from ",[602,2627,2628],{},"authorizationApi"," in\n",[602,2631,2632],{},"@frigear-nu\u002Fauthorization\u002Fapi",". The caller's own access, ",[602,2635,2636],{},"GET \u002Fapi\u002Fauth\u002Fme\u002Faccess",", belongs to\n",[629,2639,168],{"href":2640},"\u002Fmodules\u002Fidentity\u002Fauth\u002Freference#routes",[1579,2642,2643,2659],{},[1582,2644,2645],{},[1585,2646,2647,2650,2653,2656],{},[1588,2648,2649],{},"Method",[1588,2651,2652],{},"Path",[1588,2654,2655],{},"Who",[1588,2657,2658],{},"Answers",[1601,2660,2661,2684,2709,2730,2755],{},[1585,2662,2663,2668,2676,2681],{},[1606,2664,2665],{},[602,2666,2667],{},"GET",[1606,2669,2670,609,2673,1175],{},[602,2671,2672],{},"\u002Fapi\u002Fadmin\u002Fauthorization\u002Froles",[602,2674,2675],{},"admin.roles",[1606,2677,2678],{},[602,2679,2680],{},"roles:read",[1606,2682,2683],{},"Every role, most senior first, with its user count.",[1585,2685,2686,2690,2698,2702],{},[1606,2687,2688],{},[602,2689,2667],{},[1606,2691,2692,609,2695,1175],{},[602,2693,2694],{},"\u002Fapi\u002Fadmin\u002Fauthorization\u002Froles\u002F:name",[602,2696,2697],{},"admin.role(name)",[1606,2699,2700],{},[602,2701,2680],{},[1606,2703,2704,2705,2708],{},"One role: every registered permission, whether it holds it and why. ",[602,2706,2707],{},"404"," for an unknown role.",[1585,2710,2711,2715,2723,2727],{},[1606,2712,2713],{},[602,2714,2667],{},[1606,2716,2717,609,2720,1175],{},[602,2718,2719],{},"\u002Fapi\u002Fadmin\u002Fauthorization\u002Froles\u002F:name\u002Fusers",[602,2721,2722],{},"admin.roleUsers(name)",[1606,2724,2725],{},[602,2726,2680],{},[1606,2728,2729],{},"The users with that role assigned, paginated.",[1585,2731,2732,2736,2744,2752],{},[1606,2733,2734],{},[602,2735,2667],{},[1606,2737,2738,609,2741,1175],{},[602,2739,2740],{},"\u002Fapi\u002Fadmin\u002Fauthorization\u002Fusers\u002F:id\u002Froles",[602,2742,2743],{},"admin.userRoles(id)",[1606,2745,2746,2748,2749],{},[602,2747,2680],{}," or ",[602,2750,2751],{},"roles:assign",[1606,2753,2754],{},"A user's assigned and effective roles, their permissions, and the roles the caller may assign.",[1585,2756,2757,2762,2768,2773],{},[1606,2758,2759],{},[602,2760,2761],{},"PUT",[1606,2763,2764,609,2766,1175],{},[602,2765,2740],{},[602,2767,2743],{},[1606,2769,2770,2772],{},[602,2771,2751],{}," (session only)",[1606,2774,2775,2776,613,2779,613,2782,634],{},"Replaces the roles assigned by staff. ",[602,2777,2778],{},"400 unknown_role",[602,2780,2781],{},"403 forbidden",[602,2783,2784],{},"409 role_not_assignable",[652,2786,2787],{"id":599},"Permissions",[1579,2789,2790,2806],{},[1582,2791,2792],{},[1585,2793,2794,2797,2800,2803],{},[1588,2795,2796],{},"Permission",[1588,2798,2799],{},"Flags",[1588,2801,2802],{},"Default grant",[1588,2804,2805],{},"Allows",[1601,2807,2808,2826],{},[1585,2809,2810,2814,2816,2823],{},[1606,2811,2812],{},[602,2813,2680],{},[1606,2815],{},[1606,2817,2818,2820,2821],{},[602,2819,612],{}," through ",[602,2822,1118],{},[1606,2824,2825],{},"See the roles, what each may do and who has them.",[1585,2827,2828,2832,2837,2843],{},[1606,2829,2830],{},[602,2831,2751],{},[1606,2833,2834],{},[602,2835,2836],{},"sessionOnly",[1606,2838,2839,2820,2841],{},[602,2840,612],{},[602,2842,1118],{},[1606,2844,2845],{},"Give users roles and take them away, within your own permissions.",[593,2847,2848,2849,613,2852,2855,2856,707,2859,2862],{},"The sensitive permissions of other modules (",[602,2850,2851],{},"events:pii",[602,2853,2854],{},"forms:pii",") are sensitive (MCP only): they gate personal data\nin MCP tool output, while the admin HTTP API is gated by ",[602,2857,2858],{},"events:manage",[602,2860,2861],{},"forms:manage",". Grant them by name.",[652,2864,41],{"id":2865},"database",[593,2867,2868,2869,2872],{},"Tables the module adds. Generate and commit a ",[629,2870,1245],{"href":2871},"\u002Fget-started\u002Fdatabase#migrations"," after installing. Both\nexist for SQLite and PostgreSQL.",[1579,2874,2875,2885],{},[1582,2876,2877],{},[1585,2878,2879,2882],{},[1588,2880,2881],{},"Table",[1588,2883,2884],{},"Holds",[1601,2886,2887,2925],{},[1585,2888,2889,2893],{},[1606,2890,2891],{},[602,2892,679],{},[1606,2894,2895,2896,613,2899,613,2902,609,2905,613,2908,2748,2911,2914,2915,613,2918,2921,2922,634],{},"One row per assigned role: ",[602,2897,2898],{},"user_id",[602,2900,2901],{},"role",[602,2903,2904],{},"source",[602,2906,2907],{},"manual",[602,2909,2910],{},"sso",[602,2912,2913],{},"migrated","), ",[602,2916,2917],{},"granted_by",[602,2919,2920],{},"created_at",". Primary key ",[602,2923,2924],{},"(user_id, role)",[1585,2926,2927,2931],{},[1606,2928,2929],{},[602,2930,1251],{},[1606,2932,2933,2934,2937],{},"Markers of one-off tasks, such as the ",[602,2935,2936],{},"users.role"," migration.",[593,2939,2940,2941,2943,2944,2947,2948,634],{},"The ",[602,2942,2936],{}," column is still added to the ",[602,2945,2946],{},"users"," table, for the one-off migration only. Nothing reads it as a live\nrole, and a later release drops it. See\n",[629,2949,2951],{"href":2950},"\u002Fmodules\u002Fidentity\u002Fauthorization\u002Froles-and-requirements#the-usersrole-migration","the role migration",[652,2953,2955],{"id":2954},"next-steps","Next steps",[657,2957,2958,2963,2968,2978,2983,2988],{},[660,2959,2960,2962],{},[629,2961,205],{"href":206}," – how roles are built and assigned.",[660,2964,2965,2967],{},[629,2966,209],{"href":210}," – refine a permission for one record.",[660,2969,2970,2972,2973,613,2975,2977],{},[629,2971,213],{"href":214}," – ",[602,2974,703],{},[602,2976,706],{}," and route rules.",[660,2979,2980,2982],{},[629,2981,217],{"href":218}," – the roles pages and the user roles tab.",[660,2984,2985,2987],{},[629,2986,482],{"href":483}," – the two-step route in context.",[660,2989,2990,2993],{},[629,2991,31],{"href":2992},"\u002Fget-started\u002Fauthentication#_4-roles-and-the-first-admin"," – make the first user an admin.",[2995,2996,2997],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":821,"searchDepth":897,"depth":897,"links":2999},[3000,3001,3007,3008,3009,3010,3011,3012],{"id":654,"depth":897,"text":655},{"id":805,"depth":897,"text":806,"children":3002},[3003,3004,3005,3006],{"id":813,"depth":904,"text":814},{"id":845,"depth":904,"text":846},{"id":1238,"depth":904,"text":1239},{"id":1276,"depth":904,"text":1277},{"id":1569,"depth":897,"text":1570},{"id":2538,"depth":897,"text":234},{"id":2621,"depth":897,"text":2622},{"id":599,"depth":897,"text":2787},{"id":2865,"depth":897,"text":41},{"id":2954,"depth":897,"text":2955},"Roles, permissions and policies that decide what a signed-in user may do on pages, server routes and in the interface.","md",null,{},{"title":173},{"title":199,"description":3013},"tRUNKEEn-Vf3WbG-fCkz0c0YRXTzVNXGT9zB0iOPhqs",[3021,3023],{"title":195,"path":196,"stem":197,"description":3022,"children":-1},"Gives signed-in users an account area where they change their profile, password, passkeys and API tokens.",{"title":205,"path":206,"stem":207,"description":3024,"children":-1},"How roles are built from host config and module defaults, how users get them, and how to keep a role tied to a condition such as a subscription.",1794503146343]