Files
fusion/packages/dashboard/app/components/settings/sections/SourceControlGlobalSection.search.ts
gsxdsm a426e28781 FN-9165: Add optional JIRA workspace branch derivation
Add opt-in JIRA-backed workspace branch naming while preserving editable manual branch workflows.

- add scoped JIRA configuration, secret resolution, and documented inheritance
- expose a bounded JIRA issue client and branch-derivation API route
- add settings and task-form controls with recoverable errors and coverage
- derive sanitized branch names from configurable issue-key and summary templates

Files changed:
 .changeset/fn-9165-jira-branch-name.md             |   7 ++
 docs/secrets.md                                    |   4 +
 docs/settings-reference.md                         |  18 ++++
 docs/workspaces.md                                 |   4 +
 packages/core/src/__tests__/jira-config.test.ts    |   6 ++
 .../core/src/__tests__/settings-parity.test.ts     |  12 +++
 packages/core/src/config/settings-schema.ts        |  14 +++
 packages/core/src/index.ts                         |   2 +
 packages/core/src/jira/index.ts                    |   1 +
 packages/core/src/jira/jira-config.ts              |  34 +++++++
 packages/core/src/types/settings/settings-scope.ts |  16 ++++
 .../app/__tests__/settings-save-split.test.ts      |  43 +++++++++
 .../dashboard/app/components/SettingsModal.tsx     |  29 +++++-
 packages/dashboard/app/components/TaskForm.tsx     |  23 ++++-
 .../app/components/__tests__/TaskForm.test.tsx     |  31 +++++++
 .../settings/__tests__/section-keys.test.ts        |   2 +
 .../app/components/settings/save-split.ts          |  64 ++++++++++++-
 .../app/components/settings/section-keys.ts        |   1 +
 .../sections/SourceControlGlobalSection.search.ts  |   9 ++
 .../sections/SourceControlGlobalSection.tsx        |  20 ++++-
 .../sections/SourceControlSection.search.ts        |   9 ++
 .../settings/sections/SourceControlSection.tsx     |  12 +++
 .../settings-default-descriptions.test.tsx         |   7 ++
 .../dashboard/src/__tests__/jira-client.test.ts    |  58 ++++++++++++
 .../src/__tests__/register-jira-routes.test.ts     |  70 +++++++++++++++
 packages/dashboard/src/jira-auth.ts                |  18 ++++
 packages/dashboard/src/jira.ts                     |  75 ++++++++++++++++
 packages/dashboard/src/routes.ts                   |   2 +
 packages/dashboard/src/routes/README.md            | 100 +++++++++++----------
 .../src/routes/create-api-routes-mount-sequence.ts |   2 +-
 packages/dashboard/src/routes/register-jira.ts     |  66 ++++++++++++++
 packages/engine/src/index.ts                       |   2 +
 .../worktree/__tests__/jira-branch-name.test.ts    |   7 ++
 packages/engine/src/worktree/jira-branch-name.ts   |   6 ++
 packages/i18n/locales/en/app.json                  |  23 +++++
 35 files changed, 739 insertions(+), 58 deletions(-)

Fusion-Task-Id: FN-9165

Fusion-Task-Lineage: 88ab5fa3-f66e-421d-8139-5c3e8917348d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-19 22:44:46 -07:00

89 lines
5.3 KiB
TypeScript

