paperclip-github-plugin 0.9.0 → 0.9.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
@@ -205,7 +205,10 @@ If Paperclip-managed secrets are not available, the worker can read a local fall
205
205
 
206
206
  ```json
207
207
  {
208
- "githubToken": "ghp_your_token_here"
208
+ "githubToken": "ghp_your_token_here",
209
+ "githubTokensByCompanyId": {
210
+ "company-uuid": "ghp_company_specific_token_here"
211
+ }
209
212
  }
210
213
  ```
211
214
 
@@ -213,7 +216,8 @@ Notes:
213
216
 
214
217
  - This file is read by the worker only.
215
218
  - The raw token is never persisted back into plugin state or plugin config.
216
- - A GitHub token secret saved through the settings UI takes precedence over the local file.
219
+ - A GitHub token secret saved through the settings UI is the primary source. If the current Paperclip host rejects plugin secret-ref resolution while company-scoped plugin config is unavailable, GitHub Sync stores the validated token in `githubTokensByCompanyId` as a worker-local compatibility fallback.
220
+ - On authenticated deployments, selected agents receive `GITHUB_TOKEN` as a latest-version secret-ref env binding, and the settings UI patches agent adapter config with `replaceAdapterConfig: true` so newer Paperclip hosts persist the merged env map.
217
221
 
218
222
  ### Worker-facing Paperclip API URL
219
223
 
