paperclip-github-plugin 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,7 +29,7 @@ With this plugin, you can:
29
29
  The plugin adds a full in-host workflow instead of a one-off import script:
30
30
 
31
31
  - a hosted settings page for GitHub auth, repository mappings, company defaults, and sync controls
32
- - authenticated-only setup controls for Paperclip board access and company-scoped agent token propagation
32
+ - setup controls for Paperclip board access and company-scoped agent token propagation on authenticated and `local_trusted` deployments
33
33
  - a dashboard widget that shows readiness, sync status, and last-run results
34
34
  - saved sync diagnostics that let operators inspect the latest per-issue failures, raw errors, and suggested next steps
35
35
  - a project sidebar item that opens a live project-scoped Pull Requests page for the mapped repository and can show the open PR count through a lightweight badge read
@@ -39,7 +39,7 @@ The plugin adds a full in-host workflow instead of a one-off import script:
39
39
 
40
40
  ## How it works
41
41
 
42
- 1. Save a GitHub token in the plugin settings.
42
+ 1. Save a GitHub token in the plugin settings for the current company.
43
43
  2. Connect one or more GitHub repositories to Paperclip projects.
44
44
  3. Run a sync manually or let the scheduled job keep things up to date.
45
45
 
@@ -53,7 +53,7 @@ Long-running syncs continue in the background, so quick actions do not have to w
53
53
 
54
54
  ### Company-aware configuration
55
55
 
56
- GitHub tokens and sync cadence are shared at the plugin instance level, while repository mappings, advanced import defaults, and Paperclip board access are managed per company. When you open settings inside a specific company, you only edit that company's mappings and defaults.
56
+ GitHub tokens, repository mappings, advanced import defaults, and Paperclip board access are all managed per company, while sync cadence remains shared at the plugin instance level. When you open settings inside a specific company, you only edit that company's setup and defaults.
57
57
 
58
58
  ### Project binding that respects existing work
59
59
 
@@ -107,14 +107,15 @@ npx paperclipai plugin install --local "$PWD"
107
107
 
108
108
  1. Open the plugin settings for **GitHub Sync** from inside the Paperclip company you want to configure.
109
109
  2. Paste a GitHub token, validate it, and save it.
110
- 3. If the deployment is authenticated, connect Paperclip board access from the same settings page and complete the approval flow.
111
- 4. If the deployment is authenticated, choose which agents in the current company should receive the saved GitHub token as `GITHUB_TOKEN`.
112
- 5. Add one or more repository mappings for the current company.
113
- 6. For each mapping, either choose an existing GitHub-linked Paperclip project or enter the project name that should receive synced issues.
114
- 7. Optionally configure company-wide defaults for imported issues, including the default assignee, the default Paperclip status, and ignored GitHub usernames. Bot aliases such as `renovate[bot]` are matched when you save `renovate`.
115
- 8. Choose the automatic sync interval in minutes.
116
- 9. Save the settings and run the first manual sync.
117
- 10. Repeat inside other companies if they need their own mappings, defaults, board access, or agent token propagation.
110
+ 3. If the deployment is authenticated or `local_trusted`, the settings page shows Paperclip board access and GitHub token propagation controls so you can configure and test them locally.
111
+ 4. If the deployment is authenticated, connect Paperclip board access from the same settings page and complete the approval flow before running sync.
112
+ 5. If the deployment is authenticated or `local_trusted`, choose which agents in the current company should receive the saved GitHub token as `GITHUB_TOKEN`.
113
+ 6. Add one or more repository mappings for the current company.
114
+ 7. For each mapping, either choose an existing GitHub-linked Paperclip project or enter the project name that should receive synced issues.
115
+ 8. Optionally configure company-wide defaults for imported issues, including the default assignee, the default Paperclip status, and ignored GitHub usernames. Bot aliases such as `renovate[bot]` are matched when you save `renovate`.
116
+ 9. Choose the automatic sync interval in minutes.
117
+ 10. Save the settings and run the first manual sync.
118
+ 11. Repeat inside other companies if they need their own mappings, defaults, board access, or agent token propagation.
118
119
 
119
120
  Repository input accepts either `owner/repo` or `https://github.com/owner/repo`.
