[{"data":1,"prerenderedAt":447},["ShallowReactive",2],{"navigation_docs":3,"-docs-architecture-organization-activation-and-routes":158,"-docs-architecture-organization-activation-and-routes-surround":442},[4,15,74,98,113],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"\u002Fdocs\u002Fgetting-started","docs\u002F1.getting-started",[10],{"title":11,"path":12,"stem":13,"icon":14},"Zeeq Introduction","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"children":19,"page":6},"Key Features","\u002Fdocs\u002Fkey-features","docs\u002F3.key-features",[20,25,30,35,40,45,50,55,59,64,69],{"title":21,"path":22,"stem":23,"icon":24},"Membership Invitations","\u002Fdocs\u002Fkey-features\u002Fmembership-invitations","docs\u002F3.key-features\u002F1.membership-invitations","i-hugeicons-cube",{"title":26,"path":27,"stem":28,"icon":29},"Command Palette","\u002Fdocs\u002Fkey-features\u002Fcommand-palette","docs\u002F3.key-features\u002F10.command-palette","i-hugeicons-search-01",{"title":31,"path":32,"stem":33,"icon":34},"Library Import and Export","\u002Fdocs\u002Fkey-features\u002Flibrary-import-export","docs\u002F3.key-features\u002F11.library-import-export","i-lucide-package-open",{"title":36,"path":37,"stem":38,"icon":39},"LLM Settings Configuration","\u002Fdocs\u002Fkey-features\u002Fllm-settings-configuration","docs\u002F3.key-features\u002F2.llm-settings-configuration","i-hugeicons-ai-magic",{"title":41,"path":42,"stem":43,"icon":44},"Agent Code Review Findings","\u002Fdocs\u002Fkey-features\u002Fagent-code-review-findings","docs\u002F3.key-features\u002F3.agent-code-review-findings","i-lucide-list-checks",{"title":46,"path":47,"stem":48,"icon":49},"Credentials & API Tokens","\u002Fdocs\u002Fkey-features\u002Fcredentials","docs\u002F3.key-features\u002F4.credentials","i-hugeicons-key-01",{"title":51,"path":52,"stem":53,"icon":54},"Manual Document Libraries","\u002Fdocs\u002Fkey-features\u002Fmanual-document-libraries","docs\u002F3.key-features\u002F5.manual-document-libraries","i-lucide-library-big",{"title":56,"path":57,"stem":58,"icon":29},"Snippet Search","\u002Fdocs\u002Fkey-features\u002Fsnippet-search","docs\u002F3.key-features\u002F6.snippet-search",{"title":60,"path":61,"stem":62,"icon":63},"Shared Prompt Fragment","\u002Fdocs\u002Fkey-features\u002Fshared-prompt-fragment","docs\u002F3.key-features\u002F7.shared-prompt-fragment","i-lucide-notebook-pen",{"title":65,"path":66,"stem":67,"icon":68},"Code Review Sources & Telemetry","\u002Fdocs\u002Fkey-features\u002Fcode-review-sources","docs\u002F3.key-features\u002F8.code-review-sources","i-hugeicons-book-01",{"title":70,"path":71,"stem":72,"icon":73},"Excluding Documents from Code Reviews","\u002Fdocs\u002Fkey-features\u002Fcode-review-document-exclusion","docs\u002F3.key-features\u002F9.code-review-document-exclusion","i-lucide-eye-off",{"title":75,"path":76,"stem":77,"children":78,"page":6},"Runtime Configuration","\u002Fdocs\u002Fconfiguration","docs\u002F5.configuration",[79,84,89,93],{"title":80,"path":81,"stem":82,"icon":83},"Google Cloud Configuration","\u002Fdocs\u002Fconfiguration\u002Fgcp-runtime","docs\u002F5.configuration\u002F1.gcp-runtime","i-hugeicons-google",{"title":85,"path":86,"stem":87,"icon":88},"GitHub Configuration","\u002Fdocs\u002Fconfiguration\u002Fgithub-configuration","docs\u002F5.configuration\u002F2.github-configuration","i-hugeicons-github",{"title":90,"path":91,"stem":92},"Local OpenIddict Certificates","\u002Fdocs\u002Fconfiguration\u002Flocal-openiddict-certificates","docs\u002F5.configuration\u002F3.local-openiddict-certificates",{"title":94,"path":95,"stem":96,"icon":97},"System Admin Access","\u002Fdocs\u002Fconfiguration\u002Fsystem-admin-access","docs\u002F5.configuration\u002F4.system-admin-access","i-hugeicons-shield-01",{"title":99,"path":100,"stem":101,"children":102,"page":6},"Metrics","\u002Fdocs\u002Fmetrics","docs\u002F6.metrics",[103,108],{"title":104,"path":105,"stem":106,"icon":107},"Metrics Dashboard","\u002Fdocs\u002Fmetrics\u002Fmetrics-dashboard","docs\u002F6.metrics\u002F1.metrics-dashboard","i-hugeicons-analytics-01",{"title":109,"path":110,"stem":111,"icon":112},"Metrics Pipeline","\u002Fdocs\u002Fmetrics\u002Fmetrics-pipeline","docs\u002F6.metrics\u002F2.metrics-pipeline","i-hugeicons-database-02",{"title":114,"path":115,"stem":116,"children":117,"page":6},"Design and Architecture","\u002Fdocs\u002Farchitecture","docs\u002F9.architecture",[118,123,128,133,137,141,145,150,154],{"title":119,"path":120,"stem":121,"icon":122},"Caching","\u002Fdocs\u002Farchitecture\u002Fcaching","docs\u002F9.architecture\u002F1.caching","i-lucide-database",{"title":124,"path":125,"stem":126,"icon":127},"Messaging and Queueing","\u002Fdocs\u002Farchitecture\u002Fmessaging-and-queueing","docs\u002F9.architecture\u002F2.messaging-and-queueing","i-lucide-message-square",{"title":129,"path":130,"stem":131,"icon":132},"GitHub Comment Rendering","\u002Fdocs\u002Farchitecture\u002Fgithub-comment-rendering","docs\u002F9.architecture\u002F3.github-comment-rendering","i-lucide-github",{"title":134,"path":135,"stem":136},"GitHub Integration","\u002Fdocs\u002Farchitecture\u002Fgithub-integration","docs\u002F9.architecture\u002F4.github-integration",{"title":138,"path":139,"stem":140},"LLM Settings and Secret Storage","\u002Fdocs\u002Farchitecture\u002Fllm-settings-and-secret-storage","docs\u002F9.architecture\u002F5.llm-settings-and-secret-storage",{"title":142,"path":143,"stem":144},"Organization Activation and Routes","\u002Fdocs\u002Farchitecture\u002Forganization-activation-and-routes","docs\u002F9.architecture\u002F6.organization-activation-and-routes",{"title":146,"path":147,"stem":148,"icon":149},"MCP Uploaded-Diff Code Reviews","\u002Fdocs\u002Farchitecture\u002Fmcp-uploaded-diff-code-reviews","docs\u002F9.architecture\u002F7.mcp-uploaded-diff-code-reviews","i-lucide-file-search",{"title":151,"path":152,"stem":153},"Repository Content Ingest","\u002Fdocs\u002Farchitecture\u002Frepository-content-ingest","docs\u002F9.architecture\u002F8.repository-content-ingest",{"title":155,"path":156,"stem":157},"Telemetry Ingest","\u002Fdocs\u002Farchitecture\u002Ftelemetry-ingest","docs\u002F9.architecture\u002F9.telemetry-ingest",{"id":159,"title":142,"body":160,"description":434,"extension":435,"links":436,"meta":437,"navigation":439,"path":143,"seo":440,"stem":144,"__hash__":441},"docs\u002Fdocs\u002F9.architecture\u002F6.organization-activation-and-routes.md",{"type":161,"value":162,"toc":424},"minimark",[163,167,180,187,192,199,206,271,274,278,284,309,315,319,322,342,345,349,360,363,367,378,381,385,392,409],[164,165,142],"h1",{"id":166},"organization-activation-and-routes",[168,169,170,171,175,176,179],"p",{},"Zeeq treats organization activation as a server-side authorization precondition for organization-scoped state changes. An organization is active when ",[172,173,174],"code",{},"Organization.ActivatedAtUtc"," is set and ",[172,177,178],{},"Organization.DisabledAtUtc"," is not set.",[168,181,182,183,186],{},"New organizations are activated at creation time. Existing non-disabled organizations are backfilled with ",[172,184,185],{},"activated_at_utc = created_at_utc"," during the activation migration. Disabled organizations remain inactive.",[188,189,191],"h2",{"id":190},"route-shape","Route Shape",[168,193,194,195,198],{},"Organization-scoped APIs use ",[172,196,197],{},"\u002Fapi\u002Fv1\u002Forgs\u002F{orgId}\u002F...",".",[168,200,201,202,205],{},"The route ",[172,203,204],{},"orgId"," must match the active organization ID carried by the authenticated cookie. The route\u002Fcookie consistency filter runs before active-state checks:",[207,208,209,222],"table",{},[210,211,212],"thead",{},[213,214,215,219],"tr",{},[216,217,218],"th",{},"Condition",[216,220,221],{},"Result",[223,224,225,238,248,261],"tbody",{},[213,226,227,233],{},[228,229,230,231],"td",{},"Missing route ",[172,232,204],{},[228,234,235],{},[172,236,237],{},"400 Bad Request",[213,239,240,243],{},[228,241,242],{},"Missing cookie organization claim",[228,244,245],{},[172,246,247],{},"401 Unauthorized",[213,249,250,256],{},[228,251,252,253,255],{},"Route ",[172,254,204],{}," does not match the cookie organization",[228,257,258],{},[172,259,260],{},"403 Forbidden",[213,262,263,268],{},[228,264,252,265,267],{},[172,266,204],{}," matches the cookie organization",[228,269,270],{},"The request continues",[168,272,273],{},"Do not accept organization scope only through query string parameters for new org-scoped APIs. If an endpoint needs organization context, put it in the route unless it is an auth bootstrap or activation-adjacent flow that deliberately has no active organization yet.",[188,275,277],{"id":276},"protected-routes","Protected Routes",[168,279,280,281,283],{},"Mutation routes under ",[172,282,197],{}," require an active organization before they can mutate state. This includes:",[285,286,287,291,294,297,300,303,306],"ul",{},[288,289,290],"li",{},"Organization profile updates.",[288,292,293],{},"Member role changes and member removal.",[288,295,296],{},"Organization invitation create and cancel.",[288,298,299],{},"LLM settings, key management, and provider tests.",[288,301,302],{},"Code-review manual requests, organization settings, reviewer agents, and repository review configuration.",[288,304,305],{},"GitHub repository mapping create, update, and disable.",[288,307,308],{},"User-owned client credentials and API tokens under the active organization route.",[168,310,311,314],{},[172,312,313],{},"GET \u002Fapi\u002Fv1\u002Fme"," uses the current organization from the cookie instead of a route parameter. It also requires that current organization to be active so the app shell can redirect inactive sessions consistently.",[188,316,318],{"id":317},"exempt-routes","Exempt Routes",[168,320,321],{},"These routes intentionally do not use the active-organization filter:",[285,323,324,327,330,333],{},[288,325,326],{},"Organization creation and slug checks.",[288,328,329],{},"Login, logout, OAuth callbacks, and dynamic auth bootstrap flows.",[288,331,332],{},"GitHub App install and callback routes.",[288,334,335,338,339,198],{},[172,336,337],{},"POST \u002Fapi\u002Fv1\u002Fme\u002Finvitations\u002F{id}\u002Faccept"," and ",[172,340,341],{},"\u002Fdecline",[168,343,344],{},"Invitation accept and decline are activation-adjacent. A user may need to accept an invitation into an active organization while their current organization is inactive or unset, so those handlers validate the invitation transition directly instead of depending on the current organization activation filter.",[188,346,348],{"id":347},"inactive-behavior","Inactive Behavior",[168,350,351,352,355,356,359],{},"When the active-organization filter finds an inactive organization, it returns a redirect to ",[172,353,354],{},"\u002Flogin?inactiveOrg=true",". The frontend Kubb fetch transport handles redirected responses before JSON parsing and navigates the browser to the login page. The login view uses the ",[172,357,358],{},"inactiveOrg=true"," page state to render the inactive-organization notice below the OAuth login card.",[168,361,362],{},"The redirect is intentional for browser callers. API code should not treat inactive-organization responses as ordinary JSON error bodies.",[188,364,366],{"id":365},"cache-window","Cache Window",[168,368,369,370,373,374,377],{},"The active-state lookup uses ",[172,371,372],{},"HybridCache"," with a 30-second expiration and local expiration. Within that window, repeated endpoint-filter checks can reuse the cached ",[172,375,376],{},"OrganizationActivationState"," projection instead of loading the full organization row.",[168,379,380],{},"The cache is a short consistency window. Activation or disable changes may take up to 30 seconds to be reflected by filters on every process.",[188,382,384],{"id":383},"implementation-notes","Implementation Notes",[168,386,387,388,391],{},"The filters live in ",[172,389,390],{},"Zeeq.Core.Identity.Organizations",":",[285,393,394,399,404],{},[288,395,396],{},[172,397,398],{},"RequireRouteOrganizationMatchesCookieFilter",[288,400,401],{},[172,402,403],{},"RequireActiveOrganizationFilter",[288,405,406],{},[172,407,408],{},"RequireActiveCurrentOrganizationFilter",[168,410,411,412,415,416,419,420,423],{},"Endpoint groups attach them through ",[172,413,414],{},"RequireRouteOrganizationMatchesCookie()",", ",[172,417,418],{},"RequireActiveOrganization()",", and ",[172,421,422],{},"RequireActiveCurrentOrganization()",". Prefer applying the route\u002Fcookie filter at the route group and the active filter only to the mutation handlers that need it.",{"title":425,"searchDepth":426,"depth":426,"links":427},"",2,[428,429,430,431,432,433],{"id":190,"depth":426,"text":191},{"id":276,"depth":426,"text":277},{"id":317,"depth":426,"text":318},{"id":347,"depth":426,"text":348},{"id":365,"depth":426,"text":366},{"id":383,"depth":426,"text":384},"How organization activation gates mutation APIs and why org-scoped APIs use route org IDs.","md",null,{"icon":438},"i-lucide-shield-check",true,{"title":142,"description":434},"NkFvmnTe0dQOieXP9-47nqmkO6qzNEZXdO0JK9vrzgY",[443,445],{"title":138,"path":139,"stem":140,"description":444,"children":-1},"Architecture for organization LLM configuration, encrypted tenant keys, and default LLM clients.",{"title":146,"path":147,"stem":148,"description":446,"icon":149,"children":-1},"How local coding agents upload diffs and run the shared code-review agents through MCP.",1784297365800]