@growthub/cli 0.9.10 → 0.9.11

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.
Files changed (28) hide show
  1. package/README.md +1 -1
  2. package/assets/worker-kits/creative-strategist-v1/kit.json +5 -2
  3. package/assets/worker-kits/growthub-agency-portal-starter-v1/kit.json +4 -1
  4. package/assets/worker-kits/growthub-ai-website-cloner-v1/kit.json +6 -3
  5. package/assets/worker-kits/growthub-creative-video-pipeline-v1/kit.json +4 -1
  6. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/README.md +4 -4
  7. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integration-entities/route.js +50 -0
  8. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/globals.css +284 -15
  9. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/page.jsx +5 -2
  10. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/settings/integrations/page.jsx +4 -5
  11. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/workspace-builder.jsx +507 -34
  12. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/growthub-connection-normalizer.js +12 -16
  13. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/index.js +61 -11
  14. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/domain/integrations.js +31 -1
  15. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-schema.js +54 -7
  16. package/assets/worker-kits/growthub-custom-workspace-starter-v1/kit.json +5 -2
  17. package/assets/worker-kits/growthub-email-marketing-v1/kit.json +5 -2
  18. package/assets/worker-kits/growthub-geo-seo-v1/kit.json +5 -2
  19. package/assets/worker-kits/growthub-hyperframes-studio-v1/kit.json +5 -2
  20. package/assets/worker-kits/growthub-marketing-skills-v1/kit.json +6 -3
  21. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/kit.json +5 -2
  22. package/assets/worker-kits/growthub-open-montage-studio-v1/kit.json +6 -3
  23. package/assets/worker-kits/growthub-postiz-social-v1/kit.json +5 -2
  24. package/assets/worker-kits/growthub-twenty-crm-v1/kit.json +6 -3
  25. package/assets/worker-kits/growthub-video-use-studio-v1/kit.json +5 -2
  26. package/assets/worker-kits/growthub-zernio-social-v1/kit.json +5 -2
  27. package/dist/index.js +1750 -433
  28. package/package.json +1 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  `@growthub/cli` is the CLI control plane for Growthub Local.
4
4
 
5
- It creates governed **Workspaces** from any source — repo, skill, kit, template, or greenfield. The Workspace is the top-level product object; this CLI is the local executor that creates, customizes, and inspects them.
5
+ It creates governed **Workspaces** from any source — repo, skill, kit, template, or starter. The Workspace is the top-level product object; this CLI is the local executor that creates, customizes, and inspects them.
6
6
 
7
7
  ## Start here: create a governed Workspace
8
8
 
@@ -3,7 +3,7 @@
3
3
  "kit": {
4
4
  "id": "creative-strategist-v1",
5
5
  "version": "1.0.0",
6
- "name": "Growthub Agent Worker Kit Creative Strategist",
6
+ "name": "Growthub Agent Worker Kit \u2014 Creative Strategist",
7
7
  "description": "Frozen Creative Strategist worker kit for exporting a working-directory-ready video creative brief worker.",
8
8
  "type": "worker",
9
9
  "visibility": "public-open-source",
@@ -99,5 +99,8 @@
99
99
  "provenance": {
100
100
  "sourceRepo": "claude-workers",
101
101
  "frozenAt": "2026-04-09T00:00:00.000Z"
102
- }
102
+ },
103
+ "workspaceVisibility": "addon",
104
+ "workspaceCompatible": true,
105
+ "workspaceCategory": "creative-strategy"
103
106
  }
@@ -154,5 +154,8 @@
154
154
  "provenance": {
155
155
  "sourceRepo": "growthub-local",
156
156
  "frozenAt": "2026-04-23T00:00:00.000Z"
157
- }
157
+ },
158
+ "workspaceVisibility": "official",
159
+ "workspaceCompatible": true,
160
+ "workspaceCategory": "workspace-addon"
158
161
  }