package/dist/manifest.js CHANGED
@@ -642,7 +642,7 @@ var PULL_REQUEST_ASSET_API_ROUTE_URL_PATH = `/api/plugins/${GITHUB_SYNC_PLUGIN_I
642
642
  var require2 = createRequire(import.meta.url);
643
643
  var packageJson = require2("../package.json");
644
644
  var SCHEDULE_TICK_CRON = "* * * * *";
645
- var MANIFEST_VERSION = "0.9.0"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
645
+ var MANIFEST_VERSION = "0.9.1"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
646
646
  var manifest = {
647
647
  id: GITHUB_SYNC_PLUGIN_ID,
648
648
  apiVersion: 1,
package/dist/ui/index.js CHANGED
@@ -23165,6 +23165,9 @@ function resolveToolbarButtonState(params) {
23165
23165
  syncStartPending
23166
23166
  };
23167
23167
  }
23168
+ function clearGitHubTokenConfigSyncAttemptOnFailure(currentAttemptKey, failedAttemptKey) {
23169
+ return currentAttemptKey === failedAttemptKey ? null : currentAttemptKey;
23170
+ }
23168
23171
  function getSyncToastTitle(syncState) {
23169
23172
  if (getActiveRateLimitPause(syncState)) {
23170
23173
  return "GitHub sync is paused";
@@ -28430,7 +28433,8 @@ function getAgentPropagationPatch(params) {
28430
28433
  ...currentEnv,
28431
28434
  GITHUB_TOKEN: {
28432
28435
  type: "secret_ref",
28433
- secretId: params.githubTokenSecretRef
28436
+ secretId: params.githubTokenSecretRef,
28437
+ version: "latest"
28434
28438
  }
28435
28439
  };
28436
28440
  if (JSON.stringify(nextEnv2) === JSON.stringify(currentEnv)) {
@@ -28485,7 +28489,8 @@ async function applyGitHubTokenPropagationUpdate(params) {
28485
28489
  await fetchJson(`/api/agents/${params.agentId}`, {
28486
28490
  method: "PATCH",
28487
28491
  body: JSON.stringify({
28488
- adapterConfig: nextAdapterConfig
28492
+ adapterConfig: nextAdapterConfig,
28493
+ replaceAdapterConfig: true
28489
28494
  })
28490
28495
  });
28491
28496
  }
@@ -31968,6 +31973,7 @@ function GitHubSyncSettingsPage() {
31968
31973
  const saveRegistration = usePluginAction("settings.saveRegistration");
31969
31974
  const updateBoardAccess = usePluginAction("settings.updateBoardAccess");
31970
31975
  const validateToken = usePluginAction("settings.validateToken");
31976
+ const ensureGitHubTokenAvailable = usePluginAction("settings.ensureGitHubTokenAvailable");
31971
31977
  const runSyncNow = usePluginAction("sync.runNow");
31972
31978
  const cancelSync = usePluginAction("sync.cancel");
31973
31979
  const [form, setForm] = useState2(EMPTY_SETTINGS);
@@ -31995,6 +32001,7 @@ function GitHubSyncSettingsPage() {
31995
32001
  const themeMode = useResolvedThemeMode();
31996
32002
  const boardAccessRequirement = usePaperclipBoardAccessRequirement();
31997
32003
  const armSyncCompletionToast = useSyncCompletionToast(form.syncState, toast);
32004
+ const githubTokenConfigSyncAttemptRef = useRef(null);
31998
32005
  const boardAccessConfigSyncAttemptRef = useRef(null);
31999
32006
  const assigneeFallbackAttemptRef = useRef(null);
32000
32007
  const currentSettings = settings.data ?? cachedSettings;
@@ -32111,6 +32118,76 @@ function GitHubSyncSettingsPage() {
32111
32118
  cancelled = true;
32112
32119
  };
32113
32120
  }, [currentSettings?.availableAssignees?.length, currentSettings?.updatedAt, hostContext.companyId]);
32121
+ useEffect2(() => {
32122
+ const companyId = hostContext.companyId;
32123
+ const secretRef = settings.data?.githubTokenNeedsConfigSync ? settings.data.githubTokenConfigSyncRef : void 0;
32124
+ if (!companyId || !secretRef) {
32125
+ return;
32126
+ }
32127
+ const attemptKey = `${companyId}:${secretRef}`;
32128
+ if (githubTokenConfigSyncAttemptRef.current === attemptKey) {
32129
+ return;
32130
+ }
32131
+ githubTokenConfigSyncAttemptRef.current = attemptKey;
32132
+ let cancelled = false;
32133
+ void (async () => {
32134
+ try {
32135
+ const pluginId = await resolveCurrentPluginId(pluginIdFromLocation);
32136
+ if (!pluginId) {
32137
+ throw new Error("Plugin id is required to finish syncing the GitHub token into plugin config.");
32138
+ }
32139
+ await patchPluginConfig(pluginId, {
32140
+ githubTokenRefs: {
32141
+ [companyId]: secretRef
32142
+ }
32143
+ });
32144
+ const selectedAgentIds = normalizeAgentIds(settings.data?.advancedSettings?.githubTokenPropagationAgentIds);
32145
+ if (selectedAgentIds.length > 0) {
32146
+ await propagateGitHubTokenToSelectedAgents({
32147
+ selectedAgentIds,
32148
+ previousAgentIds: selectedAgentIds,
32149
+ githubTokenSecretRef: secretRef
32150
+ });
32151
+ }
32152
+ if (cancelled) {
32153
+ return;
32154
+ }
32155
+ notifyGitHubSyncSettingsChanged();
32156
+ try {
32157
+ await settings.refresh();
32158
+ } catch {
32159
+ return;
32160
+ }
32161
+ } catch (error) {
32162
+ githubTokenConfigSyncAttemptRef.current = clearGitHubTokenConfigSyncAttemptOnFailure(
32163
+ githubTokenConfigSyncAttemptRef.current,
32164
+ attemptKey
32165
+ );
32166
+ if (cancelled) {
32167
+ return;
32168
+ }
32169
+ toast({
32170
+ title: "GitHub token needs reconnection",
32171
+ body: getActionErrorMessage(
32172
+ error,
32173
+ "GitHub Sync could not finish migrating the saved GitHub token into plugin config."
32174
+ ),
32175
+ tone: "error"
32176
+ });
32177
+ }
32178
+ })();
32179
+ return () => {
32180
+ cancelled = true;
32181
+ };
32182
+ }, [
32183
+ hostContext.companyId,
32184
+ pluginIdFromLocation,
32185
+ settings.data?.advancedSettings?.githubTokenPropagationAgentIds,
32186
+ settings.data?.githubTokenNeedsConfigSync,
32187
+ settings.data?.githubTokenConfigSyncRef,
32188
+ settings.refresh,
32189
+ toast
32190
+ ]);
32114
32191
  useEffect2(() => {
32115
32192
  const companyId = hostContext.companyId;
32116
32193
  const secretRef = settings.data?.paperclipBoardAccessNeedsConfigSync ? settings.data.paperclipBoardAccessConfigSyncRef : void 0;
@@ -32581,6 +32658,16 @@ function GitHubSyncSettingsPage() {
32581
32658
  },
32582
32659
  githubTokenLogin: validation.login
32583
32660
  });
32661
+ let availabilityWarning = null;
32662
+ try {
32663
+ await ensureGitHubTokenAvailable({
32664
+ companyId,
32665
+ githubTokenRef: secret.id,
32666
+ token: trimmedToken
32667
+ });
32668
+ } catch (error) {
32669
+ availabilityWarning = error;
32670
+ }
32584
32671
  const selectedAgentIds = normalizeAgentIds(currentSettings?.advancedSettings?.githubTokenPropagationAgentIds);
32585
32672
  let propagationError = null;
32586
32673
  try {
@@ -32616,6 +32703,16 @@ function GitHubSyncSettingsPage() {
32616
32703
  tone: "error"
32617
32704
  });
32618
32705
  }
32706
+ if (availabilityWarning) {
32707
+ toast({
32708
+ title: "GitHub token saved, but worker token access needs attention",
32709
+ body: getActionErrorMessage(
32710
+ availabilityWarning,
32711
+ "GitHub Sync could not verify worker access to the saved token."
32712
+ ),
32713
+ tone: "error"
32714
+ });
32715
+ }
32619
32716
  notifyGitHubSyncSettingsChanged();
32620
32717
  try {
32621
32718
  await settings.refresh();
@@ -35133,6 +35230,7 @@ export {
35133
35230
  GitHubSyncProjectPullRequestsPage,
35134
35231
  GitHubSyncProjectPullRequestsSidebarItem,
35135
35232
  GitHubSyncSettingsPage,
35233
+ clearGitHubTokenConfigSyncAttemptOnFailure,
35136
35234
  index_default as default,
35137
35235
  resolveGitHubIssueDetailTabState,
35138
35236
  resolveOrCreateProject,