120
121
  When a token is saved, the settings page audits the mapped repositories for the permissions needed by pull request actions and warns when permissions are missing or GitHub cannot verify them yet.
@@ -153,10 +154,11 @@ Additional behavior:
153
154
 
154
155
  The plugin is designed to avoid persisting raw credentials in plugin state.
155
156
 
156
- - GitHub tokens saved through the UI are stored as Paperclip secret references.
157
+ - GitHub tokens saved through the UI are stored as per-company Paperclip secret references.
157
158
  - Paperclip board access tokens are also stored as per-company secret references.
158
- - The settings UI also keeps lightweight non-secret identity labels for those saved connections, so later visits can still show who the shared GitHub token and company board access are connected as.
159
- - On authenticated deployments, any selected propagation agents receive `GITHUB_TOKEN` as an agent env secret-ref binding that points at the same saved GitHub token secret instead of a copied raw token.
159
+ - The settings UI also keeps lightweight non-secret identity labels for those saved connections, so later visits can still show who that company’s GitHub token and board access are connected as.
160
+ - On authenticated and `local_trusted` deployments, any selected propagation agents receive `GITHUB_TOKEN` as an agent env secret-ref binding that points at the same saved GitHub token secret instead of a copied raw token.
161
+ - If an older save left the company token secret only in plugin state, the settings UI repairs the config mirror and retries selected-agent propagation from that same company secret.
160
162
  - The worker resolves those secret references at runtime instead of storing raw tokens in plugin state.
161
163
  - On authenticated Paperclip deployments, sync is blocked until the relevant company has connected Paperclip board access.
162
164
 
package/dist/manifest.js CHANGED
@@ -503,7 +503,7 @@ var require2 = createRequire(import.meta.url);
503
503
  var packageJson = require2("../package.json");
504
504
  var DASHBOARD_WIDGET_CAPABILITY = "ui.dashboardWidget.register";
505
505
  var SCHEDULE_TICK_CRON = "* * * * *";