@@ -3,8 +3,8 @@
3
3
  "kit": {
4
4
  "id": "growthub-ai-website-cloner-v1",
5
5
  "version": "1.0.0",
6
- "name": "Growthub Agent Worker Kit AI Website Cloner",
7
- "description": "Self-contained local workspace for cloning any website into a clean Next.js 16 + shadcn/ui + Tailwind CSS v4 codebase using AI coding agents. Produces pixel-perfect component clones from a target URL via multi-phase reconnaissance, spec writing, parallel builder dispatch, and visual QA all driven by the ai-website-cloner-template fork.",
6
+ "name": "Growthub Agent Worker Kit \u2014 AI Website Cloner",
7
+ "description": "Self-contained local workspace for cloning any website into a clean Next.js 16 + shadcn/ui + Tailwind CSS v4 codebase using AI coding agents. Produces pixel-perfect component clones from a target URL via multi-phase reconnaissance, spec writing, parallel builder dispatch, and visual QA \u2014 all driven by the ai-website-cloner-template fork.",
8
8
  "type": "worker",
9
9
  "visibility": "public-open-source",
10
10
  "sourceRepo": "growthub-local",
@@ -113,5 +113,8 @@
113
113
  "provenance": {
114
114
  "sourceRepo": "growthub-local",
115
115
  "frozenAt": "2026-04-15T00:00:00.000Z"
116
- }
116
+ },
117
+ "workspaceVisibility": "addon",
118
+ "workspaceCompatible": false,
119
+ "workspaceCategory": "studio"
117
120
  }
@@ -150,5 +150,8 @@
150
150
  "provenance": {
151
151
  "sourceRepo": "growthub-local",
152
152
  "frozenAt": "2026-04-24T00:00:00.000Z"
153
- }
153
+ },
154
+ "workspaceVisibility": "addon",
155
+ "workspaceCompatible": true,
156
+ "workspaceCategory": "video-pipeline"
154
157
  }
@@ -16,14 +16,14 @@ It intentionally depends on adapter contracts:
16
16
 
17
17
  The Growthub local-first operator shell remains at `../../studio`.
18
18
 
19
- Settings exposes two integration lanes:
19
+ Settings exposes two universal integration lanes:
20
20
 
21
- - Data sources: Windsor AI, Google Sheets blended data, Google Analytics, Shopify, Meta Facebook/Instagram.
22
- - Workspace integrations: Asana, Slack, GoHighLevel, Google Drive, Notion.
21
+ - Data sources.
22
+ - Workspace integrations.
23
23
 
24
24
  The `/settings/integrations` page is part of the official governed workspace app shell. It uses the same light workspace rail, toolbar, and product object model as the dashboard workspace, and it renders Growthub bridge account state without redirecting to or borrowing the agency portal kit.
25
25
 
26
- Use `GROWTHUB_WORKSPACE_INTEGRATION_ADAPTER=growthub-bridge` when the deployed app should read connection state from the Growthub GH app MCP bridge. The reusable primitive is `lib/adapters/integrations/growthub-connection-normalizer.js`; it accepts SDK/profile-style `integrations[]` payloads and GH app MCP `accounts[]` payloads, then emits the same normalized object shape used by `byo-api-key`. Keep provider tokens in the hosted authority layer or named env vars; this app consumes normalized connection metadata only.
26
+ Use `GROWTHUB_WORKSPACE_INTEGRATION_ADAPTER=growthub-bridge` when the deployed app should read connection state from the Growthub GH app MCP bridge. The reusable primitive is `lib/adapters/integrations/growthub-connection-normalizer.js`; it accepts SDK/profile-style `integrations[]` payloads and GH app MCP `accounts[]` payloads, then emits the same normalized object shape used by `byo-api-key`. Keep source credentials in the hosted authority layer or named env vars; this app consumes normalized connection metadata only.
27
27
 
28
28
  For first boot, the bundled app also supports a hybrid path: keep `GROWTHUB_WORKSPACE_INTEGRATION_ADAPTER=growthub-bridge` and set `WINDSOR_API_KEY` locally. That overlays connected state for Windsor AI and Google Sheets blended data without moving the rest of the workspace off the hosted bridge authority path.
29
29
 
