[{"data":1,"prerenderedAt":5155},["ShallowReactive",2],{"api-nav":3,"api-guide:\u002Fapi\u002Fpermissions":351,"api-spec:guide:\u002Fapi\u002Fpermissions":5154},[4,28,57,95,115,301,317,331],{"id":5,"title":6,"links":7,"groups":27},"start","Start here",[8,11,15,18,21,24],{"title":9,"to":10},"Overview","\u002Fapi",{"title":12,"to":13,"status":14},"Quickstart","\u002Fapi\u002Fquickstart","available",{"title":16,"to":17,"status":14},"Environments","\u002Fapi\u002Fenvironments",{"title":19,"to":20,"status":14},"Authentication","\u002Fapi\u002Fauthentication",{"title":22,"to":23,"status":14},"Organizations","\u002Fapi\u002Forganizations",{"title":25,"to":26,"status":14},"Permissions","\u002Fapi\u002Fpermissions",[],{"id":29,"title":30,"links":31,"groups":56},"concepts","Concepts",[32,35,38,41,44,47,50,53],{"title":33,"to":34,"status":14},"Requests and responses","\u002Fapi\u002Frequests-and-responses",{"title":36,"to":37,"status":14},"Identifiers","\u002Fapi\u002Fidentifiers",{"title":39,"to":40,"status":14},"Pagination","\u002Fapi\u002Fpagination",{"title":42,"to":43},"Errors","\u002Fapi\u002Ferrors",{"title":45,"to":46,"status":14},"Rate limits","\u002Fapi\u002Frate-limits",{"title":48,"to":49,"status":14},"Retries","\u002Fapi\u002Fretries-and-idempotency",{"title":51,"to":52,"status":14},"Security","\u002Fapi\u002Fsecurity",{"title":54,"to":55,"status":14},"Versioning","\u002Fapi\u002Fversioning",[],{"id":58,"title":59,"links":60,"groups":94},"resources","Guides",[61,64,67,70,73,76,79,82,85,88,91],{"title":62,"to":63,"status":14},"Students","\u002Fapi\u002Fguides\u002Fstudents",{"title":65,"to":66,"status":14},"Bulk registration","\u002Fapi\u002Fguides\u002Fbulk-registration",{"title":68,"to":69,"status":14},"Passwords","\u002Fapi\u002Fguides\u002Fpasswords",{"title":71,"to":72,"status":14},"Supervisors","\u002Fapi\u002Fguides\u002Fsupervisors",{"title":74,"to":75,"status":14},"Reference data","\u002Fapi\u002Fguides\u002Freference-data",{"title":77,"to":78,"status":14},"API account","\u002Fapi\u002Fguides\u002Fapi-account",{"title":80,"to":81,"status":14},"Sign-in links","\u002Fapi\u002Fguides\u002Fsign-in-links",{"title":83,"to":84,"status":14},"Exams","\u002Fapi\u002Fguides\u002Fexams",{"title":86,"to":87,"status":14},"Applications","\u002Fapi\u002Fguides\u002Fapplications",{"title":89,"to":90,"status":14},"Group challenges","\u002Fapi\u002Fguides\u002Fgroup-challenges",{"title":92,"to":93,"status":14},"Certificates and reports","\u002Fapi\u002Fguides\u002Fcertificates-and-reports",[],{"id":96,"title":97,"links":98,"groups":114},"tutorials","Tutorials",[99,102,105,108,111],{"title":100,"to":101,"status":14},"Register and apply","\u002Fapi\u002Ftutorials\u002Fregister-and-apply",{"title":103,"to":104,"status":14},"Send a student to the panel","\u002Fapi\u002Ftutorials\u002Fsend-student-to-panel",{"title":106,"to":107,"status":14},"Change an application","\u002Fapi\u002Ftutorials\u002Fchange-an-application",{"title":109,"to":110,"status":14},"Collect results","\u002Fapi\u002Ftutorials\u002Fcollect-results",{"title":112,"to":113,"status":14},"Token handling","\u002Fapi\u002Ftutorials\u002Ftoken-handling",[],{"id":116,"title":117,"links":118,"groups":125},"reference","Reference",[119,122],{"title":120,"to":121},"All endpoints","\u002Fapi\u002Freference",{"title":123,"to":124},"Sandbox console","\u002Fapi\u002Fconsole",[126,135,145,166,206,212,230,255,271],{"tag":127,"slug":128,"links":129},"Health","health",[130],{"title":131,"to":132,"method":133,"deprecated":134},"Check that the API is up","\u002Fapi\u002Freference\u002Fget-health","GET",false,{"tag":77,"slug":136,"links":137},"api-account",[138,142],{"title":139,"to":140,"method":141,"deprecated":134},"Revoke the token you send, before it expires","\u002Fapi\u002Freference\u002Frevoke-token","POST",{"title":143,"to":144,"method":133,"deprecated":134},"Fetch the API account your token belongs to","\u002Fapi\u002Freference\u002Fget-current-api-account",{"tag":74,"slug":146,"links":147},"reference-data",[148,151,154,157,160,163],{"title":149,"to":150,"method":133,"deprecated":134},"List the countries a student can be registered in","\u002Fapi\u002Freference\u002Flist-countries",{"title":152,"to":153,"method":133,"deprecated":134},"Fetch one country by its id","\u002Fapi\u002Freference\u002Fget-country",{"title":155,"to":156,"method":133,"deprecated":134},"List the grades a student can be registered with","\u002Fapi\u002Freference\u002Flist-grades",{"title":158,"to":159,"method":133,"deprecated":134},"Fetch one grade by its id","\u002Fapi\u002Freference\u002Fget-grade",{"title":161,"to":162,"method":133,"deprecated":134},"List the organizations and their ids","\u002Fapi\u002Freference\u002Flist-organizations",{"title":164,"to":165,"method":133,"deprecated":134},"Fetch one organization by its id","\u002Fapi\u002Freference\u002Fget-organization",{"tag":62,"slug":167,"links":168},"students",[169,172,175,178,181,184,187,191,194,197,200,203],{"title":170,"to":171,"method":133,"deprecated":134},"List your students","\u002Fapi\u002Freference\u002Flist-students",{"title":173,"to":174,"method":141,"deprecated":134},"Register a student","\u002Fapi\u002Freference\u002Fregister-student",{"title":176,"to":177,"method":141,"deprecated":134},"Check a registration without registering the student","\u002Fapi\u002Freference\u002Fcheck-student-registration",{"title":179,"to":180,"method":141,"deprecated":134},"Register many students at once","\u002Fapi\u002Freference\u002Fcreate-student-import",{"title":182,"to":183,"method":133,"deprecated":134},"Follow a batch of students you sent","\u002Fapi\u002Freference\u002Fget-student-import",{"title":185,"to":186,"method":133,"deprecated":134},"Fetch one of your students","\u002Fapi\u002Freference\u002Fget-student",{"title":188,"to":189,"method":190,"deprecated":134},"Update one of your students","\u002Fapi\u002Freference\u002Fupdate-student","PUT",{"title":192,"to":193,"method":190,"deprecated":134},"Set the sign-in password of one of your students","\u002Fapi\u002Freference\u002Fset-student-password",{"title":195,"to":196,"method":133,"deprecated":134},"List your students who can use this organization","\u002Fapi\u002Freference\u002Flist-org-students",{"title":198,"to":199,"method":133,"deprecated":134},"Fetch one of your students, if they can use this organization","\u002Fapi\u002Freference\u002Fget-org-student",{"title":201,"to":202,"method":190,"deprecated":134},"Update one of your students and give them access to this organization","\u002Fapi\u002Freference\u002Fupdate-org-student",{"title":204,"to":205,"method":190,"deprecated":134},"Link one of your students to a supervisor on this organization","\u002Fapi\u002Freference\u002Flink-student-supervisor",{"tag":80,"slug":207,"links":208},"sign-in-links",[209],{"title":210,"to":211,"method":141,"deprecated":134},"Create a single-use sign-in link for one of your students","\u002Fapi\u002Freference\u002Fcreate-signin-link",{"tag":83,"slug":213,"links":214},"exams",[215,218,221,224,227],{"title":216,"to":217,"method":133,"deprecated":134},"List the exams open for applications","\u002Fapi\u002Freference\u002Flist-exams",{"title":219,"to":220,"method":133,"deprecated":134},"List an organization’s exam categories","\u002Fapi\u002Freference\u002Flist-exam-categories",{"title":222,"to":223,"method":133,"deprecated":134},"Fetch one exam category","\u002Fapi\u002Freference\u002Fget-exam-category",{"title":225,"to":226,"method":133,"deprecated":134},"List the exams one of your students can apply to","\u002Fapi\u002Freference\u002Flist-available-exams",{"title":228,"to":229,"method":133,"deprecated":134},"Fetch one exam that is open for applications","\u002Fapi\u002Freference\u002Fget-exam",{"tag":86,"slug":231,"links":232},"applications",[233,236,239,242,245,248,251],{"title":234,"to":235,"method":133,"deprecated":134},"List your students’ applications in this organization","\u002Fapi\u002Freference\u002Flist-applications",{"title":237,"to":238,"method":141,"deprecated":134},"Enter one of your students for an exam","\u002Fapi\u002Freference\u002Fcreate-application",{"title":240,"to":241,"method":133,"deprecated":134},"List your students’ applications for one exam","\u002Fapi\u002Freference\u002Flist-exam-applications",{"title":243,"to":244,"method":133,"deprecated":134},"List one of your students’ applications in this organization","\u002Fapi\u002Freference\u002Flist-student-applications",{"title":246,"to":247,"method":133,"deprecated":134},"Fetch one of your students’ applications","\u002Fapi\u002Freference\u002Fget-application",{"title":249,"to":250,"method":190,"deprecated":134},"Move one of your students’ applications to another exam","\u002Fapi\u002Freference\u002Fmove-application",{"title":252,"to":253,"method":254,"deprecated":134},"Withdraw one of your students from an exam","\u002Fapi\u002Freference\u002Fdelete-application","DELETE",{"tag":256,"slug":257,"links":258},"Documents","documents",[259,262,265,268],{"title":260,"to":261,"method":133,"deprecated":134},"Download a certificate file","\u002Fapi\u002Freference\u002Fdownload-certificate",{"title":263,"to":264,"method":133,"deprecated":134},"List one of your students’ released certificates","\u002Fapi\u002Freference\u002Flist-student-certificates",{"title":266,"to":267,"method":133,"deprecated":134},"Download a result report file","\u002Fapi\u002Freference\u002Fdownload-report",{"title":269,"to":270,"method":133,"deprecated":134},"List one of your students’ released result reports","\u002Fapi\u002Freference\u002Flist-student-reports",{"tag":89,"slug":272,"links":273},"group-challenges",[274,277,280,283,286,289,292,295,298],{"title":275,"to":276,"method":133,"deprecated":134},"List the group challenges an organization runs","\u002Fapi\u002Freference\u002Flist-group-challenges",{"title":278,"to":279,"method":133,"deprecated":134},"Fetch one group challenge","\u002Fapi\u002Freference\u002Fget-group-challenge",{"title":281,"to":282,"method":133,"deprecated":134},"List the groups your students are in for a group challenge","\u002Fapi\u002Freference\u002Flist-group-challenge-groups",{"title":284,"to":285,"method":133,"deprecated":134},"Fetch one group, with its steps and files","\u002Fapi\u002Freference\u002Fget-group-challenge-group",{"title":287,"to":288,"method":133,"deprecated":134},"List what has happened in one group","\u002Fapi\u002Freference\u002Flist-group-challenge-activity",{"title":290,"to":291,"method":141,"deprecated":134},"Send a group’s finished work for one of your students","\u002Fapi\u002Freference\u002Fsubmit-group-challenge-work",{"title":293,"to":294,"method":141,"deprecated":134},"Submit one step of a group for one of your students","\u002Fapi\u002Freference\u002Fsubmit-group-challenge-step",{"title":296,"to":297,"method":133,"deprecated":134},"List your students’ eligibility and groups for a group challenge","\u002Fapi\u002Freference\u002Flist-group-challenge-students",{"title":299,"to":300,"method":133,"deprecated":134},"Fetch one of your students’ eligibility and group for a group challenge","\u002Fapi\u002Freference\u002Fget-group-challenge-student",{"id":302,"title":303,"links":304,"groups":316},"clients","Clients",[305,307,310,313],{"title":9,"to":306,"status":14},"\u002Fapi\u002Fclients",{"title":308,"to":309,"status":14},"Node.js","\u002Fapi\u002Fclients\u002Fnode",{"title":311,"to":312,"status":14},"PHP","\u002Fapi\u002Fclients\u002Fphp",{"title":314,"to":315,"status":14},"Build your own","\u002Fapi\u002Fclients\u002Fbuild-your-own",[],{"id":318,"title":319,"links":320,"groups":330},"agents","AI agents",[321,324,327],{"title":322,"to":323},"AI connections","\u002Fapi\u002Fmcp",{"title":325,"to":326},"What it can do","\u002Fapi\u002Fmcp\u002Ftools",{"title":328,"to":329},"Agent skills","\u002Fapi\u002Fskills",[],{"id":332,"title":333,"links":334,"groups":350},"help","Help",[335,338,341,344,347],{"title":336,"to":337,"status":14},"Glossary","\u002Fapi\u002Fglossary",{"title":339,"to":340,"status":14},"FAQ","\u002Fapi\u002Ffaq",{"title":342,"to":343,"status":14},"Troubleshooting","\u002Fapi\u002Ftroubleshooting",{"title":345,"to":346,"status":14},"Support","\u002Fapi\u002Fsupport",{"title":348,"to":349},"Changelog","\u002Fapi\u002Fchangelog",[],{"id":352,"title":25,"body":353,"description":5146,"extension":5147,"meta":5148,"navTitle":25,"navigation":4293,"operations":5149,"order":5150,"path":26,"section":5,"seo":5151,"status":14,"stem":5152,"__hash__":5153},"apiGuides\u002Fapi\u002Fpermissions.md",{"type":354,"value":355,"toc":5109},"minimark",[356,374,377,382,388,443,713,737,740,744,747,885,888,907,909,915,1125,1127,1130,1188,1191,1231,1237,1239,1264,1268,1276,1318,1321,1324,1399,1404,1408,1419,1618,1621,1674,1677,1686,1765,1776,1780,1789,1860,1880,1891,1954,1964,1968,1974,2031,2045,2049,2052,2138,2142,2148,2152,2155,2181,2185,2188,2250,2256,2260,2266,2391,2394,2603,2616,2622,2626,2712,2715,2719,2725,2807,2824,2828,2831,2869,2873,2923,2934,2938,2943,2947,2956,2990,2994,3072,3074,3222,3226,3379,3383,3498,3500,3616,3618,3776,3779,3875,3877,4073,4077,4083,4567,5054,5060,5064,5074,5102,5105],[357,358,359,360,364,365,369,370,373],"p",{},"A valid token proves who you are. It does not decide what you may do. That is decided by the ",[361,362,363],"strong",{},"roles"," on your account, which an operator sets. Every route except ",[366,367,368],"code",{},"GET \u002Fv1\u002Fhealth"," needs a permission, and a request your roles do not cover answers ",[366,371,372],{},"403 forbidden",".",[357,375,376],{},"This page explains how to read your roles, how the API matches them against a request, which role grants each operation, and which roles to ask for.",[378,379,381],"h2",{"id":380},"where-to-see-your-roles","Where to see your roles",[357,383,384,387],{},[366,385,386],{},"GET \u002Fv1\u002Fapi-account\u002Fvalidate-me"," returns them:",[389,390,395],"pre",{"className":391,"code":392,"language":393,"meta":394,"style":394},"language-bash shiki shiki-themes github-light-high-contrast github-dark-high-contrast","curl -s https:\u002F\u002Fapi.main-team.org\u002Fv1\u002Fapi-account\u002Fvalidate-me \\\n  -H \"Authorization: Bearer $TOKEN\" | jq .roles\n","bash","",[366,396,397,418],{"__ignoreMap":394},[398,399,402,406,410,414],"span",{"class":400,"line":401},"line",1,[398,403,405],{"class":404},"soyes","curl",[398,407,409],{"class":408},"s-5SL"," -s",[398,411,413],{"class":412},"sT6z2"," https:\u002F\u002Fapi.main-team.org\u002Fv1\u002Fapi-account\u002Fvalidate-me",[398,415,417],{"class":416},"sHUrx"," \\\n",[398,419,421,424,427,431,434,437,440],{"class":400,"line":420},2,[398,422,423],{"class":408},"  -H",[398,425,426],{"class":412}," \"Authorization: Bearer ",[398,428,430],{"class":429},"suds8","$TOKEN",[398,432,433],{"class":412},"\"",[398,435,436],{"class":416}," |",[398,438,439],{"class":404}," jq",[398,441,442],{"class":412}," .roles\n",[389,444,448],{"className":445,"code":446,"language":447,"meta":394,"style":394},"language-json shiki shiki-themes github-light-high-contrast github-dark-high-contrast","[\n  { \"effect\": \"allow\", \"action\": \"api\u002F*\", \"target\": \"mto\" },\n  { \"effect\": \"allow\", \"action\": \"*\u002Fread\", \"target\": \"mto\" },\n  { \"effect\": \"allow\", \"action\": \"student\u002F*\", \"target\": \"mto\" },\n  { \"effect\": \"allow\", \"action\": \"*\u002Fread\", \"target\": \"stem\" },\n  { \"effect\": \"allow\", \"action\": \"student\u002Fupdate\", \"target\": \"stem\" },\n  { \"effect\": \"allow\", \"action\": \"application\u002F*\", \"target\": \"stem\" },\n  { \"effect\": \"allow\", \"action\": \"auth\u002Fsignin\", \"target\": \"stem\" },\n  { \"effect\": \"disallow\", \"action\": \"application\u002Fdelete\", \"target\": \"*\" }\n]\n","json",[366,449,450,455,494,524,554,584,614,644,674,707],{"__ignoreMap":394},[398,451,452],{"class":400,"line":401},[398,453,454],{"class":429},"[\n",[398,456,457,460,464,467,470,473,476,478,481,483,486,488,491],{"class":400,"line":420},[398,458,459],{"class":429},"  { ",[398,461,463],{"class":462},"sne4z","\"effect\"",[398,465,466],{"class":429},": ",[398,468,469],{"class":412},"\"allow\"",[398,471,472],{"class":429},", ",[398,474,475],{"class":462},"\"action\"",[398,477,466],{"class":429},[398,479,480],{"class":412},"\"api\u002F*\"",[398,482,472],{"class":429},[398,484,485],{"class":462},"\"target\"",[398,487,466],{"class":429},[398,489,490],{"class":412},"\"mto\"",[398,492,493],{"class":429}," },\n",[398,495,497,499,501,503,505,507,509,511,514,516,518,520,522],{"class":400,"line":496},3,[398,498,459],{"class":429},[398,500,463],{"class":462},[398,502,466],{"class":429},[398,504,469],{"class":412},[398,506,472],{"class":429},[398,508,475],{"class":462},[398,510,466],{"class":429},[398,512,513],{"class":412},"\"*\u002Fread\"",[398,515,472],{"class":429},[398,517,485],{"class":462},[398,519,466],{"class":429},[398,521,490],{"class":412},[398,523,493],{"class":429},[398,525,527,529,531,533,535,537,539,541,544,546,548,550,552],{"class":400,"line":526},4,[398,528,459],{"class":429},[398,530,463],{"class":462},[398,532,466],{"class":429},[398,534,469],{"class":412},[398,536,472],{"class":429},[398,538,475],{"class":462},[398,540,466],{"class":429},[398,542,543],{"class":412},"\"student\u002F*\"",[398,545,472],{"class":429},[398,547,485],{"class":462},[398,549,466],{"class":429},[398,551,490],{"class":412},[398,553,493],{"class":429},[398,555,557,559,561,563,565,567,569,571,573,575,577,579,582],{"class":400,"line":556},5,[398,558,459],{"class":429},[398,560,463],{"class":462},[398,562,466],{"class":429},[398,564,469],{"class":412},[398,566,472],{"class":429},[398,568,475],{"class":462},[398,570,466],{"class":429},[398,572,513],{"class":412},[398,574,472],{"class":429},[398,576,485],{"class":462},[398,578,466],{"class":429},[398,580,581],{"class":412},"\"stem\"",[398,583,493],{"class":429},[398,585,587,589,591,593,595,597,599,601,604,606,608,610,612],{"class":400,"line":586},6,[398,588,459],{"class":429},[398,590,463],{"class":462},[398,592,466],{"class":429},[398,594,469],{"class":412},[398,596,472],{"class":429},[398,598,475],{"class":462},[398,600,466],{"class":429},[398,602,603],{"class":412},"\"student\u002Fupdate\"",[398,605,472],{"class":429},[398,607,485],{"class":462},[398,609,466],{"class":429},[398,611,581],{"class":412},[398,613,493],{"class":429},[398,615,617,619,621,623,625,627,629,631,634,636,638,640,642],{"class":400,"line":616},7,[398,618,459],{"class":429},[398,620,463],{"class":462},[398,622,466],{"class":429},[398,624,469],{"class":412},[398,626,472],{"class":429},[398,628,475],{"class":462},[398,630,466],{"class":429},[398,632,633],{"class":412},"\"application\u002F*\"",[398,635,472],{"class":429},[398,637,485],{"class":462},[398,639,466],{"class":429},[398,641,581],{"class":412},[398,643,493],{"class":429},[398,645,647,649,651,653,655,657,659,661,664,666,668,670,672],{"class":400,"line":646},8,[398,648,459],{"class":429},[398,650,463],{"class":462},[398,652,466],{"class":429},[398,654,469],{"class":412},[398,656,472],{"class":429},[398,658,475],{"class":462},[398,660,466],{"class":429},[398,662,663],{"class":412},"\"auth\u002Fsignin\"",[398,665,472],{"class":429},[398,667,485],{"class":462},[398,669,466],{"class":429},[398,671,581],{"class":412},[398,673,493],{"class":429},[398,675,677,679,681,683,686,688,690,692,695,697,699,701,704],{"class":400,"line":676},9,[398,678,459],{"class":429},[398,680,463],{"class":462},[398,682,466],{"class":429},[398,684,685],{"class":412},"\"disallow\"",[398,687,472],{"class":429},[398,689,475],{"class":462},[398,691,466],{"class":429},[398,693,694],{"class":412},"\"application\u002Fdelete\"",[398,696,472],{"class":429},[398,698,485],{"class":462},[398,700,466],{"class":429},[398,702,703],{"class":412},"\"*\"",[398,705,706],{"class":429}," }\n",[398,708,710],{"class":400,"line":709},10,[398,711,712],{"class":429},"]\n",[357,714,715,716,719,720,723,724,727,728,731,732,736],{},"(",[366,717,718],{},"validate-me"," itself needs ",[366,721,722],{},"api\u002F*"," on ",[366,725,726],{},"mto",". If it answers ",[366,729,730],{},"403",", ask for that role first. See ",[733,734,19],"a",{"href":735},"\u002Fapi\u002Fauthentication#check-a-token-validate-me",".)",[357,738,739],{},"Only an operator can change roles. A change reaches the API within 60 seconds, and it applies to the tokens you already hold, because roles belong to your account, not to the token.",[378,741,743],{"id":742},"anatomy-of-a-role","Anatomy of a role",[357,745,746],{},"A role has four fields:",[748,749,750,769],"table",{},[751,752,753],"thead",{},[754,755,756,760,763,766],"tr",{},[757,758,759],"th",{},"Field",[757,761,762],{},"Values",[757,764,765],{},"Default",[757,767,768],{},"Meaning",[770,771,772,796,828,866],"tbody",{},[754,773,774,780,789,793],{},[775,776,777],"td",{},[366,778,779],{},"effect",[775,781,782,785,786],{},[366,783,784],{},"allow"," or ",[366,787,788],{},"disallow",[775,790,791],{},[366,792,784],{},[775,794,795],{},"Whether the role grants the action or forbids it",[754,797,798,803,816,819],{},[775,799,800],{},[366,801,802],{},"action",[775,804,805,808,809,812,813,815],{},[366,806,807],{},"\u003Cresource>\u002F\u003Coperation>",", with ",[366,810,811],{},"*"," as a wildcard, or ",[366,814,811],{}," alone",[775,817,818],{},"none",[775,820,821,822,785,825],{},"What the role is about, for example ",[366,823,824],{},"student\u002Fread",[366,826,827],{},"application\u002F*",[754,829,830,835,856,860],{},[775,831,832],{},[366,833,834],{},"target",[775,836,837,472,839,472,841,472,844,472,847,472,850,785,853],{},[366,838,811],{},[366,840,726],{},[366,842,843],{},"stem",[366,845,846],{},"hilingua",[366,848,849],{},"neo",[366,851,852],{},"gmath",[366,854,855],{},"coding",[775,857,858],{},[366,859,726],{},[775,861,862,863,865],{},"Which organization the role covers. ",[366,864,811],{}," means every organization and the core record",[754,867,868,873,879,882],{},[775,869,870],{},[366,871,872],{},"authorized",[775,874,875,876],{},"Empty, or your own account ",[366,877,878],{},"_id",[775,880,881],{},"empty",[775,883,884],{},"Whose role it is. Leave it empty",[886,887,779],"h3",{"id":779},[357,889,890,892,893,895,896,898,899,901,902,906],{},[366,891,784],{}," grants, ",[366,894,788],{}," forbids. A ",[366,897,788],{}," that matches a request always wins over any ",[366,900,784],{}," that matches the same request (see ",[733,903,905],{"href":904},"#disallow-wins","Disallow wins",").",[886,908,802],{"id":802},[357,910,911,912,914],{},"An action is ",[366,913,807],{},". The API uses these resources and operations:",[748,916,917,930],{},[751,918,919],{},[754,920,921,924,927],{},[757,922,923],{},"Resource",[757,925,926],{},"Operations routes check",[757,928,929],{},"Covers",[770,931,932,950,965,979,992,1012,1026,1040,1060,1074,1088,1105],{},[754,933,934,939,943],{},[775,935,936],{},[366,937,938],{},"api",[775,940,941],{},[366,942,811],{},[775,944,945,472,947],{},[366,946,718],{},[366,948,949],{},"revoke-token",[754,951,952,957,962],{},[775,953,954],{},[366,955,956],{},"country",[775,958,959],{},[366,960,961],{},"read",[775,963,964],{},"Countries",[754,966,967,972,976],{},[775,968,969],{},[366,970,971],{},"grade",[775,973,974],{},[366,975,961],{},[775,977,978],{},"Grades",[754,980,981,986,990],{},[775,982,983],{},[366,984,985],{},"organization",[775,987,988],{},[366,989,961],{},[775,991,22],{},[754,993,994,999,1009],{},[775,995,996],{},[366,997,998],{},"student",[775,1000,1001,472,1003,472,1006],{},[366,1002,961],{},[366,1004,1005],{},"create",[366,1007,1008],{},"update",[775,1010,1011],{},"Students, organization student views, supervisor links",[754,1013,1014,1019,1023],{},[775,1015,1016],{},[366,1017,1018],{},"exam-category",[775,1020,1021],{},[366,1022,961],{},[775,1024,1025],{},"Exam categories",[754,1027,1028,1033,1037],{},[775,1029,1030],{},[366,1031,1032],{},"exam",[775,1034,1035],{},[366,1036,961],{},[775,1038,1039],{},"Exams and the per-student exam picker",[754,1041,1042,1047,1058],{},[775,1043,1044],{},[366,1045,1046],{},"application",[775,1048,1049,472,1051,472,1053,472,1055],{},[366,1050,961],{},[366,1052,1005],{},[366,1054,1008],{},[366,1056,1057],{},"delete",[775,1059,86],{},[754,1061,1062,1067,1071],{},[775,1063,1064],{},[366,1065,1066],{},"certificate",[775,1068,1069],{},[366,1070,961],{},[775,1072,1073],{},"Certificate lists and downloads",[754,1075,1076,1081,1085],{},[775,1077,1078],{},[366,1079,1080],{},"report",[775,1082,1083],{},[366,1084,961],{},[775,1086,1087],{},"Report lists and downloads",[754,1089,1090,1095,1102],{},[775,1091,1092],{},[366,1093,1094],{},"group-challenge",[775,1096,1097,472,1099],{},[366,1098,961],{},[366,1100,1101],{},"submit",[775,1103,1104],{},"Group challenges, your students in them, their groups; submitting a step or a group's work for one of your students",[754,1106,1107,1112,1117],{},[775,1108,1109],{},[366,1110,1111],{},"auth",[775,1113,1114],{},[366,1115,1116],{},"signin",[775,1118,1119,1120,1124],{},"Sign-in links and student passwords (see ",[733,1121,1123],{"href":1122},"#authsignin-is-its-own-namespace","auth\u002Fsignin",")",[886,1126,834],{"id":834},[357,1128,1129],{},"The target says which organization a role covers. Every request acts on exactly one organization:",[748,1131,1132,1145],{},[751,1133,1134],{},[754,1135,1136,1139,1142],{},[757,1137,1138],{},"The request is",[757,1140,1141],{},"It acts on",[757,1143,1144],{},"A role matches when its target is",[770,1146,1147,1166],{},[754,1148,1149,1155,1160],{},[775,1150,1151,1152],{},"A flat route (no organization id in the path), such as ",[366,1153,1154],{},"\u002Fv1\u002Fstudent",[775,1156,1157,1159],{},[366,1158,726],{},", the core record",[775,1161,1162,785,1164],{},[366,1163,726],{},[366,1165,811],{},[754,1167,1168,1174,1180],{},[775,1169,1170,1171],{},"A per-organization route, ",[366,1172,1173],{},"\u002Fv1\u002F{organizationId}\u002F...",[775,1175,1176,1177,1179],{},"The organization whose ",[366,1178,878],{}," is in the path",[775,1181,1182,1183,1185,1186],{},"That organization's slug (for example ",[366,1184,843],{},") or ",[366,1187,811],{},[357,1189,1190],{},"Consequences worth knowing:",[1192,1193,1194,1210,1218,1225],"ul",{},[1195,1196,1197,1198,1200,1201,1204,1205,785,1207,1209],"li",{},"A role with target ",[366,1199,843],{}," does nothing on flat routes. Registering students (",[366,1202,1203],{},"POST \u002Fv1\u002Fstudent",") needs a role on ",[366,1206,726],{},[366,1208,811],{},", even if all your work is on stem.",[1195,1211,1197,1212,1214,1215,373],{},[366,1213,726],{}," does nothing on ",[366,1216,1217],{},"\u002Fv1\u002F{stem's id}\u002F...",[1195,1219,1197,1220,1222,1223,373],{},[366,1221,811],{}," covers everything, flat routes included. Keep that in mind when you ask for ",[366,1224,811],{},[1195,1226,1227,1228,1230],{},"Because ",[366,1229,726],{}," is the default target, a role saved without a target covers only the flat routes.",[357,1232,1233,1236],{},[733,1234,22],{"href":1235},"\u002Fapi\u002Forganizations#two-kinds-of-routes"," lists which routes are flat.",[886,1238,872],{"id":872},[357,1240,1241,1243,1244,1247,1248,1250,1251,1253,1254,1256,1257,1260,1261,1263],{},[366,1242,872],{}," says whose role it is. ",[361,1245,1246],{},"Leave it empty",": an empty ",[366,1249,872],{}," means \"the account that holds this role\", which is always what you want. Setting it to your own account ",[366,1252,878],{}," means the same thing. A role whose ",[366,1255,872],{}," is ",[361,1258,1259],{},"any other id does nothing at all",", neither as an allow nor as a disallow. If you see a role like that in ",[366,1262,718],{},", it is a mistake to report to the operator.",[378,1265,1267],{"id":1266},"how-a-request-is-checked","How a request is checked",[357,1269,1270,1271,1275],{},"For each request, the API knows the action the route needs (see the ",[733,1272,1274],{"href":1273},"#operation-permission-matrix","matrix",") and the organization it acts on. It then:",[1277,1278,1279,1296,1305,1313],"ol",{},[1195,1280,1281,1284,1285,1287,1288,1256,1290,1292,1293,1295],{},[361,1282,1283],{},"collects the matching roles",": those whose ",[366,1286,802],{}," grants the needed action, whose ",[366,1289,834],{},[366,1291,811],{}," or the request's organization, and whose ",[366,1294,872],{}," is empty or your own id;",[1195,1297,1298,1301,1302,1304],{},[361,1299,1300],{},"refuses"," if any matching role is a ",[366,1303,788],{},";",[1195,1306,1307,1310,1311,1304],{},[361,1308,1309],{},"allows"," if any matching role is an ",[366,1312,784],{},[1195,1314,1315,1317],{},[361,1316,1300],{}," otherwise. Having no matching role at all is a refusal.",[357,1319,1320],{},"The default is to refuse. A route is never open just because you have a token.",[357,1322,1323],{},"A refusal looks like this:",[389,1325,1327],{"className":445,"code":1326,"language":447,"meta":394,"style":394},"{\n  \"error\": {\n    \"code\": \"forbidden\",\n    \"message\": \"Insufficient role permissions\",\n    \"documentation_url\": \"https:\u002F\u002Fhub.main-team.org\u002Fapi\u002Ferrors#forbidden\",\n    \"request_id\": \"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\"\n  }\n}\n",[366,1328,1329,1334,1342,1355,1367,1379,1389,1394],{"__ignoreMap":394},[398,1330,1331],{"class":400,"line":401},[398,1332,1333],{"class":429},"{\n",[398,1335,1336,1339],{"class":400,"line":420},[398,1337,1338],{"class":462},"  \"error\"",[398,1340,1341],{"class":429},": {\n",[398,1343,1344,1347,1349,1352],{"class":400,"line":496},[398,1345,1346],{"class":462},"    \"code\"",[398,1348,466],{"class":429},[398,1350,1351],{"class":412},"\"forbidden\"",[398,1353,1354],{"class":429},",\n",[398,1356,1357,1360,1362,1365],{"class":400,"line":526},[398,1358,1359],{"class":462},"    \"message\"",[398,1361,466],{"class":429},[398,1363,1364],{"class":412},"\"Insufficient role permissions\"",[398,1366,1354],{"class":429},[398,1368,1369,1372,1374,1377],{"class":400,"line":556},[398,1370,1371],{"class":462},"    \"documentation_url\"",[398,1373,466],{"class":429},[398,1375,1376],{"class":412},"\"https:\u002F\u002Fhub.main-team.org\u002Fapi\u002Ferrors#forbidden\"",[398,1378,1354],{"class":429},[398,1380,1381,1384,1386],{"class":400,"line":586},[398,1382,1383],{"class":462},"    \"request_id\"",[398,1385,466],{"class":429},[398,1387,1388],{"class":412},"\"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9\"\n",[398,1390,1391],{"class":400,"line":616},[398,1392,1393],{"class":429},"  }\n",[398,1395,1396],{"class":400,"line":646},[398,1397,1398],{"class":429},"}\n",[357,1400,1401,1403],{},[366,1402,730],{}," means your token is valid and your roles do not cover this request. Signing a new token or retrying does not help. Ask for the role.",[378,1405,1407],{"id":1406},"wildcards","Wildcards",[357,1409,1410,1411,472,1413,1415,1416,1418],{},"In a role's ",[366,1412,802],{},[366,1414,811],{}," stands for \"anything\" in the segment where it appears, and ",[366,1417,811],{}," on its own grants every action.",[748,1420,1421,1434],{},[751,1422,1423],{},[754,1424,1425,1428,1431],{},[757,1426,1427],{},"Role action",[757,1429,1430],{},"Grants",[757,1432,1433],{},"Does not grant",[770,1435,1436,1453,1473,1519,1541,1560,1573,1588,1602],{},[754,1437,1438,1442,1450],{},[775,1439,1440],{},[366,1441,811],{},[775,1443,1444,1445,1447,1448],{},"Every action, including ",[366,1446,722],{}," and ",[366,1449,1123],{},[775,1451,1452],{},"—",[754,1454,1455,1460,1470],{},[775,1456,1457],{},[366,1458,1459],{},"*\u002F*",[775,1461,1462,1463,472,1465,1447,1467],{},"Every action the API checks today, including ",[366,1464,722],{},[366,1466,1123],{},[366,1468,1469],{},"group-challenge\u002Fsubmit",[775,1471,1472],{},"An action with more segments, should one ever be added",[754,1474,1475,1480,1511],{},[775,1476,1477],{},[366,1478,1479],{},"*\u002Fread",[775,1481,1482,472,1485,472,1488,472,1491,472,1493,472,1496,472,1499,472,1502,472,1505,472,1508],{},[366,1483,1484],{},"country\u002Fread",[366,1486,1487],{},"grade\u002Fread",[366,1489,1490],{},"organization\u002Fread",[366,1492,824],{},[366,1494,1495],{},"exam-category\u002Fread",[366,1497,1498],{},"exam\u002Fread",[366,1500,1501],{},"application\u002Fread",[366,1503,1504],{},"certificate\u002Fread",[366,1506,1507],{},"report\u002Fread",[366,1509,1510],{},"group-challenge\u002Fread",[775,1512,1513,1515,1516,1518],{},[366,1514,722],{},", and every write, ",[366,1517,1469],{}," included",[754,1520,1521,1526,1536],{},[775,1522,1523],{},[366,1524,1525],{},"student\u002F*",[775,1527,1528,472,1530,472,1533],{},[366,1529,824],{},[366,1531,1532],{},"student\u002Fcreate",[366,1534,1535],{},"student\u002Fupdate",[775,1537,1538,1540],{},[366,1539,1123],{},", even though it concerns students",[754,1542,1543,1547,1557],{},[775,1544,1545],{},[366,1546,827],{},[775,1548,1549,472,1551,472,1553,472,1555],{},[366,1550,1501],{},[366,1552,1005],{},[366,1554,1008],{},[366,1556,1057],{},[775,1558,1559],{},"Everything else",[754,1561,1562,1567,1571],{},[775,1563,1564],{},[366,1565,1566],{},"auth\u002F*",[775,1568,1569],{},[366,1570,1123],{},[775,1572,1559],{},[754,1574,1575,1580,1586],{},[775,1576,1577],{},[366,1578,1579],{},"group-challenge\u002F*",[775,1581,1582,472,1584],{},[366,1583,1510],{},[366,1585,1469],{},[775,1587,1559],{},[754,1589,1590,1594,1600],{},[775,1591,1592],{},[366,1593,722],{},[775,1595,1596,472,1598],{},[366,1597,718],{},[366,1599,949],{},[775,1601,1559],{},[754,1603,1604,1608,1613],{},[775,1605,1606],{},[366,1607,1498],{},[775,1609,1610,1611],{},"Exactly ",[366,1612,1498],{},[775,1614,1615,1617],{},[366,1616,1495],{}," (a different resource)",[357,1619,1620],{},"Two rules decide every case:",[1277,1622,1623,1635],{},[1195,1624,1625,1628,1629,1631,1632,1634],{},[361,1626,1627],{},"The segment counts must agree."," A two-part pattern such as ",[366,1630,1525],{}," matches two-part actions only. Only ",[366,1633,811],{}," alone matches everything.",[1195,1636,1637,1646,1647,1447,1649,1651,1652,1654,1655,472,1657,785,1659,1661,1662,1664,1665,1667,1668,1670,1671,373],{},[361,1638,1639,1640,1642,1643,1645],{},"The ",[366,1641,938],{}," routes need ",[366,1644,722],{}," literally."," ",[366,1648,718],{},[366,1650,949],{}," ask for ",[366,1653,722],{},", and a role grants that only if its action is ",[366,1656,722],{},[366,1658,1459],{},[366,1660,811],{},". ",[366,1663,1479],{}," does not grant it, because ",[366,1666,961],{}," is not ",[366,1669,811],{},", and neither does ",[366,1672,1673],{},"api\u002Fread",[378,1675,905],{"id":1676},"disallow-wins",[357,1678,1679,1680,1682,1683,1685],{},"A ",[366,1681,788],{}," role that matches a request refuses it, whatever ",[366,1684,784],{}," roles also match. This makes it easy to grant broadly and carve out exceptions:",[748,1687,1688,1698],{},[751,1689,1690],{},[754,1691,1692,1695],{},[757,1693,1694],{},"Roles",[757,1696,1697],{},"Result",[770,1699,1700,1718,1733,1750],{},[754,1701,1702,1715],{},[775,1703,1704,1705,723,1707,1709,1710,723,1713],{},"allow ",[366,1706,827],{},[366,1708,811],{},", disallow ",[366,1711,1712],{},"application\u002Fdelete",[366,1714,811],{},[775,1716,1717],{},"Read, create and move applications everywhere; never delete one",[754,1719,1720,1730],{},[775,1721,1704,1722,723,1724,1709,1726,723,1728],{},[366,1723,811],{},[366,1725,811],{},[366,1727,1123],{},[366,1729,811],{},[775,1731,1732],{},"Everything except sign-in links and passwords",[754,1734,1735,1745],{},[775,1736,1704,1737,723,1739,1709,1741,723,1743],{},[366,1738,1123],{},[366,1740,811],{},[366,1742,1123],{},[366,1744,726],{},[775,1746,1747,1748,1124],{},"Sign-in links on every olympiad; no passwords (the password routes are flat, so they act on ",[366,1749,726],{},[754,1751,1752,1762],{},[775,1753,1704,1754,723,1756,1709,1758,723,1760],{},[366,1755,1479],{},[366,1757,811],{},[366,1759,1479],{},[366,1761,855],{},[775,1763,1764],{},"Read everything except on the coding olympiad",[357,1766,1679,1767,1769,1770,1772,1773,1775],{},[366,1768,788],{}," follows the same matching rules as an ",[366,1771,784],{},". Its target must match the request's organization, and its ",[366,1774,872],{}," must be empty or your own id.",[378,1777,1779],{"id":1778},"authsignin-is-its-own-namespace","auth\u002Fsignin is its own namespace",[357,1781,1782,1784,1785,1788],{},[366,1783,1123],{}," grants the two ways of acting ",[361,1786,1787],{},"as"," a student in their panel:",[748,1790,1791,1804],{},[751,1792,1793],{},[754,1794,1795,1798,1801],{},[757,1796,1797],{},"Operation",[757,1799,1800],{},"Route",[757,1802,1803],{},"The role needs target",[770,1805,1806,1821,1838],{},[754,1807,1808,1811,1816],{},[775,1809,1810],{},"Mint a sign-in link",[775,1812,1813],{},[366,1814,1815],{},"POST \u002Fv1\u002F{organizationId}\u002Fauth\u002Fsignin",[775,1817,1818,1819],{},"That organization's slug, or ",[366,1820,811],{},[754,1822,1823,1826,1831],{},[775,1824,1825],{},"Set a student's password",[775,1827,1828],{},[366,1829,1830],{},"PUT \u002Fv1\u002Fstudent\u002F{studentId}\u002Fpassword",[775,1832,1833,785,1835,1837],{},[366,1834,726],{},[366,1836,811],{}," (a flat route)",[754,1839,1840,1847,1851],{},[775,1841,1842,1843,1846],{},"Send ",[366,1844,1845],{},"password"," when registering",[775,1848,1849],{},[366,1850,1203],{},[775,1852,1853,785,1855,1857,1858],{},[366,1854,726],{},[366,1856,811],{},", in addition to ",[366,1859,1532],{},[357,1861,1862,1863,785,1865,1867,1868,1870,1871,472,1873,1447,1875,1877,1878,373],{},"Both are stronger than reading or updating a student: they let a browser sign in as that student. That is why no ",[366,1864,1525],{},[366,1866,722],{}," role implies them, and why an operator has to grant ",[366,1869,1123],{}," explicitly. ",[366,1872,811],{},[366,1874,1459],{},[366,1876,1566],{}," do include it, so a broad role grants it too, unless you add a ",[366,1879,788],{},[357,1881,1882,1883,1885,1886,723,1888,1890],{},"Registering a student with a ",[366,1884,1845],{}," field but without ",[366,1887,1123],{},[366,1889,726],{}," is refused before anything is written:",[389,1892,1894],{"className":445,"code":1893,"language":447,"meta":394,"style":394},"{\n  \"error\": {\n    \"code\": \"forbidden\",\n    \"message\": \"Setting a student's password needs the auth\u002Fsignin permission on mto, the same grant a sign-in link needs.\",\n    \"documentation_url\": \"https:\u002F\u002Fhub.main-team.org\u002Fapi\u002Ferrors#forbidden\",\n    \"request_id\": \"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d\"\n  }\n}\n",[366,1895,1896,1900,1906,1916,1927,1937,1946,1950],{"__ignoreMap":394},[398,1897,1898],{"class":400,"line":401},[398,1899,1333],{"class":429},[398,1901,1902,1904],{"class":400,"line":420},[398,1903,1338],{"class":462},[398,1905,1341],{"class":429},[398,1907,1908,1910,1912,1914],{"class":400,"line":496},[398,1909,1346],{"class":462},[398,1911,466],{"class":429},[398,1913,1351],{"class":412},[398,1915,1354],{"class":429},[398,1917,1918,1920,1922,1925],{"class":400,"line":526},[398,1919,1359],{"class":462},[398,1921,466],{"class":429},[398,1923,1924],{"class":412},"\"Setting a student's password needs the auth\u002Fsignin permission on mto, the same grant a sign-in link needs.\"",[398,1926,1354],{"class":429},[398,1928,1929,1931,1933,1935],{"class":400,"line":556},[398,1930,1371],{"class":462},[398,1932,466],{"class":429},[398,1934,1376],{"class":412},[398,1936,1354],{"class":429},[398,1938,1939,1941,1943],{"class":400,"line":586},[398,1940,1383],{"class":462},[398,1942,466],{"class":429},[398,1944,1945],{"class":412},"\"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d\"\n",[398,1947,1948],{"class":400,"line":616},[398,1949,1393],{"class":429},[398,1951,1952],{"class":400,"line":646},[398,1953,1398],{"class":429},[357,1955,1956,1957,1959,1960,1447,1962,373],{},"Registering without a password needs only ",[366,1958,1532],{},". See ",[733,1961,68],{"href":69},[733,1963,80],{"href":81},[378,1965,1967],{"id":1966},"other-403-answers","Other 403 answers",[357,1969,1970,1971,1973],{},"A few routes also answer ",[366,1972,372],{}," for a rule of their own, which has nothing to do with roles. Their message names the rule:",[748,1975,1976,1988],{},[751,1977,1978],{},[754,1979,1980,1982,1985],{},[757,1981,1800],{},[757,1983,1984],{},"Message",[757,1986,1987],{},"What to do",[770,1989,1990,2010],{},[754,1991,1992,1996,2001],{},[775,1993,1994],{},[366,1995,1815],{},[775,1997,1998],{},[366,1999,2000],{},"Student is not activated for organization \u003Cslug>.",[775,2002,2003,2004,1959,2007],{},"Give the student access to that organization with ",[366,2005,2006],{},"PUT \u002Fv1\u002F{organizationId}\u002Fstudent\u002F{studentId}",[733,2008,22],{"href":2009},"\u002Fapi\u002Forganizations#which-students-an-organization-route-shows",[754,2011,2012,2019,2024],{},[775,2013,2014,2016,2017],{},[366,2015,1203],{}," with ",[366,2018,1845],{},[775,2020,2021],{},[366,2022,2023],{},"Setting a student's password needs the auth\u002Fsignin permission on mto, the same grant a sign-in link needs.",[775,2025,2026,2027,723,2029],{},"Register without a password, or ask for ",[366,2028,1123],{},[366,2030,726],{},[357,2032,2033,2034,2037,2038,2041,2042,2044],{},"Only ",[366,2035,2036],{},"Insufficient role permissions"," means \"ask for a role\". Base your code on the status and ",[366,2039,2040],{},"error.code",", and show the message to a person. The route-specific ",[366,2043,730],{},"s are decided after the rate limit, so unlike a role refusal they count against it.",[378,2046,2048],{"id":2047},"the-order-of-checks","The order of checks",[357,2050,2051],{},"The permission check has a fixed place in the order of checks, which explains some answers that look surprising:",[1277,2053,2054,2072,2082,2092,2100,2109,2122],{},[1195,2055,2056,2059,2060,2063,2064,2067,2068,2071],{},[361,2057,2058],{},"Reading the body."," A body over 100 kB (",[366,2061,2062],{},"413","), in an encoding the API does not read (",[366,2065,2066],{},"415","), or that is not valid JSON (",[366,2069,2070],{},"400",") is refused first, before the token is looked at.",[1195,2073,2074,2077,2078,2081],{},[361,2075,2076],{},"Token."," A bad token is ",[366,2079,2080],{},"401"," on every route.",[1195,2083,2084,2087,2088,2091],{},[361,2085,2086],{},"Organization id"," (per-organization routes). An unknown id is ",[366,2089,2090],{},"404 Organization not found!",", even if you would have had no permission there.",[1195,2093,2094,1646,2097,2099],{},[361,2095,2096],{},"Permission.",[366,2098,730],{}," if your roles do not cover the request.",[1195,2101,2102,1646,2105,2108],{},[361,2103,2104],{},"Rate limit.",[366,2106,2107],{},"429",". Requests refused at steps 2 to 4 are not counted.",[1195,2110,2111,1646,2114,2116,2117,2119,2120,373],{},[361,2112,2113],{},"Validating the body.",[366,2115,2070],{}," for a missing, badly formatted or unknown field. So a request whose JSON is valid but whose fields are wrong, sent without the permission, answers ",[366,2118,730],{},", not ",[366,2121,2070],{},[1195,2123,2124,2127,2128,2131,2132,2134,2135,2137],{},[361,2125,2126],{},"The route's own rules."," For example, a student who is not yours is treated as missing here, after the permission check (see ",[733,2129,22],{"href":2130},"\u002Fapi\u002Forganizations#a-foreign-record-looks-like-a-missing-one","). Without ",[366,2133,824],{}," you get ",[366,2136,730],{}," for every student id, yours or not.",[378,2139,2141],{"id":2140},"ready-made-role-profiles","Ready-made role profiles",[357,2143,2144,2145,2147],{},"These profiles cover the usual integrations. Copy the one that fits into your request to the operator. In every profile ",[366,2146,872],{}," is left empty.",[886,2149,2151],{"id":2150},"connectivity-only","Connectivity only",[357,2153,2154],{},"For monitoring or a first test.",[748,2156,2157,2167],{},[751,2158,2159],{},[754,2160,2161,2163,2165],{},[757,2162,779],{},[757,2164,802],{},[757,2166,834],{},[770,2168,2169],{},[754,2170,2171,2173,2177],{},[775,2172,784],{},[775,2174,2175],{},[366,2176,722],{},[775,2178,2179],{},[366,2180,726],{},[886,2182,2184],{"id":2183},"reference-data-reader","Reference data reader",[357,2186,2187],{},"Countries, grades and organizations, for building registration forms.",[748,2189,2190,2200],{},[751,2191,2192],{},[754,2193,2194,2196,2198],{},[757,2195,779],{},[757,2197,802],{},[757,2199,834],{},[770,2201,2202,2214,2226,2238],{},[754,2203,2204,2206,2210],{},[775,2205,784],{},[775,2207,2208],{},[366,2209,722],{},[775,2211,2212],{},[366,2213,726],{},[754,2215,2216,2218,2222],{},[775,2217,784],{},[775,2219,2220],{},[366,2221,1484],{},[775,2223,2224],{},[366,2225,726],{},[754,2227,2228,2230,2234],{},[775,2229,784],{},[775,2231,2232],{},[366,2233,1487],{},[775,2235,2236],{},[366,2237,726],{},[754,2239,2240,2242,2246],{},[775,2241,784],{},[775,2243,2244],{},[366,2245,1490],{},[775,2247,2248],{},[366,2249,726],{},[357,2251,715,2252,2255],{},[366,2253,2254],{},"allow *\u002Fread mto"," is shorter. It also grants reading your students on the core record.)",[886,2257,2259],{"id":2258},"enroll-students-on-one-olympiad","Enroll students on one olympiad",[357,2261,2262,2263,2265],{},"Register students, send them to the panel with sign-in links, enter them for exams, move and cancel entries, and collect certificates and reports, all on stem. Replace ",[366,2264,843],{}," with your olympiad's slug.",[748,2267,2268,2281],{},[751,2269,2270],{},[754,2271,2272,2274,2276,2278],{},[757,2273,779],{},[757,2275,802],{},[757,2277,834],{},[757,2279,2280],{},"Why",[770,2282,2283,2301,2316,2331,2346,2361,2376],{},[754,2284,2285,2287,2291,2295],{},[775,2286,784],{},[775,2288,2289],{},[366,2290,722],{},[775,2292,2293],{},[366,2294,726],{},[775,2296,2297,472,2299],{},[366,2298,718],{},[366,2300,949],{},[754,2302,2303,2305,2309,2313],{},[775,2304,784],{},[775,2306,2307],{},[366,2308,1479],{},[775,2310,2311],{},[366,2312,726],{},[775,2314,2315],{},"Countries, grades, organizations, your students on the core record",[754,2317,2318,2320,2324,2328],{},[775,2319,784],{},[775,2321,2322],{},[366,2323,1525],{},[775,2325,2326],{},[366,2327,726],{},[775,2329,2330],{},"Register and update students",[754,2332,2333,2335,2339,2343],{},[775,2334,784],{},[775,2336,2337],{},[366,2338,1479],{},[775,2340,2341],{},[366,2342,843],{},[775,2344,2345],{},"Students, exam categories, exams, the exam picker, applications, certificates and reports on stem",[754,2347,2348,2350,2354,2358],{},[775,2349,784],{},[775,2351,2352],{},[366,2353,1535],{},[775,2355,2356],{},[366,2357,843],{},[775,2359,2360],{},"Give students access to stem; link supervisors",[754,2362,2363,2365,2369,2373],{},[775,2364,784],{},[775,2366,2367],{},[366,2368,827],{},[775,2370,2371],{},[366,2372,843],{},[775,2374,2375],{},"Create, move and delete applications",[754,2377,2378,2380,2384,2388],{},[775,2379,784],{},[775,2381,2382],{},[366,2383,1123],{},[775,2385,2386],{},[366,2387,843],{},[775,2389,2390],{},"Sign-in links into stem",[357,2392,2393],{},"As JSON, for an operator:",[389,2395,2397],{"className":445,"code":2396,"language":447,"meta":394,"style":394},"[\n  { \"effect\": \"allow\", \"action\": \"api\u002F*\", \"target\": \"mto\" },\n  { \"effect\": \"allow\", \"action\": \"*\u002Fread\", \"target\": \"mto\" },\n  { \"effect\": \"allow\", \"action\": \"student\u002F*\", \"target\": \"mto\" },\n  { \"effect\": \"allow\", \"action\": \"*\u002Fread\", \"target\": \"stem\" },\n  { \"effect\": \"allow\", \"action\": \"student\u002Fupdate\", \"target\": \"stem\" },\n  { \"effect\": \"allow\", \"action\": \"application\u002F*\", \"target\": \"stem\" },\n  { \"effect\": \"allow\", \"action\": \"auth\u002Fsignin\", \"target\": \"stem\" }\n]\n",[366,2398,2399,2403,2431,2459,2487,2515,2543,2571,2599],{"__ignoreMap":394},[398,2400,2401],{"class":400,"line":401},[398,2402,454],{"class":429},[398,2404,2405,2407,2409,2411,2413,2415,2417,2419,2421,2423,2425,2427,2429],{"class":400,"line":420},[398,2406,459],{"class":429},[398,2408,463],{"class":462},[398,2410,466],{"class":429},[398,2412,469],{"class":412},[398,2414,472],{"class":429},[398,2416,475],{"class":462},[398,2418,466],{"class":429},[398,2420,480],{"class":412},[398,2422,472],{"class":429},[398,2424,485],{"class":462},[398,2426,466],{"class":429},[398,2428,490],{"class":412},[398,2430,493],{"class":429},[398,2432,2433,2435,2437,2439,2441,2443,2445,2447,2449,2451,2453,2455,2457],{"class":400,"line":496},[398,2434,459],{"class":429},[398,2436,463],{"class":462},[398,2438,466],{"class":429},[398,2440,469],{"class":412},[398,2442,472],{"class":429},[398,2444,475],{"class":462},[398,2446,466],{"class":429},[398,2448,513],{"class":412},[398,2450,472],{"class":429},[398,2452,485],{"class":462},[398,2454,466],{"class":429},[398,2456,490],{"class":412},[398,2458,493],{"class":429},[398,2460,2461,2463,2465,2467,2469,2471,2473,2475,2477,2479,2481,2483,2485],{"class":400,"line":526},[398,2462,459],{"class":429},[398,2464,463],{"class":462},[398,2466,466],{"class":429},[398,2468,469],{"class":412},[398,2470,472],{"class":429},[398,2472,475],{"class":462},[398,2474,466],{"class":429},[398,2476,543],{"class":412},[398,2478,472],{"class":429},[398,2480,485],{"class":462},[398,2482,466],{"class":429},[398,2484,490],{"class":412},[398,2486,493],{"class":429},[398,2488,2489,2491,2493,2495,2497,2499,2501,2503,2505,2507,2509,2511,2513],{"class":400,"line":556},[398,2490,459],{"class":429},[398,2492,463],{"class":462},[398,2494,466],{"class":429},[398,2496,469],{"class":412},[398,2498,472],{"class":429},[398,2500,475],{"class":462},[398,2502,466],{"class":429},[398,2504,513],{"class":412},[398,2506,472],{"class":429},[398,2508,485],{"class":462},[398,2510,466],{"class":429},[398,2512,581],{"class":412},[398,2514,493],{"class":429},[398,2516,2517,2519,2521,2523,2525,2527,2529,2531,2533,2535,2537,2539,2541],{"class":400,"line":586},[398,2518,459],{"class":429},[398,2520,463],{"class":462},[398,2522,466],{"class":429},[398,2524,469],{"class":412},[398,2526,472],{"class":429},[398,2528,475],{"class":462},[398,2530,466],{"class":429},[398,2532,603],{"class":412},[398,2534,472],{"class":429},[398,2536,485],{"class":462},[398,2538,466],{"class":429},[398,2540,581],{"class":412},[398,2542,493],{"class":429},[398,2544,2545,2547,2549,2551,2553,2555,2557,2559,2561,2563,2565,2567,2569],{"class":400,"line":616},[398,2546,459],{"class":429},[398,2548,463],{"class":462},[398,2550,466],{"class":429},[398,2552,469],{"class":412},[398,2554,472],{"class":429},[398,2556,475],{"class":462},[398,2558,466],{"class":429},[398,2560,633],{"class":412},[398,2562,472],{"class":429},[398,2564,485],{"class":462},[398,2566,466],{"class":429},[398,2568,581],{"class":412},[398,2570,493],{"class":429},[398,2572,2573,2575,2577,2579,2581,2583,2585,2587,2589,2591,2593,2595,2597],{"class":400,"line":646},[398,2574,459],{"class":429},[398,2576,463],{"class":462},[398,2578,466],{"class":429},[398,2580,469],{"class":412},[398,2582,472],{"class":429},[398,2584,475],{"class":462},[398,2586,466],{"class":429},[398,2588,663],{"class":412},[398,2590,472],{"class":429},[398,2592,485],{"class":462},[398,2594,466],{"class":429},[398,2596,581],{"class":412},[398,2598,706],{"class":429},[398,2600,2601],{"class":400,"line":676},[398,2602,712],{"class":429},[357,2604,2605,2608,2609,723,2611,2613,2614,373],{},[361,2606,2607],{},"Adding passwords."," If you also set students' passwords, add allow ",[366,2610,1123],{},[366,2612,726],{},". Prefer sign-in links where you can; see ",[733,2615,68],{"href":69},[357,2617,2618,2621],{},[361,2619,2620],{},"Adding an olympiad."," Repeat the four stem rows with the other slug.",[886,2623,2625],{"id":2624},"enroll-students-on-every-olympiad-without-passwords","Enroll students on every olympiad, without passwords",[748,2627,2628,2638],{},[751,2629,2630],{},[754,2631,2632,2634,2636],{},[757,2633,779],{},[757,2635,802],{},[757,2637,834],{},[770,2639,2640,2652,2664,2676,2688,2700],{},[754,2641,2642,2644,2648],{},[775,2643,784],{},[775,2645,2646],{},[366,2647,722],{},[775,2649,2650],{},[366,2651,811],{},[754,2653,2654,2656,2660],{},[775,2655,784],{},[775,2657,2658],{},[366,2659,1479],{},[775,2661,2662],{},[366,2663,811],{},[754,2665,2666,2668,2672],{},[775,2667,784],{},[775,2669,2670],{},[366,2671,1525],{},[775,2673,2674],{},[366,2675,811],{},[754,2677,2678,2680,2684],{},[775,2679,784],{},[775,2681,2682],{},[366,2683,827],{},[775,2685,2686],{},[366,2687,811],{},[754,2689,2690,2692,2696],{},[775,2691,784],{},[775,2693,2694],{},[366,2695,1123],{},[775,2697,2698],{},[366,2699,811],{},[754,2701,2702,2704,2708],{},[775,2703,788],{},[775,2705,2706],{},[366,2707,1123],{},[775,2709,2710],{},[366,2711,726],{},[357,2713,2714],{},"The last row keeps the password routes closed while sign-in links work everywhere.",[886,2716,2718],{"id":2717},"follow-group-challenges","Follow group challenges",[357,2720,2721,2722,2724],{},"Read where your students stand in an organization's group challenges, and submit their steps and their group's work. Replace ",[366,2723,843],{}," with your olympiad's slug. Group challenges answer only on organizations where they are switched on.",[748,2726,2727,2739],{},[751,2728,2729],{},[754,2730,2731,2733,2735,2737],{},[757,2732,779],{},[757,2734,802],{},[757,2736,834],{},[757,2738,2280],{},[770,2740,2741,2759,2774,2789],{},[754,2742,2743,2745,2749,2753],{},[775,2744,784],{},[775,2746,2747],{},[366,2748,722],{},[775,2750,2751],{},[366,2752,726],{},[775,2754,2755,472,2757],{},[366,2756,718],{},[366,2758,949],{},[754,2760,2761,2763,2767,2771],{},[775,2762,784],{},[775,2764,2765],{},[366,2766,1510],{},[775,2768,2769],{},[366,2770,843],{},[775,2772,2773],{},"The challenges, your students in them, their groups, steps, files and history",[754,2775,2776,2778,2782,2786],{},[775,2777,784],{},[775,2779,2780],{},[366,2781,1469],{},[775,2783,2784],{},[366,2785,843],{},[775,2787,2788],{},"Submit a step, or send the work, for one of your students",[754,2790,2791,2793,2797,2801],{},[775,2792,784],{},[775,2794,2795],{},[366,2796,1123],{},[775,2798,2799],{},[366,2800,843],{},[775,2802,2803,2804,1124],{},"Sign-in links that open a challenge's page (",[366,2805,2806],{},"panelPath",[357,2808,2809,2810,2812,2813,2815,2816,2818,2819,1447,2821,2823],{},"Leave out the ",[366,2811,1469],{}," row to follow without acting. ",[366,2814,1479],{}," already includes ",[366,2817,1510],{},"; ",[366,2820,1459],{},[366,2822,811],{}," include both.",[886,2825,2827],{"id":2826},"results-collector-read-only","Results collector (read-only)",[357,2829,2830],{},"A nightly job that reads students, applications, certificates and reports, and changes nothing.",[748,2832,2833,2843],{},[751,2834,2835],{},[754,2836,2837,2839,2841],{},[757,2838,779],{},[757,2840,802],{},[757,2842,834],{},[770,2844,2845,2857],{},[754,2846,2847,2849,2853],{},[775,2848,784],{},[775,2850,2851],{},[366,2852,722],{},[775,2854,2855],{},[366,2856,726],{},[754,2858,2859,2861,2865],{},[775,2860,784],{},[775,2862,2863],{},[366,2864,1479],{},[775,2866,2867],{},[366,2868,811],{},[886,2870,2872],{"id":2871},"everything-with-guard-rails","Everything, with guard rails",[748,2874,2875,2885],{},[751,2876,2877],{},[754,2878,2879,2881,2883],{},[757,2880,779],{},[757,2882,802],{},[757,2884,834],{},[770,2886,2887,2899,2911],{},[754,2888,2889,2891,2895],{},[775,2890,784],{},[775,2892,2893],{},[366,2894,811],{},[775,2896,2897],{},[366,2898,811],{},[754,2900,2901,2903,2907],{},[775,2902,788],{},[775,2904,2905],{},[366,2906,1712],{},[775,2908,2909],{},[366,2910,811],{},[754,2912,2913,2915,2919],{},[775,2914,788],{},[775,2916,2917],{},[366,2918,1123],{},[775,2920,2921],{},[366,2922,726],{},[357,2924,2925,2927,2928,2930,2931,2933],{},[366,2926,811],{}," grants every action, ",[366,2929,1123],{}," included. Drop the ",[366,2932,788],{}," rows only if you really need deletes or passwords.",[886,2935,2937],{"id":2936},"least-privilege","Least privilege",[357,2939,2940,2941,373],{},"Ask for the smallest profile that does the job. A leaked secret can do exactly what your roles allow, no more. A read-only job with read-only roles cannot change anything, whatever happens to its credentials. See ",[733,2942,51],{"href":52},[378,2944,2946],{"id":2945},"operation-permission-matrix","Operation permission matrix",[357,2948,2949,2950,2953,2954,373],{},"Every operation, the action it needs, and the role targets that grant it. Paths use ",[366,2951,2952],{},"{organizationId}"," for the organization ",[366,2955,878],{},[357,2957,2958,2959,2962,2963,2965,2966,2965,2968,2971,2972,2974,2975,2971,2978,2980,2981,2983,2984,472,2986,1447,2988,373],{},"On top of the exact action, ",[361,2960,2961],{},"every"," action below is also granted by ",[366,2964,811],{},", by ",[366,2967,1459],{},[366,2969,2970],{},"\u003Cresource>\u002F*"," (for example ",[366,2973,1525],{},") and by ",[366,2976,2977],{},"*\u002F\u003Coperation>",[366,2979,1479],{},"), with one exception: ",[366,2982,722],{}," is granted only by ",[366,2985,722],{},[366,2987,1459],{},[366,2989,811],{},[886,2991,2993],{"id":2992},"account-and-health","Account and health",[748,2995,2996,3011],{},[751,2997,2998],{},[754,2999,3000,3002,3005,3008],{},[757,3001,1797],{},[757,3003,3004],{},"Request",[757,3006,3007],{},"Action",[757,3009,3010],{},"Role target",[770,3012,3013,3029,3050],{},[754,3014,3015,3020,3024,3027],{},[775,3016,3017],{},[733,3018,3019],{"href":132},"getHealth",[775,3021,3022],{},[366,3023,368],{},[775,3025,3026],{},"none (public, no token)",[775,3028,1452],{},[754,3030,3031,3036,3040,3044],{},[775,3032,3033],{},[733,3034,3035],{"href":144},"getCurrentApiAccount",[775,3037,3038],{},[366,3039,386],{},[775,3041,3042],{},[366,3043,722],{},[775,3045,3046,785,3048],{},[366,3047,726],{},[366,3049,811],{},[754,3051,3052,3057,3062,3066],{},[775,3053,3054],{},[733,3055,3056],{"href":140},"revokeToken",[775,3058,3059],{},[366,3060,3061],{},"POST \u002Fv1\u002Fapi-account\u002Frevoke-token",[775,3063,3064],{},[366,3065,722],{},[775,3067,3068,785,3070],{},[366,3069,726],{},[366,3071,811],{},[886,3073,74],{"id":146},[748,3075,3076,3088],{},[751,3077,3078],{},[754,3079,3080,3082,3084,3086],{},[757,3081,1797],{},[757,3083,3004],{},[757,3085,3007],{},[757,3087,3010],{},[770,3089,3090,3112,3134,3156,3178,3200],{},[754,3091,3092,3097,3102,3106],{},[775,3093,3094],{},[733,3095,3096],{"href":150},"listCountries",[775,3098,3099],{},[366,3100,3101],{},"GET \u002Fv1\u002Fcountry",[775,3103,3104],{},[366,3105,1484],{},[775,3107,3108,785,3110],{},[366,3109,726],{},[366,3111,811],{},[754,3113,3114,3119,3124,3128],{},[775,3115,3116],{},[733,3117,3118],{"href":153},"getCountry",[775,3120,3121],{},[366,3122,3123],{},"GET \u002Fv1\u002Fcountry\u002F{id}",[775,3125,3126],{},[366,3127,1484],{},[775,3129,3130,785,3132],{},[366,3131,726],{},[366,3133,811],{},[754,3135,3136,3141,3146,3150],{},[775,3137,3138],{},[733,3139,3140],{"href":156},"listGrades",[775,3142,3143],{},[366,3144,3145],{},"GET \u002Fv1\u002Fgrade",[775,3147,3148],{},[366,3149,1487],{},[775,3151,3152,785,3154],{},[366,3153,726],{},[366,3155,811],{},[754,3157,3158,3163,3168,3172],{},[775,3159,3160],{},[733,3161,3162],{"href":159},"getGrade",[775,3164,3165],{},[366,3166,3167],{},"GET \u002Fv1\u002Fgrade\u002F{id}",[775,3169,3170],{},[366,3171,1487],{},[775,3173,3174,785,3176],{},[366,3175,726],{},[366,3177,811],{},[754,3179,3180,3185,3190,3194],{},[775,3181,3182],{},[733,3183,3184],{"href":162},"listOrganizations",[775,3186,3187],{},[366,3188,3189],{},"GET \u002Fv1\u002Forganization",[775,3191,3192],{},[366,3193,1490],{},[775,3195,3196,785,3198],{},[366,3197,726],{},[366,3199,811],{},[754,3201,3202,3207,3212,3216],{},[775,3203,3204],{},[733,3205,3206],{"href":165},"getOrganization",[775,3208,3209],{},[366,3210,3211],{},"GET \u002Fv1\u002Forganization\u002F{id}",[775,3213,3214],{},[366,3215,1490],{},[775,3217,3218,785,3220],{},[366,3219,726],{},[366,3221,811],{},[886,3223,3225],{"id":3224},"students-on-the-core-record","Students on the core record",[748,3227,3228,3240],{},[751,3229,3230],{},[754,3231,3232,3234,3236,3238],{},[757,3233,1797],{},[757,3235,3004],{},[757,3237,3007],{},[757,3239,3010],{},[770,3241,3242,3264,3286,3314,3336,3358],{},[754,3243,3244,3249,3254,3258],{},[775,3245,3246],{},[733,3247,3248],{"href":171},"listStudents",[775,3250,3251],{},[366,3252,3253],{},"GET \u002Fv1\u002Fstudent",[775,3255,3256],{},[366,3257,824],{},[775,3259,3260,785,3262],{},[366,3261,726],{},[366,3263,811],{},[754,3265,3266,3271,3276,3280],{},[775,3267,3268],{},[733,3269,3270],{"href":186},"getStudent",[775,3272,3273],{},[366,3274,3275],{},"GET \u002Fv1\u002Fstudent\u002F{studentId}",[775,3277,3278],{},[366,3279,824],{},[775,3281,3282,785,3284],{},[366,3283,726],{},[366,3285,811],{},[754,3287,3288,3293,3297,3307],{},[775,3289,3290],{},[733,3291,3292],{"href":174},"registerStudent",[775,3294,3295],{},[366,3296,1203],{},[775,3298,3299,3301,3302,3304,3305],{},[366,3300,1532],{},"; with a ",[366,3303,1845],{}," in the body, also ",[366,3306,1123],{},[775,3308,3309,785,3311,3313],{},[366,3310,726],{},[366,3312,811],{}," (both)",[754,3315,3316,3321,3326,3330],{},[775,3317,3318],{},[733,3319,3320],{"href":177},"checkStudentRegistration",[775,3322,3323],{},[366,3324,3325],{},"POST \u002Fv1\u002Fstudent\u002Fcheck",[775,3327,3328],{},[366,3329,1532],{},[775,3331,3332,785,3334],{},[366,3333,726],{},[366,3335,811],{},[754,3337,3338,3343,3348,3352],{},[775,3339,3340],{},[733,3341,3342],{"href":189},"updateStudent",[775,3344,3345],{},[366,3346,3347],{},"PUT \u002Fv1\u002Fstudent\u002F{studentId}",[775,3349,3350],{},[366,3351,1535],{},[775,3353,3354,785,3356],{},[366,3355,726],{},[366,3357,811],{},[754,3359,3360,3365,3369,3373],{},[775,3361,3362],{},[733,3363,3364],{"href":193},"setStudentPassword",[775,3366,3367],{},[366,3368,1830],{},[775,3370,3371],{},[366,3372,1123],{},[775,3374,3375,785,3377],{},[366,3376,726],{},[366,3378,811],{},[886,3380,3382],{"id":3381},"students-in-an-organization","Students in an organization",[748,3384,3385,3397],{},[751,3386,3387],{},[754,3388,3389,3391,3393,3395],{},[757,3390,1797],{},[757,3392,3004],{},[757,3394,3007],{},[757,3396,3010],{},[770,3398,3399,3420,3440,3459,3479],{},[754,3400,3401,3406,3411,3415],{},[775,3402,3403],{},[733,3404,3405],{"href":196},"listOrgStudents",[775,3407,3408],{},[366,3409,3410],{},"GET \u002Fv1\u002F{organizationId}\u002Fstudent",[775,3412,3413],{},[366,3414,824],{},[775,3416,3417,3418],{},"the organization's slug or ",[366,3419,811],{},[754,3421,3422,3427,3432,3436],{},[775,3423,3424],{},[733,3425,3426],{"href":199},"getOrgStudent",[775,3428,3429],{},[366,3430,3431],{},"GET \u002Fv1\u002F{organizationId}\u002Fstudent\u002F{studentId}",[775,3433,3434],{},[366,3435,824],{},[775,3437,3417,3438],{},[366,3439,811],{},[754,3441,3442,3447,3451,3455],{},[775,3443,3444],{},[733,3445,3446],{"href":202},"updateOrgStudent",[775,3448,3449],{},[366,3450,2006],{},[775,3452,3453],{},[366,3454,1535],{},[775,3456,3417,3457],{},[366,3458,811],{},[754,3460,3461,3466,3471,3475],{},[775,3462,3463],{},[733,3464,3465],{"href":205},"linkStudentSupervisor",[775,3467,3468],{},[366,3469,3470],{},"PUT \u002Fv1\u002F{organizationId}\u002Fstudent\u002F{studentId}\u002Fsupervisor",[775,3472,3473],{},[366,3474,1535],{},[775,3476,3417,3477],{},[366,3478,811],{},[754,3480,3481,3486,3490,3494],{},[775,3482,3483],{},[733,3484,3485],{"href":211},"createSigninLink",[775,3487,3488],{},[366,3489,1815],{},[775,3491,3492],{},[366,3493,1123],{},[775,3495,3417,3496],{},[366,3497,811],{},[886,3499,83],{"id":213},[748,3501,3502,3514],{},[751,3503,3504],{},[754,3505,3506,3508,3510,3512],{},[757,3507,1797],{},[757,3509,3004],{},[757,3511,3007],{},[757,3513,3010],{},[770,3515,3516,3536,3556,3576,3596],{},[754,3517,3518,3523,3528,3532],{},[775,3519,3520],{},[733,3521,3522],{"href":220},"listExamCategories",[775,3524,3525],{},[366,3526,3527],{},"GET \u002Fv1\u002F{organizationId}\u002Fexam-category",[775,3529,3530],{},[366,3531,1495],{},[775,3533,3417,3534],{},[366,3535,811],{},[754,3537,3538,3543,3548,3552],{},[775,3539,3540],{},[733,3541,3542],{"href":223},"getExamCategory",[775,3544,3545],{},[366,3546,3547],{},"GET \u002Fv1\u002F{organizationId}\u002Fexam-category\u002F{categoryId}",[775,3549,3550],{},[366,3551,1495],{},[775,3553,3417,3554],{},[366,3555,811],{},[754,3557,3558,3563,3568,3572],{},[775,3559,3560],{},[733,3561,3562],{"href":217},"listExams",[775,3564,3565],{},[366,3566,3567],{},"GET \u002Fv1\u002F{organizationId}\u002Fexam",[775,3569,3570],{},[366,3571,1498],{},[775,3573,3417,3574],{},[366,3575,811],{},[754,3577,3578,3583,3588,3592],{},[775,3579,3580],{},[733,3581,3582],{"href":226},"listAvailableExams",[775,3584,3585],{},[366,3586,3587],{},"GET \u002Fv1\u002F{organizationId}\u002Fexam\u002Favailable\u002F{studentId}",[775,3589,3590],{},[366,3591,1498],{},[775,3593,3417,3594],{},[366,3595,811],{},[754,3597,3598,3603,3608,3612],{},[775,3599,3600],{},[733,3601,3602],{"href":229},"getExam",[775,3604,3605],{},[366,3606,3607],{},"GET \u002Fv1\u002F{organizationId}\u002Fexam\u002F{examId}",[775,3609,3610],{},[366,3611,1498],{},[775,3613,3417,3614],{},[366,3615,811],{},[886,3617,86],{"id":231},[748,3619,3620,3632],{},[751,3621,3622],{},[754,3623,3624,3626,3628,3630],{},[757,3625,1797],{},[757,3627,3004],{},[757,3629,3007],{},[757,3631,3010],{},[770,3633,3634,3654,3674,3694,3714,3735,3756],{},[754,3635,3636,3641,3646,3650],{},[775,3637,3638],{},[733,3639,3640],{"href":235},"listApplications",[775,3642,3643],{},[366,3644,3645],{},"GET \u002Fv1\u002F{organizationId}\u002Fapplication",[775,3647,3648],{},[366,3649,1501],{},[775,3651,3417,3652],{},[366,3653,811],{},[754,3655,3656,3661,3666,3670],{},[775,3657,3658],{},[733,3659,3660],{"href":241},"listExamApplications",[775,3662,3663],{},[366,3664,3665],{},"GET \u002Fv1\u002F{organizationId}\u002Fapplication\u002Fexam-applications\u002F{examId}",[775,3667,3668],{},[366,3669,1501],{},[775,3671,3417,3672],{},[366,3673,811],{},[754,3675,3676,3681,3686,3690],{},[775,3677,3678],{},[733,3679,3680],{"href":244},"listStudentApplications",[775,3682,3683],{},[366,3684,3685],{},"GET \u002Fv1\u002F{organizationId}\u002Fapplication\u002Fstudent-applications\u002F{studentId}",[775,3687,3688],{},[366,3689,1501],{},[775,3691,3417,3692],{},[366,3693,811],{},[754,3695,3696,3701,3706,3710],{},[775,3697,3698],{},[733,3699,3700],{"href":247},"getApplication",[775,3702,3703],{},[366,3704,3705],{},"GET \u002Fv1\u002F{organizationId}\u002Fapplication\u002F{applicationId}",[775,3707,3708],{},[366,3709,1501],{},[775,3711,3417,3712],{},[366,3713,811],{},[754,3715,3716,3721,3726,3731],{},[775,3717,3718],{},[733,3719,3720],{"href":238},"createApplication",[775,3722,3723],{},[366,3724,3725],{},"POST \u002Fv1\u002F{organizationId}\u002Fapplication",[775,3727,3728],{},[366,3729,3730],{},"application\u002Fcreate",[775,3732,3417,3733],{},[366,3734,811],{},[754,3736,3737,3742,3747,3752],{},[775,3738,3739],{},[733,3740,3741],{"href":250},"moveApplication",[775,3743,3744],{},[366,3745,3746],{},"PUT \u002Fv1\u002F{organizationId}\u002Fapplication\u002F{applicationId}",[775,3748,3749],{},[366,3750,3751],{},"application\u002Fupdate",[775,3753,3417,3754],{},[366,3755,811],{},[754,3757,3758,3763,3768,3772],{},[775,3759,3760],{},[733,3761,3762],{"href":253},"deleteApplication",[775,3764,3765],{},[366,3766,3767],{},"DELETE \u002Fv1\u002F{organizationId}\u002Fapplication\u002F{applicationId}",[775,3769,3770],{},[366,3771,1712],{},[775,3773,3417,3774],{},[366,3775,811],{},[886,3777,92],{"id":3778},"certificates-and-reports",[748,3780,3781,3793],{},[751,3782,3783],{},[754,3784,3785,3787,3789,3791],{},[757,3786,1797],{},[757,3788,3004],{},[757,3790,3007],{},[757,3792,3010],{},[770,3794,3795,3815,3835,3855],{},[754,3796,3797,3802,3807,3811],{},[775,3798,3799],{},[733,3800,3801],{"href":264},"listStudentCertificates",[775,3803,3804],{},[366,3805,3806],{},"GET \u002Fv1\u002F{organizationId}\u002Fcertificate\u002F{userId}",[775,3808,3809],{},[366,3810,1504],{},[775,3812,3417,3813],{},[366,3814,811],{},[754,3816,3817,3822,3827,3831],{},[775,3818,3819],{},[733,3820,3821],{"href":261},"downloadCertificate",[775,3823,3824],{},[366,3825,3826],{},"GET \u002Fv1\u002F{organizationId}\u002Fcertificate\u002Fdownload\u002F{certificateId}",[775,3828,3829],{},[366,3830,1504],{},[775,3832,3417,3833],{},[366,3834,811],{},[754,3836,3837,3842,3847,3851],{},[775,3838,3839],{},[733,3840,3841],{"href":270},"listStudentReports",[775,3843,3844],{},[366,3845,3846],{},"GET \u002Fv1\u002F{organizationId}\u002Freport\u002F{userId}",[775,3848,3849],{},[366,3850,1507],{},[775,3852,3417,3853],{},[366,3854,811],{},[754,3856,3857,3862,3867,3871],{},[775,3858,3859],{},[733,3860,3861],{"href":267},"downloadReport",[775,3863,3864],{},[366,3865,3866],{},"GET \u002Fv1\u002F{organizationId}\u002Freport\u002Fdownload\u002F{reportId}",[775,3868,3869],{},[366,3870,1507],{},[775,3872,3417,3873],{},[366,3874,811],{},[886,3876,89],{"id":272},[748,3878,3879,3891],{},[751,3880,3881],{},[754,3882,3883,3885,3887,3889],{},[757,3884,1797],{},[757,3886,3004],{},[757,3888,3007],{},[757,3890,3010],{},[770,3892,3893,3913,3933,3953,3973,3993,4013,4033,4053],{},[754,3894,3895,3900,3905,3909],{},[775,3896,3897],{},[733,3898,3899],{"href":276},"listGroupChallenges",[775,3901,3902],{},[366,3903,3904],{},"GET \u002Fv1\u002F{organizationId}\u002Fgroup-challenge",[775,3906,3907],{},[366,3908,1510],{},[775,3910,3417,3911],{},[366,3912,811],{},[754,3914,3915,3920,3925,3929],{},[775,3916,3917],{},[733,3918,3919],{"href":279},"getGroupChallenge",[775,3921,3922],{},[366,3923,3924],{},"GET \u002Fv1\u002F{organizationId}\u002Fgroup-challenge\u002F{challengeId}",[775,3926,3927],{},[366,3928,1510],{},[775,3930,3417,3931],{},[366,3932,811],{},[754,3934,3935,3940,3945,3949],{},[775,3936,3937],{},[733,3938,3939],{"href":297},"listGroupChallengeStudents",[775,3941,3942],{},[366,3943,3944],{},"GET \u002Fv1\u002F{organizationId}\u002Fgroup-challenge\u002F{challengeId}\u002Fstudent",[775,3946,3947],{},[366,3948,1510],{},[775,3950,3417,3951],{},[366,3952,811],{},[754,3954,3955,3960,3965,3969],{},[775,3956,3957],{},[733,3958,3959],{"href":300},"getGroupChallengeStudent",[775,3961,3962],{},[366,3963,3964],{},"GET \u002Fv1\u002F{organizationId}\u002Fgroup-challenge\u002F{challengeId}\u002Fstudent\u002F{studentId}",[775,3966,3967],{},[366,3968,1510],{},[775,3970,3417,3971],{},[366,3972,811],{},[754,3974,3975,3980,3985,3989],{},[775,3976,3977],{},[733,3978,3979],{"href":282},"listGroupChallengeGroups",[775,3981,3982],{},[366,3983,3984],{},"GET \u002Fv1\u002F{organizationId}\u002Fgroup-challenge\u002F{challengeId}\u002Fgroup",[775,3986,3987],{},[366,3988,1510],{},[775,3990,3417,3991],{},[366,3992,811],{},[754,3994,3995,4000,4005,4009],{},[775,3996,3997],{},[733,3998,3999],{"href":285},"getGroupChallengeGroup",[775,4001,4002],{},[366,4003,4004],{},"GET \u002Fv1\u002F{organizationId}\u002Fgroup-challenge\u002F{challengeId}\u002Fgroup\u002F{groupId}",[775,4006,4007],{},[366,4008,1510],{},[775,4010,3417,4011],{},[366,4012,811],{},[754,4014,4015,4020,4025,4029],{},[775,4016,4017],{},[733,4018,4019],{"href":288},"listGroupChallengeActivity",[775,4021,4022],{},[366,4023,4024],{},"GET \u002Fv1\u002F{organizationId}\u002Fgroup-challenge\u002F{challengeId}\u002Fgroup\u002F{groupId}\u002Factivity",[775,4026,4027],{},[366,4028,1510],{},[775,4030,3417,4031],{},[366,4032,811],{},[754,4034,4035,4040,4045,4049],{},[775,4036,4037],{},[733,4038,4039],{"href":294},"submitGroupChallengeStep",[775,4041,4042],{},[366,4043,4044],{},"POST \u002Fv1\u002F{organizationId}\u002Fgroup-challenge\u002F{challengeId}\u002Fgroup\u002F{groupId}\u002Fstep\u002F{stepId}\u002Fsubmit",[775,4046,4047],{},[366,4048,1469],{},[775,4050,3417,4051],{},[366,4052,811],{},[754,4054,4055,4060,4065,4069],{},[775,4056,4057],{},[733,4058,4059],{"href":291},"submitGroupChallengeWork",[775,4061,4062],{},[366,4063,4064],{},"POST \u002Fv1\u002F{organizationId}\u002Fgroup-challenge\u002F{challengeId}\u002Fgroup\u002F{groupId}\u002Ffinal-submit",[775,4066,4067],{},[366,4068,1469],{},[775,4070,3417,4071],{},[366,4072,811],{},[378,4074,4076],{"id":4075},"check-your-roles-in-code","Check your roles in code",[357,4078,4079,4080,4082],{},"To catch a missing role before you make the call, for example to hide a button in your own admin screen, you can apply the same rules to the roles ",[366,4081,718],{}," returns. This mirrors the API's rules. The API's own answer is still the one that counts.",[389,4084,4088],{"className":4085,"code":4086,"language":4087,"meta":394,"style":394},"language-js shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u002F\u002F Does a stored role's action grant the needed action?\nfunction actionGrants(pattern, action) {\n  if (!pattern) return false;\n  if (pattern === '*' || pattern === action) return true;\n  const p = pattern.split('\u002F');\n  const a = action.split('\u002F');\n  if (p.length !== a.length) return false;\n  return p.every((part, i) => part === '*' || part === a[i]);\n}\n\n\u002F**\n * account: the object from GET \u002Fv1\u002Fapi-account\u002Fvalidate-me\n * action:  e.g. 'application\u002Fcreate' (see the matrix above)\n * org:     the organization slug the request acts on; 'mto' for flat routes\n *\u002F\nfunction canCall(account, action, org) {\n  const matching = (account.roles ?? []).filter(\n    (role) =>\n      actionGrants(role.action, action) &&\n      (role.target === '*' || role.target === org) &&\n      (!role.authorized || role.authorized === account._id),\n  );\n  if (matching.some((role) => role.effect === 'disallow')) return false;\n  return matching.some((role) => role.effect === 'allow');\n}\n\ncanCall(account, 'application\u002Fcreate', 'stem'); \u002F\u002F true with the enrollment profile\ncanCall(account, 'auth\u002Fsignin', 'mto');          \u002F\u002F false: no password role\n","js",[366,4089,4090,4096,4117,4140,4171,4196,4216,4243,4285,4289,4295,4301,4307,4313,4319,4325,4349,4374,4388,4400,4422,4444,4450,4486,4513,4518,4523,4546],{"__ignoreMap":394},[398,4091,4092],{"class":400,"line":401},[398,4093,4095],{"class":4094},"sLBg1","\u002F\u002F Does a stored role's action grant the needed action?\n",[398,4097,4098,4101,4105,4107,4110,4112,4114],{"class":400,"line":420},[398,4099,4100],{"class":416},"function",[398,4102,4104],{"class":4103},"sKwhi"," actionGrants",[398,4106,715],{"class":429},[398,4108,4109],{"class":404},"pattern",[398,4111,472],{"class":429},[398,4113,802],{"class":404},[398,4115,4116],{"class":429},") {\n",[398,4118,4119,4122,4125,4128,4131,4134,4137],{"class":400,"line":496},[398,4120,4121],{"class":416},"  if",[398,4123,4124],{"class":429}," (",[398,4126,4127],{"class":416},"!",[398,4129,4130],{"class":429},"pattern) ",[398,4132,4133],{"class":416},"return",[398,4135,4136],{"class":408}," false",[398,4138,4139],{"class":429},";\n",[398,4141,4142,4144,4147,4150,4153,4156,4159,4161,4164,4166,4169],{"class":400,"line":526},[398,4143,4121],{"class":416},[398,4145,4146],{"class":429}," (pattern ",[398,4148,4149],{"class":416},"===",[398,4151,4152],{"class":412}," '*'",[398,4154,4155],{"class":416}," ||",[398,4157,4158],{"class":429}," pattern ",[398,4160,4149],{"class":416},[398,4162,4163],{"class":429}," action) ",[398,4165,4133],{"class":416},[398,4167,4168],{"class":408}," true",[398,4170,4139],{"class":429},[398,4172,4173,4176,4179,4182,4185,4188,4190,4193],{"class":400,"line":556},[398,4174,4175],{"class":416},"  const",[398,4177,4178],{"class":408}," p",[398,4180,4181],{"class":416}," =",[398,4183,4184],{"class":429}," pattern.",[398,4186,4187],{"class":4103},"split",[398,4189,715],{"class":429},[398,4191,4192],{"class":412},"'\u002F'",[398,4194,4195],{"class":429},");\n",[398,4197,4198,4200,4203,4205,4208,4210,4212,4214],{"class":400,"line":586},[398,4199,4175],{"class":416},[398,4201,4202],{"class":408}," a",[398,4204,4181],{"class":416},[398,4206,4207],{"class":429}," action.",[398,4209,4187],{"class":4103},[398,4211,715],{"class":429},[398,4213,4192],{"class":412},[398,4215,4195],{"class":429},[398,4217,4218,4220,4223,4226,4229,4232,4234,4237,4239,4241],{"class":400,"line":616},[398,4219,4121],{"class":416},[398,4221,4222],{"class":429}," (p.",[398,4224,4225],{"class":408},"length",[398,4227,4228],{"class":416}," !==",[398,4230,4231],{"class":429}," a.",[398,4233,4225],{"class":408},[398,4235,4236],{"class":429},") ",[398,4238,4133],{"class":416},[398,4240,4136],{"class":408},[398,4242,4139],{"class":429},[398,4244,4245,4248,4251,4253,4256,4259,4261,4264,4266,4269,4272,4274,4276,4278,4280,4282],{"class":400,"line":646},[398,4246,4247],{"class":416},"  return",[398,4249,4250],{"class":429}," p.",[398,4252,2961],{"class":4103},[398,4254,4255],{"class":429},"((",[398,4257,4258],{"class":404},"part",[398,4260,472],{"class":429},[398,4262,4263],{"class":404},"i",[398,4265,4236],{"class":429},[398,4267,4268],{"class":416},"=>",[398,4270,4271],{"class":429}," part ",[398,4273,4149],{"class":416},[398,4275,4152],{"class":412},[398,4277,4155],{"class":416},[398,4279,4271],{"class":429},[398,4281,4149],{"class":416},[398,4283,4284],{"class":429}," a[i]);\n",[398,4286,4287],{"class":400,"line":676},[398,4288,1398],{"class":429},[398,4290,4291],{"class":400,"line":709},[398,4292,4294],{"emptyLinePlaceholder":4293},true,"\n",[398,4296,4298],{"class":400,"line":4297},11,[398,4299,4300],{"class":4094},"\u002F**\n",[398,4302,4304],{"class":400,"line":4303},12,[398,4305,4306],{"class":4094}," * account: the object from GET \u002Fv1\u002Fapi-account\u002Fvalidate-me\n",[398,4308,4310],{"class":400,"line":4309},13,[398,4311,4312],{"class":4094}," * action:  e.g. 'application\u002Fcreate' (see the matrix above)\n",[398,4314,4316],{"class":400,"line":4315},14,[398,4317,4318],{"class":4094}," * org:     the organization slug the request acts on; 'mto' for flat routes\n",[398,4320,4322],{"class":400,"line":4321},15,[398,4323,4324],{"class":4094}," *\u002F\n",[398,4326,4328,4330,4333,4335,4338,4340,4342,4344,4347],{"class":400,"line":4327},16,[398,4329,4100],{"class":416},[398,4331,4332],{"class":4103}," canCall",[398,4334,715],{"class":429},[398,4336,4337],{"class":404},"account",[398,4339,472],{"class":429},[398,4341,802],{"class":404},[398,4343,472],{"class":429},[398,4345,4346],{"class":404},"org",[398,4348,4116],{"class":429},[398,4350,4352,4354,4357,4359,4362,4365,4368,4371],{"class":400,"line":4351},17,[398,4353,4175],{"class":416},[398,4355,4356],{"class":408}," matching",[398,4358,4181],{"class":416},[398,4360,4361],{"class":429}," (account.roles ",[398,4363,4364],{"class":416},"??",[398,4366,4367],{"class":429}," []).",[398,4369,4370],{"class":4103},"filter",[398,4372,4373],{"class":429},"(\n",[398,4375,4377,4380,4383,4385],{"class":400,"line":4376},18,[398,4378,4379],{"class":429},"    (",[398,4381,4382],{"class":404},"role",[398,4384,4236],{"class":429},[398,4386,4387],{"class":416},"=>\n",[398,4389,4391,4394,4397],{"class":400,"line":4390},19,[398,4392,4393],{"class":4103},"      actionGrants",[398,4395,4396],{"class":429},"(role.action, action) ",[398,4398,4399],{"class":416},"&&\n",[398,4401,4403,4406,4408,4410,4412,4415,4417,4420],{"class":400,"line":4402},20,[398,4404,4405],{"class":429},"      (role.target ",[398,4407,4149],{"class":416},[398,4409,4152],{"class":412},[398,4411,4155],{"class":416},[398,4413,4414],{"class":429}," role.target ",[398,4416,4149],{"class":416},[398,4418,4419],{"class":429}," org) ",[398,4421,4399],{"class":416},[398,4423,4425,4428,4430,4433,4436,4439,4441],{"class":400,"line":4424},21,[398,4426,4427],{"class":429},"      (",[398,4429,4127],{"class":416},[398,4431,4432],{"class":429},"role.authorized ",[398,4434,4435],{"class":416},"||",[398,4437,4438],{"class":429}," role.authorized ",[398,4440,4149],{"class":416},[398,4442,4443],{"class":429}," account._id),\n",[398,4445,4447],{"class":400,"line":4446},22,[398,4448,4449],{"class":429},"  );\n",[398,4451,4453,4455,4458,4461,4463,4465,4467,4469,4472,4474,4477,4480,4482,4484],{"class":400,"line":4452},23,[398,4454,4121],{"class":416},[398,4456,4457],{"class":429}," (matching.",[398,4459,4460],{"class":4103},"some",[398,4462,4255],{"class":429},[398,4464,4382],{"class":404},[398,4466,4236],{"class":429},[398,4468,4268],{"class":416},[398,4470,4471],{"class":429}," role.effect ",[398,4473,4149],{"class":416},[398,4475,4476],{"class":412}," 'disallow'",[398,4478,4479],{"class":429},")) ",[398,4481,4133],{"class":416},[398,4483,4136],{"class":408},[398,4485,4139],{"class":429},[398,4487,4489,4491,4494,4496,4498,4500,4502,4504,4506,4508,4511],{"class":400,"line":4488},24,[398,4490,4247],{"class":416},[398,4492,4493],{"class":429}," matching.",[398,4495,4460],{"class":4103},[398,4497,4255],{"class":429},[398,4499,4382],{"class":404},[398,4501,4236],{"class":429},[398,4503,4268],{"class":416},[398,4505,4471],{"class":429},[398,4507,4149],{"class":416},[398,4509,4510],{"class":412}," 'allow'",[398,4512,4195],{"class":429},[398,4514,4516],{"class":400,"line":4515},25,[398,4517,1398],{"class":429},[398,4519,4521],{"class":400,"line":4520},26,[398,4522,4294],{"emptyLinePlaceholder":4293},[398,4524,4526,4529,4532,4535,4537,4540,4543],{"class":400,"line":4525},27,[398,4527,4528],{"class":4103},"canCall",[398,4530,4531],{"class":429},"(account, ",[398,4533,4534],{"class":412},"'application\u002Fcreate'",[398,4536,472],{"class":429},[398,4538,4539],{"class":412},"'stem'",[398,4541,4542],{"class":429},"); ",[398,4544,4545],{"class":4094},"\u002F\u002F true with the enrollment profile\n",[398,4547,4549,4551,4553,4556,4558,4561,4564],{"class":400,"line":4548},28,[398,4550,4528],{"class":4103},[398,4552,4531],{"class":429},[398,4554,4555],{"class":412},"'auth\u002Fsignin'",[398,4557,472],{"class":429},[398,4559,4560],{"class":412},"'mto'",[398,4562,4563],{"class":429},");          ",[398,4565,4566],{"class":4094},"\u002F\u002F false: no password role\n",[389,4568,4572],{"className":4569,"code":4570,"language":4571,"meta":394,"style":394},"language-php shiki shiki-themes github-light-high-contrast github-dark-high-contrast","function actionGrants(?string $pattern, string $action): bool\n{\n    if ($pattern === null || $pattern === '') return false;\n    if ($pattern === '*' || $pattern === $action) return true;\n    $p = explode('\u002F', $pattern);\n    $a = explode('\u002F', $action);\n    if (count($p) !== count($a)) return false;\n    foreach ($p as $i => $part) {\n        if ($part !== '*' && $part !== $a[$i]) return false;\n    }\n    return true;\n}\n\nfunction canCall(array $account, string $action, string $org): bool\n{\n    $matching = array_filter($account['roles'] ?? [], fn ($role) =>\n        actionGrants($role['action'] ?? null, $action)\n        && (($role['target'] ?? null) === '*' || ($role['target'] ?? null) === $org)\n        && (empty($role['authorized']) || $role['authorized'] === $account['_id']));\n\n    foreach ($matching as $role) {\n        if (($role['effect'] ?? null) === 'disallow') return false;\n    }\n    foreach ($matching as $role) {\n        if (($role['effect'] ?? null) === 'allow') return true;\n    }\n    return false;\n}\n","php",[366,4573,4574,4600,4604,4635,4660,4678,4694,4721,4739,4768,4773,4782,4786,4790,4818,4822,4852,4872,4915,4951,4955,4967,4996,5000,5010,5038,5042,5050],{"__ignoreMap":394},[398,4575,4576,4578,4580,4582,4585,4588,4591,4594,4597],{"class":400,"line":401},[398,4577,4100],{"class":416},[398,4579,4104],{"class":4103},[398,4581,715],{"class":429},[398,4583,4584],{"class":416},"?string",[398,4586,4587],{"class":429}," $pattern, ",[398,4589,4590],{"class":416},"string",[398,4592,4593],{"class":429}," $action)",[398,4595,4596],{"class":416},":",[398,4598,4599],{"class":416}," bool\n",[398,4601,4602],{"class":400,"line":420},[398,4603,1333],{"class":429},[398,4605,4606,4609,4612,4614,4617,4619,4622,4624,4627,4629,4631,4633],{"class":400,"line":496},[398,4607,4608],{"class":416},"    if",[398,4610,4611],{"class":429}," ($pattern ",[398,4613,4149],{"class":416},[398,4615,4616],{"class":408}," null",[398,4618,4155],{"class":416},[398,4620,4621],{"class":429}," $pattern ",[398,4623,4149],{"class":416},[398,4625,4626],{"class":412}," ''",[398,4628,4236],{"class":429},[398,4630,4133],{"class":416},[398,4632,4136],{"class":408},[398,4634,4139],{"class":429},[398,4636,4637,4639,4641,4643,4645,4647,4649,4651,4654,4656,4658],{"class":400,"line":526},[398,4638,4608],{"class":416},[398,4640,4611],{"class":429},[398,4642,4149],{"class":416},[398,4644,4152],{"class":412},[398,4646,4155],{"class":416},[398,4648,4621],{"class":429},[398,4650,4149],{"class":416},[398,4652,4653],{"class":429}," $action) ",[398,4655,4133],{"class":416},[398,4657,4168],{"class":408},[398,4659,4139],{"class":429},[398,4661,4662,4665,4668,4671,4673,4675],{"class":400,"line":556},[398,4663,4664],{"class":429},"    $p ",[398,4666,4667],{"class":416},"=",[398,4669,4670],{"class":408}," explode",[398,4672,715],{"class":429},[398,4674,4192],{"class":412},[398,4676,4677],{"class":429},", $pattern);\n",[398,4679,4680,4683,4685,4687,4689,4691],{"class":400,"line":586},[398,4681,4682],{"class":429},"    $a ",[398,4684,4667],{"class":416},[398,4686,4670],{"class":408},[398,4688,715],{"class":429},[398,4690,4192],{"class":412},[398,4692,4693],{"class":429},", $action);\n",[398,4695,4696,4698,4700,4703,4706,4709,4712,4715,4717,4719],{"class":400,"line":616},[398,4697,4608],{"class":416},[398,4699,4124],{"class":429},[398,4701,4702],{"class":408},"count",[398,4704,4705],{"class":429},"($p) ",[398,4707,4708],{"class":416},"!==",[398,4710,4711],{"class":408}," count",[398,4713,4714],{"class":429},"($a)) ",[398,4716,4133],{"class":416},[398,4718,4136],{"class":408},[398,4720,4139],{"class":429},[398,4722,4723,4726,4729,4731,4734,4736],{"class":400,"line":646},[398,4724,4725],{"class":416},"    foreach",[398,4727,4728],{"class":429}," ($p ",[398,4730,1787],{"class":416},[398,4732,4733],{"class":429}," $i ",[398,4735,4268],{"class":416},[398,4737,4738],{"class":429}," $part) {\n",[398,4740,4741,4744,4747,4749,4751,4754,4757,4759,4762,4764,4766],{"class":400,"line":676},[398,4742,4743],{"class":416},"        if",[398,4745,4746],{"class":429}," ($part ",[398,4748,4708],{"class":416},[398,4750,4152],{"class":412},[398,4752,4753],{"class":416}," &&",[398,4755,4756],{"class":429}," $part ",[398,4758,4708],{"class":416},[398,4760,4761],{"class":429}," $a[$i]) ",[398,4763,4133],{"class":416},[398,4765,4136],{"class":408},[398,4767,4139],{"class":429},[398,4769,4770],{"class":400,"line":709},[398,4771,4772],{"class":429},"    }\n",[398,4774,4775,4778,4780],{"class":400,"line":4297},[398,4776,4777],{"class":416},"    return",[398,4779,4168],{"class":408},[398,4781,4139],{"class":429},[398,4783,4784],{"class":400,"line":4303},[398,4785,1398],{"class":429},[398,4787,4788],{"class":400,"line":4309},[398,4789,4294],{"emptyLinePlaceholder":4293},[398,4791,4792,4794,4796,4798,4801,4804,4806,4809,4811,4814,4816],{"class":400,"line":4315},[398,4793,4100],{"class":416},[398,4795,4332],{"class":4103},[398,4797,715],{"class":429},[398,4799,4800],{"class":416},"array",[398,4802,4803],{"class":429}," $account, ",[398,4805,4590],{"class":416},[398,4807,4808],{"class":429}," $action, ",[398,4810,4590],{"class":416},[398,4812,4813],{"class":429}," $org)",[398,4815,4596],{"class":416},[398,4817,4599],{"class":416},[398,4819,4820],{"class":400,"line":4321},[398,4821,1333],{"class":429},[398,4823,4824,4827,4829,4832,4835,4838,4841,4843,4846,4849],{"class":400,"line":4327},[398,4825,4826],{"class":429},"    $matching ",[398,4828,4667],{"class":416},[398,4830,4831],{"class":408}," array_filter",[398,4833,4834],{"class":429},"($account[",[398,4836,4837],{"class":412},"'roles'",[398,4839,4840],{"class":429},"] ",[398,4842,4364],{"class":416},[398,4844,4845],{"class":429}," [], ",[398,4847,4848],{"class":416},"fn",[398,4850,4851],{"class":429}," ($role) =>\n",[398,4853,4854,4857,4860,4863,4865,4867,4869],{"class":400,"line":4351},[398,4855,4856],{"class":4103},"        actionGrants",[398,4858,4859],{"class":429},"($role[",[398,4861,4862],{"class":412},"'action'",[398,4864,4840],{"class":429},[398,4866,4364],{"class":416},[398,4868,4616],{"class":408},[398,4870,4871],{"class":429},", $action)\n",[398,4873,4874,4877,4880,4883,4885,4887,4889,4891,4893,4895,4897,4900,4902,4904,4906,4908,4910,4912],{"class":400,"line":4376},[398,4875,4876],{"class":416},"        &&",[398,4878,4879],{"class":429}," (($role[",[398,4881,4882],{"class":412},"'target'",[398,4884,4840],{"class":429},[398,4886,4364],{"class":416},[398,4888,4616],{"class":408},[398,4890,4236],{"class":429},[398,4892,4149],{"class":416},[398,4894,4152],{"class":412},[398,4896,4155],{"class":416},[398,4898,4899],{"class":429}," ($role[",[398,4901,4882],{"class":412},[398,4903,4840],{"class":429},[398,4905,4364],{"class":416},[398,4907,4616],{"class":408},[398,4909,4236],{"class":429},[398,4911,4149],{"class":416},[398,4913,4914],{"class":429}," $org)\n",[398,4916,4917,4919,4921,4923,4925,4928,4931,4933,4936,4938,4940,4942,4945,4948],{"class":400,"line":4390},[398,4918,4876],{"class":416},[398,4920,4124],{"class":429},[398,4922,881],{"class":408},[398,4924,4859],{"class":429},[398,4926,4927],{"class":412},"'authorized'",[398,4929,4930],{"class":429},"]) ",[398,4932,4435],{"class":416},[398,4934,4935],{"class":429}," $role[",[398,4937,4927],{"class":412},[398,4939,4840],{"class":429},[398,4941,4149],{"class":416},[398,4943,4944],{"class":429}," $account[",[398,4946,4947],{"class":412},"'_id'",[398,4949,4950],{"class":429},"]));\n",[398,4952,4953],{"class":400,"line":4402},[398,4954,4294],{"emptyLinePlaceholder":4293},[398,4956,4957,4959,4962,4964],{"class":400,"line":4424},[398,4958,4725],{"class":416},[398,4960,4961],{"class":429}," ($matching ",[398,4963,1787],{"class":416},[398,4965,4966],{"class":429}," $role) {\n",[398,4968,4969,4971,4973,4976,4978,4980,4982,4984,4986,4988,4990,4992,4994],{"class":400,"line":4446},[398,4970,4743],{"class":416},[398,4972,4879],{"class":429},[398,4974,4975],{"class":412},"'effect'",[398,4977,4840],{"class":429},[398,4979,4364],{"class":416},[398,4981,4616],{"class":408},[398,4983,4236],{"class":429},[398,4985,4149],{"class":416},[398,4987,4476],{"class":412},[398,4989,4236],{"class":429},[398,4991,4133],{"class":416},[398,4993,4136],{"class":408},[398,4995,4139],{"class":429},[398,4997,4998],{"class":400,"line":4452},[398,4999,4772],{"class":429},[398,5001,5002,5004,5006,5008],{"class":400,"line":4488},[398,5003,4725],{"class":416},[398,5005,4961],{"class":429},[398,5007,1787],{"class":416},[398,5009,4966],{"class":429},[398,5011,5012,5014,5016,5018,5020,5022,5024,5026,5028,5030,5032,5034,5036],{"class":400,"line":4515},[398,5013,4743],{"class":416},[398,5015,4879],{"class":429},[398,5017,4975],{"class":412},[398,5019,4840],{"class":429},[398,5021,4364],{"class":416},[398,5023,4616],{"class":408},[398,5025,4236],{"class":429},[398,5027,4149],{"class":416},[398,5029,4510],{"class":412},[398,5031,4236],{"class":429},[398,5033,4133],{"class":416},[398,5035,4168],{"class":408},[398,5037,4139],{"class":429},[398,5039,5040],{"class":400,"line":4520},[398,5041,4772],{"class":429},[398,5043,5044,5046,5048],{"class":400,"line":4525},[398,5045,4777],{"class":416},[398,5047,4136],{"class":408},[398,5049,4139],{"class":429},[398,5051,5052],{"class":400,"line":4548},[398,5053,1398],{"class":429},[357,5055,5056,5057,5059],{},"Roles can change at any time (within 60 seconds of an operator's edit), so refresh your copy of ",[366,5058,718],{}," now and then rather than keeping it forever.",[378,5061,5063],{"id":5062},"asking-for-a-role","Asking for a role",[357,5065,5066,5067,5073],{},"Write to ",[361,5068,5069],{},[733,5070,5072],{"href":5071},"mailto:info@main-team.org","info@main-team.org"," from your registered contact address with:",[1192,5075,5076,5083,5089,5092],{},[1195,5077,5078,5079,5082],{},"your ",[366,5080,5081],{},"apiKey"," (never the secret),",[1195,5084,5085,5086,5088],{},"the operations you need, by name from the ",[733,5087,1274],{"href":1273},", or a profile from this page,",[1195,5090,5091],{},"the organizations, by slug,",[1195,5093,5094,5095,5097,5098,5101],{},"for a ",[366,5096,730],{}," you already hit: the ",[366,5099,5100],{},"request_id",", the time in UTC and the request you made.",[357,5103,5104],{},"A granted role works within 60 seconds, with the token you already have.",[5106,5107,5108],"style",{},"html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}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 .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .sKwhi, html code.shiki .sKwhi{--shiki-default:#622CBC;--shiki-dark:#DBB7FF}",{"title":394,"searchDepth":420,"depth":496,"links":5110},[5111,5112,5118,5119,5120,5121,5122,5123,5124,5134,5144,5145],{"id":380,"depth":420,"text":381},{"id":742,"depth":420,"text":743,"children":5113},[5114,5115,5116,5117],{"id":779,"depth":496,"text":779},{"id":802,"depth":496,"text":802},{"id":834,"depth":496,"text":834},{"id":872,"depth":496,"text":872},{"id":1266,"depth":420,"text":1267},{"id":1406,"depth":420,"text":1407},{"id":1676,"depth":420,"text":905},{"id":1778,"depth":420,"text":1779},{"id":1966,"depth":420,"text":1967},{"id":2047,"depth":420,"text":2048},{"id":2140,"depth":420,"text":2141,"children":5125},[5126,5127,5128,5129,5130,5131,5132,5133],{"id":2150,"depth":496,"text":2151},{"id":2183,"depth":496,"text":2184},{"id":2258,"depth":496,"text":2259},{"id":2624,"depth":496,"text":2625},{"id":2717,"depth":496,"text":2718},{"id":2826,"depth":496,"text":2827},{"id":2871,"depth":496,"text":2872},{"id":2936,"depth":496,"text":2937},{"id":2945,"depth":420,"text":2946,"children":5135},[5136,5137,5138,5139,5140,5141,5142,5143],{"id":2992,"depth":496,"text":2993},{"id":146,"depth":496,"text":74},{"id":3224,"depth":496,"text":3225},{"id":3381,"depth":496,"text":3382},{"id":213,"depth":496,"text":83},{"id":231,"depth":496,"text":86},{"id":3778,"depth":496,"text":92},{"id":272,"depth":496,"text":89},{"id":4075,"depth":420,"text":4076},{"id":5062,"depth":420,"text":5063},"How roles grant access. The effect, action, target and authorized fields, wildcards, why disallow wins, auth\u002Fsignin, ready-made profiles and a full matrix.","md",{},[],"50",{"title":25,"description":5146},"api\u002Fpermissions","5pFAMwsVOJDLnQxTpFCVw6BoS2k3LGJPZEPAxtutUTc",[],1791554614910]