@ixo/editor 3.0.0 → 3.2.0

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.
@@ -2348,8 +2348,64 @@ var isNodeActive = (node, runtime) => {
2348
2348
  return { active: true };
2349
2349
  };
2350
2350
 
2351
+ // src/core/lib/flowEngine/versionManifest.ts
2352
+ var VERSION_MANIFEST = {
2353
+ "0.3": {
2354
+ version: "0.3",
2355
+ label: "Legacy",
2356
+ ucanRequired: false,
2357
+ delegationRootRequired: false,
2358
+ whitelistOnlyAllowed: true,
2359
+ unrestrictedAllowed: true,
2360
+ executionPath: "legacy",
2361
+ authorizationFn: "v1",
2362
+ allowedAuthModes: ["anyone", "actors", "capability"],
2363
+ ui: {
2364
+ showDelegationPanel: false,
2365
+ showWhitelistConfig: true,
2366
+ showAnyoneConfig: true,
2367
+ showMigrationBanner: true,
2368
+ requirePinForExecution: false
2369
+ },
2370
+ description: "Legacy version. UCAN optional, whitelist-only authorization accepted."
2371
+ },
2372
+ "1.0.0": {
2373
+ version: "1.0.0",
2374
+ label: "UCAN Required",
2375
+ ucanRequired: true,
2376
+ delegationRootRequired: true,
2377
+ whitelistOnlyAllowed: false,
2378
+ unrestrictedAllowed: false,
2379
+ executionPath: "invocation",
2380
+ authorizationFn: "v2",
2381
+ allowedAuthModes: ["capability"],
2382
+ ui: {
2383
+ showDelegationPanel: true,
2384
+ showWhitelistConfig: false,
2385
+ showAnyoneConfig: false,
2386
+ showMigrationBanner: false,
2387
+ requirePinForExecution: true
2388
+ },
2389
+ description: "UCAN-enforced. Every block execution requires a valid delegation chain."
2390
+ }
2391
+ };
2392
+ var LATEST_VERSION = "1.0.0";
2393
+ function getVersionPolicy(version) {
2394
+ const policy = VERSION_MANIFEST[version];
2395
+ if (!policy) {
2396
+ return VERSION_MANIFEST[LATEST_VERSION];
2397
+ }
2398
+ return policy;
2399
+ }
2400
+
2351
2401
  // src/core/lib/flowEngine/authorization.ts