@@ -0,0 +1,50 @@
1
+ /**
2
+ * GET /api/workspace/integration-entities?integrationId=<id>
3
+ *
4
+ * Returns NormalizedIntegrationEntity[] for the requested integration when a
5
+ * server-side object resolver can fetch real source objects.
6
+ * This route is server-side only: no source credentials are forwarded to the
7
+ * browser, and no provider queries are executed in the client.
8
+ *
9
+ * Authority invariant (from GOVERNED_WORKSPACE_TOPOLOGY_V1.md):
10
+ * The browser never queries integrations, holds tokens, or resolves
11
+ * entity metadata directly. This route is the only server-side surface
12
+ * that crosses the authority boundary.
13
+ *
14
+ * Response shape:
15
+ * 200 { integrationId: string, entities: NormalizedIntegrationEntity[], source: "resolver", requiresObjectResolver: boolean }
16
+ * 400 { error: string }
17
+ */
18
+ import { NextResponse } from "next/server";
19
+ import { listEntityMetadataForIntegration } from "@/lib/adapters/integrations";
20
+ import { readAdapterConfig } from "@/lib/adapters/env";
21
+
22
+ async function GET(request) {
23
+ const { searchParams } = new URL(request.url);
24
+ const integrationId = searchParams.get("integrationId");
25
+
26
+ if (!integrationId || typeof integrationId !== "string" || !integrationId.trim()) {
27
+ return NextResponse.json(
28
+ { error: "integrationId query parameter is required" },
29
+ { status: 400 }
30
+ );
31
+ }
32
+
33
+ const config = readAdapterConfig();
34
+ const isBridgeMode =
35
+ config.integrationAdapter === "growthub-bridge" &&
36
+ config.growthubBridge?.baseUrl &&
37
+ !!process.env.GROWTHUB_BRIDGE_ACCESS_TOKEN;
38
+
39
+ const entities = await listEntityMetadataForIntegration(integrationId.trim());
40
+
41
+ return NextResponse.json({
42
+ integrationId: integrationId.trim(),
43
+ entities,
44
+ source: entities.length ? "resolver" : "none",
45
+ requiresObjectResolver: entities.length === 0,
46
+ authority: isBridgeMode ? "growthub-bridge" : "local"
47
+ });
48
+ }
49
+
50
+ export { GET };
@@ -991,6 +991,22 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
991
991
  text-overflow: ellipsis;
992
992
  white-space: nowrap;
993
993
  }
