@timeax/service-builder 0.1.0 → 0.1.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/dist/index.js CHANGED
@@ -617,11 +617,81 @@ function normalizeRole(value) {
617
617
  return value === "utility" ? "utility" : "base";
618
618
  }
619
619
 
620
- // src/workspace/authorization.ts
621
- function hasPermission(permissions2, key) {
622
- if (!permissions2) return false;
623
- return permissions2[key] === true;
620
+ // src/workspace/permissions.ts
621
+ var BUILDER_PERMISSIONS = {
622
+ WORKSPACE_READ: "workspace.read",
623
+ WORKSPACE_WRITE: "workspace.write",
624
+ BRANCHES_READ: "branches.read",
625
+ BRANCHES_CREATE: "branches.create",
626
+ BRANCHES_WRITE: "branches.write",
627
+ BRANCHES_DELETE: "branches.delete",
628
+ BRANCHES_MERGE: "branches.merge",
629
+ BRANCHES_PUBLISH: "branches.publish",
630
+ BRANCHES_MANAGE: "branches.manage",
631
+ TEMPLATES_READ: "templates.read",
632
+ TEMPLATES_WRITE: "templates.write",
633
+ TEMPLATES_DELETE: "templates.delete",
634
+ TEMPLATES_MANAGE: "templates.manage",
635
+ COMMENTS_READ: "comments.read",
636
+ COMMENTS_WRITE: "comments.write",
637
+ COMMENTS_MODERATE: "comments.moderate",
638
+ POLICIES_READ: "policies.read",
639
+ POLICIES_WRITE: "policies.write",
640
+ POLICIES_MANAGE: "policies.manage",
641
+ PARTICIPANTS_READ: "participants.read",
642
+ PARTICIPANTS_WRITE: "participants.write",
643
+ PARTICIPANTS_MANAGE: "participants.manage",
644
+ SERVICES_READ: "services.read"
645
+ };
646
+ var BUILDER_PERMISSION_KEYS = new Set(Object.values(BUILDER_PERMISSIONS));
647
+ function toBuilderPermissionsMap(permissions2) {
648
+ if (!permissions2) return {};
649
+ const result = {};
650
+ for (const [key, value] of Object.entries(permissions2)) {
651
+ if (!BUILDER_PERMISSION_KEYS.has(key)) continue;
652
+ result[key] = value === true;
653
+ }
654
+ return result;
655
+ }
656
+ function can(map, permission) {
657
+ if (!map) return false;
658
+ return map[permission] === true;
659
+ }
660
+ function canReadWorkspace(map) {
661
+ return can(map, BUILDER_PERMISSIONS.WORKSPACE_READ);
662
+ }
663
+ function canEditBranch(map) {
664
+ return can(map, BUILDER_PERMISSIONS.BRANCHES_WRITE);
665
+ }
666
+ function canCreateBranch(map) {
667
+ return can(map, BUILDER_PERMISSIONS.BRANCHES_CREATE);
668
+ }
669
+ function canMergeBranch(map) {
670
+ return can(map, BUILDER_PERMISSIONS.BRANCHES_MERGE);
671
+ }
672
+ function canPublishBranch(map) {
673
+ return can(map, BUILDER_PERMISSIONS.BRANCHES_PUBLISH);
624
674
  }
675
+ function canDeleteBranch(map) {
676
+ return can(map, BUILDER_PERMISSIONS.BRANCHES_DELETE);
677
+ }
678
+ function canManageBranches(map) {
679
+ return can(map, BUILDER_PERMISSIONS.BRANCHES_MANAGE);
680
+ }
681
+ function canWriteTemplates(map) {
682
+ return can(map, BUILDER_PERMISSIONS.TEMPLATES_WRITE);
683
+ }
684
+ function canManageTemplates(map) {
685
+ return can(map, BUILDER_PERMISSIONS.TEMPLATES_MANAGE);
686
+ }
687
+ function canReadComments(map) {
688
+ return can(map, BUILDER_PERMISSIONS.COMMENTS_READ);
689
+ }
690
+ function canWriteComments(map) {
691
+ return can(map, BUILDER_PERMISSIONS.COMMENTS_WRITE);
692
+ }
693
+
694
+ // src/workspace/authorization.ts
625
695
  function resolveActorAuthorId(actor, authors2) {
626
696
  if (!actor) return "unknown";
627
697
  const fromMeta = actor?.meta && typeof actor.meta.authorId === "string" ? actor.meta.authorId : void 0;
@@ -633,40 +703,52 @@ function deriveWorkspaceAuthorization(args) {
633
703
  const { actor, permissions: permissions2 = null, participants = null, authors: authors2 = null } = args;
634
704
  const authorId = resolveActorAuthorId(actor, authors2);
635
705
  const participant = (participants ?? []).find((row) => row.authorId === authorId) ?? null;
636
- const canReadWorkspace = hasPermission(permissions2, "workspace.read");
637
- const canEditBranchContent = hasPermission(permissions2, "workspace.write") && participant?.canWrite === true;
638
- const canCreateBranch = canEditBranchContent && hasPermission(permissions2, "branches.create");
639
- const canMergeBranches = canEditBranchContent && hasPermission(permissions2, "branches.merge");
640
- const canManageBranches = canCreateBranch || canMergeBranches || canEditBranchContent;
641
- const canWriteTemplates = canEditBranchContent && hasPermission(permissions2, "templates.write");
642
- const canCommentRead = canReadWorkspace && hasPermission(permissions2, "comments.read");
643
- const canCommentWrite = canReadWorkspace && hasPermission(permissions2, "comments.write");
706
+ const permissionMap = toBuilderPermissionsMap(permissions2);
707
+ const readWorkspace = canReadWorkspace(permissionMap);
708
+ const editBranch = canEditBranch(permissionMap);
709
+ const createBranch = canCreateBranch(permissionMap);
710
+ const mergeBranches = canMergeBranch(permissionMap);
711
+ const publishBranches = canPublishBranch(permissionMap);
712
+ const deleteBranches = canDeleteBranch(permissionMap);
713
+ const manageBranches = canManageBranches(permissionMap);
714
+ const writeTemplates = canWriteTemplates(permissionMap);
715
+ const manageTemplates = canManageTemplates(permissionMap);
716
+ const commentRead = canReadComments(permissionMap);
717
+ const commentWrite = canWriteComments(permissionMap);
644
718
  return {
645
719
  authorId,
646
720
  participant,
647
- canReadWorkspace,
648
- canEditBranchContent,
649
- canCreateBranch,
650
- canMergeBranches,
651
- canManageBranches,
652
- canWriteTemplates,
653
- canCommentRead,
654
- canCommentWrite
721
+ permissions: permissionMap,
722
+ canReadWorkspace: readWorkspace,
723
+ canEditBranchContent: editBranch,
724
+ canCreateBranch: createBranch,
725
+ canMergeBranches: mergeBranches,
726
+ canPublishBranches: publishBranches,
727
+ canDeleteBranches: deleteBranches,
728
+ canManageBranches: manageBranches,
729
+ canWriteTemplates: writeTemplates,
730
+ canManageTemplates: manageTemplates,
731
+ canCommentRead: readWorkspace && commentRead,
732
+ canCommentWrite: readWorkspace && commentWrite
655
733
  };
656
734
  }
657
735
  function getAuthorizationDecision(auth, action) {
658
736
  switch (action) {
659
737
  case "branch-content-edit":
660
738
  case "snapshot-write":
661
- return auth.canEditBranchContent ? { ok: true } : { ok: false, reason: "Editing is disabled. You need workspace write access and branch write access." };
739
+ return auth.canEditBranchContent ? { ok: true } : { ok: false, reason: "Editing is disabled. You need branches.write." };
662
740
  case "template-write":
663
- return auth.canWriteTemplates ? { ok: true } : { ok: false, reason: "Template editing requires templates.write and branch edit access." };
741
+ return auth.canWriteTemplates ? { ok: true } : { ok: false, reason: "Template editing requires templates.write." };
664
742
  case "branch-create":
665
- return auth.canCreateBranch ? { ok: true } : { ok: false, reason: "Branch creation requires branches.create and branch edit access." };
743
+ return auth.canCreateBranch ? { ok: true } : { ok: false, reason: "Branch creation requires branches.create." };
666
744
  case "branch-merge":
667
- return auth.canMergeBranches ? { ok: true } : { ok: false, reason: "Branch merge requires branches.merge and branch edit access." };
745
+ return auth.canMergeBranches ? { ok: true } : { ok: false, reason: "Branch merge requires branches.merge." };
746
+ case "branch-publish":
747
+ return auth.canPublishBranches ? { ok: true } : { ok: false, reason: "Branch publish requires branches.publish." };
748
+ case "branch-delete":
749
+ return auth.canDeleteBranches ? { ok: true } : { ok: false, reason: "Branch deletion requires branches.delete." };
668
750
  case "branch-manage":
669
- return auth.canManageBranches ? { ok: true } : { ok: false, reason: "Branch management requires branch edit access." };
751
+ return auth.canManageBranches ? { ok: true } : { ok: false, reason: "Branch management requires branches.manage." };
670
752
  case "comment-read":
671
753
  return auth.canCommentRead ? { ok: true } : { ok: false, reason: "Comment read access is disabled for this actor." };
672
754
  case "comment-write":
@@ -3404,6 +3486,7 @@ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
3404
3486
  function AppToolbar({
3405
3487
  bootActionReason,
3406
3488
  editDisabledReason,
3489
+ publishDisabledReason,
3407
3490
  commentDisabledReason,
3408
3491
  errors,
3409
3492
  bottomPanelOpen,
@@ -3454,7 +3537,7 @@ function AppToolbar({
3454
3537
  "aria-label": "Publish commit",
3455
3538
  onClick: onPublish,
3456
3539
  disabled: pendingAction === "publish" || !canPublish,
3457
- title: (bootActionReason && !canPublish ? bootActionReason : void 0) ?? (!canPublish ? editDisabledReason : void 0) ?? "Publish commit",
3540
+ title: (bootActionReason && !canPublish ? bootActionReason : void 0) ?? (!canPublish ? publishDisabledReason : void 0) ?? "Publish commit",
3458
3541
  children: /* @__PURE__ */ jsx13(LuGitCommitHorizontal, {})
3459
3542
  }
3460
3543
  )
@@ -6067,7 +6150,9 @@ function CanvasPanel({
6067
6150
  );
6068
6151
  const canEditBranchContent = auth.canEditBranchContent;
6069
6152
  const canCommentWrite = auth.canCommentWrite;
6153
+ const canPublishBranch2 = auth.canPublishBranches;
6070
6154
  const editDecision = getAuthorizationDecision(auth, "branch-content-edit");
6155
+ const publishDecision = getAuthorizationDecision(auth, "branch-publish");
6071
6156
  const commentWriteDecision = getAuthorizationDecision(auth, "comment-write");
6072
6157
  const emitPermissionDenied = useCallback7(
6073
6158
  (reason, action, meta) => {
@@ -6217,7 +6302,7 @@ function CanvasPanel({
6217
6302
  }, [canvas.api, ws.snapshot]);
6218
6303
  const hasChanges = currentSnapshotHash !== persistedBaselineHash;
6219
6304
  const canSave = hasChanges && canEditBranchContent;
6220
- const canPublish = !!ws.snapshot.draft && !hasChanges && canEditBranchContent;
6305
+ const canPublish = !!ws.snapshot.draft && !hasChanges && canPublishBranch2;
6221
6306
  const importProps = async (nextProps) => {
6222
6307
  if (!canEditBranchContent) {
6223
6308
  emitPermissionDenied(editDecision.reason ?? "Editing is disabled for this actor.", "import-props");
@@ -6492,6 +6577,7 @@ function CanvasPanel({
6492
6577
  {
6493
6578
  bootActionReason,
6494
6579
  editDisabledReason: !canEditBranchContent ? editDecision.reason ?? "Editing is disabled for this actor." : void 0,
6580
+ publishDisabledReason: !canPublishBranch2 ? publishDecision.reason ?? "Publishing is disabled for this actor." : void 0,
6495
6581
  commentDisabledReason: !canCommentWrite ? commentWriteDecision.reason ?? "Comment write access is disabled for this actor." : void 0,
6496
6582
  errors,
6497
6583
  showErrorBadges,
@@ -6538,8 +6624,8 @@ function CanvasPanel({
6538
6624
  }
6539
6625
  },
6540
6626
  onPublish: async () => {
6541
- if (!canEditBranchContent) {
6542
- emitPermissionDenied(editDecision.reason ?? "Editing is disabled for this actor.", "snapshot-publish");
6627
+ if (!canPublishBranch2) {
6628
+ emitPermissionDenied(publishDecision.reason ?? "Publishing is disabled for this actor.", "snapshot-publish");
6543
6629
  return;
6544
6630
  }
6545
6631
  if (!canPublish) return;
@@ -7215,15 +7301,6 @@ import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
7215
7301
  function normalizeKey(input) {
7216
7302
  return input.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
7217
7303
  }
7218
- function getActorAuthorId(ws) {
7219
- const actorMetaAuthorId = ws.actor?.meta && typeof ws.actor.meta.authorId === "string" ? ws.actor.meta.authorId : void 0;
7220
- if (actorMetaAuthorId) return actorMetaAuthorId;
7221
- if ((ws.authors.data ?? []).some((author) => author.id === ws.actor.id)) return ws.actor.id;
7222
- return ws.actor.id;
7223
- }
7224
- function resolveBranchParticipant(authorId, participants) {
7225
- return (participants ?? []).find((participant) => participant.authorId === authorId);
7226
- }
7227
7304
  function ActionIconButton({
7228
7305
  icon,
7229
7306
  label,
@@ -7262,25 +7339,34 @@ var Drafts = ({ trigger }) => {
7262
7339
  const [createName, setCreateName] = useState11("");
7263
7340
  const [createFromId, setCreateFromId] = useState11(ws.branches.currentId);
7264
7341
  const [actionKey, setActionKey] = useState11(null);
7265
- const workspaceRead = ws.permissions.data?.["workspace.read"] ?? false;
7266
- const canCreateBranch = ws.permissions.data?.["branches.create"] ?? false;
7267
- const canMergeBranches = ws.permissions.data?.["branches.merge"] ?? false;
7268
- const canWriteWorkspace = ws.permissions.data?.["workspace.write"] ?? false;
7342
+ const auth = useMemo11(
7343
+ () => deriveWorkspaceAuthorization({
7344
+ actor: ws.actor,
7345
+ permissions: ws.permissions?.data,
7346
+ participants: ws.participants?.data,
7347
+ authors: ws.authors?.data
7348
+ }),
7349
+ [ws.actor, ws.authors?.data, ws.participants?.data, ws.permissions?.data]
7350
+ );
7351
+ const workspaceRead = auth.canReadWorkspace;
7352
+ const branchesReadable = auth.permissions["branches.read"] === true;
7353
+ const canCreateBranch2 = auth.canCreateBranch;
7354
+ const canMergeBranches = auth.canMergeBranches;
7355
+ const canManageBranches2 = auth.canManageBranches;
7356
+ const canDeleteBranches = auth.canDeleteBranches;
7357
+ const canWriteBranchContent = auth.canEditBranchContent;
7269
7358
  const currentBranch = ws.branches.data?.find((branch) => branch.id === ws.branches.currentId);
7270
- const actorAuthorId = getActorAuthorId(ws);
7271
7359
  const branchItems = useMemo11(() => {
7272
7360
  return (ws.branches.data ?? []).map((branch) => {
7273
- const participant = branch.id === ws.branches.currentId ? resolveBranchParticipant(actorAuthorId, ws.participants.data) : null;
7274
- const canRead = branch.id === ws.branches.currentId ? true : workspaceRead;
7275
- const canWrite = branch.id === ws.branches.currentId ? participant?.canWrite ?? false : canWriteWorkspace;
7361
+ const canRead = branchesReadable && workspaceRead;
7362
+ const canWrite = canWriteBranchContent;
7276
7363
  return {
7277
7364
  branch,
7278
- participant,
7279
7365
  canRead,
7280
7366
  canWrite
7281
7367
  };
7282
7368
  });
7283
- }, [actorAuthorId, canWriteWorkspace, workspaceRead, ws.branches.currentId, ws.branches.data, ws.participants.data]);
7369
+ }, [branchesReadable, canWriteBranchContent, workspaceRead, ws.branches.data]);
7284
7370
  const visibleBranches = useMemo11(() => {
7285
7371
  const lower = query.trim().toLowerCase();
7286
7372
  return branchItems.filter((item) => {
@@ -7376,15 +7462,15 @@ var Drafts = ({ trigger }) => {
7376
7462
  const createPermission = useMemo11(() => {
7377
7463
  if (!ws.boot.isReady) return { allowed: false, reason: bootActionReason ?? "Workspace data is still loading." };
7378
7464
  if (!workspaceRead) return { allowed: false, reason: "You do not have workspace access." };
7379
- if (!canCreateBranch) return { allowed: false, reason: "Branch creation is disabled by workspace permissions." };
7465
+ if (!canCreateBranch2) return { allowed: false, reason: "Branch creation is disabled by workspace permissions." };
7380
7466
  if (!createFromId) return { allowed: false, reason: "Choose a source branch first." };
7381
7467
  return { allowed: true };
7382
- }, [bootActionReason, canCreateBranch, createFromId, workspaceRead, ws.boot.isReady]);
7468
+ }, [bootActionReason, canCreateBranch2, createFromId, workspaceRead, ws.boot.isReady]);
7383
7469
  const branchActionMenu = (item) => {
7384
7470
  const currentId = ws.branches.currentId;
7385
7471
  const switchPermission = !ws.boot.isReady ? { allowed: false, reason: bootActionReason ?? "Workspace data is still loading." } : item.branch.id === currentId ? { allowed: false, reason: "This branch is already active." } : { allowed: true };
7386
- const setMainPermission = !ws.boot.isReady ? { allowed: false, reason: bootActionReason ?? "Workspace data is still loading." } : item.branch.isMain ? { allowed: false, reason: "This branch is already the main branch." } : !canWriteWorkspace ? { allowed: false, reason: "Setting the main branch requires workspace write access." } : !item.canWrite ? { allowed: false, reason: "You need write access to this branch to make it main." } : { allowed: true };
7387
- const deletePermission = !ws.boot.isReady ? { allowed: false, reason: bootActionReason ?? "Workspace data is still loading." } : item.branch.isMain ? { allowed: false, reason: "Set another branch as main before deleting this branch." } : !canWriteWorkspace ? { allowed: false, reason: "Deleting branches requires workspace write access." } : !item.canWrite ? { allowed: false, reason: "You need write access to delete this branch." } : { allowed: true };
7472
+ const setMainPermission = !ws.boot.isReady ? { allowed: false, reason: bootActionReason ?? "Workspace data is still loading." } : item.branch.isMain ? { allowed: false, reason: "This branch is already the main branch." } : !canManageBranches2 ? { allowed: false, reason: "Setting the main branch requires branches.manage." } : !item.canWrite ? { allowed: false, reason: "You need write access to this branch to make it main." } : { allowed: true };
7473
+ const deletePermission = !ws.boot.isReady ? { allowed: false, reason: bootActionReason ?? "Workspace data is still loading." } : item.branch.isMain ? { allowed: false, reason: "Set another branch as main before deleting this branch." } : !canDeleteBranches ? { allowed: false, reason: "Deleting branches requires branches.delete." } : !item.canWrite ? { allowed: false, reason: "You need write access to delete this branch." } : { allowed: true };
7388
7474
  const mergeTargets = visibleBranches.filter((target) => target.branch.id !== item.branch.id).map((target) => {
7389
7475
  const mergePermission = !ws.boot.isReady ? { allowed: false, reason: bootActionReason ?? "Workspace data is still loading." } : !canMergeBranches ? { allowed: false, reason: "Merging is disabled by workspace permissions." } : !item.canWrite ? { allowed: false, reason: "You need write access to the source branch to merge it." } : !target.canWrite ? { allowed: false, reason: "You need write access to the target branch to merge into it." } : { allowed: true };
7390
7476
  return {
@@ -9082,6 +9168,13 @@ import * as React22 from "react";
9082
9168
  import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
9083
9169
  function Node({ node, matched, isEditing, onCommit, onCancel }) {
9084
9170
  const spanRef = React22.useRef(null);
9171
+ React22.useEffect(() => {
9172
+ const span = spanRef.current;
9173
+ if (!span || isEditing) return;
9174
+ if (span.textContent !== node.title) {
9175
+ span.textContent = node.title;
9176
+ }
9177
+ }, [isEditing, node.title]);
9085
9178
  React22.useEffect(() => {
9086
9179
  if (isEditing && spanRef.current) {
9087
9180
  spanRef.current.focus();
@@ -9093,18 +9186,18 @@ function Node({ node, matched, isEditing, onCommit, onCancel }) {
9093
9186
  selection?.addRange(range);
9094
9187
  }
9095
9188
  }, [isEditing]);
9189
+ const commitFromDom = React22.useCallback(() => {
9190
+ if (!isEditing || !onCommit || !spanRef.current) return;
9191
+ onCommit(spanRef.current.innerText || "");
9192
+ }, [isEditing, onCommit]);
9096
9193
  const handleBlur = () => {
9097
- const edited = spanRef.current.innerText;
9098
- spanRef.current.innerText = node.title;
9099
- if (isEditing && onCommit && spanRef.current) {
9100
- onCommit(edited);
9101
- }
9194
+ commitFromDom();
9102
9195
  };
9103
9196
  const handleKeyDown = (e) => {
9104
9197
  if (!isEditing) return;
9105
9198
  if (e.key === "Enter") {
9106
9199
  e.preventDefault();
9107
- onCommit?.(spanRef.current?.innerText || "");
9200
+ spanRef.current?.blur();
9108
9201
  } else if (e.key === "Escape") {
9109
9202
  e.preventDefault();
9110
9203
  onCancel?.();
@@ -9991,6 +10084,7 @@ var Panel = React27.forwardRef(function Panel2({
9991
10084
  width: size.width != null ? `${size.width}px` : void 0,
9992
10085
  height: size.height != null ? `${size.height}px` : void 0
9993
10086
  };
10087
+ const panelWidth = size.width != null ? `${size.width}px` : panelRef.current ? `${Math.round(panelRef.current.getBoundingClientRect().width)}px` : void 0;
9994
10088
  const offsetStyle = maintainPosition ? {
9995
10089
  ...offsets.left != null ? { left: `${offsets.left}px` } : null,
9996
10090
  ...offsets.top != null ? { top: `${offsets.top}px` } : null,
@@ -10009,6 +10103,8 @@ var Panel = React27.forwardRef(function Panel2({
10009
10103
  ...sizeStyle,
10010
10104
  ...offsetStyle,
10011
10105
  ...edgeStrokeStyle,
10106
+ // expose custom property for children
10107
+ ["--panel-width"]: panelWidth,
10012
10108
  touchAction: resizable ? "none" : void 0,
10013
10109
  cursor: resizable ? cursor : void 0
10014
10110
  },
@@ -11193,7 +11289,7 @@ function IncludesList({ className, children }) {
11193
11289
  function IncludesItem({ title, badge, actions, className }) {
11194
11290
  return /* @__PURE__ */ jsxs33("div", { className: cn("flex items-center justify-between rounded-md p-2", "bg-gray-50 dark:bg-gray-800/50", className), children: [
11195
11291
  /* @__PURE__ */ jsxs33("div", { className: "flex min-w-0 items-center gap-2", children: [
11196
- /* @__PURE__ */ jsx50("span", { className: "truncate text-sm text-gray-800 dark:text-gray-200", children: title }),
11292
+ /* @__PURE__ */ jsx50("span", { title, className: "max-w-[calc(var(--panel-width)-11rem)] truncate text-sm text-gray-800 dark:text-gray-200", children: title }),
11197
11293
  badge
11198
11294
  ] }),
11199
11295
  !!actions?.length && /* @__PURE__ */ jsx50("div", { className: "flex items-center gap-2", children: actions.map((a, idx) => /* @__PURE__ */ jsx50(IncludesIconAction, { ...a }, idx)) })
@@ -11553,7 +11649,7 @@ function RenderIf({ data, emptyMessage = null, children, when }) {
11553
11649
  // src/panels/right/partials/global/add-service.tsx
11554
11650
  import { useCanvas as useCanvas7, useWorkspace as useWorkspace12 } from "@timeax/digital-service-engine/workspace";
11555
11651
  import { InputField as InputField5 } from "@timeax/form-palette";
11556
- import { useCallback as useCallback17, useEffect as useEffect19, useMemo as useMemo25, useState as useState26 } from "react";
11652
+ import { useCallback as useCallback18, useEffect as useEffect19, useMemo as useMemo25, useState as useState26 } from "react";
11557
11653
  import { BsPlus } from "react-icons/bs";
11558
11654
  import { FaFolderOpen } from "react-icons/fa";
11559
11655
  import { FiFilter } from "react-icons/fi";
@@ -11735,7 +11831,7 @@ function AddServicePopover({
11735
11831
  }
11736
11832
  return ids;
11737
11833
  }, [canvas.api.editor, contextFilterEnabled, liveSnapshot, policies2, services2]);
11738
- const setCatalogMode = useCallback17(
11834
+ const setCatalogMode = useCallback18(
11739
11835
  (mode) => {
11740
11836
  const editor = canvas.api.editor;
11741
11837
  editor.ensureCatalog?.();
@@ -14296,7 +14392,7 @@ var wireframe_tags_widget_default = WireframeTagsWidget;
14296
14392
  // src/panels/right/tabs/wireframe.tsx
14297
14393
  import { useOrderFlow, Wrapper } from "@timeax/digital-service-engine/react";
14298
14394
  import { useCanvas as useCanvas16, useWorkspace as useWorkspace14 } from "@timeax/digital-service-engine/workspace";
14299
- import { useCallback as useCallback18, useMemo as useMemo33 } from "react";
14395
+ import { useCallback as useCallback19, useMemo as useMemo33 } from "react";
14300
14396
  import { jsx as jsx71, jsxs as jsxs51 } from "react/jsx-runtime";
14301
14397
  var CHECKBOX_SINGLE_EXTRA_PROPS = Object.freeze({ single: true });
14302
14398
  function Wireframe() {
@@ -14357,7 +14453,7 @@ function Wireframe() {
14357
14453
  }
14358
14454
  return map;
14359
14455
  }, [canvas.props, canvas.selectionInfo, canvas.activeId]);
14360
- const select = useCallback18(
14456
+ const select = useCallback19(
14361
14457
  (id) => {
14362
14458
  canvas.setActive(id);
14363
14459
  canvas.api.select([id]);
@@ -14499,7 +14595,7 @@ var right_default = RightPanel;
14499
14595
  // src/workspace/fallback-editor-modal.tsx
14500
14596
  import { useCanvas as useCanvas18, useWorkspace as useWorkspace15 } from "@timeax/digital-service-engine/workspace";
14501
14597
  import cloneDeep4 from "lodash/cloneDeep";
14502
- import { Suspense, lazy, createContext as createContext4, useCallback as useCallback19, useContext as useContext4, useEffect as useEffect21, useMemo as useMemo34, useState as useState33 } from "react";
14598
+ import { Suspense, lazy, createContext as createContext4, useCallback as useCallback20, useContext as useContext4, useEffect as useEffect21, useMemo as useMemo34, useState as useState33 } from "react";
14503
14599
  import { createPortal as createPortal4 } from "react-dom";
14504
14600
  import { FiX as FiX4 } from "react-icons/fi";
14505
14601
  import { jsx as jsx73, jsxs as jsxs53 } from "react/jsx-runtime";
@@ -14522,11 +14618,11 @@ function FallbackEditorModalProvider({ children }) {
14522
14618
  const [launch, setLaunch] = useState33(null);
14523
14619
  const [sessionId, setSessionId] = useState33(0);
14524
14620
  const [surfaceError, setSurfaceError] = useState33(null);
14525
- const close = useCallback19(() => {
14621
+ const close = useCallback20(() => {
14526
14622
  setLaunch(null);
14527
14623
  setSurfaceError(null);
14528
14624
  }, []);
14529
- const openForNode = useCallback19((input) => {
14625
+ const openForNode = useCallback20((input) => {
14530
14626
  setSurfaceError(null);
14531
14627
  setSessionId((current) => current + 1);
14532
14628
  setLaunch({
@@ -14537,7 +14633,7 @@ function FallbackEditorModalProvider({ children }) {
14537
14633
  nodeLabel: input.nodeLabel ?? input.nodeId
14538
14634
  });
14539
14635
  }, []);
14540
- const openForService = useCallback19((input) => {
14636
+ const openForService = useCallback20((input) => {
14541
14637
  setSurfaceError(null);
14542
14638
  setSessionId((current) => current + 1);
14543
14639
  setLaunch({
@@ -14546,7 +14642,7 @@ function FallbackEditorModalProvider({ children }) {
14546
14642
  serviceName: input.serviceName
14547
14643
  });
14548
14644
  }, []);
14549
- const persistProps = useCallback19(
14645
+ const persistProps = useCallback20(
14550
14646
  (label, mutate) => {
14551
14647
  const editorAny = canvas.api.editor;
14552
14648
  if (typeof editorAny.transact !== "function" || typeof editorAny.replaceProps !== "function") {
@@ -14560,7 +14656,7 @@ function FallbackEditorModalProvider({ children }) {
14560
14656
  },
14561
14657
  [canvas.api.builder, canvas.api.editor, canvas.props]
14562
14658
  );
14563
- const handleSave = useCallback19(
14659
+ const handleSave = useCallback20(
14564
14660
  async (nextFallbacks) => {
14565
14661
  setSurfaceError(null);
14566
14662
  try {
@@ -14577,7 +14673,7 @@ function FallbackEditorModalProvider({ children }) {
14577
14673
  },
14578
14674
  [close, persistProps]
14579
14675
  );
14580
- const handleSettingsChange = useCallback19(
14676
+ const handleSettingsChange = useCallback20(
14581
14677
  async (nextSettings) => {
14582
14678
  setSurfaceError(null);
14583
14679
  try {
@@ -14690,7 +14786,7 @@ function useFallbackEditorModal() {
14690
14786
 
14691
14787
  // src/workspace/bottom-panel/index.tsx
14692
14788
  import { useCanvas as useCanvas21, useWorkspace as useWorkspace16 } from "@timeax/digital-service-engine/workspace";
14693
- import { useCallback as useCallback20, useEffect as useEffect24, useMemo as useMemo36, useRef as useRef12, useState as useState36 } from "react";
14789
+ import { useCallback as useCallback21, useEffect as useEffect24, useMemo as useMemo36, useRef as useRef12, useState as useState36 } from "react";
14694
14790
  import { FiEye as FiEye3, FiEyeOff as FiEyeOff2, FiSearch, FiTerminal as FiTerminal2, FiX as FiX6 } from "react-icons/fi";
14695
14791
  import { LuGripHorizontal, LuLayers3 } from "react-icons/lu";
14696
14792
  import { MdOutlineSync } from "react-icons/md";
@@ -16521,7 +16617,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
16521
16617
  window.removeEventListener("pointercancel", onPointerUp);
16522
16618
  };
16523
16619
  }, [draggingPanel, panelPosition]);
16524
- const setCatalogMode = useCallback20(
16620
+ const setCatalogMode = useCallback21(
16525
16621
  (mode) => {
16526
16622
  const editor = canvas.api.editor;
16527
16623
  editor.ensureCatalog?.();
@@ -16529,27 +16625,27 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
16529
16625
  },
16530
16626
  [canvas.api.editor]
16531
16627
  );
16532
- const handleSelectCatalogService = useCallback20(
16628
+ const handleSelectCatalogService = useCallback21(
16533
16629
  (id) => {
16534
16630
  setSelectedAllServiceId(id);
16535
16631
  canvas.api.editor.setSelectedCatalogService?.(id ?? void 0);
16536
16632
  },
16537
16633
  [canvas.api.editor]
16538
16634
  );
16539
- const handleSelectCatalogGroup = useCallback20(
16635
+ const handleSelectCatalogGroup = useCallback21(
16540
16636
  (groupId) => {
16541
16637
  canvas.api.editor.setActiveCatalogNode?.(groupId ?? void 0);
16542
16638
  },
16543
16639
  [canvas.api.editor]
16544
16640
  );
16545
- const handleCreateRootGroup = useCallback20(
16641
+ const handleCreateRootGroup = useCallback21(
16546
16642
  (label) => {
16547
16643
  if (!label.trim()) return;
16548
16644
  canvas.api.editor.createCatalogGroup?.({ label: label.trim() });
16549
16645
  },
16550
16646
  [canvas.api.editor]
16551
16647
  );
16552
- const handleCreateChildGroup = useCallback20(
16648
+ const handleCreateChildGroup = useCallback21(
16553
16649
  (label) => {
16554
16650
  if (!selectedCatalogGroupId) return;
16555
16651
  const editor = canvas.api.editor;
@@ -16558,7 +16654,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
16558
16654
  },
16559
16655
  [canvas.api.editor, selectedCatalogGroupId]
16560
16656
  );
16561
- const handleRenameGroup = useCallback20(
16657
+ const handleRenameGroup = useCallback21(
16562
16658
  (label) => {
16563
16659
  if (!selectedCatalogGroupId) return;
16564
16660
  const group = catalogGroups.find((item) => item.id === selectedCatalogGroupId);
@@ -16568,15 +16664,15 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
16568
16664
  },
16569
16665
  [canvas.api.editor, catalogGroups, selectedCatalogGroupId]
16570
16666
  );
16571
- const handleDeleteGroup = useCallback20(() => {
16667
+ const handleDeleteGroup = useCallback21(() => {
16572
16668
  if (!selectedCatalogGroupId) return;
16573
16669
  canvas.api.editor.removeCatalogNode?.(selectedCatalogGroupId, { cascade: true });
16574
16670
  }, [canvas.api.editor, selectedCatalogGroupId]);
16575
- const handleAssignServices = useCallback20(() => {
16671
+ const handleAssignServices = useCallback21(() => {
16576
16672
  if (!selectedCatalogGroupId) return;
16577
16673
  setServicePickerOpen(true);
16578
16674
  }, [selectedCatalogGroupId]);
16579
- const handleConfirmAssignServices = useCallback20(
16675
+ const handleConfirmAssignServices = useCallback21(
16580
16676
  (serviceIds) => {
16581
16677
  if (!selectedCatalogGroupId || !serviceIds.length) return;
16582
16678
  canvas.api.editor.assignServicesToCatalogGroup?.(selectedCatalogGroupId, serviceIds, "append");
@@ -17247,41 +17343,77 @@ var participantsByBranch = {
17247
17343
  var permissions = {
17248
17344
  "actor:davy": {
17249
17345
  "workspace.read": true,
17250
- "workspace.write": true,
17346
+ "workspace.write": false,
17347
+ "branches.read": true,
17251
17348
  "branches.create": true,
17349
+ "branches.write": false,
17350
+ "branches.delete": true,
17252
17351
  "branches.merge": true,
17352
+ "branches.publish": true,
17353
+ "branches.manage": true,
17253
17354
  "templates.read": true,
17254
17355
  "templates.write": true,
17356
+ "templates.delete": true,
17357
+ "templates.manage": true,
17255
17358
  "comments.read": true,
17256
17359
  "comments.write": true,
17360
+ "comments.moderate": true,
17257
17361
  "policies.read": true,
17258
17362
  "policies.write": true,
17363
+ "policies.manage": true,
17364
+ "participants.read": true,
17365
+ "participants.write": true,
17366
+ "participants.manage": true,
17259
17367
  "services.read": true
17260
17368
  },
17261
17369
  "actor:bot": {
17262
17370
  "workspace.read": true,
17263
17371
  "workspace.write": false,
17372
+ "branches.read": true,
17264
17373
  "branches.create": false,
17374
+ "branches.write": false,
17375
+ "branches.delete": false,
17265
17376
  "branches.merge": false,
17377
+ "branches.publish": false,
17378
+ "branches.manage": false,
17266
17379
  "templates.read": true,
17267
17380
  "templates.write": false,
17381
+ "templates.delete": false,
17382
+ "templates.manage": false,
17268
17383
  "comments.read": true,
17269
17384
  "comments.write": true,
17385
+ "comments.moderate": false,
17270
17386
  "policies.read": false,
17271
17387
  "policies.write": false,
17388
+ "policies.manage": false,
17389
+ "participants.read": false,
17390
+ "participants.write": false,
17391
+ "participants.manage": false,
17272
17392
  "services.read": true
17273
17393
  },
17274
17394
  "actor:readonly": {
17275
17395
  "workspace.read": true,
17276
17396
  "workspace.write": false,
17397
+ "branches.read": true,
17277
17398
  "branches.create": false,
17399
+ "branches.write": false,
17400
+ "branches.delete": false,
17278
17401
  "branches.merge": false,
17402
+ "branches.publish": false,
17403
+ "branches.manage": false,
17279
17404
  "templates.read": true,
17280
17405
  "templates.write": false,
17406
+ "templates.delete": false,
17407
+ "templates.manage": false,
17281
17408
  "comments.read": true,
17282
17409
  "comments.write": false,
17410
+ "comments.moderate": false,
17283
17411
  "policies.read": false,
17284
17412
  "policies.write": false,
17413
+ "policies.manage": false,
17414
+ "participants.read": false,
17415
+ "participants.write": false,
17416
+ "participants.manage": false,
17285
17417
  "services.read": true
17286
17418
  }
17287
17419
  };
@@ -17324,7 +17456,7 @@ var policiesByBranch = {
17324
17456
  var services = {
17325
17457
  1001: {
17326
17458
  id: 1001,
17327
- name: "Instagram Followers \u2022 Fast",
17459
+ name: "Instagram Followers this shidshjs dcsh sojf dso sodhs jhdv sdh vshfdv sohfdv sohfs fhso fhsof sihfi \u2022 Fast",
17328
17460
  rate: 1.25,
17329
17461
  min: 50,
17330
17462
  max: 5e4,
@@ -17623,7 +17755,7 @@ var workspaceBackend = {
17623
17755
  return baseBackend.branches.merge(workspaceId, sourceId, targetId);
17624
17756
  },
17625
17757
  delete: async (workspaceId, branchId) => {
17626
- const check = await authorize("branch-manage", branchId);
17758
+ const check = await authorize("branch-delete", branchId);
17627
17759
  if (!check.ok) return check;
17628
17760
  return baseBackend.branches.delete(workspaceId, branchId);
17629
17761
  }
@@ -17677,7 +17809,7 @@ var workspaceBackend = {
17677
17809
  },
17678
17810
  publish: async (params) => {
17679
17811
  if (params.actorId !== workspaceActor.id) return forbidden("Snapshot mutation denied for unknown actor.", { actorId: params.actorId });
17680
- const check = await authorize("snapshot-write", void 0);
17812
+ const check = await authorize("branch-publish", void 0);
17681
17813
  if (!check.ok) return check;
17682
17814
  return baseBackend.snapshots.publish(params);
17683
17815
  },