@wowok/skills 1.1.13 → 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.
- package/LICENSE +1 -2
- package/examples/Insurance/Insurance.md +309 -72
- package/examples/MyShop/MyShop.md +169 -39
- package/examples/MyShop_Advanced/MyShop_Advanced.md +415 -49
- package/examples/ThreeBody_Signature/ThreeBody_Signature.md +200 -18
- package/examples/Travel/Travel.md +234 -59
- package/package.json +1 -1
- package/wowok-guard/SKILL.md +192 -1
- package/wowok-machine/SKILL.md +72 -0
- package/wowok-order/APPENDIX.md +33 -33
- package/wowok-provider/SKILL.md +26 -12
- package/wowok-scenario/SKILL.md +10 -0
- package/wowok-tools/SKILL.md +2 -2
|
@@ -4,6 +4,24 @@ A complete example demonstrating how to create an Iceland travel service using W
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## ⚠️ Running Principle
|
|
8
|
+
|
|
9
|
+
> **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.
|
|
10
|
+
|
|
11
|
+
- **Execution order**: Run all build/setup steps in sequence before testing any customer or order flow. Do not skip steps — each depends on objects created by prior steps.
|
|
12
|
+
- **Prerequisites**: `travel_provider`, `weather_provider`, and `alice` (test customer) with sufficient WOW for gas. All on-chain operations require `env.confirmed: true`.
|
|
13
|
+
|
|
14
|
+
### 🔐 Two-Step Confirmation Flow (Production Safety)
|
|
15
|
+
|
|
16
|
+
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:
|
|
17
|
+
|
|
18
|
+
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.
|
|
19
|
+
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.
|
|
20
|
+
|
|
21
|
+
> Skipping Phase 1 means the user never sees the risk summary before gas is spent. Always preview first, then confirm.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
7
25
|
## Core Requirements & Features
|
|
8
26
|
|
|
9
27
|
| Requirement | Description | Implementation |
|
|
@@ -302,10 +320,77 @@ Create an Arbitration object for dispute resolution.
|
|
|
302
320
|
|
|
303
321
|
---
|
|
304
322
|
|
|
323
|
+
## Step 2.5: Create Service (Unpublished)
|
|
324
|
+
|
|
325
|
+
Create the Service without publishing to obtain its address for Guard creation. The Service address is required by the allocator Guards (Step 3.4–3.6) to verify `order.service == travel_service` (R-C3-05 cross-service theft protection).
|
|
326
|
+
|
|
327
|
+
**Prompt**: Create Service "travel_service" with permission "travel_permission", do not publish.
|
|
328
|
+
|
|
329
|
+
```json
|
|
330
|
+
{
|
|
331
|
+
"operation_type": "service",
|
|
332
|
+
"data": {
|
|
333
|
+
"object": {
|
|
334
|
+
"name": "travel_service",
|
|
335
|
+
"permission": "travel_permission",
|
|
336
|
+
"replaceExistName": true
|
|
337
|
+
},
|
|
338
|
+
"description": "Iceland travel service: Blue Lagoon SPA + Glacier Ice Scooting.",
|
|
339
|
+
"pause": false
|
|
340
|
+
},
|
|
341
|
+
"env": {
|
|
342
|
+
"account": "travel_provider",
|
|
343
|
+
"network": "testnet",
|
|
344
|
+
"no_cache": true,
|
|
345
|
+
"confirmed": true
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Record the Service address** - it will be needed for allocator Guard creation (Step 3.4–3.6) to bind `order.service` verification.
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
### Step 2.6: Create Treasury (Merchant Revenue Aggregation)
|
|
355
|
+
|
|
356
|
+
Create a Treasury object to aggregate merchant revenue. The Treasury uses the **same Permission** as the Service (`travel_permission`) for consistency — a single permission organization governs both fund collection and service operations.
|
|
357
|
+
|
|
358
|
+
**Prompt**: Create Treasury "travel_treasury" with permission "travel_permission", type parameter "0x2::wow::WOW".
|
|
359
|
+
|
|
360
|
+
```json
|
|
361
|
+
{
|
|
362
|
+
"operation_type": "treasury",
|
|
363
|
+
"data": {
|
|
364
|
+
"object": {
|
|
365
|
+
"name": "travel_treasury",
|
|
366
|
+
"type_parameter": "0x2::wow::WOW",
|
|
367
|
+
"permission": "travel_permission",
|
|
368
|
+
"replaceExistName": true
|
|
369
|
+
},
|
|
370
|
+
"description": "Treasury for aggregating travel service merchant revenue. Uses the same Permission as the Service (travel_permission) for consistency — a single permission organization governs both fund collection and service operations."
|
|
371
|
+
},
|
|
372
|
+
"env": {
|
|
373
|
+
"account": "travel_provider",
|
|
374
|
+
"network": "testnet",
|
|
375
|
+
"no_cache": true,
|
|
376
|
+
"confirmed": true
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
> **Treasury-First Rule**: Following the fund-flow design pattern established in the Insurance and MyShop_Advanced examples, merchant revenue flows to `travel_treasury` (not directly to the Service address). This:
|
|
382
|
+
> 1. **Aggregates public funds** for operational distribution and accounting
|
|
383
|
+
> 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
|
|
384
|
+
> 3. **Uses permission consistency** — Treasury and Service share `travel_permission`, ensuring unified governance
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
305
388
|
## Step 3: Create Guards
|
|
306
389
|
|
|
307
390
|
Create all Guards needed for the workflow and fund allocation. Guards are immutable once created, so create them before the Machine and Service.
|
|
308
391
|
|
|
392
|
+
> **Prerequisite**: The Service must be created (unpublished) in Step 2.5 first, because the allocator Guards (3.4–3.6) reference the Service address to verify `order.service == travel_service` (R-C3-05 cross-service theft protection).
|
|
393
|
+
|
|
309
394
|
### 3.1 Weather Check Guard
|
|
310
395
|
|
|
311
396
|
Creates a Guard that verifies weather data exists for a given date. This Guard is bound to the "go_ice_scooting" forward (entering the weather-dependent Ice Scooting activity) to ensure the activity date has a weather record in the repository.
|
|
@@ -346,7 +431,6 @@ repository.data has("Condition", convert_number_address(activity_date))
|
|
|
346
431
|
"identifier": 2,
|
|
347
432
|
"b_submission": true,
|
|
348
433
|
"value_type": "U64",
|
|
349
|
-
"value": 0,
|
|
350
434
|
"name": "Activity date timestamp (submitted at runtime)"
|
|
351
435
|
}
|
|
352
436
|
],
|
|
@@ -387,7 +471,7 @@ Creates a Guard that verifies the time-lock condition for order completion.
|
|
|
387
471
|
**Guard Logic**:
|
|
388
472
|
```
|
|
389
473
|
clock > progress.current_time + 1000
|
|
390
|
-
(progress accessed via Order + convert_witness=
|
|
474
|
+
(progress accessed via Order + convert_witness="OrderProgress")
|
|
391
475
|
```
|
|
392
476
|
|
|
393
477
|
**Prompt**: Create a Guard named "travel_complete_guard" for time-lock verification.
|
|
@@ -407,7 +491,6 @@ clock > progress.current_time + 1000
|
|
|
407
491
|
"identifier": 0,
|
|
408
492
|
"b_submission": true,
|
|
409
493
|
"value_type": "Address",
|
|
410
|
-
"value": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
411
494
|
"name": "Order ID (submitted at runtime)"
|
|
412
495
|
},
|
|
413
496
|
{
|
|
@@ -428,7 +511,7 @@ clock > progress.current_time + 1000
|
|
|
428
511
|
{
|
|
429
512
|
"type": "query",
|
|
430
513
|
"query": "progress.current_time",
|
|
431
|
-
"object": {"identifier": 0, "convert_witness":
|
|
514
|
+
"object": {"identifier": 0, "convert_witness": "OrderProgress"},
|
|
432
515
|
"parameters": []
|
|
433
516
|
},
|
|
434
517
|
{"type": "identifier", "identifier": 1}
|
|
@@ -494,9 +577,9 @@ Creates a Guard that allows order cancellation. This Guard always passes (return
|
|
|
494
577
|
}
|
|
495
578
|
```
|
|
496
579
|
|
|
497
|
-
### 3.4 Merchant Victory Guard (100% to
|
|
580
|
+
### 3.4 Merchant Victory Guard (100% to Treasury)
|
|
498
581
|
|
|
499
|
-
Checks if order progress current node is "Complete". If passed, merchant receives 100% of funds.
|
|
582
|
+
Checks if order progress current node is "Complete" AND order belongs to this service. If passed, merchant (Treasury) receives 100% of funds.
|
|
500
583
|
|
|
501
584
|
**Prompt**: Create Guard "merchant_victory_guard".
|
|
502
585
|
|
|
@@ -506,16 +589,15 @@ Checks if order progress current node is "Complete". If passed, merchant receive
|
|
|
506
589
|
"data": {
|
|
507
590
|
"namedNew": {
|
|
508
591
|
"name": "merchant_victory_guard",
|
|
509
|
-
"tags": ["merchant", "victory", "complete"],
|
|
592
|
+
"tags": ["merchant", "victory", "complete", "level3-scene-combined"],
|
|
510
593
|
"replaceExistName": true
|
|
511
594
|
},
|
|
512
|
-
"description": "Guard for merchant victory: checks if order progress current node is Complete.
|
|
595
|
+
"description": "Guard for merchant victory: checks if order progress current node is Complete AND order belongs to travel_service. VERIFIER CONSTRAINT LEVEL 3 (scene-combined): No Signer binding needed because the allocator uses sharing.who=Entity (travel_treasury) — funds always flow to the Treasury regardless of caller (R-C3-06 safe). Two-fold verification: (1) order at Complete node, (2) order belongs to this service (prevents cross-service theft, R-C3-05).",
|
|
513
596
|
"table": [
|
|
514
597
|
{
|
|
515
598
|
"identifier": 0,
|
|
516
599
|
"b_submission": true,
|
|
517
600
|
"value_type": "Address",
|
|
518
|
-
"value": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
519
601
|
"name": "Order ID (submitted at runtime)"
|
|
520
602
|
},
|
|
521
603
|
{
|
|
@@ -524,18 +606,37 @@ Checks if order progress current node is "Complete". If passed, merchant receive
|
|
|
524
606
|
"value_type": "String",
|
|
525
607
|
"value": "Complete",
|
|
526
608
|
"name": "Complete node name"
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"identifier": 2,
|
|
612
|
+
"b_submission": false,
|
|
613
|
+
"value_type": "Address",
|
|
614
|
+
"value": "travel_service",
|
|
615
|
+
"name": "Service address (this service)"
|
|
527
616
|
}
|
|
528
617
|
],
|
|
529
618
|
"root": {
|
|
530
|
-
"type": "
|
|
619
|
+
"type": "logic_and",
|
|
531
620
|
"nodes": [
|
|
532
621
|
{
|
|
533
|
-
"type": "
|
|
534
|
-
"
|
|
535
|
-
|
|
536
|
-
|
|
622
|
+
"type": "logic_equal",
|
|
623
|
+
"nodes": [
|
|
624
|
+
{
|
|
625
|
+
"type": "query",
|
|
626
|
+
"query": "progress.current",
|
|
627
|
+
"object": {"identifier": 0, "convert_witness": "OrderProgress"},
|
|
628
|
+
"parameters": []
|
|
629
|
+
},
|
|
630
|
+
{"type": "identifier", "identifier": 1}
|
|
631
|
+
]
|
|
537
632
|
},
|
|
538
|
-
{
|
|
633
|
+
{
|
|
634
|
+
"type": "logic_equal",
|
|
635
|
+
"nodes": [
|
|
636
|
+
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
637
|
+
{"type": "identifier", "identifier": 2}
|
|
638
|
+
]
|
|
639
|
+
}
|
|
539
640
|
]
|
|
540
641
|
}
|
|
541
642
|
},
|
|
@@ -548,9 +649,21 @@ Checks if order progress current node is "Complete". If passed, merchant receive
|
|
|
548
649
|
}
|
|
549
650
|
```
|
|
550
651
|
|
|
551
|
-
|
|
652
|
+
**Guard Explanation (Two-fold Verification — Level 3 Scene-Combined):**
|
|
653
|
+
- **Table Item 0**: Order address (submitted at runtime)
|
|
654
|
+
- **Table Item 1**: Constant string "Complete" (merchant win node name)
|
|
655
|
+
- **Table Item 2**: Constant address `travel_service` (this service's on-chain address)
|
|
656
|
+
- **Condition 1 — Complete Node**: `logic_equal[query(progress.current, witness="OrderProgress"), identifier[1]]` — verifies the order is at the Complete node
|
|
657
|
+
- **Condition 2 — Service Ownership**: `logic_equal[query("order.service"), identifier[2]]` — verifies the submitted Order's `service` field equals `travel_service`, **preventing cross-service theft** where someone submits another service's order (R-C3-05)
|
|
658
|
+
- **root**: `logic_and` of both conditions — all must pass for allocation to proceed
|
|
659
|
+
|
|
660
|
+
> **Risk Elimination (R-C3-05 + R-C3-06) — Level 3 Scene-Combined Design**:
|
|
661
|
+
> - **R-C3-05 (Cross-service theft)**: Eliminated by the Service Ownership check (Condition 2). An attacker cannot submit another service's order because `order.service` won't match `travel_service`.
|
|
662
|
+
> - **R-C3-06 (Fund theft via Signer)**: Eliminated by the scene itself — the allocator uses `"who": {"Entity": {"name_or_address": "travel_treasury"}}` (funds flow to the fixed Treasury address). Funds go to a fixed recipient regardless of caller, so **no Signer binding is needed**. This is the Level 3 scene-combined pattern.
|
|
552
663
|
|
|
553
|
-
|
|
664
|
+
### 3.5 No Ice Scooting Guard (80% Treasury, 20% Refund)
|
|
665
|
+
|
|
666
|
+
Checks if progress current is "Cancel" or "Ice Scooting" AND order belongs to this service. If passed, merchant (Treasury) gets 80%, user gets 20% refund.
|
|
554
667
|
|
|
555
668
|
**Prompt**: Create Guard "no_ice_scooting_guard".
|
|
556
669
|
|
|
@@ -560,16 +673,15 @@ Checks if progress current is "Cancel" or "Ice Scooting". If passed, merchant ge
|
|
|
560
673
|
"data": {
|
|
561
674
|
"namedNew": {
|
|
562
675
|
"name": "no_ice_scooting_guard",
|
|
563
|
-
"tags": ["user", "cancel", "ice_scooting"],
|
|
676
|
+
"tags": ["user", "cancel", "ice_scooting", "level3-scene-combined"],
|
|
564
677
|
"replaceExistName": true
|
|
565
678
|
},
|
|
566
|
-
"description": "Guard for user not participating in ice scooting: checks if progress current is Cancel or Ice Scooting.
|
|
679
|
+
"description": "Guard for user not participating in ice scooting: checks if progress current is Cancel or Ice Scooting AND order belongs to travel_service. VERIFIER CONSTRAINT LEVEL 3 (scene-combined): No Signer binding needed because the allocator uses sharing.who=Entity (travel_treasury) for merchant portion and sharing.who=GuardIdentifier(0) for customer refund (escrow to Order address). Two-fold verification: (1) order at Cancel/Ice Scooting node, (2) order belongs to this service (prevents cross-service theft, R-C3-05).",
|
|
567
680
|
"table": [
|
|
568
681
|
{
|
|
569
682
|
"identifier": 0,
|
|
570
683
|
"b_submission": true,
|
|
571
684
|
"value_type": "Address",
|
|
572
|
-
"value": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
573
685
|
"name": "Order ID (submitted at runtime)"
|
|
574
686
|
},
|
|
575
687
|
{
|
|
@@ -585,33 +697,52 @@ Checks if progress current is "Cancel" or "Ice Scooting". If passed, merchant ge
|
|
|
585
697
|
"value_type": "String",
|
|
586
698
|
"value": "Ice Scooting",
|
|
587
699
|
"name": "Ice Scooting node name"
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
"identifier": 3,
|
|
703
|
+
"b_submission": false,
|
|
704
|
+
"value_type": "Address",
|
|
705
|
+
"value": "travel_service",
|
|
706
|
+
"name": "Service address (this service)"
|
|
588
707
|
}
|
|
589
708
|
],
|
|
590
709
|
"root": {
|
|
591
|
-
"type": "
|
|
710
|
+
"type": "logic_and",
|
|
592
711
|
"nodes": [
|
|
593
712
|
{
|
|
594
|
-
"type": "
|
|
713
|
+
"type": "logic_or",
|
|
595
714
|
"nodes": [
|
|
596
715
|
{
|
|
597
|
-
"type": "
|
|
598
|
-
"
|
|
599
|
-
|
|
600
|
-
|
|
716
|
+
"type": "logic_equal",
|
|
717
|
+
"nodes": [
|
|
718
|
+
{
|
|
719
|
+
"type": "query",
|
|
720
|
+
"query": "progress.current",
|
|
721
|
+
"object": {"identifier": 0, "convert_witness": "OrderProgress"},
|
|
722
|
+
"parameters": []
|
|
723
|
+
},
|
|
724
|
+
{"type": "identifier", "identifier": 1}
|
|
725
|
+
]
|
|
601
726
|
},
|
|
602
|
-
{
|
|
727
|
+
{
|
|
728
|
+
"type": "logic_equal",
|
|
729
|
+
"nodes": [
|
|
730
|
+
{
|
|
731
|
+
"type": "query",
|
|
732
|
+
"query": "progress.current",
|
|
733
|
+
"object": {"identifier": 0, "convert_witness": "OrderProgress"},
|
|
734
|
+
"parameters": []
|
|
735
|
+
},
|
|
736
|
+
{"type": "identifier", "identifier": 2}
|
|
737
|
+
]
|
|
738
|
+
}
|
|
603
739
|
]
|
|
604
740
|
},
|
|
605
741
|
{
|
|
606
742
|
"type": "logic_equal",
|
|
607
743
|
"nodes": [
|
|
608
|
-
{
|
|
609
|
-
|
|
610
|
-
"query": "progress.current",
|
|
611
|
-
"object": {"identifier": 0, "convert_witness": 100},
|
|
612
|
-
"parameters": []
|
|
613
|
-
},
|
|
614
|
-
{"type": "identifier", "identifier": 2}
|
|
744
|
+
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
745
|
+
{"type": "identifier", "identifier": 3}
|
|
615
746
|
]
|
|
616
747
|
}
|
|
617
748
|
]
|
|
@@ -626,9 +757,21 @@ Checks if progress current is "Cancel" or "Ice Scooting". If passed, merchant ge
|
|
|
626
757
|
}
|
|
627
758
|
```
|
|
628
759
|
|
|
629
|
-
|
|
760
|
+
**Guard Explanation (Two-fold Verification — Level 3 Scene-Combined):**
|
|
761
|
+
- **Table Item 0**: Order address (submitted at runtime)
|
|
762
|
+
- **Table Items 1-2**: Constant strings "Cancel" and "Ice Scooting" (node names)
|
|
763
|
+
- **Table Item 3**: Constant address `travel_service` (this service's on-chain address)
|
|
764
|
+
- **Condition 1 — Cancel/Ice Scooting Node**: `logic_or` of two `logic_equal` checks against `query(progress.current, witness="OrderProgress")` — verifies the order is at Cancel or Ice Scooting node
|
|
765
|
+
- **Condition 2 — Service Ownership**: `logic_equal[query("order.service"), identifier[3]]` — verifies the submitted Order's `service` field equals `travel_service`, **preventing cross-service theft** (R-C3-05)
|
|
766
|
+
- **root**: `logic_and` of both conditions — all must pass for allocation to proceed
|
|
767
|
+
|
|
768
|
+
> **Risk Elimination (R-C3-05 + R-C3-06) — Level 3 Scene-Combined Design**:
|
|
769
|
+
> - **R-C3-05 (Cross-service theft)**: Eliminated by the Service Ownership check (Condition 2). An attacker cannot submit another service's order because `order.service` won't match `travel_service`.
|
|
770
|
+
> - **R-C3-06 (Fund theft via Signer)**: Eliminated by the scene itself — the merchant portion uses `"who": {"Entity": {"name_or_address": "travel_treasury"}}` (funds flow to the fixed Treasury address), and the customer refund uses `"who": {"GuardIdentifier": 0}` (funds flow to the Order object's address as escrow). Neither portion flows to the caller's wallet, so **no Signer binding is needed**.
|
|
771
|
+
|
|
772
|
+
### 3.6 No SPA Guard (5% Treasury, 95% Refund)
|
|
630
773
|
|
|
631
|
-
Checks if progress current is "SPA". If passed, merchant gets 5%, user gets 95% refund.
|
|
774
|
+
Checks if progress current is "SPA" AND order belongs to this service. If passed, merchant (Treasury) gets 5%, user gets 95% refund.
|
|
632
775
|
|
|
633
776
|
**Prompt**: Create Guard "no_spa_guard".
|
|
634
777
|
|
|
@@ -638,16 +781,15 @@ Checks if progress current is "SPA". If passed, merchant gets 5%, user gets 95%
|
|
|
638
781
|
"data": {
|
|
639
782
|
"namedNew": {
|
|
640
783
|
"name": "no_spa_guard",
|
|
641
|
-
"tags": ["user", "cancel", "spa"],
|
|
784
|
+
"tags": ["user", "cancel", "spa", "level3-scene-combined"],
|
|
642
785
|
"replaceExistName": true
|
|
643
786
|
},
|
|
644
|
-
"description": "Guard for user not participating in SPA: checks if progress current is SPA.
|
|
787
|
+
"description": "Guard for user not participating in SPA: checks if progress current is SPA AND order belongs to travel_service. VERIFIER CONSTRAINT LEVEL 3 (scene-combined): No Signer binding needed because the allocator uses sharing.who=Entity (travel_treasury) for merchant portion and sharing.who=GuardIdentifier(0) for customer refund (escrow to Order address). Two-fold verification: (1) order at SPA node, (2) order belongs to this service (prevents cross-service theft, R-C3-05).",
|
|
645
788
|
"table": [
|
|
646
789
|
{
|
|
647
790
|
"identifier": 0,
|
|
648
791
|
"b_submission": true,
|
|
649
792
|
"value_type": "Address",
|
|
650
|
-
"value": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
651
793
|
"name": "Order ID (submitted at runtime)"
|
|
652
794
|
},
|
|
653
795
|
{
|
|
@@ -656,18 +798,37 @@ Checks if progress current is "SPA". If passed, merchant gets 5%, user gets 95%
|
|
|
656
798
|
"value_type": "String",
|
|
657
799
|
"value": "SPA",
|
|
658
800
|
"name": "SPA node name"
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
"identifier": 2,
|
|
804
|
+
"b_submission": false,
|
|
805
|
+
"value_type": "Address",
|
|
806
|
+
"value": "travel_service",
|
|
807
|
+
"name": "Service address (this service)"
|
|
659
808
|
}
|
|
660
809
|
],
|
|
661
810
|
"root": {
|
|
662
|
-
"type": "
|
|
811
|
+
"type": "logic_and",
|
|
663
812
|
"nodes": [
|
|
664
813
|
{
|
|
665
|
-
"type": "
|
|
666
|
-
"
|
|
667
|
-
|
|
668
|
-
|
|
814
|
+
"type": "logic_equal",
|
|
815
|
+
"nodes": [
|
|
816
|
+
{
|
|
817
|
+
"type": "query",
|
|
818
|
+
"query": "progress.current",
|
|
819
|
+
"object": {"identifier": 0, "convert_witness": "OrderProgress"},
|
|
820
|
+
"parameters": []
|
|
821
|
+
},
|
|
822
|
+
{"type": "identifier", "identifier": 1}
|
|
823
|
+
]
|
|
669
824
|
},
|
|
670
|
-
{
|
|
825
|
+
{
|
|
826
|
+
"type": "logic_equal",
|
|
827
|
+
"nodes": [
|
|
828
|
+
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
829
|
+
{"type": "identifier", "identifier": 2}
|
|
830
|
+
]
|
|
831
|
+
}
|
|
671
832
|
]
|
|
672
833
|
}
|
|
673
834
|
},
|
|
@@ -680,6 +841,18 @@ Checks if progress current is "SPA". If passed, merchant gets 5%, user gets 95%
|
|
|
680
841
|
}
|
|
681
842
|
```
|
|
682
843
|
|
|
844
|
+
**Guard Explanation (Two-fold Verification — Level 3 Scene-Combined):**
|
|
845
|
+
- **Table Item 0**: Order address (submitted at runtime)
|
|
846
|
+
- **Table Item 1**: Constant string "SPA" (node name)
|
|
847
|
+
- **Table Item 2**: Constant address `travel_service` (this service's on-chain address)
|
|
848
|
+
- **Condition 1 — SPA Node**: `logic_equal[query(progress.current, witness="OrderProgress"), identifier[1]]` — verifies the order is at the SPA node
|
|
849
|
+
- **Condition 2 — Service Ownership**: `logic_equal[query("order.service"), identifier[2]]` — verifies the submitted Order's `service` field equals `travel_service`, **preventing cross-service theft** (R-C3-05)
|
|
850
|
+
- **root**: `logic_and` of both conditions — all must pass for allocation to proceed
|
|
851
|
+
|
|
852
|
+
> **Risk Elimination (R-C3-05 + R-C3-06) — Level 3 Scene-Combined Design**:
|
|
853
|
+
> - **R-C3-05 (Cross-service theft)**: Eliminated by the Service Ownership check (Condition 2). An attacker cannot submit another service's order because `order.service` won't match `travel_service`.
|
|
854
|
+
> - **R-C3-06 (Fund theft via Signer)**: Eliminated by the scene itself — the merchant portion uses `"who": {"Entity": {"name_or_address": "travel_treasury"}}` (funds flow to the fixed Treasury address), and the customer refund uses `"who": {"GuardIdentifier": 0}` (funds flow to the Order object's address as escrow). Neither portion flows to the caller's wallet, so **no Signer binding is needed**.
|
|
855
|
+
|
|
683
856
|
---
|
|
684
857
|
|
|
685
858
|
## Step 4: Create and Publish Machine
|
|
@@ -832,16 +1005,16 @@ Create a Machine to define the travel service workflow with all nodes and forwar
|
|
|
832
1005
|
|
|
833
1006
|
---
|
|
834
1007
|
|
|
835
|
-
## Step 5:
|
|
1008
|
+
## Step 5: Configure and Publish Service
|
|
836
1009
|
|
|
837
|
-
|
|
1010
|
+
Configure the travel service (created unpublished in Step 2.5) with all bindings and publish it. The Service requires:
|
|
838
1011
|
- Machine binding (must be published first)
|
|
839
1012
|
- Sales items (product listing)
|
|
840
1013
|
- Arbitration binding
|
|
841
|
-
- Order allocators (fund distribution rules)
|
|
1014
|
+
- Order allocators (fund distribution rules — merchant funds flow to `travel_treasury`)
|
|
842
1015
|
- `pause: false` and `publish: true` to make it active
|
|
843
1016
|
|
|
844
|
-
**Prompt**:
|
|
1017
|
+
**Prompt**: Configure and publish the Service named "travel_service".
|
|
845
1018
|
|
|
846
1019
|
```json
|
|
847
1020
|
{
|
|
@@ -880,7 +1053,7 @@ Create the travel service with all configurations and publish it in one operatio
|
|
|
880
1053
|
"fix": "0",
|
|
881
1054
|
"sharing": [
|
|
882
1055
|
{
|
|
883
|
-
"who": {"Entity": {"name_or_address": "
|
|
1056
|
+
"who": {"Entity": {"name_or_address": "travel_treasury"}},
|
|
884
1057
|
"sharing": 10000,
|
|
885
1058
|
"mode": "Rate"
|
|
886
1059
|
}
|
|
@@ -891,7 +1064,7 @@ Create the travel service with all configurations and publish it in one operatio
|
|
|
891
1064
|
"fix": "0",
|
|
892
1065
|
"sharing": [
|
|
893
1066
|
{
|
|
894
|
-
"who": {"Entity": {"name_or_address": "
|
|
1067
|
+
"who": {"Entity": {"name_or_address": "travel_treasury"}},
|
|
895
1068
|
"sharing": 8000,
|
|
896
1069
|
"mode": "Rate"
|
|
897
1070
|
},
|
|
@@ -907,7 +1080,7 @@ Create the travel service with all configurations and publish it in one operatio
|
|
|
907
1080
|
"fix": "0",
|
|
908
1081
|
"sharing": [
|
|
909
1082
|
{
|
|
910
|
-
"who": {"Entity": {"name_or_address": "
|
|
1083
|
+
"who": {"Entity": {"name_or_address": "travel_treasury"}},
|
|
911
1084
|
"sharing": 500,
|
|
912
1085
|
"mode": "Rate"
|
|
913
1086
|
},
|
|
@@ -950,19 +1123,21 @@ Create the travel service with all configurations and publish it in one operatio
|
|
|
950
1123
|
|
|
951
1124
|
| Type | Syntax | Resolves To | Use Case |
|
|
952
1125
|
|------|--------|-------------|----------|
|
|
953
|
-
| `Entity` | `{"Entity": {"name_or_address": "
|
|
1126
|
+
| `Entity` | `{"Entity": {"name_or_address": "travel_treasury"}}` | The named Treasury address | Merchant receipts (Treasury object — Treasury-first rule) |
|
|
954
1127
|
| `GuardIdentifier` | `{"GuardIdentifier": 0}` | Address from Guard table index 0 (submitted at runtime) | Customer refunds (Order ID submitted to Guard) |
|
|
955
|
-
| `Signer` | `{"Signer": "signer"}` | The caller of `alloc_by_guard` | When caller should receive all funds |
|
|
1128
|
+
| `Signer` | `{"Signer": "signer"}` | The caller of `alloc_by_guard` | When caller should receive all funds (**⚠️ R-C3-06 Risk**: unsafe without Guard Signer binding) |
|
|
956
1129
|
|
|
957
1130
|
> **Important**: All allocation Guards (merchant_victory_guard, no_ice_scooting_guard, no_spa_guard) have `identifier: 0` as a submission field accepting the Order ID at runtime. `{"GuardIdentifier": 0}` resolves to this submitted Order ID, so funds are sent to the Order object — the customer (Order builder) can then withdraw.
|
|
958
1131
|
|
|
1132
|
+
> **Treasury-First Rule**: Merchant funds flow to `travel_treasury` (not `travel_service`) following the fund-flow design pattern. This makes all allocators inherently safe (R-C3-06) — funds go to a fixed Treasury regardless of caller, so no Signer binding is needed in the Guards. Combined with the R-C3-05 service ownership check in each Guard, the allocators are protected against both cross-service theft and fund theft via Signer.
|
|
1133
|
+
|
|
959
1134
|
**Allocation Logic**:
|
|
960
1135
|
|
|
961
|
-
| Guard | Condition |
|
|
962
|
-
|
|
963
|
-
| merchant_victory_guard | Progress is "Complete" | 100% (Entity →
|
|
964
|
-
| no_ice_scooting_guard | Progress is "Cancel" or "Ice Scooting" | 80% (Entity →
|
|
965
|
-
| no_spa_guard | Progress is "SPA" | 5% (Entity →
|
|
1136
|
+
| Guard | Condition | Treasury Receives | Customer Receives | Verifier Level |
|
|
1137
|
+
|-------|-----------|-------------------|-------------------|----------------|
|
|
1138
|
+
| merchant_victory_guard | Progress is "Complete" + order.service verified | 100% (Entity → travel_treasury) | 0% | Level 3 (scene-combined) |
|
|
1139
|
+
| no_ice_scooting_guard | Progress is "Cancel" or "Ice Scooting" + order.service verified | 80% (Entity → travel_treasury) | 20% (GuardIdentifier: 0 → Order) | Level 3 (scene-combined) |
|
|
1140
|
+
| no_spa_guard | Progress is "SPA" + order.service verified | 5% (Entity → travel_treasury) | 95% (GuardIdentifier: 0 → Order) | Level 3 (scene-combined) |
|
|
966
1141
|
|
|
967
1142
|
---
|
|
968
1143
|
|
package/package.json
CHANGED