@burdenoff/microfe-planmagnet 2026.1001.6 → 2026.1001.7

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 (81) hide show
  1. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  2. package/dist/planmagnet/PlanMagnetRoutes.js +10 -6
  3. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  4. package/dist/planmagnet/automation/automationRuleTypes.d.ts +31 -19
  5. package/dist/planmagnet/automation/automationRuleTypes.d.ts.map +1 -1
  6. package/dist/planmagnet/automation/automationRuleTypes.js +4 -8
  7. package/dist/planmagnet/automation/automationRuleTypes.js.map +1 -1
  8. package/dist/planmagnet/controls/FeatureControls.d.ts +18 -1
  9. package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -1
  10. package/dist/planmagnet/controls/FeatureControls.js +259 -202
  11. package/dist/planmagnet/controls/FeatureControls.js.map +1 -1
  12. package/dist/planmagnet/controls/FeedbackControls.d.ts +70 -0
  13. package/dist/planmagnet/controls/FeedbackControls.d.ts.map +1 -0
  14. package/dist/planmagnet/controls/FeedbackControls.js +153 -0
  15. package/dist/planmagnet/controls/FeedbackControls.js.map +1 -0
  16. package/dist/planmagnet/controls/SyncControls.d.ts.map +1 -1
  17. package/dist/planmagnet/controls/SyncControls.js +1 -0
  18. package/dist/planmagnet/controls/SyncControls.js.map +1 -1
  19. package/dist/planmagnet/controls/WebhookSubscriptionControls.d.ts +47 -0
  20. package/dist/planmagnet/controls/WebhookSubscriptionControls.d.ts.map +1 -0
  21. package/dist/planmagnet/controls/WebhookSubscriptionControls.js +542 -0
  22. package/dist/planmagnet/controls/WebhookSubscriptionControls.js.map +1 -0
  23. package/dist/planmagnet/dashboards/DashboardUI.js +7 -7
  24. package/dist/planmagnet/dashboards/cards/RiskSeverityCard.js +4 -4
  25. package/dist/planmagnet/forecast/DeliveryForecastCard.js +8 -8
  26. package/dist/planmagnet/forecast/ProjectOutlookCard.js +10 -10
  27. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js +9 -9
  28. package/dist/planmagnet/forecast/ResourceForecastCard.js +6 -6
  29. package/dist/planmagnet/integrations/syncTypes.d.ts +2 -1
  30. package/dist/planmagnet/integrations/syncTypes.d.ts.map +1 -1
  31. package/dist/planmagnet/integrations/syncTypes.js +19 -9
  32. package/dist/planmagnet/integrations/syncTypes.js.map +1 -1
  33. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +8 -8
  34. package/dist/planmagnet/pages/DashboardDashboardPagePage.js +23 -23
  35. package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
  36. package/dist/planmagnet/pages/DocsDocDetailPagePage.js +340 -248
  37. package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
  38. package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.d.ts.map +1 -1
  39. package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.js +172 -167
  40. package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.js.map +1 -1
  41. package/dist/planmagnet/pages/IntegrationsSyncsPagePage.d.ts.map +1 -1
  42. package/dist/planmagnet/pages/IntegrationsSyncsPagePage.js +92 -83
  43. package/dist/planmagnet/pages/IntegrationsSyncsPagePage.js.map +1 -1
  44. package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.d.ts +2 -0
  45. package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.d.ts.map +1 -0
  46. package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.js +175 -0
  47. package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.js.map +1 -0
  48. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
  49. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +151 -126
  50. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
  51. package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
  52. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +136 -129
  53. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
  54. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
  55. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +149 -119
  56. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
  57. package/dist/planmagnet/pages/ProductsProductsPagePage.js +13 -13
  58. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js +9 -9
  59. package/dist/planmagnet/pages/ProjectsBudgetsPagePage.js +8 -8
  60. package/dist/planmagnet/pages/ProjectsProjectsPagePage.js +12 -12
  61. package/dist/planmagnet/pages/ReportsReportsPagePage.js +23 -23
  62. package/dist/planmagnet/pages/TasksMyDashboardPagePage.js +18 -18
  63. package/dist/planmagnet/pages/TasksMyWorkPagePage.js +10 -10
  64. package/dist/planmagnet/pages/TasksTimeEntriesPagePage.js +5 -5
  65. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.js +8 -8
  66. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js +6 -6
  67. package/dist/planmagnet/pages/analytics/MetricsCard.js +6 -6
  68. package/dist/planmagnet/pages/analytics/QualityMetricsCard.js +6 -6
  69. package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js +8 -8
  70. package/dist/planmagnet/pages/analytics/StatusFlowCard.js +7 -7
  71. package/dist/planmagnet/pages/analytics/ThroughputCard.js +7 -7
  72. package/dist/planmagnet/pages/analytics/WorkBreakdownCard.js +7 -7
  73. package/dist/planmagnet/people/People.d.ts +14 -0
  74. package/dist/planmagnet/people/People.d.ts.map +1 -1
  75. package/dist/planmagnet/people/People.js +36 -22
  76. package/dist/planmagnet/people/People.js.map +1 -1
  77. package/dist/planmagnet/webhooks/webhookTypes.d.ts +54 -0
  78. package/dist/planmagnet/webhooks/webhookTypes.d.ts.map +1 -0
  79. package/dist/planmagnet/webhooks/webhookTypes.js +17 -0
  80. package/dist/planmagnet/webhooks/webhookTypes.js.map +1 -0
  81. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"People.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/people/People.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EAElB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA8Cf,wBAAgB,cAAc,CAAC,EAC7B,WAAW,EACX,QAAQ,GACT,EAAE;IACD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAkBA;AAED,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CAsBnF;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,eAAe,2CAQ5D;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,iBAAiB,2CAahE"}
