@ixo/editor 5.40.0 → 6.0.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.
@@ -1,4 +1,4 @@
1
- import { a7 as FlowNode, ac as FlowNodeAuthzExtension, a5 as FlowNodeRuntimeState, a4 as IxoEditorType, f as UcanService, I as InvocationStore, aa as EvaluationStatus, i as UcanCapability, U as UcanDelegationStore, S as StoredDelegation } from './index-B4Qe8xbv.js';
1
+ import { a7 as FlowNode, ac as FlowNodeAuthzExtension, a4 as FlowNodeRuntimeState, a5 as IxoEditorType, f as UcanService, I as InvocationStore, aa as EvaluationStatus, i as UcanCapability, U as UcanDelegationStore, S as StoredDelegation } from './index-DL8Yh3Xu.js';
2
2
  import * as Y from 'yjs';
3
3
  import { Doc, Map } from 'yjs';
4
4
  import { MatrixClient } from 'matrix-js-sdk';
@@ -226,17 +226,302 @@ declare const createRuntimeStateManager: (editor?: IxoEditorType | null) => Flow
226
226
  */
227
227
  declare function clearRuntimeForTemplateClone(yDoc: Doc): void;
228
228
 
229
+ /**
230
+ * Run record stored in the audit trail as `type: 'block.run'`.
231
+ *
232
+ * Per Phase 0 #2 (eng review pass 2), run records are NOT a parallel
233
+ * `_yRunHistory` structure — they ride on the existing `auditTrail` Y.Map
234
+ * via `useAuditTrail.addEvent`. The shape below is what goes into the
235
+ * audit trail event's `details` field.
236
+ *
237
+ * See `docs/events-and-triggers-plan.md` §3.4, §18, §19.
238
+ */
239
+ interface RunRecordDetails {
240
+ /** Stable identifier for this run, deterministic from invocation context. */
241
+ runId: string;
242
+ /** Action's output. */
243
+ output: Record<string, unknown>;
244
+ /**
245
+ * Events the action emitted on this run. Persisted as part of the run
246
+ * record so the reconciliation loop can process them idempotently — even
247
+ * across page refreshes and across multiple clients.
248
+ */
249
+ events: Array<{
250
+ name: string;
251
+ payload: Record<string, unknown>;
252
+ }>;
253
+ /** ISO timestamp when the action started. */
254
+ startedAt: string;
255
+ /** ISO timestamp when the action completed (success or failure). */
256
+ completedAt: string;
257
+ /** DID of the actor who signed the invocation that produced this run. */
258
+ actorDid: string;
259
+ /** UCAN invocation CID when execution produced one. */
260
+ invocationCid?: string;
261
+ /** Capability/proof CID used when no invocation CID was produced. */
262
+ capabilityId?: string;
263
+ /** Optional error if the run failed. */
264
+ error?: {
265
+ message: string;
266
+ code?: string;
267
+ };
268
+ /** External read-back metadata associated with this run or reconciliation. */
269
+ readBack?: Record<string, unknown>;
270
+ /** True when this audit entry was written by external read-back reconciliation. */
271
+ reconciled?: boolean;
272
+ /**
273
+ * If this run was triggered by a pending invocation (i.e. it's a listener
274
+ * run), the id of that pending invocation. Used to dedup replays and trace
275
+ * causality back through `triggeredBy`.
276
+ */
277
+ fromPendingInvocationId?: string;
278
+ /**
279
+ * If this run is a listener run, the (sourceBlockId, eventName) that
280
+ * caused it. Used by the failure visibility surface to attribute failures
281
+ * back to the source block (CP-1).
282
+ */
283
+ triggeredBy?: {
284
+ sourceBlockId: string;
285
+ eventName: string;
286
+ };
287
+ /** Source run id for listener runs, stored explicitly for failure lookups. */
288
+ sourceRunId?: string;
289
+ }
290
+ declare const RUN_RECORD_AUDIT_TYPE = "block.run";
291
+ /**
292
+ * Pending invocation queued on a listener block.
293
+ *
294
+ * Stored in `_yPendingInvocations: Y.Map<blockId, Y.Map<id, PendingInvocation>>`.
295
+ *
296
+ * The id is deterministic — derived from
297
+ * `(sourceBlockId, sourceRunId, listenerBlockId, eventName, eventIndex)` —
298
+ * so the reconciliation loop can run idempotently from multiple clients
299
+ * without producing duplicates.
300
+ *
301
+ * See `docs/events-and-triggers-plan.md` §3.4, §3.5.1, §18.
302
+ */
303
+ interface PendingInvocation {
304
+ /** Deterministic id, see `computePendingInvocationId`. */
305
+ id: string;
306
+ /** Block that emitted the event. */
307
+ triggeringBlockId: string;
308
+ /** Run id of the triggering source run, used for the deterministic id. */
309
+ sourceRunId: string;
310
+ /** Event name from the source action's vocabulary. */
311
+ eventName: string;
312
+ /** Event index within the source run's `events` array (a single run can emit multiple). */
313
+ eventIndex: number;
314
+ /**
315
+ * The frozen event payload, captured by value at emission time. The
316
+ * assignee invokes the listener against this payload, not against the
317
+ * source block's current state. This is the property that makes the
318
+ * Sally → Mike scenario produce 10 distinct emails even when Mike acts
319
+ * on them all hours later.
320
+ */
321
+ payload: Record<string, unknown>;
322
+ /**
323
+ * Snapshots of `nodeId.output.*` ref values that the listener's inputs
324
+ * reference, captured at queue time. Keyed by the full ref string.
325
+ *
326
+ * §3.5.1: ref snapshots are the load-bearing fix for the lag-time
327
+ * overwrite scenario. If a listener references a non-trigger block's
328
+ * output (e.g. `evaluateBlock.output.claimId`), that value is captured
329
+ * here at queue time. Resolution at invocation time prefers the snapshot
330
+ * over current state, so multiple queued invocations don't drift when
331
+ * the source re-runs.
332
+ */
333
+ refSnapshots: Record<string, unknown>;
334
+ /** DID of the assigned actor who must invoke this listener. Resolved from `props.assignment.assignedActor.did`. */
335
+ assigneeDid: string;
336
+ /** ISO timestamp when the source emission happened. */
337
+ emittedAt: string;
338
+ /** ISO timestamp after which this pending invocation is considered expired. Resolved from `FlowCapability.ttl` at queue time. */
339
+ expiresAt: string;
340
+ }
341
+ /**
342
+ * Compute a deterministic id for a pending invocation from its content.
343
+ *
344
+ * The same (sourceBlockId, sourceRunId, listenerBlockId, eventName,
345
+ * eventIndex) tuple always produces the same id. This is the property that
346
+ * makes the reconciliation loop idempotent — re-running it from a different
347
+ * client, or after a page refresh, produces the same `Y.Map.set` operation
348
+ * with the same key, which Yjs converges to a single entry.
349
+ *
350
+ * Implementation: simple deterministic string concatenation, hashed via a
351
+ * 32-bit FNV-1a. The id is short and stable; collision risk within a single
352
+ * flow is negligible because the inputs are scoped (block ids are unique
353
+ * within a flow, run ids are unique within a block).
354
+ */
355
+ declare function computePendingInvocationId(args: {
356
+ sourceBlockId: string;
357
+ sourceRunId: string;
358
+ listenerBlockId: string;
359
+ eventName: string;
360
+ eventIndex: number;
361
+ }): string;
362
+ /**
363
+ * Walk an inputs object and collect every RuntimeRef of the form
364
+ * `nodeId.output.fieldPath`. Returns a map of `{refString: resolvedValue}`
365
+ * suitable for storing as `PendingInvocation.refSnapshots`.
366
+ *
367
+ * The walker mirrors `resolveRuntimeRefs` in `flowCompiler/resolveRefs.ts`
368
+ * but reads instead of resolving — it captures the current value of each
369
+ * ref so the listener can later resolve against the snapshot rather than
370
+ * against current state.
371
+ *
372
+ * See `docs/events-and-triggers-plan.md` §3.5.1.
373
+ */
374
+ declare function snapshotInputRefs(inputs: unknown, getNodeOutput: (nodeId: string) => Record<string, unknown> | undefined): Record<string, unknown>;
375
+ /**
376
+ * Get the top-level pending invocations Y.Map from the editor's yDoc.
377
+ * Lazily creates it if missing.
378
+ *
379
+ * Shape: `Y.Map<blockId, Y.Map<pendingInvocationId, PendingInvocation>>`.
380
+ * The outer map is keyed by listener block id; the inner map is keyed by
381
+ * deterministic pending invocation id (see `computePendingInvocationId`).
382
+ */
383
+ declare function getPendingInvocationsMap(yDoc: Y.Doc): Y.Map<Y.Map<unknown>>;
384
+ /**
385
+ * Get the inner pending-invocations map for a specific listener block.
386
+ * Lazily creates it if missing. Caller is responsible for being inside a
387
+ * Yjs transaction if atomic creation matters.
388
+ */
389
+ declare function getOrCreateBlockPendingMap(yDoc: Y.Doc, blockId: string): Y.Map<unknown>;
390
+ /**
391
+ * Read all pending invocations for a block as plain JS objects.
392
+ * Returns an array sorted by `emittedAt` ascending (oldest first).
393
+ */
394
+ declare function readPendingInvocations(yDoc: Y.Doc, blockId: string): PendingInvocation[];
395
+ /**
396
+ * Idempotently write a pending invocation under its deterministic id.
397
+ *
398
+ * Returns true if a new entry was created, false if the id already
399
+ * existed (meaning another client or a previous reconciliation pass
400
+ * already queued this invocation). This is the property that makes
401
+ * `reconcilePendingInvocations` safe to run from multiple clients
402
+ * simultaneously and across page refreshes — see plan §18.
403
+ *
404
+ * Wraps the write in a Yjs transaction so the existence check and the
405
+ * subsequent set are atomic from the local client's perspective. Concurrent
406
+ * clients each computing the same id will all converge to a single entry
407
+ * because Y.Map.set with the same key is last-writer-wins on identical
408
+ * content.
409
+ */
410
+ declare function queuePendingInvocation(yDoc: Y.Doc, listenerBlockId: string, invocation: PendingInvocation): boolean;
411
+ /**
412
+ * Remove a pending invocation by id. Used when the assignee completes the
413
+ * invocation (transitioning to a `block.run` audit trail entry) or when
414
+ * the expiration sweep marks it as expired.
415
+ */
416
+ declare function removePendingInvocation(yDoc: Y.Doc, listenerBlockId: string, pendingInvocationId: string): boolean;
417
+ /**
418
+ * Append a run record to the audit trail for a block. Run records are
419
+ * stored as audit trail events with `type: 'block.run'` and the structured
420
+ * data in `details`. Per Phase 0 #2 of eng review pass 2, this avoids
421
+ * inventing a parallel `_yRunHistory` storage system.
422
+ *
423
+ * Y.Array.push from concurrent clients merges correctly — verified by the
424
+ * existing `useAuditTrail` shipping in production.
425
+ */
426
+ declare function appendRunRecord(yDoc: Y.Doc, blockId: string, details: RunRecordDetails, userId: string): void;
427
+ /**
428
+ * Read all run records for a block from the audit trail. Filters audit
429
+ * trail entries to only those with `type: 'block.run'`.
430
+ */
431
+ declare function readRunRecords(yDoc: Y.Doc, blockId: string): RunRecordDetails[];
432
+ /**
433
+ * A failed listener run, attributed to the source block emission that
434
+ * triggered it. Used by the failure visibility surface (CP-1) on source
435
+ * blocks: the source block can show "N listeners failed for your last run".
436
+ */
437
+ interface FailedListenerRun {
438
+ /** Block id of the listener whose run failed. */
439
+ listenerBlockId: string;
440
+ /** The full RunRecordDetails of the failed listener invocation. */
441
+ record: RunRecordDetails;
442
+ }
443
+ /**
444
+ * Find all failed listener runs that were triggered by a specific source
445
+ * block run. Walks every block's audit trail, filters to listener runs
446
+ * triggered by (sourceBlockId, sourceRunId), and returns the ones with an
447
+ * error set.
448
+ *
449
+ * Used by the source block UI to show a failure badge linked to a specific
450
+ * run — if Sally evaluates 10 claims and 2 of Mike's emails fail, Sally
451
+ * sees "2 failed listeners on claim-G" rather than discovering it days
452
+ * later in the email service logs.
453
+ */
454
+ declare function findFailedListenersForSourceRun(yDoc: Y.Doc, sourceBlockId: string, sourceRunId: string, listenerBlockIds: string[]): FailedListenerRun[];
455
+ /**
456
+ * Replay a previously failed listener run by re-queueing a pending
457
+ * invocation with the same content. Reuses the original frozen payload
458
+ * and ref snapshots from the failed run record's audit trail entry, so the
459
+ * replay sees exactly the same data the original invocation saw.
460
+ *
461
+ * CP-2 from the plan. Used by the replay button in the failure visibility
462
+ * surface. Returns true if a new pending invocation was queued.
463
+ *
464
+ * Note: replay does NOT re-derive the deterministic id from the original
465
+ * source emission, because the original pending invocation's id is already
466
+ * present (or removed) in the pendingInvocations Y.Map. Instead, replay
467
+ * generates a fresh id by appending a `:replay-N` suffix to the original.
468
+ * This means the replay creates a NEW pending invocation that the assignee
469
+ * can act on, separate from any history of the original.
470
+ */
471
+ declare function replayFailedListenerRun(yDoc: Y.Doc, failedRecord: RunRecordDetails, listenerBlockId: string, originalPayload: Record<string, unknown>, originalRefSnapshots: Record<string, unknown>, assigneeDid: string): boolean;
472
+
473
+ /**
474
+ * The raw consumer handler bag (mantine `BlocknoteHandlers`), as visible to
475
+ * action `run()` implementations via `ctx.handlers`. The real interface lives
476
+ * in the mantine layer and cannot be imported here without a core→mantine
477
+ * cycle, so this declares only the members actions actually call — loosely
478
+ * typed, since the parameter shapes are owned by the consumer contract.
479
+ *
480
+ * There is deliberately NO index signature: calling an undeclared handler is a
481
+ * compile error, so a renamed consumer handler surfaces here instead of
482
+ * failing at runtime. Add the member when an action starts using a new
483
+ * handler. Prefer `ctx.services.*` (the typed, adapted contract) over
484
+ * `ctx.handlers` for new actions — this escape hatch exists for actions that
485
+ * predate `buildServicesFromHandlers`.
486
+ */
487
+ interface ActionHandlers {
488
+ askCompanion?: (prompt: string) => Promise<any>;
489
+ vote?: (...args: any[]) => any;
490
+ getPreProposalContractAddress?: (...args: any[]) => any;
491
+ getGroupContractAddress?: (...args: any[]) => any;
492
+ getProposalContractAddress?: (...args: any[]) => any;
493
+ createProposal?: (...args: any[]) => any;
494
+ getUserRoles?: (...args: any[]) => any;
495
+ getClaimData?: (...args: any[]) => any;
496
+ requestPin?: (...args: any[]) => any;
497
+ signCredential?: (...args: any[]) => any;
498
+ publicFileUpload?: (...args: any[]) => any;
499
+ createDomain?: (...args: any[]) => any;
500
+ createAddLinkedResourceMessage?: (...args: any[]) => any;
501
+ executeTransaction?: (...args: any[]) => any;
502
+ createGovernanceGroup?: (...args: any[]) => any;
503
+ getEntityDid?: (...args: any[]) => any;
504
+ getCurrentUser?: (...args: any[]) => any;
505
+ createAddLinkedEntityMessage?: (...args: any[]) => any;
506
+ sourceDomainSpaces?: (...args: any[]) => any;
507
+ importProtocolTemplatesToSpace?: (...args: any[]) => any;
508
+ integrations?: {
509
+ executeTool?: (...args: any[]) => any;
510
+ fetchCurrentState?: (...args: any[]) => any;
511
+ getEntityDid?: (...args: any[]) => any;
512
+ };
513
+ }
229
514
  interface ActionContext {
230
515
  actorDid: string;
231
516
  flowId: string;
232
517
  nodeId: string;
233
518
  services: ActionServices;
234
- flowNode?: any;
235
- runtime?: any;
519
+ flowNode?: FlowNode;
520
+ runtime?: FlowRuntimeStateManager;
236
521
  flowUri?: string;
237
- handlers?: any;
238
- editor?: any;
239
- pendingInvocation?: any;
522
+ handlers?: ActionHandlers;
523
+ editor?: IxoEditorType;
524
+ pendingInvocation?: PendingInvocation;
240
525
  }
