{"openapi":"3.1.0","info":{"title":"Graphify Control Plane","version":"0.1.0"},"paths":{"/health":{"get":{"tags":["health"],"summary":"Health","description":"Liveness. Deliberately dependency-free: answers \"is the process up?\"\n\nA failing dependency must not restart the container, so this never touches\nthe database. Readiness is a separate question -- see /readyz.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Health Get"}}}}}}},"/healthz":{"get":{"tags":["health"],"summary":"Healthz","description":"Alias for /health, matching the query service's endpoint naming.","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Healthz Healthz Get"}}}}}}},"/readyz":{"get":{"tags":["health"],"summary":"Readyz","description":"Readiness. Answers \"can this task actually serve traffic?\"\n\nLoad balancers point here, so a task that cannot reach PostgreSQL is pulled\nfrom rotation instead of accepting requests it will only fail.","operationId":"readyz_readyz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Readyz Readyz Get"}}}}}}},"/.well-known/openai-apps-challenge":{"get":{"summary":"Openai Apps Challenge","operationId":"openai_apps_challenge__well_known_openai_apps_challenge_get","responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/.well-known/oauth-protected-resource/mcp":{"get":{"summary":"Oauth Protected Resource","operationId":"oauth_protected_resource__well_known_oauth_protected_resource_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-protected-resource/v1/mcp":{"get":{"summary":"Oauth Protected Resource","operationId":"oauth_protected_resource__well_known_oauth_protected_resource_v1_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"summary":"Oauth Protected Resource","operationId":"oauth_protected_resource__well_known_oauth_protected_resource_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/openid-configuration":{"get":{"summary":"Oauth Authorization Server","operationId":"oauth_authorization_server__well_known_openid_configuration_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"summary":"Oauth Authorization Server","operationId":"oauth_authorization_server__well_known_oauth_authorization_server_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/graphify-fleet-jwks.json":{"get":{"summary":"Fleet Jwks","operationId":"fleet_jwks__well_known_graphify_fleet_jwks_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/register":{"post":{"summary":"Register","operationId":"register_oauth_register_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/authorize":{"get":{"summary":"Authorize","operationId":"authorize_oauth_authorize_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/callback":{"get":{"summary":"Callback","operationId":"callback_oauth_callback_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/token":{"post":{"summary":"Token","operationId":"token_oauth_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_token_oauth_token_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/revoke":{"post":{"summary":"Revoke","operationId":"revoke_oauth_revoke_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_revoke_oauth_revoke_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/api-keys":{"post":{"summary":"Create Api Key","operationId":"create_api_key_v1_api_keys_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Api Keys","operationId":"list_api_keys_v1_api_keys_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/api-keys/{token_id}":{"delete":{"summary":"Revoke Api Key","operationId":"revoke_api_key_v1_api_keys__token_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Token Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ask":{"post":{"summary":"Ask","operationId":"ask_v1_ask_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ask/history":{"get":{"summary":"Ask History","description":"The tenant's recent Ask questions + answers, newest first (Ask history).\n\nGated at ``REPOS_READ`` (any repo reader in the workspace). Returns an empty\npage while ``ask_history_enabled`` is off (the feature is dark) rather than a\n404, so the dashboard can call it unconditionally and simply render nothing.\n``repository_id`` optionally narrows to one repo; ``cursor`` is a row offset for\n\"load more\".","operationId":"ask_history_v1_ask_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repository Id"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Cursor"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ask/suggestions":{"get":{"summary":"Ask Suggestions","description":"Up to 4 suggested Ask questions for one repository (Ask suggestions, phase 1).\n\nDeterministic templates over signals already stored here -- recent PR reviews that\nneed attention, files with an FV-reported behaviour change, files named by review\nfindings (see ``app/services/ask_suggestions``). No model call. 404 while\n``ask_suggestions_enabled`` is off so the dashboard hides the chips.\n\nGated at REPOS_READ (it is a repo-scoped Ask surface) AND BUILDS_READ (the signals\nare review/FV run artifacts, which read at BUILDS_READ). Tenant-scoped: the repo\nmust belong to the caller's tenant (404 otherwise), and every signal query filters\non tenant + repo. Cached briefly per (tenant, repo) on this task.","operationId":"ask_suggestions_v1_ask_suggestions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repositoryId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repositoryid"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/experience/summary":{"get":{"summary":"Summary","operationId":"summary_v1_experience_summary_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/experience/seen":{"post":{"summary":"Mark Seen","operationId":"mark_seen_v1_experience_seen_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeenBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/experience/preferences":{"get":{"summary":"Preferences","operationId":"preferences_v1_experience_preferences_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Set Preferences","operationId":"set_preferences_v1_experience_preferences_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferenceBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Patch Preferences","operationId":"patch_preferences_v1_experience_preferences_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExperiencePreferencePatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/experience/capabilities":{"get":{"summary":"Discovery Capabilities","operationId":"discovery_capabilities_v1_experience_capabilities_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Repository Id"}},{"name":"current","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/experience/enrollment":{"get":{"summary":"Discovery Enrollment","description":"Assignment exists before workspace creation and remains stable across devices.","operationId":"discovery_enrollment_v1_experience_enrollment_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/repositories/{repository_id}/patterns":{"get":{"summary":"Patterns","operationId":"patterns_v1_repositories__repository_id__patterns_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","maxLength":4096,"default":"","title":"Query"}},{"name":"paths","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string","maxLength":2048},"maxItems":20},{"type":"null"}],"title":"Paths"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}},{"name":"include_suppressed","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Suppressed"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repositories/{repository_id}/structure":{"get":{"summary":"Patterns","operationId":"patterns_v1_repositories__repository_id__structure_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","maxLength":4096,"default":"","title":"Query"}},{"name":"paths","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string","maxLength":2048},"maxItems":20},{"type":"null"}],"title":"Paths"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}},{"name":"include_suppressed","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Suppressed"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repositories/{repository_id}/patterns/{pattern_id}":{"get":{"summary":"Pattern Detail","operationId":"pattern_detail_v1_repositories__repository_id__patterns__pattern_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"pattern_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{32}$","title":"Pattern Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repositories/{repository_id}/patterns/{pattern_id}/control":{"post":{"summary":"Control Pattern","operationId":"control_pattern_v1_repositories__repository_id__patterns__pattern_id__control_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"pattern_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{32}$","title":"Pattern Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatternFeedback"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/repositories/{repository_id}/patterns":{"post":{"summary":"Agent Patterns","description":"Called by the query service on every code query with paths: on a warm cache this\nis one authorization statement, no artifact read and no re-validation.","operationId":"agent_patterns_v1_internal_tenants__tenant_id__repositories__repository_id__patterns_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentPatternQuery"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repositories/{repository_id}/patterns/{pattern_id}/history":{"get":{"summary":"Pattern History","operationId":"pattern_history_v1_repositories__repository_id__patterns__pattern_id__history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"pattern_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{32}$","title":"Pattern Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/resend-verification":{"post":{"summary":"Resend Verification","operationId":"resend_verification_v1_auth_resend_verification_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendVerificationRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendVerificationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/draft-fix":{"post":{"summary":"Draft Fix","description":"Draft a fix for a Jira ticket -> a verified draft PR. Mirrors the apply-fix route's\ngating: REPOS_MANAGE, the ``autofix_enabled`` kill switch, a PAID plan, a connected\nJira, an owned repo, and a per-tenant monthly cap.","operationId":"draft_fix_v1_repos__repository_id__draft_fix_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftFixRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/resolve-issue":{"post":{"summary":"Resolve Issue","description":"Resolve a Sentry issue -> a verified draft PR. Mirrors ``draft_fix``'s gating\nEXACTLY (REPOS_MANAGE, the ``autofix_enabled`` kill switch, a PAID plan, an active\nsubscription, the tenant-wide monthly COST cap, and the per-tenant autofix COUNT\ncap); the only difference is the INPUT source -- a connected Sentry instead of Jira,\nand a Sentry issue instead of a Jira ticket. Everything downstream (create_run,\noutbox, SQS, worker, callback, review-trigger, metering) is reused unchanged.","operationId":"resolve_issue_v1_repos__repository_id__resolve_issue_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveIssueRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/autofix/{job_id}":{"get":{"summary":"Get Autofix","description":"One autofix run's projected status, tenant-scoped.","operationId":"get_autofix_v1_autofix__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/autofix-runs/{job_id}/start":{"post":{"summary":"Start Autofix Run","description":"An autofix worker claiming its run: the WRITE clone token (contents:write +\npull_requests:write, single repo), the tenant callback secret, and the base sha.","operationId":"start_autofix_run_v1_internal_autofix_runs__job_id__start_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutofixStartRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/autofix-runs/{job_id}/status":{"post":{"summary":"Autofix Run Status","description":"An autofix worker reporting progress or its terminal outcome.\n\nAuthenticated by the job token (``InternalWorker``) + the HMAC over the tenant's\nderived callback secret. Idempotent by ``sequence``. On a terminal ``ready`` with\n``outcome == \"drafted\"`` the drafted PR is directly enqueued for review (draft PRs\nare not auto-reviewed by the webhook path -- Gap A). The Opus-tier drafting agent's\nLLM usage is metered on the (applied) terminal event.","operationId":"autofix_run_status_v1_internal_autofix_runs__job_id__status_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Signature"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/autofix-runs/{job_id}/base-graph":{"get":{"summary":"Autofix Run Base Graph","description":"A presigned read of THIS autofix repo's promoted graph.json, to ground the fix\n(mirror ``presign_review_base_graph``). 404 if none -- the worker cold-builds. Auth\nis the job token bound to this ``{job_id}``; tenant + repo are read from the run.","operationId":"autofix_run_base_graph_v1_internal_autofix_runs__job_id__base_graph_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/autofix-runs/reconcile":{"post":{"summary":"Reconcile Autofix Runs","description":"Drain the pending autofix outbox, sweep runs stranded by a dead worker, recover\nany drafted run whose review-trigger never landed (Gap A recovery), AND act on\ndrafted fixes that went red (signal-when-red). All run whenever autofix is\nconfigured; a no-op (zeros) otherwise.","operationId":"reconcile_autofix_runs_v1_internal_autofix_runs_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutofixReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/summary":{"get":{"summary":"Billing Summary","operationId":"billing_summary_v1_billing_summary_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/checkout":{"post":{"summary":"Billing Checkout","operationId":"billing_checkout_v1_billing_checkout_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingCheckoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/upgrade/preflight":{"get":{"summary":"Billing Upgrade Preflight","description":"Whether this Pro tenant can flip in place to Teams (owner/admin).\n\nReturns ``{canUpgradeInPlace, personalAccountInstall, privateRepositories[]}``.\n``canUpgradeInPlace`` is always true now (the personal-account-install gate was\nremoved) and ``personalAccountInstall`` is retained on the wire but always false;\n``privateRepositories`` enumerates the repos the flip would expose, for the disclosure.","operationId":"billing_upgrade_preflight_v1_billing_upgrade_preflight_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/upgrade":{"post":{"summary":"Billing Upgrade","description":"Pro -> Teams upgrade (owner/admin). Two-phase: an unconfirmed in-place request\nreturns ``{preview}``; ``confirm=true`` commits the in-place swap; ``inPlace=false``\nreturns ``{createNewRequired: true}`` (the FE then mints a new Teams workspace +\nchecks it out -- there is no ``url`` field). 402 until Teams is armed.","operationId":"billing_upgrade_v1_billing_upgrade_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingUpgradeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/downgrade":{"post":{"summary":"Billing Downgrade","description":"Teams -> Pro downgrade (owner-only), scheduled at period end. 402 until armed.","operationId":"billing_downgrade_v1_billing_downgrade_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingDowngradeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/interval":{"post":{"summary":"Billing Interval Switch","description":"Switch the current subscription's billing interval (owner/admin). month->year is\nimmediate + prorated (unconfirmed returns a `{preview}`, `confirm=true` commits a\n`{switched}` swap); year->month returns `{scheduledAt}` (period-end). 503 until the\ntarget-interval price is configured.","operationId":"billing_interval_switch_v1_billing_interval_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingIntervalSwitchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/portal":{"get":{"summary":"Billing Portal","operationId":"billing_portal_v1_billing_portal_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/invoices":{"get":{"summary":"Billing Invoices","description":"Recent Stripe invoices for inline display. Empty (not an error) when no\nStripe customer exists yet. ``limit`` bounds the fetch window (1..100); the\ndashboard paginates it client-side.","operationId":"billing_invoices_v1_billing_invoices_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":24,"title":"Limit"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/stripe":{"post":{"summary":"Stripe Webhook","operationId":"stripe_webhook_v1_webhooks_stripe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/reviews/{review_id}/findings/{finding_id}/capa":{"post":{"summary":"Record Capa","operationId":"record_capa_v1_reviews__review_id__findings__finding_id__capa_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}},{"name":"finding_id","in":"path","required":true,"schema":{"type":"string","title":"Finding Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapaCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{review_id}/findings/{finding_id}/capa/prefill":{"post":{"summary":"Prefill Capa","description":"A drafted narrative the user confirms or edits before recording. Nothing is\nstored; any failure (unconfigured, rate-limited, locked, slow, bad output) returns\nempty fields with ``drafted: false``.","operationId":"prefill_capa_v1_reviews__review_id__findings__finding_id__capa_prefill_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}},{"name":"finding_id","in":"path","required":true,"schema":{"type":"string","title":"Finding Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapaPrefill"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/capa/{capa_id}":{"patch":{"summary":"Update Capa","operationId":"update_capa_v1_capa__capa_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"capa_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Capa Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapaUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/capa":{"get":{"summary":"List Capa","description":"The tenant's CAPAs (optionally one repo or one review run). Without ``review``,\nalso one block per repository with the rules its fixed CAPAs propose, whether each\nis already in the default branch's rules.json, and that file merged with them.","operationId":"list_capa_v1_capa_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repo","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repo"}},{"name":"review","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Review"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/profile":{"get":{"summary":"Get Profile","operationId":"get_profile_v1_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"summary":"Update Profile","operationId":"update_profile_v1_profile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"summary":"Update Profile","operationId":"update_profile_v1_profile_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/profile/avatar/upload-url":{"post":{"summary":"Create Avatar Upload","description":"Presigned PUT for the caller's own avatar (png/jpeg/webp/gif/avif).\n\nThe browser uploads straight to S3 -- the bytes never touch this service, which is a\n1-vCPU single-process task. Then POST /v1/profile/avatar with the returned key.","operationId":"create_avatar_upload_v1_profile_avatar_upload_url_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarUploadRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/profile/avatar":{"post":{"summary":"Confirm Avatar","description":"Adopt an uploaded object as the avatar, after the server verifies it exists and is\nwithin the size/type limits. Returns the refreshed profile.","operationId":"confirm_avatar_v1_profile_avatar_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarConfirmRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/orgs/{organization_id}/icon/upload-url":{"post":{"summary":"Create Workspace Icon Upload","description":"Presigned PUT for the WORKSPACE icon. Owner/admin only, re-checked at confirm.","operationId":"create_workspace_icon_upload_v1_orgs__organization_id__icon_upload_url_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceIconUploadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/icon":{"post":{"summary":"Confirm Workspace Icon","operationId":"confirm_workspace_icon_v1_orgs__organization_id__icon_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceIconConfirmRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Clear Workspace Icon","operationId":"clear_workspace_icon_v1_orgs__organization_id__icon_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/profile/metrics":{"get":{"summary":"Get Profile Metrics","description":"Badges, weekly performance and the activity ranking for the signed-in user.\n\nSplit from /profile so the page can refresh the metrics card without re-reading the\nwhole profile, and kept OFF /usage because that endpoint is workspace-scoped while\nthis is personal. `null` when achievements are dark or the read degrades.","operationId":"get_profile_metrics_v1_profile_metrics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/profile/activity-metrics":{"get":{"summary":"Get Profile Activity Metrics","description":"The profile charts, as the public profile's ``metrics`` block shows them.\n\nOne snapshot for both pages: every workspace the user belongs to, summed. `null` when\nthere is nothing to show or the read degrades.","operationId":"get_profile_activity_metrics_v1_profile_activity_metrics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/usernames/availability":{"get":{"summary":"Username Availability","description":"Advisory availability check for a candidate handle.\n\nAuthenticated and rate-limited at the edge. It reserves nothing and reveals nothing\nabout who holds a taken name -- only `available` / `unavailable` / `invalid`.","operationId":"username_availability_v1_usernames_availability_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"username","in":"query","required":true,"schema":{"type":"string","title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/profile/username":{"patch":{"summary":"Change Username","description":"Spend the caller's ONE username change. Returns the refreshed profile.\n\n422 for a handle that cannot be had (format, reserved); 409 `username_taken` or\n`username_change_used`. Submitting the handle already held is a no-op that succeeds\nand spends nothing.","operationId":"change_username_v1_profile_username_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsernameUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/profile/acknowledgements/{key}":{"put":{"summary":"Acknowledge","description":"Record that the caller has seen a one-time UI moment (the product tour, a modal).\n\nReplaces the per-device localStorage latches, which re-fired in every new browser.\nIdempotent; 422 `unknown_acknowledgement` for a key outside ACKNOWLEDGEMENT_KEYS.","operationId":"acknowledge_v1_profile_acknowledgements__key__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/profile/agent-workspace":{"put":{"summary":"Set Agent Workspace","description":"Point the caller's agent (MCP/gx) at a workspace by tenant id (AD-MCP-1). Writes\n``default_tenant_id`` (authority) + mirrors app_metadata; 404 ``workspace_not_found``\nif the caller is not a member (indistinguishable from nonexistent).","operationId":"set_agent_workspace_v1_profile_agent_workspace_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentWorkspaceUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/onboarding":{"get":{"summary":"Get Onboarding","operationId":"get_onboarding_v1_onboarding_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Update Onboarding","operationId":"update_onboarding_v1_onboarding_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Update Onboarding","operationId":"update_onboarding_v1_onboarding_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs":{"get":{"summary":"List Organizations","operationId":"list_organizations_v1_orgs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"summary":"Create Organization","operationId":"create_organization_v1_orgs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/orgs/{organization_id}":{"get":{"summary":"Get Organization","operationId":"get_organization_v1_orgs__organization_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/access-requests":{"get":{"summary":"List Org Access Requests","description":"Pending requests to join this org (owner/admin only; the callback opens them).","operationId":"list_org_access_requests_v1_orgs__organization_id__access_requests_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/access-requests/{request_id}/approve":{"post":{"summary":"Approve Org Access Request","description":"Grant the requester a membership in this org. Owner-only (enforced in service).\n\nOn a Team workspace with no free seat, ``confirmSeatBump=true`` buys one via the\nAD-FLOW-3 prorated bump; otherwise a full workspace refuses (seat_limit_reached).","operationId":"approve_org_access_request_v1_orgs__organization_id__access_requests__request_id__approve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}},{"name":"confirmSeatBump","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Confirmseatbump"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/access-requests/{request_id}/deny":{"post":{"summary":"Deny Org Access Request","description":"Decline a pending join request. Owner-only (enforced in service). Grants nothing.","operationId":"deny_org_access_request_v1_orgs__organization_id__access_requests__request_id__deny_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/invitations":{"get":{"summary":"List Org Invitations","description":"Pending invitations for this workspace (owner/admin/member read).","operationId":"list_org_invitations_v1_orgs__organization_id__invitations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Create Org Invitation","description":"Invite a person to this workspace by email (owner/admin only). Returns the\none-time accept link once. When no seat is free, ``confirmSeatBump=true`` buys one\nvia the AD-FLOW-3 prorated bump; without it a full workspace returns\n``seat_bump_required`` (bump available) or ``seat_limit_reached`` (dark).","operationId":"create_org_invitation_v1_orgs__organization_id__invitations_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"confirmSeatBump","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Confirmseatbump"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/invitations/{token}":{"get":{"summary":"Preview Invitation","description":"The pre-accept preview for an invitee's landing page (workspace, inviter, role,\nexpiry, and whether THIS session is the invited email). Tenant-less: resolves solely\nfrom the raw token, and NEVER echoes it (or the invited address) back.","operationId":"preview_invitation_v1_invitations__token__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/invitations/{invitation_id}/resend":{"post":{"summary":"Resend Org Invitation","description":"Re-issue a pending invitation with a fresh token + expiry and re-send it\n(owner/admin). Returns the new one-time accept link.","operationId":"resend_org_invitation_v1_orgs__organization_id__invitations__invitation_id__resend_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"invitation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invitation Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/invitations/{invitation_id}/revoke":{"post":{"summary":"Revoke Org Invitation","description":"Revoke a pending invitation (owner/admin) and release its reserved seat.","operationId":"revoke_org_invitation_v1_orgs__organization_id__invitations__invitation_id__revoke_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"invitation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invitation Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/invitations/{token}/accept":{"post":{"summary":"Accept Invitation","description":"Accept an invitation by its raw token, joining the workspace. Tenant-less: the\ninvitee is not a member yet, so the token is the capability and the verified email\nmust match the invite.","operationId":"accept_invitation_v1_invitations__token__accept_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/invitations/{token}/decline":{"post":{"summary":"Decline Invitation","description":"Decline an invitation by its raw token, releasing the reserved seat. Tenant-less.","operationId":"decline_invitation_v1_invitations__token__decline_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/members":{"get":{"summary":"List Org Members","description":"The workspace member roster (owner/admin/member read).","operationId":"list_org_members_v1_orgs__organization_id__members_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/members/{membership_id}":{"patch":{"summary":"Change Org Member Role","description":"Change a member's role (owner/admin). Never sets OWNER; refuses demoting the last\nowner.","operationId":"change_org_member_role_v1_orgs__organization_id__members__membership_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"membership_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Membership Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipRoleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Remove Org Member","description":"Remove a member (owner/admin). Refuses removing the last owner.","operationId":"remove_org_member_v1_orgs__organization_id__members__membership_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"membership_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Membership Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{organization_id}/members/leave":{"post":{"summary":"Leave Org","description":"Leave the workspace (self-service). Refuses if the caller is the last owner.","operationId":"leave_org_v1_orgs__organization_id__members_leave_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Organization Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/enterprise-leads":{"post":{"summary":"Capture Enterprise Lead","operationId":"capture_enterprise_lead_v1_enterprise_leads_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnterpriseLeadCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/repos":{"get":{"summary":"List Repositories","operationId":"list_repositories_v1_repos_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/sync":{"post":{"summary":"Sync Repositories","description":"The dashboard's Sync: the current repository list, plus a GitHub re-read.\n\nReturns exactly what GET /repos returns (under `repositories`), and -- at most once\nper install per minute -- starts a background re-read of the tenant's GitHub\ninstalls so repos created or granted on GitHub since the last read show up. The\nre-read is additive (new repos land disabled; nothing is ever disabled), so any\nmember who can list repositories may trigger it. `githubSync.started` tells the\nclient whether to re-poll shortly; `retryAfterSeconds` when throttled.","operationId":"sync_repositories_v1_repos_sync_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/enable":{"post":{"summary":"Enable Repository","operationId":"enable_repository_v1_repos__repository_id__enable_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryEnable"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/removal-preview":{"get":{"summary":"Repository Removal Preview","description":"What removing this repository would destroy, for the confirmation dialog.\n\nA read (REPOS_READ): seeing the cost of a removal is not itself privileged. A\nnon-empty `inFlight` means the DELETE below would be refused.","operationId":"repository_removal_preview_v1_repos__repository_id__removal_preview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}":{"delete":{"summary":"Remove Repository Route","description":"Remove a repository: the row, its 16 cascades, and its S3 prefix (queued).\n\nDestructive and not undoable. The non-destructive path is the per-repo toggles\n(POST /repos/{id}/enable) -- that is \"disable\", this is \"remove\". Refused 409\n`repository_busy` while any build, review, verification or autofix is non-terminal.\n\nBehind ``repository_removal_enabled`` (404 ``repository_removal_disabled`` when off).","operationId":"remove_repository_route_v1_repos__repository_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/reindex":{"post":{"summary":"Reindex Repository","operationId":"reindex_repository_v1_repos__repository_id__reindex_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/graph":{"get":{"summary":"Repository Graph","description":"The repository's promoted build's node-link graph, for the frontend graph view.\n\nWhen ``graph_presign_enabled`` (Path B) the response is a short-TTL presigned S3\nGET (``{\"url\", \"expiresIn\"}``) the browser fetches directly, so the graph never\ntransits the control plane; otherwise the graph body is proxied. ``limit`` is\naccepted and wired through but NOT enforced on the proxy path.","operationId":"repository_graph_v1_repos__repository_id__graph_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Limit"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/contributors":{"get":{"summary":"Repository Contributors","description":"The repository's contributor overlay summary: one row per contributor with\nname/handle, commit count, signed/unsigned split, AI-assisted count, first/last\nseen, and reach (code nodes authored) -- sliced from the promoted graph.json.\n\nBehind ``contributors_enabled`` (404 when off). Gated at ``REPOS_READ`` like the\ngraph view: the summary is name-only (emails are scrubbed engine-side) and no more\nsensitive than the graph itself, so any repo reader may see it. ``contributors`` is\n``[]`` when the index carries no overlay (built with GRAPHIFY_ENT_CONTRIBUTORS off).","operationId":"repository_contributors_v1_repos__repository_id__contributors_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/contributors/audit":{"get":{"summary":"Repository Contributor Audit","description":"The repository's ranked supply-chain risk report (sole_owner_critical /\nnew_in_high_impact / unsigned_in_sensitive / ai_unverified_in_blast_radius) with\nper-finding evidence + remedy, sliced from the promoted graph.json.\n\nNames risk on specific components, but it is derived from git authorship of the same\nrepo the caller already reads (emails scrubbed, handle-only), so gated at\n``REPOS_READ`` like the summary + the graph itself -- any repo reader, including a\nplain member, may see it. (It is a code-ownership surface, not a billing/PII one, so\nit does not warrant the ``AUDIT_READ`` audit-log tier.) Behind ``contributors_enabled``\n(404 when off). ``audit`` is ``null`` when the index carries no overlay.","operationId":"repository_contributor_audit_v1_repos__repository_id__contributors_audit_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/wiki":{"get":{"summary":"Repository Wiki","description":"The repository's promoted build's code-wiki bundle (index + articles + wikilink\nresolution), for the frontend Wiki view.\n\nBehind ``wiki_enabled`` (404 when off). Gated at ``REPOS_READ`` like the graph view:\nthe bundle is derived from the same graph the caller already reads. Presigned when\n``graph_presign_enabled`` (browser fetches straight from S3), else proxied. A build\nwith no WIKI artifact (not re-indexed with the wiki stage armed) returns\n``{\"available\": false}`` -- an empty state, not an error.","operationId":"repository_wiki_v1_repos__repository_id__wiki_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/dead-code":{"get":{"summary":"Repository Dead Code","description":"Private symbols the promoted graphs have found unreferenced for at least 14 days\nacross at least two promoted builds (a heuristic, shown as \"Unreferenced code\").\n``dwellingCount`` counts candidates still inside the dwell.","operationId":"repository_dead_code_v1_repos__repository_id__dead_code_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/builds":{"get":{"summary":"List Builds","operationId":"list_builds_v1_builds_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/builds/page":{"get":{"summary":"List Builds Page","operationId":"list_builds_page_v1_builds_page_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews":{"get":{"summary":"List Reviews","operationId":"list_reviews_v1_reviews_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/summary":{"get":{"summary":"Review Summary","operationId":"review_summary_v1_reviews_summary_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":366,"minimum":1,"default":60,"title":"Days"}},{"name":"repositoryId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Repositoryid"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{review_id}":{"get":{"summary":"Get Review","description":"One hosted PR-review run, the detail behind an expanded Reviews row.\n\nTenant-scoped and BUILDS_READ-gated in the service; 404s a run the tenant\ndoes not own. Same projection as one list row (the frontend's ReviewRunDetail\naliases the list ReviewRun), fetched one run at a time so it can grow richer\nthan the list later without churning callers -- parallel to\nGET /verifications/{verification_id}.","operationId":"get_review_v1_reviews__review_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{review_id}/fixes/{fix_id}/apply":{"post":{"summary":"Apply Review Fix","description":"Commit one verified review fix onto its PR head branch (the in-app \"Apply fix\"\nbutton). The client sends only the run id + the fix's content id; the actual patch is\nre-loaded from the run's signed result server-side. REPOS_MANAGE-gated, paid + per-repo\nopt-in, behind the ``fix_apply_enabled`` kill switch; a typed error code drives the\nbutton's failure state (needs_approval / head_moved / fork_pr_unsupported / ...).","operationId":"apply_review_fix_v1_reviews__review_id__fixes__fix_id__apply_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}},{"name":"fix_id","in":"path","required":true,"schema":{"type":"string","title":"Fix Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/verifications":{"get":{"summary":"List Verifications","operationId":"list_verifications_v1_verifications_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"repositoryId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Repositoryid"}},{"name":"baseSha","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^[a-fA-F0-9]{7,64}$"},{"type":"null"}],"title":"Basesha"}},{"name":"headSha","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^[a-fA-F0-9]{7,64}$"},{"type":"null"}],"title":"Headsha"}},{"name":"prNumber","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Prnumber"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/verifications/{verification_id}":{"get":{"summary":"Get Verification","operationId":"get_verification_v1_verifications__verification_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"verification_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Verification Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/verifications/{verification_id}/evidence":{"get":{"summary":"Get Verification Evidence","description":"The run's evidence certificates (JSON or Markdown) as a downloadable document.","operationId":"get_verification_evidence_v1_verifications__verification_id__evidence_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"verification_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Verification Id"}},{"name":"format","in":"query","required":false,"schema":{"enum":["json","md"],"type":"string","default":"json","title":"Format"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/verifications/{verification_id}/functions/{index}/proof":{"get":{"summary":"Get Verification Proof","description":"One verdict's proof-carrying certificate; 404 unless it is a sound proof.","operationId":"get_verification_proof_v1_verifications__verification_id__functions__index__proof_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"verification_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Verification Id"}},{"name":"index","in":"path","required":true,"schema":{"type":"integer","minimum":0,"title":"Index"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/verifications/{verification_id}/rerun":{"post":{"summary":"Rerun Verification","description":"Manually re-verify a run's PR head, forcing a fresh run even on an unchanged\ncommit (retry a failed/abstained run, or re-run after an FV-config change).\nREPOS_MANAGE, the same product-use permission as reindex; tenant-scoped and\ngated by the same entitlement/kill-switch/fork checks as any FV run.","operationId":"rerun_verification_v1_verifications__verification_id__rerun_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"verification_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Verification Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/audit":{"get":{"summary":"List Audit","operationId":"list_audit_v1_audit_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/github/install-url":{"post":{"summary":"Github Install Url","operationId":"github_install_url_v1_integrations_github_install_url_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubInstallUrlRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/github/callback":{"get":{"summary":"Github Callback","operationId":"github_callback_v1_integrations_github_callback_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"installation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Installation Id"}},{"name":"setup_action","in":"query","required":false,"schema":{"type":"string","maxLength":32,"default":"install","title":"Setup Action"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":32,"maxLength":4096},{"type":"null"}],"title":"State"}},{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":512},{"type":"null"}],"title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/github/unclaimed":{"get":{"summary":"Github Unclaimed Installations","description":"Pending GitHub installs GitHub itself attributed to THIS session's identity.\n\nWhat this fixes: the claim card rendered only from the callback's one redirect, so\nlosing it -- closing the tab, or installing from GitHub's own UI, which sends no\nredirect at all -- made the install unreachable through the product forever.\n\nPROOF OF CONTROL. A bearer-authenticated GET has no GitHub token (the claim's is\nexchanged per attempt and never persisted), so the claim's per-row\n`GET /user/installations` proof is unavailable here. Rather than weaken it, this uses\na STRICTLY NARROWER one: a row is listed only when GitHub attested a specific account\nas the install's OWNER (``installer_github_user_id`` -- the webhook `sender`, or a\ncallback token holder who passed the claim's ownership test, write-once) AND the\nsession subject IS that account, as ``github|<id>`` compared to the subject directly.\nAccess-grade identity is deliberately not enough, and a non-GitHub session therefore\nlists nothing rather than everything.\n\nSo it cannot enumerate (the filter takes no caller input at all -- the id comes from\nthe authenticated subject) and it is not a trust anchor (it only DISCLOSES; binding\nstays with /link/start -> /link/callback, which re-proves ownership against the\nclaimant's own token). SETTINGS_MANAGE, as /link/start requires.","operationId":"github_unclaimed_installations_v1_integrations_github_unclaimed_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/github/link/start":{"get":{"summary":"Github Link Start","description":"Begin the in-app claim: mint a session-bound signed state + double-submit cookie and\nreturn the GitHub user-authorization URL. Authenticated (SETTINGS_MANAGE) -- the bind\ntarget is THIS session's tenant, signed into the state so the no-bearer callback can\ntrust it.","operationId":"github_link_start_v1_integrations_github_link_start_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"installation_id","in":"query","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"Installation Id"}},{"name":"return_path","in":"query","required":false,"schema":{"type":"string","maxLength":2048,"default":"/onboarding?installed=github","title":"Return Path"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/github/link/callback":{"get":{"summary":"Github Link Callback","description":"Return leg of the in-app claim (a github.com redirect, NO bearer). Verify the\nsession-bound state + double-submit cookie, exchange the code for an EPHEMERAL user\ntoken, prove installation control via GET /user/installations (+ org admin), and bind\nto the state's tenant. The token is never stored. Every outcome clears the cookie and\nredirects into the app -- never a raw error page.","operationId":"github_link_callback_v1_integrations_github_link_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":512},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":4096},{"type":"null"}],"title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/github/{installation_id}":{"delete":{"summary":"Github Disconnect","description":"Disconnect a GitHub installation: uninstall upstream, then delete our row.\n\nMirrors the Jira / Sentry / Slack disconnects. The one FK to ``git_installation``\ncascades every repository under it, and each of those cascades its own 16\nrelationships -- so this is destructive and refused 409 ``repository_busy`` while\nany of those repositories has work in flight.\n\nThe upstream uninstall is best-effort and never fails the endpoint: a 404 means the\nApp is already gone (the entire 162-tenant backlog), and an unreachable GitHub must\nnot be able to trap a tenant with rows it cannot remove. Disconnect stays available\neven when the App is unconfigured, for exactly that reason.","operationId":"github_disconnect_v1_integrations_github__installation_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"installation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Installation Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/github/refresh":{"post":{"summary":"Github Refresh","description":"Re-read this tenant's GitHub installations from GitHub and re-sync them.\n\nThe recovery path for the failure this module's discovery backoff narrows but\ncannot close: an install whose repository set was still empty on every read\ninside the callback's budget. Nothing else ever re-reads it -- the\n`installation` webhook covers suspend/resume, `installation_repositories`\nonly a later add/remove -- so without this the stored empty set is permanent\nand the wizard's \"Retry\" just re-reads our own database and fails identically\nforever. This makes that button do the one thing that can actually help.\n\nReports what is true rather than inferring it from the repository count, so\nthe caller can tell \"GitHub is not connected\" apart from \"GitHub is connected\nand shared no repositories\" -- two states the wizard used to collapse into a\nsingle, terminal-sounding \"no verified installation was found\".\n\nSETTINGS_MANAGE, the same permission that issued the install URL: this\nre-reads third-party state for the tenant and rewrites repository rows.","operationId":"github_refresh_v1_integrations_github_refresh_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/integrations/github/refresh-stuck":{"post":{"summary":"Github Refresh Stuck","description":"Heal GitHub installs stranded with an empty repository set (internal sweep).\n\nThe platform-wide backstop for the miss `github_refresh` fixes one tenant at a\ntime: an install whose repositories were still empty on every read inside the\ncallback's budget is committed empty, and nothing ever re-reads it. This sweep\nre-reads every such install under the launcher identity -- so a stuck install\nheals without the user pressing Retry, and every future one heals until the\n`installation.created` webhook backstop lands. Pass `tenantId` to force-refresh\na single tenant's installs (a one-off) instead of sweeping the empty-set backlog.\n\nScheduled alongside the reindex-catchup sweep; a no-op when nothing is stuck, so\nit is safe to run unconditionally. SETTINGS_MANAGE is not required (and no user\ncontext exists here) because the launcher identity, not a tenant admin, drives it.","operationId":"github_refresh_stuck_v1_internal_integrations_github_refresh_stuck_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshStuckRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/github":{"post":{"summary":"Github Webhook","operationId":"github_webhook_v1_webhooks_github_post","responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/integrations/gitlab/authorize-url":{"post":{"summary":"Gitlab Authorize Url","operationId":"gitlab_authorize_url_v1_integrations_gitlab_authorize_url_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitLabAuthorizeUrlRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/gitlab/callback":{"get":{"summary":"Gitlab Callback","operationId":"gitlab_callback_v1_integrations_gitlab_callback_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":2048},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":32,"maxLength":4096},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/gitlab/refresh-projects":{"post":{"summary":"Gitlab Refresh Projects","description":"Re-drive the project sync from the stored OAuth token -- no re-auth.\n\nThe OAuth callback commits the installation before its (up to 20-page)\nproject listing, so a listing failure leaves a durable \"connected,\nprojects syncing\" install (``projects_synced_at IS NULL``). This is its\nrecovery path; it is also a plain refresh for an already-synced install.","operationId":"gitlab_refresh_projects_v1_integrations_gitlab_refresh_projects_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/gitlab":{"delete":{"summary":"Gitlab Disconnect","description":"Disconnect GitLab: release what we created upstream, then delete our row.\n\nMirrors the Jira / Sentry / Slack disconnects. Deletes the webhooks and\n``read_repository`` deploy tokens we minted per project, revokes the OAuth grant,\nthen deletes the installation row -- which cascades every repository under it.\nDestructive, so refused 409 ``repository_busy`` while any of them has work in\nflight.\n\nEvery upstream step is best-effort and independent: the reporting customer had\nalready deleted the project AND revoked our grant, so each call 404s or 401s. None\nof that may stop the local delete -- that is the whole bug. Disconnect also works\nwhen the integration is unconfigured, for the same reason.","operationId":"gitlab_disconnect_v1_integrations_gitlab_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/gitlab":{"post":{"summary":"Gitlab Webhook","operationId":"gitlab_webhook_v1_webhooks_gitlab_post","responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/integrations/google-drive":{"get":{"summary":"Google Drive Status","operationId":"google_drive_status_v1_integrations_google_drive_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Google Drive Disconnect","description":"Revoke the grant at Google, forget the tokens, and stop every folder.","operationId":"google_drive_disconnect_v1_integrations_google_drive_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/google-drive/authorize-url":{"post":{"summary":"Google Drive Authorize Url","operationId":"google_drive_authorize_url_v1_integrations_google_drive_authorize_url_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveAuthorizeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/google-drive/callback":{"get":{"summary":"Google Drive Callback","description":"Exchange the code and PARK the grant; attach nothing yet.\n\nThis top-level navigation carries no logged-in user, so attaching here would let\nanyone who sends a victim their own authorize link bind the victim's Drive to\ntheir workspace. Instead the browser gets a one-time code, and only the user who\nstarted the flow can confirm it from the app (POST .../confirm).","operationId":"google_drive_callback_v1_integrations_google_drive_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":2048},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":32,"maxLength":4096},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/google-drive/confirm":{"post":{"summary":"Google Drive Confirm","description":"Attach a parked grant: only its initiator, in the workspace it was started for.","operationId":"google_drive_confirm_v1_integrations_google_drive_confirm_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveConfirmRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/google-drive/picker-session":{"post":{"summary":"Google Drive Picker Session","description":"A short-lived token for the browser folder Picker, for the connecting user only.\n\nThe token can read the connector's whole Drive, so no other member may mint it.","operationId":"google_drive_picker_session_v1_integrations_google_drive_picker_session_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/google-drive/folders":{"post":{"summary":"Google Drive Add Folder","operationId":"google_drive_add_folder_v1_integrations_google_drive_folders_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveFolderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/google-drive/folders/{repository_id}":{"delete":{"summary":"Google Drive Remove Folder","description":"Stop indexing a folder. Its last graph stays until the repository is removed.","operationId":"google_drive_remove_folder_v1_integrations_google_drive_folders__repository_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/drive-links":{"get":{"summary":"Google Drive Links","description":"Graph path -> Google Drive URL of the file at that path NOW (latest listing).","operationId":"google_drive_links_v1_repos__repository_id__drive_links_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/integrations/google-drive/reconcile":{"post":{"summary":"Reconcile Google Drive","description":"Re-check due folders; a changed folder becomes a push-triggered build.\n\nTime-boxed and per-folder isolated: one slow or broken folder backs off on its\nown and never fails the tick, so it cannot stall the launcher's other drains.","operationId":"reconcile_google_drive_v1_internal_integrations_google_drive_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/integrations/jira/connect":{"post":{"summary":"Jira Connect","operationId":"jira_connect_v1_integrations_jira_connect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JiraConnectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/jira/status":{"get":{"summary":"Jira Status","operationId":"jira_status_v1_integrations_jira_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/jira":{"delete":{"summary":"Jira Disconnect","operationId":"jira_disconnect_v1_integrations_jira_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/group-jobs/{job_id}/claim":{"post":{"summary":"Claim Group Job","operationId":"claim_group_job_v1_internal_group_jobs__job_id__claim_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/group-jobs/{job_id}/renew":{"post":{"summary":"Renew Group Job","operationId":"renew_group_job_v1_internal_group_jobs__job_id__renew_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/group-jobs/{job_id}/callbacks":{"post":{"summary":"Group Job Callback","operationId":"group_job_callback_v1_internal_tenants__tenant_id__group_jobs__job_id__callbacks_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Signature"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/groups/{group_id}/current-index":{"get":{"summary":"Current Group Index Pointer","operationId":"current_group_index_pointer_v1_internal_tenants__tenant_id__groups__group_id__current_index_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/groups":{"post":{"summary":"Create Group","operationId":"create_group_v1_groups_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Groups","operationId":"list_groups_v1_groups_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/groups/{group_id}/merge":{"post":{"summary":"Merge Group","operationId":"merge_group_v1_groups__group_id__merge_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/groups/{group_id}/graph":{"get":{"summary":"Group Graph","description":"The workspace's promoted merged build's node-link graph, for the graph view.\n\nBehind ``cross_repo_groups_enabled`` (404 when off) like the rest of this\nsurface. ``limit`` is accepted and wired through but NOT enforced -- an\noversized graph is logged and returned whole.","operationId":"group_graph_v1_groups__group_id__graph_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Limit"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/repositories/{repository_id}/current-index":{"get":{"summary":"Current Index Pointer","operationId":"current_index_pointer_v1_internal_tenants__tenant_id__repositories__repository_id__current_index_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/repositories/{repository_id}/memory/turns":{"post":{"summary":"Ingest Memory Turn","description":"Persist one hardened `remember` note into the short-term memory tier.\n\nThe query fleet is authenticated as the QUERY service (``InternalQuery``) and\nholds no write credentials of its own, so this is the only path that writes a\nturn. Design radius #3: the fleet must assert the SAME tenant/repo in the body\nthat it names in the path (both derived from the caller's verified JWT); a\nmismatch is a bug or a spoof and is rejected before anything is written. The\ntenant assertion itself is trusted from the authenticated fleet, exactly as the\ncurrent-index pointer trusts it.","operationId":"ingest_memory_turn_v1_internal_tenants__tenant_id__repositories__repository_id__memory_turns_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/repositories/{repository_id}/memory/turns/batch":{"post":{"summary":"Ingest Memory Turns Batch","description":"Persist a whole conversation SESSION of hardened turns in one call.\n\nThe batch sibling of ``ingest_memory_turn``: same single-writer principal\n(``InternalQuery``), same entitlement + subscription gates + path/identity binding.\nIt lands N turns under one ingest lock and -- when ``finalize`` is set or the\nturn-count threshold is crossed -- dispatches a single consolidation over the\nsession, which gives the distiller the session's turns TOGETHER (cross-turn\ncoreference) and lets each turn carry its real ``captured_at`` for correct temporal\nanchoring. All turns share one ``(tenant, repository)`` (contract-enforced).","operationId":"ingest_memory_turns_batch_v1_internal_tenants__tenant_id__repositories__repository_id__memory_turns_batch_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/memory-consolidations/{job_id}/claim":{"post":{"summary":"Claim Memory Consolidation","description":"A memory worker claims its job: mints the lease + returns the callback secret.\n\nThe tenant-scoped callback secret is derived (never stored, never the master\nsecret) and handed over on this SigV4-signed response, so the one-shot worker\ncan both sign and prove ownership of its status callbacks.","operationId":"claim_memory_consolidation_v1_internal_memory_consolidations__job_id__claim_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Worker-Capabilities","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Worker-Capabilities"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/memory-consolidations/{job_id}/result":{"post":{"summary":"Memory Consolidation Result","description":"A memory worker reporting progress or its final consolidation result.\n\nThe tenant is read from the run (never a header) and the callback verified with\nthat tenant's derived secret. Following the callback-skew lesson, an\nauthenticated-but-unparseable body is a 422 contract skew, not a 401 forgery.","operationId":"memory_consolidation_result_v1_internal_memory_consolidations__job_id__result_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Signature"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/repositories/{repository_id}/current-memory":{"get":{"summary":"Current Memory Pointer","description":"The pointer to a tenant/repo's current memory store, for the query fleet.\n\nMirrors current-index: entitlement + trial gates, then the freshest READY\nconsolidation BY WATERMARK (so a job that finishes out of order never regresses\nthe pointer). Hidden (404) from a non-entitled tenant. The pointer confers no\naccess -- reading the artifact still requires assuming the tenant's role.","operationId":"current_memory_pointer_v1_internal_tenants__tenant_id__repositories__repository_id__current_memory_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"schema_version","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Schema Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/repositories/{repository_id}/memory/recent-turns":{"get":{"summary":"Recent Memory Turns","description":"Un-consolidated turns for recall's freshness-merge (turns newer than the\nlast consolidation, which the store does not yet contain). Hidden from a\nnon-entitled tenant. Text is already hardened at rest; render escaped anyway.","operationId":"recent_memory_turns_v1_internal_tenants__tenant_id__repositories__repository_id__memory_recent_turns_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"session_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Session Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/memory-consolidations/{job_id}/turns":{"get":{"summary":"Memory Consolidation Turns","description":"The turns a consolidation job CLAIMED, for the worker to consolidate.\n\nJob-scoped (``InternalWorker`` -> the token is bound to this job_id). Returns\nexactly the claimed set so the worker and the READY stamp agree on the window.","operationId":"memory_consolidation_turns_v1_internal_memory_consolidations__job_id__turns_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/memory-consolidations/reconcile":{"post":{"summary":"Reconcile Memory Consolidations","description":"Drain stuck-pending consolidations and enqueue successors for un-consolidated\ntails, so a transport fault or a burst-during-run cannot wedge a repo.","operationId":"reconcile_memory_consolidations_v1_internal_memory_consolidations_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/profile-stats/reconcile":{"post":{"summary":"Reconcile Profile Stats","description":"Recompute the activity counts on the stalest PUBLISHED profiles.\n\nHere rather than on the read path: the public page is `no-store`, so every crawler hit\nwould otherwise run both aggregates. Bounded batch per tick.","operationId":"reconcile_profile_stats_v1_internal_profile_stats_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/tenants/{tenant_id}/repositories":{"get":{"summary":"List Tenant Repositories","description":"The repositories a query token scoped to this tenant may name.\n\nBacks the fleet's `list_repositories` MCP tool. Every query tool needs a\n`repository_id`, but nothing else tells an agent which repositories exist or\nwhat their ids are -- this does. Enabled repositories only; a disabled repo\nhas no servable index. `queryable` marks the ones whose current build is\npromoted (what the current-index pointer will actually serve), so the agent\ncan tell \"ready to ask\" from \"still indexing\".\n\nAuthorization is the `InternalQuery` dependency alone: reaching here means\nthe caller is the query fleet. The endpoint returns every repository of the\nnamed tenant, plus every cross-repo group (workspace) as a queryable target\nin the same shape -- the group's id in the `repositoryId` slot, exactly as\nits serving pointer uses it. Per-repo scoping -- when a token's `repositories`\nclaim is not `[\"*\"]` -- is applied by the fleet against the claim it holds;\nthis service token carries no such claim.\n\nA `kind` field distinguishes a `\"repository\"` from a `\"workspace\"`. It is the\nonly addition to the existing repository rows, which are otherwise unchanged;\ngroups are naturally absent when a tenant has none, so this stays dark until\nthe first workspace is created.","operationId":"list_tenant_repositories_v1_internal_tenants__tenant_id__repositories_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/index-placement":{"get":{"summary":"Index Placement","description":"Where this tenant's index tasks run.\n\nReplaces the labelled Kubernetes namespace the launcher used to resolve\nagainst the cluster. The registry is now the control plane, so placement and\nthe artifact bucket it is checked against come from one place and cannot\ndisagree.","operationId":"index_placement_v1_internal_tenants__tenant_id__index_placement_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"repositoryId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Repositoryid"}},{"name":"buildId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Buildid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/index-jobs/reconcile":{"post":{"summary":"Reconcile Index Jobs","description":"Reap stranded index builds to ``failed`` AND drain the pending index outbox.\n\nTwo independent recoveries share this one tick, mirroring ``reconcile_fv_runs`` /\n``reconcile_review_runs``:\n\n* The REAP (pure DB, ``BuildRecoverySweeper``) runs on EVERY tick regardless of\n  whether indexing is currently configured -- it takes the OPTIONAL indexer so a\n  build stranded before a mid-flight disable is still terminalised (a required\n  indexer would 503 before the reap). An index worker that dies mid-run (e.g. OOM\n  on a large repo) never posts a terminal callback, so its build sits in a\n  non-terminal status with a merely-EXPIRED lease -- untouched by the callback\n  projector (which rejects an expired lease) and invisible to the outbox drain\n  (which only re-drives ``pending`` rows; a stranded build is already\n  ``enqueued``). The reap marks every such build ``failed`` so a lost worker\n  SURFACES instead of stranding forever, and emits ``stranded_inprogress`` when it\n  reaps anything.\n* The DRAIN re-drives ``outbox_status=\"pending\"`` builds whose SQS publish failed\n  transiently. It no-ops (zeros) when indexing is unconfigured, so this tick is\n  safe on every deployment.\n* The stuck-queued RECOVERY (pure DB, ``StuckQueuedBuildRecovery``; DARK behind\n  ``stuck_queued_recovery_enabled``) remediates the class the reap cannot reach and\n  the gauge only counts: dispatched (``enqueued``) but NEVER-leased ``queued`` rows\n  whose SQS message was dead-lettered by a capacity burst. It runs BETWEEN reap and\n  drain so a row it flips back to ``pending`` is republished later this same tick.\n  Flag off => not constructed at all; the tick is byte-identical to before.\n* The FROZEN-PENDING gauge (``detect_frozen_pending_builds``, detection only) runs\n  AFTER the drain and pages on the one class nothing above can see: a build whose\n  FIRST publish was lost (``enqueue_attempts=0``), still ``pending``, with no gate\n  explaining the wait. The drain is what increments attempts, so such a row can never\n  reach the thrasher ceiling, and the coalescer used to fold every later push into it\n  -- a repo frozen with no build and no error (2026-09-04).","operationId":"reconcile_index_jobs_v1_internal_index_jobs_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/group-jobs/reconcile":{"post":{"summary":"Reconcile Group Jobs","description":"Reap stranded group-merge builds to ``failed`` AND recover stuck-queued ones.\n\n* The REAP (pure DB, ``BuildRecoverySweeper``) is the durable backstop for a group\n  worker that dies mid-merge -- the fix for Graphify-Ent #117: a cross-repo union\n  OOM-kills the worker mid-``building_index`` before it posts a terminal callback,\n  so the build strands with an expired lease and RE-strands every time a member\n  re-indexes. The reap terminalises each such build ``failed`` (releasing the lease\n  and surfacing the failure) and emits ``stranded_inprogress``.\n* The stuck-queued RECOVERY (pure DB, ``StuckQueuedGroupRecovery``; DARK behind\n  ``stuck_queued_recovery_enabled``) remediates the class NEITHER the reap nor a\n  merge trigger reaches: a merge published EXACTLY ONCE at the ``/merge`` trigger\n  whose SQS message was dead-lettered by a capacity burst, sitting ``queued`` +\n  never-leased forever. Unlike the index/review ticks there is NO outbox drain to\n  republish a flipped row, so the recovery hands the orphans it flipped to\n  ``pending`` back here and we re-publish each via ``enqueue_group_build`` (exactly\n  as the ``/merge`` endpoint does, best-effort). Flag off => not constructed at\n  all; the tick is byte-identical to before.","operationId":"reconcile_group_jobs_v1_internal_group_jobs_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/index-jobs/reindex-catchup/reconcile":{"post":{"summary":"Reconcile Reindex Catchup","description":"Coalescing catch-up sweep for repos the daily push-reindex cap parked.\n\nMeant to run on a slow cadence (a few times a day is enough -- it only needs\nto fire after the UTC midnight counter reset). A no-op when the daily caps are\ndisabled or no repo is behind, so it is safe to schedule unconditionally.","operationId":"reconcile_reindex_catchup_v1_internal_index_jobs_reindex_catchup_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/index-jobs/cost-eval/reconcile":{"post":{"summary":"Reconcile Index Cost Caps","description":"Cost-evaluation sweep (#215): re-classify each tenant that has pending index builds\nagainst its monthly cost cap and set/clear ``tenant.cost_capped_until``.\n\nThis is the ONLY place tenant cost is classified for dispatch fairness; the drain just\nexcludes capped tenants by the marker. Meant to run on its OWN (slow) cadence, decoupled\nfrom the hot dispatch drain -- a sibling of the reindex-catchup tick. A strict no-op when\nthe monthly cost caps are dark (every tenant evaluates under cap, so no marker is set),\nso it is safe to schedule unconditionally. Takes no limit: it evaluates the whole (finite)\nset of tenants with pending builds each run so no over-cap tenant is left unflagged.","operationId":"reconcile_index_cost_caps_v1_internal_index_jobs_cost_eval_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/seats/reconcile":{"post":{"summary":"Reconcile Seats","description":"Reconcile every Team workspace's occupied seats against what it purchased.\n\nFlags first drift with a heal-grace banner, suspends the newest over-quota seats once\npast the grace (never an owner's), and heals back down when the drift resolves. Idempotent\nand time-gated, so it is safe to run on a fixed cadence -- and a strict no-op while Teams\nis dark, since no tenant is ``workspace_kind=team`` yet. Runs under the launcher identity\nlike the other reconcilers; the launcher tick is wired separately (engine-worker).","operationId":"reconcile_seats_v1_internal_seats_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/lifecycle-emails/reconcile":{"post":{"summary":"Reconcile Lifecycle Emails","description":"Lifecycle-email drip: welcome, day-3 and day-5 nudges, then a Pro pitch (day 7).\n\nIdempotent + best-effort, and a STRICT no-op unless armed AND graphify-email is\nconfigured -- safe on the ~60s tick like the other reconcilers. Each nudge is sent\nat most once per user (unique lifecycle_email row claimed before the send).","operationId":"reconcile_lifecycle_emails_v1_internal_lifecycle_emails_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/github-webhooks/reconcile":{"post":{"summary":"Reconcile Github Webhooks","operationId":"reconcile_github_webhooks_v1_internal_github_webhooks_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/github-webhooks/retention/reconcile":{"post":{"summary":"Reconcile Github Webhook Retention","description":"Prune expired terminal `github_webhook_delivery` rows (ignored 7d, processed 30d).\n\nIts OWN route, deliberately not folded into `github-webhooks/reconcile`: that call's\nbudget is the review critical path and has already starved twice. Bounded per call\n(batched deletes inside a wall-clock budget) and a strict no-op once the backlog is\npruned, so it is safe on every tick. Never touches `queued` or `failed`.","operationId":"reconcile_github_webhook_retention_v1_internal_github_webhooks_retention_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/oauth-tokens/retention/reconcile":{"post":{"summary":"Reconcile Oauth Token Retention","description":"Delete `oauth_refresh_token` families that are terminally dead (revoked 7d+).\n\nIts own route rather than folded into a hot reconcile, for the same reason as\n`github-webhooks/retention`: nothing here is on a critical path, so it must never\ncompete for another tick's budget. Bounded per call and a strict no-op once the\nbacklog is clear, so it is safe on every tick. Only families with no live handle\nare eligible -- see app/oauth/retention.","operationId":"reconcile_oauth_token_retention_v1_internal_oauth_tokens_retention_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/gitlab-webhooks/reconcile":{"post":{"summary":"Reconcile Gitlab Webhooks","operationId":"reconcile_gitlab_webhooks_v1_internal_gitlab_webhooks_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/repository-purge/reconcile":{"post":{"summary":"Reconcile Repository Purges","description":"Drain the repository purge outbox: all versions + delete markers per prefix.\n\nA repository removal commits its S3 work here rather than running it in the\nrequest (a large repo is hundreds of builds x objects x versions). Always 2xx: the\nlauncher fails the rest of its reconcile tick on any non-2xx, and a prefix that\ncannot be purged is a counted row plus a >24h WARNING, never a failed tick.\n\nFirst removes repositories GitHub reported gone whose grace has passed\n(app/services/repository_gone.py), so their purge rows drain in the same tick.\nPiggybacks here so no launcher change is needed.","operationId":"reconcile_repository_purges_v1_internal_repository_purge_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/index-jobs/{job_id}/claim":{"post":{"summary":"Claim Index Job","operationId":"claim_index_job_v1_internal_index_jobs__job_id__claim_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/index-jobs/{job_id}/renew":{"post":{"summary":"Renew Index Job","operationId":"renew_index_job_v1_internal_index_jobs__job_id__renew_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/index-jobs/{job_id}/repository-token":{"post":{"summary":"Issue Index Job Repository Token","operationId":"issue_index_job_repository_token_v1_internal_index_jobs__job_id__repository_token_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/tenants/{tenant_id}/index-jobs/{job_id}/callbacks":{"post":{"summary":"Index Job Callback","operationId":"index_job_callback_v1_internal_tenants__tenant_id__index_jobs__job_id__callbacks_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Signature"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/review-runs/{job_id}/start":{"post":{"summary":"Start Review Run","description":"A review worker claiming its run: a lease, a clone token, and the callback\nsecret it will sign results with.\n\n`InternalWorker` has already proved the caller holds a token minted for this\n`{job_id}`. The clone token (repository-scoped, read-only) and the tenant\ncallback secret (derived, never stored) are minted here and returned exactly\nonce -- they never touch the `/result` path and are never logged.","operationId":"start_review_run_v1_internal_review_runs__job_id__start_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewStartRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/review-runs/{job_id}/peer-graphs":{"get":{"summary":"Review Run Peer Graphs","description":"Presigned reads of the review's workspace peers' PROMOTED graphs.\n\nThe review worker calls this during ``_analyse`` to stitch the PR's head graph\nwith its group peers' promoted graphs (cross-repo blast radius). Auth is the\nSAME strength as the sibling ``/result`` route -- a job token bound to this\n``{job_id}`` (``InternalWorker``) PLUS an active review lease -- so only the\nworker currently leasing this run can fetch peers; there is no weaker path.\n\nEverything that selects a graph is derived from the AUTHENTICATED run, never\nfrom client input: the tenant is read from the run row, and the workspace id is\nread from the run's own (server-written, worker-immutable) envelope. There is no\nclient-supplied ``group_id`` or member id to forge or guess -- a review can only\never reach its own tenant's own workspace. Peers are resolved live from DB\nmembership and are PROMOTED-only; un-promoted members degrade to a skip+count.","operationId":"review_run_peer_graphs_v1_internal_review_runs__job_id__peer_graphs_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/review-runs/{job_id}/scip":{"get":{"summary":"Review Run Scip","description":"Presigned reads of the workspace members' promoted SCIP artifacts + manifests,\nfor the review worker's cross-repo TRUST chain (issue #210).\n\nSame auth + tenant-derivation guarantees as ``/peer-graphs`` (a job token bound to\nthis run PLUS an active lease; the tenant/group/home/base-SHA all read from the\nAUTHENTICATED run, never from client input). Gated behind BOTH the cross-repo group\nflag AND a dedicated ``scip_trust_enabled`` flag, so it 404s until the gate-capable\npath is deliberately armed. The service applies the package-collision + base-SHA\nprovenance downgrades before returning anything (see ``presign_group_scip``).","operationId":"review_run_scip_v1_internal_review_runs__job_id__scip_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/review-runs/{job_id}/base-graph":{"get":{"summary":"Review Run Base Graph","description":"A presigned read of THIS review repo's own promoted graph, to seed the\nreview's BASE graph instead of cold-extracting the base checkout (issue #2).\n\nAuth is the SAME strength as the sibling ``/peer-graphs`` and ``/result``\nroutes -- a job token bound to this ``{job_id}`` (``InternalWorker``) PLUS an\nactive review lease -- so only the worker currently leasing this run can fetch\nthe base, and the tenant + repo are read from the AUTHENTICATED run row, never\nfrom client input. Unlike ``/peer-graphs`` there is no workspace requirement:\nthe base graph is the repo's OWN promoted build.\n\nDark by default: gated behind ``review_seed_base_from_promoted_enabled`` so it\n404s until armed (the worker then cold-builds the base, today's behaviour). A\nrepo with no promoted build surfaces the usual graph-absence error, which the\nworker also treats as \"cold-build the base\" -- so a never-indexed repo is a\nclean fallback, not a failure.","operationId":"review_run_base_graph_v1_internal_review_runs__job_id__base_graph_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/review-runs/{job_id}/extract-cache":{"get":{"summary":"Review Run Extract Cache","description":"A presigned read of THIS review repo's latest index AST-cache bundle, so the\nreview worker can pre-warm its HEAD extraction and re-parse only the PR's\nchanged files (issue #2, Phase 2 -- cold-identical head, extraction cost ∝ the\ndelta).\n\nSame auth as ``/base-graph`` and ``/peer-graphs`` -- a job token bound to this\n``{job_id}`` plus an active lease; tenant + repo read from the AUTHENTICATED run.\nDark by default behind ``review_incremental_head_enabled`` (404 until armed ->\nthe worker cold-builds the head, today's behaviour). A repo with no promoted\nbuild surfaces the usual graph-absence error, and a missing bundle object is a\ndownload-time 404 -- both are clean cold-build fallbacks, never a failure.","operationId":"review_run_extract_cache_v1_internal_review_runs__job_id__extract_cache_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/review-runs/{job_id}/result":{"post":{"summary":"Review Run Result","description":"A review worker reporting progress or its final review + gate verdict.\n\n`InternalWorker` has already proved the caller holds a token minted for this\n`{job_id}`. Unlike the index callback there is no `{tenant_id}` in the path:\nthe review route carries only the job id, so the tenant is read from the run\nitself and the callback is verified with *that* tenant's derived secret. A\nheader-supplied tenant is never trusted -- it would let a valid token pick\nwhich tenant's secret verifies the body.","operationId":"review_run_result_v1_internal_review_runs__job_id__result_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Signature"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/fv-runs/{job_id}/start":{"post":{"summary":"Start Fv Run","description":"An FV runner claiming its run: a lease, a read-only clone token, the tenant\ncallback secret, and the TRUSTED verification policy.\n\nEligibility (entitlement, kill switch, fork) is re-checked inside ``start_fv``;\nan ineligible or superseded run is terminalised there and this raises 409, so\nno expensive verification ever begins on a stale/unentitled run.","operationId":"start_fv_run_v1_internal_fv_runs__job_id__start_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FvStartRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/fv-runs/{job_id}/renew":{"post":{"summary":"Renew Fv Run","description":"Extend an FV runner's lease, or tell it the run was cancelled/superseded/expired.\n\nA ``cancelled: true`` response is the runner's signal to kill its repo-code\nchildren and exit; the lease never extends the absolute run deadline. Uses\n``FvRunnerForRenew`` (wired, not enabled) so flipping the global kill switch\n(``fv_pipeline_enabled``) off still reaches ``renew_fv`` and cancels already-leased\nruns within one renew cycle, instead of 503ing the STOP path. (#198)","operationId":"renew_fv_run_v1_internal_fv_runs__job_id__renew_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FvRenewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/fv-runs/{job_id}/result":{"post":{"summary":"Fv Run Result","description":"An FV runner reporting progress or its final verification result.\n\nAs with review, the tenant is read from the run (never a header), the callback\nis verified with that tenant's derived secret, and the write-capable GitHub\ntoken is minted HERE -- never handed to the runner that executed repo code.","operationId":"fv_run_result_v1_internal_fv_runs__job_id__result_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Signature"}},{"name":"X-Graphify-Lease-Token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Lease-Token"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/fv-runs/reconcile":{"post":{"summary":"Reconcile Fv Runs","description":"Drain the pending FV outbox, expire runs past their deadline, and re-drive\nREADY runs whose GitHub write-back failed transiently.\n\nThe sweeper (pure DB, deadline expiry) runs on every tick regardless of whether\nthe pipeline is currently configured, so a run stranded by a mid-flight disable\nis still terminalised. The pending-outbox drain runs only when FV is live. The\nwrite-back re-drive (see ``_redrive_fv_writeback_failures``) runs whenever the\nGitHub App is configured and never fails the tick.","operationId":"reconcile_fv_runs_v1_internal_fv_runs_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/review-runs/reconcile":{"post":{"summary":"Reconcile Review Runs","description":"Sweep stranded review runs to ``failed``, drain the pending review outbox, AND\nre-drive READY runs whose GitHub write-back failed transiently\n(``_redrive_review_writeback_failures`` -- runs whenever the GitHub App is\nconfigured, never fails the tick).\n\nTwo independent recoveries share this one tick, mirroring\n``reconcile_fv_runs``:\n\n* The SWEEP (pure DB, ``ReviewRecoverySweeper``) runs on EVERY tick regardless\n  of whether review is currently configured, so a run stranded by a mid-flight\n  disable is still terminalised. A worker that dies mid-build never posts a\n  terminal callback, so its run sits in ``reviewing`` / ``provisioning`` with a\n  merely-EXPIRED lease -- untouched by the projector (which rejects an expired\n  lease) and invisible to the outbox drain (which only re-drives ``pending``\n  rows, and a stranded run is already ``enqueued``). The sweep marks every such\n  run ``failed`` so a lost worker SURFACES instead of stranding forever.\n* The strand RETRY (pure DB, ``StrandedReviewRetry``; DARK behind\n  ``review_strand_retry_enabled``) re-dispatches what the sweep terminalised. The\n  sweep's ``lease_expired`` verdict is a guess -- the run produced no result because\n  the worker was reclaimed or its terminal callback never landed -- and same-head\n  idempotency means only a new push re-runs it today. Bounded by\n  ``recovery_attempts``; it waits out a grace, so a run swept on THIS tick is never\n  retried on it (a late terminal callback, which the projector now accepts on a\n  stranded run, gets first claim on delivering the real result).\n* The DRAIN re-drives ``outbox_status=\"pending\"`` rows whose SQS publish failed\n  transiently -- without it a single transient publish fault stranded the\n  review, unsurfaced. It no-ops (zeros) when review is not configured, so this\n  tick is safe on every deployment. Re-driving is safe: ``enqueue_review``\n  no-ops a run already committed as \"enqueued\", and the transport collapses a\n  republish of the SAME run inside FIFO's dedup window (its dedup id is salted\n  with the run's fixed job_id), as for the index/FV outbox siblings.\n* The stuck-queued RECOVERY (pure DB, ``StuckQueuedReviewRecovery``; DARK behind\n  ``stuck_queued_recovery_enabled``) remediates the class NEITHER of the above can\n  reach: dispatched (``enqueued``) but NEVER-leased ``queued`` runs whose SQS\n  message was dead-lettered by a capacity burst -- the sweep requires a dead lease,\n  the drain only sees ``pending``. It runs BETWEEN sweep and drain so a run it\n  flips back to ``pending`` is republished later this same tick. Flag off => not\n  constructed at all; the tick is byte-identical to before.","operationId":"reconcile_review_runs_v1_internal_review_runs_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/fv-runs/{job_id}/attempts/{attempt_number}/accepted":{"post":{"summary":"Fv Attempt Accepted","description":"Record that an FV attempt's ECS task reached RUNNING: its task ARN, capacity\nprovider, task-def, and image digest.","operationId":"fv_attempt_accepted_v1_internal_fv_runs__job_id__attempts__attempt_number__accepted_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"attempt_number","in":"path","required":true,"schema":{"type":"integer","maximum":100000,"minimum":1,"title":"Attempt Number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FvAttemptAcceptedRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/fv-runs/{job_id}/attempts/{attempt_number}/stopped":{"post":{"summary":"Fv Attempt Stopped","description":"Record that an FV attempt's ECS task STOPPED, with its stop code / exit code\nand the typed failure family. First stop wins (idempotent).","operationId":"fv_attempt_stopped_v1_internal_fv_runs__job_id__attempts__attempt_number__stopped_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"attempt_number","in":"path","required":true,"schema":{"type":"integer","maximum":100000,"minimum":1,"title":"Attempt Number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FvAttemptStoppedRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/fv-runs/orphans":{"get":{"summary":"List Fv Orphans","description":"ECS tasks the reconciler/dispatcher should StopTask: still RUNNING per our\nrecords but whose FV run is already terminal or superseded (orphans). The\nterminal/superseded gate is the guard that a live retry is never listed.","operationId":"list_fv_orphans_v1_internal_fv_runs_orphans_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/fv-runs/{run_id}/redrive":{"post":{"summary":"Fv Run Redrive","description":"Re-dispatch a run whose live SQS message died in the FV DLQ.\n\nCalled by the ``graphify-fv-redriver`` draining the FV dead-letter queue.\n``attempt`` is the ``attempt`` the DLQ message carried, which anchors the\nidempotency guard against re-delivery. The body's ``action`` (``redriven`` /\n``dropped`` / ``deferred``) tells the drainer whether to delete or leave the DLQ\nmessage. ``FvRunnerRequired`` (not the direct-session recorder the attempt\nendpoints use) because redrive re-publishes through the transport, which is only\nwired when FV is configured -- during a mid-flight disable this 503s and the\ndrainer leaves the message, which is the intended \"retry when FV is back\"\nbehaviour.","operationId":"fv_run_redrive_v1_internal_fv_runs__run_id__redrive_post","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}},{"name":"attempt","in":"query","required":true,"schema":{"type":"integer","maximum":10,"minimum":1,"title":"Attempt"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/learning":{"get":{"summary":"Learning","operationId":"learning_v1_learning_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repo","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repo"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mcp/connections/me":{"get":{"summary":"My Agent Connection","description":"The caller's own agent connection state, seen from the active workspace.\n\nMembership is enforced by the tenant context and the read is pinned to the caller's\nuser id, so nobody sees another member's activity. It is NOT pinned to this tenant:\nan agent bound to another of the caller's workspaces comes back as ``elsewhere``\n(named only while the caller is still a member there), so a multi-workspace user who\ndid connect is not left waiting. A principal with no user row (a service token, dev\nauth) has no agent of its own and reads as not connected.\n\nPollable, but the consumer should back off and stop on success or a hidden tab: the\nsingle-workspace case is one LIMIT 1 index read, the elsewhere case up to three.","operationId":"my_agent_connection_v1_mcp_connections_me_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/facts":{"get":{"summary":"Memory Facts","operationId":"memory_facts_v1_memory_facts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"query","required":true,"schema":{"type":"string","title":"Repository Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":60,"title":"Limit"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/recall":{"post":{"summary":"Memory Recall","description":"Dashboard RANKED recall -- the search box runs the real cross-encoder path on the\nfleet, not client-side string scoring. Same gate + bearer-forwarding as the facts\nbrowse; an unbuilt store is an honest-empty 200.","operationId":"memory_recall_v1_memory_recall_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryRecallBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/turns":{"get":{"summary":"Memory Turns","description":"Resolve a fact's source turns to verbatim text for the drawer. ``ids`` is the\ncomma-separated ``source_turn_ids``. An empty list (nothing to resolve) is an\nhonest-empty 200 that never touches the fleet.","operationId":"memory_turns_v1_memory_turns_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"query","required":true,"schema":{"type":"string","title":"Repository Id"}},{"name":"ids","in":"query","required":false,"schema":{"type":"string","default":"","title":"Ids"}},{"name":"record_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Record Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/stats":{"get":{"summary":"Memory Stats","description":"The dashboard stat strip for a repository. Same gate as the facts browse; an\nunbuilt store is honest-zeros.","operationId":"memory_stats_v1_memory_stats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"query","required":true,"schema":{"type":"string","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/brief":{"post":{"summary":"Memory Brief","operationId":"memory_brief_v1_memory_brief_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/inspect":{"post":{"summary":"Memory Inspect","operationId":"memory_inspect_v1_memory_inspect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/records/query":{"post":{"summary":"Query Records","operationId":"query_records_v1_memory_records_query_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"enum":["newest","oldest"],"type":"string"},{"type":"null"}],"title":"Sort"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/entities/query":{"post":{"summary":"Query Entities","operationId":"query_entities_v1_memory_entities_query_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"enum":["newest","oldest"],"type":"string"},{"type":"null"}],"title":"Sort"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/entities/records/query":{"post":{"summary":"Query Entity Records","operationId":"query_entity_records_v1_memory_entities_records_query_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"subject_id","in":"query","required":true,"schema":{"type":"string","title":"Subject Id"}},{"name":"subject_kind","in":"query","required":true,"schema":{"type":"string","title":"Subject Kind"}},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"enum":["newest","oldest"],"type":"string"},{"type":"null"}],"title":"Sort"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/records/{record_id}":{"get":{"summary":"Detail Record","operationId":"detail_record_v1_memory_records__record_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"string","title":"Record Id"}},{"name":"repository_id","in":"query","required":true,"schema":{"type":"string","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/records":{"post":{"summary":"Create Record","operationId":"create_record_v1_memory_records_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/ask/{ask_query_id}/save":{"post":{"summary":"Save Ask Record","operationId":"save_ask_record_v1_memory_ask__ask_query_id__save_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ask_query_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ask Query Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/records/{record_id}/revisions":{"post":{"summary":"Revise Record","operationId":"revise_record_v1_memory_records__record_id__revisions_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"string","title":"Record Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/records/{record_id}/undo-auto-publish":{"post":{"summary":"Undo Auto Publish","description":"One-click undo of a memory the workspace's agent added automatically.\n\nServer-side and permanent: the record's auto-published version is dismissed by the\nperson who clicked (an ordinary ``dismiss`` revision, so the outbox command and its\n``human_record`` evidence are the audit trail, plus a ``memory.auto_publish_undone``\naudit row). Idempotent: repeating the click returns the same command, or reports\nthat the undo already happened. Only a version added automatically can be undone\nhere; anything else is a normal revision.","operationId":"undo_auto_publish_v1_memory_records__record_id__undo_auto_publish_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"string","title":"Record Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/captures/{event_id}":{"get":{"summary":"Capture Status","operationId":"capture_status_v1_memory_captures__event_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","title":"Event Id"}},{"name":"repository_id","in":"query","required":true,"schema":{"type":"string","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/records/{record_id}/usage":{"get":{"summary":"Record Usage History","operationId":"record_usage_history_v1_memory_records__record_id__usage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"string","title":"Record Id"}},{"name":"repository_id","in":"query","required":true,"schema":{"type":"string","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{run_id}/memory-lesson":{"post":{"summary":"Save Review Lesson","operationId":"save_review_lesson_v1_reviews__run_id__memory_lesson_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/quality/inbox":{"get":{"summary":"Memory Quality Inbox","operationId":"memory_quality_inbox_v1_memory_quality_inbox_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repository Id"}},{"name":"repositoryId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repositoryid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":5,"title":"Limit"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memory/quality/weekly":{"get":{"summary":"Memory Quality Weekly","operationId":"memory_quality_weekly_v1_memory_quality_weekly_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repository Id"}},{"name":"repositoryId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repositoryid"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/public/profiles/{username}":{"get":{"tags":["public"],"summary":"Read Public Profile","description":"A published profile, by handle. Anonymous, read-only, allowlisted.\n\nA handle asked for in the wrong case, or by a handle its owner has since renamed\naway from, answers 200 with ``canonicalUsername`` set and no profile body -- the\ncaller (the page route) turns that into a 307 to the canonical URL. Visibility is\nre-checked before the redirect is offered, so a redirect cannot confirm a private\nprofile exists.\n\nA read that FAILS must surface as a 5xx, never as this 404: a transient database\nerror answered \"no such user\" is a lie that crawlers and caches will keep.","operationId":"read_public_profile_v1_public_profiles__username__get","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string","title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/public/profiles/{username}/avatar":{"get":{"tags":["public"],"summary":"Read Public Avatar","description":"The uploaded picture of a published profile, as image bytes.\n\nBytes, not a redirect: a presigned URL names the internal user id, and the OG card\nrenderer fetches with ``redirect: \"manual\"``. ``private`` so no shared cache can keep\nserving it after the owner unpublishes; ``?v=`` busts the viewer's own copy on change.\nAn S3 failure is a 503, never a cacheable 404.","operationId":"read_public_avatar_v1_public_profiles__username__avatar_get","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string","title":"Username"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/query/{tool_name}":{"post":{"summary":"Run Query","operationId":"run_query_v1_query__tool_name__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tool_name","in":"path","required":true,"schema":{"type":"string","title":"Tool Name"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mcp":{"get":{"summary":"Mcp Proxy","description":"Proxy MCP Streamable HTTP to the pooled query fleet.\n\nThe response is streamed rather than buffered. MCP replies may be\ntext/event-stream, and reading one to completion before returning would\ndefeat the point of a streaming transport and stall the client until the\nwhole exchange finished.\n\nThree credentials reach this door. An OAuth bearer from the broker takes the\narmed path (verify, resolve the active workspace, mint a fleet token) or, with\nno signer configured, the dark path that forwards it unchanged for the query\nservice to verify independently. A `gfy_mcp_` Workspace API Token takes the\ntoken path instead: it names its own workspace, so it is verified here and a\nfleet token is minted for it -- the raw token is never forwarded.","operationId":"mcp_proxy_v1_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Mcp Proxy","description":"Proxy MCP Streamable HTTP to the pooled query fleet.\n\nThe response is streamed rather than buffered. MCP replies may be\ntext/event-stream, and reading one to completion before returning would\ndefeat the point of a streaming transport and stall the client until the\nwhole exchange finished.\n\nThree credentials reach this door. An OAuth bearer from the broker takes the\narmed path (verify, resolve the active workspace, mint a fleet token) or, with\nno signer configured, the dark path that forwards it unchanged for the query\nservice to verify independently. A `gfy_mcp_` Workspace API Token takes the\ntoken path instead: it names its own workspace, so it is verified here and a\nfleet token is minted for it -- the raw token is never forwarded.","operationId":"mcp_proxy_v1_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"delete":{"summary":"Mcp Proxy","description":"Proxy MCP Streamable HTTP to the pooled query fleet.\n\nThe response is streamed rather than buffered. MCP replies may be\ntext/event-stream, and reading one to completion before returning would\ndefeat the point of a streaming transport and stall the client until the\nwhole exchange finished.\n\nThree credentials reach this door. An OAuth bearer from the broker takes the\narmed path (verify, resolve the active workspace, mint a fleet token) or, with\nno signer configured, the dark path that forwards it unchanged for the query\nservice to verify independently. A `gfy_mcp_` Workspace API Token takes the\ntoken path instead: it names its own workspace, so it is verified here and a\nfleet token is minted for it -- the raw token is never forwarded.","operationId":"mcp_proxy_v1_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/z7k2m9v3x8w":{"post":{"summary":"Relay To Email Service","operationId":"relay_to_email_service_v1_z7k2m9v3x8w_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/integrations/sentry/connect":{"post":{"summary":"Sentry Connect","operationId":"sentry_connect_v1_integrations_sentry_connect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryConnectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/sentry/status":{"get":{"summary":"Sentry Status","operationId":"sentry_status_v1_integrations_sentry_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/sentry":{"delete":{"summary":"Sentry Disconnect","operationId":"sentry_disconnect_v1_integrations_sentry_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/slack/install-url":{"post":{"summary":"Slack Install Url","operationId":"slack_install_url_v1_integrations_slack_install_url_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackInstallUrlRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/slack/callback":{"get":{"summary":"Slack Callback","description":"Browser-navigated: always redirects back to the app with a status word.","operationId":"slack_callback_v1_integrations_slack_callback_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"State"}},{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Code"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/slack/status":{"get":{"summary":"Slack Status","operationId":"slack_status_v1_integrations_slack_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/slack/settings":{"patch":{"summary":"Slack Settings","operationId":"slack_settings_v1_integrations_slack_settings_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackSettingsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/slack/channels":{"get":{"summary":"Slack Channels","operationId":"slack_channels_v1_integrations_slack_channels_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/slack":{"delete":{"summary":"Slack Disconnect","operationId":"slack_disconnect_v1_integrations_slack_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/slack/events":{"post":{"summary":"Slack Events","operationId":"slack_events_v1_integrations_slack_events_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/integrations/slack/interactions":{"post":{"summary":"Slack Interactions","description":"Block Kit button clicks (Approve/Deny). Signed like events. The decision is\nsaved (one atomic update) BEFORE acking, so a restart can't lose an accepted click;\nthe Slack follow-up and the approved run go to the background, and the reconcile\ntick re-runs an approval that a restart interrupted.","operationId":"slack_interactions_v1_integrations_slack_interactions_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/slack-events/reconcile":{"post":{"summary":"Reconcile Slack Events","description":"Re-run turns a control-plane roll dropped. Returns at once; the work runs in\nthe background (each turn re-checks its own claim).","operationId":"reconcile_slack_events_v1_internal_slack_events_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackReconcileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/specs":{"post":{"summary":"Create Spec","description":"Validate up to five English properties of one Python function.","operationId":"create_spec_v1_repos__repository_id__specs_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpecRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/specs/{job_id}":{"get":{"summary":"Get Spec","operationId":"get_spec_v1_specs__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/specs/{job_id}/draft-pr":{"post":{"summary":"Open Spec Pr","description":"Open the validated entry as a draft PR on ``graphify/spec-<job>``. Needs the\ninstallation's contents:write grant; never writes the default branch.","operationId":"open_spec_pr_v1_specs__job_id__draft_pr_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/spec-runs/{job_id}/start":{"post":{"summary":"Start Spec Run","description":"A spec worker claiming its job: a READ-only single-repo token, the tenant\ncallback secret and the base sha.","operationId":"start_spec_run_v1_internal_spec_runs__job_id__start_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpecStartRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/internal/spec-runs/{job_id}/status":{"post":{"summary":"Spec Run Status","description":"A spec worker's signed progress or result (job token + HMAC, sequence-idempotent).","operationId":"spec_run_status_v1_internal_spec_runs__job_id__status_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Job Id"}},{"name":"X-Graphify-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Graphify-Signature"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/rules/export":{"get":{"summary":"Export Team Rules","operationId":"export_team_rules_v1_repos__repository_id__rules_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}},{"name":"format","in":"query","required":false,"schema":{"enum":["skill","fragment"],"type":"string","default":"skill","title":"Format"}},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/repos/{repository_id}/test-impact":{"post":{"summary":"Repo Test Impact","operationId":"repo_test_impact_v1_repos__repository_id__test_impact_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Repository Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestImpactRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Repo Test Impact V1 Repos  Repository Id  Test Impact Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/test-impact":{"get":{"summary":"Test Impact Status","operationId":"test_impact_status_v1_integrations_test_impact_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Test Impact Toggle","operationId":"test_impact_toggle_v1_integrations_test_impact_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestImpactToggleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/usage/savings":{"get":{"summary":"Usage Savings","description":"The honest token-savings headline for the caller's workspace (#127).\n\nSavings vs the GROUNDED answer-bearing baseline (not the ungrounded counterfactual),\ndeduped + signed + token-weighted through the shared econ_meter primitive. A workspace\nwith no grounded rows yet gets an honest zero (``verified_queries == 0``), never a\nfabricated number. Authed tenant scope only — a caller sees only its own metering.","operationId":"usage_savings_v1_usage_savings_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Repository Id"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/usage":{"get":{"summary":"Usage Current","description":"Per-plan usage counter for the caller's workspace (2026-09-25).\n\nReturns each capped feature's ``used / limit / window / resets_at / state`` for the\ntenant's plan -- the SAME per-plan caps + counts the admission gates enforce, so the\ndashboard meter and the enforcement never disagree. A dark (unarmed) cap surfaces as\n``limit=null``. Authed tenant scope only.","operationId":"usage_current_v1_usage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/usage/history":{"get":{"summary":"Usage History","description":"Daily per-feature usage history for the caller's workspace (last ``days``, max 90).\n\n``series`` maps each feature (fv_runs / reviews / index_builds / group_builds) to a\nlist of ``{date, count}`` per UTC day. Authed tenant scope only.","operationId":"usage_history_v1_usage_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":30,"title":"Days"}},{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/vercel/install":{"post":{"tags":["vercel"],"summary":"Install","description":"Server-to-server from the app's callback, before login: spend the code now.\n\nUnauthenticated by design: the code itself is the credential, and the result\nstays unbound until the browser holding ``claim`` signs in and picks a workspace.","operationId":"install_v1_integrations_vercel_install_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__vercel__InstallInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/vercel/prepare":{"post":{"tags":["vercel"],"summary":"Prepare","operationId":"prepare_v1_integrations_vercel_prepare_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__vercel__PrepareInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/vercel/status":{"post":{"tags":["vercel"],"summary":"Status","operationId":"status_v1_integrations_vercel_status_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallationInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/vercel/connect":{"post":{"tags":["vercel"],"summary":"Connect","operationId":"connect_v1_integrations_vercel_connect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__vercel__ConnectInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/vercel/disconnect":{"post":{"tags":["vercel"],"summary":"Disconnect","operationId":"disconnect_v1_integrations_vercel_disconnect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/vercel/webhook":{"post":{"tags":["vercel"],"summary":"Webhook","operationId":"webhook_v1_integrations_vercel_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/internal/integrations/vercel/reconcile":{"post":{"tags":["vercel"],"summary":"Reconcile","description":"Launcher tick. Runs even with issuance off: revocation must keep working.","operationId":"reconcile_v1_internal_integrations_vercel_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/install":{"post":{"tags":["origin"],"summary":"Install","operationId":"install_v1_integrations_origin_install_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__origin__InstallInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/state":{"post":{"tags":["origin"],"summary":"State","operationId":"state_v1_integrations_origin_state_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/integrations/origin/pending":{"post":{"tags":["origin"],"summary":"Pending","operationId":"pending_v1_integrations_origin_pending_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/prepare":{"post":{"tags":["origin"],"summary":"Prepare","operationId":"prepare_v1_integrations_origin_prepare_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__origin__PrepareInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/status":{"post":{"tags":["origin"],"summary":"Status","operationId":"status_v1_integrations_origin_status_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/refresh":{"post":{"tags":["origin"],"summary":"Refresh","operationId":"refresh_v1_integrations_origin_refresh_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/connect":{"post":{"tags":["origin"],"summary":"Connect","operationId":"connect_v1_integrations_origin_connect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__origin__ConnectInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/disconnect":{"post":{"tags":["origin"],"summary":"Disconnect","operationId":"disconnect_v1_integrations_origin_disconnect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/connections":{"get":{"tags":["origin"],"summary":"Connections","operationId":"connections_v1_integrations_origin_connections_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Graphify-Tenant-ID","in":"header","required":true,"schema":{"type":"string","title":"X-Graphify-Tenant-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrations/origin/webhook":{"post":{"tags":["origin"],"summary":"Webhook","operationId":"webhook_v1_integrations_origin_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AgentPatternQuery":{"properties":{"query":{"type":"string","maxLength":4096,"title":"Query","default":""},"paths":{"items":{"type":"string","maxLength":2048},"type":"array","maxItems":20,"title":"Paths"},"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","default":20},"offset":{"type":"integer","maximum":10000.0,"minimum":0.0,"title":"Offset","default":0},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"proactive":{"type":"boolean","title":"Proactive","default":false},"build_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Build Id"},"manifest_sha256":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Manifest Sha256"}},"additionalProperties":false,"type":"object","title":"AgentPatternQuery"},"AgentWorkspaceUpdate":{"properties":{"tenantId":{"type":"string","format":"uuid","title":"Tenantid"}},"additionalProperties":false,"type":"object","required":["tenantId"],"title":"AgentWorkspaceUpdate","description":"The body of ``PUT /v1/profile/agent-workspace`` (AD-MCP-1): the workspace a user's\nagent (MCP/gx) should point at. Writes ``user.default_tenant_id`` as the authority.\nAccepts ``tenantId`` (camelCase) or ``tenant_id``; membership is validated server-side."},"ApiKeyCreate":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"scopes":{"items":{"type":"string"},"type":"array","maxItems":8,"title":"Scopes"}},"additionalProperties":false,"type":"object","required":["name"],"title":"ApiKeyCreate"},"AutofixReconcileRequest":{"properties":{"limit":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Limit","default":100}},"additionalProperties":false,"type":"object","title":"AutofixReconcileRequest"},"AutofixStartRequest":{"properties":{"owner":{"type":"string","maxLength":128,"minLength":3,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Owner"},"leaseSeconds":{"type":"integer","maximum":7200.0,"minimum":30.0,"title":"Leaseseconds","default":1800}},"additionalProperties":false,"type":"object","required":["owner"],"title":"AutofixStartRequest"},"AvatarConfirmRequest":{"properties":{"key":{"type":"string","maxLength":512,"minLength":1,"title":"Key"}},"type":"object","required":["key"],"title":"AvatarConfirmRequest","description":"Adopt an uploaded object. `key` is one WE issued -- still client input, so the\nserver re-checks it belongs to the caller's own prefix."},"AvatarUploadRequest":{"properties":{"contentType":{"type":"string","maxLength":100,"minLength":3,"title":"Contenttype"}},"type":"object","required":["contentType"],"title":"AvatarUploadRequest","description":"Ask for a presigned PUT. The client declares the type it is about to send; it is\npinned into the signature, so sending something else fails at S3."},"BillingCheckoutRequest":{"properties":{"plan":{"type":"string","enum":["team","pro","teams"],"title":"Plan"},"seats":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Seats"},"interval":{"type":"string","enum":["month","year"],"title":"Interval","default":"month"},"successUrl":{"type":"string","minLength":1,"format":"uri","title":"Successurl"},"cancelUrl":{"type":"string","minLength":1,"format":"uri","title":"Cancelurl"}},"additionalProperties":false,"type":"object","required":["plan","seats","successUrl","cancelUrl"],"title":"BillingCheckoutRequest"},"BillingDowngradeRequest":{"properties":{"confirmSuspendMembers":{"type":"boolean","title":"Confirmsuspendmembers","default":false},"expectedMemberCount":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Expectedmembercount"}},"additionalProperties":false,"type":"object","title":"BillingDowngradeRequest","description":"POST /v1/billing/downgrade (Teams -> Pro, AD-FLOW-2, owner-only). A workspace with\nmore than one active developer seat must confirm member suspension AND pass the\ncurrent member count it observed, so a stale UI cannot silently strand members."},"BillingIntervalSwitchRequest":{"properties":{"interval":{"type":"string","enum":["month","year"],"title":"Interval"},"confirm":{"type":"boolean","title":"Confirm","default":false}},"additionalProperties":false,"type":"object","required":["interval"],"title":"BillingIntervalSwitchRequest","description":"POST /v1/billing/interval -- switch the billing interval, same plan tier + seats.\n\n``month`` -> ``year`` is immediate + prorated (two-phase: an unconfirmed request\nreturns a proration preview; ``confirm=true`` commits). ``year`` -> ``month`` is\nscheduled at the period boundary (no refund)."},"BillingUpgradeRequest":{"properties":{"seats":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Seats"},"inPlace":{"type":"boolean","title":"Inplace","default":true},"successUrl":{"type":"string","minLength":1,"format":"uri","title":"Successurl"},"cancelUrl":{"type":"string","minLength":1,"format":"uri","title":"Cancelurl"},"confirm":{"type":"boolean","title":"Confirm","default":false}},"additionalProperties":false,"type":"object","required":["seats","successUrl","cancelUrl"],"title":"BillingUpgradeRequest","description":"POST /v1/billing/upgrade (Pro -> Teams, AD-FLOW-1). Two-phase: an unconfirmed\nin-place request returns a proration preview; ``confirm=true`` commits the swap."},"Body_revoke_oauth_revoke_post":{"properties":{"token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},"type":"object","title":"Body_revoke_oauth_revoke_post"},"Body_token_oauth_token_post":{"properties":{"grant_type":{"type":"string","title":"Grant Type"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"code_verifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Verifier"},"redirect_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Uri"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"}},"type":"object","required":["grant_type"],"title":"Body_token_oauth_token_post"},"CapaCreate":{"properties":{"outcome":{"type":"string","enum":["dismissed","fixed"],"title":"Outcome"},"problem":{"type":"string","maxLength":4000,"title":"Problem","default":""},"rootCause":{"type":"string","maxLength":4000,"title":"Rootcause","default":""},"preventativeAction":{"type":"string","maxLength":4000,"title":"Preventativeaction","default":""}},"additionalProperties":false,"type":"object","required":["outcome"],"title":"CapaCreate"},"CapaPrefill":{"properties":{"outcome":{"type":"string","enum":["dismissed","fixed"],"title":"Outcome"}},"additionalProperties":false,"type":"object","required":["outcome"],"title":"CapaPrefill"},"CapaUpdate":{"properties":{"ruleStatus":{"type":"string","enum":["proposed","added"],"title":"Rulestatus"}},"additionalProperties":false,"type":"object","required":["ruleStatus"],"title":"CapaUpdate"},"ClaimRequest":{"properties":{"owner":{"type":"string","maxLength":128,"minLength":3,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Owner"},"leaseSeconds":{"type":"integer","maximum":3600.0,"minimum":30.0,"title":"Leaseseconds","default":900}},"additionalProperties":false,"type":"object","required":["owner"],"title":"ClaimRequest"},"ConnectionInput":{"properties":{"installationId":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Installationid"}},"type":"object","required":["installationId"],"title":"ConnectionInput"},"DraftFixRequest":{"properties":{"ticketKey":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9][A-Za-z0-9._-]*$","title":"Ticketkey"}},"additionalProperties":false,"type":"object","required":["ticketKey"],"title":"DraftFixRequest","description":"The body of ``POST /v1/repos/{repository_id}/draft-fix``: the ticket to fix."},"DriveAuthorizeRequest":{"properties":{"returnUrl":{"type":"string","maxLength":2048,"minLength":1,"title":"Returnurl","default":"/settings/integrations"}},"type":"object","title":"DriveAuthorizeRequest"},"DriveConfirmRequest":{"properties":{"grant":{"type":"string","maxLength":128,"minLength":16,"title":"Grant"}},"type":"object","required":["grant"],"title":"DriveConfirmRequest"},"DriveFolderRequest":{"properties":{"folderId":{"type":"string","pattern":"^[A-Za-z0-9_-]{10,128}$","title":"Folderid"},"acknowledgeWorkspaceVisibility":{"type":"boolean","title":"Acknowledgeworkspacevisibility"}},"type":"object","required":["folderId","acknowledgeWorkspaceVisibility"],"title":"DriveFolderRequest"},"EnterpriseLeadCreate":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"company":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Company"}},"type":"object","required":["email"],"title":"EnterpriseLeadCreate"},"ExperiencePreferencePatch":{"properties":{"expected_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Expected User Id"},"expected_tenant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Expected Tenant Id"},"primary_goal":{"anyOf":[{"type":"string","enum":["build_with_agents","understand_code","review_changes","share_knowledge","integrate_product","explore"]},{"type":"null"}],"title":"Primary Goal"},"work_role":{"anyOf":[{"type":"string","enum":["developer","engineering_lead","platform_engineer","founder","other"]},{"type":"null"}],"title":"Work Role"},"guidance_mode":{"anyOf":[{"type":"string","enum":["quiet","on_request"]},{"type":"null"}],"title":"Guidance Mode"},"personalization_prompt_state":{"anyOf":[{"type":"string","enum":["unseen","answered","skipped"]},{"type":"null"}],"title":"Personalization Prompt State"},"memory_explanation_dismissed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Memory Explanation Dismissed"}},"additionalProperties":false,"type":"object","title":"ExperiencePreferencePatch"},"FvAttemptAcceptedRequest":{"properties":{"ecsTaskArn":{"type":"string","maxLength":512,"minLength":1,"title":"Ecstaskarn"},"capacityProvider":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Capacityprovider"},"taskDefinitionArn":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Taskdefinitionarn"},"imageDigest":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Imagedigest"}},"additionalProperties":false,"type":"object","required":["ecsTaskArn"],"title":"FvAttemptAcceptedRequest"},"FvAttemptStoppedRequest":{"properties":{"stopCode":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Stopcode"},"containerExitCode":{"anyOf":[{"type":"integer","maximum":255.0,"minimum":-1.0},{"type":"null"}],"title":"Containerexitcode"},"failureFamily":{"anyOf":[{"$ref":"#/components/schemas/FvFailureFamily"},{"type":"null"}]},"retryDisposition":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Retrydisposition"},"ecsTaskArn":{"anyOf":[{"type":"string","maxLength":512,"minLength":1},{"type":"null"}],"title":"Ecstaskarn"}},"additionalProperties":false,"type":"object","title":"FvAttemptStoppedRequest"},"FvFailureFamily":{"type":"string","enum":["repository","policy","provider_writeback","cancelled","expired","security","runner_resource","capacity","aws_transient","control_plane"],"title":"FvFailureFamily","description":"Typed cause of an FvAttempt's stop, reported by the task-state reconciler on\nPOST /stopped. The single source of truth for the taxonomy: the /stopped intake\nvalidates against it (so a producer that drifts fails loudly with a 422 rather\nthan silently), and the dispatch circuit breaker keys off it."},"FvRenewRequest":{"properties":{"leaseToken":{"type":"string","maxLength":64,"minLength":64,"pattern":"^[a-f0-9]{64}$","title":"Leasetoken"},"version":{"type":"integer","minimum":1.0,"title":"Version"},"leaseSeconds":{"type":"integer","maximum":3600.0,"minimum":30.0,"title":"Leaseseconds","default":900}},"additionalProperties":false,"type":"object","required":["leaseToken","version"],"title":"FvRenewRequest"},"FvStartRequest":{"properties":{"owner":{"type":"string","maxLength":128,"minLength":3,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Owner"},"leaseSeconds":{"type":"integer","maximum":3600.0,"minimum":30.0,"title":"Leaseseconds","default":900}},"additionalProperties":false,"type":"object","required":["owner"],"title":"FvStartRequest"},"GitHubInstallUrlRequest":{"properties":{"handle":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Handle"},"returnUrl":{"type":"string","maxLength":2048,"minLength":1,"title":"Returnurl","default":"/onboarding?installed=github"}},"type":"object","title":"GitHubInstallUrlRequest"},"GitLabAuthorizeUrlRequest":{"properties":{"handle":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Handle"},"returnUrl":{"type":"string","maxLength":2048,"minLength":1,"title":"Returnurl","default":"/onboarding?installed=gitlab"}},"type":"object","title":"GitLabAuthorizeUrlRequest"},"GroupCreate":{"properties":{"name":{"type":"string","maxLength":120,"minLength":2,"title":"Name"},"repositoryIds":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"minItems":1,"title":"Repositoryids"}},"additionalProperties":false,"type":"object","required":["name","repositoryIds"],"title":"GroupCreate"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InstallationInput":{"properties":{"configurationId":{"type":"string","maxLength":200,"pattern":"^icfg_[A-Za-z0-9_-]+$","title":"Configurationid"}},"additionalProperties":false,"type":"object","required":["configurationId"],"title":"InstallationInput"},"InvitationCreate":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"role":{"type":"string","enum":["admin","member"],"title":"Role"}},"additionalProperties":false,"type":"object","required":["email","role"],"title":"InvitationCreate","description":"An owner/admin-issued invitation to join a Team workspace.\n\n``role`` is restricted to the invitable roles (owner is never invitable, and\nbilling is deferred to a later phase); the granted membership role is taken\nfrom the persisted invite on accept, never from the accepting client."},"JiraConnectRequest":{"properties":{"siteUrl":{"type":"string","maxLength":2048,"minLength":8,"title":"Siteurl"},"email":{"type":"string","maxLength":320,"minLength":1,"title":"Email"},"apiToken":{"type":"string","maxLength":1024,"minLength":1,"title":"Apitoken"}},"additionalProperties":false,"type":"object","required":["siteUrl","email","apiToken"],"title":"JiraConnectRequest","description":"The body of ``POST /v1/integrations/jira/connect`` (hosted Jira -> autofix).\n\n``siteUrl`` is the tenant's Jira base URL (SSRF-validated server-side), ``email`` +\n``apiToken`` are the Jira Cloud Basic-auth pair. The token is stored Fernet-encrypted\nand NEVER echoed back on any read path."},"MembershipRoleUpdate":{"properties":{"role":{"type":"string","enum":["admin","member","billing"],"title":"Role"}},"additionalProperties":false,"type":"object","required":["role"],"title":"MembershipRoleUpdate","description":"A change to a member's role. ``owner`` is intentionally not settable here --\nthe last-owner invariant and singular-owner posture are enforced server-side, so\na role is never promoted to owner through this path."},"MemoryRecallBody":{"properties":{"repository_id":{"type":"string","title":"Repository Id"},"query":{"type":"string","maxLength":4096,"minLength":1,"title":"Query"},"k":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"K","default":20},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"}},"additionalProperties":false,"type":"object","required":["repository_id","query"],"title":"MemoryRecallBody","description":"The dashboard search box's ranked-recall request. The tenant is derived from the\nverified session, never the body."},"OnboardingUpdate":{"properties":{"step":{"anyOf":[{"type":"integer","maximum":7.0,"minimum":0.0},{"type":"null"}],"title":"Step"},"plan":{"anyOf":[{"type":"string","enum":["free","enterprise_waitlist"]},{"type":"null"}],"title":"Plan"},"challenges":{"anyOf":[{"items":{"type":"string","enum":["orientation","ai_context","change_impact","pr_prioritization","team_learning","token_economics"]},"type":"array","maxItems":10},{"type":"null"}],"title":"Challenges"},"referralSource":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Referralsource"},"completed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Completed"}},"type":"object","title":"OnboardingUpdate"},"OrganizationCreate":{"properties":{"name":{"type":"string","maxLength":80,"minLength":2,"title":"Name"},"website":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"Website"},"size":{"type":"string","maxLength":40,"minLength":1,"title":"Size"}},"additionalProperties":false,"type":"object","required":["name","size"],"title":"OrganizationCreate"},"PatternFeedback":{"properties":{"action":{"type":"string","enum":["suppress","restore"],"title":"Action"}},"additionalProperties":false,"type":"object","required":["action"],"title":"PatternFeedback"},"PendingInput":{"properties":{"installationId":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Installationid"},"claim":{"type":"string","pattern":"^[A-Za-z0-9_-]{32,128}$","title":"Claim"}},"type":"object","required":["installationId","claim"],"title":"PendingInput"},"PreferenceBody":{"properties":{"weekly_digest":{"type":"boolean","title":"Weekly Digest"}},"additionalProperties":false,"type":"object","required":["weekly_digest"],"title":"PreferenceBody"},"ProfileUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":2},{"type":"null"}],"title":"Name"},"bio":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Bio"},"avatarUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatarurl"},"socials":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Socials"},"visibility":{"anyOf":[{"type":"string","enum":["private","public"]},{"type":"null"}],"title":"Visibility"},"showStats":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Showstats"}},"type":"object","title":"ProfileUpdate"},"ProjectInput":{"properties":{"configurationId":{"type":"string","maxLength":200,"pattern":"^icfg_[A-Za-z0-9_-]+$","title":"Configurationid"},"projectId":{"type":"string","maxLength":200,"pattern":"^prj_[A-Za-z0-9_-]+$","title":"Projectid"}},"additionalProperties":false,"type":"object","required":["configurationId","projectId"],"title":"ProjectInput"},"ReconcileInput":{"properties":{"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","default":10}},"type":"object","title":"ReconcileInput"},"ReconcileRequest":{"properties":{"limit":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Limit","default":100}},"additionalProperties":false,"type":"object","title":"ReconcileRequest"},"RefreshStuckRequest":{"properties":{"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","default":50},"tenantId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenantid"}},"additionalProperties":false,"type":"object","title":"RefreshStuckRequest","description":"Body for the stuck-install sweep. Both fields optional; an empty body sweeps."},"Rename":{"properties":{"old":{"type":"string","maxLength":1024,"minLength":1,"title":"Old"},"new":{"type":"string","maxLength":1024,"minLength":1,"title":"New"}},"additionalProperties":false,"type":"object","required":["old","new"],"title":"Rename"},"RenewRequest":{"properties":{"leaseToken":{"type":"string","maxLength":64,"minLength":64,"pattern":"^[a-f0-9]{64}$","title":"Leasetoken"},"version":{"type":"integer","minimum":1.0,"title":"Version"},"leaseSeconds":{"type":"integer","maximum":3600.0,"minimum":30.0,"title":"Leaseseconds","default":900}},"additionalProperties":false,"type":"object","required":["leaseToken","version"],"title":"RenewRequest"},"RepositoryEnable":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true},"reviewConfig":{"anyOf":[{"type":"string","enum":["all-prs","requested","off"]},{"type":"null"}],"title":"Reviewconfig"},"suggestFixes":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Suggestfixes"},"feedbackLearning":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Feedbacklearning"},"healthInline":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Healthinline"},"riskyPatterns":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Riskypatterns"},"docDrift":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Docdrift"},"enforceRules":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enforcerules"},"fv":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Fv"},"scipIndexing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Scipindexing"}},"type":"object","title":"RepositoryEnable"},"ResendVerificationRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"ResendVerificationRequest"},"ResendVerificationResponse":{"properties":{"status":{"type":"string","title":"Status","default":"accepted"}},"type":"object","title":"ResendVerificationResponse"},"ResolveIssueRequest":{"properties":{"issueRef":{"type":"string","maxLength":2048,"minLength":1,"title":"Issueref"}},"additionalProperties":false,"type":"object","required":["issueRef"],"title":"ResolveIssueRequest","description":"The body of ``POST /v1/repos/{repository_id}/resolve-issue``: the Sentry issue.\n\n``issueRef`` is whatever the user pasted -- a bare Sentry issue id OR a full issue\npermalink. The backend only extracts the id and reads it from the tenant's STORED\nbase URL (never the pasted permalink), so a hostile URL is never dereferenced."},"ReviewStartRequest":{"properties":{"owner":{"type":"string","maxLength":128,"minLength":3,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Owner"},"leaseSeconds":{"type":"integer","maximum":7200.0,"minimum":30.0,"title":"Leaseseconds","default":900}},"additionalProperties":false,"type":"object","required":["owner"],"title":"ReviewStartRequest"},"SeenBody":{"properties":{"cutoff":{"type":"string","format":"uuid","title":"Cutoff"}},"additionalProperties":false,"type":"object","required":["cutoff"],"title":"SeenBody"},"SentryConnectRequest":{"properties":{"siteUrl":{"type":"string","maxLength":2048,"minLength":8,"title":"Siteurl","default":"https://sentry.io"},"org":{"type":"string","maxLength":255,"minLength":1,"title":"Org"},"project":{"type":"string","maxLength":255,"minLength":1,"title":"Project"},"authToken":{"type":"string","maxLength":1024,"minLength":1,"title":"Authtoken"}},"additionalProperties":false,"type":"object","required":["org","project","authToken"],"title":"SentryConnectRequest","description":"The body of ``POST /v1/integrations/sentry/connect`` (hosted Sentry -> autofix).\n\n``siteUrl`` is the tenant's Sentry base URL (SSRF-validated server-side), defaulting\nto Sentry SaaS (``https://sentry.io``); ``org`` + ``project`` are the Sentry slugs the\nissue lives under (``project`` may be a comma-separated list); ``authToken`` is a\nSentry auth/internal-integration token. The token is stored Fernet-encrypted and\nNEVER echoed back on any read path."},"SlackInstallUrlRequest":{"properties":{"returnUrl":{"type":"string","maxLength":2048,"title":"Returnurl","default":"/"}},"type":"object","title":"SlackInstallUrlRequest"},"SlackReconcileRequest":{"properties":{"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","default":10}},"type":"object","title":"SlackReconcileRequest"},"SlackSettingsRequest":{"properties":{"defaultRepositoryId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Defaultrepositoryid"},"channels":{"anyOf":[{"additionalProperties":{"type":"string","format":"uuid"},"type":"object"},{"type":"null"}],"title":"Channels"},"chimeEnabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Chimeenabled"},"chimeLimitPerChannelPerDay":{"anyOf":[{"type":"integer","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Chimelimitperchannelperday"}},"additionalProperties":false,"type":"object","title":"SlackSettingsRequest"},"SpecRequest":{"properties":{"path":{"type":"string","maxLength":1024,"minLength":4,"title":"Path"},"symbol":{"type":"string","maxLength":258,"minLength":1,"title":"Symbol"},"line":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Line"},"properties":{"items":{"type":"string","maxLength":300,"minLength":1},"type":"array","maxItems":5,"minItems":1,"title":"Properties"}},"additionalProperties":false,"type":"object","required":["path","symbol","properties"],"title":"SpecRequest"},"SpecStartRequest":{"properties":{"owner":{"type":"string","maxLength":128,"minLength":3,"pattern":"^[a-z0-9][a-z0-9._-]*$","title":"Owner"},"leaseSeconds":{"type":"integer","maximum":7200.0,"minimum":30.0,"title":"Leaseseconds","default":900}},"additionalProperties":false,"type":"object","required":["owner"],"title":"SpecStartRequest"},"TestImpactRequest":{"properties":{"changedFiles":{"items":{"type":"string","maxLength":1024,"minLength":1},"type":"array","maxItems":2000,"title":"Changedfiles"},"deletedFiles":{"items":{"type":"string","maxLength":1024,"minLength":1},"type":"array","maxItems":2000,"title":"Deletedfiles"},"renames":{"items":{"$ref":"#/components/schemas/Rename"},"type":"array","maxItems":2000,"title":"Renames"},"command":{"type":"string","maxLength":200,"minLength":1,"title":"Command","default":"pytest"},"format":{"type":"string","title":"Format","default":"buildkite"},"baseSha":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Basesha"},"headSha":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Headsha"}},"additionalProperties":false,"type":"object","title":"TestImpactRequest"},"TestImpactToggleRequest":{"properties":{"enabled":{"type":"boolean","title":"Enabled"}},"type":"object","required":["enabled"],"title":"TestImpactToggleRequest"},"TokenRequest":{"properties":{"leaseToken":{"type":"string","maxLength":64,"minLength":64,"pattern":"^[a-f0-9]{64}$","title":"Leasetoken"}},"additionalProperties":false,"type":"object","required":["leaseToken"],"title":"TokenRequest"},"UsernameUpdate":{"properties":{"username":{"type":"string","maxLength":64,"minLength":1,"title":"Username"}},"additionalProperties":false,"type":"object","required":["username"],"title":"UsernameUpdate","description":"The body of ``PATCH /v1/profile/username``. The exact submitted spelling is\nvalidated, never rewritten: a rejected handle must be reported, not silently\ncorrected into something the user did not choose."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WorkspaceIconConfirmRequest":{"properties":{"key":{"type":"string","maxLength":512,"minLength":1,"title":"Key"}},"type":"object","required":["key"],"title":"WorkspaceIconConfirmRequest"},"WorkspaceIconUploadRequest":{"properties":{"contentType":{"type":"string","maxLength":100,"minLength":3,"title":"Contenttype"}},"type":"object","required":["contentType"],"title":"WorkspaceIconUploadRequest","description":"Ask for a presigned PUT for the WORKSPACE icon. Same contract as a user avatar; the\ndifference is authorization, which is checked server-side against current membership."},"app__api__origin__ConnectInput":{"properties":{"installationId":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Installationid"},"repositoryId":{"type":"string","format":"uuid","title":"Repositoryid"},"consent":{"type":"boolean","const":true,"title":"Consent"}},"type":"object","required":["installationId","repositoryId","consent"],"title":"ConnectInput"},"app__api__origin__InstallInput":{"properties":{"receipt":{"type":"string","maxLength":8192,"minLength":1,"title":"Receipt"},"claim":{"type":"string","pattern":"^[A-Za-z0-9_-]{32,128}$","title":"Claim"}},"type":"object","required":["receipt","claim"],"title":"InstallInput"},"app__api__origin__PrepareInput":{"properties":{"installationId":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","title":"Installationid"},"claim":{"type":"string","pattern":"^[A-Za-z0-9_-]{32,128}$","title":"Claim"},"namespaceId":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"},{"type":"null"}],"title":"Namespaceid"}},"type":"object","required":["installationId","claim"],"title":"PrepareInput"},"app__api__vercel__ConnectInput":{"properties":{"configurationId":{"type":"string","maxLength":200,"pattern":"^icfg_[A-Za-z0-9_-]+$","title":"Configurationid"},"projectId":{"type":"string","maxLength":200,"pattern":"^prj_[A-Za-z0-9_-]+$","title":"Projectid"},"targets":{"items":{"type":"string","enum":["production","preview"]},"type":"array","maxItems":2,"minItems":1,"title":"Targets"},"consent":{"type":"boolean","const":true,"title":"Consent"}},"additionalProperties":false,"type":"object","required":["configurationId","projectId","targets","consent"],"title":"ConnectInput"},"app__api__vercel__InstallInput":{"properties":{"configurationId":{"type":"string","maxLength":200,"pattern":"^icfg_[A-Za-z0-9_-]+$","title":"Configurationid"},"code":{"type":"string","maxLength":2048,"minLength":1,"title":"Code"},"claim":{"type":"string","pattern":"^[A-Za-z0-9_-]{32,128}$","title":"Claim"}},"additionalProperties":false,"type":"object","required":["configurationId","code","claim"],"title":"InstallInput"},"app__api__vercel__PrepareInput":{"properties":{"configurationId":{"type":"string","maxLength":200,"pattern":"^icfg_[A-Za-z0-9_-]+$","title":"Configurationid"},"claim":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9_-]{32,128}$"},{"type":"null"}],"title":"Claim"}},"additionalProperties":false,"type":"object","required":["configurationId"],"title":"PrepareInput"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}