/**
* Search entries for the Source Control · Global section.
*
* FNXC:SettingsSearch 2026-07-15-20:30:
* One entry per descriptor row the section renders, co-located so a setting and its index entry change in the same edit. Labels and help mirror the section's `t()` calls verbatim: the index matches on the copy operators actually read, so a paraphrase here would make search miss the words on screen.
* These rows carry the same `key`s as their project counterparts in SourceControlSection.search.ts — they are the same dual-scope settings at the other tier, and `sectionId` is what keeps them distinct (the index's uniqueness rule is per section+key). Their labels are the operator-facing discriminator: every one reads "Global …".
* The global default tracking repo is absent: TrackingRepoSelect is a bespoke widget with no descriptor `key`, so it has no `data-settings-key` anchor to scroll to. It stays reachable via the section's `searchableText` in SETTINGS_SECTIONS.
*/
import type { SettingsSearchEntry } from "../search/types";
export const sourceControlGlobalSearchEntries: SettingsSearchEntry[] = [
{
sectionId: "source-control-global",
key: "reportRoadmapDedupeEnabled",
labelKey: "settings.globalGeneral.reportRoadmapDedupeEnabled",
labelFallback: "Global public-roadmap deduplication",
helpKey: "settings.globalGeneral.reportRoadmapDedupeEnabledHelp",
helpFallback: "Fallback for projects that do not set a public-roadmap deduplication preference. No default — unset (projects default to enabled).",
keywords: ["roadmap", "dedup", "report", "fallback"],
},
{
sectionId: "source-control-global",
key: "reportRoadmapLabel",
labelKey: "settings.globalGeneral.reportRoadmapLabel",
labelFallback: "Global public roadmap label",
helpKey: "settings.globalGeneral.reportRoadmapLabelHelp",
helpFallback: "Fallback label for open public-roadmap issues when a project does not set one. No default — unset (projects default to roadmap).",
keywords: ["roadmap", "label", "report", "fallback"],
},
{
sectionId: "source-control-global",
key: "reportRoadmapRepo",
labelKey: "settings.globalGeneral.reportRoadmapRepo",
labelFallback: "Global public roadmap repository (optional)",
helpKey: "settings.globalGeneral.reportRoadmapRepoHelp",
helpFallback: "Fallback GitHub owner/repository for public-roadmap issues. When unset, uses the tracking repository. No default — unset.",
keywords: ["roadmap", "repository", "repo", "tracking", "fallback"],
},
{
sectionId: "source-control-global",
key: "gitlabInstanceUrl",
labelKey: "settings.globalGeneral.gitLabInstanceUrl",
labelFallback: "Global GitLab instance URL",
helpKey: "settings.globalGeneral.gitLabInstanceUrlHint",
helpFallback:
"Blank defaults to GitLab.com. Projects inherit this self-managed GitLab URL unless they set their own project value. No default — unset.",
keywords: ["self managed", "self-hosted", "fallback", "inherit"],
},
{
sectionId: "source-control-global",
key: "gitlabApiBaseUrl",
labelKey: "settings.globalGeneral.gitLabApiBaseUrlOptional",
labelFallback: "Global GitLab API base URL (optional / advanced)",
helpKey: "settings.globalGeneral.gitLabApiBaseUrlHint",
helpFallback:
"Blank derives <instance>/api/v4. Override only for self-managed GitLab API gateways that use a different absolute http:// or https:// URL. No default — unset.",
keywords: ["api v4", "gateway", "fallback", "self managed"],
},
{
sectionId: "source-control-global",
key: "gitlabAuthTokenType",
labelKey: "settings.globalGeneral.gitLabTokenType",
labelFallback: "Global GitLab token type",
helpKey: "settings.globalGeneral.gitLabTokenTypeHint",
helpFallback:
"No default — unset (the selector falls back to personal access token until you choose otherwise).",
keywords: ["personal access token", "project access token", "group access token", "pat"],
},
{
sectionId: "source-control-global",
key: "gitlabAuthToken",
labelKey: "settings.globalGeneral.gitLabAccessToken",
labelFallback: "Global GitLab access token",
helpKey: "settings.globalGeneral.gitLabAuthTokenHint",
helpFallback:
"Projects inherit this fallback only when they do not set a project GitLab token. Read-only operations need read_api or api; write actions need api; project/group tokens remain limited by resource membership. No default — unset.",
keywords: ["glpat", "private-token", "credentials", "secret", "fallback"],
},
...[
["jiraBaseUrl", "JIRA site URL", "JIRA site URL. Default: unset."],
["jiraApiBaseUrl", "JIRA API base URL (optional)", "Default: <site>/rest/api/3."],
["jiraAuthEmail", "JIRA account email (optional)", "Email selects Basic authentication. Default: unset."],
["jiraAuthTokenSecretKey", "JIRA token secret key", "Secret-store key only. Default: JIRA_API_TOKEN."],
["jiraAuthTokenSecretScope", "JIRA token secret scope", "Default: project."],
["jiraBranchNameTemplate", "JIRA branch-name template", "Default: feature/{key}-{summary}."],
].map(([key, labelFallback, helpFallback]) => ({ sectionId: "source-control-global", key, labelKey: `settings.jira.${key}`, labelFallback, helpKey: `settings.jira.${key}Help`, helpFallback, keywords: ["jira", "branch", "tracker"] })),
];