@wowok/skills 1.1.12 → 1.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.
@@ -6,6 +6,24 @@ An advanced e-commerce example demonstrating escrow with multiple order fund all
6
6
 
7
7
  ***
8
8
 
9
+ ## ⚠️ Running Principle
10
+
11
+ > **Run the example in full every time (repeatable).** This example uses `replaceExistName: true` on all object creations — each run generates new objects with new addresses. If you skip build steps, operations may silently act on orphaned objects from previous runs, producing incorrect results. Old objects' configurations do not reflect the current document version.
12
+
13
+ - **Execution order**: Part 1 (read) → Part 2 Steps 1–14 (build all) → Part 3 (customer flow) → Part 4 (fund allocation). Do not skip steps — each depends on objects created by prior steps.
14
+ - **Prerequisites**: `myshop_merchant` ≥ 0.05 WOW (gas), `myshop_customer` ≥ 0.15 WOW (gas + order payment). All on-chain operations require `env.confirmed: true`.
15
+
16
+ ### 🔐 Two-Step Confirmation Flow (Production Safety)
17
+
18
+ This example sets `env.confirmed: true` on irreversible operations (e.g., `publish: true` on Machine) for brevity. In real deployments, follow the two-step flow enforced by the ConfirmGate safety layer:
19
+
20
+ 1. **Phase 1 — Preview**: Call the tool **without** `env.confirmed`. The server returns `{ status: "pending_confirmation", confirmation_text: "..." }` containing the full operation summary, risk assessment, and irreversible-action warnings.
21
+ 2. **Phase 2 — Confirm**: Review `confirmation_text` with the user. Only after explicit user approval, call the tool again **with** `env.confirmed: true` to actually execute the on-chain transaction.
22
+
23
+ > Skipping Phase 1 means the user never sees the risk summary before gas is spent. Always preview first, then confirm.
24
+
25
+ ***
26
+
9
27
  ## Core Requirements & Features
10
28
 
11
29
  | Requirement | Description | Implementation |
@@ -23,7 +41,7 @@ An advanced e-commerce example demonstrating escrow with multiple order fund all
23
41
  2. **Privacy-Preserving Logistics**: Merchant handles logistics independently using any logistics provider. Tracking numbers are shared privately via Messenger (not on-chain), with only Merkle Root submitted on-chain as proof of communication
24
42
  3. **Reward Incentive Model**: Additional reward pool for excellent service (Wonderful reward) and compensation for lost packages
25
43
  4. **Multi-Path Workflow**: Order can complete through normal delivery, wonderful rating, or various return paths
26
- 5. **Dual-Signature Returns**: Return processes require both customer and merchant confirmation (threshold=2)
44
+ 5. **Dual-Signature Returns**: Receipt return processes require both customer and merchant confirmation (threshold=2). Non-receipt returns (customer never received goods) require only merchant confirmation of goods recovery (threshold=1), since the customer has nothing to return and their non-receipt was already confirmed when entering the Non-receipt Return node.
27
45
 
28
46
  ### Important Design Principle: "Who Completes the Key Action, Who Submits the Proof"
29
47
 
@@ -43,7 +61,7 @@ This advanced example demonstrates an enterprise-grade e-commerce system with:
43
61
 
44
62
  - **Single WIP-Verified Product**: One product listing ("The Three-Body Problem + Author Signature") with WIP file verification
45
63
  - **Multi-Path Workflow**: Order progress with delivery confirmation, wonderful rating, lost handling, and multiple return paths
46
- - **Dual-Signature Returns**: Return processes require confirmation from both customer and merchant
64
+ - **Dual-Signature Returns**: Receipt returns require both customer and merchant confirmation; non-receipt returns require only merchant confirmation of goods recovery
47
65
  - **Reward Incentive System**: Reward pool for excellent service and compensation for lost packages
48
66
  - **Time-Based Auto-Completion**: Orders auto-complete after time thresholds
49
67
 
@@ -101,7 +119,7 @@ graph TD
101
119
 
102
120
  RR["Receipt Return (Dual-Sig)<br/>Threshold = 2"]:::dualsig
103
121
  RF["Return Fail (Merchant)<br/>Time >= 10 days"]:::merchant
104
- RC["Return Complete (Dual-Sig)<br/>Threshold = 2"]:::dualsig
122
+ RC["Return Complete<br/>From Receipt: Dual-Sig (threshold=2)<br/>From Non-receipt: Merchant only (threshold=1)"]:::dualsig
105
123
 
106
124
  START --> OC
107
125
  START --> OR
@@ -167,6 +185,13 @@ Understanding the correct order for creating WoWok objects is crucial for a succ
167
185
  │ └────────┬────────┘ │
168
186
  │ │ │
169
187
  │ ▼ │
188
+ │ ┌─────────────────┐ │
189
+ │ │ Treasury │◄─── Requires: Permission (same as Service) │
190
+ │ │(myshop_treasury │ Aggregates merchant revenue │
191
+ │ │ _v2) │ Referenced by order_allocators (Phase 6) │
192
+ │ └────────┬────────┘ │
193
+ │ │ │
194
+ │ ▼ │
170
195
  │ Phase 2: Guard Creation │
171
196
  │ ═══════════════════════ │
172
197
  │ │
@@ -251,6 +276,7 @@ Understanding the correct order for creating WoWok objects is crucial for a succ
251
276
  | 1 | **Permission** | None | Permission is the foundation. Machine and Service both reference a permission object for access control. |
252
277
  | 1b | **Permission Indexes** | Permission | Grant permission indexes 1000 and 1001 to merchant. Required for Machine node operations. |
253
278
  | 2 | **Service (Empty)** | Permission | Create Service without publishing first to obtain its name. This name is used in Guard verification. |
279
+ | 2b | **Treasury** | Permission | Treasury aggregates merchant revenue. Uses same Permission as Service. Referenced by order\_allocators in Phase 7. |
254
280
  | 3 | **Guards** | Service Name | Guards must verify that orders belong to the correct Service. They query Service name and Progress state. |
255
281
  | 4 | **Machine** | Permission, Guards | Machine requires guards for node verification. Guards need Service name which is now available. |
256
282
  | 5 | **Machine Binding** | Service, Machine | Bind Machine to Service before publishing. Once published, Machine cannot be bound. |
@@ -266,6 +292,7 @@ Understanding the correct order for creating WoWok objects is crucial for a succ
266
292
  1. **Permission First**: Every major object (Machine, Service) requires a permission object. Create this first.
267
293
  2. **Permission Indexes**: Grant permission indexes 1000 and 1001 to merchant account. These are used in Machine node forwards.
268
294
  3. **Service Before Guards**: Create Service without publishing to get its name. Guards use Service name to verify orders belong to the correct service.
295
+ 3b. **Treasury for Fund Aggregation**: Create Treasury with the same Permission as the Service. Merchant revenue flows to the Treasury (not the Service address), making allocators inherently safe (R-C3-06) and aggregating public funds for operational distribution.
269
296
  4. **Guards Before Machine**: Machine nodes reference guards for verification. Create all guards first, then create Machine with guard references.
270
297
  5. **Machine Binding Before Publish**: Bind Machine to Service before publishing. Once published, Machine cannot be bound.
271
298
  6. **Arbitration Before Service Update**: Arbitration must be created before Service update so it can be bound to Service.
@@ -285,6 +312,12 @@ Phase 2: Service Creation
285
312
  ├── Publish: FALSE
286
313
  └── Record the Service address for Guard creation
287
314
 
315
+ Phase 2b: Treasury Creation
316
+ └── 2b. Create Treasury (myshop_treasury_v2)
317
+ ├── Permission: myshop_perm_v2 (same as Service)
318
+ ├── Type parameter: 0x2::wow::WOW
319
+ └── Aggregates merchant revenue; referenced by order_allocators (Phase 7)
320
+
288
321
  Phase 3: Guard Creation (Machine Guards)
289
322
  └── 3. Create Machine Guards (4 guards)
290
323
  ├── machine_merkle_root_v2 (verify string length = 66)
@@ -350,7 +383,9 @@ Reuse existing accounts from basic MyShop:
350
383
  - Account: `myshop_merchant` (store owner)
351
384
  - Account: `myshop_customer` (customer)
352
385
 
353
- Ensure both accounts have sufficient testnet WOW tokens.
386
+ > **Mandatory**: Ensure both accounts (`myshop_merchant` and `myshop_customer`) exist as local marks BEFORE proceeding. The Permission object (Step 2) grants indexes to `myshop_merchant` by name — if the account does not exist when the permission is created, the grant will silently fail or target the wrong account, causing "Permission denied" errors in later steps.
387
+
388
+ Ensure both accounts have sufficient mainnet WOW tokens.
354
389
 