1
+ {"version":3,"file":"People.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/people/People.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EAElB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA4Cf;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEzE;AAED;8GAC8G;AAC9G,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAMnE;AAID,wBAAgB,cAAc,CAAC,EAC7B,WAAW,EACX,QAAQ,GACT,EAAE;IACD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAkBA;AAED,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CA2BnF;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,eAAe,2CAW5D;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,iBAAiB,2CAahE"}
@@ -1,48 +1,62 @@
1
1
  import { createContext as e, useCallback as t, useContext as n, useEffect as r, useMemo as i, useState as a } from "react";
2
2
  import { jsx as o } from "react/jsx-runtime";
3
3
  import { buildActorFallback as s, useActorProfiles as c } from "@burdenoff/fe-libs/shared";
4
+ import { Badge as l } from "@burdenoff/fe-libs/ui";
4
5
  //#region src/planmagnet/people/People.tsx
5
- var l = {
6
+ var u = {
6
7
  "automation:engine": "Automation",
7
8
  "automation:scheduler": "Automation"
8
- }, u = e(null);
9
- function d({ workspaceId: e, children: n }) {
9
+ }, d = "anonymous";
10
+ function f(e) {
11
+ return e === d;
12
+ }
13
+ function p({ className: e }) {
14
+ return /* @__PURE__ */ o(l, {
15
+ variant: "secondary",
16
+ className: e ?? "text-xs",
17
+ "data-testid": "anonymous-badge",
18
+ children: "Anonymous"
19
+ });
20
+ }
21
+ var m = e(null);
22
+ function h({ workspaceId: e, children: n }) {
10
23
  let [r, s] = a([]), l = t((e) => {
11
24
  s((t) => t.includes(e) ? t : [...t, e]);
12
- }, []), d = c(i(() => r.map((e) => ({
25
+ }, []), u = c(i(() => r.map((e) => ({
13
26
  actorId: e,
14
27
  actorType: "user"
15
- })), [r]), { workspaceId: e }), f = i(() => ({
28
+ })), [r]), { workspaceId: e }), d = i(() => ({
16
29
  request: l,
17
- profiles: d
18
- }), [l, d]);
19
- return /* @__PURE__ */ o(u.Provider, {
20
- value: f,
30
+ profiles: u
31
+ }), [l, u]);
32
+ return /* @__PURE__ */ o(m.Provider, {
33
+ value: d,
21
34
  children: n
22
35
  });
23
36
  }
24
- function f(e) {
25
- let t = n(u), i = t?.request, a = e ? l[e] : void 0;
37
+ function g(e) {
38
+ let t = n(m), i = t?.request, a = e ? u[e] : void 0, o = f(e);
26
39
  return r(() => {
27
- e && i && !a && i(e);
40
+ e && i && !a && !o && i(e);
28
41
  }, [
29
42
  e,
30
43
  i,
31
- a
44
+ a,
45
+ o
32
46
  ]), e ? a ? {
33
47
  actorId: e,
34
48
  actorType: "service",
35
49
  displayName: a,
36
50
  secondaryLabel: "Automation",
37
51
  resolved: !0
38
- } : t?.profiles[e] ?? s({
52
+ } : o ? null : t?.profiles[e] ?? s({
39
53
  actorId: e,
40
54
  actorType: "user"
41
55
  }) : null;
42
56
  }
43
- function p({ id: e, className: t }) {
44
- let n = f(e);
45
- return n ? /* @__PURE__ */ o("span", {
57
+ function _({ id: e, className: t }) {
58
+ let n = g(e);
59
+ return f(e) ? /* @__PURE__ */ o(p, { className: t }) : n ? /* @__PURE__ */ o("span", {
46
60
  className: t,
47
61
  title: n.email ?? void 0,
48
62
  children: n.displayName
@@ -51,19 +65,19 @@ function p({ id: e, className: t }) {
51
65
  children: "—"
52
66
  });
53
67
  }
54
- function m(e) {
68
+ function v(e) {
55
69
  return e.trim().split(/\s+/).filter(Boolean).slice(0, 2).map((e) => e[0].toUpperCase()).join("");
56
70
  }
57
- function h({ id: e, className: t }) {
58
- let n = f(e), r = n ? n.email ? `${n.displayName} (${n.email})` : n.displayName : void 0;
71
+ function y({ id: e, className: t }) {
72
+ let n = g(e), r = n ? n.email ? `${n.displayName} (${n.email})` : n.displayName : void 0;
59
73
  return /* @__PURE__ */ o("span", {
60
74
  className: t,
61
75
  title: r,
62
76
  "aria-label": r,
63
- children: (n?.resolved ? m(n.displayName) : "") || "?"
77
+ children: (n?.resolved ? v(n.displayName) : "") || "?"
64
78
  });
65
79
  }
66
80
  //#endregion
67
- export { d as PeopleProvider, h as PersonAvatar, p as PersonName, m as initialsOf, f as usePersonProfile };
81
+ export { h as PeopleProvider, y as PersonAvatar, _ as PersonName, v as initialsOf, g as usePersonProfile };
68
82
 
69
83
  //# sourceMappingURL=People.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"People.js","names":[],"sources":["../../../src/planmagnet/people/People.tsx"],"sourcesContent":["import {\n buildActorFallback,\n useActorProfiles,\n type ActorInput,\n type ActorProfile,\n type ActorProfileMap,\n} from '@burdenoff/fe-libs/shared';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\n/**\n * Show people by name, not by UUID.\n *\n * Until 2026-09-24, 21 places in this MFE rendered a raw user id where a\n * person belonged — project owners, roadmap owners, assignees, the team lead.\n * fe-libs already resolves ids to workspace-member identities\n * (`useActorProfiles`, with a 5-minute cache), but it batches per CALL and\n * does not dedupe across calls, so calling it from every row would fire a\n * burst of lookups on the first render of each list.\n *\n * So there is exactly one call, here. Every `<PersonName id>` on screen\n * registers its id with the provider; ids registered during the same render\n * land in one state update, and the provider resolves them together. A\n * growing list costs one request for the NEW ids only — already-resolved ids\n * come from the fe-libs cache.\n *\n * An id that cannot be resolved (not a member of this workspace, lookup\n * failed) renders fe-libs' short fallback, \"User 1a2b3c\", rather than the full\n * UUID: still identifiable, never a wall of hex.\n */\n\ninterface PeopleContextValue {\n request: (id: string) => void;\n profiles: ActorProfileMap;\n}\n\n/**\n * The automation engine's own actor identities (BOFF-8047 follow-up) — never a real workspace member's id, so\n * they are mapped explicitly rather than sent through `useActorProfiles` (which would only ever resolve them to\n * its generic \"not a member\" fallback). Sourced directly from wspace-planmagnet-svc, not guessed:\n * - `automation-engine.ts`'s `AUTOMATION_COMMENT_AUTHOR_ID` (`'automation:engine'`) — the fixed author of every\n * comment a POST_COMMENT action posts, regardless of which trigger or actor caused the run.\n * - `automation-scheduler.ts`'s `AUTOMATION_SCHEDULER_ACTOR_ID` (`'automation:scheduler'`) — the actor behind a\n * SCHEDULE-triggered run (threaded through as `updatedBy` on that run's other actions).\n * No real actor id can ever collide with the `automation:` prefix (workspace-member ids are uuids) — see that\n * constant's own doc comment in the engine.\n */\nconst AUTOMATION_ACTOR_NAMES: Record<string, string> = {\n 'automation:engine': 'Automation',\n 'automation:scheduler': 'Automation',\n};\n\nconst PeopleContext = createContext<PeopleContextValue | null>(null);\n\nexport function PeopleProvider({\n workspaceId,\n children,\n}: {\n workspaceId?: string;\n children: ReactNode;\n}) {\n const [ids, setIds] = useState<readonly string[]>([]);\n\n const request = useCallback((id: string) => {\n setIds((previous) => (previous.includes(id) ? previous : [...previous, id]));\n }, []);\n\n const actors = useMemo<ActorInput[]>(\n () => ids.map((actorId) => ({ actorId, actorType: 'user' })),\n [ids]\n );\n\n // No apiGatewayUrl on purpose: this MFE is handed the WORKSPACE gateway, and\n // the hook resolves the right gateways from the hostname itself.\n const profiles = useActorProfiles(actors, { workspaceId });\n\n const value = useMemo(() => ({ request, profiles }), [request, profiles]);\n return <PeopleContext.Provider value={value}>{children}</PeopleContext.Provider>;\n}\n\nexport interface PersonNameProps {\n /** A user id. Empty or missing renders an em dash. */\n id: string | null | undefined;\n className?: string;\n}\n\n/**\n * Inline text on purpose. fe-libs' `ActorIdentity` is a block (avatar plus two\n * stacked paragraphs); every place this replaces is an inline label —\n * \"Owner: …\", a table cell, a <span> inside a <p> — where a block would break\n * the layout and nest a <div> inside a <p>. The email, when known, is the\n * hover title, so two people with the same name stay distinguishable.\n */\n/**\n * Register an id with the provider and return its profile: the resolved identity, or fe-libs' short fallback\n * (\"User 1a2b3c\", `resolved: false`) until and unless it resolves. `null` for an empty id.\n */\nexport function usePersonProfile(id: string | null | undefined): ActorProfile | null {\n const context = useContext(PeopleContext);\n const request = context?.request;\n const automationName = id ? AUTOMATION_ACTOR_NAMES[id] : undefined;\n\n useEffect(() => {\n // An automation identity is never a real workspace member — registering it with the provider would only\n // ever come back as the generic \"not a member\" fallback, and would cost a wasted slot in every batch lookup.\n if (id && request && !automationName) request(id);\n }, [id, request, automationName]);\n\n if (!id) return null;\n if (automationName) {\n return {\n actorId: id,\n actorType: 'service',\n displayName: automationName,\n secondaryLabel: 'Automation',\n resolved: true,\n };\n }\n return context?.profiles[id] ?? buildActorFallback({ actorId: id, actorType: 'user' });\n}\n\nexport function PersonName({ id, className }: PersonNameProps) {\n const profile = usePersonProfile(id);\n if (!profile) return <span className={className ?? 'text-muted-foreground'}>—</span>;\n return (\n <span className={className} title={profile.email ?? undefined}>\n {profile.displayName}\n </span>\n );\n}\n\n/** Up to two initials from a display name (\"Ada Lovelace\" → \"AL\", \"ada\" → \"A\"). */\nexport function initialsOf(name: string): string {\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => word[0]!.toUpperCase())\n .join('');\n}\n\nexport interface PersonAvatarProps {\n id: string | null | undefined;\n className?: string;\n}\n\n/**\n * An initials bubble for a user id. Initials come from the RESOLVED name; until the id resolves (or when it never\n * does) the bubble shows a neutral \"?\" rather than letters cut from the UUID, which matched nobody (BOFF-7977,\n * BOFF-8000). The tooltip is the name, plus the email when known.\n */\nexport function PersonAvatar({ id, className }: PersonAvatarProps) {\n const profile = usePersonProfile(id);\n const label = profile\n ? profile.email\n ? `${profile.displayName} (${profile.email})`\n : profile.displayName\n : undefined;\n const initials = profile?.resolved ? initialsOf(profile.displayName) : '';\n return (\n <span className={className} title={label} aria-label={label}>\n {initials || '?'}\n </span>\n );\n}\n"],"mappings":";;;;AAsDA,IAAM,IAAiD;CACrD,qBAAqB;CACrB,wBAAwB;CACzB,EAEK,IAAgB,EAAyC,KAAK;AAEpE,SAAgB,EAAe,EAC7B,gBACA,eAIC;CACD,IAAM,CAAC,GAAK,KAAU,EAA4B,EAAE,CAAC,EAE/C,IAAU,GAAa,MAAe;AAC1C,KAAQ,MAAc,EAAS,SAAS,EAAG,GAAG,IAAW,CAAC,GAAG,GAAU,EAAG,CAAE;IAC3E,EAAE,CAAC,EASA,IAAW,EAPF,QACP,EAAI,KAAK,OAAa;EAAE;EAAS,WAAW;EAAQ,EAAE,EAC5D,CAAC,EAAI,CACN,EAIyC,EAAE,gBAAa,CAAC,EAEpD,IAAQ,SAAe;EAAE;EAAS;EAAU,GAAG,CAAC,GAAS,EAAS,CAAC;AACzE,QAAO,kBAAC,EAAc,UAAf;EAA+B;EAAQ;EAAkC,CAAA;;AAoBlF,SAAgB,EAAiB,GAAoD;CACnF,IAAM,IAAU,EAAW,EAAc,EACnC,IAAU,GAAS,SACnB,IAAiB,IAAK,EAAuB,KAAM,KAAA;AAkBzD,QAhBA,QAAgB;AAGd,EAAI,KAAM,KAAW,CAAC,KAAgB,EAAQ,EAAG;IAChD;EAAC;EAAI;EAAS;EAAe,CAAC,EAE5B,IACD,IACK;EACL,SAAS;EACT,WAAW;EACX,aAAa;EACb,gBAAgB;EAChB,UAAU;EACX,GAEI,GAAS,SAAS,MAAO,EAAmB;EAAE,SAAS;EAAI,WAAW;EAAQ,CAAC,GAVtE;;AAalB,SAAgB,EAAW,EAAE,OAAI,gBAA8B;CAC7D,IAAM,IAAU,EAAiB,EAAG;AAEpC,QADK,IAEH,kBAAC,QAAD;EAAiB;EAAW,OAAO,EAAQ,SAAS,KAAA;YACjD,EAAQ;EACJ,CAAA,GAJY,kBAAC,QAAD;EAAM,WAAW,KAAa;YAAyB;EAAQ,CAAA;;AAStF,SAAgB,EAAW,GAAsB;AAC/C,QAAO,EACJ,MAAM,CACN,MAAM,MAAM,CACZ,OAAO,QAAQ,CACf,MAAM,GAAG,EAAE,CACX,KAAK,MAAS,EAAK,GAAI,aAAa,CAAC,CACrC,KAAK,GAAG;;AAab,SAAgB,EAAa,EAAE,OAAI,gBAAgC;CACjE,IAAM,IAAU,EAAiB,EAAG,EAC9B,IAAQ,IACV,EAAQ,QACN,GAAG,EAAQ,YAAY,IAAI,EAAQ,MAAM,KACzC,EAAQ,cACV,KAAA;AAEJ,QACE,kBAAC,QAAD;EAAiB;EAAW,OAAO;EAAO,cAAY;aAFvC,GAAS,WAAW,EAAW,EAAQ,YAAY,GAAG,OAGtD;EACR,CAAA"}
1
+ {"version":3,"file":"People.js","names":[],"sources":["../../../src/planmagnet/people/People.tsx"],"sourcesContent":["import {\n buildActorFallback,\n useActorProfiles,\n type ActorInput,\n type ActorProfile,\n type ActorProfileMap,\n} from '@burdenoff/fe-libs/shared';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\n/**\n * Show people by name, not by UUID.\n *\n * Until 2026-09-24, 21 places in this MFE rendered a raw user id where a\n * person belonged — project owners, roadmap owners, assignees, the team lead.\n * fe-libs already resolves ids to workspace-member identities\n * (`useActorProfiles`, with a 5-minute cache), but it batches per CALL and\n * does not dedupe across calls, so calling it from every row would fire a\n * burst of lookups on the first render of each list.\n *\n * So there is exactly one call, here. Every `<PersonName id>` on screen\n * registers its id with the provider; ids registered during the same render\n * land in one state update, and the provider resolves them together. A\n * growing list costs one request for the NEW ids only — already-resolved ids\n * come from the fe-libs cache.\n *\n * An id that cannot be resolved (not a member of this workspace, lookup\n * failed) renders fe-libs' short fallback, \"User 1a2b3c\", rather than the full\n * UUID: still identifiable, never a wall of hex.\n */\n\ninterface PeopleContextValue {\n request: (id: string) => void;\n profiles: ActorProfileMap;\n}\n\n/**\n * The automation engine's own actor identities (BOFF-8047 follow-up) — never a real workspace member's id, so\n * they are mapped explicitly rather than sent through `useActorProfiles` (which would only ever resolve them to\n * its generic \"not a member\" fallback). Sourced directly from wspace-planmagnet-svc, not guessed:\n * - `automation-engine.ts`'s `AUTOMATION_COMMENT_AUTHOR_ID` (`'automation:engine'`) — the fixed author of every\n * comment a POST_COMMENT action posts, regardless of which trigger or actor caused the run.\n * - `automation-scheduler.ts`'s `AUTOMATION_SCHEDULER_ACTOR_ID` (`'automation:scheduler'`) — the actor behind a\n * SCHEDULE-triggered run (threaded through as `updatedBy` on that run's other actions).\n * No real actor id can ever collide with the `automation:` prefix (workspace-member ids are uuids) — see that\n * constant's own doc comment in the engine.\n */\nconst AUTOMATION_ACTOR_NAMES: Record<string, string> = {\n 'automation:engine': 'Automation',\n 'automation:scheduler': 'Automation',\n};\n\n/**\n * CWF-15's redaction sentinel: `FeatureRequest.submittedBy`/`createdBy`/`updatedBy` and `FeatureVote.voterId`\n * read back this literal string, instead of the real actor id, for a non-moderator caller when the record (or,\n * for a vote, that vote) is flagged `isAnonymous`. Never a real actor id — those are workspace-member uuids —\n * so, like the `automation:` actor ids above, it must never be sent through `useActorProfiles`: that would only\n * ever resolve to the generic \"not a member\" fallback, and would burn a wasted slot in every batch lookup.\n */\nexport const ANONYMOUS_ACTOR_ID = 'anonymous';\n\nexport function isAnonymousActorId(id: string | null | undefined): boolean {\n return id === ANONYMOUS_ACTOR_ID;\n}\n\n/** The literal \"Anonymous\" badge CWF-15 asks for everywhere a redacted actor id would otherwise show — see\n * `PersonName` below, which is the one place `submittedBy`/`createdBy`/`updatedBy`/`voterId` ever render. */\nexport function AnonymousBadge({ className }: { className?: string }) {\n return (\n <Badge variant=\"secondary\" className={className ?? 'text-xs'} data-testid=\"anonymous-badge\">\n Anonymous\n </Badge>\n );\n}\n\nconst PeopleContext = createContext<PeopleContextValue | null>(null);\n\nexport function PeopleProvider({\n workspaceId,\n children,\n}: {\n workspaceId?: string;\n children: ReactNode;\n}) {\n const [ids, setIds] = useState<readonly string[]>([]);\n\n const request = useCallback((id: string) => {\n setIds((previous) => (previous.includes(id) ? previous : [...previous, id]));\n }, []);\n\n const actors = useMemo<ActorInput[]>(\n () => ids.map((actorId) => ({ actorId, actorType: 'user' })),\n [ids]\n );\n\n // No apiGatewayUrl on purpose: this MFE is handed the WORKSPACE gateway, and\n // the hook resolves the right gateways from the hostname itself.\n const profiles = useActorProfiles(actors, { workspaceId });\n\n const value = useMemo(() => ({ request, profiles }), [request, profiles]);\n return <PeopleContext.Provider value={value}>{children}</PeopleContext.Provider>;\n}\n\nexport interface PersonNameProps {\n /** A user id. Empty or missing renders an em dash. */\n id: string | null | undefined;\n className?: string;\n}\n\n/**\n * Inline text on purpose. fe-libs' `ActorIdentity` is a block (avatar plus two\n * stacked paragraphs); every place this replaces is an inline label —\n * \"Owner: …\", a table cell, a <span> inside a <p> — where a block would break\n * the layout and nest a <div> inside a <p>. The email, when known, is the\n * hover title, so two people with the same name stay distinguishable.\n */\n/**\n * Register an id with the provider and return its profile: the resolved identity, or fe-libs' short fallback\n * (\"User 1a2b3c\", `resolved: false`) until and unless it resolves. `null` for an empty id.\n */\nexport function usePersonProfile(id: string | null | undefined): ActorProfile | null {\n const context = useContext(PeopleContext);\n const request = context?.request;\n const automationName = id ? AUTOMATION_ACTOR_NAMES[id] : undefined;\n const anonymous = isAnonymousActorId(id);\n\n useEffect(() => {\n // An automation identity is never a real workspace member, and the CWF-15 \"anonymous\" sentinel is never an\n // actor id at all — registering either with the provider would only ever come back as the generic \"not a\n // member\" fallback, and would cost a wasted slot in every batch lookup.\n if (id && request && !automationName && !anonymous) request(id);\n }, [id, request, automationName, anonymous]);\n\n if (!id) return null;\n if (automationName) {\n return {\n actorId: id,\n actorType: 'service',\n displayName: automationName,\n secondaryLabel: 'Automation',\n resolved: true,\n };\n }\n // CWF-15: \"anonymous\" is a redaction sentinel, never a real actor id — PersonName/PersonAvatar below render it\n // specially rather than resolving it (which would only ever land on the generic \"not a member\" fallback).\n if (anonymous) return null;\n return context?.profiles[id] ?? buildActorFallback({ actorId: id, actorType: 'user' });\n}\n\nexport function PersonName({ id, className }: PersonNameProps) {\n const profile = usePersonProfile(id);\n // CWF-15: the literal \"anonymous\" sentinel renders as the Anonymous badge everywhere a person's name would\n // otherwise show — never resolved as, or displayed like, a real user id.\n if (isAnonymousActorId(id)) return <AnonymousBadge className={className} />;\n if (!profile) return <span className={className ?? 'text-muted-foreground'}>—</span>;\n return (\n <span className={className} title={profile.email ?? undefined}>\n {profile.displayName}\n </span>\n );\n}\n\n/** Up to two initials from a display name (\"Ada Lovelace\" → \"AL\", \"ada\" → \"A\"). */\nexport function initialsOf(name: string): string {\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => word[0]!.toUpperCase())\n .join('');\n}\n\nexport interface PersonAvatarProps {\n id: string | null | undefined;\n className?: string;\n}\n\n/**\n * An initials bubble for a user id. Initials come from the RESOLVED name; until the id resolves (or when it never\n * does) the bubble shows a neutral \"?\" rather than letters cut from the UUID, which matched nobody (BOFF-7977,\n * BOFF-8000). The tooltip is the name, plus the email when known.\n */\nexport function PersonAvatar({ id, className }: PersonAvatarProps) {\n const profile = usePersonProfile(id);\n const label = profile\n ? profile.email\n ? `${profile.displayName} (${profile.email})`\n : profile.displayName\n : undefined;\n const initials = profile?.resolved ? initialsOf(profile.displayName) : '';\n return (\n <span className={className} title={label} aria-label={label}>\n {initials || '?'}\n </span>\n );\n}\n"],"mappings":";;;;;AAuDA,IAAM,IAAiD;CACrD,qBAAqB;CACrB,wBAAwB;CACzB,EASY,IAAqB;AAElC,SAAgB,EAAmB,GAAwC;AACzE,QAAO,MAAO;;AAKhB,SAAgB,EAAe,EAAE,gBAAqC;AACpE,QACE,kBAAC,GAAD;EAAO,SAAQ;EAAY,WAAW,KAAa;EAAW,eAAY;YAAkB;EAEpF,CAAA;;AAIZ,IAAM,IAAgB,EAAyC,KAAK;AAEpE,SAAgB,EAAe,EAC7B,gBACA,eAIC;CACD,IAAM,CAAC,GAAK,KAAU,EAA4B,EAAE,CAAC,EAE/C,IAAU,GAAa,MAAe;AAC1C,KAAQ,MAAc,EAAS,SAAS,EAAG,GAAG,IAAW,CAAC,GAAG,GAAU,EAAG,CAAE;IAC3E,EAAE,CAAC,EASA,IAAW,EAPF,QACP,EAAI,KAAK,OAAa;EAAE;EAAS,WAAW;EAAQ,EAAE,EAC5D,CAAC,EAAI,CACN,EAIyC,EAAE,gBAAa,CAAC,EAEpD,IAAQ,SAAe;EAAE;EAAS;EAAU,GAAG,CAAC,GAAS,EAAS,CAAC;AACzE,QAAO,kBAAC,EAAc,UAAf;EAA+B;EAAQ;EAAkC,CAAA;;AAoBlF,SAAgB,EAAiB,GAAoD;CACnF,IAAM,IAAU,EAAW,EAAc,EACnC,IAAU,GAAS,SACnB,IAAiB,IAAK,EAAuB,KAAM,KAAA,GACnD,IAAY,EAAmB,EAAG;AAsBxC,QApBA,QAAgB;AAId,EAAI,KAAM,KAAW,CAAC,KAAkB,CAAC,KAAW,EAAQ,EAAG;IAC9D;EAAC;EAAI;EAAS;EAAgB;EAAU,CAAC,EAEvC,IACD,IACK;EACL,SAAS;EACT,WAAW;EACX,aAAa;EACb,gBAAgB;EAChB,UAAU;EACX,GAIC,IAAkB,OACf,GAAS,SAAS,MAAO,EAAmB;EAAE,SAAS;EAAI,WAAW;EAAQ,CAAC,GAbtE;;AAgBlB,SAAgB,EAAW,EAAE,OAAI,gBAA8B;CAC7D,IAAM,IAAU,EAAiB,EAAG;AAKpC,QAFI,EAAmB,EAAG,GAAS,kBAAC,GAAD,EAA2B,cAAa,CAAA,GACtE,IAEH,kBAAC,QAAD;EAAiB;EAAW,OAAO,EAAQ,SAAS,KAAA;YACjD,EAAQ;EACJ,CAAA,GAJY,kBAAC,QAAD;EAAM,WAAW,KAAa;YAAyB;EAAQ,CAAA;;AAStF,SAAgB,EAAW,GAAsB;AAC/C,QAAO,EACJ,MAAM,CACN,MAAM,MAAM,CACZ,OAAO,QAAQ,CACf,MAAM,GAAG,EAAE,CACX,KAAK,MAAS,EAAK,GAAI,aAAa,CAAC,CACrC,KAAK,GAAG;;AAab,SAAgB,EAAa,EAAE,OAAI,gBAAgC;CACjE,IAAM,IAAU,EAAiB,EAAG,EAC9B,IAAQ,IACV,EAAQ,QACN,GAAG,EAAQ,YAAY,IAAI,EAAQ,MAAM,KACzC,EAAQ,cACV,KAAA;AAEJ,QACE,kBAAC,QAAD;EAAiB;EAAW,OAAO;EAAO,cAAY;aAFvC,GAAS,WAAW,EAAW,EAAQ,YAAY,GAAG,OAGtD;EACR,CAAA"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Outbound webhook subscriptions (AUT-33) — shared shapes and constants. GraphQL Hive doc comments
3
+ * (`graphql/wspace.graphql`, `PlanmagnetWebhookSubscription*`) are the source of truth for all of this, not
4
+ * guesswork:
5
+ *
6
+ * - `events` is a list of `PlanmagnetAutomationTriggerType` values (the SAME enum the automation rule builder's
7
+ * trigger select uses — see `automation/automationRuleTypes.ts`). Every value delivers a real webhook today
8
+ * EXCEPT `WEBHOOK` itself, which is accepted and saveable (so a subscription can be prepared ahead of time)
9
+ * but not yet live — gated on the public-gateway route for inbound GitHub deliveries (Platform ticket
10
+ * BOFF-8238). `SCHEDULE` and `MILESTONE_DUE` deliver from `automation-scheduler.ts`'s periodic job rather than
11
+ * a synchronous write, same as they do for automation rules.
12
+ * - The signing secret (`PlanmagnetWebhookSubscriptionWithSecret.secret`) is returned in PLAINTEXT exactly once,
13
+ * on create and again on rotate — it cannot be read back from the API afterwards. See
14
+ * `controls/WebhookSubscriptionControls.tsx` for the "shown once, every close path resets it" discipline this
15
+ * demands (the same one `reports/ShareDialog.tsx` was fixed to use, #45).
16
+ * - `consecutiveFailures` resets to 0 on the next successful delivery, or whenever an update moves `status` back
17
+ * to ACTIVE; reaching the engine's own failure threshold moves `status` to DISABLED automatically.
18
+ */
19
+ export declare const WEBHOOK_SUBSCRIPTION_STATUSES: readonly ["ACTIVE", "PAUSED", "DISABLED"];
20
+ export type WebhookSubscriptionStatus = (typeof WEBHOOK_SUBSCRIPTION_STATUSES)[number];
21
+ export declare const WEBHOOK_DELIVERY_STATUSES: readonly ["SUCCESS", "FAILED"];
22
+ export type WebhookDeliveryStatus = (typeof WEBHOOK_DELIVERY_STATUSES)[number];
23
+ export interface WebhookSubscriptionRow {
24
+ id: string;
25
+ url: string;
26
+ events: string[];
27
+ status: WebhookSubscriptionStatus;
28
+ consecutiveFailures: number;
29
+ lastDeliveryAt: string | null;
30
+ lastDeliveryStatus: WebhookDeliveryStatus | null;
31
+ createdAt: string;
32
+ createdBy: string;
33
+ updatedAt: string;
34
+ updatedBy: string | null;
35
+ disabledAt: string | null;
36
+ }
37
+ export interface WebhookSubscriptionDeliveryRow {
38
+ id: string;
39
+ event: string;
40
+ status: WebhookDeliveryStatus;
41
+ /** Null for a connection-level failure (DNS/SSRF refusal, timeout, connection reset) that never got far
42
+ * enough to receive one. */
43
+ responseStatus: number | null;
44
+ attempts: number;
45
+ error: string | null;
46
+ deliveredAt: string;
47
+ }
48
+ /** `PlanmagnetCreateWebhookSubscriptionInput.url` must be an absolute `https://` URL — the server's own SSRF
49
+ * guard (private/loopback/link-local/metadata ranges) is the real gate and runs again at every delivery; this
50
+ * is only the client-side sanity check that catches an obviously wrong URL before a round trip. */
51
+ export declare function isPlausibleWebhookUrl(value: string): boolean;
52
+ /** The event-select option suffix — `WEBHOOK` is accepted and saveable but not yet live (BOFF-8238). */
53
+ export declare function webhookEventOptionSuffix(trigger: string): string;
54
+ //# sourceMappingURL=webhookTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhookTypes.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/webhooks/webhookTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,6BAA6B,2CAA4C,CAAC;AACvF,MAAM,MAAM,yBAAyB,GAAG,CAAC,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvF,eAAO,MAAM,yBAAyB,gCAAiC,CAAC;AACxE,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,yBAAyB,CAAC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kBAAkB,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,8BAA8B;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,qBAAqB,CAAC;IAC9B;iCAC6B;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;oGAEoG;AACpG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAQ5D;AAED,wGAAwG;AACxG,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhE"}
@@ -0,0 +1,17 @@
1
+ //#region src/planmagnet/webhooks/webhookTypes.ts
2
+ function e(e) {
3
+ if (!/^https:\/\//i.test(e.trim())) return !1;
4
+ try {
5
+ let t = new URL(e.trim());
6
+ return t.protocol === "https:" && t.hostname.length > 0;
7
+ } catch {
8
+ return !1;
9
+ }
10
+ }
11
+ function t(e) {
12
+ return e === "WEBHOOK" ? " (not live yet)" : "";
13
+ }
14
+ //#endregion
15
+ export { e as isPlausibleWebhookUrl, t as webhookEventOptionSuffix };
16
+
17
+ //# sourceMappingURL=webhookTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhookTypes.js","names":[],"sources":["../../../src/planmagnet/webhooks/webhookTypes.ts"],"sourcesContent":["/**\n * Outbound webhook subscriptions (AUT-33) — shared shapes and constants. GraphQL Hive doc comments\n * (`graphql/wspace.graphql`, `PlanmagnetWebhookSubscription*`) are the source of truth for all of this, not\n * guesswork:\n *\n * - `events` is a list of `PlanmagnetAutomationTriggerType` values (the SAME enum the automation rule builder's\n * trigger select uses — see `automation/automationRuleTypes.ts`). Every value delivers a real webhook today\n * EXCEPT `WEBHOOK` itself, which is accepted and saveable (so a subscription can be prepared ahead of time)\n * but not yet live — gated on the public-gateway route for inbound GitHub deliveries (Platform ticket\n * BOFF-8238). `SCHEDULE` and `MILESTONE_DUE` deliver from `automation-scheduler.ts`'s periodic job rather than\n * a synchronous write, same as they do for automation rules.\n * - The signing secret (`PlanmagnetWebhookSubscriptionWithSecret.secret`) is returned in PLAINTEXT exactly once,\n * on create and again on rotate — it cannot be read back from the API afterwards. See\n * `controls/WebhookSubscriptionControls.tsx` for the \"shown once, every close path resets it\" discipline this\n * demands (the same one `reports/ShareDialog.tsx` was fixed to use, #45).\n * - `consecutiveFailures` resets to 0 on the next successful delivery, or whenever an update moves `status` back\n * to ACTIVE; reaching the engine's own failure threshold moves `status` to DISABLED automatically.\n */\n\nexport const WEBHOOK_SUBSCRIPTION_STATUSES = ['ACTIVE', 'PAUSED', 'DISABLED'] as const;\nexport type WebhookSubscriptionStatus = (typeof WEBHOOK_SUBSCRIPTION_STATUSES)[number];\n\nexport const WEBHOOK_DELIVERY_STATUSES = ['SUCCESS', 'FAILED'] as const;\nexport type WebhookDeliveryStatus = (typeof WEBHOOK_DELIVERY_STATUSES)[number];\n\nexport interface WebhookSubscriptionRow {\n id: string;\n url: string;\n events: string[];\n status: WebhookSubscriptionStatus;\n consecutiveFailures: number;\n lastDeliveryAt: string | null;\n lastDeliveryStatus: WebhookDeliveryStatus | null;\n createdAt: string;\n createdBy: string;\n updatedAt: string;\n updatedBy: string | null;\n disabledAt: string | null;\n}\n\nexport interface WebhookSubscriptionDeliveryRow {\n id: string;\n event: string;\n status: WebhookDeliveryStatus;\n /** Null for a connection-level failure (DNS/SSRF refusal, timeout, connection reset) that never got far\n * enough to receive one. */\n responseStatus: number | null;\n attempts: number;\n error: string | null;\n deliveredAt: string;\n}\n\n/** `PlanmagnetCreateWebhookSubscriptionInput.url` must be an absolute `https://` URL — the server's own SSRF\n * guard (private/loopback/link-local/metadata ranges) is the real gate and runs again at every delivery; this\n * is only the client-side sanity check that catches an obviously wrong URL before a round trip. */\nexport function isPlausibleWebhookUrl(value: string): boolean {\n if (!/^https:\\/\\//i.test(value.trim())) return false;\n try {\n const url = new URL(value.trim());\n return url.protocol === 'https:' && url.hostname.length > 0;\n } catch {\n return false;\n }\n}\n\n/** The event-select option suffix — `WEBHOOK` is accepted and saveable but not yet live (BOFF-8238). */\nexport function webhookEventOptionSuffix(trigger: string): string {\n return trigger === 'WEBHOOK' ? ' (not live yet)' : '';\n}\n"],"mappings":";AAuDA,SAAgB,EAAsB,GAAwB;AAC5D,KAAI,CAAC,eAAe,KAAK,EAAM,MAAM,CAAC,CAAE,QAAO;AAC/C,KAAI;EACF,IAAM,IAAM,IAAI,IAAI,EAAM,MAAM,CAAC;AACjC,SAAO,EAAI,aAAa,YAAY,EAAI,SAAS,SAAS;SACpD;AACN,SAAO;;;AAKX,SAAgB,EAAyB,GAAyB;AAChE,QAAO,MAAY,YAAY,oBAAoB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-planmagnet",
3
- "version": "2026.1001.6",
3
+ "version": "2026.1001.7",
4
4
  "description": "Burdenoff PlanMagnet Microfrontend",
5
5
  "type": "module",
6
6
  "files": [