@ixo/editor 3.2.0 → 3.2.1
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/{chunk-3EZI42YS.mjs → chunk-F2JSGDES.mjs} +577 -570
- package/dist/chunk-F2JSGDES.mjs.map +1 -0
- package/dist/{chunk-BAW3ML7X.mjs → chunk-IQX6H7AK.mjs} +2 -2
- package/dist/{chunk-3MI2QQYH.mjs → chunk-ZCRLP7QH.mjs} +572 -510
- package/dist/chunk-ZCRLP7QH.mjs.map +1 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.mjs +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +3 -3
- package/dist/mantine/index.mjs +2 -2
- package/dist/{setup-Cbd3tcfL.d.ts → setup-B0la8n04.d.ts} +20 -17
- package/package.json +1 -1
- package/dist/chunk-3EZI42YS.mjs.map +0 -1
- package/dist/chunk-3MI2QQYH.mjs.map +0 -1
- /package/dist/{chunk-BAW3ML7X.mjs.map → chunk-IQX6H7AK.mjs.map} +0 -0
|
@@ -1904,97 +1904,408 @@ registerDiffResolver("evaluateClaim", {
|
|
|
1904
1904
|
}
|
|
1905
1905
|
});
|
|
1906
1906
|
|
|
1907
|
-
// src/core/
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1907
|
+
// src/core/services/ucanService.ts
|
|
1908
|
+
import {
|
|
1909
|
+
createDelegation as ucanCreateDelegation,
|
|
1910
|
+
createInvocation as ucanCreateInvocation,
|
|
1911
|
+
serializeDelegation,
|
|
1912
|
+
serializeInvocation,
|
|
1913
|
+
parseDelegation,
|
|
1914
|
+
parseSigner,
|
|
1915
|
+
signerFromMnemonic
|
|
1916
|
+
} from "@ixo/ucan";
|
|
1917
|
+
function toSupportedDID(did) {
|
|
1918
|
+
if (did.startsWith("did:ixo:") || did.startsWith("did:key:")) {
|
|
1919
|
+
return did;
|
|
1920
|
+
}
|
|
1921
|
+
return void 0;
|
|
1922
|
+
}
|
|
1923
|
+
function toUcantoCapabilities(capabilities) {
|
|
1924
|
+
return capabilities.map((cap) => ({
|
|
1925
|
+
can: cap.can,
|
|
1926
|
+
with: cap.with,
|
|
1927
|
+
...cap.nb && { nb: cap.nb }
|
|
1928
|
+
}));
|
|
1929
|
+
}
|
|
1930
|
+
async function getSigner(handlers, did, didType, entityRoomId, pin) {
|
|
1931
|
+
const supportedDid = toSupportedDID(did);
|
|
1932
|
+
if (handlers.getPrivateKey) {
|
|
1933
|
+
const privateKey = await handlers.getPrivateKey({ did, didType, entityRoomId, pin });
|
|
1934
|
+
return parseSigner(privateKey, supportedDid);
|
|
1935
|
+
}
|
|
1936
|
+
if (handlers.getMnemonic) {
|
|
1937
|
+
const mnemonic = await handlers.getMnemonic({ did, didType, entityRoomId, pin });
|
|
1938
|
+
const result = await signerFromMnemonic(mnemonic, supportedDid);
|
|
1939
|
+
return result.signer;
|
|
1940
|
+
}
|
|
1941
|
+
throw new Error("No signer handler configured (need getPrivateKey or getMnemonic)");
|
|
1942
|
+
}
|
|
1943
|
+
function getCidFromDelegation(delegation) {
|
|
1944
|
+
return delegation.cid.toString();
|
|
1945
|
+
}
|
|
1946
|
+
var createUcanService = (config) => {
|
|
1947
|
+
const { delegationStore, invocationStore, handlers, flowOwnerDid } = config;
|
|
1948
|
+
const delegationCache = /* @__PURE__ */ new Map();
|
|
1949
|
+
const isConfigured = () => {
|
|
1950
|
+
const hasSessionHandlers = !!(handlers.createSignerSession && handlers.signWithSession);
|
|
1951
|
+
const hasLegacyHandlers = !!(handlers.getPrivateKey || handlers.getMnemonic);
|
|
1952
|
+
return hasSessionHandlers || hasLegacyHandlers;
|
|
1928
1953
|
};
|
|
1929
|
-
const
|
|
1930
|
-
|
|
1954
|
+
const parseDelegationFromStore = async (cid) => {
|
|
1955
|
+
if (delegationCache.has(cid)) {
|
|
1956
|
+
return delegationCache.get(cid);
|
|
1957
|
+
}
|
|
1958
|
+
const stored = delegationStore.get(cid);
|
|
1959
|
+
if (!stored || !stored.delegation) {
|
|
1960
|
+
return null;
|
|
1961
|
+
}
|
|
1962
|
+
try {
|
|
1963
|
+
const delegation = await parseDelegation(stored.delegation);
|
|
1964
|
+
delegationCache.set(cid, delegation);
|
|
1965
|
+
return delegation;
|
|
1966
|
+
} catch {
|
|
1967
|
+
return null;
|
|
1968
|
+
}
|
|
1931
1969
|
};
|
|
1932
|
-
const
|
|
1933
|
-
|
|
1970
|
+
const getProofDelegations = async (proofCids) => {
|
|
1971
|
+
const proofs = [];
|
|
1972
|
+
for (const cid of proofCids) {
|
|
1973
|
+
const delegation = await parseDelegationFromStore(cid);
|
|
1974
|
+
if (delegation) {
|
|
1975
|
+
proofs.push(delegation);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
return proofs;
|
|
1934
1979
|
};
|
|
1935
|
-
const
|
|
1936
|
-
const
|
|
1937
|
-
|
|
1938
|
-
|
|
1980
|
+
const createRootDelegation = async (params) => {
|
|
1981
|
+
const { flowOwnerDid: ownerDid, issuerType, entityRoomId, flowUri: uri, pin } = params;
|
|
1982
|
+
const signer = await getSigner(handlers, ownerDid, issuerType, entityRoomId, pin);
|
|
1983
|
+
const capabilities = [{ can: "flow/*", with: uri }];
|
|
1984
|
+
const delegation = await ucanCreateDelegation({
|
|
1985
|
+
issuer: signer,
|
|
1986
|
+
audience: ownerDid,
|
|
1987
|
+
capabilities,
|
|
1988
|
+
proofs: []
|
|
1989
|
+
});
|
|
1990
|
+
const serialized = await serializeDelegation(delegation);
|
|
1991
|
+
const cid = getCidFromDelegation(delegation);
|
|
1992
|
+
const storedDelegation = {
|
|
1993
|
+
cid,
|
|
1994
|
+
delegation: serialized,
|
|
1995
|
+
issuerDid: ownerDid,
|
|
1996
|
+
audienceDid: ownerDid,
|
|
1997
|
+
capabilities,
|
|
1998
|
+
createdAt: Date.now(),
|
|
1999
|
+
format: "car",
|
|
2000
|
+
proofCids: []
|
|
2001
|
+
};
|
|
2002
|
+
delegationStore.set(storedDelegation);
|
|
2003
|
+
delegationStore.setRootCid(cid);
|
|
2004
|
+
delegationCache.set(cid, delegation);
|
|
2005
|
+
return storedDelegation;
|
|
1939
2006
|
};
|
|
1940
|
-
const
|
|
1941
|
-
|
|
2007
|
+
const createDelegation = async (params) => {
|
|
2008
|
+
const { issuerDid, issuerType, entityRoomId, audience, capabilities, proofs = [], expiration, pin } = params;
|
|
2009
|
+
const signer = await getSigner(handlers, issuerDid, issuerType, entityRoomId, pin);
|
|
2010
|
+
const proofCids = proofs.length > 0 ? proofs : [delegationStore.getRootCid()].filter(Boolean);
|
|
2011
|
+
const proofDelegations = await getProofDelegations(proofCids);
|
|
2012
|
+
const delegation = await ucanCreateDelegation({
|
|
2013
|
+
issuer: signer,
|
|
2014
|
+
audience,
|
|
2015
|
+
capabilities: toUcantoCapabilities(capabilities),
|
|
2016
|
+
proofs: proofDelegations,
|
|
2017
|
+
expiration: expiration ? Math.floor(expiration / 1e3) : void 0
|
|
2018
|
+
});
|
|
2019
|
+
const serialized = await serializeDelegation(delegation);
|
|
2020
|
+
const cid = getCidFromDelegation(delegation);
|
|
2021
|
+
const storedDelegation = {
|
|
2022
|
+
cid,
|
|
2023
|
+
delegation: serialized,
|
|
2024
|
+
issuerDid,
|
|
2025
|
+
audienceDid: audience,
|
|
2026
|
+
capabilities,
|
|
2027
|
+
expiration,
|
|
2028
|
+
createdAt: Date.now(),
|
|
2029
|
+
format: "car",
|
|
2030
|
+
proofCids
|
|
2031
|
+
};
|
|
2032
|
+
delegationStore.set(storedDelegation);
|
|
2033
|
+
delegationCache.set(cid, delegation);
|
|
2034
|
+
return storedDelegation;
|
|
1942
2035
|
};
|
|
1943
|
-
const
|
|
1944
|
-
|
|
2036
|
+
const revokeDelegation = (cid) => {
|
|
2037
|
+
delegationStore.remove(cid);
|
|
2038
|
+
delegationCache.delete(cid);
|
|
1945
2039
|
};
|
|
1946
|
-
const
|
|
1947
|
-
|
|
1948
|
-
yMap.forEach((value, key) => {
|
|
1949
|
-
if (isReservedKey(key)) return;
|
|
1950
|
-
if (isValidEntry(value)) {
|
|
1951
|
-
delegations.push(value.data);
|
|
1952
|
-
}
|
|
1953
|
-
});
|
|
1954
|
-
return delegations;
|
|
2040
|
+
const getDelegation = (cid) => {
|
|
2041
|
+
return delegationStore.get(cid);
|
|
1955
2042
|
};
|
|
1956
|
-
const
|
|
1957
|
-
return getAll()
|
|
2043
|
+
const getAllDelegations = () => {
|
|
2044
|
+
return delegationStore.getAll();
|
|
1958
2045
|
};
|
|
1959
|
-
const
|
|
1960
|
-
return
|
|
2046
|
+
const getRootDelegation = () => {
|
|
2047
|
+
return delegationStore.getRoot();
|
|
1961
2048
|
};
|
|
1962
|
-
const
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
2049
|
+
const findValidProofs = async (audienceDid, capability) => {
|
|
2050
|
+
const delegations = delegationStore.getByAudience(audienceDid);
|
|
2051
|
+
if (delegations.length === 0) {
|
|
2052
|
+
const root = delegationStore.getRoot();
|
|
2053
|
+
if (root && root.audienceDid === audienceDid) {
|
|
2054
|
+
return { found: true, proofCids: [root.cid] };
|
|
2055
|
+
}
|
|
2056
|
+
return { found: false, error: "No delegations found for actor" };
|
|
2057
|
+
}
|
|
2058
|
+
for (const delegation of delegations) {
|
|
2059
|
+
const covers = delegation.capabilities.some((c) => {
|
|
2060
|
+
if (c.can === capability.can && c.with === capability.with) return true;
|
|
1966
2061
|
if (c.can === "*" || c.can === "flow/*") return true;
|
|
1967
2062
|
if (c.can.endsWith("/*")) {
|
|
1968
2063
|
const prefix = c.can.slice(0, -1);
|
|
1969
|
-
if (can.startsWith(prefix)) return true;
|
|
2064
|
+
if (capability.can.startsWith(prefix)) return true;
|
|
1970
2065
|
}
|
|
1971
2066
|
if (c.with === "*") return true;
|
|
1972
2067
|
if (c.with.endsWith("*")) {
|
|
1973
2068
|
const prefix = c.with.slice(0, -1);
|
|
1974
|
-
if (
|
|
2069
|
+
if (capability.with.startsWith(prefix)) return true;
|
|
1975
2070
|
}
|
|
1976
2071
|
return false;
|
|
1977
|
-
})
|
|
1978
|
-
|
|
2072
|
+
});
|
|
2073
|
+
if (covers) {
|
|
2074
|
+
if (delegation.expiration && delegation.expiration < Date.now()) {
|
|
2075
|
+
continue;
|
|
2076
|
+
}
|
|
2077
|
+
const proofCids = [delegation.cid, ...delegation.proofCids];
|
|
2078
|
+
return { found: true, proofCids };
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
return { found: false, error: "No valid delegation found for capability" };
|
|
1979
2082
|
};
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2083
|
+
const validateDelegationChain = async (audienceDid, capability) => {
|
|
2084
|
+
const proofsResult = await findValidProofs(audienceDid, capability);
|
|
2085
|
+
if (!proofsResult.found || !proofsResult.proofCids) {
|
|
2086
|
+
return { valid: false, error: proofsResult.error };
|
|
2087
|
+
}
|
|
2088
|
+
const proofChain = [];
|
|
2089
|
+
for (const cid of proofsResult.proofCids) {
|
|
2090
|
+
const delegation = delegationStore.get(cid);
|
|
2091
|
+
if (!delegation) {
|
|
2092
|
+
return { valid: false, error: `Proof delegation ${cid} not found` };
|
|
2093
|
+
}
|
|
2094
|
+
proofChain.push(delegation);
|
|
2095
|
+
}
|
|
2096
|
+
for (let i = 0; i < proofChain.length - 1; i++) {
|
|
2097
|
+
const current = proofChain[i];
|
|
2098
|
+
const parent = proofChain[i + 1];
|
|
2099
|
+
if (parent.audienceDid !== current.issuerDid) {
|
|
2100
|
+
return {
|
|
2101
|
+
valid: false,
|
|
2102
|
+
error: `Chain broken: ${parent.cid} audience (${parent.audienceDid}) != ${current.cid} issuer (${current.issuerDid})`
|
|
2103
|
+
};
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
const root = proofChain[proofChain.length - 1];
|
|
2107
|
+
if (root.issuerDid !== flowOwnerDid) {
|
|
2108
|
+
return { valid: false, error: `Root issuer ${root.issuerDid} is not flow owner ${flowOwnerDid}` };
|
|
2109
|
+
}
|
|
2110
|
+
return { valid: true, proofChain };
|
|
1992
2111
|
};
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2112
|
+
const createAndValidateInvocation = async (params, _flowId, _blockId) => {
|
|
2113
|
+
const { invokerDid, invokerType, entityRoomId, capability, proofs, pin } = params;
|
|
2114
|
+
const validation = await validateDelegationChain(invokerDid, capability);
|
|
2115
|
+
if (!validation.valid) {
|
|
2116
|
+
return {
|
|
2117
|
+
cid: "",
|
|
2118
|
+
invocation: "",
|
|
2119
|
+
valid: false,
|
|
2120
|
+
error: validation.error
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
const signer = await getSigner(handlers, invokerDid, invokerType, entityRoomId, pin);
|
|
2124
|
+
const proofDelegations = await getProofDelegations(proofs);
|
|
2125
|
+
const ucantoCapability = {
|
|
2126
|
+
can: capability.can,
|
|
2127
|
+
with: capability.with,
|
|
2128
|
+
...capability.nb && { nb: capability.nb }
|
|
2129
|
+
};
|
|
2130
|
+
const invocation = await ucanCreateInvocation({
|
|
2131
|
+
issuer: signer,
|
|
2132
|
+
audience: flowOwnerDid,
|
|
2133
|
+
capability: ucantoCapability,
|
|
2134
|
+
proofs: proofDelegations
|
|
2135
|
+
});
|
|
2136
|
+
const serialized = await serializeInvocation(invocation);
|
|
2137
|
+
const built = await invocation.buildIPLDView();
|
|
2138
|
+
const cid = built.cid.toString();
|
|
2139
|
+
return {
|
|
2140
|
+
cid,
|
|
2141
|
+
invocation: serialized,
|
|
2142
|
+
valid: true
|
|
2143
|
+
};
|
|
2144
|
+
};
|
|
2145
|
+
const executeWithInvocation = async (params, action, flowId, blockId) => {
|
|
2146
|
+
const invocationResult = await createAndValidateInvocation(params, flowId, blockId);
|
|
2147
|
+
if (!invocationResult.valid) {
|
|
2148
|
+
return {
|
|
2149
|
+
success: false,
|
|
2150
|
+
invocationCid: invocationResult.cid,
|
|
2151
|
+
error: invocationResult.error
|
|
2152
|
+
};
|
|
2153
|
+
}
|
|
2154
|
+
if (invocationStore.hasBeenInvoked(invocationResult.cid)) {
|
|
2155
|
+
return {
|
|
2156
|
+
success: false,
|
|
2157
|
+
invocationCid: invocationResult.cid,
|
|
2158
|
+
error: "Invocation has already been used (replay attack prevented)"
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
try {
|
|
2162
|
+
const actionResult = await action();
|
|
2163
|
+
const storedInvocation = {
|
|
2164
|
+
cid: invocationResult.cid,
|
|
2165
|
+
invocation: invocationResult.invocation,
|
|
2166
|
+
invokerDid: params.invokerDid,
|
|
2167
|
+
capability: params.capability,
|
|
2168
|
+
executedAt: Date.now(),
|
|
2169
|
+
flowId,
|
|
2170
|
+
blockId,
|
|
2171
|
+
result: "success",
|
|
2172
|
+
proofCids: params.proofs
|
|
2173
|
+
};
|
|
2174
|
+
invocationStore.add(storedInvocation);
|
|
2175
|
+
return {
|
|
2176
|
+
success: true,
|
|
2177
|
+
invocationCid: invocationResult.cid,
|
|
2178
|
+
result: actionResult,
|
|
2179
|
+
actionResult
|
|
2180
|
+
};
|
|
2181
|
+
} catch (error) {
|
|
2182
|
+
const storedInvocation = {
|
|
2183
|
+
cid: invocationResult.cid,
|
|
2184
|
+
invocation: invocationResult.invocation,
|
|
2185
|
+
invokerDid: params.invokerDid,
|
|
2186
|
+
capability: params.capability,
|
|
2187
|
+
executedAt: Date.now(),
|
|
2188
|
+
flowId,
|
|
2189
|
+
blockId,
|
|
2190
|
+
result: "failure",
|
|
2191
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
2192
|
+
proofCids: params.proofs
|
|
2193
|
+
};
|
|
2194
|
+
invocationStore.add(storedInvocation);
|
|
2195
|
+
return {
|
|
2196
|
+
success: false,
|
|
2197
|
+
invocationCid: invocationResult.cid,
|
|
2198
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
2199
|
+
};
|
|
2200
|
+
}
|
|
2201
|
+
};
|
|
2202
|
+
return {
|
|
2203
|
+
createRootDelegation,
|
|
2204
|
+
createDelegation,
|
|
2205
|
+
revokeDelegation,
|
|
2206
|
+
getDelegation,
|
|
2207
|
+
getAllDelegations,
|
|
2208
|
+
getRootDelegation,
|
|
2209
|
+
createAndValidateInvocation,
|
|
2210
|
+
executeWithInvocation,
|
|
2211
|
+
validateDelegationChain,
|
|
2212
|
+
findValidProofs,
|
|
2213
|
+
parseDelegationFromStore,
|
|
2214
|
+
isConfigured
|
|
2215
|
+
};
|
|
2216
|
+
};
|
|
2217
|
+
|
|
2218
|
+
// src/core/lib/ucanDelegationStore.ts
|
|
2219
|
+
var ROOT_DELEGATION_KEY = "__root__";
|
|
2220
|
+
var STORE_VERSION_KEY = "__version__";
|
|
2221
|
+
var CURRENT_VERSION = 2;
|
|
2222
|
+
var isValidEntry = (value) => {
|
|
2223
|
+
if (!value || typeof value !== "object") return false;
|
|
2224
|
+
const entry = value;
|
|
2225
|
+
return entry.v === CURRENT_VERSION && entry.data !== void 0;
|
|
2226
|
+
};
|
|
2227
|
+
var isReservedKey = (key) => key === ROOT_DELEGATION_KEY || key === STORE_VERSION_KEY;
|
|
2228
|
+
var createUcanDelegationStore = (yMap) => {
|
|
2229
|
+
const get = (cid) => {
|
|
2230
|
+
if (isReservedKey(cid)) return null;
|
|
2231
|
+
const raw = yMap.get(cid);
|
|
2232
|
+
if (!raw) return null;
|
|
2233
|
+
if (isValidEntry(raw)) return raw.data;
|
|
2234
|
+
return null;
|
|
2235
|
+
};
|
|
2236
|
+
const set = (delegation) => {
|
|
2237
|
+
const entry = { v: CURRENT_VERSION, data: delegation };
|
|
2238
|
+
yMap.set(delegation.cid, entry);
|
|
2239
|
+
};
|
|
2240
|
+
const remove = (cid) => {
|
|
2241
|
+
yMap.delete(cid);
|
|
2242
|
+
};
|
|
2243
|
+
const has = (cid) => {
|
|
2244
|
+
return yMap.has(cid) && !isReservedKey(cid);
|
|
2245
|
+
};
|
|
2246
|
+
const getRoot = () => {
|
|
2247
|
+
const rootCid = yMap.get(ROOT_DELEGATION_KEY);
|
|
2248
|
+
if (!rootCid) return null;
|
|
2249
|
+
return get(rootCid);
|
|
2250
|
+
};
|
|
2251
|
+
const setRootCid = (cid) => {
|
|
2252
|
+
yMap.set(ROOT_DELEGATION_KEY, cid);
|
|
2253
|
+
};
|
|
2254
|
+
const getRootCid = () => {
|
|
2255
|
+
return yMap.get(ROOT_DELEGATION_KEY) || null;
|
|
2256
|
+
};
|
|
2257
|
+
const getAll = () => {
|
|
2258
|
+
const delegations = [];
|
|
2259
|
+
yMap.forEach((value, key) => {
|
|
2260
|
+
if (isReservedKey(key)) return;
|
|
2261
|
+
if (isValidEntry(value)) {
|
|
2262
|
+
delegations.push(value.data);
|
|
2263
|
+
}
|
|
2264
|
+
});
|
|
2265
|
+
return delegations;
|
|
2266
|
+
};
|
|
2267
|
+
const getByAudience = (audienceDid) => {
|
|
2268
|
+
return getAll().filter((d) => d.audienceDid === audienceDid);
|
|
2269
|
+
};
|
|
2270
|
+
const getByIssuer = (issuerDid) => {
|
|
2271
|
+
return getAll().filter((d) => d.issuerDid === issuerDid);
|
|
2272
|
+
};
|
|
2273
|
+
const findByCapability = (can, withUri) => {
|
|
2274
|
+
return getAll().filter(
|
|
2275
|
+
(d) => d.capabilities.some((c) => {
|
|
2276
|
+
if (c.can === can && c.with === withUri) return true;
|
|
2277
|
+
if (c.can === "*" || c.can === "flow/*") return true;
|
|
2278
|
+
if (c.can.endsWith("/*")) {
|
|
2279
|
+
const prefix = c.can.slice(0, -1);
|
|
2280
|
+
if (can.startsWith(prefix)) return true;
|
|
2281
|
+
}
|
|
2282
|
+
if (c.with === "*") return true;
|
|
2283
|
+
if (c.with.endsWith("*")) {
|
|
2284
|
+
const prefix = c.with.slice(0, -1);
|
|
2285
|
+
if (withUri.startsWith(prefix)) return true;
|
|
2286
|
+
}
|
|
2287
|
+
return false;
|
|
2288
|
+
})
|
|
2289
|
+
);
|
|
2290
|
+
};
|
|
2291
|
+
return {
|
|
2292
|
+
get,
|
|
2293
|
+
set,
|
|
2294
|
+
remove,
|
|
2295
|
+
has,
|
|
2296
|
+
getRoot,
|
|
2297
|
+
setRootCid,
|
|
2298
|
+
getRootCid,
|
|
2299
|
+
getAll,
|
|
2300
|
+
getByAudience,
|
|
2301
|
+
getByIssuer,
|
|
2302
|
+
findByCapability
|
|
2303
|
+
};
|
|
2304
|
+
};
|
|
2305
|
+
var createMemoryUcanDelegationStore = () => {
|
|
2306
|
+
const store = /* @__PURE__ */ new Map();
|
|
2307
|
+
const get = (cid) => {
|
|
2308
|
+
if (isReservedKey(cid)) return null;
|
|
1998
2309
|
const raw = store.get(cid);
|
|
1999
2310
|
if (!raw) return null;
|
|
2000
2311
|
if (isValidEntry(raw)) return raw.data;
|
|
@@ -2346,523 +2657,219 @@ var isNodeActive = (node, runtime) => {
|
|
|
2346
2657
|
}
|
|
2347
2658
|
}
|
|
2348
2659
|
return { active: true };
|
|
2349
|
-
};
|
|
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
|
-
|
|
2401
|
-
// src/core/lib/flowEngine/authorization.ts
|
|
2402
|
-
var isAuthorized = async (blockId, actorDid, ucanService, flowUri, schemaVersion) => {
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
can: "flow/block/execute",
|
|
2411
|
-
with: `${flowUri}:${blockId}`
|
|
2412
|
-
};
|
|
2413
|
-
const result = await ucanService.validateDelegationChain(actorDid, capability);
|
|
2414
|
-
if (!result.valid) {
|
|
2415
|
-
return {
|
|
2416
|
-
authorized: false,
|
|
2417
|
-
reason: result.error || "No valid capability chain found"
|
|
2418
|
-
};
|
|
2419
|
-
}
|
|
2420
|
-
const proofCids = result.proofChain?.map((d) => d.cid) || [];
|
|
2421
|
-
return {
|
|
2422
|
-
authorized: true,
|
|
2423
|
-
capabilityId: proofCids[0],
|
|
2424
|
-
proofCids
|
|
2425
|
-
};
|
|
2426
|
-
};
|
|
2427
|
-
|
|
2428
|
-
// src/core/lib/flowEngine/executor.ts
|
|
2429
|
-
var updateRuntimeAfterSuccess = (node, actorDid, runtime, actionResult, invocationCid, now) => {
|
|
2430
|
-
const updates = {
|
|
2431
|
-
submittedByDid: actionResult.submittedByDid || actorDid,
|
|
2432
|
-
evaluationStatus: actionResult.evaluationStatus || "pending",
|
|
2433
|
-
executionTimestamp: now ? now() : Date.now(),
|
|
2434
|
-
lastInvocationCid: invocationCid
|
|
2435
|
-
};
|
|
2436
|
-
if (actionResult.claimId) {
|
|
2437
|
-
updates.claimId = actionResult.claimId;
|
|
2438
|
-
}
|
|
2439
|
-
runtime.update(node.id, updates);
|
|
2440
|
-
};
|
|
2441
|
-
var executeNode = async ({ node, actorDid, actorType, entityRoomId, context, action, pin }) => {
|
|
2442
|
-
const { runtime, ucanService, invocationStore, flowUri, flowId, now } = context;
|
|
2443
|
-
const activation = isNodeActive(node, runtime);
|
|
2444
|
-
if (!activation.active) {
|
|
2445
|
-
return { success: false, stage: "activation", error: activation.reason };
|
|
2446
|
-
}
|
|
2447
|
-
const auth = await isAuthorized(node.id, actorDid, ucanService, flowUri);
|
|
2448
|
-
if (!auth.authorized) {
|
|
2449
|
-
return { success: false, stage: "authorization", error: auth.reason };
|
|
2450
|
-
}
|
|
2451
|
-
if (node.linkedClaim && !node.linkedClaim.collectionId) {
|
|
2452
|
-
return { success: false, stage: "claim", error: "Linked claim collection is required but missing." };
|
|
2453
|
-
}
|
|
2454
|
-
let invocationCid;
|
|
2455
|
-
let invocationData;
|
|
2456
|
-
if (auth.proofCids && auth.proofCids.length > 0) {
|
|
2457
|
-
const capability = {
|
|
2458
|
-
can: "flow/block/execute",
|
|
2459
|
-
with: `${flowUri}:${node.id}`
|
|
2460
|
-
};
|
|
2461
|
-
try {
|
|
2462
|
-
const invocationResult = await ucanService.createAndValidateInvocation(
|
|
2463
|
-
{
|
|
2464
|
-
invokerDid: actorDid,
|
|
2465
|
-
invokerType: actorType,
|
|
2466
|
-
entityRoomId,
|
|
2467
|
-
capability,
|
|
2468
|
-
proofs: auth.proofCids,
|
|
2469
|
-
pin
|
|
2470
|
-
},
|
|
2471
|
-
flowId,
|
|
2472
|
-
node.id
|
|
2473
|
-
);
|
|
2474
|
-
if (!invocationResult.valid) {
|
|
2475
|
-
return {
|
|
2476
|
-
success: false,
|
|
2477
|
-
stage: "authorization",
|
|
2478
|
-
error: `Invocation validation failed: ${invocationResult.error}`
|
|
2479
|
-
};
|
|
2480
|
-
}
|
|
2481
|
-
invocationCid = invocationResult.cid;
|
|
2482
|
-
invocationData = invocationResult.invocation;
|
|
2483
|
-
} catch (error) {
|
|
2484
|
-
const message = error instanceof Error ? error.message : "Failed to create invocation";
|
|
2485
|
-
return { success: false, stage: "authorization", error: message };
|
|
2486
|
-
}
|
|
2487
|
-
}
|
|
2488
|
-
try {
|
|
2489
|
-
const result = await action();
|
|
2490
|
-
if (node.linkedClaim && !result.claimId) {
|
|
2491
|
-
if (invocationStore && invocationCid && invocationData) {
|
|
2492
|
-
const storedInvocation = {
|
|
2493
|
-
cid: invocationCid,
|
|
2494
|
-
invocation: invocationData,
|
|
2495
|
-
invokerDid: actorDid,
|
|
2496
|
-
capability: { can: "flow/block/execute", with: `${flowUri}:${node.id}` },
|
|
2497
|
-
executedAt: now ? now() : Date.now(),
|
|
2498
|
-
flowId,
|
|
2499
|
-
blockId: node.id,
|
|
2500
|
-
result: "failure",
|
|
2501
|
-
error: "Execution did not return a claimId for linked claim requirement.",
|
|
2502
|
-
proofCids: auth.proofCids || []
|
|
2503
|
-
};
|
|
2504
|
-
invocationStore.add(storedInvocation);
|
|
2505
|
-
}
|
|
2506
|
-
return {
|
|
2507
|
-
success: false,
|
|
2508
|
-
stage: "claim",
|
|
2509
|
-
error: "Execution did not return a claimId for linked claim requirement.",
|
|
2510
|
-
invocationCid
|
|
2511
|
-
};
|
|
2512
|
-
}
|
|
2513
|
-
if (invocationStore && invocationCid && invocationData) {
|
|
2514
|
-
const storedInvocation = {
|
|
2515
|
-
cid: invocationCid,
|
|
2516
|
-
invocation: invocationData,
|
|
2517
|
-
invokerDid: actorDid,
|
|
2518
|
-
capability: { can: "flow/block/execute", with: `${flowUri}:${node.id}` },
|
|
2519
|
-
executedAt: now ? now() : Date.now(),
|
|
2520
|
-
flowId,
|
|
2521
|
-
blockId: node.id,
|
|
2522
|
-
result: "success",
|
|
2523
|
-
proofCids: auth.proofCids || [],
|
|
2524
|
-
claimId: result.claimId
|
|
2525
|
-
};
|
|
2526
|
-
invocationStore.add(storedInvocation);
|
|
2527
|
-
}
|
|
2528
|
-
updateRuntimeAfterSuccess(node, actorDid, runtime, result, invocationCid || auth.capabilityId, now);
|
|
2529
|
-
return {
|
|
2530
|
-
success: true,
|
|
2531
|
-
stage: "complete",
|
|
2532
|
-
result,
|
|
2533
|
-
capabilityId: auth.capabilityId,
|
|
2534
|
-
invocationCid
|
|
2535
|
-
};
|
|
2536
|
-
} catch (error) {
|
|
2537
|
-
const message = error instanceof Error ? error.message : "Execution failed";
|
|
2538
|
-
if (invocationStore && invocationCid && invocationData) {
|
|
2539
|
-
const storedInvocation = {
|
|
2540
|
-
cid: invocationCid,
|
|
2541
|
-
invocation: invocationData,
|
|
2542
|
-
invokerDid: actorDid,
|
|
2543
|
-
capability: { can: "flow/block/execute", with: `${flowUri}:${node.id}` },
|
|
2544
|
-
executedAt: now ? now() : Date.now(),
|
|
2545
|
-
flowId,
|
|
2546
|
-
blockId: node.id,
|
|
2547
|
-
result: "failure",
|
|
2548
|
-
error: message,
|
|
2549
|
-
proofCids: auth.proofCids || []
|
|
2550
|
-
};
|
|
2551
|
-
invocationStore.add(storedInvocation);
|
|
2552
|
-
}
|
|
2553
|
-
return { success: false, stage: "action", error: message, invocationCid };
|
|
2554
|
-
}
|
|
2555
|
-
};
|
|
2556
|
-
|
|
2557
|
-
// src/core/services/ucanService.ts
|
|
2558
|
-
import {
|
|
2559
|
-
createDelegation as ucanCreateDelegation,
|
|
2560
|
-
createInvocation as ucanCreateInvocation,
|
|
2561
|
-
serializeDelegation,
|
|
2562
|
-
serializeInvocation,
|
|
2563
|
-
parseDelegation,
|
|
2564
|
-
parseSigner,
|
|
2565
|
-
signerFromMnemonic
|
|
2566
|
-
} from "@ixo/ucan";
|
|
2567
|
-
function toSupportedDID(did) {
|
|
2568
|
-
if (did.startsWith("did:ixo:") || did.startsWith("did:key:")) {
|
|
2569
|
-
return did;
|
|
2570
|
-
}
|
|
2571
|
-
return void 0;
|
|
2572
|
-
}
|
|
2573
|
-
function toUcantoCapabilities(capabilities) {
|
|
2574
|
-
return capabilities.map((cap) => ({
|
|
2575
|
-
can: cap.can,
|
|
2576
|
-
with: cap.with,
|
|
2577
|
-
...cap.nb && { nb: cap.nb }
|
|
2578
|
-
}));
|
|
2579
|
-
}
|
|
2580
|
-
async function getSigner(handlers, did, didType, entityRoomId, pin) {
|
|
2581
|
-
const supportedDid = toSupportedDID(did);
|
|
2582
|
-
if (handlers.getPrivateKey) {
|
|
2583
|
-
const privateKey = await handlers.getPrivateKey({ did, didType, entityRoomId, pin });
|
|
2584
|
-
return parseSigner(privateKey, supportedDid);
|
|
2585
|
-
}
|
|
2586
|
-
if (handlers.getMnemonic) {
|
|
2587
|
-
const mnemonic = await handlers.getMnemonic({ did, didType, entityRoomId, pin });
|
|
2588
|
-
const result = await signerFromMnemonic(mnemonic, supportedDid);
|
|
2589
|
-
return result.signer;
|
|
2590
|
-
}
|
|
2591
|
-
throw new Error("No signer handler configured (need getPrivateKey or getMnemonic)");
|
|
2592
|
-
}
|
|
2593
|
-
function getCidFromDelegation(delegation) {
|
|
2594
|
-
return delegation.cid.toString();
|
|
2595
|
-
}
|
|
2596
|
-
var createUcanService = (config) => {
|
|
2597
|
-
const { delegationStore, invocationStore, handlers, flowOwnerDid } = config;
|
|
2598
|
-
const delegationCache = /* @__PURE__ */ new Map();
|
|
2599
|
-
const isConfigured = () => {
|
|
2600
|
-
const hasSessionHandlers = !!(handlers.createSignerSession && handlers.signWithSession);
|
|
2601
|
-
const hasLegacyHandlers = !!(handlers.getPrivateKey || handlers.getMnemonic);
|
|
2602
|
-
return hasSessionHandlers || hasLegacyHandlers;
|
|
2603
|
-
};
|
|
2604
|
-
const parseDelegationFromStore = async (cid) => {
|
|
2605
|
-
if (delegationCache.has(cid)) {
|
|
2606
|
-
return delegationCache.get(cid);
|
|
2607
|
-
}
|
|
2608
|
-
const stored = delegationStore.get(cid);
|
|
2609
|
-
if (!stored || !stored.delegation) {
|
|
2610
|
-
return null;
|
|
2611
|
-
}
|
|
2612
|
-
try {
|
|
2613
|
-
const delegation = await parseDelegation(stored.delegation);
|
|
2614
|
-
delegationCache.set(cid, delegation);
|
|
2615
|
-
return delegation;
|
|
2616
|
-
} catch {
|
|
2617
|
-
return null;
|
|
2618
|
-
}
|
|
2619
|
-
};
|
|
2620
|
-
const getProofDelegations = async (proofCids) => {
|
|
2621
|
-
const proofs = [];
|
|
2622
|
-
for (const cid of proofCids) {
|
|
2623
|
-
const delegation = await parseDelegationFromStore(cid);
|
|
2624
|
-
if (delegation) {
|
|
2625
|
-
proofs.push(delegation);
|
|
2626
|
-
}
|
|
2627
|
-
}
|
|
2628
|
-
return proofs;
|
|
2629
|
-
};
|
|
2630
|
-
const createRootDelegation = async (params) => {
|
|
2631
|
-
const { flowOwnerDid: ownerDid, issuerType, entityRoomId, flowUri: uri, pin } = params;
|
|
2632
|
-
const signer = await getSigner(handlers, ownerDid, issuerType, entityRoomId, pin);
|
|
2633
|
-
const capabilities = [{ can: "flow/*", with: uri }];
|
|
2634
|
-
const delegation = await ucanCreateDelegation({
|
|
2635
|
-
issuer: signer,
|
|
2636
|
-
audience: ownerDid,
|
|
2637
|
-
capabilities,
|
|
2638
|
-
proofs: []
|
|
2639
|
-
});
|
|
2640
|
-
const serialized = await serializeDelegation(delegation);
|
|
2641
|
-
const cid = getCidFromDelegation(delegation);
|
|
2642
|
-
const storedDelegation = {
|
|
2643
|
-
cid,
|
|
2644
|
-
delegation: serialized,
|
|
2645
|
-
issuerDid: ownerDid,
|
|
2646
|
-
audienceDid: ownerDid,
|
|
2647
|
-
capabilities,
|
|
2648
|
-
createdAt: Date.now(),
|
|
2649
|
-
format: "car",
|
|
2650
|
-
proofCids: []
|
|
2651
|
-
};
|
|
2652
|
-
delegationStore.set(storedDelegation);
|
|
2653
|
-
delegationStore.setRootCid(cid);
|
|
2654
|
-
delegationCache.set(cid, delegation);
|
|
2655
|
-
return storedDelegation;
|
|
2656
|
-
};
|
|
2657
|
-
const createDelegation = async (params) => {
|
|
2658
|
-
const { issuerDid, issuerType, entityRoomId, audience, capabilities, proofs = [], expiration, pin } = params;
|
|
2659
|
-
const signer = await getSigner(handlers, issuerDid, issuerType, entityRoomId, pin);
|
|
2660
|
-
const proofCids = proofs.length > 0 ? proofs : [delegationStore.getRootCid()].filter(Boolean);
|
|
2661
|
-
const proofDelegations = await getProofDelegations(proofCids);
|
|
2662
|
-
const delegation = await ucanCreateDelegation({
|
|
2663
|
-
issuer: signer,
|
|
2664
|
-
audience,
|
|
2665
|
-
capabilities: toUcantoCapabilities(capabilities),
|
|
2666
|
-
proofs: proofDelegations,
|
|
2667
|
-
expiration: expiration ? Math.floor(expiration / 1e3) : void 0
|
|
2668
|
-
});
|
|
2669
|
-
const serialized = await serializeDelegation(delegation);
|
|
2670
|
-
const cid = getCidFromDelegation(delegation);
|
|
2671
|
-
const storedDelegation = {
|
|
2672
|
-
cid,
|
|
2673
|
-
delegation: serialized,
|
|
2674
|
-
issuerDid,
|
|
2675
|
-
audienceDid: audience,
|
|
2676
|
-
capabilities,
|
|
2677
|
-
expiration,
|
|
2678
|
-
createdAt: Date.now(),
|
|
2679
|
-
format: "car",
|
|
2680
|
-
proofCids
|
|
2681
|
-
};
|
|
2682
|
-
delegationStore.set(storedDelegation);
|
|
2683
|
-
delegationCache.set(cid, delegation);
|
|
2684
|
-
return storedDelegation;
|
|
2685
|
-
};
|
|
2686
|
-
const revokeDelegation = (cid) => {
|
|
2687
|
-
delegationStore.remove(cid);
|
|
2688
|
-
delegationCache.delete(cid);
|
|
2689
|
-
};
|
|
2690
|
-
const getDelegation = (cid) => {
|
|
2691
|
-
return delegationStore.get(cid);
|
|
2692
|
-
};
|
|
2693
|
-
const getAllDelegations = () => {
|
|
2694
|
-
return delegationStore.getAll();
|
|
2695
|
-
};
|
|
2696
|
-
const getRootDelegation = () => {
|
|
2697
|
-
return delegationStore.getRoot();
|
|
2698
|
-
};
|
|
2699
|
-
const findValidProofs = async (audienceDid, capability) => {
|
|
2700
|
-
const delegations = delegationStore.getByAudience(audienceDid);
|
|
2701
|
-
if (delegations.length === 0) {
|
|
2702
|
-
const root = delegationStore.getRoot();
|
|
2703
|
-
if (root && root.audienceDid === audienceDid) {
|
|
2704
|
-
return { found: true, proofCids: [root.cid] };
|
|
2705
|
-
}
|
|
2706
|
-
return { found: false, error: "No delegations found for actor" };
|
|
2707
|
-
}
|
|
2708
|
-
for (const delegation of delegations) {
|
|
2709
|
-
const covers = delegation.capabilities.some((c) => {
|
|
2710
|
-
if (c.can === capability.can && c.with === capability.with) return true;
|
|
2711
|
-
if (c.can === "*" || c.can === "flow/*") return true;
|
|
2712
|
-
if (c.can.endsWith("/*")) {
|
|
2713
|
-
const prefix = c.can.slice(0, -1);
|
|
2714
|
-
if (capability.can.startsWith(prefix)) return true;
|
|
2715
|
-
}
|
|
2716
|
-
if (c.with === "*") return true;
|
|
2717
|
-
if (c.with.endsWith("*")) {
|
|
2718
|
-
const prefix = c.with.slice(0, -1);
|
|
2719
|
-
if (capability.with.startsWith(prefix)) return true;
|
|
2720
|
-
}
|
|
2721
|
-
return false;
|
|
2722
|
-
});
|
|
2723
|
-
if (covers) {
|
|
2724
|
-
if (delegation.expiration && delegation.expiration < Date.now()) {
|
|
2725
|
-
continue;
|
|
2726
|
-
}
|
|
2727
|
-
const proofCids = [delegation.cid, ...delegation.proofCids];
|
|
2728
|
-
return { found: true, proofCids };
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
return { found: false, error: "No valid delegation found for capability" };
|
|
2732
|
-
};
|
|
2733
|
-
const validateDelegationChain = async (audienceDid, capability) => {
|
|
2734
|
-
const proofsResult = await findValidProofs(audienceDid, capability);
|
|
2735
|
-
if (!proofsResult.found || !proofsResult.proofCids) {
|
|
2736
|
-
return { valid: false, error: proofsResult.error };
|
|
2737
|
-
}
|
|
2738
|
-
const proofChain = [];
|
|
2739
|
-
for (const cid of proofsResult.proofCids) {
|
|
2740
|
-
const delegation = delegationStore.get(cid);
|
|
2741
|
-
if (!delegation) {
|
|
2742
|
-
return { valid: false, error: `Proof delegation ${cid} not found` };
|
|
2743
|
-
}
|
|
2744
|
-
proofChain.push(delegation);
|
|
2745
|
-
}
|
|
2746
|
-
for (let i = 0; i < proofChain.length - 1; i++) {
|
|
2747
|
-
const current = proofChain[i];
|
|
2748
|
-
const parent = proofChain[i + 1];
|
|
2749
|
-
if (parent.audienceDid !== current.issuerDid) {
|
|
2750
|
-
return {
|
|
2751
|
-
valid: false,
|
|
2752
|
-
error: `Chain broken: ${parent.cid} audience (${parent.audienceDid}) != ${current.cid} issuer (${current.issuerDid})`
|
|
2753
|
-
};
|
|
2754
|
-
}
|
|
2755
|
-
}
|
|
2756
|
-
const root = proofChain[proofChain.length - 1];
|
|
2757
|
-
if (root.issuerDid !== flowOwnerDid) {
|
|
2758
|
-
return { valid: false, error: `Root issuer ${root.issuerDid} is not flow owner ${flowOwnerDid}` };
|
|
2759
|
-
}
|
|
2760
|
-
return { valid: true, proofChain };
|
|
2761
|
-
};
|
|
2762
|
-
const createAndValidateInvocation = async (params, _flowId, _blockId) => {
|
|
2763
|
-
const { invokerDid, invokerType, entityRoomId, capability, proofs, pin } = params;
|
|
2764
|
-
const validation = await validateDelegationChain(invokerDid, capability);
|
|
2765
|
-
if (!validation.valid) {
|
|
2766
|
-
return {
|
|
2767
|
-
cid: "",
|
|
2768
|
-
invocation: "",
|
|
2769
|
-
valid: false,
|
|
2770
|
-
error: validation.error
|
|
2771
|
-
};
|
|
2660
|
+
};
|
|
2661
|
+
|
|
2662
|
+
// src/core/lib/flowEngine/versionManifest.ts
|
|
2663
|
+
var VERSION_MANIFEST = {
|
|
2664
|
+
"0.3": {
|
|
2665
|
+
version: "0.3",
|
|
2666
|
+
label: "Legacy",
|
|
2667
|
+
ucanRequired: false,
|
|
2668
|
+
delegationRootRequired: false,
|
|
2669
|
+
whitelistOnlyAllowed: true,
|
|
2670
|
+
unrestrictedAllowed: true,
|
|
2671
|
+
executionPath: "legacy",
|
|
2672
|
+
authorizationFn: "v1",
|
|
2673
|
+
allowedAuthModes: ["anyone", "actors", "capability"],
|
|
2674
|
+
ui: {
|
|
2675
|
+
showDelegationPanel: false,
|
|
2676
|
+
showWhitelistConfig: true,
|
|
2677
|
+
showAnyoneConfig: true,
|
|
2678
|
+
showMigrationBanner: true,
|
|
2679
|
+
requirePinForExecution: false
|
|
2680
|
+
},
|
|
2681
|
+
description: "Legacy version. UCAN optional, whitelist-only authorization accepted."
|
|
2682
|
+
},
|
|
2683
|
+
"1.0.0": {
|
|
2684
|
+
version: "1.0.0",
|
|
2685
|
+
label: "UCAN Required",
|
|
2686
|
+
ucanRequired: true,
|
|
2687
|
+
delegationRootRequired: true,
|
|
2688
|
+
whitelistOnlyAllowed: false,
|
|
2689
|
+
unrestrictedAllowed: false,
|
|
2690
|
+
executionPath: "invocation",
|
|
2691
|
+
authorizationFn: "v2",
|
|
2692
|
+
allowedAuthModes: ["capability"],
|
|
2693
|
+
ui: {
|
|
2694
|
+
showDelegationPanel: true,
|
|
2695
|
+
showWhitelistConfig: false,
|
|
2696
|
+
showAnyoneConfig: false,
|
|
2697
|
+
showMigrationBanner: false,
|
|
2698
|
+
requirePinForExecution: true
|
|
2699
|
+
},
|
|
2700
|
+
description: "UCAN-enforced. Every block execution requires a valid delegation chain."
|
|
2701
|
+
}
|
|
2702
|
+
};
|
|
2703
|
+
var LATEST_VERSION = "1.0.0";
|
|
2704
|
+
function getVersionPolicy(version) {
|
|
2705
|
+
const policy = VERSION_MANIFEST[version];
|
|
2706
|
+
if (!policy) {
|
|
2707
|
+
return VERSION_MANIFEST[LATEST_VERSION];
|
|
2708
|
+
}
|
|
2709
|
+
return policy;
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2712
|
+
// src/core/lib/flowEngine/authorization.ts
|
|
2713
|
+
var isAuthorized = async (blockId, actorDid, ucanService, flowUri, schemaVersion) => {
|
|
2714
|
+
const policy = schemaVersion ? getVersionPolicy(schemaVersion) : null;
|
|
2715
|
+
if (policy && !policy.ucanRequired) {
|
|
2716
|
+
return { authorized: true };
|
|
2717
|
+
}
|
|
2718
|
+
if (!ucanService) {
|
|
2719
|
+
if (!policy) {
|
|
2720
|
+
return { authorized: true };
|
|
2772
2721
|
}
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
can: capability.can,
|
|
2777
|
-
with: capability.with,
|
|
2778
|
-
...capability.nb && { nb: capability.nb }
|
|
2722
|
+
return {
|
|
2723
|
+
authorized: false,
|
|
2724
|
+
reason: "UCAN service is not configured. This flow version requires UCAN authorization."
|
|
2779
2725
|
};
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
const built = await invocation.buildIPLDView();
|
|
2788
|
-
const cid = built.cid.toString();
|
|
2726
|
+
}
|
|
2727
|
+
const capability = {
|
|
2728
|
+
can: "flow/block/execute",
|
|
2729
|
+
with: `${flowUri}:${blockId}`
|
|
2730
|
+
};
|
|
2731
|
+
const result = await ucanService.validateDelegationChain(actorDid, capability);
|
|
2732
|
+
if (!result.valid) {
|
|
2789
2733
|
return {
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
valid: true
|
|
2734
|
+
authorized: false,
|
|
2735
|
+
reason: result.error || "No valid capability chain found"
|
|
2793
2736
|
};
|
|
2737
|
+
}
|
|
2738
|
+
const proofCids = result.proofChain?.map((d) => d.cid) || [];
|
|
2739
|
+
return {
|
|
2740
|
+
authorized: true,
|
|
2741
|
+
capabilityId: proofCids[0],
|
|
2742
|
+
proofCids
|
|
2794
2743
|
};
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2744
|
+
};
|
|
2745
|
+
|
|
2746
|
+
// src/core/lib/flowEngine/executor.ts
|
|
2747
|
+
var updateRuntimeAfterSuccess = (node, actorDid, runtime, actionResult, invocationCid, now) => {
|
|
2748
|
+
const updates = {
|
|
2749
|
+
submittedByDid: actionResult.submittedByDid || actorDid,
|
|
2750
|
+
evaluationStatus: actionResult.evaluationStatus || "pending",
|
|
2751
|
+
executionTimestamp: now ? now() : Date.now(),
|
|
2752
|
+
lastInvocationCid: invocationCid
|
|
2753
|
+
};
|
|
2754
|
+
if (actionResult.claimId) {
|
|
2755
|
+
updates.claimId = actionResult.claimId;
|
|
2756
|
+
}
|
|
2757
|
+
runtime.update(node.id, updates);
|
|
2758
|
+
};
|
|
2759
|
+
var executeNode = async ({ node, actorDid, actorType, entityRoomId, context, action, pin }) => {
|
|
2760
|
+
const { runtime, ucanService, invocationStore, flowUri, flowId, schemaVersion, now } = context;
|
|
2761
|
+
const activation = isNodeActive(node, runtime);
|
|
2762
|
+
if (!activation.active) {
|
|
2763
|
+
return { success: false, stage: "activation", error: activation.reason };
|
|
2764
|
+
}
|
|
2765
|
+
const auth = await isAuthorized(node.id, actorDid, ucanService, flowUri, schemaVersion);
|
|
2766
|
+
if (!auth.authorized) {
|
|
2767
|
+
return { success: false, stage: "authorization", error: auth.reason };
|
|
2768
|
+
}
|
|
2769
|
+
if (node.linkedClaim && !node.linkedClaim.collectionId) {
|
|
2770
|
+
return { success: false, stage: "claim", error: "Linked claim collection is required but missing." };
|
|
2771
|
+
}
|
|
2772
|
+
let invocationCid;
|
|
2773
|
+
let invocationData;
|
|
2774
|
+
if (ucanService && auth.proofCids && auth.proofCids.length > 0) {
|
|
2775
|
+
const capability = {
|
|
2776
|
+
can: "flow/block/execute",
|
|
2777
|
+
with: `${flowUri}:${node.id}`
|
|
2778
|
+
};
|
|
2779
|
+
try {
|
|
2780
|
+
const invocationResult = await ucanService.createAndValidateInvocation(
|
|
2781
|
+
{
|
|
2782
|
+
invokerDid: actorDid,
|
|
2783
|
+
invokerType: actorType,
|
|
2784
|
+
entityRoomId,
|
|
2785
|
+
capability,
|
|
2786
|
+
proofs: auth.proofCids,
|
|
2787
|
+
pin
|
|
2788
|
+
},
|
|
2789
|
+
flowId,
|
|
2790
|
+
node.id
|
|
2791
|
+
);
|
|
2792
|
+
if (!invocationResult.valid) {
|
|
2793
|
+
return {
|
|
2794
|
+
success: false,
|
|
2795
|
+
stage: "authorization",
|
|
2796
|
+
error: `Invocation validation failed: ${invocationResult.error}`
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
invocationCid = invocationResult.cid;
|
|
2800
|
+
invocationData = invocationResult.invocation;
|
|
2801
|
+
} catch (error) {
|
|
2802
|
+
const message = error instanceof Error ? error.message : "Failed to create invocation";
|
|
2803
|
+
return { success: false, stage: "authorization", error: message };
|
|
2803
2804
|
}
|
|
2804
|
-
|
|
2805
|
+
}
|
|
2806
|
+
try {
|
|
2807
|
+
const result = await action();
|
|
2808
|
+
if (node.linkedClaim && !result.claimId) {
|
|
2809
|
+
if (invocationStore && invocationCid && invocationData) {
|
|
2810
|
+
const storedInvocation = {
|
|
2811
|
+
cid: invocationCid,
|
|
2812
|
+
invocation: invocationData,
|
|
2813
|
+
invokerDid: actorDid,
|
|
2814
|
+
capability: { can: "flow/block/execute", with: `${flowUri}:${node.id}` },
|
|
2815
|
+
executedAt: now ? now() : Date.now(),
|
|
2816
|
+
flowId,
|
|
2817
|
+
blockId: node.id,
|
|
2818
|
+
result: "failure",
|
|
2819
|
+
error: "Execution did not return a claimId for linked claim requirement.",
|
|
2820
|
+
proofCids: auth.proofCids || []
|
|
2821
|
+
};
|
|
2822
|
+
invocationStore.add(storedInvocation);
|
|
2823
|
+
}
|
|
2805
2824
|
return {
|
|
2806
2825
|
success: false,
|
|
2807
|
-
|
|
2808
|
-
error: "
|
|
2826
|
+
stage: "claim",
|
|
2827
|
+
error: "Execution did not return a claimId for linked claim requirement.",
|
|
2828
|
+
invocationCid
|
|
2809
2829
|
};
|
|
2810
2830
|
}
|
|
2811
|
-
|
|
2812
|
-
const actionResult = await action();
|
|
2831
|
+
if (invocationStore && invocationCid && invocationData) {
|
|
2813
2832
|
const storedInvocation = {
|
|
2814
|
-
cid:
|
|
2815
|
-
invocation:
|
|
2816
|
-
invokerDid:
|
|
2817
|
-
capability:
|
|
2818
|
-
executedAt: Date.now(),
|
|
2833
|
+
cid: invocationCid,
|
|
2834
|
+
invocation: invocationData,
|
|
2835
|
+
invokerDid: actorDid,
|
|
2836
|
+
capability: { can: "flow/block/execute", with: `${flowUri}:${node.id}` },
|
|
2837
|
+
executedAt: now ? now() : Date.now(),
|
|
2819
2838
|
flowId,
|
|
2820
|
-
blockId,
|
|
2839
|
+
blockId: node.id,
|
|
2821
2840
|
result: "success",
|
|
2822
|
-
proofCids:
|
|
2841
|
+
proofCids: auth.proofCids || [],
|
|
2842
|
+
claimId: result.claimId
|
|
2823
2843
|
};
|
|
2824
2844
|
invocationStore.add(storedInvocation);
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2845
|
+
}
|
|
2846
|
+
updateRuntimeAfterSuccess(node, actorDid, runtime, result, invocationCid || auth.capabilityId, now);
|
|
2847
|
+
return {
|
|
2848
|
+
success: true,
|
|
2849
|
+
stage: "complete",
|
|
2850
|
+
result,
|
|
2851
|
+
capabilityId: auth.capabilityId,
|
|
2852
|
+
invocationCid
|
|
2853
|
+
};
|
|
2854
|
+
} catch (error) {
|
|
2855
|
+
const message = error instanceof Error ? error.message : "Execution failed";
|
|
2856
|
+
if (invocationStore && invocationCid && invocationData) {
|
|
2832
2857
|
const storedInvocation = {
|
|
2833
|
-
cid:
|
|
2834
|
-
invocation:
|
|
2835
|
-
invokerDid:
|
|
2836
|
-
capability:
|
|
2837
|
-
executedAt: Date.now(),
|
|
2858
|
+
cid: invocationCid,
|
|
2859
|
+
invocation: invocationData,
|
|
2860
|
+
invokerDid: actorDid,
|
|
2861
|
+
capability: { can: "flow/block/execute", with: `${flowUri}:${node.id}` },
|
|
2862
|
+
executedAt: now ? now() : Date.now(),
|
|
2838
2863
|
flowId,
|
|
2839
|
-
blockId,
|
|
2864
|
+
blockId: node.id,
|
|
2840
2865
|
result: "failure",
|
|
2841
|
-
error:
|
|
2842
|
-
proofCids:
|
|
2866
|
+
error: message,
|
|
2867
|
+
proofCids: auth.proofCids || []
|
|
2843
2868
|
};
|
|
2844
2869
|
invocationStore.add(storedInvocation);
|
|
2845
|
-
return {
|
|
2846
|
-
success: false,
|
|
2847
|
-
invocationCid: invocationResult.cid,
|
|
2848
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
2849
|
-
};
|
|
2850
2870
|
}
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
createRootDelegation,
|
|
2854
|
-
createDelegation,
|
|
2855
|
-
revokeDelegation,
|
|
2856
|
-
getDelegation,
|
|
2857
|
-
getAllDelegations,
|
|
2858
|
-
getRootDelegation,
|
|
2859
|
-
createAndValidateInvocation,
|
|
2860
|
-
executeWithInvocation,
|
|
2861
|
-
validateDelegationChain,
|
|
2862
|
-
findValidProofs,
|
|
2863
|
-
parseDelegationFromStore,
|
|
2864
|
-
isConfigured
|
|
2865
|
-
};
|
|
2871
|
+
return { success: false, stage: "action", error: message, invocationCid };
|
|
2872
|
+
}
|
|
2866
2873
|
};
|
|
2867
2874
|
|
|
2868
2875
|
// src/core/lib/flowEngine/migration.ts
|
|
@@ -3035,6 +3042,7 @@ export {
|
|
|
3035
3042
|
didToMatrixUserId,
|
|
3036
3043
|
findOrCreateDMRoom,
|
|
3037
3044
|
sendDirectMessage,
|
|
3045
|
+
createUcanService,
|
|
3038
3046
|
createUcanDelegationStore,
|
|
3039
3047
|
createMemoryUcanDelegationStore,
|
|
3040
3048
|
createInvocationStore,
|
|
@@ -3046,7 +3054,6 @@ export {
|
|
|
3046
3054
|
clearRuntimeForTemplateClone,
|
|
3047
3055
|
isNodeActive,
|
|
3048
3056
|
isAuthorized,
|
|
3049
|
-
executeNode
|
|
3050
|
-
createUcanService
|
|
3057
|
+
executeNode
|
|
3051
3058
|
};
|
|
3052
|
-
//# sourceMappingURL=chunk-
|
|
3059
|
+
//# sourceMappingURL=chunk-F2JSGDES.mjs.map
|