> For the complete documentation index, see [llms.txt](https://docs.flxbl.io/flxbl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flxbl.io/flxbl/sfp-server/api-reference/projects.md).

# Projects

## Replace build-on-merge domain allow-list rules for a project

> Replaces all branch-scoped domain allow-list rules for the build-on-merge flow.\
> \
> When build-on-merge runs for a branch, only the domains allow-listed for the first matching \`branchPattern\` are built; every other impacted domain is skipped. No matching rule (or an empty list) imposes no restriction.\
> \
> \*\*Branch patterns\*\* support wildcards: \`main\`, \`release/\*\`, \`\*\`. \*\*Domains\*\* are matched by exact, case-insensitive name (a release config's \`releaseName\`).

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"SetBuildOnMergeDomainRulesDto":{"type":"object","properties":{"repositoryIdentifier":{"type":"string","description":"Repository identifier (e.g., flxbl-io/sf-core)"},"domainRules":{"description":"Branch-scoped domain allow-list rules. Replaces all existing rules.","type":"array","items":{"$ref":"#/components/schemas/BuildOnMergeDomainRuleDto"}}},"required":["repositoryIdentifier","domainRules"]},"BuildOnMergeDomainRuleDto":{"type":"object","properties":{"branchPattern":{"type":"string","description":"Wildcard pattern for the merged branch (e.g. `main`, `release/*`). First matching rule wins."},"allowedDomains":{"description":"Exact domain names (releaseName) allowed to build on a matching branch. Empty = no restriction.","type":"array","items":{"type":"string"}}},"required":["branchPattern","allowedDomains"]}}},"paths":{"/sfp/api/projects/config/build-on-merge":{"put":{"operationId":"ProjectsController_setBuildOnMergeDomainRules","summary":"Replace build-on-merge domain allow-list rules for a project","description":"Replaces all branch-scoped domain allow-list rules for the build-on-merge flow.\n\nWhen build-on-merge runs for a branch, only the domains allow-listed for the first matching `branchPattern` are built; every other impacted domain is skipped. No matching rule (or an empty list) imposes no restriction.\n\n**Branch patterns** support wildcards: `main`, `release/*`, `*`. **Domains** are matched by exact, case-insensitive name (a release config's `releaseName`).","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetBuildOnMergeDomainRulesDto"}}}},"responses":{"200":{"description":"Domain allow-list rules updated"},"403":{"description":"Forbidden - Requires role: owner, application"},"404":{"description":"Project not found"}},"tags":["Projects"]}}}}
```

## Replace changeset template settings for a project

> Replaces the project-scoped changeset selection mode and template list.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"SetChangesetSettingsDto":{"type":"object","properties":{"selectionMode":{"type":"string","enum":["any","template_only"],"default":"any"},"templates":{"type":"array","items":{"$ref":"#/components/schemas/ChangesetTemplateDto"}},"repositoryIdentifier":{"type":"string","description":"Project/repository identifier"}},"required":["selectionMode","repositoryIdentifier"]},"ChangesetTemplateDto":{"type":"object","properties":{"id":{"type":"string","description":"Stable template identifier"},"name":{"type":"string","description":"Template display name"},"description":{"type":"string","description":"Template description"},"source":{"$ref":"#/components/schemas/ChangesetTemplateSourceDto"},"metadataTypes":{"description":"Metadata types allowed by this template","type":"array","items":{"type":"string"}},"components":{"description":"Exact metadata components allowed by this template","type":"array","items":{"$ref":"#/components/schemas/ChangesetComponentDto"}},"allowedOperations":{"type":"array","items":{"type":"string","enum":["deploy","delete"]}},"allowedDestructiveStages":{"type":"array","items":{"type":"string","enum":["pre","post"]}},"createdBy":{"type":"string"},"createdAt":{"type":"string"},"updatedBy":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","source"]},"ChangesetTemplateSourceDto":{"type":"object","properties":{"type":{"type":"string","enum":["manual","package_latest_published","platform"]},"packageName":{"type":"string","description":"Package name for latest-published package templates"},"platformTemplateId":{"type":"string","description":"Platform template identifier for future out-of-box templates"}},"required":["type"]},"ChangesetComponentDto":{"type":"object","properties":{"metadataType":{"type":"string","description":"Salesforce metadata type, for example ApexClass or CustomObject"},"memberName":{"type":"string","description":"Salesforce metadata member name"},"operation":{"type":"string","enum":["deploy","delete"],"description":"How this component participates in the changeset"},"destructiveStage":{"type":"string","enum":["pre","post"],"description":"Destructive stage when operation is delete"}},"required":["metadataType","memberName"]}}},"paths":{"/sfp/api/projects/config/changesets":{"put":{"operationId":"ProjectsController_setChangesetSettings","summary":"Replace changeset template settings for a project","description":"Replaces the project-scoped changeset selection mode and template list.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChangesetSettingsDto"}}}},"responses":{"200":{"description":"Changeset settings updated"},"403":{"description":"Forbidden - Requires role: owner, application"},"404":{"description":"Project not found"}},"tags":["Projects"]}}}}
```

## List all onboarded projects

> Returns a list of all projects that have been onboarded to the system. Projects are returned in no particular order. This endpoint is useful for discovering available projects before performing operations on them.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"ProjectDto":{"type":"object","properties":{"identifier":{"type":"string","description":"Repository identifier"},"remoteUrl":{"type":"string","description":"Remote repository URL"},"platform":{"type":"string","description":"Platform for the repository (user-specified)","enum":["github","gitlab","bitbucket","azure-devops","other"]},"createdAt":{"type":"string","description":"Creation timestamp"},"updatedAt":{"type":"string","description":"Last update timestamp"},"version":{"type":"number","description":"Document version for optimistic concurrency control"},"configuration":{"type":"object","description":"Project configuration object for extensibility.\n\nIncludes optional fields for:\n- **workItems**: Issue tracker integration (Jira, GitHub, Azure DevOps)\n- **metricsAlertConfig**: Custom alert thresholds for dashboard metrics\n- **branches**: Tracked branches\n- **settings**: Build and deployment settings"},"integrations":{"type":"array","description":"Integration references linked to this project"}},"required":["identifier","remoteUrl","platform","createdAt","updatedAt","version"]}}},"paths":{"/sfp/api/projects":{"get":{"operationId":"ProjectsController_listProjects","summary":"List all onboarded projects","description":"Returns a list of all projects that have been onboarded to the system. Projects are returned in no particular order. This endpoint is useful for discovering available projects before performing operations on them.","parameters":[],"responses":{"200":{"description":"List of projects retrieved successfully.","schema":{},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectDto"}}}}},"403":{"description":"Forbidden - Requires role: member, application"},"500":{"description":"Internal server error"}},"tags":["Projects"]}}}}
```

## Onboard a new repository

> Creates a new project entry for repository onboarding. Fails if the project already exists to prevent accidental updates through POST requests. Use this endpoint to register repositories with the SFP server for future operations. Only users with the "owner" role can create projects.

````json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"CreateProjectDto":{"type":"object","properties":{"identifier":{"type":"string","description":"Repository identifier (e.g., \"org/repo\" for GitHub, \"org/project/repo\" for Azure DevOps). Must be lowercase. If omitted, auto-derived from remoteUrl."},"remoteUrl":{"type":"string","description":"Remote repository URL"},"platform":{"type":"string","description":"Platform for the repository. If not provided, will be inferred from URL (deprecated behavior)","enum":["github","gitlab","bitbucket","azure-devops","other"]},"configuration":{"description":"Project configuration including workItems settings","allOf":[{"$ref":"#/components/schemas/ProjectConfigurationDto"}]}},"required":["remoteUrl"]},"ProjectConfigurationDto":{"type":"object","properties":{"platform":{"type":"string","description":"Platform identifier"},"checksumSkip":{"type":"boolean","description":"Global master switch for the component-level checksum skip optimisation. Default true. When false, checksum skip is disabled across ALL flows (validation, releases, build-on-merge deploys) regardless of validation branch rules or per-environment settings.","default":true},"workItems":{"description":"Work items / issue tracker configuration","allOf":[{"$ref":"#/components/schemas/WorkItemsConfigDto"}]},"branches":{"description":"Tracked branches for this project. Used to determine which branches trigger `build-on-merge` on push webhooks and which branches are analyzed by scheduled code analysis.\n\nDefaults to `[\"main\"]` if not specified.","type":"array","items":{"type":"string"}},"integrations":{"type":"array","description":"Integration configurations"},"metricsAlertConfig":{"type":"object","description":"Custom alert thresholds for dashboard metrics. Override default thresholds for specific metrics.\n\n**Valid metric keys:**\n- Success rates (0-1 scale, warning > alert): `validation.successRate`, `deploy.successRate`, `build.successRate`, `release.successRate`, `install.successRate`\n- Durations (minutes, warning < alert): `pr.turnaroundTime`, `validation.duration`, `build.avgCreationTime`, `release.avgDuration`, `install.avgDuration`, `deploy.avgDuration`, `workflow.validation.avgDuration`, `workflow.build.avgDuration`, `workflow.release.avgDuration`\n- Coverage (percentage, warning > alert): `apexTests.avgCoverage`\n\n**Default thresholds (see alert-thresholds.config.ts for complete list):**\n| Metric | Warning | Alert | Direction |\n|--------|---------|-------|-----------|\n| validation.successRate | 0.90 | 0.75 | below |\n| deploy.successRate | 0.95 | 0.85 | below |\n| build.successRate | 0.90 | 0.75 | below |\n| pr.turnaroundTime | 2880 (48h) | 4320 (72h) | above |\n| validation.duration | 30 min | 45 min | above |\n| build.avgCreationTime | 20 min | 40 min | above |\n| apexTests.avgCoverage | 85% | 75% | below |","additionalProperties":{"$ref":"#/components/schemas/MetricThresholdDto"}},"disabledFlows":{"description":"List of disabled flow type IDs. Disabled flows will not be triggered by webhooks or API calls.","type":"array","items":{"type":"string"}},"flowOverrides":{"type":"object","description":"Per-project flow type overrides. Maps original flow type IDs to replacement flow type IDs. When a webhook or API triggers \"build-on-merge\", if an override exists it will route to the replacement instead."},"version":{"type":"number","description":"Configuration version for migrations"},"aiProvider":{"type":"string","description":"AI provider for architecture analysis. The credentials must be stored via `POST /integrations`.\n\n**Available providers:**\n- `ai_anthropic` - Anthropic Claude models (recommended)\n- `ai_openai` - OpenAI GPT models\n- `ai_google` - Google Gemini models\n- `ai_github_copilot` - GitHub Copilot\n- `ai_amazon_bedrock` - Amazon Bedrock\n- `none` - Explicitly opt out of AI features for this project\n\n**Setup:**\n1. Store credentials: `POST /integrations` with `provider: \"ai_anthropic\"`, `credentials: { api_key: \"sk-ant-...\" }`\n2. Configure project: `PATCH /projects/{id}` with `configuration.aiProvider: \"ai_anthropic\"`\n\n**Default resolution:** If no AI provider is configured for a project, the system falls back to the default integration (if one is marked `isDefault`). Set `aiProvider: \"none\"` to explicitly disable AI for a project.","enum":["ai_anthropic","ai_openai","ai_google","ai_github_copilot","ai_amazon_bedrock","none"]},"cherryTo":{"description":"Opt-in target branch policy for PR-only cherry delivery. A target must match at least one configured pattern.","allOf":[{"$ref":"#/components/schemas/CherryToConfigDto"}]},"webhookFilters":{"description":"Webhook filter exclusion rules. When a webhook matches eventType + branchPattern, the matching flows are NOT triggered.\n\n**Branch matching:** Uses wildcard patterns (e.g., `release/*`, `release-*`, `main`).\n- For `push` events: matches the pushed branch\n- For `pull_request` events: matches the target (base) branch\n\n**Flow filtering:** If `flowIds` is specified, only those flows are excluded. If omitted, ALL flows for that event+branch are excluded.\n\n**Example:** Skip build-on-merge for release branches, and skip pr-analyze for PRs targeting main:\n```json\n[\n  { \"eventType\": \"push\", \"branchPattern\": \"release/*\" },\n  { \"eventType\": \"push\", \"branchPattern\": \"release-*\" },\n  { \"eventType\": \"pull_request\", \"branchPattern\": \"main\", \"flowIds\": [\"pr-analyze\"] }\n]\n```","type":"array","items":{"$ref":"#/components/schemas/WebhookFilterRuleDto"}},"buildOnMerge":{"description":"`build-on-merge` flow configuration.\n\n**domainRules** — branch-scoped domain allow-list. When build-on-merge runs for a branch, only the domains allow-listed for the first matching `branchPattern` are built; every other impacted domain is skipped. No matching rule (or an empty list) imposes no restriction, so every impacted domain builds (the default).\n\n**Example:** build everything on `main`, but only `core` on release branches:\n```json\n{\n  \"domainRules\": [\n    { \"branchPattern\": \"main\", \"allowedDomains\": [\"core\", \"sales\", \"billing\"] },\n    { \"branchPattern\": \"release/*\", \"allowedDomains\": [\"core\"] }\n  ]\n}\n```","allOf":[{"$ref":"#/components/schemas/BuildOnMergeConfigDto"}]},"changesets":{"description":"Changeset governance settings. Project owners use this to allow unrestricted component selection or restrict changeset creation to owner-defined templates.","allOf":[{"$ref":"#/components/schemas/ChangesetSettingsDto"}]},"analyzeConfig":{"description":"Configuration for automated PR analysis (`sfp analyze`).\n\n**All linters are ON by default.** Use this to turn specific linters off or configure which should cause check failures.\n\n**Branch rules:** Matched against the **target branch** (baseBranch) of the PR. First matching rule wins.\n\n**Valid linter types:** `duplicates`, `compliance`, `architecture`, `code-analyzer`\n\n**Example:** Fail on compliance globally, but for release branches also fail on code-analyzer and skip architecture:\n```json\n{\n  \"failOn\": [\"compliance\"],\n  \"branchRules\": [\n    {\n      \"pattern\": \"release/*\",\n      \"excludeLinters\": [\"architecture\"],\n      \"failOn\": [\"compliance\", \"code-analyzer\"]\n    }\n  ]\n}\n```","allOf":[{"$ref":"#/components/schemas/AnalyzeConfigDto"}]},"validateConfig":{"description":"Configuration for automated PR validation (`sfp validate org`).\n\n**Top-level fields are defaults.** Branch rules override specific settings for matching target branches.\nFirst matching rule wins; if none match, top-level defaults apply.\n\n**Validation modes:** `thorough` (full deploy, default) or `individual` (per-package)\n\n**Example:** Skip testing by default, but enable it for release branches with individual mode:\n```json\n{\n  \"validationMode\": \"thorough\",\n  \"skipTesting\": true,\n  \"skipCoverage\": false,\n  \"continueOnTestFailure\": false,\n  \"diffCheck\": true,\n  \"installDeps\": true,\n  \"coveragePercent\": 75,\n  \"branchRules\": [\n    {\n      \"pattern\": \"release/*\",\n      \"validationMode\": \"individual\",\n      \"skipTesting\": false,\n      \"continueOnTestFailure\": true,\n      \"disableArtifactUpdate\": true\n    }\n  ]\n}\n```","allOf":[{"$ref":"#/components/schemas/ValidateConfigDto"}]},"jiraWriteBack":{"description":"Jira write-back configuration for deployment and release events","allOf":[{"$ref":"#/components/schemas/JiraWriteBackConfigDto"}]},"releaseApprovalGates":{"description":"Environment-specific release approval gates. Missing environment entries default to ['human'].","allOf":[{"$ref":"#/components/schemas/ReleaseApprovalGatesConfigDto"}]},"serviceNowChangeRequest":{"description":"ServiceNow change-request creation and defaults for releases","allOf":[{"$ref":"#/components/schemas/ServiceNowChangeRequestConfigDto"}]},"serviceNowGate":{"description":"Deprecated alias for serviceNowChangeRequest","allOf":[{"$ref":"#/components/schemas/ServiceNowGateConfigDto"}]},"notifications":{"description":"Channel notification settings for build and release events","allOf":[{"$ref":"#/components/schemas/NotificationsConfigDto"}]},"approvalSettings":{"description":"Approval workflow settings (segregation of duties, etc.). Used by compliance audit pipeline to enforce SOX Section 404 requirements on production change approvals.","allOf":[{"$ref":"#/components/schemas/ApprovalSettingsDto"}]},"preflight":{"description":"Preflight status for this project. Automatically updated by the `project-preflight` workflow. Read-only — not editable from the UI.\n\n**Statuses:**\n- `valid`: Project is correctly configured for sfp (ready to use)\n- `configured`: Changes were made but not yet merged\n- `pr-created`: A PR was created with configuration changes — user must merge and re-run\n- `error`: Preflight check failed","readOnly":true,"allOf":[{"$ref":"#/components/schemas/PreflightStatusDto"}]},"versionManagement":{"description":"Server-managed package version increment settings (see decision record 016).","allOf":[{"$ref":"#/components/schemas/VersionManagementConfigDto"}]}}},"WorkItemsConfigDto":{"type":"object","properties":{"provider":{"type":"string","description":"Issue tracker provider","enum":["jira","github","azure-devops"]},"jiraProjects":{"description":"**Jira only**: Project keys to filter work items (e.g., [\"DP\", \"PROJ\"])","type":"array","items":{"type":"string"}},"baseUrl":{"type":"string","description":"**Jira only**: Base URL for work item links"},"workItemRegexFilter":{"type":"string","description":"**Jira only**: Regex pattern to match work item IDs in commit messages"},"project":{"type":"string","description":"**Azure DevOps only**: Project name within the organization (required for ADO)"},"organizationUrl":{"type":"string","description":"**Azure DevOps only**: Organization URL"},"areaPaths":{"description":"**Azure DevOps only**: Area paths to filter work items (e.g., [\"sf-core\\\\Team1\", \"sf-core\\\\Team2\"])","type":"array","items":{"type":"string"}}}},"MetricThresholdDto":{"type":"object","properties":{"warning":{"type":"number","description":"Warning threshold value. For success rates/coverage, this should be > alert. For durations, this should be < alert.","minimum":0},"alert":{"type":"number","description":"Alert threshold value (more severe than warning). For success rates/coverage, this should be < warning. For durations, this should be > warning.","minimum":0}}},"CherryToConfigDto":{"type":"object","properties":{"targetBranches":{"description":"Target branch patterns enabled for `/codev cherry-to`. Supports the same single-star wildcard syntax as other branch rules.","type":"array","items":{"type":"string"}}},"required":["targetBranches"]},"WebhookFilterRuleDto":{"type":"object","properties":{"eventType":{"type":"string","description":"Webhook event category to filter","enum":["push","pull_request"]},"branchPattern":{"type":"string","description":"Wildcard pattern for branch name. For push: the pushed branch. For pull_request: the target (base) branch."},"flowIds":{"description":"Specific flow IDs to exclude. If omitted, ALL flows for this event+branch are excluded.","type":"array","items":{"type":"string"}}},"required":["eventType","branchPattern"]},"BuildOnMergeConfigDto":{"type":"object","properties":{"domainRules":{"description":"Branch-scoped domain allow-list rules. When build-on-merge runs, only the domains allow-listed for the first matching branch pattern are built.","type":"array","items":{"$ref":"#/components/schemas/BuildOnMergeDomainRuleDto"}}}},"BuildOnMergeDomainRuleDto":{"type":"object","properties":{"branchPattern":{"type":"string","description":"Wildcard pattern for the merged branch (e.g. `main`, `release/*`). First matching rule wins."},"allowedDomains":{"description":"Exact domain names (releaseName) allowed to build on a matching branch. Empty = no restriction.","type":"array","items":{"type":"string"}}},"required":["branchPattern","allowedDomains"]},"ChangesetSettingsDto":{"type":"object","properties":{"selectionMode":{"type":"string","enum":["any","template_only"],"default":"any"},"templates":{"type":"array","items":{"$ref":"#/components/schemas/ChangesetTemplateDto"}}},"required":["selectionMode"]},"ChangesetTemplateDto":{"type":"object","properties":{"id":{"type":"string","description":"Stable template identifier"},"name":{"type":"string","description":"Template display name"},"description":{"type":"string","description":"Template description"},"source":{"$ref":"#/components/schemas/ChangesetTemplateSourceDto"},"metadataTypes":{"description":"Metadata types allowed by this template","type":"array","items":{"type":"string"}},"components":{"description":"Exact metadata components allowed by this template","type":"array","items":{"$ref":"#/components/schemas/ChangesetComponentDto"}},"allowedOperations":{"type":"array","items":{"type":"string","enum":["deploy","delete"]}},"allowedDestructiveStages":{"type":"array","items":{"type":"string","enum":["pre","post"]}},"createdBy":{"type":"string"},"createdAt":{"type":"string"},"updatedBy":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","source"]},"ChangesetTemplateSourceDto":{"type":"object","properties":{"type":{"type":"string","enum":["manual","package_latest_published","platform"]},"packageName":{"type":"string","description":"Package name for latest-published package templates"},"platformTemplateId":{"type":"string","description":"Platform template identifier for future out-of-box templates"}},"required":["type"]},"ChangesetComponentDto":{"type":"object","properties":{"metadataType":{"type":"string","description":"Salesforce metadata type, for example ApexClass or CustomObject"},"memberName":{"type":"string","description":"Salesforce metadata member name"},"operation":{"type":"string","enum":["deploy","delete"],"description":"How this component participates in the changeset"},"destructiveStage":{"type":"string","enum":["pre","post"],"description":"Destructive stage when operation is delete"}},"required":["metadataType","memberName"]},"AnalyzeConfigDto":{"type":"object","properties":{"excludeLinters":{"description":"Linters to turn OFF globally (default: none — all linters run)","type":"array","items":{"type":"string"}},"failOn":{"description":"Linters whose issues should cause the check to fail (default: none — informational only)","type":"array","items":{"type":"string"}},"changeSignificanceEnabled":{"type":"boolean","description":"Enable change significance check for architecture linter — skip AI for small/trivial changes (default: false — AI runs for all changes). Same key as changeSignificance.enabled in ai-architecture.yaml."},"versionAssistEnabled":{"type":"boolean","description":"AI Version Assist (DR-019) — score impacted server-managed packages and post a sticky /version comment. ON by default; set false to disable. Self-gates on impacted 0.0.0.NEXT packages and a configured AI provider. Override per target branch via branchRules."},"branchRules":{"description":"Target-branch-specific overrides. First matching pattern wins.","type":"array","items":{"$ref":"#/components/schemas/AnalyzeBranchRuleDto"}}}},"AnalyzeBranchRuleDto":{"type":"object","properties":{"pattern":{"type":"string","description":"Glob pattern for target branch (e.g., \"release/*\", \"hotfix/*\", \"main\")"},"excludeLinters":{"description":"Linters to turn OFF for PRs targeting this branch pattern","type":"array","items":{"type":"string"}},"failOn":{"description":"Linters whose issues should cause the check to fail for PRs targeting this branch pattern","type":"array","items":{"type":"string"}},"changeSignificanceEnabled":{"type":"boolean","description":"Enable change significance check for architecture linter — skip AI for small/trivial changes (default: false — AI runs for all changes). Same key as changeSignificance.enabled in ai-architecture.yaml."},"versionAssistEnabled":{"type":"boolean","description":"AI Version Assist per target branch pattern (DR-019). ON by default; set false to disable for matching branches. Requires versionManagement (also on by default). The analyzer scores impacted server-managed packages and posts a sticky /version comment."}}},"ValidateConfigDto":{"type":"object","properties":{"validationMode":{"type":"string","description":"Default validation mode","enum":["thorough","individual"]},"skipTesting":{"type":"boolean","description":"Skip Apex test execution during validation (default)"},"skipCoverage":{"type":"boolean","description":"Skip code coverage validation during validation (default)"},"continueOnTestFailure":{"type":"boolean","description":"Continue validating remaining packages when package test execution fails (default)"},"coveragePercent":{"type":"number","description":"Required code coverage percentage (default, 0-100)","minimum":0,"maximum":100},"disableParallelTesting":{"type":"boolean","description":"Disable parallel test execution (default)"},"installDeps":{"type":"boolean","description":"Install dependent packages before validation (default)"},"disableArtifactUpdate":{"type":"boolean","description":"Disable artifact update after validation (default)"},"diffCheck":{"type":"boolean","description":"Enable diff-based change detection (default)"},"deployWithTests":{"type":"boolean","description":"Deploy with Apex tests during validation (default)"},"checksumSkip":{"type":"boolean","description":"Component-level checksum skip during validation (default). Skips deploying components unchanged vs the previously installed artifact; most effective with disableArtifactUpdate. Set false to always deploy the full component set.","default":true},"branchRules":{"description":"Target-branch-specific overrides. First matching pattern wins.","type":"array","items":{"$ref":"#/components/schemas/ValidateBranchRuleDto"}}}},"ValidateBranchRuleDto":{"type":"object","properties":{"pattern":{"type":"string","description":"Wildcard pattern for target branch (e.g., \"release/*\", \"main\")"},"validationMode":{"type":"string","description":"Validation mode: thorough (full deploy) or individual (per package)","enum":["thorough","individual"]},"skipTesting":{"type":"boolean","description":"Skip Apex test execution during validation"},"skipCoverage":{"type":"boolean","description":"Skip code coverage validation during validation"},"continueOnTestFailure":{"type":"boolean","description":"Continue validating remaining packages when package test execution fails"},"coveragePercent":{"type":"number","description":"Required code coverage percentage (0-100)","minimum":0,"maximum":100},"disableParallelTesting":{"type":"boolean","description":"Disable parallel test execution"},"installDeps":{"type":"boolean","description":"Install dependent packages before validation"},"disableArtifactUpdate":{"type":"boolean","description":"Disable artifact update after validation"},"diffCheck":{"type":"boolean","description":"Enable diff-based change detection"},"deployWithTests":{"type":"boolean","description":"Deploy with Apex tests during validation"},"checksumSkip":{"type":"boolean","description":"Component-level checksum skip during validation. Skips deploying components unchanged vs the previously installed artifact; most effective with disableArtifactUpdate. Set false to always deploy the full component set.","default":true}},"required":["pattern"]},"JiraWriteBackConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable Jira write-back. Not configured = not enabled."}}},"ReleaseApprovalGatesConfigDto":{"type":"object","properties":{"environments":{"type":"object","description":"Environment-specific release approval policy. Missing environment entries default to ['human'].","additionalProperties":{"$ref":"#/components/schemas/EnvironmentReleaseApprovalGatesDto"}}}},"EnvironmentReleaseApprovalGatesDto":{"type":"object","properties":{"gates":{"type":"array","description":"Approval gates for this environment. Omit an environment entry or omit `gates` to use the implicit default ['human']; set [] for no approval gates.","items":{"type":"string","enum":["human","servicenow"]}},"humanApprovers":{"description":"Human approver policy for this environment. `users` is enforced; `requiredApprovals` is schema-ready.","allOf":[{"$ref":"#/components/schemas/HumanReleaseApproversDto"}]}}},"HumanReleaseApproversDto":{"type":"object","properties":{"users":{"description":"User emails allowed to approve the human gate for this environment.","type":"array","items":{"type":"string"}},"requiredApprovals":{"type":"number","description":"Number of listed users required to approve. Schema-only for now."}}},"ServiceNowChangeRequestConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Create or reuse one ServiceNow change request per release candidate, even when ServiceNow is not an approval gate. ServiceNow approval gates create/reuse a CR regardless of this flag."},"timeoutHours":{"type":"number","description":"Hours to wait for the change request before timing out (default 24)."},"pollIntervalMinutes":{"type":"number","description":"Minutes between change-request approval polls (default 5)."},"assignmentGroup":{"type":"string","description":"ServiceNow assignment group for the change request (sys_id or name)."},"changeType":{"type":"string","description":"Change request type for CAB routing.","enum":["normal","standard","emergency"]},"category":{"type":"string","description":"Change request category."},"risk":{"type":"string","description":"Change request risk."}}},"ServiceNowGateConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Create or reuse one ServiceNow change request per release candidate, even when ServiceNow is not an approval gate. ServiceNow approval gates create/reuse a CR regardless of this flag."},"timeoutHours":{"type":"number","description":"Hours to wait for the change request before timing out (default 24)."},"pollIntervalMinutes":{"type":"number","description":"Minutes between change-request approval polls (default 5)."},"assignmentGroup":{"type":"string","description":"ServiceNow assignment group for the change request (sys_id or name)."},"changeType":{"type":"string","description":"Change request type for CAB routing.","enum":["normal","standard","emergency"]},"category":{"type":"string","description":"Change request category."},"risk":{"type":"string","description":"Change request risk."}}},"NotificationsConfigDto":{"type":"object","properties":{"slack":{"description":"Slack incoming-webhook notification settings","allOf":[{"$ref":"#/components/schemas/SlackNotificationConfigDto"}]},"teams":{"description":"Microsoft Teams webhook notification settings","allOf":[{"$ref":"#/components/schemas/TeamsNotificationConfigDto"}]}}},"SlackNotificationConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable Slack webhook notifications. Not configured = not enabled."},"mode":{"type":"string","description":"Which events to notify on.","enum":["all","failures"]}}},"TeamsNotificationConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable Microsoft Teams webhook notifications. Not configured = not enabled."},"mode":{"type":"string","description":"Which events to notify on.","enum":["all","failures"]}}},"ApprovalSettingsDto":{"type":"object","properties":{"defaultTimeoutHours":{"type":"number","description":"Default approval-request timeout in hours when a gate does not provide an explicit timeout. Applies across approval gates; default is 60 hours.","default":60},"requireSegregationOfDuties":{"type":"boolean","description":"Require segregation of duties: the user who requested an approval cannot resolve it. Non-human requesters (e.g., `app:ci-bot`, `api`, `system`) are allowed — there is no human identity to compare against.","default":false},"operationalApprovers":{"description":"Explicit approver policy for operational human gates. Omit to use the existing owner fallback. If configured, only listed users can approve, and segregation-of-duties is still enforced.","allOf":[{"$ref":"#/components/schemas/OperationalApproversDto"}]}}},"OperationalApproversDto":{"type":"object","properties":{"users":{"description":"Explicit user emails allowed to approve operational gates such as sandbox, package install, sync, and access requests. When omitted, operational approvals fall back to project owners. When configured, the list is authoritative, so include owner emails that should still approve.","type":"array","items":{"type":"string"}}}},"PreflightStatusDto":{"type":"object","properties":{"status":{"type":"string","description":"Preflight result status","enum":["already-configured","configured","not-configured","pr-created","error"]},"lastCheckedAt":{"type":"string","description":"ISO 8601 timestamp of the last preflight check"},"prUrl":{"type":"string","description":"URL of the PR created by preflight (if status is pr-created)"},"prNumber":{"type":"number","description":"PR number created by preflight"}}},"VersionManagementConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Server-managed automated package version increments for this project. Builds compute versions for packages stripped to 0.0.0.NEXT and preflight seeds version state during onboarding. Both build/analyze consumption and preflight seeding are ON by default; set enabled:false to disable."}}},"ProjectDto":{"type":"object","properties":{"identifier":{"type":"string","description":"Repository identifier"},"remoteUrl":{"type":"string","description":"Remote repository URL"},"platform":{"type":"string","description":"Platform for the repository (user-specified)","enum":["github","gitlab","bitbucket","azure-devops","other"]},"createdAt":{"type":"string","description":"Creation timestamp"},"updatedAt":{"type":"string","description":"Last update timestamp"},"version":{"type":"number","description":"Document version for optimistic concurrency control"},"configuration":{"type":"object","description":"Project configuration object for extensibility.\n\nIncludes optional fields for:\n- **workItems**: Issue tracker integration (Jira, GitHub, Azure DevOps)\n- **metricsAlertConfig**: Custom alert thresholds for dashboard metrics\n- **branches**: Tracked branches\n- **settings**: Build and deployment settings"},"integrations":{"type":"array","description":"Integration references linked to this project"}},"required":["identifier","remoteUrl","platform","createdAt","updatedAt","version"]}}},"paths":{"/sfp/api/projects":{"post":{"operationId":"ProjectsController_createProject","summary":"Onboard a new repository","description":"Creates a new project entry for repository onboarding. Fails if the project already exists to prevent accidental updates through POST requests. Use this endpoint to register repositories with the SFP server for future operations. Only users with the \"owner\" role can create projects.","parameters":[],"requestBody":{"required":true,"description":"Project details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectDto"}}}},"responses":{"201":{"description":"The project has been successfully created.","schema":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDto"}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden - Requires role: owner, application"},"409":{"description":"The project already exists.","content":{"application/json":{"schema":{}}}}},"tags":["Projects"]}}}}
````

## Get a specific project by identifier

> Retrieves a project by its repository identifier (e.g., "org/repo"). The identifier must match exactly what was used during project creation. This endpoint supports identifiers with slashes for GitHub-style repositories.

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"ProjectDto":{"type":"object","properties":{"identifier":{"type":"string","description":"Repository identifier"},"remoteUrl":{"type":"string","description":"Remote repository URL"},"platform":{"type":"string","description":"Platform for the repository (user-specified)","enum":["github","gitlab","bitbucket","azure-devops","other"]},"createdAt":{"type":"string","description":"Creation timestamp"},"updatedAt":{"type":"string","description":"Last update timestamp"},"version":{"type":"number","description":"Document version for optimistic concurrency control"},"configuration":{"type":"object","description":"Project configuration object for extensibility.\n\nIncludes optional fields for:\n- **workItems**: Issue tracker integration (Jira, GitHub, Azure DevOps)\n- **metricsAlertConfig**: Custom alert thresholds for dashboard metrics\n- **branches**: Tracked branches\n- **settings**: Build and deployment settings"},"integrations":{"type":"array","description":"Integration references linked to this project"}},"required":["identifier","remoteUrl","platform","createdAt","updatedAt","version"]}}},"paths":{"/sfp/api/projects/{identifier}":{"get":{"operationId":"ProjectsController_getProject","summary":"Get a specific project by identifier","description":"Retrieves a project by its repository identifier (e.g., \"org/repo\"). The identifier must match exactly what was used during project creation. This endpoint supports identifiers with slashes for GitHub-style repositories.","parameters":[{"name":"identifier","required":true,"in":"path","description":"Repository identifier (e.g., \"org/repo\")","schema":{"type":"string"}}],"responses":{"200":{"description":"Project retrieved successfully.","schema":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDto"}}}},"403":{"description":"Forbidden - Requires role: member, application"},"404":{"description":"Project not found.","content":{"application/json":{"schema":{}}}},"500":{"description":"Internal server error"}},"tags":["Projects"]}}}}
```

## Delete a project

> Permanently deletes a project and its stored configuration. Only owners can delete projects. This does not delete external resources (webhooks, environments, etc.).

```json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}}},"paths":{"/sfp/api/projects/{identifier}":{"delete":{"operationId":"ProjectsController_deleteProject","summary":"Delete a project","description":"Permanently deletes a project and its stored configuration. Only owners can delete projects. This does not delete external resources (webhooks, environments, etc.).","parameters":[{"name":"identifier","required":true,"in":"path","description":"Repository identifier (e.g., \"org/repo\")","schema":{"type":"string"}}],"responses":{"204":{"description":"Project deleted successfully."},"403":{"description":"Forbidden - Requires role: owner, application"},"404":{"description":"Project not found.","content":{"application/json":{"schema":{}}}},"500":{"description":"Internal server error"}},"tags":["Projects"]}}}}
```

## Update project configuration

> Updates an existing project's configuration. Supports partial updates via PATCH semantics. Only owners can update projects. Includes optimistic concurrency control through version checking to prevent concurrent update conflicts.\
> \
> \*\*Renaming:\*\* Pass \`identifier\` in the body to rename the project. The old identifier is deleted and a new one is created with all existing data.

````json
{"openapi":"3.0.0","info":{"title":"sfp server","version":"51.40.2"},"security":[{"access-token":[]}],"components":{"securitySchemes":{"access-token":{"scheme":"bearer","bearerFormat":"JWT","type":"http","in":"header"}},"schemas":{"UpdateProjectDto":{"type":"object","properties":{"identifier":{"type":"string","description":"New repository identifier. Renames the project key in the store. Must be lowercase in format org/repo or org/project/repo."},"remoteUrl":{"type":"string","description":"Remote repository URL"},"platform":{"type":"string","description":"Platform for the repository","enum":["github","gitlab","bitbucket","azure-devops","other"]},"configuration":{"description":"Project configuration object.\n\n**Examples by provider:**\n- **Jira**: `{ workItems: { provider: \"jira\", jiraProjects: [\"DP\", \"PROJ\"], baseUrl: \"https://company.atlassian.net/browse\" } }`\n- **GitHub**: `{ workItems: { provider: \"github\" } }` (uses project identifier directly)\n- **Azure DevOps**: `{ workItems: { provider: \"azure-devops\", project: \"sf-core\", organizationUrl: \"https://dev.azure.com/org\", areaPaths: [\"sf-core\\\\Team1\"] } }`","allOf":[{"$ref":"#/components/schemas/ProjectConfigurationDto"}]},"version":{"type":"number","description":"Document version for optimistic concurrency control"}}},"ProjectConfigurationDto":{"type":"object","properties":{"platform":{"type":"string","description":"Platform identifier"},"checksumSkip":{"type":"boolean","description":"Global master switch for the component-level checksum skip optimisation. Default true. When false, checksum skip is disabled across ALL flows (validation, releases, build-on-merge deploys) regardless of validation branch rules or per-environment settings.","default":true},"workItems":{"description":"Work items / issue tracker configuration","allOf":[{"$ref":"#/components/schemas/WorkItemsConfigDto"}]},"branches":{"description":"Tracked branches for this project. Used to determine which branches trigger `build-on-merge` on push webhooks and which branches are analyzed by scheduled code analysis.\n\nDefaults to `[\"main\"]` if not specified.","type":"array","items":{"type":"string"}},"integrations":{"type":"array","description":"Integration configurations"},"metricsAlertConfig":{"type":"object","description":"Custom alert thresholds for dashboard metrics. Override default thresholds for specific metrics.\n\n**Valid metric keys:**\n- Success rates (0-1 scale, warning > alert): `validation.successRate`, `deploy.successRate`, `build.successRate`, `release.successRate`, `install.successRate`\n- Durations (minutes, warning < alert): `pr.turnaroundTime`, `validation.duration`, `build.avgCreationTime`, `release.avgDuration`, `install.avgDuration`, `deploy.avgDuration`, `workflow.validation.avgDuration`, `workflow.build.avgDuration`, `workflow.release.avgDuration`\n- Coverage (percentage, warning > alert): `apexTests.avgCoverage`\n\n**Default thresholds (see alert-thresholds.config.ts for complete list):**\n| Metric | Warning | Alert | Direction |\n|--------|---------|-------|-----------|\n| validation.successRate | 0.90 | 0.75 | below |\n| deploy.successRate | 0.95 | 0.85 | below |\n| build.successRate | 0.90 | 0.75 | below |\n| pr.turnaroundTime | 2880 (48h) | 4320 (72h) | above |\n| validation.duration | 30 min | 45 min | above |\n| build.avgCreationTime | 20 min | 40 min | above |\n| apexTests.avgCoverage | 85% | 75% | below |","additionalProperties":{"$ref":"#/components/schemas/MetricThresholdDto"}},"disabledFlows":{"description":"List of disabled flow type IDs. Disabled flows will not be triggered by webhooks or API calls.","type":"array","items":{"type":"string"}},"flowOverrides":{"type":"object","description":"Per-project flow type overrides. Maps original flow type IDs to replacement flow type IDs. When a webhook or API triggers \"build-on-merge\", if an override exists it will route to the replacement instead."},"version":{"type":"number","description":"Configuration version for migrations"},"aiProvider":{"type":"string","description":"AI provider for architecture analysis. The credentials must be stored via `POST /integrations`.\n\n**Available providers:**\n- `ai_anthropic` - Anthropic Claude models (recommended)\n- `ai_openai` - OpenAI GPT models\n- `ai_google` - Google Gemini models\n- `ai_github_copilot` - GitHub Copilot\n- `ai_amazon_bedrock` - Amazon Bedrock\n- `none` - Explicitly opt out of AI features for this project\n\n**Setup:**\n1. Store credentials: `POST /integrations` with `provider: \"ai_anthropic\"`, `credentials: { api_key: \"sk-ant-...\" }`\n2. Configure project: `PATCH /projects/{id}` with `configuration.aiProvider: \"ai_anthropic\"`\n\n**Default resolution:** If no AI provider is configured for a project, the system falls back to the default integration (if one is marked `isDefault`). Set `aiProvider: \"none\"` to explicitly disable AI for a project.","enum":["ai_anthropic","ai_openai","ai_google","ai_github_copilot","ai_amazon_bedrock","none"]},"cherryTo":{"description":"Opt-in target branch policy for PR-only cherry delivery. A target must match at least one configured pattern.","allOf":[{"$ref":"#/components/schemas/CherryToConfigDto"}]},"webhookFilters":{"description":"Webhook filter exclusion rules. When a webhook matches eventType + branchPattern, the matching flows are NOT triggered.\n\n**Branch matching:** Uses wildcard patterns (e.g., `release/*`, `release-*`, `main`).\n- For `push` events: matches the pushed branch\n- For `pull_request` events: matches the target (base) branch\n\n**Flow filtering:** If `flowIds` is specified, only those flows are excluded. If omitted, ALL flows for that event+branch are excluded.\n\n**Example:** Skip build-on-merge for release branches, and skip pr-analyze for PRs targeting main:\n```json\n[\n  { \"eventType\": \"push\", \"branchPattern\": \"release/*\" },\n  { \"eventType\": \"push\", \"branchPattern\": \"release-*\" },\n  { \"eventType\": \"pull_request\", \"branchPattern\": \"main\", \"flowIds\": [\"pr-analyze\"] }\n]\n```","type":"array","items":{"$ref":"#/components/schemas/WebhookFilterRuleDto"}},"buildOnMerge":{"description":"`build-on-merge` flow configuration.\n\n**domainRules** — branch-scoped domain allow-list. When build-on-merge runs for a branch, only the domains allow-listed for the first matching `branchPattern` are built; every other impacted domain is skipped. No matching rule (or an empty list) imposes no restriction, so every impacted domain builds (the default).\n\n**Example:** build everything on `main`, but only `core` on release branches:\n```json\n{\n  \"domainRules\": [\n    { \"branchPattern\": \"main\", \"allowedDomains\": [\"core\", \"sales\", \"billing\"] },\n    { \"branchPattern\": \"release/*\", \"allowedDomains\": [\"core\"] }\n  ]\n}\n```","allOf":[{"$ref":"#/components/schemas/BuildOnMergeConfigDto"}]},"changesets":{"description":"Changeset governance settings. Project owners use this to allow unrestricted component selection or restrict changeset creation to owner-defined templates.","allOf":[{"$ref":"#/components/schemas/ChangesetSettingsDto"}]},"analyzeConfig":{"description":"Configuration for automated PR analysis (`sfp analyze`).\n\n**All linters are ON by default.** Use this to turn specific linters off or configure which should cause check failures.\n\n**Branch rules:** Matched against the **target branch** (baseBranch) of the PR. First matching rule wins.\n\n**Valid linter types:** `duplicates`, `compliance`, `architecture`, `code-analyzer`\n\n**Example:** Fail on compliance globally, but for release branches also fail on code-analyzer and skip architecture:\n```json\n{\n  \"failOn\": [\"compliance\"],\n  \"branchRules\": [\n    {\n      \"pattern\": \"release/*\",\n      \"excludeLinters\": [\"architecture\"],\n      \"failOn\": [\"compliance\", \"code-analyzer\"]\n    }\n  ]\n}\n```","allOf":[{"$ref":"#/components/schemas/AnalyzeConfigDto"}]},"validateConfig":{"description":"Configuration for automated PR validation (`sfp validate org`).\n\n**Top-level fields are defaults.** Branch rules override specific settings for matching target branches.\nFirst matching rule wins; if none match, top-level defaults apply.\n\n**Validation modes:** `thorough` (full deploy, default) or `individual` (per-package)\n\n**Example:** Skip testing by default, but enable it for release branches with individual mode:\n```json\n{\n  \"validationMode\": \"thorough\",\n  \"skipTesting\": true,\n  \"skipCoverage\": false,\n  \"continueOnTestFailure\": false,\n  \"diffCheck\": true,\n  \"installDeps\": true,\n  \"coveragePercent\": 75,\n  \"branchRules\": [\n    {\n      \"pattern\": \"release/*\",\n      \"validationMode\": \"individual\",\n      \"skipTesting\": false,\n      \"continueOnTestFailure\": true,\n      \"disableArtifactUpdate\": true\n    }\n  ]\n}\n```","allOf":[{"$ref":"#/components/schemas/ValidateConfigDto"}]},"jiraWriteBack":{"description":"Jira write-back configuration for deployment and release events","allOf":[{"$ref":"#/components/schemas/JiraWriteBackConfigDto"}]},"releaseApprovalGates":{"description":"Environment-specific release approval gates. Missing environment entries default to ['human'].","allOf":[{"$ref":"#/components/schemas/ReleaseApprovalGatesConfigDto"}]},"serviceNowChangeRequest":{"description":"ServiceNow change-request creation and defaults for releases","allOf":[{"$ref":"#/components/schemas/ServiceNowChangeRequestConfigDto"}]},"serviceNowGate":{"description":"Deprecated alias for serviceNowChangeRequest","allOf":[{"$ref":"#/components/schemas/ServiceNowGateConfigDto"}]},"notifications":{"description":"Channel notification settings for build and release events","allOf":[{"$ref":"#/components/schemas/NotificationsConfigDto"}]},"approvalSettings":{"description":"Approval workflow settings (segregation of duties, etc.). Used by compliance audit pipeline to enforce SOX Section 404 requirements on production change approvals.","allOf":[{"$ref":"#/components/schemas/ApprovalSettingsDto"}]},"preflight":{"description":"Preflight status for this project. Automatically updated by the `project-preflight` workflow. Read-only — not editable from the UI.\n\n**Statuses:**\n- `valid`: Project is correctly configured for sfp (ready to use)\n- `configured`: Changes were made but not yet merged\n- `pr-created`: A PR was created with configuration changes — user must merge and re-run\n- `error`: Preflight check failed","readOnly":true,"allOf":[{"$ref":"#/components/schemas/PreflightStatusDto"}]},"versionManagement":{"description":"Server-managed package version increment settings (see decision record 016).","allOf":[{"$ref":"#/components/schemas/VersionManagementConfigDto"}]}}},"WorkItemsConfigDto":{"type":"object","properties":{"provider":{"type":"string","description":"Issue tracker provider","enum":["jira","github","azure-devops"]},"jiraProjects":{"description":"**Jira only**: Project keys to filter work items (e.g., [\"DP\", \"PROJ\"])","type":"array","items":{"type":"string"}},"baseUrl":{"type":"string","description":"**Jira only**: Base URL for work item links"},"workItemRegexFilter":{"type":"string","description":"**Jira only**: Regex pattern to match work item IDs in commit messages"},"project":{"type":"string","description":"**Azure DevOps only**: Project name within the organization (required for ADO)"},"organizationUrl":{"type":"string","description":"**Azure DevOps only**: Organization URL"},"areaPaths":{"description":"**Azure DevOps only**: Area paths to filter work items (e.g., [\"sf-core\\\\Team1\", \"sf-core\\\\Team2\"])","type":"array","items":{"type":"string"}}}},"MetricThresholdDto":{"type":"object","properties":{"warning":{"type":"number","description":"Warning threshold value. For success rates/coverage, this should be > alert. For durations, this should be < alert.","minimum":0},"alert":{"type":"number","description":"Alert threshold value (more severe than warning). For success rates/coverage, this should be < warning. For durations, this should be > warning.","minimum":0}}},"CherryToConfigDto":{"type":"object","properties":{"targetBranches":{"description":"Target branch patterns enabled for `/codev cherry-to`. Supports the same single-star wildcard syntax as other branch rules.","type":"array","items":{"type":"string"}}},"required":["targetBranches"]},"WebhookFilterRuleDto":{"type":"object","properties":{"eventType":{"type":"string","description":"Webhook event category to filter","enum":["push","pull_request"]},"branchPattern":{"type":"string","description":"Wildcard pattern for branch name. For push: the pushed branch. For pull_request: the target (base) branch."},"flowIds":{"description":"Specific flow IDs to exclude. If omitted, ALL flows for this event+branch are excluded.","type":"array","items":{"type":"string"}}},"required":["eventType","branchPattern"]},"BuildOnMergeConfigDto":{"type":"object","properties":{"domainRules":{"description":"Branch-scoped domain allow-list rules. When build-on-merge runs, only the domains allow-listed for the first matching branch pattern are built.","type":"array","items":{"$ref":"#/components/schemas/BuildOnMergeDomainRuleDto"}}}},"BuildOnMergeDomainRuleDto":{"type":"object","properties":{"branchPattern":{"type":"string","description":"Wildcard pattern for the merged branch (e.g. `main`, `release/*`). First matching rule wins."},"allowedDomains":{"description":"Exact domain names (releaseName) allowed to build on a matching branch. Empty = no restriction.","type":"array","items":{"type":"string"}}},"required":["branchPattern","allowedDomains"]},"ChangesetSettingsDto":{"type":"object","properties":{"selectionMode":{"type":"string","enum":["any","template_only"],"default":"any"},"templates":{"type":"array","items":{"$ref":"#/components/schemas/ChangesetTemplateDto"}}},"required":["selectionMode"]},"ChangesetTemplateDto":{"type":"object","properties":{"id":{"type":"string","description":"Stable template identifier"},"name":{"type":"string","description":"Template display name"},"description":{"type":"string","description":"Template description"},"source":{"$ref":"#/components/schemas/ChangesetTemplateSourceDto"},"metadataTypes":{"description":"Metadata types allowed by this template","type":"array","items":{"type":"string"}},"components":{"description":"Exact metadata components allowed by this template","type":"array","items":{"$ref":"#/components/schemas/ChangesetComponentDto"}},"allowedOperations":{"type":"array","items":{"type":"string","enum":["deploy","delete"]}},"allowedDestructiveStages":{"type":"array","items":{"type":"string","enum":["pre","post"]}},"createdBy":{"type":"string"},"createdAt":{"type":"string"},"updatedBy":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","source"]},"ChangesetTemplateSourceDto":{"type":"object","properties":{"type":{"type":"string","enum":["manual","package_latest_published","platform"]},"packageName":{"type":"string","description":"Package name for latest-published package templates"},"platformTemplateId":{"type":"string","description":"Platform template identifier for future out-of-box templates"}},"required":["type"]},"ChangesetComponentDto":{"type":"object","properties":{"metadataType":{"type":"string","description":"Salesforce metadata type, for example ApexClass or CustomObject"},"memberName":{"type":"string","description":"Salesforce metadata member name"},"operation":{"type":"string","enum":["deploy","delete"],"description":"How this component participates in the changeset"},"destructiveStage":{"type":"string","enum":["pre","post"],"description":"Destructive stage when operation is delete"}},"required":["metadataType","memberName"]},"AnalyzeConfigDto":{"type":"object","properties":{"excludeLinters":{"description":"Linters to turn OFF globally (default: none — all linters run)","type":"array","items":{"type":"string"}},"failOn":{"description":"Linters whose issues should cause the check to fail (default: none — informational only)","type":"array","items":{"type":"string"}},"changeSignificanceEnabled":{"type":"boolean","description":"Enable change significance check for architecture linter — skip AI for small/trivial changes (default: false — AI runs for all changes). Same key as changeSignificance.enabled in ai-architecture.yaml."},"versionAssistEnabled":{"type":"boolean","description":"AI Version Assist (DR-019) — score impacted server-managed packages and post a sticky /version comment. ON by default; set false to disable. Self-gates on impacted 0.0.0.NEXT packages and a configured AI provider. Override per target branch via branchRules."},"branchRules":{"description":"Target-branch-specific overrides. First matching pattern wins.","type":"array","items":{"$ref":"#/components/schemas/AnalyzeBranchRuleDto"}}}},"AnalyzeBranchRuleDto":{"type":"object","properties":{"pattern":{"type":"string","description":"Glob pattern for target branch (e.g., \"release/*\", \"hotfix/*\", \"main\")"},"excludeLinters":{"description":"Linters to turn OFF for PRs targeting this branch pattern","type":"array","items":{"type":"string"}},"failOn":{"description":"Linters whose issues should cause the check to fail for PRs targeting this branch pattern","type":"array","items":{"type":"string"}},"changeSignificanceEnabled":{"type":"boolean","description":"Enable change significance check for architecture linter — skip AI for small/trivial changes (default: false — AI runs for all changes). Same key as changeSignificance.enabled in ai-architecture.yaml."},"versionAssistEnabled":{"type":"boolean","description":"AI Version Assist per target branch pattern (DR-019). ON by default; set false to disable for matching branches. Requires versionManagement (also on by default). The analyzer scores impacted server-managed packages and posts a sticky /version comment."}}},"ValidateConfigDto":{"type":"object","properties":{"validationMode":{"type":"string","description":"Default validation mode","enum":["thorough","individual"]},"skipTesting":{"type":"boolean","description":"Skip Apex test execution during validation (default)"},"skipCoverage":{"type":"boolean","description":"Skip code coverage validation during validation (default)"},"continueOnTestFailure":{"type":"boolean","description":"Continue validating remaining packages when package test execution fails (default)"},"coveragePercent":{"type":"number","description":"Required code coverage percentage (default, 0-100)","minimum":0,"maximum":100},"disableParallelTesting":{"type":"boolean","description":"Disable parallel test execution (default)"},"installDeps":{"type":"boolean","description":"Install dependent packages before validation (default)"},"disableArtifactUpdate":{"type":"boolean","description":"Disable artifact update after validation (default)"},"diffCheck":{"type":"boolean","description":"Enable diff-based change detection (default)"},"deployWithTests":{"type":"boolean","description":"Deploy with Apex tests during validation (default)"},"checksumSkip":{"type":"boolean","description":"Component-level checksum skip during validation (default). Skips deploying components unchanged vs the previously installed artifact; most effective with disableArtifactUpdate. Set false to always deploy the full component set.","default":true},"branchRules":{"description":"Target-branch-specific overrides. First matching pattern wins.","type":"array","items":{"$ref":"#/components/schemas/ValidateBranchRuleDto"}}}},"ValidateBranchRuleDto":{"type":"object","properties":{"pattern":{"type":"string","description":"Wildcard pattern for target branch (e.g., \"release/*\", \"main\")"},"validationMode":{"type":"string","description":"Validation mode: thorough (full deploy) or individual (per package)","enum":["thorough","individual"]},"skipTesting":{"type":"boolean","description":"Skip Apex test execution during validation"},"skipCoverage":{"type":"boolean","description":"Skip code coverage validation during validation"},"continueOnTestFailure":{"type":"boolean","description":"Continue validating remaining packages when package test execution fails"},"coveragePercent":{"type":"number","description":"Required code coverage percentage (0-100)","minimum":0,"maximum":100},"disableParallelTesting":{"type":"boolean","description":"Disable parallel test execution"},"installDeps":{"type":"boolean","description":"Install dependent packages before validation"},"disableArtifactUpdate":{"type":"boolean","description":"Disable artifact update after validation"},"diffCheck":{"type":"boolean","description":"Enable diff-based change detection"},"deployWithTests":{"type":"boolean","description":"Deploy with Apex tests during validation"},"checksumSkip":{"type":"boolean","description":"Component-level checksum skip during validation. Skips deploying components unchanged vs the previously installed artifact; most effective with disableArtifactUpdate. Set false to always deploy the full component set.","default":true}},"required":["pattern"]},"JiraWriteBackConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable Jira write-back. Not configured = not enabled."}}},"ReleaseApprovalGatesConfigDto":{"type":"object","properties":{"environments":{"type":"object","description":"Environment-specific release approval policy. Missing environment entries default to ['human'].","additionalProperties":{"$ref":"#/components/schemas/EnvironmentReleaseApprovalGatesDto"}}}},"EnvironmentReleaseApprovalGatesDto":{"type":"object","properties":{"gates":{"type":"array","description":"Approval gates for this environment. Omit an environment entry or omit `gates` to use the implicit default ['human']; set [] for no approval gates.","items":{"type":"string","enum":["human","servicenow"]}},"humanApprovers":{"description":"Human approver policy for this environment. `users` is enforced; `requiredApprovals` is schema-ready.","allOf":[{"$ref":"#/components/schemas/HumanReleaseApproversDto"}]}}},"HumanReleaseApproversDto":{"type":"object","properties":{"users":{"description":"User emails allowed to approve the human gate for this environment.","type":"array","items":{"type":"string"}},"requiredApprovals":{"type":"number","description":"Number of listed users required to approve. Schema-only for now."}}},"ServiceNowChangeRequestConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Create or reuse one ServiceNow change request per release candidate, even when ServiceNow is not an approval gate. ServiceNow approval gates create/reuse a CR regardless of this flag."},"timeoutHours":{"type":"number","description":"Hours to wait for the change request before timing out (default 24)."},"pollIntervalMinutes":{"type":"number","description":"Minutes between change-request approval polls (default 5)."},"assignmentGroup":{"type":"string","description":"ServiceNow assignment group for the change request (sys_id or name)."},"changeType":{"type":"string","description":"Change request type for CAB routing.","enum":["normal","standard","emergency"]},"category":{"type":"string","description":"Change request category."},"risk":{"type":"string","description":"Change request risk."}}},"ServiceNowGateConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Create or reuse one ServiceNow change request per release candidate, even when ServiceNow is not an approval gate. ServiceNow approval gates create/reuse a CR regardless of this flag."},"timeoutHours":{"type":"number","description":"Hours to wait for the change request before timing out (default 24)."},"pollIntervalMinutes":{"type":"number","description":"Minutes between change-request approval polls (default 5)."},"assignmentGroup":{"type":"string","description":"ServiceNow assignment group for the change request (sys_id or name)."},"changeType":{"type":"string","description":"Change request type for CAB routing.","enum":["normal","standard","emergency"]},"category":{"type":"string","description":"Change request category."},"risk":{"type":"string","description":"Change request risk."}}},"NotificationsConfigDto":{"type":"object","properties":{"slack":{"description":"Slack incoming-webhook notification settings","allOf":[{"$ref":"#/components/schemas/SlackNotificationConfigDto"}]},"teams":{"description":"Microsoft Teams webhook notification settings","allOf":[{"$ref":"#/components/schemas/TeamsNotificationConfigDto"}]}}},"SlackNotificationConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable Slack webhook notifications. Not configured = not enabled."},"mode":{"type":"string","description":"Which events to notify on.","enum":["all","failures"]}}},"TeamsNotificationConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable Microsoft Teams webhook notifications. Not configured = not enabled."},"mode":{"type":"string","description":"Which events to notify on.","enum":["all","failures"]}}},"ApprovalSettingsDto":{"type":"object","properties":{"defaultTimeoutHours":{"type":"number","description":"Default approval-request timeout in hours when a gate does not provide an explicit timeout. Applies across approval gates; default is 60 hours.","default":60},"requireSegregationOfDuties":{"type":"boolean","description":"Require segregation of duties: the user who requested an approval cannot resolve it. Non-human requesters (e.g., `app:ci-bot`, `api`, `system`) are allowed — there is no human identity to compare against.","default":false},"operationalApprovers":{"description":"Explicit approver policy for operational human gates. Omit to use the existing owner fallback. If configured, only listed users can approve, and segregation-of-duties is still enforced.","allOf":[{"$ref":"#/components/schemas/OperationalApproversDto"}]}}},"OperationalApproversDto":{"type":"object","properties":{"users":{"description":"Explicit user emails allowed to approve operational gates such as sandbox, package install, sync, and access requests. When omitted, operational approvals fall back to project owners. When configured, the list is authoritative, so include owner emails that should still approve.","type":"array","items":{"type":"string"}}}},"PreflightStatusDto":{"type":"object","properties":{"status":{"type":"string","description":"Preflight result status","enum":["already-configured","configured","not-configured","pr-created","error"]},"lastCheckedAt":{"type":"string","description":"ISO 8601 timestamp of the last preflight check"},"prUrl":{"type":"string","description":"URL of the PR created by preflight (if status is pr-created)"},"prNumber":{"type":"number","description":"PR number created by preflight"}}},"VersionManagementConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Server-managed automated package version increments for this project. Builds compute versions for packages stripped to 0.0.0.NEXT and preflight seeds version state during onboarding. Both build/analyze consumption and preflight seeding are ON by default; set enabled:false to disable."}}},"ProjectDto":{"type":"object","properties":{"identifier":{"type":"string","description":"Repository identifier"},"remoteUrl":{"type":"string","description":"Remote repository URL"},"platform":{"type":"string","description":"Platform for the repository (user-specified)","enum":["github","gitlab","bitbucket","azure-devops","other"]},"createdAt":{"type":"string","description":"Creation timestamp"},"updatedAt":{"type":"string","description":"Last update timestamp"},"version":{"type":"number","description":"Document version for optimistic concurrency control"},"configuration":{"type":"object","description":"Project configuration object for extensibility.\n\nIncludes optional fields for:\n- **workItems**: Issue tracker integration (Jira, GitHub, Azure DevOps)\n- **metricsAlertConfig**: Custom alert thresholds for dashboard metrics\n- **branches**: Tracked branches\n- **settings**: Build and deployment settings"},"integrations":{"type":"array","description":"Integration references linked to this project"}},"required":["identifier","remoteUrl","platform","createdAt","updatedAt","version"]}}},"paths":{"/sfp/api/projects/{identifier}":{"patch":{"operationId":"ProjectsController_updateProject","summary":"Update project configuration","description":"Updates an existing project's configuration. Supports partial updates via PATCH semantics. Only owners can update projects. Includes optimistic concurrency control through version checking to prevent concurrent update conflicts.\n\n**Renaming:** Pass `identifier` in the body to rename the project. The old identifier is deleted and a new one is created with all existing data.","parameters":[{"name":"identifier","required":true,"in":"path","description":"Repository identifier (e.g., \"org/repo\")","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"Fields to update","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectDto"}}}},"responses":{"200":{"description":"Project updated successfully.","schema":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDto"}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden - Requires role: owner, application"},"404":{"description":"Project not found.","content":{"application/json":{"schema":{}}}},"409":{"description":"Version conflict - the project has been modified by another process.","content":{"application/json":{"schema":{}}}},"500":{"description":"Internal server error"}},"tags":["Projects"]}}}}
````


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.flxbl.io/flxbl/sfp-server/api-reference/projects.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