241
526
  /**
242
527
  * Lifecycle state of an IXO claims-module collection.
@@ -488,6 +773,273 @@ interface CarbonRetireableBatch {
488
773
  /** Human-readable entity name, for display. */
489
774
  alsoKnownAs?: string;
490
775
  }
776
+ interface HttpService {
777
+ request: (params: {
778
+ url: string;
779
+ method: string;
780
+ headers?: Record<string, string>;
781
+ body?: any;
782
+ }) => Promise<{
783
+ status: number;
784
+ headers: Record<string, string>;
785
+ data: any;
786
+ }>;
787
+ }
788
+ interface EmailService {
789
+ send: (params: {
790
+ to: string;
791
+ subject: string;
792
+ template: string;
793
+ templateVersion?: string;
794
+ variables?: Record<string, any>;
795
+ cc?: string;
796
+ bcc?: string;
797
+ replyTo?: string;
798
+ }) => Promise<{
799
+ messageId: string;
800
+ sentAt: string;
801
+ }>;
802
+ }
803
+ interface NotifyService {
804
+ send: (params: {
805
+ channel: string;
806
+ to: string[];
807
+ cc?: string[];
808
+ bcc?: string[];
809
+ subject?: string;
810
+ body?: string;
811
+ bodyType?: 'text' | 'html';
812
+ from?: string;
813
+ replyTo?: string;
814
+ }) => Promise<{
815
+ messageId: string;
816
+ sentAt: string;
817
+ }>;
818
+ }
819
+ interface BidService {
820
+ submitBid: (params: {
821
+ collectionId: string;
822
+ role: string;
823
+ surveyAnswers: Record<string, any>;
824
+ entityDid?: string;
825
+ }) => Promise<any>;
826
+ approveBid: (params: {
827
+ bidId: string;
828
+ collectionId: string;
829
+ did: string;
830
+ entityDid?: string;
831
+ }) => Promise<any>;
832
+ rejectBid: (params: {
833
+ bidId: string;
834
+ collectionId: string;
835
+ did: string;
836
+ reason: string;
837
+ entityDid?: string;
838
+ }) => Promise<any>;
839
+ approveServiceAgentApplication: (params: {
840
+ adminAddress: string;
841
+ collectionId: string;
842
+ agentQuota: number;
843
+ deedDid: string;
844
+ currentUserAddress: string;
845
+ }) => Promise<void>;
846
+ approveEvaluatorApplication: (params: {
847
+ adminAddress: string;
848
+ collectionId: string;
849
+ deedDid: string;
850
+ evaluatorAddress: string;
851
+ agentQuota?: number;
852
+ claimIds?: string[];
853
+ maxAmounts?: Array<{
854
+ denom: string;
855
+ amount: string;
856
+ }>;
857
+ }) => Promise<void>;
858
+ }
859
+ interface ClaimService {
860
+ requestPin: (config?: {
861
+ title?: string;
862
+ description?: string;
863
+ submitText?: string;
864
+ }) => Promise<string>;
865
+ submitClaim: (params: {
866
+ surveyData: any;
867
+ deedDid: string;
868
+ collectionId: string;
869
+ adminAddress: string;
870
+ pin: string;
871
+ entityDid?: string;
872
+ }) => Promise<{
873
+ transactionHash: string;
874
+ claimId: string;
875
+ }>;
876
+ evaluateClaim: (granteeAddress: string, did: string, payload: {
877
+ claimId: string;
878
+ collectionId: string;
879
+ adminAddress: string;
880
+ status?: number;
881
+ verificationProof: string;
882
+ amount?: {
883
+ denom: string;
884
+ amount: string;
885
+ };
886
+ }) => Promise<{
887
+ code: number;
888
+ transactionHash: string;
889
+ rawLog?: string;
890
+ height?: number;
891
+ txIndex?: number;
892
+ gasWanted?: bigint;
893
+ gasUsed?: bigint;
894
+ }>;
895
+ disputeClaim?: (granteeAddress: string, did: string, payload: {
896
+ subjectId: string;
897
+ disputeType: number;
898
+ reason: string;
899
+ }) => Promise<any>;
900
+ getCurrentUser: () => {
901
+ address: string;
902
+ did?: string;
903
+ };
904
+ createUdid?: (params: any) => Promise<any>;
905
+ }
906
+ /**
907
+ * Claims-module collection lifecycle service. The editor declares the
908
+ * contract only; the consumer app implements each method (broadcast on chain,
909
+ * resolve admin from its wallet context, map string<->Long).
910
+ *
911
+ * Per IXO-2573, each write op should broadcast then the dispatcher re-fetches
912
+ * via `get(...)` so `runtime.output` always holds the latest full
913
+ * `CollectionState`. `get` is the read-only `refresh` primitive.
914
+ */
915
+ interface CollectionService {
916
+ /** Read the full current on-chain state of a collection. */
917
+ get: (params: {
918
+ collectionId: string;
919
+ }) => Promise<CollectionState>;
920
+ /** Broadcast `MsgCreateCollection`. Returns the new collectionId + tx hash. */
921
+ create: (params: CollectionCreateParams) => Promise<{
922
+ transactionHash: string;
923
+ collectionId: string;
924
+ }>;
925
+ /** Broadcast `MsgUpdateCollectionState`. */
926
+ updateState: (params: {
927
+ collectionId: string;
928
+ state: CollectionStateEnum;
929
+ adminAddress: string;
930
+ }) => Promise<{
931
+ transactionHash: string;
932
+ }>;
933
+ /** Broadcast `MsgUpdateCollectionDates`. */
934
+ updateDates: (params: {
935
+ collectionId: string;
936
+ startDate?: string;
937
+ endDate?: string;
938
+ adminAddress: string;
939
+ }) => Promise<{
940
+ transactionHash: string;
941
+ }>;
942
+ /** Broadcast `MsgUpdateCollectionQuota`. `quota` carried as a string; `0` = unlimited. */
943
+ updateQuota: (params: {
944
+ collectionId: string;
945
+ quota: string;
946
+ adminAddress: string;
947
+ }) => Promise<{
948
+ transactionHash: string;
949
+ }>;
950
+ /** Broadcast `MsgUpdateCollectionPayments`. */
951
+ updatePayments: (params: {
952
+ collectionId: string;
953
+ payments: Payments;
954
+ adminAddress: string;
955
+ }) => Promise<{
956
+ transactionHash: string;
957
+ }>;
958
+ /** Broadcast `MsgUpdateCollectionIntents`. */
959
+ updateIntents: (params: {
960
+ collectionId: string;
961
+ intents: CollectionIntentOptions;
962
+ adminAddress: string;
963
+ }) => Promise<{
964
+ transactionHash: string;
965
+ }>;
966
+ }
967
+ /**
968
+ * Claim-collection user-management service (IXO-2586). The editor declares the
969
+ * contract only; the consumer app implements each method (build/broadcast the
970
+ * claims-module authz messages, query authz grants, classify addresses,
971
+ * enumerate group members). Extends → replaces the reactive `bid` service.
972
+ */
973
+ interface CollectionUsersService {
974
+ /**
975
+ * Grant submit/evaluate authz for ONE collection to a grantee. The handler
976
+ * reads the grantee's existing authz for the role's msgTypeUrl and APPENDS a
977
+ * per-collection constraint (preserving other collections' live values),
978
+ * then broadcasts `MsgCreateClaimAuthorization` routed via
979
+ * `MsgGrantEntityAccountAuthz` (entity admin = granter). See IXO-2589.
980
+ */
981
+ grant: (params: {
982
+ granterAdminAddress: string;
983
+ granteeAddress: string;
984
+ collectionId: string;
985
+ role: CollectionUserRole;
986
+ agentQuota?: string;
987
+ maxAmount?: CollectionCoin[];
988
+ intentDurationNs?: string;
989
+ deedDid?: string;
990
+ }) => Promise<{
991
+ transactionHash: string;
992
+ }>;
993
+ /**
994
+ * Per-collection read-modify-write revoke (IXO-2590). Reads the grantee's
995
+ * live authz, drops the target collection's constraint, and — when other
996
+ * constraints remain — broadcasts a single atomic tx ordered
997
+ * `[MsgRevokeEntityAccountAuthz, then one MsgCreateClaimAuthorization per
998
+ * remaining constraint]`, preserving each remaining constraint's live
999
+ * (decremented) quota/limits. Short-circuits to a plain revoke when the
1000
+ * target was the only constraint.
1001
+ */
1002
+ revoke: (params: {
1003
+ granterAdminAddress: string;
1004
+ granteeAddress: string;
1005
+ collectionId: string;
1006
+ role: CollectionUserRole;
1007
+ }) => Promise<{
1008
+ transactionHash: string;
1009
+ }>;
1010
+ /**
1011
+ * List the grantees holding a submit/evaluate constraint for a collection.
1012
+ * Queries authz grants against the entity admin account, decodes the
1013
+ * authorizations, and filters constraints by `collectionId` (IXO-2591).
1014
+ */
1015
+ list: (params: {
1016
+ granterAdminAddress: string;
1017
+ collectionId: string;
1018
+ }) => Promise<{
1019
+ grantees: CollectionGrantee[];
1020
+ }>;
1021
+ /** Classify an address as a plain user vs a DAO DAO contract (IXO-2592). */
1022
+ classifyAddress: (params: {
1023
+ address: string;
1024
+ }) => Promise<AddressClassification>;
1025
+ /** Enumerate the members of a group account for grant fan-out (IXO-2592). */
1026
+ enumerateMembers: (params: {
1027
+ groupAddress: string;
1028
+ }) => Promise<{
1029
+ members: CollectionMember[];
1030
+ }>;
1031
+ }
1032
+ interface MatrixCredentialService {
1033
+ storeCredential: (params: {
1034
+ roomId: string;
1035
+ credentialKey: string;
1036
+ credential: Record<string, any>;
1037
+ cid: string;
1038
+ }) => Promise<{
1039
+ storedAt: string;
1040
+ duplicate: boolean;
1041
+ }>;
1042
+ }
491
1043
  /** Result of any integration tool execution (direct or via a binding). */