994
+ .workspace-widget-source-chip {
995
+ max-width: 150px;
996
+ min-width: 0;
997
+ flex: 0 1 auto;
998
+ overflow: hidden;
999
+ border: 1px solid #d1d5db;
1000
+ border-radius: 999px;
1001
+ background: #fff;
1002
+ color: #374151;
1003
+ padding: 2px 8px;
1004
+ font-size: 11px;
1005
+ font-weight: 600;
1006
+ line-height: 16px;
1007
+ text-overflow: ellipsis;
1008
+ white-space: nowrap;
1009
+ }
994
1010
  .workspace-widget-preview-title button {
995
1011
  width: 22px;
996
1012
  height: 22px;
@@ -1057,11 +1073,14 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
1057
1073
  .workspace-chart-preview span {
1058
1074
  flex: 1;
1059
1075
  border-radius: 5px 5px 0 0;
1060
- background: #d9e4ff;
1076
+ background: var(--chart-accent, #d9e4ff);
1061
1077
  }
1062
1078
  .workspace-widget-panel {
1063
1079
  border-left: 1px solid #e8e8e8;
1064
1080
  padding: 0 12px 16px;
1081
+ max-height: 100vh;
1082
+ overflow-y: auto;
1083
+ overscroll-behavior: contain;
1065
1084
  }
1066
1085
  .workspace-panel-title {
1067
1086
  height: 48px;
@@ -1785,32 +1804,41 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
1785
1804
  }
1786
1805
 
1787
1806
  /* Settings row buttons (replace bare div on the root inspector list) */
1807
+ .workspace-settings-row,
1788
1808
  .workspace-settings-list .workspace-settings-row {
1789
1809
  width: 100%;
1790
1810
  display: flex;
1791
1811
  align-items: center;
1792
1812
  justify-content: space-between;
1793
- min-height: 34px;
1794
- border: 0;
1795
- border-radius: 5px;
1796
- background: transparent;
1813
+ gap: 10px;
1814
+ min-height: 38px;
1815
+ border: 1px solid #e8eef8;
1816
+ border-radius: 7px;
1817
+ background: #fff;
1797
1818
  color: #666;
1798
1819
  font: inherit;
1799
1820
  font-size: 13px;
1800
- padding: 0 8px;
1821
+ padding: 8px 10px;
1801
1822
  text-align: left;
1802
1823
  cursor: pointer;
1824
+ box-shadow: 0 2px 8px rgba(15, 23, 42, 0.05);
1803
1825
  }
1826
+ .workspace-settings-row:hover:not([disabled]),
1804
1827
  .workspace-settings-list .workspace-settings-row:hover:not([disabled]) {
1805
- background: #f3f3f3;
1828
+ border-color: #d6e4ff;
1829
+ background: #fff;
1806
1830
  }
1831
+ .workspace-settings-row[disabled],
1807
1832
  .workspace-settings-list .workspace-settings-row[disabled] {
1808
1833
  cursor: default;
1809
1834
  color: #888;
1810
1835
  }
1836
+ .workspace-settings-row code,
1811
1837
  .workspace-settings-list .workspace-settings-row code {
1812
1838
  color: #888;
1813
1839
  background: transparent;
1840
+ text-align: right;
1841
+ white-space: normal;
1814
1842
  }
1815
1843
 
1816
1844
  /* Source picker */
@@ -1818,6 +1846,43 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
1818
1846
  display: grid;
1819
1847
  gap: 4px;
1820
1848
  }
1849
+ .workspace-source-object-list {
1850
+ display: grid;
1851
+ gap: 8px;
1852
+ }
1853
+ .workspace-source-object-row {
1854
+ width: 100%;
1855
+ display: grid;
1856
+ grid-template-columns: 30px minmax(0, 1fr) auto;
1857
+ align-items: center;
1858
+ gap: 10px;
1859
+ border: 1px solid #e8e8e8;
1860
+ border-radius: 7px;
1861
+ background: #fff;
1862
+ color: #444;
1863
+ padding: 9px 10px;
1864
+ text-align: left;
1865
+ cursor: pointer;
1866
+ font: inherit;
1867
+ box-shadow: 0 3px 10px rgba(15, 23, 42, 0.06);
1868
+ }
1869
+ .workspace-source-object-row[disabled] {
1870
+ cursor: default;
1871
+ }
1872
+ .workspace-source-object-row.active {
1873
+ border-color: #111827;
1874
+ box-shadow: 0 0 0 1px #111827, 0 3px 10px rgba(15, 23, 42, 0.06);
1875
+ }
1876
+ .workspace-source-object-icon {
1877
+ width: 28px;
1878
+ height: 28px;
1879
+ display: grid;
1880
+ place-items: center;
1881
+ border: 1px solid #e5e7eb;
1882
+ border-radius: 6px;
1883
+ background: #f9fafb;
1884
+ color: #374151;
1885
+ }
1821
1886
  .workspace-source-controls {
1822
1887
  display: grid;
1823
1888
  gap: 8px;
@@ -1872,14 +1937,80 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
1872
1937
  text-align: left;
1873
1938
  cursor: pointer;
1874
1939
  font: inherit;
1940
+ box-shadow: 0 2px 8px rgba(15, 23, 42, 0.05);
1875
1941
  }
1876
1942
  .workspace-source-row:hover {
1877
1943
  border-color: #d0d0d0;
1878
1944
  background: #fafafa;
1879
1945
  }
1880
1946
  .workspace-source-row.active {
1881
- border-color: #38bdf8;
1882
- background: rgba(56, 189, 248, 0.06);
1947
+ border-color: #111827;
1948
+ background: #f9fafb;
1949
+ box-shadow: 0 0 0 1px #111827, 0 2px 8px rgba(15, 23, 42, 0.05);
1950
+ }
1951
+ .workspace-source-info-card {
1952
+ margin: 0 0 14px;
1953
+ padding: 10px 12px;
1954
+ border: 1px solid #e5e7eb;
1955
+ border-radius: 8px;
1956
+ background: #fff;
1957
+ color: #6b7280;
1958
+ font-size: 12px;
1959
+ line-height: 1.4;
1960
+ box-shadow: 0 2px 8px rgba(15, 23, 42, 0.04);
1961
+ }
1962
+ .workspace-custom-source-config,
1963
+ .workspace-active-source-state,
1964
+ .workspace-filter-source-state {
1965
+ display: grid;
1966
+ gap: 7px;
1967
+ border: 1px solid #e8eef8;
1968
+ border-radius: 8px;
1969
+ background: #fff;
1970
+ box-shadow: 0 2px 8px rgba(15, 23, 42, 0.05);
1971
+ padding: 10px;
1972
+ }
1973
+ .workspace-active-source-state,
1974
+ .workspace-filter-source-state {
1975
+ margin-top: 10px;
1976
+ }
1977
+ .workspace-active-source-state span,
1978
+ .workspace-filter-source-state span {
1979
+ color: #8a97a8;
1980
+ font-size: 10px;
1981
+ font-weight: 700;
1982
+ text-transform: uppercase;
1983
+ }
1984
+ .workspace-active-source-state strong,
1985
+ .workspace-filter-source-state strong {
1986
+ color: #1f2937;
1987
+ font-size: 13px;
1988
+ }
1989
+ .workspace-active-source-state code,
1990
+ .workspace-filter-source-state code {
1991
+ color: #64748b;
1992
+ background: transparent;
1993
+ font-size: 11px;
1994
+ overflow-wrap: anywhere;
1995
+ }
1996
+ .workspace-custom-source-config label {
1997
+ display: grid;
1998
+ gap: 5px;
1999
+ }
2000
+ .workspace-custom-source-config span {
2001
+ color: #8a97a8;
2002
+ font-size: 10px;
2003
+ font-weight: 700;
2004
+ text-transform: uppercase;
2005
+ }
2006
+ .workspace-custom-source-config input {
2007
+ border: 1px solid #e5e7eb;
2008
+ border-radius: 6px;
2009
+ background: #fff;
2010
+ color: #333;
2011
+ font: inherit;
2012
+ font-size: 12px;
2013
+ padding: 7px 8px;
1883
2014
  }
1884
2015
  .workspace-source-icon {
1885
2016
  width: 26px;
@@ -1912,8 +2043,118 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
1912
2043
  font-style: normal;
1913
2044
  }
1914
2045
  .workspace-source-tick {
1915
- color: #38bdf8;
2046
+ color: #111827;
1916
2047
  font-weight: 700;
2048
+ display: inline-grid;
2049
+ place-items: center;
2050
+ }
2051
+
2052
+ /* Governed integration reference binding — entity selector + badge */
2053
+ .workspace-entity-selector {
2054
+ display: grid;
2055
+ gap: 6px;
2056
+ margin-top: 4px;
2057
+ padding-top: 10px;
2058
+ border-top: 1px solid #ececec;
2059
+ }
2060
+ .workspace-entity-dropdown {
2061
+ display: grid;
2062
+ gap: 5px;
2063
+ min-width: 0;
2064
+ }
2065
+ .workspace-entity-dropdown span {
2066
+ color: #8a8a8a;
2067
+ font-size: 11px;
2068
+ font-weight: 700;
2069
+ }
2070
+ .workspace-entity-dropdown select {
2071
+ width: 100%;
2072
+ min-width: 0;
2073
+ min-height: 38px;
2074
+ border: 1px solid #d1d5db;
2075
+ border-radius: 7px;
2076
+ background: #fff;
2077
+ color: #111827;
2078
+ font: inherit;
2079
+ font-size: 13px;
2080
+ padding: 0 10px;
2081
+ box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
2082
+ }
2083
+ .workspace-entity-dropdown select:focus {
2084
+ border-color: #111827;
2085
+ outline: 0;
2086
+ box-shadow: 0 0 0 1px #111827;
2087
+ }
2088
+ .workspace-entity-badge {
2089
+ display: grid;
2090
+ grid-template-columns: 26px 1fr auto;
2091
+ align-items: center;
2092
+ gap: 8px;
2093
+ padding: 7px 10px;
2094
+ border: 1px solid #d1d5db;
2095
+ border-radius: 7px;
2096
+ background: #fff;
2097
+ min-width: 0;
2098
+ }
2099
+ .workspace-entity-badge-icon {
2100
+ width: 24px;
2101
+ height: 24px;
2102
+ display: grid;
2103
+ place-items: center;
2104
+ border: 1px solid #e5e7eb;
2105
+ border-radius: 5px;
2106
+ background: #f9fafb;
2107
+ color: #374151;
2108
+ font-size: 11px;
2109
+ font-weight: 700;
2110
+ flex-shrink: 0;
2111
+ }
2112
+ .workspace-entity-badge-meta {
2113
+ display: flex;
2114
+ flex-direction: column;
2115
+ min-width: 0;
2116
+ }
2117
+ .workspace-entity-badge-meta strong {
2118
+ color: #111827;
2119
+ font-size: 12px;
2120
+ font-weight: 600;
2121
+ white-space: nowrap;
2122
+ overflow: hidden;
2123
+ text-overflow: ellipsis;
2124
+ }
2125
+ .workspace-entity-badge-meta em {
2126
+ color: #6b7280;
2127
+ font-size: 10px;
2128
+ font-style: normal;
2129
+ white-space: nowrap;
2130
+ overflow: hidden;
2131
+ text-overflow: ellipsis;
2132
+ }
2133
+ .workspace-entity-badge-clear {
2134
+ width: 20px;
2135
+ height: 20px;
2136
+ display: grid;
2137
+ place-items: center;
2138
+ border: 0;
2139
+ border-radius: 4px;
2140
+ background: transparent;
2141
+ color: #6b7280;
2142
+ cursor: pointer;
2143
+ flex-shrink: 0;
2144
+ }
2145
+ .workspace-entity-badge-clear:hover {
2146
+ background: #f3f4f6;
2147
+ color: #111827;
2148
+ }
2149
+ .workspace-entity-empty {
2150
+ color: #bbb;
2151
+ font-size: 12px;
2152
+ padding: 6px 2px;
2153
+ margin: 0;
2154
+ }
2155
+ .workspace-entity-sample-hint {
2156
+ color: #f59e0b;
2157
+ font-size: 11px;
1917
2158
  }
1918
2159
 
1919
2160
  /* Fields manager */
@@ -2055,10 +2296,11 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
2055
2296
  .workspace-filter-clause input {
2056
2297
  border: 1px solid #e5e5e5;
2057
2298
  border-radius: 6px;
2058
- background: #fafafa;
2299
+ background: #fff;
2059
2300
  color: #444;
2060
2301
  font: inherit;
2061
2302
  padding: 6px 8px;
2303
+ box-shadow: 0 1px 4px rgba(15, 23, 42, 0.04);
2062
2304
  }
2063
2305
  .workspace-sort-row button,
2064
2306
  .workspace-filter-clause button {
@@ -2080,13 +2322,14 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
2080
2322
  align-items: center;
2081
2323
  gap: 4px;
2082
2324
  border: 1px dashed #d8d8d8;
2083
- background: #fafafa;
2325
+ background: #fff;
2084
2326
  color: #555;
2085
2327
  border-radius: 6px;
2086
2328
  padding: 6px 10px;
2087
2329
  cursor: pointer;
2088
2330
  font: inherit;
2089
2331
  font-size: 12px;
2332
+ box-shadow: 0 1px 4px rgba(15, 23, 42, 0.04);
2090
2333
  }
2091
2334
  .workspace-add-clause:hover:not(:disabled) {
2092
2335
  border-color: #38bdf8;
@@ -2105,6 +2348,32 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
2105
2348
  width: fit-content;
2106
2349
  background: #fafafa;
2107
2350
  }
2351
+ .workspace-color-preview-row {
2352
+ display: grid;
2353
+ grid-template-columns: auto 22px minmax(0, 1fr);
2354
+ align-items: center;
2355
+ gap: 8px;
2356
+ border: 1px solid #e8eef8;
2357
+ border-radius: 7px;
2358
+ background: #fff;
2359
+ padding: 8px 10px;
2360
+ box-shadow: 0 1px 4px rgba(15, 23, 42, 0.04);
2361
+ }
2362
+ .workspace-color-preview-row span {
2363
+ color: #777;
2364
+ font-size: 12px;
2365
+ }
2366
+ .workspace-color-preview-row em {
2367
+ width: 22px;
2368
+ height: 22px;
2369
+ border-radius: 5px;
2370
+ border: 1px solid rgba(15, 23, 42, 0.12);
2371
+ }
2372
+ .workspace-color-preview-row code {
2373
+ color: #64748b;
2374
+ background: transparent;
2375
+ font-size: 11px;
2376
+ }
2108
2377
  .workspace-filter-op-toggle button {
2109
2378
  border: 0;
2110
2379
  background: transparent;
@@ -2224,7 +2493,7 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
2224
2493
  }
2225
2494
  .workspace-chart-preview .workspace-chart-bar-h {
2226
2495
  height: 12px;
2227
- background: #38bdf8;
2496
+ background: var(--chart-accent, #38bdf8);
2228
2497
  border-radius: 3px;
2229
2498
  position: relative;
2230
2499
  }
@@ -2244,7 +2513,7 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
2244
2513
  width: 60%;
2245
2514
  aspect-ratio: 1;
2246
2515
  border-radius: 50%;
2247
- background: conic-gradient(#38bdf8 0 60%, #93c5fd 60% 85%, #cffafe 85% 100%);
2516
+ background: conic-gradient(var(--chart-accent, #38bdf8) 0 60%, #93c5fd 60% 85%, #cffafe 85% 100%);
2248
2517
  }
2249
2518
  .workspace-chart-preview.kind-line {
2250
2519
  display: grid;
@@ -2283,7 +2552,7 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
2283
2552
  height: 36%;
2284
2553
  border-radius: 999px 999px 0 0;
2285
2554
  background:
2286
- radial-gradient(circle at 50% 100%, transparent 56%, #38bdf8 56%, #38bdf8 var(--gauge-fill, 70%), #e5e5e5 var(--gauge-fill, 70%));
2555
+ radial-gradient(circle at 50% 100%, transparent 56%, var(--chart-accent, #38bdf8) 56%, var(--chart-accent, #38bdf8) var(--gauge-fill, 70%), #e5e5e5 var(--gauge-fill, 70%));
2287
2556
  position: relative;
2288
2557
  }
2289
2558
  .workspace-chart-preview span em {
@@ -1,18 +1,21 @@
1
1
  import workspaceConfig from "../growthub.config.json";
2
2
  import { readAdapterConfig } from "@/lib/adapters/env";
3
- import { describeIntegrationAdapter } from "@/lib/adapters/integrations";
3
+ import { describeIntegrationAdapter, listGovernedWorkspaceIntegrations } from "@/lib/adapters/integrations";
4
+ import { groupIntegrationsByLane } from "@/lib/domain/integrations";
4
5
  import { describePersistenceMode } from "@/lib/workspace-config";
5
6
  import WorkspaceBuilder from "./workspace-builder.jsx";
6
7
 
7
- function Home() {
8
+ async function Home() {
8
9
  const adapterConfig = readAdapterConfig();
9
10
  const integrationAdapter = describeIntegrationAdapter();
11
+ const integrations = await listGovernedWorkspaceIntegrations();
10
12
  const persistence = describePersistenceMode();
11
13
  return (
12
14
  <WorkspaceBuilder
13
15
  initialConfig={workspaceConfig}
14
16
  adapterConfig={adapterConfig}
15
17
  integrationAdapter={integrationAdapter}
18
+ integrationSettings={{ integrations: groupIntegrationsByLane(integrations) }}
16
19
  persistence={persistence}
17
20
  />
18
21
  );
@@ -10,10 +10,9 @@ function countConnected(rows) {
10
10
  function integrationKey(item, lane, index) {
11
11
  return [
12
12
  lane,
13
- item.provider,
14
- item.id,
15
- item.accountId,
16
- item.connectionId,
13
+ item.provider,
14
+ item.id,
15
+ item.connectionId,
17
16
  index
18
17
  ].filter(Boolean).join(":");
19
18
  }
@@ -99,7 +98,7 @@ async function IntegrationsSettingsPage() {
99
98
  <section className="workspace-integration-toolbar">
100
99
  <div>
101
100
  <strong>Connection catalog</strong>
102
- <p>{countConnected(allRows)}/{allRows.length} connected. Setup state is resolved from the selected adapter without storing provider tokens in the app.</p>
101
+ <p>{countConnected(allRows)}/{allRows.length} connected. Setup state is resolved from the selected adapter without storing source credentials in the app.</p>
103
102
  </div>
104
103
  </section>
105
104