[{"data":1,"prerenderedAt":2507},["ShallowReactive",2],{"navigation_docs":3,"-docs-configuration-gcp-runtime":158,"-docs-configuration-gcp-runtime-surround":2502},[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":80,"body":160,"description":2495,"extension":2496,"links":2497,"meta":2498,"navigation":2499,"path":81,"seo":2500,"stem":82,"__hash__":2501},"docs\u002Fdocs\u002F5.configuration\u002F1.gcp-runtime.md",{"type":161,"value":162,"toc":2484},"minimark",[163,168,193,197,249,253,257,325,329,332,404,407,1210,1214,1217,1220,1224,1559,1563,1566,1569,1590,1597,1747,1751,1762,2008,2022,2035,2079,2086,2101,2108,2112,2201,2205,2223,2325,2328,2387,2394,2410,2433,2436,2480],[164,165,167],"h2",{"id":166},"services","Services",[169,170,171,175,178,181,184,187,190],"ul",{},[172,173,174],"li",{},"KMS",[172,176,177],{},"SQL",[172,179,180],{},"Secret Manager",[172,182,183],{},"Pub\u002FSub",[172,185,186],{},"Cloud Storage",[172,188,189],{},"Cloud Run",[172,191,192],{},"OAuth",[164,194,196],{"id":195},"service-account-roles","Service Account Roles",[198,199,200,213],"table",{},[201,202,203],"thead",{},[204,205,206,210],"tr",{},[207,208,209],"th",{},"Role",[207,211,212],{},"Purpose",[214,215,216,225,233,241],"tbody",{},[204,217,218,222],{},[219,220,221],"td",{},"Cloud KMS Viewer",[219,223,224],{},"Allows the service account to read the KMS key for decrypting secrets.",[204,226,227,230],{},[219,228,229],{},"Cloud SQL Client",[219,231,232],{},"Allows the service account to connect to Cloud SQL instances.",[204,234,235,238],{},[219,236,237],{},"Secret Manager Secret Accessor",[219,239,240],{},"Allows the service account to access secrets stored in Secret Manager.",[204,242,243,246],{},[219,244,245],{},"Pub\u002FSub Editor",[219,247,248],{},"Allows the service account to publish and subscribe to Pub\u002FSub topics.",[164,250,252],{"id":251},"google-oauth","Google OAuth",[254,255,256],"p",{},"Required to allow login with Google",[198,258,259,272],{},[201,260,261],{},[204,262,263,266,269],{},[207,264,265],{},"Settings",[207,267,268],{},"Value",[207,270,271],{},"Description",[214,273,274,285,299,312],{},[204,275,276,279,282],{},[219,277,278],{},"Application type",[219,280,281],{},"Web application",[219,283,284],{},"Select \"Web application\" as the application type.",[204,286,287,290,296],{},[219,288,289],{},"Name",[219,291,292],{},[293,294,295],"code",{},"zeeq-oauth-prod",[219,297,298],{},"Name your application.",[204,300,301,304,309],{},[219,302,303],{},"Authorized JavaScript origins",[219,305,306],{},[293,307,308],{},"https:\u002F\u002Fapp.zeeq.ai",[219,310,311],{},"The web application domain for valid origins",[204,313,314,317,322],{},[219,315,316],{},"Authorized redirect URIs",[219,318,319],{},[293,320,321],{},"https:\u002F\u002Fapp.zeeq.ai\u002Fauth\u002Fcallback\u002Fgoogle",[219,323,324],{},"The post-authorization redirect target",[164,326,328],{"id":327},"secrets-required","Secrets Required",[254,330,331],{},"Several secrets are required for OpenIddict to generate secure tokens.",[333,334,339],"pre",{"className":335,"code":336,"language":337,"meta":338,"style":338},"language-shell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Generate the certificates used for signing the tokens\n.\u002Fbuild\u002Fcerts\u002Fgen-openiddict-certs.sh\n\n# Create the secrets in GCP Secret Manager (use the cert password)\nZEEQ_OPENIDDICT_ENCRYPTION_PASSWORD=\"...\" ZEEQ_OPENIDDICT_SIGNING_PASSWORD=\"...\" .\u002Fbuild\u002Fcerts\u002Fupload-openiddict-secrets.sh\n","shell","",[293,340,341,350,357,364,370],{"__ignoreMap":338},[342,343,346],"span",{"class":344,"line":345},"line",1,[342,347,349],{"class":348},"sHwdD","# Generate the certificates used for signing the tokens\n",[342,351,353],{"class":344,"line":352},2,[342,354,356],{"class":355},"sBMFI",".\u002Fbuild\u002Fcerts\u002Fgen-openiddict-certs.sh\n",[342,358,360],{"class":344,"line":359},3,[342,361,363],{"emptyLinePlaceholder":362},true,"\n",[342,365,367],{"class":344,"line":366},4,[342,368,369],{"class":348},"# Create the secrets in GCP Secret Manager (use the cert password)\n",[342,371,373,377,381,384,388,390,393,395,397,399,401],{"class":344,"line":372},5,[342,374,376],{"class":375},"sTEyZ","ZEEQ_OPENIDDICT_ENCRYPTION_PASSWORD",[342,378,380],{"class":379},"sMK4o","=",[342,382,383],{"class":379},"\"",[342,385,387],{"class":386},"sfazB","...",[342,389,383],{"class":379},[342,391,392],{"class":375}," ZEEQ_OPENIDDICT_SIGNING_PASSWORD",[342,394,380],{"class":379},[342,396,383],{"class":379},[342,398,387],{"class":386},[342,400,383],{"class":379},[342,402,403],{"class":355}," .\u002Fbuild\u002Fcerts\u002Fupload-openiddict-secrets.sh\n",[254,405,406],{},"Additional secrets:",[333,408,410],{"className":335,"code":409,"language":337,"meta":338,"style":338},"# The GitHub App Private Key (PEM); used to access GitHub API as app.\nprintf \"SECRET_VALUE\" | gcloud secrets create AppSettings__GitHub__PrivateKeyPem \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# The GitHub App Webhook Secret (used to validate the incoming webhook requests)\nprintf \"SECRET_VALUE\" | gcloud secrets create AppSettings__GitHub__WebhookSecret \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# Used when encrypting the contents of the review request link.\nopenssl rand -base64 48 | tr -d '\\n' | \\\n  gcloud secrets create AppSettings__CodeReview__ReviewRequestLinkEncryptionKey \\\n    --replication-policy=automatic \\\n    --data-file=- \\\n    --project=$GCP_PROJECT_ID\n\n# Used to sign Zeeq library export packages before they can be imported.\nopenssl rand -base64 48 | tr -d '\\n' | \\\n  gcloud secrets create AppSettings__Documents__LibraryExportSigningKey \\\n    --replication-policy=automatic \\\n    --data-file=- \\\n    --project=$GCP_PROJECT_ID\n\n# System-admin allow-list entry in provider:subject format. Create as empty and\n# Then update after the first accounts are created.\nprintf \"SECRET_VALUE\" | gcloud secrets create AppSettings__Platform__SystemAdminSubjects__0 \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# Default Fireworks API Key for the LLM model. The default model is Fireworks GLM 5.2\n# (accounts\u002Ffireworks\u002Fmodels\u002Fglm-5p2). High and Max tiers inherit the Fast key when blank.\nprintf \"SECRET_VALUE\" | gcloud secrets create AppSettings__Llm__Models__Fast__ApiKey \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# Fireworks API key for snippet embeddings (separate from the chat-completion key —\n# different model, and rotated independently since only the sweep and the search API use it).\nprintf \"SECRET_VALUE\" | gcloud secrets create AppSettings__Llm__Embeddings__ApiKey \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# Auth client secret for Google OAuth (login)\nprintf \"SECRET_VALUE\" | gcloud secrets create AppSettings__Auth__Providers__0__ClientSecret \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# Auth client secret for GitHub OAuth (login)\nprintf \"SECRET_VALUE\" | gcloud secrets create AppSettings__Auth__Providers__1__ClientSecret \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# The database connection string for the production database\n# Host=\u002Fcloudsql\u002Fzeeq-ai-prod:us-central1:zeeq-pg-prod;Database=zeeq;Username=zeeq-app;Password=\u003Cpassword>;SSL Mode=Prefer;Pooling=true;Maximum Pool Size=20;Include Error Detail=true\nprintf \"SECRET_VALUE\" | gcloud secrets create AppSettings__Database__ConnectionString \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# OTEL API key (e.g. Datadog, Honeycomb) injected as header. e.g.: `x-honeycomb-team=abc1234...`\nprintf \"SECRET_VALUE\" | gcloud secrets create zeeq-otel-api-key-header \\\n  --replication-policy=\"automatic\" \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n\n# (Updating a secret)\nprintf \"SECRET_VALUE\" | gcloud secrets versions add AppSettings__Llm__Models__Fast__ApiKey \\\n  --data-file=- \\\n  --project=$GCP_PROJECT_ID\n",[293,411,412,417,449,463,470,478,483,489,513,526,533,540,545,551,588,603,611,619,627,632,638,665,679,686,693,700,705,711,717,741,754,761,768,773,779,785,809,822,829,836,841,847,853,877,890,897,904,909,915,939,952,959,966,971,977,1001,1014,1021,1028,1033,1039,1045,1069,1082,1089,1096,1101,1107,1131,1144,1151,1158,1163,1169,1196,1203],{"__ignoreMap":338},[342,413,414],{"class":344,"line":345},[342,415,416],{"class":348},"# The GitHub App Private Key (PEM); used to access GitHub API as app.\n",[342,418,419,423,426,429,431,434,437,440,443,446],{"class":344,"line":352},[342,420,422],{"class":421},"s2Zo4","printf",[342,424,425],{"class":379}," \"",[342,427,428],{"class":386},"SECRET_VALUE",[342,430,383],{"class":379},[342,432,433],{"class":379}," |",[342,435,436],{"class":355}," gcloud",[342,438,439],{"class":386}," secrets",[342,441,442],{"class":386}," create",[342,444,445],{"class":386}," AppSettings__GitHub__PrivateKeyPem",[342,447,448],{"class":375}," \\\n",[342,450,451,454,456,459,461],{"class":344,"line":359},[342,452,453],{"class":386},"  --replication-policy=",[342,455,383],{"class":379},[342,457,458],{"class":386},"automatic",[342,460,383],{"class":379},[342,462,448],{"class":375},[342,464,465,468],{"class":344,"line":366},[342,466,467],{"class":386},"  --data-file=-",[342,469,448],{"class":375},[342,471,472,475],{"class":344,"line":372},[342,473,474],{"class":386},"  --project=",[342,476,477],{"class":375},"$GCP_PROJECT_ID\n",[342,479,481],{"class":344,"line":480},6,[342,482,363],{"emptyLinePlaceholder":362},[342,484,486],{"class":344,"line":485},7,[342,487,488],{"class":348},"# The GitHub App Webhook Secret (used to validate the incoming webhook requests)\n",[342,490,492,494,496,498,500,502,504,506,508,511],{"class":344,"line":491},8,[342,493,422],{"class":421},[342,495,425],{"class":379},[342,497,428],{"class":386},[342,499,383],{"class":379},[342,501,433],{"class":379},[342,503,436],{"class":355},[342,505,439],{"class":386},[342,507,442],{"class":386},[342,509,510],{"class":386}," AppSettings__GitHub__WebhookSecret",[342,512,448],{"class":375},[342,514,516,518,520,522,524],{"class":344,"line":515},9,[342,517,453],{"class":386},[342,519,383],{"class":379},[342,521,458],{"class":386},[342,523,383],{"class":379},[342,525,448],{"class":375},[342,527,529,531],{"class":344,"line":528},10,[342,530,467],{"class":386},[342,532,448],{"class":375},[342,534,536,538],{"class":344,"line":535},11,[342,537,474],{"class":386},[342,539,477],{"class":375},[342,541,543],{"class":344,"line":542},12,[342,544,363],{"emptyLinePlaceholder":362},[342,546,548],{"class":344,"line":547},13,[342,549,550],{"class":348},"# Used when encrypting the contents of the review request link.\n",[342,552,554,557,560,563,567,569,572,575,578,581,584,586],{"class":344,"line":553},14,[342,555,556],{"class":355},"openssl",[342,558,559],{"class":386}," rand",[342,561,562],{"class":386}," -base64",[342,564,566],{"class":565},"sbssI"," 48",[342,568,433],{"class":379},[342,570,571],{"class":355}," tr",[342,573,574],{"class":386}," -d",[342,576,577],{"class":379}," '",[342,579,580],{"class":386},"\\n",[342,582,583],{"class":379},"'",[342,585,433],{"class":379},[342,587,448],{"class":375},[342,589,591,594,596,598,601],{"class":344,"line":590},15,[342,592,593],{"class":355},"  gcloud",[342,595,439],{"class":386},[342,597,442],{"class":386},[342,599,600],{"class":386}," AppSettings__CodeReview__ReviewRequestLinkEncryptionKey",[342,602,448],{"class":375},[342,604,606,609],{"class":344,"line":605},16,[342,607,608],{"class":386},"    --replication-policy=automatic",[342,610,448],{"class":375},[342,612,614,617],{"class":344,"line":613},17,[342,615,616],{"class":386},"    --data-file=-",[342,618,448],{"class":375},[342,620,622,625],{"class":344,"line":621},18,[342,623,624],{"class":386},"    --project=",[342,626,477],{"class":375},[342,628,630],{"class":344,"line":629},19,[342,631,363],{"emptyLinePlaceholder":362},[342,633,635],{"class":344,"line":634},20,[342,636,637],{"class":348},"# Used to sign Zeeq library export packages before they can be imported.\n",[342,639,641,643,645,647,649,651,653,655,657,659,661,663],{"class":344,"line":640},21,[342,642,556],{"class":355},[342,644,559],{"class":386},[342,646,562],{"class":386},[342,648,566],{"class":565},[342,650,433],{"class":379},[342,652,571],{"class":355},[342,654,574],{"class":386},[342,656,577],{"class":379},[342,658,580],{"class":386},[342,660,583],{"class":379},[342,662,433],{"class":379},[342,664,448],{"class":375},[342,666,668,670,672,674,677],{"class":344,"line":667},22,[342,669,593],{"class":355},[342,671,439],{"class":386},[342,673,442],{"class":386},[342,675,676],{"class":386}," AppSettings__Documents__LibraryExportSigningKey",[342,678,448],{"class":375},[342,680,682,684],{"class":344,"line":681},23,[342,683,608],{"class":386},[342,685,448],{"class":375},[342,687,689,691],{"class":344,"line":688},24,[342,690,616],{"class":386},[342,692,448],{"class":375},[342,694,696,698],{"class":344,"line":695},25,[342,697,624],{"class":386},[342,699,477],{"class":375},[342,701,703],{"class":344,"line":702},26,[342,704,363],{"emptyLinePlaceholder":362},[342,706,708],{"class":344,"line":707},27,[342,709,710],{"class":348},"# System-admin allow-list entry in provider:subject format. Create as empty and\n",[342,712,714],{"class":344,"line":713},28,[342,715,716],{"class":348},"# Then update after the first accounts are created.\n",[342,718,720,722,724,726,728,730,732,734,736,739],{"class":344,"line":719},29,[342,721,422],{"class":421},[342,723,425],{"class":379},[342,725,428],{"class":386},[342,727,383],{"class":379},[342,729,433],{"class":379},[342,731,436],{"class":355},[342,733,439],{"class":386},[342,735,442],{"class":386},[342,737,738],{"class":386}," AppSettings__Platform__SystemAdminSubjects__0",[342,740,448],{"class":375},[342,742,744,746,748,750,752],{"class":344,"line":743},30,[342,745,453],{"class":386},[342,747,383],{"class":379},[342,749,458],{"class":386},[342,751,383],{"class":379},[342,753,448],{"class":375},[342,755,757,759],{"class":344,"line":756},31,[342,758,467],{"class":386},[342,760,448],{"class":375},[342,762,764,766],{"class":344,"line":763},32,[342,765,474],{"class":386},[342,767,477],{"class":375},[342,769,771],{"class":344,"line":770},33,[342,772,363],{"emptyLinePlaceholder":362},[342,774,776],{"class":344,"line":775},34,[342,777,778],{"class":348},"# Default Fireworks API Key for the LLM model. The default model is Fireworks GLM 5.2\n",[342,780,782],{"class":344,"line":781},35,[342,783,784],{"class":348},"# (accounts\u002Ffireworks\u002Fmodels\u002Fglm-5p2). High and Max tiers inherit the Fast key when blank.\n",[342,786,788,790,792,794,796,798,800,802,804,807],{"class":344,"line":787},36,[342,789,422],{"class":421},[342,791,425],{"class":379},[342,793,428],{"class":386},[342,795,383],{"class":379},[342,797,433],{"class":379},[342,799,436],{"class":355},[342,801,439],{"class":386},[342,803,442],{"class":386},[342,805,806],{"class":386}," AppSettings__Llm__Models__Fast__ApiKey",[342,808,448],{"class":375},[342,810,812,814,816,818,820],{"class":344,"line":811},37,[342,813,453],{"class":386},[342,815,383],{"class":379},[342,817,458],{"class":386},[342,819,383],{"class":379},[342,821,448],{"class":375},[342,823,825,827],{"class":344,"line":824},38,[342,826,467],{"class":386},[342,828,448],{"class":375},[342,830,832,834],{"class":344,"line":831},39,[342,833,474],{"class":386},[342,835,477],{"class":375},[342,837,839],{"class":344,"line":838},40,[342,840,363],{"emptyLinePlaceholder":362},[342,842,844],{"class":344,"line":843},41,[342,845,846],{"class":348},"# Fireworks API key for snippet embeddings (separate from the chat-completion key —\n",[342,848,850],{"class":344,"line":849},42,[342,851,852],{"class":348},"# different model, and rotated independently since only the sweep and the search API use it).\n",[342,854,856,858,860,862,864,866,868,870,872,875],{"class":344,"line":855},43,[342,857,422],{"class":421},[342,859,425],{"class":379},[342,861,428],{"class":386},[342,863,383],{"class":379},[342,865,433],{"class":379},[342,867,436],{"class":355},[342,869,439],{"class":386},[342,871,442],{"class":386},[342,873,874],{"class":386}," AppSettings__Llm__Embeddings__ApiKey",[342,876,448],{"class":375},[342,878,880,882,884,886,888],{"class":344,"line":879},44,[342,881,453],{"class":386},[342,883,383],{"class":379},[342,885,458],{"class":386},[342,887,383],{"class":379},[342,889,448],{"class":375},[342,891,893,895],{"class":344,"line":892},45,[342,894,467],{"class":386},[342,896,448],{"class":375},[342,898,900,902],{"class":344,"line":899},46,[342,901,474],{"class":386},[342,903,477],{"class":375},[342,905,907],{"class":344,"line":906},47,[342,908,363],{"emptyLinePlaceholder":362},[342,910,912],{"class":344,"line":911},48,[342,913,914],{"class":348},"# Auth client secret for Google OAuth (login)\n",[342,916,918,920,922,924,926,928,930,932,934,937],{"class":344,"line":917},49,[342,919,422],{"class":421},[342,921,425],{"class":379},[342,923,428],{"class":386},[342,925,383],{"class":379},[342,927,433],{"class":379},[342,929,436],{"class":355},[342,931,439],{"class":386},[342,933,442],{"class":386},[342,935,936],{"class":386}," AppSettings__Auth__Providers__0__ClientSecret",[342,938,448],{"class":375},[342,940,942,944,946,948,950],{"class":344,"line":941},50,[342,943,453],{"class":386},[342,945,383],{"class":379},[342,947,458],{"class":386},[342,949,383],{"class":379},[342,951,448],{"class":375},[342,953,955,957],{"class":344,"line":954},51,[342,956,467],{"class":386},[342,958,448],{"class":375},[342,960,962,964],{"class":344,"line":961},52,[342,963,474],{"class":386},[342,965,477],{"class":375},[342,967,969],{"class":344,"line":968},53,[342,970,363],{"emptyLinePlaceholder":362},[342,972,974],{"class":344,"line":973},54,[342,975,976],{"class":348},"# Auth client secret for GitHub OAuth (login)\n",[342,978,980,982,984,986,988,990,992,994,996,999],{"class":344,"line":979},55,[342,981,422],{"class":421},[342,983,425],{"class":379},[342,985,428],{"class":386},[342,987,383],{"class":379},[342,989,433],{"class":379},[342,991,436],{"class":355},[342,993,439],{"class":386},[342,995,442],{"class":386},[342,997,998],{"class":386}," AppSettings__Auth__Providers__1__ClientSecret",[342,1000,448],{"class":375},[342,1002,1004,1006,1008,1010,1012],{"class":344,"line":1003},56,[342,1005,453],{"class":386},[342,1007,383],{"class":379},[342,1009,458],{"class":386},[342,1011,383],{"class":379},[342,1013,448],{"class":375},[342,1015,1017,1019],{"class":344,"line":1016},57,[342,1018,467],{"class":386},[342,1020,448],{"class":375},[342,1022,1024,1026],{"class":344,"line":1023},58,[342,1025,474],{"class":386},[342,1027,477],{"class":375},[342,1029,1031],{"class":344,"line":1030},59,[342,1032,363],{"emptyLinePlaceholder":362},[342,1034,1036],{"class":344,"line":1035},60,[342,1037,1038],{"class":348},"# The database connection string for the production database\n",[342,1040,1042],{"class":344,"line":1041},61,[342,1043,1044],{"class":348},"# Host=\u002Fcloudsql\u002Fzeeq-ai-prod:us-central1:zeeq-pg-prod;Database=zeeq;Username=zeeq-app;Password=\u003Cpassword>;SSL Mode=Prefer;Pooling=true;Maximum Pool Size=20;Include Error Detail=true\n",[342,1046,1048,1050,1052,1054,1056,1058,1060,1062,1064,1067],{"class":344,"line":1047},62,[342,1049,422],{"class":421},[342,1051,425],{"class":379},[342,1053,428],{"class":386},[342,1055,383],{"class":379},[342,1057,433],{"class":379},[342,1059,436],{"class":355},[342,1061,439],{"class":386},[342,1063,442],{"class":386},[342,1065,1066],{"class":386}," AppSettings__Database__ConnectionString",[342,1068,448],{"class":375},[342,1070,1072,1074,1076,1078,1080],{"class":344,"line":1071},63,[342,1073,453],{"class":386},[342,1075,383],{"class":379},[342,1077,458],{"class":386},[342,1079,383],{"class":379},[342,1081,448],{"class":375},[342,1083,1085,1087],{"class":344,"line":1084},64,[342,1086,467],{"class":386},[342,1088,448],{"class":375},[342,1090,1092,1094],{"class":344,"line":1091},65,[342,1093,474],{"class":386},[342,1095,477],{"class":375},[342,1097,1099],{"class":344,"line":1098},66,[342,1100,363],{"emptyLinePlaceholder":362},[342,1102,1104],{"class":344,"line":1103},67,[342,1105,1106],{"class":348},"# OTEL API key (e.g. Datadog, Honeycomb) injected as header. e.g.: `x-honeycomb-team=abc1234...`\n",[342,1108,1110,1112,1114,1116,1118,1120,1122,1124,1126,1129],{"class":344,"line":1109},68,[342,1111,422],{"class":421},[342,1113,425],{"class":379},[342,1115,428],{"class":386},[342,1117,383],{"class":379},[342,1119,433],{"class":379},[342,1121,436],{"class":355},[342,1123,439],{"class":386},[342,1125,442],{"class":386},[342,1127,1128],{"class":386}," zeeq-otel-api-key-header",[342,1130,448],{"class":375},[342,1132,1134,1136,1138,1140,1142],{"class":344,"line":1133},69,[342,1135,453],{"class":386},[342,1137,383],{"class":379},[342,1139,458],{"class":386},[342,1141,383],{"class":379},[342,1143,448],{"class":375},[342,1145,1147,1149],{"class":344,"line":1146},70,[342,1148,467],{"class":386},[342,1150,448],{"class":375},[342,1152,1154,1156],{"class":344,"line":1153},71,[342,1155,474],{"class":386},[342,1157,477],{"class":375},[342,1159,1161],{"class":344,"line":1160},72,[342,1162,363],{"emptyLinePlaceholder":362},[342,1164,1166],{"class":344,"line":1165},73,[342,1167,1168],{"class":348},"# (Updating a secret)\n",[342,1170,1172,1174,1176,1178,1180,1182,1184,1186,1189,1192,1194],{"class":344,"line":1171},74,[342,1173,422],{"class":421},[342,1175,425],{"class":379},[342,1177,428],{"class":386},[342,1179,383],{"class":379},[342,1181,433],{"class":379},[342,1183,436],{"class":355},[342,1185,439],{"class":386},[342,1187,1188],{"class":386}," versions",[342,1190,1191],{"class":386}," add",[342,1193,806],{"class":386},[342,1195,448],{"class":375},[342,1197,1199,1201],{"class":344,"line":1198},75,[342,1200,467],{"class":386},[342,1202,448],{"class":375},[342,1204,1206,1208],{"class":344,"line":1205},76,[342,1207,474],{"class":386},[342,1209,477],{"class":375},[164,1211,1213],{"id":1212},"kms-setup","KMS Setup",[254,1215,1216],{},"KMS is used to manage encryption and decryption of user-entered API keys and secrets.",[254,1218,1219],{},"This ensures that secrets are securely encrypted at rest and can be rotated as needed.",[1221,1222,1223],"note",{},"Ensure that the service account is already provisioned.",[333,1225,1227],{"className":335,"code":1226,"language":337,"meta":338,"style":338},"# GCP_RUNTIME_SA=... .\u002Fbuild\u002Finit\u002Fgcp-kms.sh\nPROJECT=$GCP_PROJECT_ID # Set in .config\u002Fmise.toml\nRUNTIME_SA=$GCP_RUNTIME_SA # Set via env var\nREGION=us-central1\nKEYRING=zeeq-runtime\nKEY=zeeq-llm-secrets\n\ngcloud services enable cloudkms.googleapis.com \\\n  --project=\"$PROJECT\"\n\ngcloud kms keyrings create \"$KEYRING\" \\\n  --location=\"$REGION\" \\\n  --project=\"$PROJECT\"\n\ngcloud kms keys create \"$KEY\" \\\n  --keyring=\"$KEYRING\" \\\n  --location=\"$REGION\" \\\n  --purpose=encryption \\\n  --rotation-period=90d \\\n  --next-rotation-time=\"$(date -u -v+90d '+%Y-%m-%dT%H:%M:%SZ')\" \\\n  --project=\"$PROJECT\"\n\ngcloud kms keys add-iam-policy-binding \"$KEY\" \\\n  --keyring=\"$KEYRING\" \\\n  --location=\"$REGION\" \\\n  --member=\"serviceAccount:${RUNTIME_SA}\" \\\n  --role=\"roles\u002Fcloudkms.cryptoKeyEncrypterDecrypter\" \\\n  --project=\"$PROJECT\"\n\n",[293,1228,1229,1234,1247,1260,1270,1280,1290,1294,1310,1322,1326,1347,1361,1371,1375,1395,1408,1420,1427,1434,1458,1468,1472,1491,1503,1515,1535,1549],{"__ignoreMap":338},[342,1230,1231],{"class":344,"line":345},[342,1232,1233],{"class":348},"# GCP_RUNTIME_SA=... .\u002Fbuild\u002Finit\u002Fgcp-kms.sh\n",[342,1235,1236,1239,1241,1244],{"class":344,"line":352},[342,1237,1238],{"class":375},"PROJECT",[342,1240,380],{"class":379},[342,1242,1243],{"class":375},"$GCP_PROJECT_ID ",[342,1245,1246],{"class":348},"# Set in .config\u002Fmise.toml\n",[342,1248,1249,1252,1254,1257],{"class":344,"line":359},[342,1250,1251],{"class":375},"RUNTIME_SA",[342,1253,380],{"class":379},[342,1255,1256],{"class":375},"$GCP_RUNTIME_SA ",[342,1258,1259],{"class":348},"# Set via env var\n",[342,1261,1262,1265,1267],{"class":344,"line":366},[342,1263,1264],{"class":375},"REGION",[342,1266,380],{"class":379},[342,1268,1269],{"class":386},"us-central1\n",[342,1271,1272,1275,1277],{"class":344,"line":372},[342,1273,1274],{"class":375},"KEYRING",[342,1276,380],{"class":379},[342,1278,1279],{"class":386},"zeeq-runtime\n",[342,1281,1282,1285,1287],{"class":344,"line":480},[342,1283,1284],{"class":375},"KEY",[342,1286,380],{"class":379},[342,1288,1289],{"class":386},"zeeq-llm-secrets\n",[342,1291,1292],{"class":344,"line":485},[342,1293,363],{"emptyLinePlaceholder":362},[342,1295,1296,1299,1302,1305,1308],{"class":344,"line":491},[342,1297,1298],{"class":355},"gcloud",[342,1300,1301],{"class":386}," services",[342,1303,1304],{"class":386}," enable",[342,1306,1307],{"class":386}," cloudkms.googleapis.com",[342,1309,448],{"class":375},[342,1311,1312,1314,1316,1319],{"class":344,"line":515},[342,1313,474],{"class":386},[342,1315,383],{"class":379},[342,1317,1318],{"class":375},"$PROJECT",[342,1320,1321],{"class":379},"\"\n",[342,1323,1324],{"class":344,"line":528},[342,1325,363],{"emptyLinePlaceholder":362},[342,1327,1328,1330,1333,1336,1338,1340,1343,1345],{"class":344,"line":535},[342,1329,1298],{"class":355},[342,1331,1332],{"class":386}," kms",[342,1334,1335],{"class":386}," keyrings",[342,1337,442],{"class":386},[342,1339,425],{"class":379},[342,1341,1342],{"class":375},"$KEYRING",[342,1344,383],{"class":379},[342,1346,448],{"class":375},[342,1348,1349,1352,1354,1357,1359],{"class":344,"line":542},[342,1350,1351],{"class":386},"  --location=",[342,1353,383],{"class":379},[342,1355,1356],{"class":375},"$REGION",[342,1358,383],{"class":379},[342,1360,448],{"class":375},[342,1362,1363,1365,1367,1369],{"class":344,"line":547},[342,1364,474],{"class":386},[342,1366,383],{"class":379},[342,1368,1318],{"class":375},[342,1370,1321],{"class":379},[342,1372,1373],{"class":344,"line":553},[342,1374,363],{"emptyLinePlaceholder":362},[342,1376,1377,1379,1381,1384,1386,1388,1391,1393],{"class":344,"line":590},[342,1378,1298],{"class":355},[342,1380,1332],{"class":386},[342,1382,1383],{"class":386}," keys",[342,1385,442],{"class":386},[342,1387,425],{"class":379},[342,1389,1390],{"class":375},"$KEY",[342,1392,383],{"class":379},[342,1394,448],{"class":375},[342,1396,1397,1400,1402,1404,1406],{"class":344,"line":605},[342,1398,1399],{"class":386},"  --keyring=",[342,1401,383],{"class":379},[342,1403,1342],{"class":375},[342,1405,383],{"class":379},[342,1407,448],{"class":375},[342,1409,1410,1412,1414,1416,1418],{"class":344,"line":613},[342,1411,1351],{"class":386},[342,1413,383],{"class":379},[342,1415,1356],{"class":375},[342,1417,383],{"class":379},[342,1419,448],{"class":375},[342,1421,1422,1425],{"class":344,"line":621},[342,1423,1424],{"class":386},"  --purpose=encryption",[342,1426,448],{"class":375},[342,1428,1429,1432],{"class":344,"line":629},[342,1430,1431],{"class":386},"  --rotation-period=90d",[342,1433,448],{"class":375},[342,1435,1436,1439,1442,1445,1448,1450,1453,1456],{"class":344,"line":634},[342,1437,1438],{"class":386},"  --next-rotation-time=",[342,1440,1441],{"class":379},"\"$(",[342,1443,1444],{"class":355},"date",[342,1446,1447],{"class":386}," -u -v+90d ",[342,1449,583],{"class":379},[342,1451,1452],{"class":386},"+%Y-%m-%dT%H:%M:%SZ",[342,1454,1455],{"class":379},"')\"",[342,1457,448],{"class":375},[342,1459,1460,1462,1464,1466],{"class":344,"line":640},[342,1461,474],{"class":386},[342,1463,383],{"class":379},[342,1465,1318],{"class":375},[342,1467,1321],{"class":379},[342,1469,1470],{"class":344,"line":667},[342,1471,363],{"emptyLinePlaceholder":362},[342,1473,1474,1476,1478,1480,1483,1485,1487,1489],{"class":344,"line":681},[342,1475,1298],{"class":355},[342,1477,1332],{"class":386},[342,1479,1383],{"class":386},[342,1481,1482],{"class":386}," add-iam-policy-binding",[342,1484,425],{"class":379},[342,1486,1390],{"class":375},[342,1488,383],{"class":379},[342,1490,448],{"class":375},[342,1492,1493,1495,1497,1499,1501],{"class":344,"line":688},[342,1494,1399],{"class":386},[342,1496,383],{"class":379},[342,1498,1342],{"class":375},[342,1500,383],{"class":379},[342,1502,448],{"class":375},[342,1504,1505,1507,1509,1511,1513],{"class":344,"line":695},[342,1506,1351],{"class":386},[342,1508,383],{"class":379},[342,1510,1356],{"class":375},[342,1512,383],{"class":379},[342,1514,448],{"class":375},[342,1516,1517,1520,1522,1525,1528,1530,1533],{"class":344,"line":702},[342,1518,1519],{"class":386},"  --member=",[342,1521,383],{"class":379},[342,1523,1524],{"class":386},"serviceAccount:",[342,1526,1527],{"class":379},"${",[342,1529,1251],{"class":375},[342,1531,1532],{"class":379},"}\"",[342,1534,448],{"class":375},[342,1536,1537,1540,1542,1545,1547],{"class":344,"line":707},[342,1538,1539],{"class":386},"  --role=",[342,1541,383],{"class":379},[342,1543,1544],{"class":386},"roles\u002Fcloudkms.cryptoKeyEncrypterDecrypter",[342,1546,383],{"class":379},[342,1548,448],{"class":375},[342,1550,1551,1553,1555,1557],{"class":344,"line":713},[342,1552,474],{"class":386},[342,1554,383],{"class":379},[342,1556,1318],{"class":375},[342,1558,1321],{"class":379},[164,1560,1562],{"id":1561},"cloud-sql","Cloud SQL",[254,1564,1565],{},"Any CloudSQL Postgres configuration is suitable.",[254,1567,1568],{},"Two flags need to be enabled:",[333,1570,1572],{"className":335,"code":1571,"language":337,"meta":338,"style":338},"cloudsql.enable_pg_cron=on\ncron.database_name=zeeq\n",[293,1573,1574,1582],{"__ignoreMap":338},[342,1575,1576,1579],{"class":344,"line":345},[342,1577,1578],{"class":355},"cloudsql.enable_pg_cron",[342,1580,1581],{"class":386},"=on\n",[342,1583,1584,1587],{"class":344,"line":352},[342,1585,1586],{"class":355},"cron.database_name",[342,1588,1589],{"class":386},"=zeeq\n",[254,1591,1592,1593,1596],{},"These flags enable ",[293,1594,1595],{},"pg_partman"," cleanup and self provisioning of partitions to work.",[333,1598,1600],{"className":335,"code":1599,"language":337,"meta":338,"style":338},"# Enable pg_cron extension.\nPROJECT=zeeq-ai-prod\nINSTANCE=zeeq-pg-prod\n\ngcloud sql instances patch \"$INSTANCE\" \\\n  --project=\"$PROJECT\" \\\n  --database-flags=cloudsql.enable_pg_cron=on,cron.database_name=zeeq\n\n# Access\nbrew install cloud-sql-proxy\ngcloud auth application-default login\ngcloud auth login\ngcloud services enable sqladmin.googleapis.com\n\ncloud-sql-proxy \\\n  --port 55432 \\\n  zeeq-ai-prod:us-central1:zeeq-pg-prod\n",[293,1601,1602,1607,1616,1626,1630,1652,1664,1669,1673,1678,1689,1702,1710,1721,1725,1732,1742],{"__ignoreMap":338},[342,1603,1604],{"class":344,"line":345},[342,1605,1606],{"class":348},"# Enable pg_cron extension.\n",[342,1608,1609,1611,1613],{"class":344,"line":352},[342,1610,1238],{"class":375},[342,1612,380],{"class":379},[342,1614,1615],{"class":386},"zeeq-ai-prod\n",[342,1617,1618,1621,1623],{"class":344,"line":359},[342,1619,1620],{"class":375},"INSTANCE",[342,1622,380],{"class":379},[342,1624,1625],{"class":386},"zeeq-pg-prod\n",[342,1627,1628],{"class":344,"line":366},[342,1629,363],{"emptyLinePlaceholder":362},[342,1631,1632,1634,1637,1640,1643,1645,1648,1650],{"class":344,"line":372},[342,1633,1298],{"class":355},[342,1635,1636],{"class":386}," sql",[342,1638,1639],{"class":386}," instances",[342,1641,1642],{"class":386}," patch",[342,1644,425],{"class":379},[342,1646,1647],{"class":375},"$INSTANCE",[342,1649,383],{"class":379},[342,1651,448],{"class":375},[342,1653,1654,1656,1658,1660,1662],{"class":344,"line":480},[342,1655,474],{"class":386},[342,1657,383],{"class":379},[342,1659,1318],{"class":375},[342,1661,383],{"class":379},[342,1663,448],{"class":375},[342,1665,1666],{"class":344,"line":485},[342,1667,1668],{"class":386},"  --database-flags=cloudsql.enable_pg_cron=on,cron.database_name=zeeq\n",[342,1670,1671],{"class":344,"line":491},[342,1672,363],{"emptyLinePlaceholder":362},[342,1674,1675],{"class":344,"line":515},[342,1676,1677],{"class":348},"# Access\n",[342,1679,1680,1683,1686],{"class":344,"line":528},[342,1681,1682],{"class":355},"brew",[342,1684,1685],{"class":386}," install",[342,1687,1688],{"class":386}," cloud-sql-proxy\n",[342,1690,1691,1693,1696,1699],{"class":344,"line":535},[342,1692,1298],{"class":355},[342,1694,1695],{"class":386}," auth",[342,1697,1698],{"class":386}," application-default",[342,1700,1701],{"class":386}," login\n",[342,1703,1704,1706,1708],{"class":344,"line":542},[342,1705,1298],{"class":355},[342,1707,1695],{"class":386},[342,1709,1701],{"class":386},[342,1711,1712,1714,1716,1718],{"class":344,"line":547},[342,1713,1298],{"class":355},[342,1715,1301],{"class":386},[342,1717,1304],{"class":386},[342,1719,1720],{"class":386}," sqladmin.googleapis.com\n",[342,1722,1723],{"class":344,"line":553},[342,1724,363],{"emptyLinePlaceholder":362},[342,1726,1727,1730],{"class":344,"line":590},[342,1728,1729],{"class":355},"cloud-sql-proxy",[342,1731,448],{"class":375},[342,1733,1734,1737,1740],{"class":344,"line":605},[342,1735,1736],{"class":386},"  --port",[342,1738,1739],{"class":565}," 55432",[342,1741,448],{"class":375},[342,1743,1744],{"class":344,"line":613},[342,1745,1746],{"class":386},"  zeeq-ai-prod:us-central1:zeeq-pg-prod\n",[164,1748,1750],{"id":1749},"ingest-workspace-storage","Ingest Workspace Storage",[254,1752,1753,1754,1757,1758,1761],{},"The worker pool clones repositories for repository content ingest under\n",[293,1755,1756],{},"AppSettings__Ingest__ContentRootPath"," — a GCS bucket mounted via Cloud\nStorage FUSE, rather than the OS temp directory local dev uses by default.\n",[293,1759,1760],{},"LocalTempWorkspaceProvider"," needs no code change for this: it already reads\nits workspace root from that setting.",[333,1763,1765],{"className":335,"code":1764,"language":337,"meta":338,"style":338},"# One-time bucket provisioning (.\u002Fbuild\u002Finit\u002Fgcp-storage.sh)\nPROJECT=$GCP_PROJECT_ID # Set in .config\u002Fmise.toml\nRUNTIME_SA=$GCP_RUNTIME_SA # Set via env var\nREGION=us-central1\nBUCKET=\"${PROJECT}-ingest\"\n\ngcloud services enable storage.googleapis.com --project=\"$PROJECT\"\n\ngcloud storage buckets create \"gs:\u002F\u002F${BUCKET}\" \\\n  --project=\"$PROJECT\" \\\n  --location=\"$REGION\" \\\n  --uniform-bucket-level-access\n\n# 3-day lifecycle TTL as a backstop against a workspace surviving a hard\n# process kill mid-run (see build\u002Finit\u002Fgcp-storage.sh for the full rule).\ngcloud storage buckets update \"gs:\u002F\u002F${BUCKET}\" --lifecycle-file=lifecycle.json\n\n# roles\u002Fstorage.objectUser is Google's own documented role for a read-write\n# Cloud Storage volume mount — see the \"Grant access\" section of\n# https:\u002F\u002Fdocs.cloud.google.com\u002Frun\u002Fdocs\u002Fconfiguring\u002Fservices\u002Fcloud-storage-volume-mounts.\ngcloud storage buckets add-iam-policy-binding \"gs:\u002F\u002F${BUCKET}\" \\\n  --member=\"serviceAccount:${RUNTIME_SA}\" \\\n  --role=\"roles\u002Fstorage.objectUser\"\n",[293,1766,1767,1772,1782,1792,1800,1820,1824,1844,1848,1873,1885,1897,1902,1906,1911,1916,1940,1944,1949,1954,1959,1981,1997],{"__ignoreMap":338},[342,1768,1769],{"class":344,"line":345},[342,1770,1771],{"class":348},"# One-time bucket provisioning (.\u002Fbuild\u002Finit\u002Fgcp-storage.sh)\n",[342,1773,1774,1776,1778,1780],{"class":344,"line":352},[342,1775,1238],{"class":375},[342,1777,380],{"class":379},[342,1779,1243],{"class":375},[342,1781,1246],{"class":348},[342,1783,1784,1786,1788,1790],{"class":344,"line":359},[342,1785,1251],{"class":375},[342,1787,380],{"class":379},[342,1789,1256],{"class":375},[342,1791,1259],{"class":348},[342,1793,1794,1796,1798],{"class":344,"line":366},[342,1795,1264],{"class":375},[342,1797,380],{"class":379},[342,1799,1269],{"class":386},[342,1801,1802,1805,1807,1810,1812,1815,1818],{"class":344,"line":372},[342,1803,1804],{"class":375},"BUCKET",[342,1806,380],{"class":379},[342,1808,1809],{"class":379},"\"${",[342,1811,1238],{"class":375},[342,1813,1814],{"class":379},"}",[342,1816,1817],{"class":386},"-ingest",[342,1819,1321],{"class":379},[342,1821,1822],{"class":344,"line":480},[342,1823,363],{"emptyLinePlaceholder":362},[342,1825,1826,1828,1830,1832,1835,1838,1840,1842],{"class":344,"line":485},[342,1827,1298],{"class":355},[342,1829,1301],{"class":386},[342,1831,1304],{"class":386},[342,1833,1834],{"class":386}," storage.googleapis.com",[342,1836,1837],{"class":386}," --project=",[342,1839,383],{"class":379},[342,1841,1318],{"class":375},[342,1843,1321],{"class":379},[342,1845,1846],{"class":344,"line":491},[342,1847,363],{"emptyLinePlaceholder":362},[342,1849,1850,1852,1855,1858,1860,1862,1865,1867,1869,1871],{"class":344,"line":515},[342,1851,1298],{"class":355},[342,1853,1854],{"class":386}," storage",[342,1856,1857],{"class":386}," buckets",[342,1859,442],{"class":386},[342,1861,425],{"class":379},[342,1863,1864],{"class":386},"gs:\u002F\u002F",[342,1866,1527],{"class":379},[342,1868,1804],{"class":375},[342,1870,1532],{"class":379},[342,1872,448],{"class":375},[342,1874,1875,1877,1879,1881,1883],{"class":344,"line":528},[342,1876,474],{"class":386},[342,1878,383],{"class":379},[342,1880,1318],{"class":375},[342,1882,383],{"class":379},[342,1884,448],{"class":375},[342,1886,1887,1889,1891,1893,1895],{"class":344,"line":535},[342,1888,1351],{"class":386},[342,1890,383],{"class":379},[342,1892,1356],{"class":375},[342,1894,383],{"class":379},[342,1896,448],{"class":375},[342,1898,1899],{"class":344,"line":542},[342,1900,1901],{"class":386},"  --uniform-bucket-level-access\n",[342,1903,1904],{"class":344,"line":547},[342,1905,363],{"emptyLinePlaceholder":362},[342,1907,1908],{"class":344,"line":553},[342,1909,1910],{"class":348},"# 3-day lifecycle TTL as a backstop against a workspace surviving a hard\n",[342,1912,1913],{"class":344,"line":590},[342,1914,1915],{"class":348},"# process kill mid-run (see build\u002Finit\u002Fgcp-storage.sh for the full rule).\n",[342,1917,1918,1920,1922,1924,1927,1929,1931,1933,1935,1937],{"class":344,"line":605},[342,1919,1298],{"class":355},[342,1921,1854],{"class":386},[342,1923,1857],{"class":386},[342,1925,1926],{"class":386}," update",[342,1928,425],{"class":379},[342,1930,1864],{"class":386},[342,1932,1527],{"class":379},[342,1934,1804],{"class":375},[342,1936,1532],{"class":379},[342,1938,1939],{"class":386}," --lifecycle-file=lifecycle.json\n",[342,1941,1942],{"class":344,"line":613},[342,1943,363],{"emptyLinePlaceholder":362},[342,1945,1946],{"class":344,"line":621},[342,1947,1948],{"class":348},"# roles\u002Fstorage.objectUser is Google's own documented role for a read-write\n",[342,1950,1951],{"class":344,"line":629},[342,1952,1953],{"class":348},"# Cloud Storage volume mount — see the \"Grant access\" section of\n",[342,1955,1956],{"class":344,"line":634},[342,1957,1958],{"class":348},"# https:\u002F\u002Fdocs.cloud.google.com\u002Frun\u002Fdocs\u002Fconfiguring\u002Fservices\u002Fcloud-storage-volume-mounts.\n",[342,1960,1961,1963,1965,1967,1969,1971,1973,1975,1977,1979],{"class":344,"line":640},[342,1962,1298],{"class":355},[342,1964,1854],{"class":386},[342,1966,1857],{"class":386},[342,1968,1482],{"class":386},[342,1970,425],{"class":379},[342,1972,1864],{"class":386},[342,1974,1527],{"class":379},[342,1976,1804],{"class":375},[342,1978,1532],{"class":379},[342,1980,448],{"class":375},[342,1982,1983,1985,1987,1989,1991,1993,1995],{"class":344,"line":667},[342,1984,1519],{"class":386},[342,1986,383],{"class":379},[342,1988,1524],{"class":386},[342,1990,1527],{"class":379},[342,1992,1251],{"class":375},[342,1994,1532],{"class":379},[342,1996,448],{"class":375},[342,1998,1999,2001,2003,2006],{"class":344,"line":681},[342,2000,1539],{"class":386},[342,2002,383],{"class":379},[342,2004,2005],{"class":386},"roles\u002Fstorage.objectUser",[342,2007,1321],{"class":379},[2009,2010,2012,2013,2017,2018,2021],"callout",{"icon":2011},"i-lucide-alert-triangle","This bucket is a ",[2014,2015,2016],"strong",{},"single shared namespace across every organization's\nprivate-source clones"," — paths are scoped by org+library only at the\napplication layer (",[293,2019,2020],{},"LocalTempWorkspaceProvider.ResolveWorkspacePath","), not by\nGCS IAM, which has no native per-prefix authorization.",[254,2023,2024,2027,2028,2031,2032,2034],{},[293,2025,2026],{},"build\u002Fship-worker.sh"," mounts this bucket at ",[293,2029,2030],{},"\u002Fmnt\u002Fingest"," and points\n",[293,2033,1756],{}," there:",[333,2036,2038],{"className":335,"code":2037,"language":337,"meta":338,"style":338},"--add-volume=\"name=ingest,type=cloud-storage,bucket=${ZEEQ_INGEST_BUCKET}\" \\\n--add-volume-mount=\"volume=ingest,mount-path=${ZEEQ_INGEST_MOUNT_PATH}\"\n",[293,2039,2040,2061],{"__ignoreMap":338},[342,2041,2042,2045,2047,2049,2052,2054,2057,2059],{"class":344,"line":345},[342,2043,2044],{"class":375},"--add-volume",[342,2046,380],{"class":379},[342,2048,383],{"class":379},[342,2050,2051],{"class":386},"name=ingest,type=cloud-storage,bucket=",[342,2053,1527],{"class":379},[342,2055,2056],{"class":375},"ZEEQ_INGEST_BUCKET",[342,2058,1532],{"class":379},[342,2060,448],{"class":355},[342,2062,2063,2066,2068,2071,2073,2076],{"class":344,"line":352},[342,2064,2065],{"class":375},"--add-volume-mount=",[342,2067,383],{"class":379},[342,2069,2070],{"class":386},"volume=ingest,mount-path=",[342,2072,1527],{"class":379},[342,2074,2075],{"class":375},"ZEEQ_INGEST_MOUNT_PATH",[342,2077,2078],{"class":379},"}\"\n",[254,2080,2081,2082,2085],{},"Only the worker pool mounts this bucket — the web service never runs the\ningest pipeline, so ",[293,2083,2084],{},"ship.sh"," is unaffected.",[2009,2087,2089,2092,2093,2096,2097,2100],{"icon":2088},"i-lucide-info",[293,2090,2091],{},"ZeeqIngestWorkspaceStartupCheck"," (a hosted service registered only by\n",[293,2094,2095],{},"ZeeqWorkerHost",", before message-consumer registration) runs a synthetic\nwrite\u002Fread\u002Fdelete against the configured ",[293,2098,2099],{},"Ingest.ContentRootPath"," before the\nworker starts consuming any messages — a broken mount (wrong path, missing\nvolume, an IAM permission gap) fails loud at startup and crash-loops the\nCloud Run worker instance.",[2009,2102,2103,2104,2107],{"icon":2088},"Each ingest run still deletes its own workspace directory on dispose,\nregardless of storage medium (",[293,2105,2106],{},"LocalIngestWorkspace","'s local-temp semantics\nare unchanged) — a repeat sync re-clones rather than reuses a prior pull.",[164,2109,2111],{"id":2110},"diagnostic-logging","Diagnostic Logging",[333,2113,2115],{"className":335,"code":2114,"language":337,"meta":338,"style":338},"# Tail the logs of the Cloud Run web service\ngcloud run services logs tail zeeq-runtime \\\n  --project zeeq-ai-prod \\\n  --region us-central1\n\n# Tail the logs of the Cloud Run worker\ngcloud run worker-pools logs tail zeeq-worker \\\n  --project zeeq-ai-prod \\\n  --region us-central1\n",[293,2116,2117,2122,2142,2152,2160,2164,2169,2187,2195],{"__ignoreMap":338},[342,2118,2119],{"class":344,"line":345},[342,2120,2121],{"class":348},"# Tail the logs of the Cloud Run web service\n",[342,2123,2124,2126,2129,2131,2134,2137,2140],{"class":344,"line":352},[342,2125,1298],{"class":355},[342,2127,2128],{"class":386}," run",[342,2130,1301],{"class":386},[342,2132,2133],{"class":386}," logs",[342,2135,2136],{"class":386}," tail",[342,2138,2139],{"class":386}," zeeq-runtime",[342,2141,448],{"class":375},[342,2143,2144,2147,2150],{"class":344,"line":359},[342,2145,2146],{"class":386},"  --project",[342,2148,2149],{"class":386}," zeeq-ai-prod",[342,2151,448],{"class":375},[342,2153,2154,2157],{"class":344,"line":366},[342,2155,2156],{"class":386},"  --region",[342,2158,2159],{"class":386}," us-central1\n",[342,2161,2162],{"class":344,"line":372},[342,2163,363],{"emptyLinePlaceholder":362},[342,2165,2166],{"class":344,"line":480},[342,2167,2168],{"class":348},"# Tail the logs of the Cloud Run worker\n",[342,2170,2171,2173,2175,2178,2180,2182,2185],{"class":344,"line":485},[342,2172,1298],{"class":355},[342,2174,2128],{"class":386},[342,2176,2177],{"class":386}," worker-pools",[342,2179,2133],{"class":386},[342,2181,2136],{"class":386},[342,2183,2184],{"class":386}," zeeq-worker",[342,2186,448],{"class":375},[342,2188,2189,2191,2193],{"class":344,"line":491},[342,2190,2146],{"class":386},[342,2192,2149],{"class":386},[342,2194,448],{"class":375},[342,2196,2197,2199],{"class":344,"line":515},[342,2198,2156],{"class":386},[342,2200,2159],{"class":386},[164,2202,2204],{"id":2203},"cloud-run-runtime-roles","Cloud Run Runtime Roles",[254,2206,2207,2208,2211,2212,2215,2216,2219,2220,2222],{},"Zeeq uses the same container image for the HTTP web runtime and the background worker runtime. The process behavior is selected with environment variables. ",[293,2209,2210],{},"ZEEQ_MESSAGING_ROLE"," is required so a production web service cannot accidentally start consumers when the role is omitted. Production Cloud Run deployments also run with the GCP Pub\u002FSub transport, so the Pub\u002FSub project id must be available before startup topology reconciliation runs. The deployment scripts pass the explicit ",[293,2213,2214],{},"ZeeqMessaging__GcpPubSub__ProjectId"," setting from ",[293,2217,2218],{},"GCP_PROJECT_ID"," and also set ",[293,2221,2218],{}," for fallback resolution.",[198,2224,2225,2237],{},[201,2226,2227],{},[204,2228,2229,2232,2235],{},[207,2230,2231],{},"Setting",[207,2233,2234],{},"Values",[207,2236,212],{},[214,2238,2239,2264,2284,2299,2314],{},[204,2240,2241,2246,2255],{},[219,2242,2243],{},[293,2244,2245],{},"ZEEQ_RUN_MODE",[219,2247,2248,2251,2252],{},[293,2249,2250],{},"web",", ",[293,2253,2254],{},"worker",[219,2256,2257,2258,2260,2261,2263],{},"Selects the host shape. ",[293,2259,2250],{}," starts ASP.NET Core; ",[293,2262,2254],{}," starts the generic-host worker without HTTP middleware.",[204,2265,2266,2270,2281],{},[219,2267,2268],{},[293,2269,2210],{},[219,2271,2272,2251,2275,2251,2278],{},[293,2273,2274],{},"producer",[293,2276,2277],{},"consumer",[293,2279,2280],{},"producer-consumer",[219,2282,2283],{},"Selects which Brighter messaging services the process registers.",[204,2285,2286,2291,2296],{},[219,2287,2288],{},[293,2289,2290],{},"ZeeqMessaging__Provider",[219,2292,2293],{},[293,2294,2295],{},"GcpPubSub",[219,2297,2298],{},"Selects the production messaging transport. CI forces Postgres regardless of this setting.",[204,2300,2301,2305,2308],{},[219,2302,2303],{},[293,2304,2214],{},[219,2306,2307],{},"GCP project id",[219,2309,2310,2311,2313],{},"Required when the provider is ",[293,2312,2295],{},"; used to create and validate topics and subscriptions.",[204,2315,2316,2320,2322],{},[219,2317,2318],{},[293,2319,2218],{},[219,2321,2307],{},[219,2323,2324],{},"Passed by the deployment scripts and used as a runtime fallback for Pub\u002FSub project resolution.",[254,2326,2327],{},"Production uses two Cloud Run runtimes:",[198,2329,2330,2343],{},[201,2331,2332],{},[204,2333,2334,2337,2340],{},[207,2335,2336],{},"Runtime",[207,2338,2339],{},"Required env vars",[207,2341,2342],{},"Behavior",[214,2344,2345,2367],{},[204,2346,2347,2350,2364],{},[219,2348,2349],{},"Web service",[219,2351,2352,2251,2355,2251,2358,2251,2361],{},[293,2353,2354],{},"ZEEQ_RUN_MODE=web",[293,2356,2357],{},"ZEEQ_MESSAGING_ROLE=producer",[293,2359,2360],{},"ZeeqMessaging__Provider=GcpPubSub",[293,2362,2363],{},"ZeeqMessaging__GcpPubSub__ProjectId=$GCP_PROJECT_ID",[219,2365,2366],{},"Accepts HTTP traffic and publishes messages only.",[204,2368,2369,2372,2384],{},[219,2370,2371],{},"Worker pool",[219,2373,2374,2251,2377,2251,2380,2251,2382],{},[293,2375,2376],{},"ZEEQ_RUN_MODE=worker",[293,2378,2379],{},"ZEEQ_MESSAGING_ROLE=producer-consumer",[293,2381,2360],{},[293,2383,2363],{},[219,2385,2386],{},"Runs message consumers and can publish follow-up messages from handlers.",[254,2388,2389,2390,2393],{},"Only the web service mounts the OpenIddict certificate ",[293,2391,2392],{},".pfx"," secrets as files. Cloud Run worker pools do not support Secret Manager volume mounts, and worker mode exits before ASP.NET Core\u002FOpenIddict setup.",[254,2395,2396,2397,2399,2400,2403,2404,2406,2407,2409],{},"The local Aspire app uses ",[293,2398,2379],{}," for the single-process development shape. When ",[293,2401,2402],{},"ZEEQ_ASPIRE_MODE=split",", the web resource switches to ",[293,2405,2274],{}," and the worker resource uses ",[293,2408,2280],{},".",[254,2411,2412,2414,2415,2418,2419,2422,2423,2425,2426,2428,2429,2432],{},[293,2413,2218],{}," defaults to ",[293,2416,2417],{},"zeeq-ai-prod"," in ",[293,2420,2421],{},"build\u002Fship.sh"," and ",[293,2424,2026],{}," when it is not set by the caller. Set ",[293,2427,2218],{}," explicitly before running ",[293,2430,2431],{},"build\u002Fsend.sh"," to deploy the same image to another project.",[254,2434,2435],{},"Deployment scripts:",[198,2437,2438,2447],{},[201,2439,2440],{},[204,2441,2442,2445],{},[207,2443,2444],{},"Script",[207,2446,2336],{},[214,2448,2449,2460,2471],{},[204,2450,2451,2455],{},[219,2452,2453],{},[293,2454,2421],{},[219,2456,2457,2458,2409],{},"Deploys the production web service as ",[293,2459,2274],{},[204,2461,2462,2466],{},[219,2463,2464],{},[293,2465,2026],{},[219,2467,2468,2469,2409],{},"Deploys the production worker pool as ",[293,2470,2280],{},[204,2472,2473,2477],{},[219,2474,2475],{},[293,2476,2431],{},[219,2478,2479],{},"Builds\u002Fpushes the image and deploys both runtimes.",[2481,2482,2483],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":338,"searchDepth":352,"depth":352,"links":2485},[2486,2487,2488,2489,2490,2491,2492,2493,2494],{"id":166,"depth":352,"text":167},{"id":195,"depth":352,"text":196},{"id":251,"depth":352,"text":252},{"id":327,"depth":352,"text":328},{"id":1212,"depth":352,"text":1213},{"id":1561,"depth":352,"text":1562},{"id":1749,"depth":352,"text":1750},{"id":2110,"depth":352,"text":2111},{"id":2203,"depth":352,"text":2204},"How to configure Zeeq to run on Google Cloud Platform (GCP).","md",null,{},{"icon":83},{"title":80,"description":2495},"72RLZlVZQMsM3qhCEp2EoULqv3t1DA9xRq0jEN-vr6Y",[2503,2505],{"title":70,"path":71,"stem":72,"description":2504,"icon":73,"children":-1},"Mark operational or informational documents so code-review agents never consult them, while interactive tools keep full visibility.",{"title":85,"path":86,"stem":87,"description":2506,"icon":88,"children":-1},"How to configure Zeeq to run on GitHub.",1784297365800]