[{"data":1,"prerenderedAt":1571},["ShallowReactive",2],{"navigation":3,"/guides/end-to-end-tutorial":145,"/guides/end-to-end-tutorial-surround":1566},[4,28,49,88,101,127],{"title":5,"path":6,"stem":7,"children":8,"icon":27},"Getting Started","/getting-started","1.getting-started/1.index",[9,11,15,19,23],{"title":10,"path":6,"stem":7},"Introduction",{"title":12,"path":13,"stem":14},"Working with Agents","/getting-started/working-with-agents","1.getting-started/2.working-with-agents",{"title":16,"path":17,"stem":18},"Setup a Service Provider","/getting-started/setup-service-provider","1.getting-started/3.setup-service-provider",{"title":20,"path":21,"stem":22},"Setup an Identity Provider","/getting-started/setup-identity-provider","1.getting-started/4.setup-identity-provider",{"title":24,"path":25,"stem":26},"Developers","/getting-started/developers","1.getting-started/5.developers",false,{"title":29,"icon":27,"path":30,"stem":31,"children":32,"page":27},"Guides","/guides","2.guides",[33,37,41,45],{"title":34,"path":35,"stem":36},"How It Works","/guides/how-it-works","2.guides/1.how-it-works",{"title":38,"path":39,"stem":40},"Capabilities Guide","/guides/capabilities-guide","2.guides/2.capabilities-guide",{"title":42,"path":43,"stem":44},"End-to-End Tutorial","/guides/end-to-end-tutorial","2.guides/3.end-to-end-tutorial",{"title":46,"path":47,"stem":48},"Delegation Guide","/guides/delegation-guide","2.guides/4.delegation-guide",{"title":50,"path":51,"stem":52,"children":53,"icon":27},"Ecosystem","/ecosystem","3.ecosystem/1.index",[54,56,60,64,68,72,76,80,84],{"title":55,"path":51,"stem":52},"Overview",{"title":57,"path":58,"stem":59},"grapes CLI","/ecosystem/grapes","3.ecosystem/2.grapes",{"title":61,"path":62,"stem":63},"shapes CLI","/ecosystem/shapes","3.ecosystem/3.shapes",{"title":65,"path":66,"stem":67},"escapes","/ecosystem/escapes","3.ecosystem/4.escapes",{"title":69,"path":70,"stem":71},"OpenApe Proxy","/ecosystem/proxy","3.ecosystem/5.proxy",{"title":73,"path":74,"stem":75},"OpenApe Browser","/ecosystem/browser","3.ecosystem/6.browser",{"title":77,"path":78,"stem":79},"OpenApe Auth","/ecosystem/auth","3.ecosystem/7.auth",{"title":81,"path":82,"stem":83},"OpenApe Grants","/ecosystem/grants","3.ecosystem/8.grants",{"title":85,"path":86,"stem":87},"nuxt-auth-sp","/ecosystem/nuxt-auth-sp","3.ecosystem/9.nuxt-auth-sp",{"title":89,"icon":27,"path":90,"stem":91,"children":92,"page":27},"Security","/security","4.security",[93,97],{"title":94,"path":95,"stem":96},"Compliance","/security/compliance","4.security/1.compliance",{"title":98,"path":99,"stem":100},"Threat Model","/security/threat-model","4.security/2.threat-model",{"title":102,"path":103,"stem":104,"children":105,"icon":27},"Reference","/reference","5.reference/1.index",[106,107,111,115,119,123],{"title":102,"path":103,"stem":104},{"title":108,"path":109,"stem":110},"IdP Configuration","/reference/idp-configuration","5.reference/2.idp-configuration",{"title":112,"path":113,"stem":114},"SP Configuration","/reference/sp-configuration","5.reference/3.sp-configuration",{"title":116,"path":117,"stem":118},"API Endpoints","/reference/api-endpoints","5.reference/4.api-endpoints",{"title":120,"path":121,"stem":122},"escapes Config","/reference/escapes-config","5.reference/5.escapes-config",{"title":124,"path":125,"stem":126},"Proxy Config","/reference/proxy-config","5.reference/6.proxy-config",{"title":128,"path":129,"stem":130,"children":131,"icon":27},"Operations","/operations","6.operations/1.index",[132,133,137,141],{"title":128,"path":129,"stem":130},{"title":134,"path":135,"stem":136},"Deployment","/operations/deployment","6.operations/2.deployment",{"title":138,"path":139,"stem":140},"Troubleshooting","/operations/troubleshooting","6.operations/3.troubleshooting",{"title":142,"path":143,"stem":144},"Monitoring","/operations/monitoring","6.operations/4.monitoring",{"id":146,"title":42,"body":147,"description":1560,"extension":1561,"links":1562,"meta":1563,"navigation":486,"path":43,"seo":1564,"stem":44,"__hash__":1565},"docs/2.guides/3.end-to-end-tutorial.md",{"type":148,"value":149,"toc":1533},"minimark",[150,154,158,163,174,177,190,194,199,246,250,257,431,435,460,463,500,504,507,511,542,546,615,619,625,882,886,906,910,927,931,950,953,963,966,983,987,1020,1023,1027,1031,1204,1208,1246,1250,1253,1294,1305,1309,1316,1380,1387,1391,1460,1467,1500,1504,1529],[151,152,42],"h1",{"id":153},"end-to-end-tutorial",[155,156,157],"p",{},"This tutorial walks through setting up a complete OpenApe environment on your local machine: an Identity Provider (IdP), a Service Provider (SP) app, and an AI agent that requests grants.",[159,160,162],"h2",{"id":161},"what-well-build","What We'll Build",[164,165,170],"pre",{"className":166,"code":168,"language":169},[167],"language-text","┌──────────────────┐     DDISA      ┌──────────────────┐\n│   Service Provider│◄──────────────►│  Identity Provider│\n│   (Nuxt App)      │   Login Flow   │  (Nuxt + IdP)    │\n│   localhost:3001   │               │  localhost:3000    │\n└──────────────────┘               └──────────────────┘\n                                            ▲\n                                            │ Grant Request\n                                            │ + Approval\n                                   ┌────────┴─────────┐\n                                   │  AI Agent (CLI)   │\n                                   │  grapes + escapes │\n                                   └──────────────────┘\n","text",[171,172,168],"code",{"__ignoreMap":173},"",[155,175,176],{},"By the end, you'll have:",[178,179,180,184,187],"ol",{},[181,182,183],"li",{},"An IdP that issues Passkey-based logins and manages grants",[181,185,186],{},"An SP app that authenticates users via DDISA",[181,188,189],{},"An enrolled agent that can request and use grants",[159,191,193],{"id":192},"part-1-set-up-the-idp","Part 1: Set Up the IdP",[195,196,198],"h3",{"id":197},"create-the-idp-project","Create the IdP project",[164,200,204],{"className":201,"code":202,"language":203,"meta":173,"style":173},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","npx nuxi@latest init my-idp\ncd my-idp\nnpm install @openape/nuxt-auth-idp\n","bash",[171,205,206,225,234],{"__ignoreMap":173},[207,208,211,215,219,222],"span",{"class":209,"line":210},"line",1,[207,212,214],{"class":213},"sBMFI","npx",[207,216,218],{"class":217},"sfazB"," nuxi@latest",[207,220,221],{"class":217}," init",[207,223,224],{"class":217}," my-idp\n",[207,226,228,232],{"class":209,"line":227},2,[207,229,231],{"class":230},"s2Zo4","cd",[207,233,224],{"class":217},[207,235,237,240,243],{"class":209,"line":236},3,[207,238,239],{"class":213},"npm",[207,241,242],{"class":217}," install",[207,244,245],{"class":217}," @openape/nuxt-auth-idp\n",[195,247,249],{"id":248},"configure-the-idp","Configure the IdP",[155,251,252,253,256],{},"Add the module to ",[171,254,255],{},"nuxt.config.ts",":",[164,258,262],{"className":259,"code":260,"language":261,"meta":173,"style":173},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@openape/nuxt-auth-idp'],\n  openapeIdp: {\n    rpName: 'My OpenApe IdP',\n    rpID: 'localhost',\n    rpOrigin: 'http://localhost:3000',\n    managementToken: 'dev-management-token-change-in-prod',\n    grants: {\n      enablePages: true\n    }\n  }\n})\n","typescript",[171,263,264,284,309,319,337,354,371,388,398,410,416,422],{"__ignoreMap":173},[207,265,266,270,273,276,280],{"class":209,"line":210},[207,267,269],{"class":268},"s7zQu","export",[207,271,272],{"class":268}," default",[207,274,275],{"class":230}," defineNuxtConfig",[207,277,279],{"class":278},"sTEyZ","(",[207,281,283],{"class":282},"sMK4o","{\n",[207,285,286,290,292,295,298,301,303,306],{"class":209,"line":227},[207,287,289],{"class":288},"swJcz","  modules",[207,291,256],{"class":282},[207,293,294],{"class":278}," [",[207,296,297],{"class":282},"'",[207,299,300],{"class":217},"@openape/nuxt-auth-idp",[207,302,297],{"class":282},[207,304,305],{"class":278},"]",[207,307,308],{"class":282},",\n",[207,310,311,314,316],{"class":209,"line":236},[207,312,313],{"class":288},"  openapeIdp",[207,315,256],{"class":282},[207,317,318],{"class":282}," {\n",[207,320,322,325,327,330,333,335],{"class":209,"line":321},4,[207,323,324],{"class":288},"    rpName",[207,326,256],{"class":282},[207,328,329],{"class":282}," '",[207,331,332],{"class":217},"My OpenApe IdP",[207,334,297],{"class":282},[207,336,308],{"class":282},[207,338,340,343,345,347,350,352],{"class":209,"line":339},5,[207,341,342],{"class":288},"    rpID",[207,344,256],{"class":282},[207,346,329],{"class":282},[207,348,349],{"class":217},"localhost",[207,351,297],{"class":282},[207,353,308],{"class":282},[207,355,357,360,362,364,367,369],{"class":209,"line":356},6,[207,358,359],{"class":288},"    rpOrigin",[207,361,256],{"class":282},[207,363,329],{"class":282},[207,365,366],{"class":217},"http://localhost:3000",[207,368,297],{"class":282},[207,370,308],{"class":282},[207,372,374,377,379,381,384,386],{"class":209,"line":373},7,[207,375,376],{"class":288},"    managementToken",[207,378,256],{"class":282},[207,380,329],{"class":282},[207,382,383],{"class":217},"dev-management-token-change-in-prod",[207,385,297],{"class":282},[207,387,308],{"class":282},[207,389,391,394,396],{"class":209,"line":390},8,[207,392,393],{"class":288},"    grants",[207,395,256],{"class":282},[207,397,318],{"class":282},[207,399,401,404,406],{"class":209,"line":400},9,[207,402,403],{"class":288},"      enablePages",[207,405,256],{"class":282},[207,407,409],{"class":408},"sfNiH"," true\n",[207,411,413],{"class":209,"line":412},10,[207,414,415],{"class":282},"    }\n",[207,417,419],{"class":209,"line":418},11,[207,420,421],{"class":282},"  }\n",[207,423,425,428],{"class":209,"line":424},12,[207,426,427],{"class":282},"}",[207,429,430],{"class":278},")\n",[195,432,434],{"id":433},"start-the-idp","Start the IdP",[164,436,438],{"className":201,"code":437,"language":203,"meta":173,"style":173},"npm run dev -- --port 3000\n",[171,439,440],{"__ignoreMap":173},[207,441,442,444,447,450,453,456],{"class":209,"line":210},[207,443,239],{"class":213},[207,445,446],{"class":217}," run",[207,448,449],{"class":217}," dev",[207,451,452],{"class":217}," --",[207,454,455],{"class":217}," --port",[207,457,459],{"class":458},"sbssI"," 3000\n",[155,461,462],{},"Verify it's running:",[164,464,466],{"className":201,"code":465,"language":203,"meta":173,"style":173},"# JWKS endpoint\ncurl http://localhost:3000/.well-known/jwks.json\n\n# OIDC discovery\ncurl http://localhost:3000/.well-known/openid-configuration\n",[171,467,468,474,482,488,493],{"__ignoreMap":173},[207,469,470],{"class":209,"line":210},[207,471,473],{"class":472},"sHwdD","# JWKS endpoint\n",[207,475,476,479],{"class":209,"line":227},[207,477,478],{"class":213},"curl",[207,480,481],{"class":217}," http://localhost:3000/.well-known/jwks.json\n",[207,483,484],{"class":209,"line":236},[207,485,487],{"emptyLinePlaceholder":486},true,"\n",[207,489,490],{"class":209,"line":321},[207,491,492],{"class":472},"# OIDC discovery\n",[207,494,495,497],{"class":209,"line":339},[207,496,478],{"class":213},[207,498,499],{"class":217}," http://localhost:3000/.well-known/openid-configuration\n",[159,501,503],{"id":502},"part-2-set-up-the-sp","Part 2: Set Up the SP",[155,505,506],{},"In a separate terminal:",[195,508,510],{"id":509},"create-the-sp-project","Create the SP project",[164,512,514],{"className":201,"code":513,"language":203,"meta":173,"style":173},"npx nuxi@latest init my-sp\ncd my-sp\nnpm install @openape/nuxt-auth-sp\n",[171,515,516,527,533],{"__ignoreMap":173},[207,517,518,520,522,524],{"class":209,"line":210},[207,519,214],{"class":213},[207,521,218],{"class":217},[207,523,221],{"class":217},[207,525,526],{"class":217}," my-sp\n",[207,528,529,531],{"class":209,"line":227},[207,530,231],{"class":230},[207,532,526],{"class":217},[207,534,535,537,539],{"class":209,"line":236},[207,536,239],{"class":213},[207,538,242],{"class":217},[207,540,541],{"class":217}," @openape/nuxt-auth-sp\n",[195,543,545],{"id":544},"configure-the-sp","Configure the SP",[164,547,549],{"className":259,"code":548,"language":261,"meta":173,"style":173},"export default defineNuxtConfig({\n  modules: ['@openape/nuxt-auth-sp'],\n  openapeSp: {\n    fallbackIdpUrl: 'http://localhost:3000'\n  }\n})\n",[171,550,551,563,582,591,605,609],{"__ignoreMap":173},[207,552,553,555,557,559,561],{"class":209,"line":210},[207,554,269],{"class":268},[207,556,272],{"class":268},[207,558,275],{"class":230},[207,560,279],{"class":278},[207,562,283],{"class":282},[207,564,565,567,569,571,573,576,578,580],{"class":209,"line":227},[207,566,289],{"class":288},[207,568,256],{"class":282},[207,570,294],{"class":278},[207,572,297],{"class":282},[207,574,575],{"class":217},"@openape/nuxt-auth-sp",[207,577,297],{"class":282},[207,579,305],{"class":278},[207,581,308],{"class":282},[207,583,584,587,589],{"class":209,"line":236},[207,585,586],{"class":288},"  openapeSp",[207,588,256],{"class":282},[207,590,318],{"class":282},[207,592,593,596,598,600,602],{"class":209,"line":321},[207,594,595],{"class":288},"    fallbackIdpUrl",[207,597,256],{"class":282},[207,599,329],{"class":282},[207,601,366],{"class":217},[207,603,604],{"class":282},"'\n",[207,606,607],{"class":209,"line":339},[207,608,421],{"class":282},[207,610,611,613],{"class":209,"line":356},[207,612,427],{"class":282},[207,614,430],{"class":278},[195,616,618],{"id":617},"add-a-login-page","Add a Login Page",[155,620,621,622,256],{},"Create ",[171,623,624],{},"app/pages/index.vue",[164,626,630],{"className":627,"code":628,"language":629,"meta":173,"style":173},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Ctemplate>\n  \u003Cdiv style=\"max-width: 400px; margin: 50px auto;\">\n    \u003Ch1>My App\u003C/h1>\n    \u003Cdiv v-if=\"user\">\n      \u003Cp>Logged in as: \u003Cstrong>{{ user.email }}\u003C/strong>\u003C/p>\n      \u003Cp>Type: {{ user.act }}\u003C/p>\n      \u003Cbutton @click=\"logout()\">Logout\u003C/button>\n    \u003C/div>\n    \u003COpenApeAuth v-else />\n  \u003C/div>\n\u003C/template>\n\n\u003Cscript setup>\nconst { user, logout } = useOpenApeAuth()\n\u003C/script>\n","vue",[171,631,632,643,668,688,708,741,758,788,797,810,819,827,831,844,873],{"__ignoreMap":173},[207,633,634,637,640],{"class":209,"line":210},[207,635,636],{"class":282},"\u003C",[207,638,639],{"class":288},"template",[207,641,642],{"class":282},">\n",[207,644,645,648,651,655,658,661,664,666],{"class":209,"line":227},[207,646,647],{"class":282},"  \u003C",[207,649,650],{"class":288},"div",[207,652,654],{"class":653},"spNyl"," style",[207,656,657],{"class":282},"=",[207,659,660],{"class":282},"\"",[207,662,663],{"class":217},"max-width: 400px; margin: 50px auto;",[207,665,660],{"class":282},[207,667,642],{"class":282},[207,669,670,673,675,678,681,684,686],{"class":209,"line":236},[207,671,672],{"class":282},"    \u003C",[207,674,151],{"class":288},[207,676,677],{"class":282},">",[207,679,680],{"class":278},"My App",[207,682,683],{"class":282},"\u003C/",[207,685,151],{"class":288},[207,687,642],{"class":282},[207,689,690,692,694,697,699,701,704,706],{"class":209,"line":321},[207,691,672],{"class":282},[207,693,650],{"class":288},[207,695,696],{"class":653}," v-if",[207,698,657],{"class":282},[207,700,660],{"class":282},[207,702,703],{"class":217},"user",[207,705,660],{"class":282},[207,707,642],{"class":282},[207,709,710,713,715,717,720,722,725,727,730,732,734,737,739],{"class":209,"line":339},[207,711,712],{"class":282},"      \u003C",[207,714,155],{"class":288},[207,716,677],{"class":282},[207,718,719],{"class":278},"Logged in as: ",[207,721,636],{"class":282},[207,723,724],{"class":288},"strong",[207,726,677],{"class":282},[207,728,729],{"class":278},"{{ user.email }}",[207,731,683],{"class":282},[207,733,724],{"class":288},[207,735,736],{"class":282},">\u003C/",[207,738,155],{"class":288},[207,740,642],{"class":282},[207,742,743,745,747,749,752,754,756],{"class":209,"line":356},[207,744,712],{"class":282},[207,746,155],{"class":288},[207,748,677],{"class":282},[207,750,751],{"class":278},"Type: {{ user.act }}",[207,753,683],{"class":282},[207,755,155],{"class":288},[207,757,642],{"class":282},[207,759,760,762,765,768,770,772,775,777,779,782,784,786],{"class":209,"line":373},[207,761,712],{"class":282},[207,763,764],{"class":288},"button",[207,766,767],{"class":653}," @click",[207,769,657],{"class":282},[207,771,660],{"class":282},[207,773,774],{"class":217},"logout()",[207,776,660],{"class":282},[207,778,677],{"class":282},[207,780,781],{"class":278},"Logout",[207,783,683],{"class":282},[207,785,764],{"class":288},[207,787,642],{"class":282},[207,789,790,793,795],{"class":209,"line":390},[207,791,792],{"class":282},"    \u003C/",[207,794,650],{"class":288},[207,796,642],{"class":282},[207,798,799,801,804,807],{"class":209,"line":400},[207,800,672],{"class":282},[207,802,803],{"class":288},"OpenApeAuth",[207,805,806],{"class":653}," v-else",[207,808,809],{"class":282}," />\n",[207,811,812,815,817],{"class":209,"line":412},[207,813,814],{"class":282},"  \u003C/",[207,816,650],{"class":288},[207,818,642],{"class":282},[207,820,821,823,825],{"class":209,"line":418},[207,822,683],{"class":282},[207,824,639],{"class":288},[207,826,642],{"class":282},[207,828,829],{"class":209,"line":424},[207,830,487],{"emptyLinePlaceholder":486},[207,832,834,836,839,842],{"class":209,"line":833},13,[207,835,636],{"class":282},[207,837,838],{"class":288},"script",[207,840,841],{"class":653}," setup",[207,843,642],{"class":282},[207,845,847,850,853,856,859,862,864,867,870],{"class":209,"line":846},14,[207,848,849],{"class":653},"const",[207,851,852],{"class":282}," {",[207,854,855],{"class":278}," user",[207,857,858],{"class":282},",",[207,860,861],{"class":278}," logout ",[207,863,427],{"class":282},[207,865,866],{"class":282}," =",[207,868,869],{"class":230}," useOpenApeAuth",[207,871,872],{"class":278},"()\n",[207,874,876,878,880],{"class":209,"line":875},15,[207,877,683],{"class":282},[207,879,838],{"class":288},[207,881,642],{"class":282},[195,883,885],{"id":884},"start-the-sp","Start the SP",[164,887,889],{"className":201,"code":888,"language":203,"meta":173,"style":173},"npm run dev -- --port 3001\n",[171,890,891],{"__ignoreMap":173},[207,892,893,895,897,899,901,903],{"class":209,"line":210},[207,894,239],{"class":213},[207,896,446],{"class":217},[207,898,449],{"class":217},[207,900,452],{"class":217},[207,902,455],{"class":217},[207,904,905],{"class":458}," 3001\n",[159,907,909],{"id":908},"part-3-install-the-cli-and-register-a-human-user","Part 3: Install the CLI and Register a Human User",[164,911,913],{"className":201,"code":912,"language":203,"meta":173,"style":173},"npm install -g @openape/grapes\n",[171,914,915],{"__ignoreMap":173},[207,916,917,919,921,924],{"class":209,"line":210},[207,918,239],{"class":213},[207,920,242],{"class":217},[207,922,923],{"class":217}," -g",[207,925,926],{"class":217}," @openape/grapes\n",[195,928,930],{"id":929},"register-and-login","Register and Login",[164,932,934],{"className":201,"code":933,"language":203,"meta":173,"style":173},"grapes login --idp http://localhost:3000\n",[171,935,936],{"__ignoreMap":173},[207,937,938,941,944,947],{"class":209,"line":210},[207,939,940],{"class":213},"grapes",[207,942,943],{"class":217}," login",[207,945,946],{"class":217}," --idp",[207,948,949],{"class":217}," http://localhost:3000\n",[155,951,952],{},"This opens a browser where you register with a Passkey and log in.",[954,955,957],"callout",{"type":956},"info",[155,958,959,960,962],{},"In development on ",[171,961,349],{},", Passkeys use the device's built-in authenticator. On macOS, this uses Touch ID or iCloud Keychain.",[155,964,965],{},"Verify:",[164,967,969],{"className":201,"code":968,"language":203,"meta":173,"style":173},"grapes whoami\n# → alice@localhost (human) via http://localhost:3000\n",[171,970,971,978],{"__ignoreMap":173},[207,972,973,975],{"class":209,"line":210},[207,974,940],{"class":213},[207,976,977],{"class":217}," whoami\n",[207,979,980],{"class":209,"line":227},[207,981,982],{"class":472},"# → alice@localhost (human) via http://localhost:3000\n",[159,984,986],{"id":985},"part-4-human-logs-in-to-the-sp","Part 4: Human Logs In to the SP",[178,988,989,996,1003,1012,1015],{},[181,990,991,992,995],{},"Open ",[171,993,994],{},"http://localhost:3001"," in your browser",[181,997,998,999,1002],{},"Enter ",[171,1000,1001],{},"alice@localhost"," in the login form",[181,1004,1005,1006,1008,1009,1011],{},"Since there's no DNS record for ",[171,1007,349],{},", the SP uses the fallback IdP (",[171,1010,366],{},")",[181,1013,1014],{},"Authenticate with your Passkey",[181,1016,1017,1018],{},"You're redirected back to the SP, logged in as ",[171,1019,1001],{},[155,1021,1022],{},"This is the complete DDISA flow: email → IdP discovery → Passkey auth → JWT → SP session.",[159,1024,1026],{"id":1025},"part-5-enroll-an-agent","Part 5: Enroll an Agent",[195,1028,1030],{"id":1029},"generate-the-agents-key-and-enroll","Generate the agent's key and enroll",[164,1032,1034],{"className":201,"code":1033,"language":203,"meta":173,"style":173},"# Generate a key pair for the agent\nssh-keygen -t ed25519 -f /tmp/agent_key -N \"\"\n\n# Enroll via the admin API (this still requires curl — it's an admin operation)\ncurl -X POST http://localhost:3000/api/agent/enroll \\\n  -H \"Authorization: Bearer dev-management-token-change-in-prod\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\n    \\\"email\\\": \\\"agent+worker@localhost\\\",\n    \\\"name\\\": \\\"test-worker\\\",\n    \\\"publicKey\\\": \\\"$(cat /tmp/agent_key.pub)\\\"\n  }\"\n",[171,1035,1036,1041,1064,1068,1073,1089,1104,1117,1126,1149,1169,1196],{"__ignoreMap":173},[207,1037,1038],{"class":209,"line":210},[207,1039,1040],{"class":472},"# Generate a key pair for the agent\n",[207,1042,1043,1046,1049,1052,1055,1058,1061],{"class":209,"line":227},[207,1044,1045],{"class":213},"ssh-keygen",[207,1047,1048],{"class":217}," -t",[207,1050,1051],{"class":217}," ed25519",[207,1053,1054],{"class":217}," -f",[207,1056,1057],{"class":217}," /tmp/agent_key",[207,1059,1060],{"class":217}," -N",[207,1062,1063],{"class":282}," \"\"\n",[207,1065,1066],{"class":209,"line":236},[207,1067,487],{"emptyLinePlaceholder":486},[207,1069,1070],{"class":209,"line":321},[207,1071,1072],{"class":472},"# Enroll via the admin API (this still requires curl — it's an admin operation)\n",[207,1074,1075,1077,1080,1083,1086],{"class":209,"line":339},[207,1076,478],{"class":213},[207,1078,1079],{"class":217}," -X",[207,1081,1082],{"class":217}," POST",[207,1084,1085],{"class":217}," http://localhost:3000/api/agent/enroll",[207,1087,1088],{"class":278}," \\\n",[207,1090,1091,1094,1097,1100,1102],{"class":209,"line":356},[207,1092,1093],{"class":217},"  -H",[207,1095,1096],{"class":282}," \"",[207,1098,1099],{"class":217},"Authorization: Bearer dev-management-token-change-in-prod",[207,1101,660],{"class":282},[207,1103,1088],{"class":278},[207,1105,1106,1108,1110,1113,1115],{"class":209,"line":373},[207,1107,1093],{"class":217},[207,1109,1096],{"class":282},[207,1111,1112],{"class":217},"Content-Type: application/json",[207,1114,660],{"class":282},[207,1116,1088],{"class":278},[207,1118,1119,1122,1124],{"class":209,"line":390},[207,1120,1121],{"class":217},"  -d",[207,1123,1096],{"class":282},[207,1125,283],{"class":217},[207,1127,1128,1131,1134,1137,1140,1142,1145,1147],{"class":209,"line":400},[207,1129,1130],{"class":278},"    \\\"",[207,1132,1133],{"class":217},"email",[207,1135,1136],{"class":278},"\\\"",[207,1138,1139],{"class":217},": ",[207,1141,1136],{"class":278},[207,1143,1144],{"class":217},"agent+worker@localhost",[207,1146,1136],{"class":278},[207,1148,308],{"class":217},[207,1150,1151,1153,1156,1158,1160,1162,1165,1167],{"class":209,"line":412},[207,1152,1130],{"class":278},[207,1154,1155],{"class":217},"name",[207,1157,1136],{"class":278},[207,1159,1139],{"class":217},[207,1161,1136],{"class":278},[207,1163,1164],{"class":217},"test-worker",[207,1166,1136],{"class":278},[207,1168,308],{"class":217},[207,1170,1171,1173,1176,1178,1180,1182,1185,1188,1191,1193],{"class":209,"line":418},[207,1172,1130],{"class":278},[207,1174,1175],{"class":217},"publicKey",[207,1177,1136],{"class":278},[207,1179,1139],{"class":217},[207,1181,1136],{"class":278},[207,1183,1184],{"class":282},"$(",[207,1186,1187],{"class":213},"cat",[207,1189,1190],{"class":217}," /tmp/agent_key.pub",[207,1192,1011],{"class":282},[207,1194,1195],{"class":278},"\\\"\n",[207,1197,1198,1201],{"class":209,"line":424},[207,1199,1200],{"class":217},"  }",[207,1202,1203],{"class":282},"\"\n",[195,1205,1207],{"id":1206},"login-as-the-agent","Login as the agent",[164,1209,1211],{"className":201,"code":1210,"language":203,"meta":173,"style":173},"grapes login --idp http://localhost:3000 --key /tmp/agent_key --email agent+worker@localhost\ngrapes whoami\n# → agent+worker@localhost (agent) via http://localhost:3000\n",[171,1212,1213,1235,1241],{"__ignoreMap":173},[207,1214,1215,1217,1219,1221,1224,1227,1229,1232],{"class":209,"line":210},[207,1216,940],{"class":213},[207,1218,943],{"class":217},[207,1220,946],{"class":217},[207,1222,1223],{"class":217}," http://localhost:3000",[207,1225,1226],{"class":217}," --key",[207,1228,1057],{"class":217},[207,1230,1231],{"class":217}," --email",[207,1233,1234],{"class":217}," agent+worker@localhost\n",[207,1236,1237,1239],{"class":209,"line":227},[207,1238,940],{"class":213},[207,1240,977],{"class":217},[207,1242,1243],{"class":209,"line":236},[207,1244,1245],{"class":472},"# → agent+worker@localhost (agent) via http://localhost:3000\n",[159,1247,1249],{"id":1248},"part-6-agent-requests-a-grant","Part 6: Agent Requests a Grant",[155,1251,1252],{},"The agent requests permission to perform an action:",[164,1254,1256],{"className":201,"code":1255,"language":203,"meta":173,"style":173},"grapes request \"echo Hello from OpenApe!\" --audience escapes --reason \"Testing the grant flow\" --wait &\n",[171,1257,1258],{"__ignoreMap":173},[207,1259,1260,1262,1265,1267,1270,1272,1275,1278,1281,1283,1286,1288,1291],{"class":209,"line":210},[207,1261,940],{"class":213},[207,1263,1264],{"class":217}," request",[207,1266,1096],{"class":282},[207,1268,1269],{"class":217},"echo Hello from OpenApe!",[207,1271,660],{"class":282},[207,1273,1274],{"class":217}," --audience",[207,1276,1277],{"class":217}," escapes",[207,1279,1280],{"class":217}," --reason",[207,1282,1096],{"class":282},[207,1284,1285],{"class":217},"Testing the grant flow",[207,1287,660],{"class":282},[207,1289,1290],{"class":217}," --wait",[207,1292,1293],{"class":282}," &\n",[155,1295,1296,1297,1300,1301,1304],{},"The ",[171,1298,1299],{},"--wait"," flag blocks until a human approves or denies. Check the IdP's grant dashboard at ",[171,1302,1303],{},"http://localhost:3000/grants"," — you'll see the pending request.",[159,1306,1308],{"id":1307},"part-7-approve-the-grant","Part 7: Approve the Grant",[155,1310,1311,1312,1315],{},"In a ",[724,1313,1314],{},"separate terminal",", login as the human approver and approve:",[164,1317,1319],{"className":201,"code":1318,"language":203,"meta":173,"style":173},"grapes login --idp http://localhost:3000\n\n# See pending grants\ngrapes list --status pending\n\n# Approve\ngrapes approve \u003Cgrant-id>\n",[171,1320,1321,1331,1335,1340,1353,1357,1362],{"__ignoreMap":173},[207,1322,1323,1325,1327,1329],{"class":209,"line":210},[207,1324,940],{"class":213},[207,1326,943],{"class":217},[207,1328,946],{"class":217},[207,1330,949],{"class":217},[207,1332,1333],{"class":209,"line":227},[207,1334,487],{"emptyLinePlaceholder":486},[207,1336,1337],{"class":209,"line":236},[207,1338,1339],{"class":472},"# See pending grants\n",[207,1341,1342,1344,1347,1350],{"class":209,"line":321},[207,1343,940],{"class":213},[207,1345,1346],{"class":217}," list",[207,1348,1349],{"class":217}," --status",[207,1351,1352],{"class":217}," pending\n",[207,1354,1355],{"class":209,"line":339},[207,1356,487],{"emptyLinePlaceholder":486},[207,1358,1359],{"class":209,"line":356},[207,1360,1361],{"class":472},"# Approve\n",[207,1363,1364,1366,1369,1372,1375,1378],{"class":209,"line":373},[207,1365,940],{"class":213},[207,1367,1368],{"class":217}," approve",[207,1370,1371],{"class":282}," \u003C",[207,1373,1374],{"class":217},"grant-i",[207,1376,1377],{"class":278},"d",[207,1379,642],{"class":282},[155,1381,1382,1383,1386],{},"The agent's ",[171,1384,1385],{},"grapes request --wait"," in the other terminal now completes — the grant is approved.",[195,1388,1390],{"id":1389},"use-the-grant-with-escapes","Use the grant with escapes",[164,1392,1394],{"className":201,"code":1393,"language":203,"meta":173,"style":173},"# Get the AuthZ-JWT\nJWT=$(grapes token \u003Cgrant-id>)\n\n# Execute the approved command\nescapes --grant \"$JWT\" -- echo Hello from OpenApe!\n",[171,1395,1396,1401,1423,1427,1432],{"__ignoreMap":173},[207,1397,1398],{"class":209,"line":210},[207,1399,1400],{"class":472},"# Get the AuthZ-JWT\n",[207,1402,1403,1406,1409,1411,1414,1416,1418,1420],{"class":209,"line":227},[207,1404,1405],{"class":278},"JWT",[207,1407,1408],{"class":282},"=$(",[207,1410,940],{"class":213},[207,1412,1413],{"class":217}," token",[207,1415,1371],{"class":282},[207,1417,1374],{"class":217},[207,1419,1377],{"class":278},[207,1421,1422],{"class":282},">)\n",[207,1424,1425],{"class":209,"line":236},[207,1426,487],{"emptyLinePlaceholder":486},[207,1428,1429],{"class":209,"line":321},[207,1430,1431],{"class":472},"# Execute the approved command\n",[207,1433,1434,1436,1439,1441,1444,1446,1448,1451,1454,1457],{"class":209,"line":339},[207,1435,65],{"class":213},[207,1437,1438],{"class":217}," --grant",[207,1440,1096],{"class":282},[207,1442,1443],{"class":278},"$JWT",[207,1445,660],{"class":282},[207,1447,452],{"class":217},[207,1449,1450],{"class":217}," echo",[207,1452,1453],{"class":217}," Hello",[207,1455,1456],{"class":217}," from",[207,1458,1459],{"class":217}," OpenApe!\n",[155,1461,1462,1463,1466],{},"Or use ",[171,1464,1465],{},"grapes run"," for the one-liner version:",[164,1468,1470],{"className":201,"code":1469,"language":203,"meta":173,"style":173},"grapes run escapes \"echo Hello from OpenApe!\" --reason \"Testing\"\n# → Requests grant, waits for approval, executes via escapes\n",[171,1471,1472,1495],{"__ignoreMap":173},[207,1473,1474,1476,1478,1480,1482,1484,1486,1488,1490,1493],{"class":209,"line":210},[207,1475,940],{"class":213},[207,1477,446],{"class":217},[207,1479,1277],{"class":217},[207,1481,1096],{"class":282},[207,1483,1269],{"class":217},[207,1485,660],{"class":282},[207,1487,1280],{"class":217},[207,1489,1096],{"class":282},[207,1491,1492],{"class":217},"Testing",[207,1494,1203],{"class":282},[207,1496,1497],{"class":209,"line":227},[207,1498,1499],{"class":472},"# → Requests grant, waits for approval, executes via escapes\n",[159,1501,1503],{"id":1502},"whats-next","What's Next?",[1505,1506,1507,1514,1519,1524],"ul",{},[181,1508,1509,1513],{},[1510,1511,1512],"a",{"href":25},"Agent Integration Guide"," — Detailed API reference for each endpoint",[181,1515,1516,1518],{},[1510,1517,81],{"href":82}," — Grant types, AuthZ-JWT, and security model",[181,1520,1521,1523],{},[1510,1522,65],{"href":66}," — Local privilege elevation with grants",[181,1525,1526,1528],{},[1510,1527,134],{"href":135}," — Deploy IdP and SP to production",[1530,1531,1532],"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 pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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}",{"title":173,"searchDepth":236,"depth":227,"links":1534},[1535,1536,1541,1547,1550,1551,1555,1556,1559],{"id":161,"depth":227,"text":162},{"id":192,"depth":227,"text":193,"children":1537},[1538,1539,1540],{"id":197,"depth":236,"text":198},{"id":248,"depth":236,"text":249},{"id":433,"depth":236,"text":434},{"id":502,"depth":227,"text":503,"children":1542},[1543,1544,1545,1546],{"id":509,"depth":236,"text":510},{"id":544,"depth":236,"text":545},{"id":617,"depth":236,"text":618},{"id":884,"depth":236,"text":885},{"id":908,"depth":227,"text":909,"children":1548},[1549],{"id":929,"depth":236,"text":930},{"id":985,"depth":227,"text":986},{"id":1025,"depth":227,"text":1026,"children":1552},[1553,1554],{"id":1029,"depth":236,"text":1030},{"id":1206,"depth":236,"text":1207},{"id":1248,"depth":227,"text":1249},{"id":1307,"depth":227,"text":1308,"children":1557},[1558],{"id":1389,"depth":236,"text":1390},{"id":1502,"depth":227,"text":1503},"Set up a complete OpenApe environment with IdP, Service Provider, and Agent from scratch.","md",null,{},{"title":42,"description":1560},"2fc5FV2rKu16Q2zVEu1EwnFQ3ngBmRkRaLkLcph1Ieg",[1567,1569],{"title":38,"path":39,"stem":40,"description":1568,"children":-1},"Set up what your agent can do — from read-only access to full automation.",{"title":46,"path":47,"stem":48,"description":1570,"children":-1},"Let agents act on behalf of users with controlled, auditable delegations.",1774221117377]