506
- var MANIFEST_VERSION = "0.4.0"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
506
+ var MANIFEST_VERSION = "0.4.1"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
507
507
  var manifest = {
508
508
  id: "paperclip-github-plugin",
509
509
  apiVersion: 1,
@@ -537,9 +537,12 @@ var manifest = {
537
537
  instanceConfigSchema: {
538
538
  type: "object",
539
539
  properties: {
540
- githubTokenRef: {
541
- type: "string",
542
- title: "GitHub Token Secret"
540
+ githubTokenRefs: {
541
+ type: "object",
542
+ title: "GitHub Token Secrets",
543
+ additionalProperties: {
544
+ type: "string"
545
+ }
543
546
  },
544
547
  paperclipBoardApiTokenRefs: {
545
548
  type: "object",
package/dist/ui/index.js CHANGED
@@ -22400,6 +22400,11 @@ function requiresPaperclipBoardAccess(value) {
22400
22400
  const health = normalizePaperclipHealthResponse(value);
22401
22401
  return health?.deploymentMode?.toLowerCase() === "authenticated";
22402
22402
  }
22403
+ function shouldShowPaperclipBoardAccessSettings(value) {
22404
+ const health = normalizePaperclipHealthResponse(value);
22405
+ const deploymentMode = health?.deploymentMode?.toLowerCase();
22406
+ return deploymentMode === "authenticated" || deploymentMode === "local_trusted";
22407
+ }
22403
22408
 
22404
22409
  // src/ui/assignees.ts
22405
22410
  function normalizeCompanyAssigneeOptionsResponse(response) {
@@ -22648,18 +22653,32 @@ function normalizePluginConfigBoardTokenRefs(value) {
22648
22653
  }
22649
22654
  return Object.fromEntries(entries);
22650
22655
  }
22656
+ function normalizePluginConfigGitHubTokenRefs(value) {
22657
+ if (!value || typeof value !== "object") {
22658
+ return void 0;
22659
+ }
22660
+ const entries = Object.entries(value).map(([companyId, secretRef]) => {
22661
+ const normalizedCompanyId = normalizeOptionalString2(companyId);
22662
+ const normalizedSecretRef = normalizeOptionalString2(secretRef);
22663
+ return normalizedCompanyId && normalizedSecretRef ? [normalizedCompanyId, normalizedSecretRef] : null;
22664
+ }).filter((entry) => Boolean(entry));
22665
+ if (entries.length === 0) {
22666
+ return void 0;
22667
+ }
22668
+ return Object.fromEntries(entries);
22669
+ }
22651
22670
  function normalizePluginConfig(value) {
22652
22671
  if (!value || typeof value !== "object") {
22653
22672
  return {};
22654
22673
  }
22655
22674
  const record = { ...value };
22656
- const githubTokenRef = normalizeOptionalString2(record.githubTokenRef);
22675
+ const githubTokenRefs = normalizePluginConfigGitHubTokenRefs(record.githubTokenRefs);
22657
22676
  const paperclipBoardApiTokenRefs = normalizePluginConfigBoardTokenRefs(record.paperclipBoardApiTokenRefs);
22658
22677
  const paperclipApiBaseUrl = normalizePaperclipApiBaseUrl(record.paperclipApiBaseUrl);
22659
- if (githubTokenRef) {
22660
- record.githubTokenRef = githubTokenRef;
22678
+ if (githubTokenRefs) {
22679
+ record.githubTokenRefs = githubTokenRefs;
22661
22680
  } else {
22662
- delete record.githubTokenRef;
22681
+ delete record.githubTokenRefs;
22663
22682
  }
22664
22683
  if (paperclipBoardApiTokenRefs) {
22665
22684
  record.paperclipBoardApiTokenRefs = paperclipBoardApiTokenRefs;
@@ -22675,12 +22694,27 @@ function normalizePluginConfig(value) {
22675
22694
  }
22676
22695
  function mergePluginConfig(currentValue, patch5) {
22677
22696
  const current = normalizePluginConfig(currentValue);
22697
+ const currentGitHubTokenRefs = normalizePluginConfigGitHubTokenRefs(current.githubTokenRefs);
22698
+ const patchGitHubTokenRefs = normalizePluginConfigGitHubTokenRefs(patch5.githubTokenRefs);
22678
22699
  const currentBoardTokenRefs = normalizePluginConfigBoardTokenRefs(current.paperclipBoardApiTokenRefs);
22679
22700
  const patchBoardTokenRefs = normalizePluginConfigBoardTokenRefs(patch5.paperclipBoardApiTokenRefs);
22680
22701
  const next2 = normalizePluginConfig({
22681
22702
  ...current,
22682
22703
  ...patch5
22683
22704
  });
22705
+ if ("githubTokenRefs" in patch5) {
22706
+ const mergedGitHubTokenRefs = {
22707
+ ...currentGitHubTokenRefs ?? {},
22708
+ ...patchGitHubTokenRefs ?? {}
22709
+ };
22710
+ if (Object.keys(mergedGitHubTokenRefs).length > 0) {
22711
+ next2.githubTokenRefs = mergedGitHubTokenRefs;
22712
+ } else {
22713
+ delete next2.githubTokenRefs;
22714
+ }
22715
+ } else if (currentGitHubTokenRefs) {
22716
+ next2.githubTokenRefs = currentGitHubTokenRefs;
22717
+ }
22684
22718
  if ("paperclipBoardApiTokenRefs" in patch5) {
22685
22719
  const mergedBoardTokenRefs = {
22686
22720
  ...currentBoardTokenRefs ?? {},
@@ -23011,6 +23045,7 @@ function getSyncSetupMessage(issue, hasCompanyContext) {
23011
23045
  }
23012
23046
  function usePaperclipBoardAccessRequirement() {
23013
23047
  const [status, setStatus] = useState2("loading");
23048
+ const [visible, setVisible] = useState2(false);
23014
23049
  useEffect2(() => {
23015
23050
  let cancelled = false;
23016
23051
  void (async () => {
@@ -23020,8 +23055,10 @@ function usePaperclipBoardAccessRequirement() {
23020
23055
  }
23021
23056
  if (!health) {
23022
23057
  setStatus("unknown");
23058
+ setVisible(false);
23023
23059
  return;
23024
23060
  }
23061
+ setVisible(shouldShowPaperclipBoardAccessSettings(health));
23025
23062
  setStatus(requiresPaperclipBoardAccess(health) ? "required" : "not_required");
23026
23063
  })();
23027
23064
  return () => {
@@ -23030,7 +23067,8 @@ function usePaperclipBoardAccessRequirement() {
23030
23067
  }, []);
23031
23068
  return {
23032
23069
  status,
23033
- required: status === "required"
23070
+ required: status === "required",
23071
+ visible
23034
23072
  };
23035
23073
  }
23036
23074
  function getGitHubRateLimitResourceLabel(resource) {
@@ -31049,6 +31087,7 @@ function GitHubSyncSettingsPage() {
31049
31087
  const themeMode = useResolvedThemeMode();
31050
31088
  const boardAccessRequirement = usePaperclipBoardAccessRequirement();
31051
31089
  const armSyncCompletionToast = useSyncCompletionToast(form.syncState, toast);
31090
+ const githubTokenConfigSyncAttemptRef = useRef(null);
31052
31091
  const boardAccessConfigSyncAttemptRef = useRef(null);
31053
31092
  const assigneeFallbackAttemptRef = useRef(null);
31054
31093
  const currentSettings = settings.data ?? cachedSettings;
@@ -31162,6 +31201,75 @@ function GitHubSyncSettingsPage() {
31162
31201
  cancelled = true;
31163
31202
  };
31164
31203
  }, [currentSettings?.availableAssignees?.length, currentSettings?.updatedAt, hostContext.companyId]);
31204
+ useEffect2(() => {
31205
+ const companyId = hostContext.companyId;
31206
+ const secretRef = settings.data?.githubTokenNeedsConfigSync ? settings.data.githubTokenConfigSyncRef : void 0;
31207
+ if (!companyId || !secretRef) {
31208
+ return;
31209
+ }
31210
+ const attemptKey = `${companyId}:${secretRef}`;
31211
+ if (githubTokenConfigSyncAttemptRef.current === attemptKey) {
31212
+ return;
31213
+ }
31214
+ githubTokenConfigSyncAttemptRef.current = attemptKey;
31215
+ let cancelled = false;
31216
+ void (async () => {
31217
+ try {
31218
+ const pluginId = await resolveCurrentPluginId(pluginIdFromLocation);
31219
+ if (!pluginId) {
31220
+ throw new Error("Plugin id is required to finish syncing the GitHub token secret into plugin config.");
31221
+ }
31222
+ await patchPluginConfig(pluginId, {
31223
+ githubTokenRefs: {
31224
+ [companyId]: secretRef
31225
+ }
31226
+ });
31227
+ if (cancelled) {
31228
+ return;
31229
+ }
31230
+ const selectedAgentIds = normalizeAgentIds(settings.data?.advancedSettings?.githubTokenPropagationAgentIds);
31231
+ if (selectedAgentIds.length > 0) {
31232
+ try {
31233
+ await propagateGitHubTokenToSelectedAgents({
31234
+ selectedAgentIds,
31235
+ previousAgentIds: selectedAgentIds,
31236
+ githubTokenSecretRef: secretRef
31237
+ });
31238
+ } catch {
31239
+ }
31240
+ }
31241
+ notifyGitHubSyncSettingsChanged();
31242
+ try {
31243
+ await settings.refresh();
31244
+ } catch {
31245
+ return;
31246
+ }
31247
+ } catch (error) {
31248
+ if (cancelled) {
31249
+ return;
31250
+ }
31251
+ toast({
31252
+ title: "GitHub token needs reconnection",
31253
+ body: getActionErrorMessage(
31254
+ error,
31255
+ "GitHub Sync could not finish migrating the saved GitHub token secret into plugin config."
31256
+ ),
31257
+ tone: "error"
31258
+ });
31259
+ }
31260
+ })();
31261
+ return () => {
31262
+ cancelled = true;
31263
+ };
31264
+ }, [
31265
+ hostContext.companyId,
31266
+ pluginIdFromLocation,
31267
+ settings.data?.advancedSettings?.githubTokenPropagationAgentIds,
31268
+ settings.data?.githubTokenConfigSyncRef,
31269
+ settings.data?.githubTokenNeedsConfigSync,
31270
+ settings.refresh,
31271
+ toast
31272
+ ]);
31165
31273
  useEffect2(() => {
31166
31274
  const companyId = hostContext.companyId;
31167
31275
  const secretRef = settings.data?.paperclipBoardAccessNeedsConfigSync ? settings.data.paperclipBoardAccessConfigSyncRef : void 0;
@@ -31289,6 +31397,7 @@ function GitHubSyncSettingsPage() {
31289
31397
  const hasSavedToken = Boolean(form.githubTokenConfigured || showSavedTokenHint);
31290
31398
  const boardAccessConfigured = Boolean(form.paperclipBoardAccessConfigured);
31291
31399
  const boardAccessRequired = boardAccessRequirement.required;
31400
+ const boardAccessVisible = boardAccessRequirement.visible;
31292
31401
  const boardAccessReady = !boardAccessRequired || hasCompanyContext && boardAccessConfigured;
31293
31402
  const tokenStatus = tokenStatusOverride ?? (hasSavedToken ? "valid" : "required");
31294
31403
  const tokenTone = tokenStatus === "valid" ? "success" : tokenStatus === "invalid" ? "danger" : "warning";
@@ -31383,7 +31492,7 @@ function GitHubSyncSettingsPage() {
31383
31492
  const manualSyncScopePillLabel = hasCompanyContext ? "This company" : "All companies";
31384
31493
  const manualSyncButtonLabel = hasCompanyContext ? "Run sync for this company" : "Run sync across all companies";
31385
31494
  const advancedSettingsSummary = formatAdvancedSettingsSummary(form.advancedSettings, availableAssignees, {
31386
- includePropagation: boardAccessRequired
31495
+ includePropagation: boardAccessVisible
31387
31496
  });
31388
31497
  const assigneeSelectOptions = [
31389
31498
  { value: "", label: "Unassigned" },
@@ -31529,7 +31638,7 @@ function GitHubSyncSettingsPage() {
31529
31638
  });
31530
31639
  }
31531
31640
  async function propagateGitHubTokenToSelectedAgents(options) {
31532
- if (!boardAccessRequired) {
31641
+ if (!boardAccessVisible) {
31533
31642
  return;
31534
31643
  }
31535
31644
  const selectedAgentIds = normalizeAgentIds(options.selectedAgentIds);
@@ -31539,12 +31648,16 @@ function GitHubSyncSettingsPage() {
31539
31648
  }
31540
31649
  let githubTokenSecretRef = typeof options.githubTokenSecretRef === "string" && options.githubTokenSecretRef.trim() ? options.githubTokenSecretRef.trim() : void 0;
31541
31650
  if (!githubTokenSecretRef) {
31651
+ const companyId = hostContext.companyId;
31652
+ if (!companyId) {
31653
+ throw new Error("Company context is required to propagate the GitHub token to selected agents.");
31654
+ }
31542
31655
  const pluginId = await resolveCurrentPluginId(pluginIdFromLocation);
31543
31656
  if (!pluginId) {
31544
31657
  throw new Error("Plugin id is required to propagate the GitHub token to selected agents.");
31545
31658
  }
31546
31659
  const currentConfigResponse = await fetchJson(`/api/plugins/${pluginId}/config`);
31547
- githubTokenSecretRef = normalizePluginConfig(currentConfigResponse?.configJson).githubTokenRef;
31660
+ githubTokenSecretRef = normalizePluginConfig(currentConfigResponse?.configJson).githubTokenRefs?.[companyId];
31548
31661
  }
31549
31662
  if (!githubTokenSecretRef) {
31550
31663
  throw new Error("GitHub token propagation requires a GitHub token saved through this settings page.");
@@ -31594,7 +31707,9 @@ function GitHubSyncSettingsPage() {
31594
31707
  const secretName = `github_sync_${companyId.replace(/[^a-z0-9]+/gi, "_").toLowerCase()}`;
31595
31708
  const secret = await resolveOrCreateCompanySecret(companyId, secretName, trimmedToken);
31596
31709
  await patchPluginConfig(pluginId, {
31597
- githubTokenRef: secret.id
31710
+ githubTokenRefs: {
31711
+ [companyId]: secret.id
31712
+ }
31598
31713
  });
31599
31714
  await saveRegistration({
31600
31715
  companyId,
@@ -32048,7 +32163,7 @@ function GitHubSyncSettingsPage() {
32048
32163
  /* @__PURE__ */ jsx2("div", { className: "ghsync__permission-audit-list", children: /* @__PURE__ */ jsx2("div", { className: "ghsync__permission-audit-item", children: /* @__PURE__ */ jsx2("span", { children: tokenPermissionAuditData?.warnings[0] ?? "Add a mapped repository in this company so GitHub Sync can verify the token permissions it needs." }) }) })
32049
32164
  ] }) : null
32050
32165
  ] }),
32051
- boardAccessRequired ? /* @__PURE__ */ jsxs2("section", { className: "ghsync__section", children: [
32166
+ boardAccessVisible ? /* @__PURE__ */ jsxs2("section", { className: "ghsync__section", children: [
32052
32167
  /* @__PURE__ */ jsxs2("div", { className: "ghsync__section-head", children: [
32053
32168
  /* @__PURE__ */ jsxs2("div", { className: "ghsync__section-copy", children: [
32054
32169
  /* @__PURE__ */ jsxs2("div", { className: "ghsync__section-title-row", children: [
@@ -32062,7 +32177,7 @@ function GitHubSyncSettingsPage() {
32062
32177
  hostContext.companyId ? /* @__PURE__ */ jsxs2("div", { className: "ghsync__connected", children: [
32063
32178
  /* @__PURE__ */ jsxs2("div", { children: [
32064
32179
  /* @__PURE__ */ jsx2("strong", { children: boardAccessConfigured ? boardAccessIdentity ? `Connected as ${boardAccessIdentity}` : "Connected" : boardAccessRequired ? "Required" : boardAccessRequirement.status === "loading" ? "Checking requirement" : "Optional" }),
32065
- /* @__PURE__ */ jsx2("span", { children: boardAccessConfigured ? "Used for Paperclip API calls." : boardAccessRequired ? "Required in authenticated deployments." : boardAccessRequirement.status === "loading" ? "Checking whether it is required." : "Only needed when Paperclip API calls require sign-in." })
32180
+ /* @__PURE__ */ jsx2("span", { children: boardAccessConfigured ? "Used for Paperclip API calls." : boardAccessRequired ? "Required in authenticated deployments." : boardAccessRequirement.status === "loading" ? "Checking whether it is required." : "Available here for local testing and only required when Paperclip API calls need sign-in." })
32066
32181
  ] }),
32067
32182
  /* @__PURE__ */ jsx2(
32068
32183
  "button",
@@ -32318,7 +32433,7 @@ function GitHubSyncSettingsPage() {
32318
32433
  ),
32319
32434
  /* @__PURE__ */ jsx2("p", { className: "ghsync__hint", children: "Comma or newline separated." })
32320
32435
  ] }),
32321
- boardAccessRequired ? /* @__PURE__ */ jsxs2("div", { className: "ghsync__field", children: [
32436
+ boardAccessVisible ? /* @__PURE__ */ jsxs2("div", { className: "ghsync__field", children: [
32322
32437
  /* @__PURE__ */ jsx2("label", { htmlFor: "advanced-token-propagation", children: "Propagate GitHub token to agents" }),
32323
32438
  /* @__PURE__ */ jsx2(
32324
32439
  SettingsAgentMultiPicker,
@@ -32492,7 +32607,7 @@ function GitHubSyncSettingsPage() {
32492
32607
  ] }),
32493
32608
  /* @__PURE__ */ jsx2("span", { children: !repositoriesUnlocked ? "Requires a token." : savedMappingCount > 0 ? hasCompanyContext ? `${savedMappingCount} saved.` : `${savedMappingCount} saved.` : hasCompanyContext ? "Add a repository." : "Select a company." })
32494
32609
  ] }),
32495
- boardAccessRequired ? /* @__PURE__ */ jsxs2("div", { className: "ghsync__check", children: [
32610
+ boardAccessVisible ? /* @__PURE__ */ jsxs2("div", { className: "ghsync__check", children: [
32496
32611
  /* @__PURE__ */ jsxs2("div", { className: "ghsync__check-top", children: [
32497
32612
  /* @__PURE__ */ jsx2("strong", { children: "Paperclip board access" }),
32498
32613
  /* @__PURE__ */ jsx2("span", { className: `ghsync__badge ${getToneClass(boardAccessStatusTone)}`, children: boardAccessStatusLabel })