2352
- var isAuthorized = async (blockId, actorDid, ucanService, flowUri) => {
2402
+ var isAuthorized = async (blockId, actorDid, ucanService, flowUri, schemaVersion) => {
2403
+ if (schemaVersion) {
2404
+ const policy = getVersionPolicy(schemaVersion);
2405
+ if (!policy.ucanRequired) {
2406
+ return { authorized: true };
2407
+ }
2408
+ }
2353
2409
  const capability = {
2354
2410
  can: "flow/block/execute",
2355
2411
  with: `${flowUri}:${blockId}`
@@ -2809,6 +2865,153 @@ var createUcanService = (config) => {
2809
2865
  };
2810
2866
  };
2811
2867
 
2868
+ // src/core/lib/flowEngine/migration.ts
2869
+ var MIGRATION_REGISTRY = {};
2870
+ function registerMigration(definition) {
2871
+ const key = `${definition.from}->${definition.to}`;
2872
+ MIGRATION_REGISTRY[key] = definition;
2873
+ }
2874
+
2875
+ // src/core/lib/flowEngine/migrations/v0_3_to_v1_0_0.ts
2876
+ var NON_EXECUTABLE_BLOCK_TYPES = /* @__PURE__ */ new Set(["paragraph", "heading", "bulletListItem", "numberedListItem", "image", "table"]);
2877
+ function hasDelegationForBlock(ctx, blockId) {
2878
+ const delegations = ctx.ucanService.getAllDelegations();
2879
+ const resourceUri = `${ctx.flowUri}:${blockId}`;
2880
+ return delegations.some((d) => d.capabilities.some((c) => c.can === "flow/block/execute" && c.with === resourceUri));
2881
+ }
2882
+ var migration_0_3_to_1_0_0 = {
2883
+ from: "0.3",
2884
+ to: "1.0.0",
2885
+ preconditions: [
2886
+ {
2887
+ id: "has_flow_owner",
2888
+ description: "Flow must have a flowOwnerDid set",
2889
+ check: (ctx) => {
2890
+ const ownerDid = ctx.editor.getFlowOwnerDid?.() || ctx.flowOwnerDid;
2891
+ return !!ownerDid;
2892
+ },
2893
+ blocking: true
2894
+ },
2895
+ {
2896
+ id: "is_owner",
2897
+ description: "Only the flow owner can initiate migration",
2898
+ check: (ctx) => {
2899
+ const ownerDid = ctx.editor.getFlowOwnerDid?.() || ctx.flowOwnerDid;
2900
+ return ctx.actorDid === ownerDid;
2901
+ },
2902
+ blocking: true
2903
+ },
2904
+ {
2905
+ id: "ucan_service_available",
2906
+ description: "UCAN service must be configured",
2907
+ check: (ctx) => {
2908
+ return !!ctx.ucanService && ctx.ucanService.isConfigured();
2909
+ },
2910
+ blocking: true
2911
+ }
2912
+ ],
2913
+ async analyze(ctx) {
2914
+ const items = [];
2915
+ const blocks = ctx.editor.document;
2916
+ const rootDelegation = ctx.ucanService.getRootDelegation();
2917
+ if (!rootDelegation) {
2918
+ items.push({
2919
+ id: "__root_delegation__",
2920
+ nodeId: "",
2921
+ type: "create_root_delegation",
2922
+ status: "pending",
2923
+ requiresUserAction: true,
2924
+ description: "Create root delegation for flow owner"
2925
+ });
2926
+ }
2927
+ if (blocks) {
2928
+ for (const block of blocks) {
2929
+ if (NON_EXECUTABLE_BLOCK_TYPES.has(block.type)) continue;
2930
+ if (!hasDelegationForBlock(ctx, block.id)) {
2931
+ items.push({
2932
+ id: `node_delegation_${block.id}`,
2933
+ nodeId: block.id,
2934
+ type: "create_node_delegation",
2935
+ status: "pending",
2936
+ requiresUserAction: true,
2937
+ description: `Create delegation for block "${block.type}" (${block.id})`
2938
+ });
2939
+ }
2940
+ }
2941
+ }
2942
+ return items;
2943
+ },
2944
+ async executeItem(ctx, item) {
2945
+ try {
2946
+ switch (item.type) {
2947
+ case "create_root_delegation": {
2948
+ await ctx.ucanService.createRootDelegation({
2949
+ flowOwnerDid: ctx.flowOwnerDid,
2950
+ issuerType: ctx.actorType,
2951
+ entityRoomId: ctx.entityRoomId,
2952
+ flowUri: ctx.flowUri,
2953
+ pin: ctx.pin
2954
+ });
2955
+ return { success: true };
2956
+ }
2957
+ case "create_node_delegation":
2958
+ case "backfill_capability": {
2959
+ const capability = {
2960
+ can: "flow/block/execute",
2961
+ with: `${ctx.flowUri}:${item.nodeId}`
2962
+ };
2963
+ await ctx.ucanService.createDelegation({
2964
+ issuerDid: ctx.flowOwnerDid,
2965
+ issuerType: ctx.actorType,
2966
+ entityRoomId: ctx.entityRoomId,
2967
+ audience: ctx.flowOwnerDid,
2968
+ // Owner delegates to self initially; actors get sub-delegations
2969
+ capabilities: [capability],
2970
+ pin: ctx.pin
2971
+ });
2972
+ return { success: true };
2973
+ }
2974
+ default:
2975
+ return { success: false, error: `Unknown work item type: ${item.type}` };
2976
+ }
2977
+ } catch (err) {
2978
+ const message = err instanceof Error ? err.message : String(err);
2979
+ return { success: false, error: message };
2980
+ }
2981
+ },
2982
+ async postValidate(ctx) {
2983
+ const errors = [];
2984
+ const blocks = ctx.editor.document;
2985
+ const rootDelegation = ctx.ucanService.getRootDelegation();
2986
+ if (!rootDelegation) {
2987
+ errors.push("Root delegation is missing after migration");
2988
+ }
2989
+ if (blocks) {
2990
+ for (const block of blocks) {
2991
+ if (NON_EXECUTABLE_BLOCK_TYPES.has(block.type)) continue;
2992
+ const requiredCapability = {
2993
+ can: "flow/block/execute",
2994
+ with: `${ctx.flowUri}:${block.id}`
2995
+ };
2996
+ const validation = await ctx.ucanService.validateDelegationChain(ctx.flowOwnerDid, requiredCapability);
2997
+ if (!validation.valid) {
2998
+ errors.push(`Block "${block.type}" (${block.id}): delegation chain invalid \u2014 ${validation.error || "unknown error"}`);
2999
+ }
3000
+ }
3001
+ }
3002
+ return { valid: errors.length === 0, errors };
3003
+ },
3004
+ finalize(ctx) {
3005
+ const root = ctx.editor._yRoot;
3006
+ if (!root) {
3007
+ throw new Error("Cannot finalize: editor _yRoot not available");
3008
+ }
3009
+ root.set("schema_version", "1.0.0");
3010
+ root.set("@context", "https://ixo.world/flow/1.0");
3011
+ }
3012
+ };
3013
+ registerMigration(migration_0_3_to_1_0_0);
3014
+
2812
3015
  export {
2813
3016
  resolveActionType,
2814
3017
  registerAction,
@@ -2836,6 +3039,7 @@ export {
2836
3039
  createMemoryUcanDelegationStore,
2837
3040
  createInvocationStore,
2838
3041
  createMemoryInvocationStore,
3042
+ LATEST_VERSION,
2839
3043
  buildAuthzFromProps,
2840
3044
  buildFlowNodeFromBlock,
2841
3045
  createRuntimeStateManager,
@@ -2845,4 +3049,4 @@ export {
2845
3049
  executeNode,
2846
3050
  createUcanService
2847
3051
  };
2848
- //# sourceMappingURL=chunk-5D26UG3I.mjs.map
3052
+ //# sourceMappingURL=chunk-3EZI42YS.mjs.map