@betterportal/config-manager 10.1.41 → 10.1.43

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 (27) hide show
  1. package/lib/.bsb/clients/service-betterportal-config-manager.d.ts +1 -1
  2. package/lib/.bsb/clients/service-betterportal-config-manager.js +1 -1
  3. package/lib/bp-contracts/org.betterportal.config-manager.json +191 -1
  4. package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts.map +1 -1
  5. package/lib/plugins/service-betterportal-config-manager/adminApi.js +72 -0
  6. package/lib/plugins/service-betterportal-config-manager/adminApi.js.map +1 -1
  7. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/GET.d.ts.map +1 -1
  8. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/GET.js +12 -2
  9. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/GET.js.map +1 -1
  10. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/route.impl.d.ts +50 -0
  11. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/route.impl.d.ts.map +1 -1
  12. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/route.impl.js +29 -2
  13. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/route.impl.js.map +1 -1
  14. package/lib/plugins/service-betterportal-config-manager/index.d.ts +0 -2
  15. package/lib/plugins/service-betterportal-config-manager/index.d.ts.map +1 -1
  16. package/lib/plugins/service-betterportal-config-manager/index.js +7 -0
  17. package/lib/plugins/service-betterportal-config-manager/index.js.map +1 -1
  18. package/lib/plugins/service-betterportal-config-manager/m2mConnections.d.ts +45 -0
  19. package/lib/plugins/service-betterportal-config-manager/m2mConnections.d.ts.map +1 -0
  20. package/lib/plugins/service-betterportal-config-manager/m2mConnections.js +228 -0
  21. package/lib/plugins/service-betterportal-config-manager/m2mConnections.js.map +1 -0
  22. package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts.map +1 -1
  23. package/lib/plugins/service-betterportal-config-manager/storage/core.js +13 -0
  24. package/lib/plugins/service-betterportal-config-manager/storage/core.js.map +1 -1
  25. package/lib/schemas/service-betterportal-config-manager.json +1 -8
  26. package/lib/schemas/service-betterportal-config-manager.plugin.json +1 -8
  27. package/package.json +5 -5
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Auto-generated BSB virtual client for service-betterportal-config-manager
3
3
  * DO NOT EDIT - Regenerated on every build
4
- * @version 10.1.41
4
+ * @version 10.1.43
5
5
  */
6
6
  import { ServiceClient, BSBService } from "@bsb/base";
7
7
  import type { Observable, BSBServiceClientDefinition, EventInputType } from "@bsb/base";
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Auto-generated BSB virtual client for service-betterportal-config-manager
3
3
  * DO NOT EDIT - Regenerated on every build
4
- * @version 10.1.41
4
+ * @version 10.1.43
5
5
  */
6
6
  import { ServiceClient, bsb, createBroadcastEvent, createEventSchemas } from "@bsb/base";