492
1044
  interface IntegrationExecuteOutcome {
493
1045
  successful: boolean;
@@ -495,582 +1047,332 @@ interface IntegrationExecuteOutcome {
495
1047
  error?: string;
496
1048
  code?: 'OK' | 'VALIDATION' | 'AUTH_EXPIRED' | 'UPSTREAM_4XX' | 'UPSTREAM_5XX' | 'RATE_LIMIT' | 'UNKNOWN';
497
1049
  }
498
- interface ActionServices {
499
- http?: {
500
- request: (params: {
501
- url: string;
502
- method: string;
503
- headers?: Record<string, string>;
504
- body?: any;
505
- }) => Promise<{
506
- status: number;
507
- headers: Record<string, string>;
508
- data: any;
509
- }>;
510
- };
511
- email?: {
512
- send: (params: {
513
- to: string;
514
- subject: string;
515
- template: string;
516
- templateVersion?: string;
517
- variables?: Record<string, any>;
518
- cc?: string;
519
- bcc?: string;
520
- replyTo?: string;
521
- }) => Promise<{
522
- messageId: string;
523
- sentAt: string;
524
- }>;
525
- };
526
- notify?: {
527
- send: (params: {
528
- channel: string;
529
- to: string[];
530
- cc?: string[];
531
- bcc?: string[];
532
- subject?: string;
533
- body?: string;
534
- bodyType?: 'text' | 'html';
535
- from?: string;
536
- replyTo?: string;
537
- }) => Promise<{
538
- messageId: string;
539
- sentAt: string;
540
- }>;
541
- };
542
- bid?: {
543
- submitBid: (params: {
544
- collectionId: string;
545
- role: string;
546
- surveyAnswers: Record<string, any>;
547
- entityDid?: string;
548
- }) => Promise<any>;
549
- approveBid: (params: {
550
- bidId: string;
551
- collectionId: string;
552
- did: string;
553
- entityDid?: string;
554
- }) => Promise<any>;
555
- rejectBid: (params: {
556
- bidId: string;
557
- collectionId: string;
558
- did: string;
559
- reason: string;
560
- entityDid?: string;
561
- }) => Promise<any>;
562
- approveServiceAgentApplication: (params: {
563
- adminAddress: string;
564
- collectionId: string;
565
- agentQuota: number;
566
- deedDid: string;
567
- currentUserAddress: string;
568
- }) => Promise<void>;
569
- approveEvaluatorApplication: (params: {
570
- adminAddress: string;
571
- collectionId: string;
572
- deedDid: string;
573
- evaluatorAddress: string;
574
- agentQuota?: number;
575
- claimIds?: string[];
576
- maxAmounts?: Array<{
577
- denom: string;
578
- amount: string;
579
- }>;
580
- }) => Promise<void>;
581
- };
582
- claim?: {
583
- requestPin: (config?: {
584
- title?: string;
585
- description?: string;
586
- submitText?: string;
587
- }) => Promise<string>;
588
- submitClaim: (params: {
589
- surveyData: any;
590
- deedDid: string;
591
- collectionId: string;
592
- adminAddress: string;
593
- pin: string;
594
- entityDid?: string;
595
- }) => Promise<{
596
- transactionHash: string;
597
- claimId: string;
598
- }>;
599
- evaluateClaim: (granteeAddress: string, did: string, payload: {
600
- claimId: string;
601
- collectionId: string;
602
- adminAddress: string;
603
- status?: number;
604
- verificationProof: string;
605
- amount?: {
606
- denom: string;
607
- amount: string;
608
- };
609
- }) => Promise<{
610
- code: number;
611
- transactionHash: string;
612
- rawLog?: string;
613
- height?: number;
614
- txIndex?: number;
615
- gasWanted?: bigint;
616
- gasUsed?: bigint;
617
- }>;
618
- disputeClaim?: (granteeAddress: string, did: string, payload: {
619
- subjectId: string;
620
- disputeType: number;
621
- reason: string;
622
- }) => Promise<any>;
623
- getCurrentUser: () => {
624
- address: string;
625
- did?: string;
626
- };
627
- createUdid?: (params: any) => Promise<any>;
628
- };
1050
+ interface IntegrationsService {
1051
+ executeTool: (args: {
1052
+ toolSlug: string;
1053
+ connectedAccountId: string;
1054
+ arguments: Record<string, unknown>;
1055
+ }) => Promise<IntegrationExecuteOutcome>;
1056
+ fetchCurrentState?: (args: {
1057
+ toolSlug: string;
1058
+ connectedAccountId: string;
1059
+ arguments: Record<string, unknown>;
1060
+ }) => Promise<Record<string, unknown>>;
1061
+ getEntityDid?: () => string | undefined;
629
1062
  /**
630
- * Claims-module collection lifecycle service. The editor declares the
631
- * contract only; the consumer app implements each method (broadcast on chain,
632
- * resolve admin from its wallet context, map string<->Long).
633
- *
634
- * Per IXO-2573, each write op should broadcast then the dispatcher re-fetches
635
- * via `get(...)` so `runtime.output` always holds the latest full
636
- * `CollectionState`. `get` is the read-only `refresh` primitive.
1063
+ * Execute a tool on the template author's behalf via an opaque, server-side
1064
+ * binding (delegated blocks). The runner never holds the author's
1065
+ * credential — `bindingId` selects it on the worker. Returns the same
1066
+ * outcome shape as `executeTool`.
637
1067
  */
638
- collection?: {
639
- /** Read the full current on-chain state of a collection. */
640
- get: (params: {
641
- collectionId: string;
642
- }) => Promise<CollectionState>;
643
- /** Broadcast `MsgCreateCollection`. Returns the new collectionId + tx hash. */
644
- create: (params: CollectionCreateParams) => Promise<{
645
- transactionHash: string;
646
- collectionId: string;
647
- }>;
648
- /** Broadcast `MsgUpdateCollectionState`. */
649
- updateState: (params: {
650
- collectionId: string;
651
- state: CollectionStateEnum;
652
- adminAddress: string;
653
- }) => Promise<{
654
- transactionHash: string;
655
- }>;
656
- /** Broadcast `MsgUpdateCollectionDates`. */
657
- updateDates: (params: {
658
- collectionId: string;
659
- startDate?: string;
660
- endDate?: string;
661
- adminAddress: string;
662
- }) => Promise<{
663
- transactionHash: string;
664
- }>;
665
- /** Broadcast `MsgUpdateCollectionQuota`. `quota` carried as a string; `0` = unlimited. */
666
- updateQuota: (params: {
667
- collectionId: string;
668
- quota: string;
669
- adminAddress: string;
670
- }) => Promise<{
671
- transactionHash: string;
672
- }>;
673
- /** Broadcast `MsgUpdateCollectionPayments`. */
674
- updatePayments: (params: {
675
- collectionId: string;
676
- payments: Payments;
677
- adminAddress: string;
678
- }) => Promise<{
679
- transactionHash: string;
680
- }>;
681
- /** Broadcast `MsgUpdateCollectionIntents`. */
682
- updateIntents: (params: {
683
- collectionId: string;
684
- intents: CollectionIntentOptions;
685
- adminAddress: string;
686
- }) => Promise<{
687
- transactionHash: string;
688
- }>;
689
- };
1068
+ executeBinding?: (args: {
1069
+ bindingId: string;
1070
+ toolSlug: string;
1071
+ arguments: Record<string, unknown>;
1072
+ }) => Promise<IntegrationExecuteOutcome>;
1073
+ }
1074
+ interface OracleService {
1075
+ generateWallet: () => Promise<{
1076
+ address: string;
1077
+ did: string;
1078
+ pubKey: string;
1079
+ mnemonic: string;
1080
+ }>;
1081
+ fundWallet: (params: {
1082
+ address: string;
1083
+ amount: number;
1084
+ }) => Promise<{
1085
+ transactionHash: string;
1086
+ }>;
1087
+ createIidDocument: (params: {
1088
+ mnemonic: string;
1089
+ did: string;
1090
+ address: string;
1091
+ pubKey: string;
1092
+ }) => Promise<{
1093
+ did: string;
1094
+ transactionHash: string;
1095
+ }>;
1096
+ registerMatrixAccount: (params: {
1097
+ mnemonic: string;
1098
+ address: string;
1099
+ did: string;
1100
+ pin: string;
1101
+ oracleName: string;
1102
+ avatarUrl?: string;
1103
+ }) => Promise<{
1104
+ matrixUserId: string;
1105
+ matrixAccessToken: string;
1106
+ matrixRoomId: string;
1107
+ matrixDeviceId: string;
1108
+ matrixMnemonic: string;
1109
+ matrixPassword: string;
1110
+ matrixRecoveryPhrase: string;
1111
+ matrixHomeServerUrl: string;
1112
+ }>;
1113
+ createOracleEntity: (params: {
1114
+ mnemonic: string;
1115
+ address: string;
1116
+ did: string;
1117
+ pubKey: string;
1118
+ pin: string;
1119
+ matrixAccessToken: string;
1120
+ matrixRoomId: string;
1121
+ oracleName: string;
1122
+ orgName: string;
1123
+ description: string;
1124
+ location: string;
1125
+ logoUrl: string;
1126
+ coverImageUrl: string;
1127
+ apiUrl: string;
1128
+ price: number;
1129
+ llmModel: string;
1130
+ opening?: string;
1131
+ communicationStyle?: string;
1132
+ capabilities?: string;
1133
+ mcpConfig?: any;
1134
+ parentProtocol?: string;
1135
+ }) => Promise<{
1136
+ entityDid: string;
1137
+ transactionHash: string;
1138
+ /** Multibase-encoded P-256 public key registered as a keyAgreement vm on the oracle entity DID. */
1139
+ encryptionPublicKeyMultibase: string;
1140
+ /** DID verification method id of the P-256 keyAgreement key. */
1141
+ encryptionVerificationMethodId: string;
1142
+ }>;
690
1143
  /**
691
- * Claim-collection user-management service (IXO-2586). The editor declares the
692
- * contract only; the consumer app implements each method (build/broadcast the
693
- * claims-module authz messages, query authz grants, classify addresses,
694
- * enumerate group members). Extends → replaces the reactive `bid` service.
1144
+ * Contract the oracle: ensure the user↔oracle Matrix DM room exists and
1145
+ * the user has joined it. Pure Matrix work — no chain calls, no key setup.
1146
+ * Returns the user↔oracle room id which downstream steps (storeSecrets,
1147
+ * storeConfig) write into.
695
1148
  */
696
- collectionUsers?: {
697
- /**
698
- * Grant submit/evaluate authz for ONE collection to a grantee. The handler
699
- * reads the grantee's existing authz for the role's msgTypeUrl and APPENDS a
700
- * per-collection constraint (preserving other collections' live values),
701
- * then broadcasts `MsgCreateClaimAuthorization` routed via
702
- * `MsgGrantEntityAccountAuthz` (entity admin = granter). See IXO-2589.
703
- */
704
- grant: (params: {
705
- granterAdminAddress: string;
706
- granteeAddress: string;
707
- collectionId: string;
708
- role: CollectionUserRole;
709
- agentQuota?: string;
710
- maxAmount?: CollectionCoin[];
711
- intentDurationNs?: string;
712
- deedDid?: string;
713
- }) => Promise<{
714
- transactionHash: string;
715
- }>;
716
- /**
717
- * Per-collection read-modify-write revoke (IXO-2590). Reads the grantee's
718
- * live authz, drops the target collection's constraint, and — when other
719
- * constraints remain — broadcasts a single atomic tx ordered
720
- * `[MsgRevokeEntityAccountAuthz, then one MsgCreateClaimAuthorization per
721
- * remaining constraint]`, preserving each remaining constraint's live
722
- * (decremented) quota/limits. Short-circuits to a plain revoke when the
723
- * target was the only constraint.
724
- */
725
- revoke: (params: {
726
- granterAdminAddress: string;
727
- granteeAddress: string;
728
- collectionId: string;
729
- role: CollectionUserRole;
730
- }) => Promise<{
731
- transactionHash: string;
732
- }>;
733
- /**
734
- * List the grantees holding a submit/evaluate constraint for a collection.
735
- * Queries authz grants against the entity admin account, decodes the
736
- * authorizations, and filters constraints by `collectionId` (IXO-2591).
737
- */
738
- list: (params: {
739
- granterAdminAddress: string;
740
- collectionId: string;
741
- }) => Promise<{
742
- grantees: CollectionGrantee[];
743
- }>;
744
- /** Classify an address as a plain user vs a DAO DAO contract (IXO-2592). */
745
- classifyAddress: (params: {
746
- address: string;
747
- }) => Promise<AddressClassification>;
748
- /** Enumerate the members of a group account for grant fan-out (IXO-2592). */
749
- enumerateMembers: (params: {
750
- groupAddress: string;
751
- }) => Promise<{
752
- members: CollectionMember[];
753
- }>;
754
- };
755
- matrix?: {
756
- storeCredential: (params: {
757
- roomId: string;
758
- credentialKey: string;
759
- credential: Record<string, any>;
760
- cid: string;
761
- }) => Promise<{
762
- storedAt: string;
763
- duplicate: boolean;
764
- }>;
765
- };
766
- integrations?: {
767
- executeTool: (args: {
768
- toolSlug: string;
769
- connectedAccountId: string;
770
- arguments: Record<string, unknown>;
771
- }) => Promise<IntegrationExecuteOutcome>;
772
- fetchCurrentState?: (args: {
773
- toolSlug: string;
774
- connectedAccountId: string;
775
- arguments: Record<string, unknown>;
776
- }) => Promise<Record<string, unknown>>;
777
- getEntityDid?: () => string | undefined;
778
- /**
779
- * Execute a tool on the template author's behalf via an opaque, server-side
780
- * binding (delegated blocks). The runner never holds the author's
781
- * credential — `bindingId` selects it on the worker. Returns the same
782
- * outcome shape as `executeTool`.
783
- */
784
- executeBinding?: (args: {
785
- bindingId: string;
786
- toolSlug: string;
787
- arguments: Record<string, unknown>;
788
- }) => Promise<IntegrationExecuteOutcome>;
789
- };
790
- oracle?: {
791
- generateWallet: () => Promise<{
792
- address: string;
793
- did: string;
794
- pubKey: string;
795
- mnemonic: string;
796
- }>;
797
- fundWallet: (params: {
798
- address: string;
799
- amount: number;
800
- }) => Promise<{
801
- transactionHash: string;
802
- }>;
803
- createIidDocument: (params: {
804
- mnemonic: string;
805
- did: string;
806
- address: string;
807
- pubKey: string;
808
- }) => Promise<{
809
- did: string;
810
- transactionHash: string;
811
- }>;
812
- registerMatrixAccount: (params: {
813
- mnemonic: string;
814
- address: string;
815
- did: string;
816
- pin: string;
817
- oracleName: string;
818
- avatarUrl?: string;
819
- }) => Promise<{
820
- matrixUserId: string;
821
- matrixAccessToken: string;
822
- matrixRoomId: string;
823
- matrixDeviceId: string;
824
- matrixMnemonic: string;
825
- matrixPassword: string;
826
- matrixRecoveryPhrase: string;
827
- matrixHomeServerUrl: string;
1149
+ contract: (params: {
1150
+ oracleEntityDid: string;
1151
+ }) => Promise<{
1152
+ userOracleRoomId: string;
1153
+ userOracleRoomAlias: string;
1154
+ }>;
1155
+ provisionSandbox: (params: {
1156
+ entityDid: string;
1157
+ matrixRoomId: string;
1158
+ }) => Promise<{
1159
+ sandboxUrl: string;
1160
+ status: string;
1161
+ }>;
1162
+ storeSecrets: (params: {
1163
+ matrixRoomId: string;
1164
+ publicKeyMultibase: string;
1165
+ verificationMethodId: string;
1166
+ matrixHomeServerUrl: string;
1167
+ matrixUsername: string;
1168
+ matrixPassword: string;
1169
+ secrets: Record<string, string>;
1170
+ preEncryptedSecrets?: Record<string, string>;
1171
+ }) => Promise<{
1172
+ storedSecrets: string[];
1173
+ roomId: string;
1174
+ freshAccessToken?: string;
1175
+ }>;
1176
+ /** JWE-encrypts a single plaintext value to the oracle's P-256 public key (multibase).
1177
+ * Used by storeSecrets FlowDetail to encrypt user-typed OpenRouter key at-rest. */
1178
+ encryptForOracle: (params: {
1179
+ plaintext: string;
1180
+ publicKeyMultibase: string;
1181
+ }) => Promise<{
1182
+ jwe: string;
1183
+ }>;
1184
+ /** Reads `ixo.room.secret.index` state events from the matrix room and returns the
1185
+ * list of secret names already stored. Used for idempotency checks. */
1186
+ readStoredSecrets: (params: {
1187
+ matrixRoomId: string;
1188
+ }) => Promise<{
1189
+ secretNames: string[];
1190
+ }>;
1191
+ /** Returns the network-derived .env constants (RPC URL, matrix homeserver, etc.)
1192
+ * for the consumer's currently configured network. Used by the storeSecrets
1193
+ * FlowDetail's "Additional Configuration" display section, and merged into the
1194
+ * storeConfig state event by the consumer handler. Must be deterministic per network. */
1195
+ getNetworkConstants: (params: {
1196
+ oracleName: string;
1197
+ }) => Promise<{
1198
+ constants: Record<string, string>;
1199
+ }>;
1200
+ validateMcpServer: (params: {
1201
+ url: string;
1202
+ authType?: 'bearer' | 'api-key' | 'none';
1203
+ authToken?: string;
1204
+ }) => Promise<{
1205
+ success: boolean;
1206
+ tools?: Array<{
1207
+ name: string;
1208
+ description?: string;
828
1209
  }>;
829
- createOracleEntity: (params: {
830
- mnemonic: string;
831
- address: string;
832
- did: string;
833
- pubKey: string;
834
- pin: string;
835
- matrixAccessToken: string;
836
- matrixRoomId: string;
1210
+ error?: string;
1211
+ }>;
1212
+ storeConfig: (params: {
1213
+ matrixRoomId: string;
1214
+ config: {
837
1215
  oracleName: string;
838
1216
  orgName: string;
839
1217
  description: string;
840
1218
  location: string;
841
- logoUrl: string;
842
- coverImageUrl: string;
843
- apiUrl: string;
844
1219
  price: number;
1220
+ apiUrl: string;
1221
+ entityDid: string;
1222
+ logoUrl: string;
845
1223
  llmModel: string;
846
1224
  opening?: string;
847
1225
  communicationStyle?: string;
848
1226
  capabilities?: string;
849
- mcpConfig?: any;
850
- parentProtocol?: string;
851
- }) => Promise<{
852
- entityDid: string;
853
- transactionHash: string;
854
- /** Multibase-encoded P-256 public key registered as a keyAgreement vm on the oracle entity DID. */
855
- encryptionPublicKeyMultibase: string;
856
- /** DID verification method id of the P-256 keyAgreement key. */
857
- encryptionVerificationMethodId: string;
858
- }>;
859
- /**
860
- * Contract the oracle: ensure the user↔oracle Matrix DM room exists and
861
- * the user has joined it. Pure Matrix work — no chain calls, no key setup.
862
- * Returns the user↔oracle room id which downstream steps (storeSecrets,
863
- * storeConfig) write into.
864
- */
865
- contract: (params: {
866
- oracleEntityDid: string;
867
- }) => Promise<{
868
- userOracleRoomId: string;
869
- userOracleRoomAlias: string;
870
- }>;
871
- provisionSandbox: (params: {
872
- entityDid: string;
873
- matrixRoomId: string;
874
- }) => Promise<{
875
- sandboxUrl: string;
876
- status: string;
877
- }>;
878
- storeSecrets: (params: {
879
- matrixRoomId: string;
880
- publicKeyMultibase: string;
881
- verificationMethodId: string;
882
- matrixHomeServerUrl: string;
883
- matrixUsername: string;
884
- matrixPassword: string;
885
- secrets: Record<string, string>;
886
- preEncryptedSecrets?: Record<string, string>;
887
- }) => Promise<{
888
- storedSecrets: string[];
889
- roomId: string;
890
- freshAccessToken?: string;
891
- }>;
892
- /** JWE-encrypts a single plaintext value to the oracle's P-256 public key (multibase).
893
- * Used by storeSecrets FlowDetail to encrypt user-typed OpenRouter key at-rest. */
894
- encryptForOracle: (params: {
895
- plaintext: string;
896
- publicKeyMultibase: string;
897
- }) => Promise<{
898
- jwe: string;
899
- }>;
900
- /** Reads `ixo.room.secret.index` state events from the matrix room and returns the
901
- * list of secret names already stored. Used for idempotency checks. */
902
- readStoredSecrets: (params: {
903
- matrixRoomId: string;
904
- }) => Promise<{
905
- secretNames: string[];
906
- }>;
907
- /** Returns the network-derived .env constants (RPC URL, matrix homeserver, etc.)
908
- * for the consumer's currently configured network. Used by the storeSecrets
909
- * FlowDetail's "Additional Configuration" display section, and merged into the
910
- * storeConfig state event by the consumer handler. Must be deterministic per network. */
911
- getNetworkConstants: (params: {
912
- oracleName: string;
913
- }) => Promise<{
914
- constants: Record<string, string>;
915
- }>;
916
- validateMcpServer: (params: {
917
- url: string;
918
- authType?: 'bearer' | 'api-key' | 'none';
919
- authToken?: string;
920
- }) => Promise<{
921
- success: boolean;
922
- tools?: Array<{
1227
+ skills?: string[];
1228
+ mcpServers?: Array<{
923
1229
  name: string;
1230
+ url: string;
924
1231
  description?: string;
1232
+ authEnvVar?: string;
925
1233
  }>;
926
- error?: string;
927
- }>;
928
- storeConfig: (params: {
929
- matrixRoomId: string;
930
- config: {
931
- oracleName: string;
932
- orgName: string;
933
- description: string;
934
- location: string;
935
- price: number;
936
- apiUrl: string;
937
- entityDid: string;
938
- logoUrl: string;
939
- llmModel: string;
940
- opening?: string;
941
- communicationStyle?: string;
942
- capabilities?: string;
943
- skills?: string[];
944
- mcpServers?: Array<{
945
- name: string;
946
- url: string;
947
- description?: string;
948
- authEnvVar?: string;
949
- }>;
950
- matrixUserId?: string;
951
- matrixAccountRoomId?: string;
952
- oracleAddress?: string;
953
- oracleDid?: string;
954
- };
955
- }) => Promise<{
956
- configStored: boolean;
957
- roomId: string;
958
- }>;
959
- deploySetup: (params: {
960
- name: string;
961
- config: Record<string, any>;
962
- roomId: string;
963
- secrets?: Record<string, string>;
964
- }) => Promise<{
965
- setupComplete: boolean;
966
- stdout?: string;
967
- stderr?: string;
968
- }>;
969
- deployStart: (params: {
970
- name: string;
971
- entityDid: string;
972
- roomId: string;
973
- secrets?: Record<string, string>;
974
- }) => Promise<{
975
- processId: string;
976
- status: string;
977
- url?: string;
978
- }>;
979
- updateOracleDomain: (params: {
1234
+ matrixUserId?: string;
1235
+ matrixAccountRoomId?: string;
1236
+ oracleAddress?: string;
1237
+ oracleDid?: string;
1238
+ };
1239
+ }) => Promise<{
1240
+ configStored: boolean;
1241
+ roomId: string;
1242
+ }>;
1243
+ deploySetup: (params: {
1244
+ name: string;
1245
+ config: Record<string, any>;
1246
+ roomId: string;
1247
+ secrets?: Record<string, string>;
1248
+ }) => Promise<{
1249
+ setupComplete: boolean;
1250
+ stdout?: string;
1251
+ stderr?: string;
1252
+ }>;
1253
+ deployStart: (params: {
1254
+ name: string;
1255
+ entityDid: string;
1256
+ roomId: string;
1257
+ secrets?: Record<string, string>;
1258
+ }) => Promise<{
1259
+ processId: string;
1260
+ status: string;
1261
+ url?: string;
1262
+ }>;
1263
+ updateOracleDomain: (params: {
1264
+ entityDid: string;
1265
+ newApiUrl: string;
1266
+ }) => Promise<{
1267
+ transactionHash: string;
1268
+ }>;
1269
+ }
1270
+ /**
1271
+ * Carbon credit batch service (IXO-2675). The editor declares the contract
1272
+ * only; the consumer app implements each method (run the owner/admin
1273
+ * reconciliation read, build + broadcast the harvest grant/exec pair and the
1274
+ * retire message, sign via its own wallet/SignX). Both writes are USER-signed
1275
+ * — the editor never signs on the user's behalf.
1276
+ */
1277
+ interface CarbonService {
1278
+ /**
1279
+ * Reconcile the user's owner-side and entity-admin-side batches into the
1280
+ * unified view. Pure read (no signing). Performs provenance recovery for
1281
+ * transferred batches so every `harvestableBatch` carries `entityDid` +
1282
+ * `adminAddress`. See technical doc §3–§4.
1283
+ */
1284
+ loadBatches: (params: {
1285
+ ownerAddress: string;
1286
+ }) => Promise<{
1287
+ harvestableBatches: CarbonHarvestableBatch[];
1288
+ retireableBatches: CarbonRetireableBatch[];
1289
+ totalClaimable: number;
1290
+ totalAvailable: number;
1291
+ totalRetired: number;
1292
+ }>;
1293
+ /**
1294
+ * Harvest (claim) the given batches: per entity, grant the owner authz to
1295
+ * transfer out of the entity admin account, then exec that transfer into
1296
+ * the owner's wallet (ordered pairs, 30-min grant). User-signed. See §5.2.
1297
+ */
1298
+ harvest: (params: {
1299
+ ownerAddress: string;
1300
+ tokens: Array<{
1301
+ id: string;
980
1302
  entityDid: string;
981
- newApiUrl: string;
982
- }) => Promise<{
983
- transactionHash: string;
1303
+ adminAddress: string;
1304
+ claimable: number;
984
1305
  }>;
985
- };
1306
+ }) => Promise<{
1307
+ transactionHash: string;
1308
+ harvestedBatchIds: string[];
1309
+ harvestedAmount: number;
1310
+ }>;
986
1311
  /**
987
- * Carbon credit batch service (IXO-2675). The editor declares the contract
988
- * only; the consumer app implements each method (run the owner/admin
989
- * reconciliation read, build + broadcast the harvest grant/exec pair and the
990
- * retire message, sign via its own wallet/SignX). Both writes are USER-signed
991
- * — the editor never signs on the user's behalf.
1312
+ * Retire (burn/offset) the given amounts from the owner's wallet. Single
1313
+ * owner-signed `MsgRetireToken`. Irreversible. `jurisdiction` arrives
1314
+ * pre-composed as a string (default "Global"); `reason` defaults to
1315
+ * "offset". See §5.1.
992
1316
  */
993
- carbon?: {
994
- /**
995
- * Reconcile the user's owner-side and entity-admin-side batches into the
996
- * unified view. Pure read (no signing). Performs provenance recovery for
997
- * transferred batches so every `harvestableBatch` carries `entityDid` +
998
- * `adminAddress`. See technical doc §3–§4.
999
- */
1000
- loadBatches: (params: {
1001
- ownerAddress: string;
1002
- }) => Promise<{
1003
- harvestableBatches: CarbonHarvestableBatch[];
1004
- retireableBatches: CarbonRetireableBatch[];
1005
- totalClaimable: number;
1006
- totalAvailable: number;
1007
- totalRetired: number;
1008
- }>;
1009
- /**
1010
- * Harvest (claim) the given batches: per entity, grant the owner authz to
1011
- * transfer out of the entity admin account, then exec that transfer into
1012
- * the owner's wallet (ordered pairs, 30-min grant). User-signed. See §5.2.
1013
- */
1014
- harvest: (params: {
1015
- ownerAddress: string;
1016
- tokens: Array<{
1017
- id: string;
1018
- entityDid: string;
1019
- adminAddress: string;
1020
- claimable: number;
1021
- }>;
1022
- }) => Promise<{
1023
- transactionHash: string;
1024
- harvestedBatchIds: string[];
1025
- harvestedAmount: number;
1026
- }>;
1027
- /**
1028
- * Retire (burn/offset) the given amounts from the owner's wallet. Single
1029
- * owner-signed `MsgRetireToken`. Irreversible. `jurisdiction` arrives
1030
- * pre-composed as a string (default "Global"); `reason` defaults to
1031
- * "offset". See §5.1.
1032
- */
1033
- retire: (params: {
1034
- owner: string;
1035
- reason?: string;
1036
- jurisdiction?: string;
1037
- tokens: Array<{
1038
- id: string;
1039
- amount: number;
1040
- }>;
1041
- }) => Promise<{
1042
- transactionHash: string;
1043
- retiredBatchIds: string[];
1044
- retiredAmount: number;
1317
+ retire: (params: {
1318
+ owner: string;
1319
+ reason?: string;
1320
+ jurisdiction?: string;
1321
+ tokens: Array<{
1322
+ id: string;
1323
+ amount: number;
1045
1324
  }>;
1046
- };
1325
+ }) => Promise<{
1326
+ transactionHash: string;
1327
+ retiredBatchIds: string[];
1328
+ retiredAmount: number;
1329
+ }>;
1330
+ }
1331
+ /**
1332
+ * Entity (domain) ownership service (IXO-2696). The editor declares the
1333
+ * contract only; the consumer app implements `transfer` — resolve a group
1334
+ * recipient to its DAO controller, ensure the recipient has an IID document,
1335
+ * build + broadcast `MsgTransferEntity`, and sign via its own wallet/SignX.
1336
+ * USER-signed and IRREVERSIBLE — the editor never signs on the user's behalf.
1337
+ */
1338
+ interface EntityService {
1047
1339
  /**
1048
- * Entity (domain) ownership service (IXO-2696). The editor declares the
1049
- * contract only; the consumer app implements `transfer` — resolve a group
1050
- * recipient to its DAO controller, ensure the recipient has an IID document,
1051
- * build + broadcast `MsgTransferEntity`, and sign via its own wallet/SignX.
1052
- * USER-signed and IRREVERSIBLE — the editor never signs on the user's behalf.
1340
+ * Transfer ownership of `entityDid` to `recipientDid`. The consumer resolves
1341
+ * a `did:ixo:entity:` group recipient to its `did:ixo:wasm:` controller
1342
+ * (reported back as `recipientResolved` when changed) and creates the
1343
+ * recipient's IID document first if it is missing (`createdRecipientIid`).
1344
+ * `ownerDid`/`ownerAddress` default to the connected user inside the host.
1345
+ * Proof of a real transfer is the returned `transactionHash`.
1053
1346
  */
1054
- entity?: {
1055
- /**
1056
- * Transfer ownership of `entityDid` to `recipientDid`. The consumer resolves
1057
- * a `did:ixo:entity:` group recipient to its `did:ixo:wasm:` controller
1058
- * (reported back as `recipientResolved` when changed) and creates the
1059
- * recipient's IID document first if it is missing (`createdRecipientIid`).
1060
- * `ownerDid`/`ownerAddress` default to the connected user inside the host.
1061
- * Proof of a real transfer is the returned `transactionHash`.
1062
- */
1063
- transfer: (params: {
1064
- entityDid: string;
1065
- recipientDid: string;
1066
- ownerDid?: string;
1067
- ownerAddress?: string;
1068
- }) => Promise<{
1069
- transactionHash: string;
1070
- recipientResolved?: string;
1071
- createdRecipientIid?: boolean;
1072
- }>;
1073
- };
1347
+ transfer: (params: {
1348
+ entityDid: string;
1349
+ recipientDid: string;
1350
+ ownerDid?: string;
1351
+ ownerAddress?: string;
1352
+ }) => Promise<{
1353
+ transactionHash: string;
1354
+ recipientResolved?: string;
1355
+ createdRecipientIid?: boolean;
1356
+ }>;
1357
+ }
1358
+ /**
1359
+ * The full service contract an action execution context can carry. Composed
1360
+ * from the per-domain service interfaces above so consumers can implement and
1361
+ * type one domain at a time; the runtime shape is unchanged.
1362
+ */
1363
+ interface ActionServices {
1364
+ http?: HttpService;
1365
+ email?: EmailService;
1366
+ notify?: NotifyService;
1367
+ bid?: BidService;
1368
+ claim?: ClaimService;
1369
+ collection?: CollectionService;
1370
+ collectionUsers?: CollectionUsersService;
1371
+ matrix?: MatrixCredentialService;
1372
+ integrations?: IntegrationsService;
1373
+ oracle?: OracleService;
1374
+ carbon?: CarbonService;
1375
+ entity?: EntityService;
1074
1376
  }
1075
1377
  interface OutputSchemaField {
1076
1378
  path: string;
@@ -1108,6 +1410,23 @@ interface ActionEventDefinition {
1108
1410
  */
1109
1411
  pendingDisplayFields?: string[];
1110
1412
  }
1413
+ /**
1414
+ * Declares what counts as proof that this action's side effect actually
1415
+ * happened. Enforced centrally by `executeActionBlock`: a run that returns
1416
+ * success without satisfying its proof declaration is recorded as
1417
+ * `state: 'failed'` (code `PROOF_MISSING`), never as `completed`.
1418
+ *
1419
+ * - `{ fields }` — at least one of the listed output paths (dot notation
1420
+ * allowed) must be truthy. Empty arrays and `false` do not count.
1421
+ * - `{ validate }` — custom predicate over the raw output.
1422
+ * - `'none'` — explicit opt-out for actions with no side effect to prove
1423
+ * (pure selection/config actions). Must be stated, not omitted.
1424
+ */
1425
+ type ActionProofDeclaration = {
1426
+ fields: string[];
1427
+ } | {
1428
+ validate: (output: Record<string, unknown>) => boolean;
1429
+ } | 'none';
1111
1430
  interface ActionDefinition<TInputs extends Record<string, any> = Record<string, any>> {
1112
1431
  type: string;
1113
1432
  /** UCAN-style ability string used by the flow compiler, e.g., "bid/submit". */
@@ -1115,6 +1434,29 @@ interface ActionDefinition<TInputs extends Record<string, any> = Record<string,
1115
1434
  sideEffect: boolean;
1116
1435
  defaultRequiresConfirmation: boolean;
1117
1436
  requiredCapability?: string;
1437
+ /** Proof-of-execution declaration. See {@link ActionProofDeclaration}. */
1438
+ proof: ActionProofDeclaration;
1439
+ /**
1440
+ * How many times this action is meant to run within a single flow.
1441
+ *
1442
+ * - 'once' (the default) — a one-shot step that reaches a terminal
1443
+ * `completed` state and is then Done.
1444
+ * - 'many' — a standing, repeatable capability that can fire any number of
1445
+ * times on a cadence the flow (not the action) decides — e.g. submitting a
1446
+ * claim every month. A repeatable block never latches to a terminal Done:
1447
+ * a `completed` runtime entry means "has fired at least once", and its real
1448
+ * progress is the count of successful runs in the audit trail, not this
1449
+ * single summary entry. Such blocks never withhold the flow.
1450
+ */
1451
+ cardinality?: 'once' | 'many';
1452
+ /**
1453
+ * How dynamic resolver results combine with the static `events` /
1454
+ * `outputSchema` baselines. 'merge' (the default) dedupes by event name /
1455
+ * field path with the dynamic entry winning; 'replace' hands the resolver
1456
+ * full control of the vocabulary (needed e.g. to hide the baseline until
1457
+ * configuration is complete).
1458
+ */
1459
+ dynamicResolutionMode?: 'merge' | 'replace';
1118
1460
  inputSchema?: object;
1119
1461
  /** Static output schema for action types with predictable output (e.g. email.send).
1120
1462
  * For action types with dynamic output (e.g. http.request), the schema is user-defined in inputs. */
@@ -1136,9 +1478,10 @@ interface ActionDefinition<TInputs extends Record<string, any> = Record<string,
1136
1478
  *
1137
1479
  * Consumers (trigger picker, flow compiler, event payload picker) prefer
1138
1480
  * `getDynamicEvents(inputs)` when defined and fall back to static `events`
1139
- * otherwise. The contract is: whatever this returns **is** the event list
1140
- * for the block — it does not merge with `events`. Include the static
1141
- * baseline yourself if you want it.
1481
+ * otherwise. By default the result is MERGED with the static `events`
1482
+ * baseline (deduped by name, dynamic wins). Set
1483
+ * `dynamicResolutionMode: 'replace'` when the resolver must control the
1484
+ * full vocabulary (e.g. returning [] to hide the baseline).
1142
1485
  */
1143
1486
  getDynamicEvents?: (inputs: TInputs) => ActionEventDefinition[];
1144
1487
  /**
@@ -1147,8 +1490,9 @@ interface ActionDefinition<TInputs extends Record<string, any> = Record<string,
1147
1490
  * refs so survey-derived fields like `output.surveyAnswers.<question>` show
1148
1491
  * up alongside the static baseline.
1149
1492
  *
1150
- * Returned array **replaces** `outputSchema` for this specific block (no
1151
- * merging). Include the baseline fields yourself.
1493
+ * By default the returned array is MERGED with the static `outputSchema`
1494
+ * baseline (deduped by path, dynamic wins); `dynamicResolutionMode:
1495
+ * 'replace'` gives the resolver full control.
1152
1496
  */
1153
1497
  getDynamicOutputSchema?: (inputs: TInputs) => OutputSchemaField[];
1154
1498
  /**
@@ -1234,7 +1578,7 @@ interface ExecuteNodeParams {
1234
1578
  */
1235
1579
  declare const executeNode: ({ node, actorDid, actorType, entityRoomId, context, action, pin }: ExecuteNodeParams) => Promise<ExecutionOutcome>;
1236
1580
 
1237
- type ActionExecutionCompletionState = 'completed' | 'failed' | 'awaiting_readback';
1581
+ type ActionExecutionCompletionState = 'completed' | 'failed' | 'awaiting_readback' | 'needs_verification';
1238
1582
 
1239
1583
  interface AuthorizationResult {
1240
1584
  authorized: boolean;
@@ -1455,9 +1799,9 @@ declare function readCompiledFlowFromYDoc(yDoc: Doc): CompiledFlow | null;
1455
1799
  */
1456
1800
  declare function decompileToBaseUcanFlow(compiled: CompiledFlow): BaseUcanFlow;
1457
1801
 
1458
- type FlowAgentPublicNodeState = 'Pending' | 'Blocked' | 'Overdue' | 'Done';
1802
+ type FlowAgentPublicNodeState = 'Pending' | 'Blocked' | 'Overdue' | 'Done' | 'Active';
1459
1803
  type FlowAgentRunPhase = 'Running' | 'Validating' | 'Failed' | 'Archived';
1460
- type FlowAgentBlockerCause = 'missing_input' | 'failed_upstream' | 'missing_ucan' | 'stale_config' | 'service_error' | 'external_confirmation_pending' | 'validation_mismatch' | 'unknown';
1804
+ type FlowAgentBlockerCause = 'missing_input' | 'failed_upstream' | 'missing_ucan' | 'stale_config' | 'service_error' | 'external_confirmation_pending' | 'validation_mismatch' | 'unverified_completion' | 'awaiting_verification' | 'unknown';
1461
1805
  type FlowAgentCommandType = 'diagnose_blocker' | 'assign_actor' | 'notify_actor' | 'execute_action' | 'validate_external_state' | 'submit_claim' | 'watch_udid' | 'archive_flow' | 'propose_config_change';
1462
1806
  type FlowAgentCommandStatus = 'queued' | 'leased' | 'running' | 'confirmed' | 'awaiting_readback' | 'failed' | 'skipped';
1463
1807
  type FlowAgentLedgerEventType = 'agent.decision' | 'agent.command' | 'agent.validation' | 'agent.escalation' | 'agent.memory';
@@ -1682,4 +2026,4 @@ declare function appendAgentLedgerEvent(yDoc: Doc, event: Omit<FlowAgentLedgerEv
1682
2026
  }): FlowAgentLedgerEvent;
1683
2027
  declare function readAgentLedgerEvents(yDoc: Doc, eventType?: FlowAgentLedgerEventType): FlowAgentLedgerEvent[];
1684
2028
 
1685
- export { type FlowAgentContext as $, type AuthorizationResult as A, type BaseUcanFlow as B, type CompilerRegistry as C, buildFlowAgentContext as D, type ExecuteNodeParams as E, type FlowRuntimeStateManager as F, cleanupExpiredFlowAgentLeases as G, createAgentCommand as H, evaluateFlowAgentPolicy as I, executeQueuedAgentCommands as J, getFlowAgentMaps as K, planRalphLoopCommands as L, type MergeResult as M, type NodeActionResult as N, queueAgentCommand as O, readAgentLedgerEvents as P, readQueuedAgentCommands as Q, type ReadFlowOptions as R, type SetupFlowOptions as S, releaseFlowAgentLease as T, tickFlowAgent as U, validateAgentCommand as V, validateFlowAgentLease as W, type BuildFlowAgentContextParams as X, type FlowAgentActor as Y, type FlowAgentCommand as Z, type FlowAgentCommandResult as _, buildAuthzFromProps as a, type FlowAgentExecutor as a0, type FlowAgentLease as a1, type FlowAgentNodeSnapshot as a2, type FlowAgentPublicNodeState as a3, type FlowAgentTickResult as a4, type ActionDefinition as a5, type ActionEventDefinition as a6, type OutputSchemaField as a7, type ActionServices as a8, type CompiledBlock as a9, type ActorConstraint as aA, type TTLConstraint as aB, type RuntimeRef as aC, type CompiledFlowNode as aD, type TriggerSpec as aE, isRuntimeRef as aF, type CompiledEdge as aa, type FlowAgentBlockerCause as ab, clearRuntimeForTemplateClone as ac, type ActionContext as ad, type ActionResult as ae, canMatches as af, computeAgentCommandId as ag, isCapabilityMatch as ah, isExternalMutation as ai, requiredCapabilityForCommand as aj, resourceMatches as ak, updateAgentCommand as al, type AcquireFlowAgentLeaseParams as am, type CreateAgentCommandParams as an, type EvaluateFlowAgentPolicyParams as ao, type FlowAgentOrchestratorOptions as ap, type FlowAgentServiceOptions as aq, type FlowAgentCommandBase as ar, type FlowAgentCommandStatus as as, type FlowAgentCommandType as at, type FlowAgentLedgerEvent as au, type FlowAgentLedgerEventType as av, type FlowAgentMaps as aw, type FlowAgentPolicyDecision as ax, type FlowAgentRunPhase as ay, type ConditionRef as az, buildFlowNodeFromBlock as b, createRuntimeStateManager as c, type ExecutionOutcome as d, executeNode as e, type ExecutionContext as f, readFlowFromEditor as g, readFlow as h, isAuthorized as i, setActiveEditor as j, getActiveEditor as k, compileBaseUcanFlow as l, readCompiledFlowFromYDoc as m, mergeCompiledFlows as n, decompileToBaseUcanFlow as o, type SetupFlowResult as p, type ReadFlowResult as q, readFlowAsBaseUcan as r, setupFlowFromBaseUcan as s, type ReadableEditor as t, type FlowCapability as u, type CompiledFlow as v, type FlowStrategy as w, FlowAgentService as x, acquireFlowAgentLease as y, appendAgentLedgerEvent as z };
2029
+ export { type FlowAgentContext as $, type AuthorizationResult as A, type BaseUcanFlow as B, type CompilerRegistry as C, buildFlowAgentContext as D, type ExecuteNodeParams as E, type FlowRuntimeStateManager as F, cleanupExpiredFlowAgentLeases as G, createAgentCommand as H, evaluateFlowAgentPolicy as I, executeQueuedAgentCommands as J, getFlowAgentMaps as K, planRalphLoopCommands as L, type MergeResult as M, type NodeActionResult as N, queueAgentCommand as O, readAgentLedgerEvents as P, readQueuedAgentCommands as Q, type ReadFlowOptions as R, type SetupFlowOptions as S, releaseFlowAgentLease as T, tickFlowAgent as U, validateAgentCommand as V, validateFlowAgentLease as W, type BuildFlowAgentContextParams as X, type FlowAgentActor as Y, type FlowAgentCommand as Z, type FlowAgentCommandResult as _, buildAuthzFromProps as a, type FlowAgentRunPhase as a$, type FlowAgentExecutor as a0, type FlowAgentLease as a1, type FlowAgentNodeSnapshot as a2, type FlowAgentPublicNodeState as a3, type FlowAgentTickResult as a4, type ActionDefinition as a5, type ActionEventDefinition as a6, type OutputSchemaField as a7, type ActionServices as a8, type ActionProofDeclaration as a9, removePendingInvocation as aA, findFailedListenersForSourceRun as aB, replayFailedListenerRun as aC, snapshotInputRefs as aD, computePendingInvocationId as aE, RUN_RECORD_AUDIT_TYPE as aF, type PendingInvocation as aG, type FailedListenerRun as aH, canMatches as aI, computeAgentCommandId as aJ, isCapabilityMatch as aK, isExternalMutation as aL, requiredCapabilityForCommand as aM, resourceMatches as aN, updateAgentCommand as aO, type AcquireFlowAgentLeaseParams as aP, type CreateAgentCommandParams as aQ, type EvaluateFlowAgentPolicyParams as aR, type FlowAgentOrchestratorOptions as aS, type FlowAgentServiceOptions as aT, type FlowAgentCommandBase as aU, type FlowAgentCommandStatus as aV, type FlowAgentCommandType as aW, type FlowAgentLedgerEvent as aX, type FlowAgentLedgerEventType as aY, type FlowAgentMaps as aZ, type FlowAgentPolicyDecision as a_, type RunRecordDetails as aa, type CompiledBlock as ab, type CompiledEdge as ac, type ActionHandlers as ad, type FlowAgentBlockerCause as ae, clearRuntimeForTemplateClone as af, type ActionContext as ag, type HttpService as ah, type EmailService as ai, type NotifyService as aj, type BidService as ak, type ClaimService as al, type CollectionService as am, type CollectionUsersService as an, type MatrixCredentialService as ao, type IntegrationsService as ap, type OracleService as aq, type CarbonService as ar, type EntityService as as, type ActionResult as at, appendRunRecord as au, readRunRecords as av, getPendingInvocationsMap as aw, getOrCreateBlockPendingMap as ax, readPendingInvocations as ay, queuePendingInvocation as az, buildFlowNodeFromBlock as b, type ConditionRef as b0, type ActorConstraint as b1, type TTLConstraint as b2, type RuntimeRef as b3, type CompiledFlowNode as b4, type TriggerSpec as b5, isRuntimeRef as b6, createRuntimeStateManager as c, type ExecutionOutcome as d, executeNode as e, type ExecutionContext as f, readFlowFromEditor as g, readFlow as h, isAuthorized as i, setActiveEditor as j, getActiveEditor as k, compileBaseUcanFlow as l, readCompiledFlowFromYDoc as m, mergeCompiledFlows as n, decompileToBaseUcanFlow as o, type SetupFlowResult as p, type ReadFlowResult as q, readFlowAsBaseUcan as r, setupFlowFromBaseUcan as s, type ReadableEditor as t, type FlowCapability as u, type CompiledFlow as v, type FlowStrategy as w, FlowAgentService as x, acquireFlowAgentLease as y, appendAgentLedgerEvent as z };