355
390
  ***
356
391
 
@@ -372,7 +407,7 @@ Create a new permission object for the advanced shop.
372
407
  },
373
408
  "env": {
374
409
  "account": "myshop_merchant",
375
- "network": "testnet",
410
+ "network": "mainnet",
376
411
  "no_cache": true
377
412
  }
378
413
  }
@@ -406,7 +441,7 @@ Add custom permission indexes for advanced operations.
406
441
  },
407
442
  "env": {
408
443
  "account": "myshop_merchant",
409
- "network": "testnet",
444
+ "network": "mainnet",
410
445
  "no_cache": true
411
446
  }
412
447
  }
@@ -434,7 +469,7 @@ Add custom permission indexes for advanced operations.
434
469
  },
435
470
  "env": {
436
471
  "account": "myshop_merchant",
437
- "network": "testnet",
472
+ "network": "mainnet",
438
473
  "no_cache": true
439
474
  }
440
475
  }
@@ -462,7 +497,7 @@ Create the Service without publishing to obtain its address for Guard creation.
462
497
  },
463
498
  "env": {
464
499
  "account": "myshop_merchant",
465
- "network": "testnet",
500
+ "network": "mainnet",
466
501
  "no_cache": true
467
502
  }
468
503
  }
@@ -472,6 +507,39 @@ Create the Service without publishing to obtain its address for Guard creation.
472
507
 
473
508
  ***
474
509
 
510
+ ### Step 3b: Create Treasury (Merchant Revenue Aggregation)
511
+
512
+ Create a Treasury object to aggregate merchant revenue. The Treasury uses the **same Permission** as the Service (`myshop_perm_v2`) for consistency — a single permission organization governs both fund collection and service operations.
513
+
514
+ **Prompt**: Create Treasury "myshop\_treasury\_v2" with permission "myshop\_perm\_v2", type parameter "0x2::wow::WOW".
515
+
516
+ ```json
517
+ {
518
+ "operation_type": "treasury",
519
+ "data": {
520
+ "object": {
521
+ "name": "myshop_treasury_v2",
522
+ "type_parameter": "0x2::wow::WOW",
523
+ "permission": "myshop_perm_v2",
524
+ "replaceExistName": true
525
+ },
526
+ "description": "Treasury for aggregating MyShop merchant revenue. Uses the same Permission as the Service (myshop_perm_v2) for consistency — a single permission organization governs both fund collection and service operations."
527
+ },
528
+ "env": {
529
+ "account": "myshop_merchant",
530
+ "network": "mainnet",
531
+ "no_cache": true
532
+ }
533
+ }
534
+ ```
535
+
536
+ > **Treasury-First Rule**: Following the fund-flow design pattern established in the Insurance example, merchant revenue flows to `myshop_treasury_v2` (not directly to the Service address). This:
537
+ > 1. **Aggregates public funds** for operational distribution and accounting
538
+ > 2. **Makes allocators inherently safe** (R-C3-06) — funds always flow to the fixed Treasury regardless of caller, so no Signer binding is needed in the Guard
539
+ > 3. **Uses permission consistency** — Treasury and Service share `myshop_perm_v2`, ensuring unified governance
540
+
541
+ ***
542
+
475
543
  ### Step 4: Create Guards (Machine Guards)
476
544
 
477
545
  Create Guards using the Service address. Guards verify order state and service ownership.
@@ -487,7 +555,7 @@ Create Guards using the Service address. Guards verify order state and service o
487
555
  >
488
556
  > Key instructions used in this example:
489
557
  > - Query ID 1563 (`order.service`): Returns the Service address of an Order — used to verify order belongs to this service
490
- > - Query ID for `progress.node_current`: Returns current node name — used to verify order at specific workflow node
558
+ > - Query ID 1253 (`progress.current`): Returns current node name — used to verify order at specific workflow node
491
559
 
492
560
  **Guard 1: machine_merkle_root_v2** - Verify Merkle Root string length = 66 (0x prefix + 64 hex chars)
493
561
 
@@ -514,12 +582,91 @@ Create Guards using the Service address. Guards verify order state and service o
514
582
  },
515
583
  "env": {
516
584
  "account": "myshop_merchant",
517
- "network": "testnet",
585
+ "network": "mainnet",
518
586
  "no_cache": true
519
587
  }
520
588
  }
521
589
  ```
522
590
 
591
+ **Guard 1b: machine_messenger_proof_v2** - Strict-mode privacy delivery (alternative to Guard 1)
592
+
593
+ > **Two standard modes for "privacy info delivered via Messenger but not suitable for on-chain publication":**
594
+ >
595
+ > | Mode | Guard | Submission | Verification | Trust model |
596
+ > |------|-------|-----------|-------------|-------------|
597
+ > | **Broad** | `machine_merkle_root_v2` (Guard 1) | String (Merkle Root) | Length == 66 | Trusts submitter honesty; counterparty disputes via own Messenger log. Arbitration basis. |
598
+ > | **Strict** | `machine_messenger_proof_v2` (Guard 1b) | Proof addr + Order addr | Signer==proof.signer ∧ proof.time>order.time ∧ order.service==service | Submitter accountability (谁得利谁举证); no content verification. |
599
+ >
600
+ > Machine forwards may reference **either** Guard 1 or Guard 1b — choose before publishing (Forward.guard is immutable). The same strict Guard can be reused across all forwards that need Merkle-Root verification (shipping, lost, returns, etc.).
601
+
602
+ ```json
603
+ {
604
+ "operation_type": "guard",
605
+ "data": {
606
+ "namedNew": {
607
+ "name": "machine_messenger_proof_v2",
608
+ "replaceExistName": true
609
+ },
610
+ "description": "Strict-mode privacy delivery: verify Signer==proof.signer AND proof.time>order.time AND order.service==service (verifier submits Proof+Order object addresses)",
611
+ "table": [
612
+ {"identifier": 0, "b_submission": true, "value_type": "Address", "name": "Proof object from submitChainProof"},
613
+ {"identifier": 1, "b_submission": true, "value_type": "Address", "name": "Order object submitted by verifier"},
614
+ {"identifier": 2, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
615
+ ],
616
+ "root": {
617
+ "type": "logic_and",
618
+ "nodes": [
619
+ {
620
+ "type": "logic_equal",
621
+ "nodes": [
622
+ {"type": "context", "context": "Signer"},
623
+ {"type": "query", "query": "proof.signer", "object": {"identifier": 0}, "parameters": []}
624
+ ]
625
+ },
626
+ {
627
+ "type": "logic_as_u256_greater",
628
+ "nodes": [
629
+ {"type": "query", "query": "proof.time", "object": {"identifier": 0}, "parameters": []},
630
+ {"type": "query", "query": "order.time", "object": {"identifier": 1}, "parameters": []}
631
+ ]
632
+ },
633
+ {
634
+ "type": "logic_equal",
635
+ "nodes": [
636
+ {"type": "query", "query": "order.service", "object": {"identifier": 1}, "parameters": []},
637
+ {"type": "identifier", "identifier": 2}
638
+ ]
639
+ }
640
+ ]
641
+ }
642
+ },
643
+ "env": {
644
+ "account": "myshop_merchant",
645
+ "network": "mainnet",
646
+ "no_cache": true
647
+ }
648
+ }
649
+ ```
650
+
651
+ **Three conditions (logic_and):**
652
+ 1. **Submitter accountability** — `logic_equal[context(Signer), query("proof.signer", obj=proof)]`: the transaction signer must be the Proof's signer (the party who generated the Proof via `submitChainProof`). Suppresses R-C3-01.
653
+ 2. **Freshness** — `logic_as_u256_greater[query("proof.time", obj=proof), query("order.time", obj=order)]`: the Proof was created after the order, preventing stale-proof replay. (`proof.time` has invariant `clock_derived`, always > 0.)
654
+ 3. **Project binding** — `logic_equal[query("order.service", obj=order), identifier[2]]`: the submitted Order belongs to `three_body_signature_service_v2`. Suppresses R-C3-05 (cross-project bypass).
655
+
656
+ **Generating the Proof (provider side, before submitting to the forward):**
657
+ ```json
658
+ // SDK call: messenger.submitChainProof(env, peerAddress, description?)
659
+ // - about_address is set to peerAddress (the customer's address)
660
+ // - pass the order_id in description to associate the Proof with the order
661
+ // Returns: { proofAddress, txHash }
662
+ ```
663
+
664
+ **Runtime submission (verifier side, advancing the Machine forward):**
665
+ - Broad mode (Guard 1): submit one String identifier — the Merkle Root.
666
+ - Strict mode (Guard 1b): submit two Address identifiers — the Proof object address (identifier 0) and the Order object address (identifier 1).
667
+
668
+ > No content verification is performed in either mode — only submission responsibility. The counterparty can dispute a fraudulent claim by checking their own Messenger conversation for the alleged dialogue. This follows the 谁得利谁举证 (whoever benefits bears the burden of proof) principle.
669
+
523
670
  **Guard 2: machine_time_10d_v2** - Verify 10-day timeout (864000000 ms)
524
671
 
525
672
  ```json
@@ -551,7 +698,7 @@ Create Guards using the Service address. Guards verify order state and service o
551
698
  },