7
7
  const _platformConfigChangedSchema = bsb.object({
@@ -4,7 +4,7 @@
4
4
  "pluginId": "org.betterportal.config-manager",
5
5
  "title": "BetterPortal Config Manager",
6
6
  "description": "Admin-facing BetterPortal service for discovering and managing service config surfaces.",
7
- "version": "10.1.41",
7
+ "version": "10.1.43",
8
8
  "category": "service",
9
9
  "deploymentModes": [
10
10
  "self-hosted"
@@ -388,6 +388,9 @@
388
388
  },
389
389
  "auth": {
390
390
  "required": true,
391
+ "callers": [
392
+ "user"
393
+ ],
391
394
  "permissions": [
392
395
  {
393
396
  "serviceId": "org.betterportal.config-manager",
@@ -586,6 +589,9 @@
586
589
  },
587
590
  "auth": {
588
591
  "required": true,
592
+ "callers": [
593
+ "user"
594
+ ],
589
595
  "permissions": [
590
596
  {
591
597
  "serviceId": "org.betterportal.config-manager",
@@ -728,6 +734,9 @@
728
734
  },
729
735
  "auth": {
730
736
  "required": true,
737
+ "callers": [
738
+ "user"
739
+ ],
731
740
  "permissions": [
732
741
  {
733
742
  "serviceId": "org.betterportal.config-manager",
@@ -943,6 +952,9 @@
943
952
  },
944
953
  "auth": {
945
954
  "required": true,
955
+ "callers": [
956
+ "user"
957
+ ],
946
958
  "permissions": [
947
959
  {
948
960
  "serviceId": "org.betterportal.config-manager",
@@ -1126,6 +1138,9 @@
1126
1138
  },
1127
1139
  "auth": {
1128
1140
  "required": true,
1141
+ "callers": [
1142
+ "user"
1143
+ ],
1129
1144
  "permissions": [
1130
1145
  {
1131
1146
  "serviceId": "org.betterportal.config-manager",
@@ -1419,6 +1434,9 @@
1419
1434
  },
1420
1435
  "auth": {
1421
1436
  "required": true,
1437
+ "callers": [
1438
+ "user"
1439
+ ],
1422
1440
  "permissions": [
1423
1441
  {
1424
1442
  "serviceId": "org.betterportal.config-manager",
@@ -1680,6 +1698,167 @@
1680
1698
  "description": "Tenant currently selected in the service registry."
1681
1699
  }
1682
1700
  },
1701
+ "selectedAppId": {
1702
+ "kind": "optional",
1703
+ "inner": {
1704
+ "kind": "string",
1705
+ "minLength": 1
1706
+ },
1707
+ "metadata": {
1708
+ "description": "App currently selected for service connections."
1709
+ }
1710
+ },
1711
+ "m2mConnections": {
1712
+ "kind": "array",
1713
+ "items": {
1714
+ "kind": "object",
1715
+ "properties": {
1716
+ "sourceServiceId": {
1717
+ "kind": "string",
1718
+ "minLength": 1
1719
+ },
1720
+ "sourceServiceTitle": {
1721
+ "kind": "string",
1722
+ "minLength": 1
1723
+ },
1724
+ "sourceServiceType": {
1725
+ "kind": "string",
1726
+ "minLength": 1
1727
+ },
1728
+ "requestId": {
1729
+ "kind": "string",
1730
+ "minLength": 1
1731
+ },
1732
+ "title": {
1733
+ "kind": "string",
1734
+ "minLength": 1
1735
+ },
1736
+ "contractId": {
1737
+ "kind": "string",
1738
+ "minLength": 1
1739
+ },
1740
+ "version": {
1741
+ "kind": "optional",
1742
+ "inner": {
1743
+ "kind": "string",
1744
+ "minLength": 1
1745
+ }
1746
+ },
1747
+ "mode": {
1748
+ "kind": "enum",
1749
+ "values": [
1750
+ "service",
1751
+ "delegated"
1752
+ ]
1753
+ },
1754
+ "methods": {
1755
+ "kind": "array",
1756
+ "items": {
1757
+ "kind": "string"
1758
+ },
1759
+ "default": []
1760
+ },
1761
+ "permissions": {
1762
+ "kind": "array",
1763
+ "items": {
1764
+ "kind": "string"
1765
+ },
1766
+ "default": []
1767
+ },
1768
+ "optional": {
1769
+ "kind": "bool",
1770
+ "default": false
1771
+ },
1772
+ "status": {
1773
+ "kind": "enum",
1774
+ "values": [
1775
+ "connected",
1776
+ "pending",
1777
+ "choice",
1778
+ "unavailable",
1779
+ "stale"
1780
+ ]
1781
+ },
1782
+ "message": {
1783
+ "kind": "string",
1784
+ "minLength": 1
1785
+ },
1786
+ "bindingId": {
1787
+ "kind": "optional",
1788
+ "inner": {
1789
+ "kind": "string",
1790
+ "minLength": 1
1791
+ }
1792
+ },
1793
+ "targetServiceId": {
1794
+ "kind": "optional",
1795
+ "inner": {
1796
+ "kind": "string",
1797
+ "minLength": 1
1798
+ }
1799
+ },
1800
+ "targetViewId": {
1801
+ "kind": "optional",
1802
+ "inner": {
1803
+ "kind": "string",
1804
+ "minLength": 1
1805
+ }
1806
+ },
1807
+ "candidates": {
1808
+ "kind": "array",
1809
+ "items": {
1810
+ "kind": "object",
1811
+ "properties": {
1812
+ "targetServiceId": {
1813
+ "kind": "string",
1814
+ "minLength": 1
1815
+ },
1816
+ "targetServiceTitle": {
1817
+ "kind": "string",
1818
+ "minLength": 1
1819
+ },
1820
+ "targetServiceType": {
1821
+ "kind": "string",
1822
+ "minLength": 1
1823
+ },
1824
+ "targetViewId": {
1825
+ "kind": "string",
1826
+ "minLength": 1
1827
+ }
1828
+ },
1829
+ "required": [
1830
+ "targetServiceId",
1831
+ "targetServiceTitle",
1832
+ "targetServiceType",
1833
+ "targetViewId"
1834
+ ],
1835
+ "unknownKeys": "strip"
1836
+ },
1837
+ "default": []
1838
+ }
1839
+ },
1840
+ "required": [
1841
+ "sourceServiceId",
1842
+ "sourceServiceTitle",
1843
+ "sourceServiceType",
1844
+ "requestId",
1845
+ "title",
1846
+ "contractId",
1847
+ "mode",
1848
+ "methods",
1849
+ "permissions",
1850
+ "optional",
1851
+ "status",
1852
+ "message",
1853
+ "candidates"
1854
+ ],
1855
+ "unknownKeys": "strip"
1856
+ },
1857
+ "default": [],
1858
+ "metadata": {
1859
+ "description": "App-scoped service dependency requests and connection status."
1860
+ }
1861
+ },
1683
1862
  "sharedServiceCatalog": {
1684
1863
  "kind": "array",
1685
1864
  "items": {
@@ -1904,6 +2083,7 @@
1904
2083
  "title",
1905
2084
  "services",
1906
2085
  "tenants",
2086
+ "m2mConnections",
1907
2087
  "sharedServiceCatalog",
1908
2088
  "sharedServiceActivations",
1909
2089
  "apps",
@@ -1943,6 +2123,9 @@
1943
2123
  },
1944
2124
  "auth": {
1945
2125
  "required": true,
2126
+ "callers": [
2127
+ "user"
2128
+ ],
1946
2129
  "permissions": [
1947
2130
  {
1948
2131
  "serviceId": "org.betterportal.config-manager",
@@ -1963,6 +2146,7 @@
1963
2146
  "title": "Service Registry",
1964
2147
  "services": [],
1965
2148
  "tenants": [],
2149
+ "m2mConnections": [],
1966
2150
  "sharedServiceCatalog": [],
1967
2151
  "sharedServiceActivations": [],
1968
2152
  "apps": [],
@@ -2228,6 +2412,9 @@
2228
2412
  },
2229
2413
  "auth": {
2230
2414
  "required": true,
2415
+ "callers": [
2416
+ "user"
2417
+ ],
2231
2418
  "permissions": [
2232
2419
  {
2233
2420
  "serviceId": "org.betterportal.config-manager",
@@ -2581,6 +2768,9 @@
2581
2768
  },
2582
2769
  "auth": {
2583
2770
  "required": true,
2771
+ "callers": [
2772
+ "user"
2773
+ ],
2584
2774
  "permissions": [
2585
2775
  {
2586
2776
  "serviceId": "org.betterportal.config-manager",
@@ -1 +1 @@
1
- {"version":3,"file":"adminApi.d.ts","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/adminApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,mBAAmB,EACnB,SAAS,EACV,MAAM,yBAAyB,CAAC;AAYjC,OAAO,KAAK,EAAuE,kBAAkB,EAAE,eAAe,EAA0C,MAAM,yBAAyB,CAAC;AAChM,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAmLzD,iBAAS,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiEpF;AAGD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,GAAG,MAAM,CA2CpG;AAwkBD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,gBAAgB,GACxB,IAAI,CAm1CN"}
1
+ {"version":3,"file":"adminApi.d.ts","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/adminApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,mBAAmB,EACnB,SAAS,EACV,MAAM,yBAAyB,CAAC;AAYjC,OAAO,KAAK,EAAuE,kBAAkB,EAAE,eAAe,EAA0C,MAAM,yBAAyB,CAAC;AAChM,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AA0LzD,iBAAS,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiEpF;AAGD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,GAAG,MAAM,CA2CpG;AAwkBD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,gBAAgB,GACxB,IAAI,CA+4CN"}
@@ -3,6 +3,7 @@ import { AppAuthRoleSchema, eventHeaders, htmlResponse, jsonResponse, resolveEmb
3
3
  import { generateApiKey, hashApiKey } from "./storage/index.js";
4
4
  import { getManifestCache } from "./syncApi.js";
5
5
  import { apiRoutePath, appRoutePatternKey, isApiRoute, pageRoutePath } from "./routeMounts.js";
6
+ import { M2MConnectionError, approveM2MConnections, buildM2MConnectionModel, revokeM2MConnection } from "./m2mConnections.js";
6
7
  const API_BASE = "/.well-known/bp/admin";
7
8
  const CONFIG_TICKET_TTL_SECONDS = 5 * 60;
8
9
  // Parse-only base for relative request URLs. Never emit this origin.
@@ -1630,6 +1631,77 @@ export function registerAdminApiRoutes(app, store, cpState) {
1630
1631
  return htmxReload(`/auth?appId=${encodeURIComponent(appId)}`);
1631
1632
  return jsonResponse({ ok: true });
1632
1633
  });
1634
+ // Service connections (per app)
1635
+ app.get(`${API_BASE}/apps/:appId/m2m/connections`, async (event) => {
1636
+ const appId = getParam(event, "appId");
1637
+ if (!appId)
1638
+ return jsonResponse({ error: "appId required" }, 400);
1639
+ const config = await store.loadConfig();
1640
+ if (!config.apps.some((candidate) => candidate.id === appId))
1641
+ return jsonResponse({ error: "App not found" }, 404);
1642
+ return jsonResponse(buildM2MConnectionModel(config, appId));
1643
+ });
1644
+ app.post(`${API_BASE}/apps/:appId/m2m/connections`, async (event) => {
1645
+ const appId = getParam(event, "appId");
1646
+ if (!appId)
1647
+ return jsonResponse({ error: "appId required" }, 400);
1648
+ const body = await readFormOrJsonBody(event);
1649
+ let rawSelections = body.connections;
1650
+ if (typeof rawSelections === "string") {
1651
+ try {
1652
+ rawSelections = JSON.parse(rawSelections);
1653
+ }
1654
+ catch {
1655
+ rawSelections = undefined;
1656
+ }
1657
+ }
1658
+ const inputs = Array.isArray(rawSelections) ? rawSelections : [body];
1659
+ const selections = inputs.flatMap((input) => {
1660
+ if (!input || typeof input !== "object")
1661
+ return [];
1662
+ const value = input;
1663
+ return typeof value.sourceServiceId === "string" && typeof value.requestId === "string"
1664
+ ? [{
1665
+ sourceServiceId: value.sourceServiceId,
1666
+ requestId: value.requestId,
1667
+ ...(typeof value.targetServiceId === "string" && value.targetServiceId ? { targetServiceId: value.targetServiceId } : {}),
1668
+ ...(typeof value.targetViewId === "string" && value.targetViewId ? { targetViewId: value.targetViewId } : {})
1669
+ }]
1670
+ : [];
1671
+ });
1672
+ const config = await store.loadConfig();
1673
+ const appDef = config.apps.find((candidate) => candidate.id === appId);
1674
+ if (!appDef)
1675
+ return jsonResponse({ error: "App not found" }, 404);
1676
+ try {
1677
+ const result = approveM2MConnections(config, appId, selections);
1678
+ if (result.created.length > 0)
1679
+ await store.saveConfig(config);
1680
+ if (wantsHtmx(event))
1681
+ return htmxReload(`/services?tenantId=${encodeURIComponent(appDef.tenantId)}&appId=${encodeURIComponent(appId)}`);
1682
+ return jsonResponse(result, result.created.length > 0 ? 201 : 200);
1683
+ }
1684
+ catch (error) {
1685
+ const status = error instanceof M2MConnectionError ? error.status : 500;
1686
+ const message = error instanceof Error ? error.message : "Unable to approve service connection";
1687
+ return wantsHtmx(event) ? htmxError(message, status) : jsonResponse({ error: message }, status);
1688
+ }
1689
+ });
1690
+ app.delete(`${API_BASE}/apps/:appId/m2m/connections/:bindingId`, async (event) => {
1691
+ const appId = getParam(event, "appId");
1692
+ const bindingId = getParam(event, "bindingId");
1693
+ if (!appId || !bindingId)
1694
+ return jsonResponse({ error: "appId and bindingId required" }, 400);
1695
+ const config = await store.loadConfig();
1696
+ const appDef = config.apps.find((candidate) => candidate.id === appId);
1697
+ if (!appDef || !revokeM2MConnection(config, appId, bindingId)) {
1698
+ return wantsHtmx(event) ? htmxError("Service connection not found", 404) : jsonResponse({ error: "Service connection not found" }, 404);
1699
+ }
1700
+ await store.saveConfig(config);
1701
+ if (wantsHtmx(event))
1702
+ return htmxReload(`/services?tenantId=${encodeURIComponent(appDef.tenantId)}&appId=${encodeURIComponent(appId)}`);
1703
+ return jsonResponse({ ok: true });
1704
+ });
1633
1705
  // Routes (per app)
1634
1706
  app.get(`${API_BASE}/apps/:appId/routes`, async (event) => {
1635
1707
  const appId = getParam(event, "appId");