paperclip-github-plugin 0.4.0 → 0.4.2
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 +4 -4
- package/dist/manifest.js +10 -7
- package/dist/ui/index.js +65 -20
- package/dist/ui/index.js.map +2 -2
- package/dist/worker.js +475 -153
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,11 +53,11 @@ 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
|
|
56
|
+
GitHub tokens, repository mappings, advanced import defaults, Paperclip board access, and sync cadence are managed per company. When you open settings inside a specific company, you only edit that company's setup.
|
|
57
57
|
|
|
58
58
|
### Project binding that respects existing work
|
|
59
59
|
|
|
60
|
-
If a company already has a Paperclip project bound to a GitHub repository workspace, the settings UI can reuse that project instead of creating a duplicate. New mappings can also create and bind a Paperclip project automatically, and those newly created projects opt into isolated issue checkouts.
|
|
60
|
+
If a company already has a Paperclip project bound to a GitHub repository workspace, the settings UI can reuse that project instead of creating a duplicate. New mappings can also create and bind a Paperclip project automatically, and those newly created projects opt into isolated issue checkouts with new issues defaulting to isolated checkout.
|
|
61
61
|
|
|
62
62
|
### Status sync with delivery context
|
|
63
63
|
|
|
@@ -153,9 +153,9 @@ Additional behavior:
|
|
|
153
153
|
|
|
154
154
|
The plugin is designed to avoid persisting raw credentials in plugin state.
|
|
155
155
|
|
|
156
|
-
- GitHub tokens saved through the UI are stored as Paperclip secret references.
|
|
156
|
+
- GitHub tokens saved through the UI are stored as per-company Paperclip secret references.
|
|
157
157
|
- 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
|
|
158
|
+
- The settings UI also keeps lightweight non-secret identity labels for those saved connections, so later visits can still show who each company GitHub token and board access are connected as.
|
|
159
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.
|
|
160
160
|
- The worker resolves those secret references at runtime instead of storing raw tokens in plugin state.
|
|
161
161
|
- On authenticated Paperclip deployments, sync is blocked until the relevant company has connected Paperclip board access.
|
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.
|
|
506
|
+
var MANIFEST_VERSION = "0.4.2"?.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
|
-
|
|
541
|
-
type: "
|
|
542
|
-
title: "GitHub Token
|
|
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",
|
|
@@ -591,10 +594,10 @@ var manifest = {
|
|
|
591
594
|
exportName: "GitHubSyncDashboardWidget"
|
|
592
595
|
},
|
|
593
596
|
{
|
|
594
|
-
type: "
|
|
597
|
+
type: "taskDetailView",
|
|
595
598
|
id: "paperclip-github-plugin-issue-detail-tab",
|
|
596
599
|
displayName: "GitHub",
|
|
597
|
-
exportName: "
|
|
600
|
+
exportName: "GitHubSyncIssueTaskDetailView",
|
|
598
601
|
entityTypes: ["issue"]
|
|
599
602
|
},
|
|
600
603
|
{
|
|
@@ -615,7 +618,7 @@ var manifest = {
|
|
|
615
618
|
id: "paperclip-github-plugin-toolbar-button",
|
|
616
619
|
displayName: "GitHub Sync",
|
|
617
620
|
exportName: "GitHubSyncEntityToolbarButton",
|
|
618
|
-
entityTypes: ["project"
|
|
621
|
+
entityTypes: ["project"]
|
|
619
622
|
},
|
|
620
623
|
{
|
|
621
624
|
type: "settingsPage",
|
package/dist/ui/index.js
CHANGED
|
@@ -22648,18 +22648,32 @@ function normalizePluginConfigBoardTokenRefs(value) {
|
|
|
22648
22648
|
}
|
|
22649
22649
|
return Object.fromEntries(entries);
|
|
22650
22650
|
}
|
|
22651
|
+
function normalizePluginConfigGitHubTokenRefs(value) {
|
|
22652
|
+
if (!value || typeof value !== "object") {
|
|
22653
|
+
return void 0;
|
|
22654
|
+
}
|
|
22655
|
+
const entries = Object.entries(value).map(([companyId, secretRef]) => {
|
|
22656
|
+
const normalizedCompanyId = normalizeOptionalString2(companyId);
|
|
22657
|
+
const normalizedSecretRef = normalizeOptionalString2(secretRef);
|
|
22658
|
+
return normalizedCompanyId && normalizedSecretRef ? [normalizedCompanyId, normalizedSecretRef] : null;
|
|
22659
|
+
}).filter((entry) => Boolean(entry));
|
|
22660
|
+
if (entries.length === 0) {
|
|
22661
|
+
return void 0;
|
|
22662
|
+
}
|
|
22663
|
+
return Object.fromEntries(entries);
|
|
22664
|
+
}
|
|
22651
22665
|
function normalizePluginConfig(value) {
|
|
22652
22666
|
if (!value || typeof value !== "object") {
|
|
22653
22667
|
return {};
|
|
22654
22668
|
}
|
|
22655
22669
|
const record = { ...value };
|
|
22656
|
-
const
|
|
22670
|
+
const githubTokenRefs = normalizePluginConfigGitHubTokenRefs(record.githubTokenRefs);
|
|
22657
22671
|
const paperclipBoardApiTokenRefs = normalizePluginConfigBoardTokenRefs(record.paperclipBoardApiTokenRefs);
|
|
22658
22672
|
const paperclipApiBaseUrl = normalizePaperclipApiBaseUrl(record.paperclipApiBaseUrl);
|
|
22659
|
-
if (
|
|
22660
|
-
record.
|
|
22673
|
+
if (githubTokenRefs) {
|
|
22674
|
+
record.githubTokenRefs = githubTokenRefs;
|
|
22661
22675
|
} else {
|
|
22662
|
-
delete record.
|
|
22676
|
+
delete record.githubTokenRefs;
|
|
22663
22677
|
}
|
|
22664
22678
|
if (paperclipBoardApiTokenRefs) {
|
|
22665
22679
|
record.paperclipBoardApiTokenRefs = paperclipBoardApiTokenRefs;
|
|
@@ -22675,12 +22689,27 @@ function normalizePluginConfig(value) {
|
|
|
22675
22689
|
}
|
|
22676
22690
|
function mergePluginConfig(currentValue, patch5) {
|
|
22677
22691
|
const current = normalizePluginConfig(currentValue);
|
|
22692
|
+
const currentGitHubTokenRefs = normalizePluginConfigGitHubTokenRefs(current.githubTokenRefs);
|
|
22693
|
+
const patchGitHubTokenRefs = normalizePluginConfigGitHubTokenRefs(patch5.githubTokenRefs);
|
|
22678
22694
|
const currentBoardTokenRefs = normalizePluginConfigBoardTokenRefs(current.paperclipBoardApiTokenRefs);
|
|
22679
22695
|
const patchBoardTokenRefs = normalizePluginConfigBoardTokenRefs(patch5.paperclipBoardApiTokenRefs);
|
|
22680
22696
|
const next2 = normalizePluginConfig({
|
|
22681
22697
|
...current,
|
|
22682
22698
|
...patch5
|
|
22683
22699
|
});
|
|
22700
|
+
if ("githubTokenRefs" in patch5) {
|
|
22701
|
+
const mergedGitHubTokenRefs = {
|
|
22702
|
+
...currentGitHubTokenRefs ?? {},
|
|
22703
|
+
...patchGitHubTokenRefs ?? {}
|
|
22704
|
+
};
|
|
22705
|
+
if (Object.keys(mergedGitHubTokenRefs).length > 0) {
|
|
22706
|
+
next2.githubTokenRefs = mergedGitHubTokenRefs;
|
|
22707
|
+
} else {
|
|
22708
|
+
delete next2.githubTokenRefs;
|
|
22709
|
+
}
|
|
22710
|
+
} else if (currentGitHubTokenRefs) {
|
|
22711
|
+
next2.githubTokenRefs = currentGitHubTokenRefs;
|
|
22712
|
+
}
|
|
22684
22713
|
if ("paperclipBoardApiTokenRefs" in patch5) {
|
|
22685
22714
|
const mergedBoardTokenRefs = {
|
|
22686
22715
|
...currentBoardTokenRefs ?? {},
|
|
@@ -27733,7 +27762,8 @@ async function resolveOrCreateProject(companyId, projectName) {
|
|
|
27733
27762
|
name: projectName.trim(),
|
|
27734
27763
|
status: "planned",
|
|
27735
27764
|
executionWorkspacePolicy: {
|
|
27736
|
-
enabled: true
|
|
27765
|
+
enabled: true,
|
|
27766
|
+
defaultMode: "isolated_workspace"
|
|
27737
27767
|
}
|
|
27738
27768
|
})
|
|
27739
27769
|
});
|
|
@@ -31294,7 +31324,7 @@ function GitHubSyncSettingsPage() {
|
|
|
31294
31324
|
const tokenTone = tokenStatus === "valid" ? "success" : tokenStatus === "invalid" ? "danger" : "warning";
|
|
31295
31325
|
const tokenBannerLabel = tokenStatus === "valid" ? "Token valid" : tokenStatus === "invalid" ? "Token invalid" : "Token required";
|
|
31296
31326
|
const tokenBadgeLabel = tokenStatus === "valid" ? "Valid" : tokenStatus === "invalid" ? "Invalid" : "Required";
|
|
31297
|
-
const tokenStatusDescription = tokenStatus === "invalid" ? "GitHub rejected the last token." : tokenStatus === "required" ? "Add a token." : "
|
|
31327
|
+
const tokenStatusDescription = tokenStatus === "invalid" ? "GitHub rejected the last token." : tokenStatus === "required" ? hasCompanyContext ? "Add a token for this company." : "Select a company." : hasCompanyContext ? "Token configured for the selected company context." : "Saved in one or more companies.";
|
|
31298
31328
|
const tokenDescription = tokenStatusDescription;
|
|
31299
31329
|
const tokenPermissionAuditData = tokenPermissionAudit.data;
|
|
31300
31330
|
const tokenPermissionAuditMeta = getGitHubTokenPermissionAuditMeta(tokenPermissionAuditData);
|
|
@@ -31418,7 +31448,7 @@ function GitHubSyncSettingsPage() {
|
|
|
31418
31448
|
] }),
|
|
31419
31449
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync__section-head-actions", children: [
|
|
31420
31450
|
/* @__PURE__ */ jsx2("span", { className: `ghsync__scope-pill ${hasCompanyContext ? "ghsync__scope-pill--company" : "ghsync__scope-pill--mixed"}`, children: hasCompanyContext ? currentCompanyName : "No company" }),
|
|
31421
|
-
/* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--
|
|
31451
|
+
hasCompanyContext ? /* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--company", children: "Company" }) : null,
|
|
31422
31452
|
/* @__PURE__ */ jsxs2("span", { className: "ghsync__badge ghsync__badge--neutral", children: [
|
|
31423
31453
|
/* @__PURE__ */ jsx2(LoadingSpinner, { size: "sm", label: "Loading settings" }),
|
|
31424
31454
|
"Loading"
|
|
@@ -31538,13 +31568,18 @@ function GitHubSyncSettingsPage() {
|
|
|
31538
31568
|
return;
|
|
31539
31569
|
}
|
|
31540
31570
|
let githubTokenSecretRef = typeof options.githubTokenSecretRef === "string" && options.githubTokenSecretRef.trim() ? options.githubTokenSecretRef.trim() : void 0;
|
|
31571
|
+
const companyId = hostContext.companyId;
|
|
31541
31572
|
if (!githubTokenSecretRef) {
|
|
31573
|
+
if (!companyId) {
|
|
31574
|
+
throw new Error("Company context is required to propagate the GitHub token.");
|
|
31575
|
+
}
|
|
31542
31576
|
const pluginId = await resolveCurrentPluginId(pluginIdFromLocation);
|
|
31543
31577
|
if (!pluginId) {
|
|
31544
31578
|
throw new Error("Plugin id is required to propagate the GitHub token to selected agents.");
|
|
31545
31579
|
}
|
|
31546
31580
|
const currentConfigResponse = await fetchJson(`/api/plugins/${pluginId}/config`);
|
|
31547
|
-
|
|
31581
|
+
const normalizedConfig = normalizePluginConfig(currentConfigResponse?.configJson);
|
|
31582
|
+
githubTokenSecretRef = normalizedConfig.githubTokenRefs?.[companyId];
|
|
31548
31583
|
}
|
|
31549
31584
|
if (!githubTokenSecretRef) {
|
|
31550
31585
|
throw new Error("GitHub token propagation requires a GitHub token saved through this settings page.");
|
|
@@ -31594,11 +31629,15 @@ function GitHubSyncSettingsPage() {
|
|
|
31594
31629
|
const secretName = `github_sync_${companyId.replace(/[^a-z0-9]+/gi, "_").toLowerCase()}`;
|
|
31595
31630
|
const secret = await resolveOrCreateCompanySecret(companyId, secretName, trimmedToken);
|
|
31596
31631
|
await patchPluginConfig(pluginId, {
|
|
31597
|
-
|
|
31632
|
+
githubTokenRefs: {
|
|
31633
|
+
[companyId]: secret.id
|
|
31634
|
+
}
|
|
31598
31635
|
});
|
|
31599
31636
|
await saveRegistration({
|
|
31600
31637
|
companyId,
|
|
31601
|
-
|
|
31638
|
+
githubTokenRefs: {
|
|
31639
|
+
[companyId]: secret.id
|
|
31640
|
+
},
|
|
31602
31641
|
githubTokenLogin: validation.login
|
|
31603
31642
|
});
|
|
31604
31643
|
const selectedAgentIds = normalizeAgentIds(currentSettings?.advancedSettings?.githubTokenPropagationAgentIds);
|
|
@@ -31920,7 +31959,7 @@ function GitHubSyncSettingsPage() {
|
|
|
31920
31959
|
] }),
|
|
31921
31960
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync__section-head-actions", children: [
|
|
31922
31961
|
/* @__PURE__ */ jsx2("span", { className: `ghsync__scope-pill ${hasCompanyContext ? "ghsync__scope-pill--company" : "ghsync__scope-pill--mixed"}`, children: hasCompanyContext ? currentCompanyName : "No company" }),
|
|
31923
|
-
/* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--
|
|
31962
|
+
/* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--company", children: "Company" }),
|
|
31924
31963
|
/* @__PURE__ */ jsxs2("span", { className: `ghsync__badge ${getToneClass(tokenTone)}`, children: [
|
|
31925
31964
|
/* @__PURE__ */ jsx2("span", { className: "ghsync__badge-dot", "aria-hidden": "true" }),
|
|
31926
31965
|
tokenBannerLabel
|
|
@@ -31942,7 +31981,7 @@ function GitHubSyncSettingsPage() {
|
|
|
31942
31981
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync__section-copy", children: [
|
|
31943
31982
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync__section-title-row", children: [
|
|
31944
31983
|
/* @__PURE__ */ jsx2("h4", { children: "GitHub access" }),
|
|
31945
|
-
/* @__PURE__ */ jsx2("div", { className: "ghsync__section-tags", children: /* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--
|
|
31984
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync__section-tags", children: /* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--company", children: "Company" }) })
|
|
31946
31985
|
] }),
|
|
31947
31986
|
/* @__PURE__ */ jsx2("p", { children: tokenDescription })
|
|
31948
31987
|
] }),
|
|
@@ -31950,8 +31989,8 @@ function GitHubSyncSettingsPage() {
|
|
|
31950
31989
|
] }),
|
|
31951
31990
|
!hasCompanyContext ? /* @__PURE__ */ jsxs2("div", { className: "ghsync__locked", children: [
|
|
31952
31991
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
31953
|
-
/* @__PURE__ */ jsx2("strong", { children:
|
|
31954
|
-
/* @__PURE__ */ jsx2("span", { children:
|
|
31992
|
+
/* @__PURE__ */ jsx2("strong", { children: "Company required" }),
|
|
31993
|
+
/* @__PURE__ */ jsx2("span", { children: "Open a company to view or save its token." })
|
|
31955
31994
|
] }),
|
|
31956
31995
|
/* @__PURE__ */ jsx2("span", { className: "ghsync__badge ghsync__badge--neutral", children: "Read only" })
|
|
31957
31996
|
] }) : showTokenForm ? /* @__PURE__ */ jsxs2("form", { className: "ghsync__stack", onSubmit: handleSaveToken, children: [
|
|
@@ -32008,8 +32047,8 @@ function GitHubSyncSettingsPage() {
|
|
|
32008
32047
|
] }) })
|
|
32009
32048
|
] }) : /* @__PURE__ */ jsxs2("div", { className: "ghsync__connected", children: [
|
|
32010
32049
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
32011
|
-
/* @__PURE__ */ jsx2("strong", { children: validatedLogin ? `Authenticated as ${validatedLogin}` : "
|
|
32012
|
-
/* @__PURE__ */ jsx2("span", { children:
|
|
32050
|
+
/* @__PURE__ */ jsx2("strong", { children: validatedLogin ? `Authenticated as ${validatedLogin}` : "Company token ready" }),
|
|
32051
|
+
/* @__PURE__ */ jsx2("span", { children: `Used for sync in ${currentCompanyName}.` })
|
|
32013
32052
|
] }),
|
|
32014
32053
|
/* @__PURE__ */ jsx2(
|
|
32015
32054
|
"button",
|
|
@@ -32349,7 +32388,7 @@ function GitHubSyncSettingsPage() {
|
|
|
32349
32388
|
/* @__PURE__ */ jsx2("h4", { children: "Sync" }),
|
|
32350
32389
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync__section-tags", children: [
|
|
32351
32390
|
/* @__PURE__ */ jsx2("span", { className: manualSyncScopePillClass, children: manualSyncScopePillLabel }),
|
|
32352
|
-
/* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--global", children: "
|
|
32391
|
+
/* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--global", children: "Company cadence" })
|
|
32353
32392
|
] })
|
|
32354
32393
|
] }),
|
|
32355
32394
|
syncSectionDescription ? /* @__PURE__ */ jsx2("p", { children: syncSectionDescription }) : null
|
|
@@ -32386,12 +32425,16 @@ function GitHubSyncSettingsPage() {
|
|
|
32386
32425
|
/* @__PURE__ */ jsx2("p", { className: `ghsync__hint${scheduleFrequencyError ? " ghsync__hint--error" : ""}`, children: scheduleFrequencyError ?? "Minutes." })
|
|
32387
32426
|
] }),
|
|
32388
32427
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync__schedule-meta", children: [
|
|
32389
|
-
/* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--global", children: "
|
|
32428
|
+
/* @__PURE__ */ jsx2("span", { className: "ghsync__scope-pill ghsync__scope-pill--global", children: "Company" }),
|
|
32390
32429
|
/* @__PURE__ */ jsxs2("strong", { children: [
|
|
32391
32430
|
"Auto-sync ",
|
|
32392
32431
|
scheduleDescription
|
|
32393
32432
|
] }),
|
|
32394
|
-
/* @__PURE__ */
|
|
32433
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
32434
|
+
"Used for sync in ",
|
|
32435
|
+
currentCompanyName,
|
|
32436
|
+
"."
|
|
32437
|
+
] })
|
|
32395
32438
|
] })
|
|
32396
32439
|
] }),
|
|
32397
32440
|
!syncUnlocked ? /* @__PURE__ */ jsxs2("div", { className: "ghsync__locked", children: [
|
|
@@ -33436,7 +33479,7 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
33436
33479
|
] }) : null
|
|
33437
33480
|
] });
|
|
33438
33481
|
}
|
|
33439
|
-
function
|
|
33482
|
+
function GitHubSyncIssueTaskDetailView() {
|
|
33440
33483
|
const context = useHostContext();
|
|
33441
33484
|
const themeMode = useResolvedThemeMode();
|
|
33442
33485
|
const theme = themeMode === "light" ? LIGHT_PALETTE : DARK_PALETTE;
|
|
@@ -33459,6 +33502,7 @@ function GitHubSyncIssueDetailTab() {
|
|
|
33459
33502
|
detailKey
|
|
33460
33503
|
);
|
|
33461
33504
|
}
|
|
33505
|
+
var GitHubSyncIssueDetailTab = GitHubSyncIssueTaskDetailView;
|
|
33462
33506
|
function GitHubSyncCommentAnnotation() {
|
|
33463
33507
|
const context = useHostContext();
|
|
33464
33508
|
const themeMode = useResolvedThemeMode();
|
|
@@ -33504,6 +33548,7 @@ export {
|
|
|
33504
33548
|
GitHubSyncEntityToolbarButton,
|
|
33505
33549
|
GitHubSyncGlobalToolbarButton,
|
|
33506
33550
|
GitHubSyncIssueDetailTab,
|
|
33551
|
+
GitHubSyncIssueTaskDetailView,
|
|
33507
33552
|
GitHubSyncProjectPullRequestsPage,
|
|
33508
33553
|
GitHubSyncProjectPullRequestsSidebarItem,
|
|
33509
33554
|
GitHubSyncSettingsPage,
|