552
699
  "env": {
553
700
  "account": "myshop_merchant",
554
- "network": "testnet",
701
+ "network": "mainnet",
555
702
  "no_cache": true
556
703
  }
557
704
  }
@@ -588,7 +735,7 @@ Create Guards using the Service address. Guards verify order state and service o
588
735
  },
589
736
  "env": {
590
737
  "account": "myshop_merchant",
591
- "network": "testnet",
738
+ "network": "mainnet",
592
739
  "no_cache": true
593
740
  }
594
741
  }
@@ -604,9 +751,10 @@ Create Guards using the Service address. Guards verify order state and service o
604
751
  "data": {
605
752
  "namedNew": {
606
753
  "name": "service_merchant_win_v2",
754
+ "tags": ["order", "merchant-win", "level3-scene-combined"],
607
755
  "replaceExistName": true
608
756
  },
609
- "description": "Verify order at merchant win nodes (Order Complete, Wonderful, Return Fail) AND order belongs to three_body_signature_service_v2",
757
+ "description": "Verify order at merchant win nodes (Order Complete, Wonderful, Return Fail) AND order belongs to three_body_signature_service_v2. VERIFIER CONSTRAINT LEVEL 3 (scene-combined): No Signer binding needed because the allocator uses sharing.who=Entity (myshop_treasury_v2) — funds always flow to the Treasury regardless of caller (R-C3-06 safe). Two-fold verification: (1) order at merchant win node, (2) order belongs to this service (prevents cross-service theft, R-C3-05).",
610
758
  "table": [
611
759
  {"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
612
760
  {"identifier": 1, "b_submission": false, "value_type": "String", "value": "Order Complete"},
@@ -623,21 +771,21 @@ Create Guards using the Service address. Guards verify order state and service o
623
771
  {
624
772
  "type": "logic_string_nocase_equal",
625
773
  "nodes": [
626
- {"type": "query", "query": 1253, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
774
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
627
775
  {"type": "identifier", "identifier": 1}
628
776
  ]
629
777
  },
630
778
  {
631
779
  "type": "logic_string_nocase_equal",
632
780
  "nodes": [
633
- {"type": "query", "query": 1253, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
781
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
634
782
  {"type": "identifier", "identifier": 2}
635
783
  ]
636
784
  },
637
785
  {
638
786
  "type": "logic_string_nocase_equal",
639
787
  "nodes": [
640
- {"type": "query", "query": 1253, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
788
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
641
789
  {"type": "identifier", "identifier": 3}
642
790
  ]
643
791
  }
@@ -646,7 +794,7 @@ Create Guards using the Service address. Guards verify order state and service o
646
794
  {
647
795
  "type": "logic_equal",
648
796
  "nodes": [
649
- {"type": "query", "query": 1563, "object": {"identifier": 0}, "parameters": []},
797
+ {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
650
798
  {"type": "identifier", "identifier": 4}
651
799
  ]
652
800
  }
@@ -655,17 +803,91 @@ Create Guards using the Service address. Guards verify order state and service o
655
803
  },
656
804
  "env": {
657
805
  "account": "myshop_merchant",
658
- "network": "testnet",
806
+ "network": "mainnet",
659
807
  "no_cache": true
660
808
  }
661
809
  }
662
810
  ```
663
811
 
664
- **Guard Logic:**
665
- 1. 验证订单当前节点是 Order Complete、Wonderful Return Fail(商家胜利节点)
666
- 2. 验证订单的 Service 地址等于当前 Guard 所属的 Service 地址(使用 `order.service` 查询指令 ID 1563)
812
+ **Guard Explanation (Two-fold Verification — Level 3 Scene-Combined):**
813
+ - **Table Item 0**: Order address (submitted at runtime)
814
+ - **Table Items 1-3**: Constant strings "Order Complete", "Wonderful", "Return Fail" (merchant win node names)
815
+ - **Table Item 4**: Constant address `three_body_signature_service_v2` (this service's on-chain address)
816
+ - **Condition 1 — Merchant Win Node**: `logic_or` of three `logic_string_nocase_equal` checks against `query("progress.current", witness="OrderProgress")` — verifies the order is at one of the merchant win nodes
817
+ - **Condition 2 — Service Ownership**: `logic_equal[query("order.service"), identifier[4]]` — verifies the submitted Order's `service` field equals `three_body_signature_service_v2`, **preventing cross-service theft** where someone submits another service's order (R-C3-05)
818
+ - **root**: `logic_and` of both conditions — all must pass for allocation to proceed
819
+
820
+ > **Risk Elimination (R-C3-06) — Level 3 Scene-Combined Design**: The allocator uses `"who": {"Entity": {"name_or_address": "myshop_treasury_v2"}}` (funds flow to the fixed Treasury address). This is inherently safe because funds go to a fixed recipient regardless of caller — **no Signer binding is needed**. The scene itself (Entity sharing to Treasury) ensures fund-flow safety, which is the Level 3 scene-combined pattern. Removing the Signer binding also eliminates R-C4-04 (Level 1 strict binding convenience warning) and avoids the lock-in risk of binding to a fixed merchant address.
821
+ ```
822
+
823
+ **Guard 4 — Alternative Shorthand Form (VecString + vec_contains_string_nocase)**
824
+
825
+ The `logic_or` of three `logic_string_nocase_equal` checks above can be collapsed into a single `vec_contains_string_nocase` over a `VecString` constant. Both forms are **semantically equivalent** (verified by `guard-examples-lint.spec.ts` → "Semantic Equivalence" tests: identical risk diagnostics, identical `root_type`, identical `errors`/`ready` state). The shorthand is preferred when the candidate set has ≥ 2 entries — it scales linearly with the vector length instead of duplicating the query node N times.
826
+
827
+ ```json
828
+ {
829
+ "operation_type": "guard",
830
+ "data": {
831
+ "namedNew": {
832
+ "name": "service_merchant_win_v2",
833
+ "tags": ["order", "merchant-win", "level3-scene-combined"],
834
+ "replaceExistName": true
835
+ },
836
+ "description": "Verify order at merchant win nodes (Order Complete, Wonderful, Return Fail) AND order belongs to three_body_signature_service_v2. SHORTHAND: collapses three String constants + logic_or[logic_string_nocase_equal x 3] into a single VecString + vec_contains_string_nocase. Semantically equivalent to the original form (see guard-examples-lint 'Semantic Equivalence' tests).",
837
+ "table": [
838
+ {"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
839
+ {"identifier": 1, "b_submission": false, "value_type": "VecString", "value": ["Order Complete", "Wonderful", "Return Fail"], "name": "merchant_win_nodes"},
840
+ {"identifier": 2, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
841
+ ],
842
+ "root": {
843
+ "type": "logic_and",
844
+ "nodes": [
845
+ {
846
+ "type": "vec_contains_string_nocase",
847
+ "nodes": [
848
+ {"type": "identifier", "identifier": 1},
849
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []}
850
+ ]
851
+ },
852
+ {
853
+ "type": "logic_equal",
854
+ "nodes": [
855
+ {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
856
+ {"type": "identifier", "identifier": 2}
857
+ ]
858
+ }
859
+ ]
860
+ }
861
+ },
862
+ "env": {
863
+ "account": "myshop_merchant",
864
+ "network": "mainnet",
865
+ "no_cache": true
866
+ }
867
+ }
667
868
  ```
668
869
 
870
+ **Shorthand Equivalence Explanation:**
871
+
872
+ | Aspect | Original Form | Shorthand Form |
873
+ |---|---|---|
874
+ | `table` count | 5 entries (1 Address + 3 String + 1 Address) | 3 entries (1 Address + 1 VecString + 1 Address) |
875
+ | Condition 1 node | `logic_or` of 3 × `logic_string_nocase_equal` | `vec_contains_string_nocase` (single node) |
876
+ | Condition 2 node | `logic_equal` (unchanged) | `logic_equal` (unchanged) |
877
+ | `root` type | `logic_and` | `logic_and` (identical) |
878
+ | Risk diagnostics (R-C3-*) | identical | identical (security-equivalent) |
879
+ | Lint diagnostics (LE-04, SG-01, SG-03) | identical | identical |
880
+ | SH-03 warnings (missing `name`) | 3 (the 3 unnamed String constants) | 0 (the VecString is named `merchant_win_nodes`) |
881
+ | Total warnings | 5 | 2 (3 fewer — the eliminated SH-03s) |
882
+
883
+ **Why the shorthand is preferred:**
884
+ - **Fewer table entries**: 3 vs 5 (40% reduction). Adding a new merchant-win node is a one-line edit to the `value` array instead of a new identifier + new `logic_string_nocase_equal` branch.
885
+ - **No SH-03 nits**: The single `VecString` entry is naturally named (`merchant_win_nodes`), eliminating the 3 missing-name warnings.
886
+ - **Linear scaling**: For N candidate nodes, the original grows as O(N) identifiers + O(N) `logic_string_nocase_equal` branches under one `logic_or` (capped at 8 children). The shorthand stays at 1 identifier + 1 `vec_contains_string_nocase` node regardless of N.
887
+ - **Same security posture**: Risk-layer diagnostics are byte-identical (R-C3-05, R-C3-06, etc. all evaluate the same), so the Level 3 scene-combined design and R-C3-06 suppression are preserved.
888
+
889
+ **Equivalence verification**: See `d:\wowok\agent\mcp\src\knowledge\__tests__\guard-examples-lint.spec.ts` → describe block `"Semantic Equivalence — Shorthand vs Original (VecString + vec_contains_string_nocase)"`. The 8-test suite verifies: identical `root_type`, identical `errors`/`ready`, identical risk diagnostic codes, identical lint diagnostic codes (excluding SH-03), fewer SH-03 warnings, reduced `table_count`, no SDK syntax errors, and complete `risk_assessment`.
890
+
669
891
  **Guard 5: machine_service_order_v2** - Verify order belongs to this Service
670
892
 
671
893
  ```json
@@ -686,7 +908,7 @@ Create Guards using the Service address. Guards verify order state and service o
686
908
  "nodes": [
687
909
  {
688
910
  "type": "query",
689
- "query": 1563,
911
+ "query": "order.service",
690
912
  "object": {"identifier": 0},
691
913
  "parameters": []
692
914
  },
@@ -699,7 +921,7 @@ Create Guards using the Service address. Guards verify order state and service o
699
921
  },
700
922
  "env": {
701
923
  "account": "myshop_merchant",
702
- "network": "testnet",
924
+ "network": "mainnet",
703
925
  "no_cache": true
704
926
  }
705
927
  }
@@ -715,9 +937,10 @@ Create Guards using the Service address. Guards verify order state and service o
715
937
  "data": {
716
938
  "namedNew": {
717
939
  "name": "service_customer_win_v2",
940
+ "tags": ["order", "customer-win", "level2-dynamic-binding"],
718
941
  "replaceExistName": true
719
942
  },
720
- "description": "Verify order at customer win nodes (Lost, Return Complete) AND order belongs to three_body_signature_service_v2",
943
+ "description": "Verify order at customer win nodes (Lost, Return Complete) AND order belongs to three_body_signature_service_v2. VERIFIER CONSTRAINT LEVEL 2 (dynamic identity binding): Signer bound to query('order.owner') — only the order's rightful owner can trigger the refund. RISK ELIMINATION: Three-fold verification - (1) order at customer win node, (2) signer is order.owner (dynamic query, prevents fund theft - only order owner can trigger their own refund), (3) order belongs to three_body_signature_service_v2 (prevents cross-service theft).",
721
944
  "table": [
722
945
  {"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
723
946
  {"identifier": 1, "b_submission": false, "value_type": "String", "value": "Lost"},
@@ -733,14 +956,14 @@ Create Guards using the Service address. Guards verify order state and service o
733
956
  {
734
957
  "type": "logic_string_nocase_equal",
735
958
  "nodes": [
736
- {"type": "query", "query": 1253, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
959
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
737
960
  {"type": "identifier", "identifier": 1}
738
961
  ]
739
962
  },
740
963
  {
741
964
  "type": "logic_string_nocase_equal",
742
965
  "nodes": [
743
- {"type": "query", "query": 1253, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
966
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
744
967
  {"type": "identifier", "identifier": 2}
745
968
  ]
746
969
  }
@@ -749,7 +972,14 @@ Create Guards using the Service address. Guards verify order state and service o
749
972
  {
750
973
  "type": "logic_equal",
751
974
  "nodes": [
752
- {"type": "query", "query": 1563, "object": {"identifier": 0}, "parameters": []},
975
+ {"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
976
+ {"type": "context", "context": "Signer"}
977
+ ]
978
+ },
979
+ {
980
+ "type": "logic_equal",
981
+ "nodes": [
982
+ {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
753
983
  {"type": "identifier", "identifier": 3}
754
984
  ]
755
985
  }
@@ -758,17 +988,96 @@ Create Guards using the Service address. Guards verify order state and service o
758
988
  },
759
989
  "env": {
760
990
  "account": "myshop_merchant",
761
- "network": "testnet",
991
+ "network": "mainnet",
762
992
  "no_cache": true
763
993
  }
764
994
  }
765
995
  ```
766
996
 
767
- **Guard Logic:**
768
- 1. 验证订单当前节点是 Lost Return Complete(客户胜利节点)
769
- 2. 验证订单的 Service 地址等于当前 Guard 所属的 Service 地址(使用 `order.service` 查询指令 ID 1563)
997
+ **Guard Explanation (Three-fold Verification — Level 2 Dynamic Binding):**
998
+ - **Table Item 0**: Order address (submitted at runtime)
999
+ - **Table Items 1-2**: Constant strings "Lost", "Return Complete" (customer win node names)
1000
+ - **Table Item 3**: Constant address `three_body_signature_service_v2` (this service's on-chain address)
1001
+ - **Condition 1 — Customer Win Node**: `logic_or` of two `logic_string_nocase_equal` checks against `query("progress.current", witness="OrderProgress")` — verifies the order is at one of the customer win nodes
1002
+ - **Condition 2 — Signer is Order Owner (Level 2 Dynamic)**: `logic_equal[query("order.owner"), context(Signer)]` — verifies the transaction caller is the order's owner (dynamic query, not a fixed address). This is the **Level 2 dynamic identity binding** pattern: the Signer is bound to a query result (not a fixed address), so it survives personnel changes and avoids the R-C4-04 lock-in risk. **Prevents fund theft by unauthorized callers** (R-C3-01/R-C3-06). Only the customer who placed the order can trigger the refund.
1003
+ - **Condition 3 — Service Ownership**: `logic_equal[query("order.service"), identifier[3]]` — verifies the submitted Order's `service` field equals `three_body_signature_service_v2`, **preventing cross-service theft** where someone submits another service's order (R-C3-05)
1004
+ - **root**: `logic_and` of all three conditions — all must pass for allocation to proceed
1005
+
1006
+ > **Risk Elimination (R-C3-06) — CRITICAL — Level 2 Dynamic Binding**: The allocator uses `"who": {"Signer": "signer"}` (funds go to the caller). This is safe ONLY because Condition 2 binds the Signer to `query("order.owner")` (dynamic query — Level 2). Without this binding, anyone could submit any Lost/Return Complete order and steal 100% of funds. The dynamic query pattern ensures funds always flow to the order's rightful owner, regardless of who calls the transaction. Unlike Level 1 (fixed address), Level 2 dynamic binding does NOT trigger R-C4-04 because the bound identity is a query result, not an immutable address constant.
1007
+ ```
1008
+
1009
+ **Guard 6 — Alternative Shorthand Form (VecString + vec_contains_string_nocase)**
1010
+
1011
+ The `logic_or` of two `logic_string_nocase_equal` checks above can be collapsed into a single `vec_contains_string_nocase` over a `VecString` constant. Both forms are **semantically equivalent** (verified by `guard-examples-lint.spec.ts` → "Semantic Equivalence — Guard 6 Shorthand" tests: identical risk diagnostics, identical `root_type`, identical `errors`/`ready` state).
1012
+
1013
+ ```json
1014
+ {
1015
+ "operation_type": "guard",
1016
+ "data": {
1017
+ "namedNew": {
1018
+ "name": "service_customer_win_v2",
1019
+ "tags": ["order", "customer-win", "level2-dynamic-binding"],
1020
+ "replaceExistName": true
1021
+ },
1022
+ "description": "Verify order at customer win nodes (Lost, Return Complete) AND order belongs to three_body_signature_service_v2. SHORTHAND: collapses two String constants + logic_or[logic_string_nocase_equal x 2] into a single VecString + vec_contains_string_nocase. Semantically equivalent to the original form (see guard-examples-lint 'Semantic Equivalence — Guard 6 Shorthand' tests).",
1023
+ "table": [
1024
+ {"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
1025
+ {"identifier": 1, "b_submission": false, "value_type": "VecString", "value": ["Lost", "Return Complete"], "name": "customer_win_nodes"},
1026
+ {"identifier": 2, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
1027
+ ],
1028
+ "root": {
1029
+ "type": "logic_and",
1030
+ "nodes": [
1031
+ {
1032
+ "type": "vec_contains_string_nocase",
1033
+ "nodes": [
1034
+ {"type": "identifier", "identifier": 1},
1035
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []}
1036
+ ]
1037
+ },
1038
+ {
1039
+ "type": "logic_equal",
1040
+ "nodes": [
1041
+ {"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
1042
+ {"type": "context", "context": "Signer"}
1043
+ ]
1044
+ },
1045
+ {
1046
+ "type": "logic_equal",
1047
+ "nodes": [
1048
+ {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
1049
+ {"type": "identifier", "identifier": 2}
1050
+ ]
1051
+ }
1052
+ ]
1053
+ }
1054
+ },
1055
+ "env": {
1056
+ "account": "myshop_merchant",
1057
+ "network": "mainnet",
1058
+ "no_cache": true
1059
+ }
1060
+ }
770
1061
  ```
771
1062
 
1063
+ **Shorthand Equivalence Explanation:**
1064
+
1065
+ | Aspect | Original Form | Shorthand Form |
1066
+ |---|---|---|
1067
+ | `table` count | 4 entries (1 Address + 2 String + 1 Address) | 3 entries (1 Address + 1 VecString + 1 Address) |
1068
+ | Condition 1 node | `logic_or` of 2 × `logic_string_nocase_equal` | `vec_contains_string_nocase` (single node) |
1069
+ | Condition 2 node (Signer binding) | `logic_equal` (unchanged) | `logic_equal` (unchanged) |
1070
+ | Condition 3 node (Service ownership) | `logic_equal` (unchanged) | `logic_equal` (unchanged) |
1071
+ | `root` type | `logic_and` | `logic_and` (identical) |
1072
+ | Risk diagnostics (R-C3-*) | identical | identical (security-equivalent) |
1073
+ | Lint diagnostics (LE-04, SG-01, SG-03) | identical | identical |
1074
+ | SH-03 warnings (missing `name`) | 2 (the 2 unnamed String constants) | 0 (the VecString is named `customer_win_nodes`) |
1075
+ | Total warnings | 4 | 2 (2 fewer — the eliminated SH-03s) |
1076
+
1077
+ **Case-sensitivity note (critical)**: The source uses `logic_string_nocase_equal` (case-insensitive), so the target is `vec_contains_string_nocase` (case-insensitive). If the source had used `logic_equal` on String (case-sensitive — "Lost" ≠ "lost"), the target would have to be `vec_contains_string` (case-sensitive) to preserve semantics. **Mixing case-sensitive and case-insensitive operators in the same `logic_or` is NOT convertible** — the original `logic_or` must be kept because there is no single `vec_contains_*` variant that captures both behaviors. This is a fundamental limitation of the contains shorthand: it is syntactic sugar, not a universal replacement.
1078
+
1079
+ **Equivalence verification**: See `d:\wowok\agent\mcp\src\knowledge\__tests__\guard-examples-lint.spec.ts` → describe block `"Semantic Equivalence — Guard 6 Shorthand (service_customer_win_v2: VecString + vec_contains_string_nocase)"`. The 8-test suite verifies: identical `root_type`, identical `errors`/`ready`, identical risk diagnostic codes, identical lint diagnostic codes (excluding SH-03), fewer SH-03 warnings, reduced `table_count`, no SDK syntax errors, and complete `risk_assessment`.
1080
+
772
1081
  ***
773
1082
 
774
1083
  ### Step 5: Create Machine (Multi-Path Workflow)
@@ -1005,25 +1314,19 @@ Create Machine with all nodes and guards in a single operation.
1005
1314
  },
1006
1315
  {
1007
1316
  "name": "Confirm Return Received",
1008
- "weight": 1,
1009
- "namedOperator": ""
1317
+ "permissionIndex": 1001,
1318
+ "weight": 1
1010
1319
  }
1011
1320
  ]
1012
1321
  },
1013
1322
  {
1014
1323
  "prev_node": "Non-receipt Return",
1015
- "threshold": 2,
1324
+ "threshold": 1,
1016
1325
  "forwards": [
1017
1326
  {
1018
- "name": "Submit Return Merkle Root",
1019
- "weight": 1,
1020
- "namedOperator": "",
1021
- "guard": { "guard": "machine_merkle_root_v2" }
1022
- },
1023
- {
1024
- "name": "Confirm Return Received",
1025
- "weight": 1,
1026
- "namedOperator": ""
1327
+ "name": "Confirm Goods Recovered",
1328
+ "permissionIndex": 1001,
1329
+ "weight": 1
1027
1330
  }
1028
1331
  ]
1029
1332
  }
@@ -1034,7 +1337,7 @@ Create Machine with all nodes and guards in a single operation.
1034
1337
  },
1035
1338
  "env": {
1036
1339
  "account": "myshop_merchant",
1037
- "network": "testnet",
1340
+ "network": "mainnet",
1038
1341
  "no_cache": true
1039
1342
  }
1040
1343
  }
@@ -1066,7 +1369,7 @@ Machine must be published before binding to Service.
1066
1369
  },
1067
1370
  "env": {
1068
1371
  "account": "myshop_merchant",
1069
- "network": "testnet",
1372
+ "network": "mainnet",
1070
1373
  "no_cache": true
1071
1374
  }
1072
1375
  }
@@ -1089,7 +1392,7 @@ Bind the Machine to the Service. **Important**: The Service must be unpublished
1089
1392
  },
1090
1393
  "env": {
1091
1394
  "account": "myshop_merchant",
1092
- "network": "testnet",
1395
+ "network": "mainnet",
1093
1396
  "no_cache": true
1094
1397
  }
1095
1398
  }
@@ -1128,7 +1431,8 @@ Create an Arbitration object as the final on-chain mechanism for protecting user
1128
1431
  "data": {
1129
1432
  "object": {
1130
1433
  "name": "myshop_arbitration_v2",
1131
- "replaceExistName": true
1434
+ "replaceExistName": true,
1435
+ "permission": "myshop_perm_v2"
1132
1436
  },
1133
1437
  "description": "Arbitration for MyShop Advanced - Final dispute resolution mechanism",
1134
1438
  "voting_guard": {
@@ -1145,7 +1449,7 @@ Create an Arbitration object as the final on-chain mechanism for protecting user
1145
1449
  },
1146
1450
  "env": {
1147
1451
  "account": "myshop_merchant",
1148
- "network": "testnet",
1452
+ "network": "mainnet",
1149
1453
  "no_cache": true
1150
1454
  }
1151
1455
  }
@@ -1166,7 +1470,7 @@ Configure order_allocators to define fund distribution rules, then publish the S
1166
1470
  > {
1167
1471
  > "query_type": "service",
1168
1472
  > "object": "three_body_signature_service_v2",
1169
- > "network": "testnet",
1473
+ > "network": "mainnet",
1170
1474
  > "no_cache": true
1171
1475
  > }
1172
1476
  > ```
@@ -1187,23 +1491,23 @@ Configure order_allocators to define fund distribution rules, then publish the S
1187
1491
  "sales": [
1188
1492
  {
1189
1493
  "name": "The Three-Body Problem + Author Signature",
1190
- "price": 1000000000,
1494
+ "price": 100000000,
1191
1495
  "stock": 100,
1192
1496
  "suspension": false,
1193
1497
  "wip": "https://wowok.net/test/three_body.wip",
1194
- "wip_hash": ""
1498
+ "wip_hash": "03c18561efa8faf4d75480eb1f732c4a46ffde95599e92eca06167785fc07a5b"
1195
1499
  }
1196
1500
  ]
1197
1501
  },
1198
1502
  "order_allocators": {
1199
- "description": "Order fund allocation - 100% to Service when order complete/wonderful/return fail, 100% to Order when lost/return complete",
1503
+ "description": "Order fund allocation - 100% to Treasury when order complete/wonderful/return fail, 100% to Order owner when lost/return complete",
1200
1504
  "threshold": 1,
1201
1505
  "allocators": [
1202
1506
  {
1203
1507
  "guard": "service_merchant_win_v2",
1204
1508
  "sharing": [
1205
1509
  {
1206
- "who": {"Entity": {"name_or_address": "three_body_signature_service_v2"}},
1510
+ "who": {"Entity": {"name_or_address": "myshop_treasury_v2"}},
1207
1511
  "sharing": 10000,
1208
1512
  "mode": "Rate"
1209
1513
  }
@@ -1233,7 +1537,7 @@ Configure order_allocators to define fund distribution rules, then publish the S
1233
1537
  },
1234
1538
  "env": {
1235
1539
  "account": "myshop_merchant",
1236
- "network": "testnet",
1540
+ "network": "mainnet",
1237
1541
  "no_cache": true
1238
1542
  }
1239
1543
  }
@@ -1241,16 +1545,51 @@ Configure order_allocators to define fund distribution rules, then publish the S
1241
1545
 
1242
1546
  **Fund Allocation Rules:**
1243
1547
 
1244
- | Guard | Condition | Recipient | Amount |
1245
- |-------|-----------|-----------|--------|
1246
- | service_merchant_win_v2 | Node is Order Complete / Wonderful / Return Fail | Service (merchant) | 100% |
1247
- | service_customer_win_v2 | Node is Lost / Return Complete | Order (customer) | 100% |
1548
+ | Guard | Condition | Recipient | Amount | Verifier Level |
1549
+ |-------|-----------|-----------|--------|----------------|
1550
+ | service_merchant_win_v2 | Node is Order Complete / Wonderful / Return Fail | Treasury (merchant revenue aggregation) | 100% | Level 3 (no Signer binding) |
1551
+ | service_customer_win_v2 | Node is Lost / Return Complete | Order owner (customer, via Signer) | 100% | Level 2 dynamic (Signer == order.owner) |
1248
1552
 
1249
1553
  **Recipient Types:**
1250
- - **Service**: 资金分配给 Service 对象(商家收款)
1251
- - **Order**: 资金分配给 Order 对象(客户收款,订单所有者可以提取)
1554
+ - `{ "Entity": { "name_or_address": "myshop_treasury_v2" } }` - Funds flow to the fixed Treasury address (merchant revenue aggregation). Safest — funds go to a fixed recipient regardless of caller. Uses the same Permission as the Service for governance consistency. **No Signer binding needed in the Guard** (R-C3-06 safe, Level 3 scene-combined).
1555
+ - `{ "Signer": "signer" }` - Transaction sender (caller). **⚠️ R-C3-06 Risk**: If the Guard does NOT bind the Signer to an authorized address, anyone who passes the Guard can steal 100% of funds. Safe ONLY when the Guard includes a `logic_equal[context(Signer), <authorized_address_or_query>]` check. This example uses Level 2 dynamic binding (`query("order.owner")`) — funds flow to the order's rightful owner.
1556
+
1557
+ > **R-C3-06 Risk Elimination — Guard + Sharing Coupling**: The `order_allocators` scene couples Guard verification (WHO can trigger) with sharing recipient (WHERE funds go). This example uses two verifier constraint levels:
1558
+ > - **Merchant win allocator** (`sharing.who = Entity → myshop_treasury_v2`, **Level 3 scene-combined**): Funds flow to the fixed Treasury address. Inherently safe — funds go to a fixed recipient regardless of caller. The `service_merchant_win_v2` Guard does NOT bind `context(Signer)` — the scene itself (Entity sharing to Treasury) ensures fund-flow safety. This is the recommended Level 3 pattern: no Signer binding, no R-C4-04 lock-in risk, no inconvenience.
1559
+ > - **Customer win allocator** (`sharing.who = Signer`, **Level 2 dynamic binding**): Funds flow to the caller. Safe ONLY because `service_customer_win_v2` Guard binds `context(Signer)` to `query("order.owner")` (dynamic query — Level 2). This ensures funds always flow to the order's rightful owner — only the customer who placed the order can receive the refund.
1560
+ >
1561
+ > **Treasury-First Rule**: Following the fund-flow design pattern established in the Insurance example, merchant revenue flows to `myshop_treasury_v2` (not the Service address). This aggregates public funds for operational distribution and makes the allocator inherently safe (R-C3-06). The Treasury uses the same Permission as the Service (`myshop_perm_v2`) for governance consistency.
1252
1562
  ```
1253
1563
 
1564
+ ### Verifier Constraint Design Notes
1565
+
1566
+ This example demonstrates all three verifier constraint levels across its Guards. The verifier constraint level classifies how strictly the Signer identity is constrained, trading off security against convenience.
1567
+
1568
+ | Guard | Level | Pattern | Why |
1569
+ |-------|-------|---------|-----|
1570
+ | Guard 1-3 (machine_merkle_root_v2, machine_service_order_v2, machine_time_*) | Level 3 | No Signer binding | Machine forward's `permissionIndex` already verifies operator identity — Signer binding is redundant |
1571
+ | Guard 4 (service_merchant_win_v2) | Level 3 | No Signer binding | Allocator uses `sharing.who=Entity` (myshop_treasury_v2) — funds flow to fixed Treasury regardless of caller (R-C3-06 safe). Two-fold verification: node + order.service binding |
1572
+ | Guard 5 (machine_service_order_v2) | Level 3 | No Signer binding | Project-binding only (order.service check); machine forward verifies operator |
1573
+ | Guard 6 (service_customer_win_v2) | Level 2 dynamic | Signer == query("order.owner") | Allocator uses `sharing.who=Signer` — funds flow to caller, must bind to order owner to prevent theft |
1574
+ | Reward guards (reward_wonderful_v2, reward_lost_v2, reward_shipping_timeout_v2) | Level 3 | No Signer binding | One-time claim via record count; funds flow to fixed reward pool recipient |
1575
+
1576
+ **Key design decisions**:
1577
+
1578
+ 1. **Merchant funds → Treasury (not Service)**: Following the Treasury-first rule, merchant revenue flows to `myshop_treasury_v2` (created with the same Permission as the Service). This aggregates public funds for operations and distribution, and makes the allocator inherently safe (R-C3-06) — no Signer binding needed (Level 3).
1579
+
1580
+ 2. **Customer refunds → order.owner (dynamic)**: Customer refunds must go to the actual customer who placed the order. The Level 2 dynamic binding (`query("order.owner")`) ensures only the rightful owner receives the refund, regardless of who calls the transaction. Unlike Level 1 (fixed address), this survives customer account changes.
1581
+
1582
+ 3. **No Level 1 strict binding anywhere**: No Guard uses `logic_equal[context(Signer), fixed_address]` because:
1583
+ - The merchant role may change (personnel rotation) — Level 1 would lock the Guard to one address permanently
1584
+ - The Treasury pattern makes Signer binding unnecessary for the merchant allocator (Level 3)
1585
+ - The dynamic `order.owner` query is more appropriate for customer refunds (Level 2 dynamic)
1586
+ - Level 1 would trigger R-C4-04 (convenience warning) and create operational risk
1587
+
1588
+ **Alternative designs considered**:
1589
+ - **Guard 4 could use Level 2 identity-set** (merchant OR admin via permission.owner OR has admin) — **rejected** because Treasury (Entity sharing) already makes Signer binding redundant. Adding Level 2 would add complexity without safety benefit.
1590
+ - **Guard 6 could use Level 2 identity-set** (order.owner OR order.agent via 1562 OR 1567) — **viable** if agents should be able to trigger refunds on behalf of customers. The current single-customer design (Level 2 dynamic, `order.owner` only) is simpler and sufficient for this example. See `tpl_allocator_identity_set_order_holder` template for the identity-set construction pattern.
1591
+ - **Guard 4 could use Level 2 dynamic permission** (permission.owner OR has admin, with dynamic permission via 1488) — **viable** for scenarios where the Service may rotate its permission. See `tpl_allocator_identity_set_service_provider_dynamic` template for this pattern. Rejected here because the Treasury pattern already provides fund-flow safety without Signer binding.
1592
+
1254
1593
  ***
1255
1594
 
1256
1595
  ### Step 11: Create Empty Reward Object (Optional)
@@ -1272,7 +1611,7 @@ Create an empty reward object first. This object will be referenced by reward gu
1272
1611
  },
1273
1612
  "env": {
1274
1613
  "account": "myshop_merchant",
1275
- "network": "testnet",
1614
+ "network": "mainnet",
1276
1615
  "no_cache": true
1277
1616
  }
1278
1617
  }
@@ -1284,6 +1623,8 @@ Create an empty reward object first. This object will be referenced by reward gu
1284
1623
 
1285
1624
  Create guards for reward verification with double-claim protection:
1286
1625
 
1626
+ > **Note on `query_reward_record_exists`**: The guard uses `query_reward_record_exists` with `where.storeFromId` to prevent double-claiming. The MCP tool automatically generates an internal identifier (identifier 4, type VecU8) for this query's parameters. You only need to define identifiers 0–3 in the table; the tool handles the rest.
1627
+
1287
1628
  | # | Guard Name | Purpose | Reward Amount |
1288
1629
  |---|------------|---------|---------------|
1289
1630
  **Guard 7: reward_wonderful_v2**
@@ -1309,21 +1650,21 @@ Create guards for reward verification with double-claim protection:
1309
1650
  {
1310
1651
  "type": "logic_string_nocase_equal",
1311
1652
  "nodes": [
1312
- {"type": "query", "query": 1253, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
1653
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
1313
1654
  {"type": "identifier", "identifier": 1}
1314
1655
  ]
1315
1656
  },
1316
1657
  {
1317
1658
  "type": "logic_equal",
1318
1659
  "nodes": [
1319
- {"type": "query", "query": 1562, "object": {"identifier": 0}, "parameters": []},
1660
+ {"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
1320
1661
  {"type": "context", "context": "Signer"}
1321
1662
  ]
1322
1663
  },
1323
1664
  {
1324
1665
  "type": "logic_equal",
1325
1666
  "nodes": [
1326
- {"type": "query", "query": 1563, "object": {"identifier": 0}, "parameters": []},
1667
+ {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
1327
1668
  {"type": "identifier", "identifier": 3}
1328
1669
  ]
1329
1670
  },
@@ -1342,7 +1683,7 @@ Create guards for reward verification with double-claim protection:
1342
1683
  },
1343
1684
  "env": {
1344
1685
  "account": "myshop_merchant",
1345
- "network": "testnet",
1686
+ "network": "mainnet",
1346
1687
  "no_cache": true
1347
1688
  }
1348
1689
  }
@@ -1371,21 +1712,21 @@ Create guards for reward verification with double-claim protection:
1371
1712
  {
1372
1713
  "type": "logic_string_nocase_equal",
1373
1714
  "nodes": [
1374
- {"type": "query", "query": 1253, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
1715
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
1375
1716
  {"type": "identifier", "identifier": 1}
1376
1717
  ]
1377
1718
  },
1378
1719
  {
1379
1720
  "type": "logic_equal",
1380
1721
  "nodes": [
1381
- {"type": "query", "query": 1562, "object": {"identifier": 0}, "parameters": []},
1722
+ {"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
1382
1723
  {"type": "context", "context": "Signer"}
1383
1724
  ]
1384
1725
  },
1385
1726
  {
1386
1727
  "type": "logic_equal",
1387
1728
  "nodes": [
1388
- {"type": "query", "query": 1563, "object": {"identifier": 0}, "parameters": []},
1729
+ {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
1389
1730
  {"type": "identifier", "identifier": 3}
1390
1731
  ]
1391
1732
  },
@@ -1404,7 +1745,7 @@ Create guards for reward verification with double-claim protection:
1404
1745
  },
1405
1746
  "env": {
1406
1747
  "account": "myshop_merchant",
1407
- "network": "testnet",
1748
+ "network": "mainnet",
1408
1749
  "no_cache": true
1409
1750
  }
1410
1751
  }
@@ -1433,21 +1774,21 @@ Create guards for reward verification with double-claim protection:
1433
1774
  {
1434
1775
  "type": "logic_string_nocase_equal",
1435
1776
  "nodes": [
1436
- {"type": "query", "query": 1253, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
1777
+ {"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
1437
1778
  {"type": "identifier", "identifier": 1}
1438
1779
  ]
1439
1780
  },
1440
1781
  {
1441
1782
  "type": "logic_equal",
1442
1783
  "nodes": [
1443
- {"type": "query", "query": 1562, "object": {"identifier": 0}, "parameters": []},
1784
+ {"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
1444
1785
  {"type": "context", "context": "Signer"}
1445
1786
  ]
1446
1787
  },
1447
1788
  {
1448
1789
  "type": "logic_equal",
1449
1790
  "nodes": [
1450
- {"type": "query", "query": 1563, "object": {"identifier": 0}, "parameters": []},
1791
+ {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
1451
1792
  {"type": "identifier", "identifier": 3}
1452
1793
  ]
1453
1794
  },
@@ -1466,7 +1807,7 @@ Create guards for reward verification with double-claim protection:
1466
1807
  },
1467
1808
  "env": {
1468
1809
  "account": "myshop_merchant",
1469
- "network": "testnet",
1810
+ "network": "mainnet",
1470
1811
  "no_cache": true
1471
1812
  }
1472
1813
  }
@@ -1508,7 +1849,7 @@ Add reward guards to the reward object with `store_from_id` set to the order ide
1508
1849
  },
1509
1850
  "env": {
1510
1851
  "account": "myshop_merchant",
1511
- "network": "testnet",
1852
+ "network": "mainnet",
1512
1853
  "no_cache": true
1513
1854
  }
1514
1855
  }
@@ -1532,7 +1873,7 @@ Deposit WOW tokens to the reward pool for rewards and compensation.
1532
1873
  },
1533
1874
  "env": {
1534
1875
  "account": "myshop_merchant",
1535
- "network": "testnet",
1876
+ "network": "mainnet",
1536
1877
  "no_cache": true
1537
1878
  }
1538
1879
  }
@@ -1563,7 +1904,7 @@ Customer places an order for "The Three-Body Problem + Author Signature" with WI
1563
1904
  }
1564
1905
  ],
1565
1906
  "total_pay": {
1566
- "balance": 1000000000
1907
+ "balance": 100000000
1567
1908
  },
1568
1909
  "payment_remark": "To my dear friend - keep exploring the universe"
1569
1910
  },
@@ -1583,7 +1924,7 @@ Customer places an order for "The Three-Body Problem + Author Signature" with WI
1583
1924
  },
1584
1925
  "env": {
1585
1926
  "account": "myshop_customer",
1586
- "network": "testnet",
1927
+ "network": "mainnet",
1587
1928
  "no_cache": true
1588
1929
  }
1589
1930
  }
@@ -1612,7 +1953,7 @@ Merchant confirms the order. This step uses permission index 1000 (no Guard subm
1612
1953
  },
1613
1954
  "env": {
1614
1955
  "account": "myshop_merchant",
1615
- "network": "testnet",
1956
+ "network": "mainnet",
1616
1957
  "no_cache": true
1617
1958
  }
1618
1959
  }
@@ -1663,7 +2004,7 @@ Merchant starts shipping after signature service is completed. The merchant subm
1663
2004
  },
1664
2005
  "env": {
1665
2006
  "account": "myshop_merchant",
1666
- "network": "testnet",
2007
+ "network": "mainnet",
1667
2008
  "no_cache": true
1668
2009
  }
1669
2010
  }
@@ -1694,7 +2035,7 @@ Customer confirms receipt of goods.
1694
2035
  },
1695
2036
  "env": {
1696
2037
  "account": "myshop_customer",
1697
- "network": "testnet",
2038
+ "network": "mainnet",
1698
2039
  "no_cache": true
1699
2040
  }
1700
2041
  }
@@ -1723,7 +2064,7 @@ Alternatively, customer can rate as Wonderful (very satisfied).
1723
2064
  },
1724
2065
  "env": {
1725
2066
  "account": "myshop_customer",
1726
- "network": "testnet",
2067
+ "network": "mainnet",
1727
2068
  "no_cache": true
1728
2069
  }
1729
2070
  }
@@ -1768,7 +2109,7 @@ Customer claims Wonderful reward from reward pool.
1768
2109
  },
1769
2110
  "env": {
1770
2111
  "account": "myshop_customer",
1771
- "network": "testnet",
2112
+ "network": "mainnet",
1772
2113
  "no_cache": true
1773
2114
  }
1774
2115
  }
@@ -1820,7 +2161,7 @@ Order can auto-complete after time thresholds or be manually completed.
1820
2161
  },
1821
2162
  "env": {
1822
2163
  "account": "myshop_merchant",
1823
- "network": "testnet",
2164
+ "network": "mainnet",
1824
2165
  "no_cache": true
1825
2166
  }
1826
2167
  }
@@ -1866,7 +2207,7 @@ Order can auto-complete after time thresholds or be manually completed.
1866
2207
  },
1867
2208
  "env": {
1868
2209
  "account": "myshop_merchant",
1869
- "network": "testnet",
2210
+ "network": "mainnet",
1870
2211
  "no_cache": true
1871
2212
  }
1872
2213
  }
@@ -1896,7 +2237,7 @@ If package is lost, customer reports and merchant confirms.
1896
2237
  },
1897
2238
  "env": {
1898
2239
  "account": "myshop_customer",
1899
- "network": "testnet",
2240
+ "network": "mainnet",
1900
2241
  "no_cache": true
1901
2242
  }
1902
2243
  }
@@ -1942,7 +2283,7 @@ If package is lost, customer reports and merchant confirms.
1942
2283
  },
1943
2284
  "env": {
1944
2285
  "account": "myshop_merchant",
1945
- "network": "testnet",
2286
+ "network": "mainnet",
1946
2287
  "no_cache": true
1947
2288
  }
1948
2289
  }
@@ -1981,7 +2322,7 @@ If package is lost, customer reports and merchant confirms.
1981
2322
  },
1982
2323
  "env": {
1983
2324
  "account": "myshop_customer",
1984
- "network": "testnet",
2325
+ "network": "mainnet",
1985
2326
  "no_cache": true
1986
2327
  }
1987
2328
  }
@@ -2011,7 +2352,7 @@ Customer requests return after delivery confirmation.
2011
2352
  },
2012
2353
  "env": {
2013
2354
  "account": "myshop_customer",
2014
- "network": "testnet",
2355
+ "network": "mainnet",
2015
2356
  "no_cache": true
2016
2357
  }
2017
2358
  }
@@ -2057,7 +2398,7 @@ Customer requests return after delivery confirmation.
2057
2398
  },
2058
2399
  "env": {
2059
2400
  "account": "myshop_merchant",
2060
- "network": "testnet",
2401
+ "network": "mainnet",
2061
2402
  "no_cache": true
2062
2403
  }
2063
2404
  }
@@ -2103,7 +2444,7 @@ Customer requests return after delivery confirmation.
2103
2444
  },
2104
2445
  "env": {
2105
2446
  "account": "myshop_customer",
2106
- "network": "testnet",
2447
+ "network": "mainnet",
2107
2448
  "no_cache": true
2108
2449
  }
2109
2450
  }
@@ -2127,12 +2468,42 @@ Customer requests return after delivery confirmation.
2127
2468
  },
2128
2469
  "env": {
2129
2470
  "account": "myshop_merchant",
2130
- "network": "testnet",
2471
+ "network": "mainnet",
2131
2472
  "no_cache": true
2132
2473
  }
2133
2474
  }
2134
2475
  ```
2135
2476
 
2477
+ > **Receipt Return path**: Steps 9.3 + 9.4 complete the Receipt Return → Return Complete transition (threshold=2, dual-signature). The customer submits return tracking (Merkle Root), and the merchant confirms receipt of the returned goods.
2478
+
2479
+ **Step 9.5: Merchant Confirms Goods Recovered (Non-receipt Return path)**
2480
+
2481
+ For the Non-receipt Return path, the customer never received the goods and has nothing to return. The customer's non-receipt was already confirmed when entering the Non-receipt Return node (dual-signature at entry). The transition to Return Complete requires only the merchant to confirm goods recovery (threshold=1).
2482
+
2483
+ ```json
2484
+ {
2485
+ "operation_type": "progress",
2486
+ "data": {
2487
+ "object": "myshop_progress_v2",
2488
+ "operate": {
2489
+ "operation": {
2490
+ "next_node_name": "Return Complete",
2491
+ "forward": "Confirm Goods Recovered"
2492
+ },
2493
+ "hold": false,
2494
+ "message": "Goods recovered by merchant - non-receipt return complete"
2495
+ }
2496
+ },
2497
+ "env": {
2498
+ "account": "myshop_merchant",
2499
+ "network": "mainnet",
2500
+ "no_cache": true
2501
+ }
2502
+ }
2503
+ ```
2504
+
2505
+ > **Non-receipt Return path**: Only Step 9.5 is needed (threshold=1, merchant-only). No customer action required — the customer never received the goods and has nothing to return or submit. The merchant confirms the goods have been recovered (e.g., returned by logistics to the merchant).
2506
+
2136
2507
  ***
2137
2508
 
2138
2509
  ### Step 10: Return Fail (Timeout)
@@ -2177,7 +2548,7 @@ If customer doesn't return within 10 days, merchant can mark as Return Fail.
2177
2548
  },
2178
2549
  "env": {
2179
2550
  "account": "myshop_merchant",
2180
- "network": "testnet",
2551
+ "network": "mainnet",
2181
2552
  "no_cache": true
2182
2553
  }
2183
2554
  }
@@ -2195,12 +2566,10 @@ When order reaches Order Complete, Wonderful, or Return Fail, merchant can withd
2195
2566
 
2196
2567
  ```json
2197
2568
  {
2198
- "operation_type": "order",
2569
+ "operation_type": "allocation",
2199
2570
  "data": {
2200
- "object": "myshop_order_v2",
2201
- "withdraw": {
2202
- "guard": "service_merchant_win_v2"
2203
- }
2571
+ "object": "myshop_allocation_v2",
2572
+ "alloc_by_guard": "service_merchant_win_v2"
2204
2573
  },
2205
2574
  "submission": {
2206
2575
  "type": "submission",
@@ -2226,7 +2595,7 @@ When order reaches Order Complete, Wonderful, or Return Fail, merchant can withd
2226
2595
  },
2227
2596
  "env": {
2228
2597
  "account": "myshop_merchant",
2229
- "network": "testnet",
2598
+ "network": "mainnet",
2230
2599
  "no_cache": true
2231
2600
  }
2232
2601
  }
@@ -2240,12 +2609,10 @@ When order reaches Lost or Return Complete, customer can withdraw funds.
2240
2609
 
2241
2610
  ```json
2242
2611
  {
2243
- "operation_type": "order",
2612
+ "operation_type": "allocation",
2244
2613
  "data": {
2245
- "object": "myshop_order_v2",
2246
- "withdraw": {
2247
- "guard": "service_customer_win_v2"
2248
- }
2614
+ "object": "myshop_allocation_v2",
2615
+ "alloc_by_guard": "service_customer_win_v2"
2249
2616
  },
2250
2617
  "submission": {
2251
2618
  "type": "submission",
@@ -2271,7 +2638,7 @@ When order reaches Lost or Return Complete, customer can withdraw funds.
2271
2638
  },
2272
2639
  "env": {
2273
2640
  "account": "myshop_customer",
2274
- "network": "testnet",
2641
+ "network": "mainnet",
2275
2642
  "no_cache": true
2276
2643
  }
2277
2644
  }
@@ -2284,7 +2651,7 @@ When order reaches Lost or Return Complete, customer can withdraw funds.
2284
2651
  This advanced e-commerce example demonstrates:
2285
2652
 
2286
2653
  1. **Multi-Path Workflow**: Orders can complete through normal delivery, wonderful rating, or various return paths
2287
- 2. **Dual-Signature Returns**: Return processes require confirmation from both parties (threshold=2)
2654
+ 2. **Dual-Signature Returns**: Receipt returns require confirmation from both parties (threshold=2); non-receipt returns require only merchant confirmation of goods recovery (threshold=1)
2288
2655
  3. **Time-Based Auto-Completion**: Orders auto-complete after time thresholds (10 days from shipping, 2 days from delivery)
2289
2656
  4. **Guard-Based Verification**: All state transitions and fund allocations are protected by guards
2290
2657
  5. **Reward Incentive System**: Wonderful ratings receive rewards, lost packages and shipping delays receive compensation