@wowok/skills 1.3.4 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -11
- package/dist/cli.js +26 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/skills.d.ts +52 -5
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +104 -63
- package/dist/skills.js.map +1 -1
- package/examples/Insurance/Insurance.md +224 -197
- package/examples/MyShop/MyShop.md +133 -35
- package/examples/MyShop_Advanced/MyShop_Advanced.md +368 -300
- package/examples/ThreeBody_Signature/ThreeBody_Signature.md +272 -25
- package/examples/Travel/Travel.md +104 -17
- package/package.json +2 -6
- package/scripts/install.js +52 -6
- package/wowok-arbitrator/SKILL.md +1 -1
- package/wowok-auditor/SKILL.md +1 -1
- package/wowok-machine/SKILL.md +2 -2
- package/wowok-messenger/SKILL.md +5 -3
- package/wowok-onboard/SKILL.md +43 -24
- package/wowok-order/SKILL.md +22 -7
- package/wowok-output/SKILL.md +4 -4
- package/wowok-planner/SKILL.md +2 -1
- package/wowok-provider/SKILL.md +48 -38
- package/wowok-guard/SKILL.md +0 -359
- package/wowok-safety/SKILL.md +0 -275
- package/wowok-scenario/SKILL.md +0 -371
- package/wowok-tools/SKILL.md +0 -389
package/wowok-order/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: wowok-order
|
|
3
3
|
description: |
|
|
4
4
|
WoWok Customer Guide — complete buyer order lifecycle: pre-purchase due diligence
|
|
5
|
-
(E1-
|
|
5
|
+
(E1-E11), consensus building, order creation, progress advancement, and arbitration.
|
|
6
6
|
when_to_use:
|
|
7
7
|
- User is a customer/buyer placing or managing orders
|
|
8
8
|
- User wants to evaluate services before purchasing
|
|
@@ -15,7 +15,8 @@ when_to_use:
|
|
|
15
15
|
# WoWok Customer Guide
|
|
16
16
|
|
|
17
17
|
> **Role**: Customer (Buyer/Order Holder)
|
|
18
|
-
> **Provider Guide**: [wowok-provider](../wowok-provider/SKILL.md) | **Arbitration Guide**: [wowok-arbitrator](../wowok-arbitrator/SKILL.md) | **
|
|
18
|
+
> **Provider Guide**: [wowok-provider](../wowok-provider/SKILL.md) | **Arbitration Guide**: [wowok-arbitrator](../wowok-arbitrator/SKILL.md) | **Machine**: [wowok-machine](../wowok-machine/SKILL.md) | **Messenger**: [wowok-messenger](../wowok-messenger/SKILL.md)
|
|
19
|
+
> Guard design patterns, safety rules, and tool references now live in the MCP knowledge layer — query via `schema_query` actions `get_guard_design_patterns`, `get_safety_rules`, `get_tool_reference`.
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
@@ -41,7 +42,7 @@ Allocation evaluates when Progress reaches **any** configured node (not just exi
|
|
|
41
42
|
|
|
42
43
|
## Phase 1: Pre-Purchase Due Diligence (MANDATORY GATE)
|
|
43
44
|
|
|
44
|
-
> **⛔ Complete E1-
|
|
45
|
+
> **⛔ Complete E1-E11 in order. User must explicitly confirm every item.**
|
|
45
46
|
> **⚠️ = explain risk, wait for decision. 🔴 = strongly advise against purchase.**
|
|
46
47
|
|
|
47
48
|
---
|
|
@@ -62,7 +63,7 @@ From E1 `sales[]`. Skip `suspension === true` items.
|
|
|
62
63
|
|
|
63
64
|
**WIP Verification** (mandatory when `wip_hash` non-empty):
|
|
64
65
|
|
|
65
|
-
Use `wip_file` → `
|
|
66
|
+
Use `wip_file` → `type: "verify"`, `wipFilePath: "<wip_url>"`, `hash_equal: "<wip_hash>"`.
|
|
66
67
|
|
|
67
68
|
- `wip_hash` empty → no on-chain commitment (auto-verified, weaker evidence)
|
|
68
69
|
- Verification fails → 🔴 **WIP tampered after publish**
|
|
@@ -112,7 +113,7 @@ Use `wip_file` → `op: "verify"`, `wipFilePath: "<wip_url>"`, `hash_equal: "<wi
|
|
|
112
113
|
|
|
113
114
|
### E4 — Guards Analysis
|
|
114
115
|
|
|
115
|
-
Guard structure and instruction reference:
|
|
116
|
+
Guard structure and instruction reference: MCP `schema_query` action='get_guard_design_patterns' (design patterns) and action='get_guard_templates' (ready-made templates).
|
|
116
117
|
|
|
117
118
|
**Step 1**: Collect unique Guard IDs from E3 Machine JSON (`forward.guard.guard`), E1 `order_allocators`, E1 `buy_guard`. Deduplicate.
|
|
118
119
|
|
|
@@ -200,9 +201,23 @@ For matched: present value, ask "correct?" and "OK to send?". For missing: ask u
|
|
|
200
201
|
|
|
201
202
|
---
|
|
202
203
|
|
|
204
|
+
### E11 — Trust Score Synthesis (Preorder Advice)
|
|
205
|
+
|
|
206
|
+
Aggregate E1–E10 into a decision-grade assessment via `trust_score`:
|
|
207
|
+
|
|
208
|
+
`wowok({ tool: "trust_score", data: { service: "<service_id>", depth: "preorder", order_amount: "<planned_amount>" } })`
|
|
209
|
+
|
|
210
|
+
- Returns trust score + per-dimension risks + preorder advice (order confidence, game strategies, preference match, industry risks, `blocking_reminders`); non-empty `blocking_reminders` → ⛔ resolve with user BEFORE Phase 2.
|
|
211
|
+
- Comparing multiple candidates → add `compare_with: ["<id2>", ...]` (1–9, same `depth: "preorder"`): output gains a `comparison` block with per-metric bests — **NO overall ranking**; present trade-offs, the buyer decides.
|
|
212
|
+
- Optional `preferences` / `user_metrics` reflect the buyer's own priorities.
|
|
213
|
+
|
|
214
|
+
> Fast pre-screen: at E1 you may call `depth: "evaluate"` (default) for a quick score; 🔴 `risk_score` (<50) → advise early abort, skip E2–E10.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
203
218
|
### Pre-Purchase GATE
|
|
204
219
|
|
|
205
|
-
**Abort conditions**: E1 `bPublished=false`/`bPaused=true` → ABORT; E8 `um=null` → ABORT; E3 no-refund + E6 no-arb → strongly advise ABORT; E4 ambiguous Guards → user MUST manually review.
|
|
220
|
+
**Abort conditions**: E1 `bPublished=false`/`bPaused=true` → ABORT; E8 `um=null` → ABORT; E3 no-refund + E6 no-arb → strongly advise ABORT; E4 ambiguous Guards → user MUST manually review; E11 `blocking_reminders` → resolve with user BEFORE proceeding.
|
|
206
221
|
|
|
207
222
|
**Any ⚠️** → explain risk, wait for user decision. **All OK** → Phase 2.
|
|
208
223
|
|
|
@@ -369,7 +384,7 @@ For precise control, pass an explicit array of `{id, type}` objects, or pass the
|
|
|
369
384
|
|
|
370
385
|
### Phase Dependency
|
|
371
386
|
|
|
372
|
-
E1 (Service) → E2 (Products/WIP), E8 (Contact), E10 (Privacy), E7 (Compensation), E6 (Arbitrations) run in parallel after E1. E3 (Machine) → E4 (Guards) → E5 (Allocators) is a strict chain. E9 (Reputation) follows E3.
|
|
387
|
+
E1 (Service) → E2 (Products/WIP), E8 (Contact), E10 (Privacy), E7 (Compensation), E6 (Arbitrations) run in parallel after E1. E3 (Machine) → E4 (Guards) → E5 (Allocators) is a strict chain. E9 (Reputation) follows E3. E11 (Trust Score) runs LAST — it aggregates all prior findings.
|
|
373
388
|
|
|
374
389
|
### ⚠️ Critical Attention Items
|
|
375
390
|
|
package/wowok-output/SKILL.md
CHANGED
|
@@ -134,11 +134,11 @@ When user asks about field meanings:
|
|
|
134
134
|
|
|
135
135
|
# Related Skills
|
|
136
136
|
|
|
137
|
-
| Skill | Purpose |
|
|
137
|
+
| Skill / MCP Knowledge | Purpose |
|
|
138
138
|
|-------|---------|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
|
139
|
+
| MCP `schema_query` action='get_safety_rules' | Pre-operation safety checks (sunk from wowok-safety) |
|
|
140
|
+
| MCP `schema_query` action='get_guard_design_patterns' | Guard design & validation (sunk from wowok-guard) |
|
|
141
|
+
| MCP `schema_query` action='get_tool_reference' | Tool selection patterns (sunk from wowok-tools) |
|
|
142
142
|
| [wowok-order](../wowok-order/SKILL.md) | Order lifecycle (buyer) |
|
|
143
143
|
| [wowok-provider](../wowok-provider/SKILL.md) | Service management (merchant) |
|
|
144
144
|
| [wowok-arbitrator](../wowok-arbitrator/SKILL.md) | Dispute resolution |
|
package/wowok-planner/SKILL.md
CHANGED
|
@@ -26,7 +26,8 @@ when_to_use:
|
|
|
26
26
|
Converts natural-language intent into an executable Object Dependency Graph (ODG) and phased execution plan. Deterministic-first: rules and scenario templates decide the shape; the LLM only clarifies ambiguity and translates free text into typed fields.
|
|
27
27
|
|
|
28
28
|
> **Layer**: L3 Skill, primary planner for L4 Harness Plan Loop
|
|
29
|
-
> **Related Skills**: [wowok-onboard](../wowok-onboard/SKILL.md) (guided execution), [wowok-
|
|
29
|
+
> **Related Skills**: [wowok-onboard](../wowok-onboard/SKILL.md) (guided execution), [wowok-machine](../wowok-machine/SKILL.md) (workflow design), [wowok-provider](../wowok-provider/SKILL.md) (post-plan operations)
|
|
30
|
+
> Industry modes, Guard design patterns, safety rules, and tool references now live in the MCP knowledge layer — query via `project_operation` (`recommend_industry` / `list_modes`) and `schema_query` (`get_guard_design_patterns` / `get_safety_rules` / `get_tool_reference`).
|
|
30
31
|
|
|
31
32
|
---
|
|
32
33
|
|
package/wowok-provider/SKILL.md
CHANGED
|
@@ -112,10 +112,9 @@ All Tool: references below are sub-tools invoked via wowok({ tool: "<name>", dat
|
|
|
112
112
|
STEP 1: Foundation
|
|
113
113
|
├── Permission — REUSE existing (strongly recommended)
|
|
114
114
|
│ Tool: "onchain_operations" (permission) | Fields: name, type_parameter
|
|
115
|
-
├── Service (unpublished) — CREATE new
|
|
116
|
-
│ Tool: "onchain_operations" (service) | Fields: name, type_parameter, permission
|
|
117
115
|
└── Machine (unpublished) — CREATE new or REUSE template
|
|
118
116
|
Tool: "onchain_operations" (machine) | Fields: nodes, pairs, forwards
|
|
117
|
+
⚠️ Machine nodes define the workflow; forward guards can be set inline here
|
|
119
118
|
Discovery: "query_toolkit" (account_list, local_mark_list, onchain_objects)
|
|
120
119
|
Template: "machineNode2file" (export existing for editing)
|
|
121
120
|
|
|
@@ -130,40 +129,41 @@ STEP 2: Trust Layer
|
|
|
130
129
|
- Reward guard → pass/fail only
|
|
131
130
|
Guard design patterns: MCP `knowledge/guard-design-patterns.ts` (auto-applied via `evaluate_project`)
|
|
132
131
|
|
|
133
|
-
STEP 3: Business Logic (MODIFY)
|
|
134
|
-
├── Machine — bind Guards to forwards
|
|
135
|
-
│ Tool: "onchain_operations" (machine)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
│
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
132
|
+
STEP 3: Business Logic (MODIFY Machine)
|
|
133
|
+
├── Machine — bind Guards to forwards (update existing forwards with guard fields)
|
|
134
|
+
│ Tool: "onchain_operations" (machine) | Fields: node (op: "add forward" / "set" with updated forwards including guard)
|
|
135
|
+
│ ⚠️ Machine is still unpublished here — guards can be freely bound/unbound
|
|
136
|
+
├── Machine — publish (locks nodes/pairs/forwards permanently)
|
|
137
|
+
│ Tool: "onchain_operations" (machine) | publish: true
|
|
138
|
+
│ ⚠️ After publish, nodes/forwards are IMMUTABLE — verify via machineNode2file first
|
|
139
|
+
└── Service (unpublished) — CREATE with machine + order_allocators + buy_guard + sales
|
|
140
|
+
Tool: "onchain_operations" (service) | Fields: object (with permission), machine, order_allocators, buy_guard, sales
|
|
141
|
+
⚠️ machine must reference a PUBLISHED Machine (else Service publish will fail)
|
|
142
|
+
⚠️ order_allocators is L1-locked — MUST be set before Service publish
|
|
143
143
|
|
|
144
144
|
STEP 4: Publication
|
|
145
|
-
├── Publish
|
|
146
|
-
│
|
|
147
|
-
|
|
148
|
-
│
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
4. Allocator splits match user's stated model?
|
|
157
|
-
5. Permission indexes: every permissionIndex in Machine forwards has entities granted? (call permission "add perm by index" for missing ones)
|
|
158
|
-
6. Arbitration Permission isolation: Arbitration uses a SEPARATE Permission object (not the Service's Permission)? Different owner/admin? (critical for mainnet trust)
|
|
159
|
-
7. Warn: publish = immutable. Proceed?
|
|
145
|
+
├── Pre-Publish Verification (export and review):
|
|
146
|
+
│ 1. machineNode2file → verify Machine nodes/forwards (published, immutable)
|
|
147
|
+
│ 2. guard2file → verify Guard logic
|
|
148
|
+
│ 3. project_operation evaluate_project (risk) → fix CRITICAL findings
|
|
149
|
+
│ 4. Permission indexes: every permissionIndex in Machine forwards has entities granted?
|
|
150
|
+
│ 5. Arbitration Permission isolation (if compensation_fund > 0)
|
|
151
|
+
├── Service — publish (locks machine/order_allocators)
|
|
152
|
+
│ Tool: "onchain_operations" (service) | object: "<service_name>", publish: true
|
|
153
|
+
│ ⚠️ L1-LOCKED: machine and order_allocators are permanently frozen
|
|
154
|
+
└── Post-publish (mutable fields):
|
|
155
|
+
description, location, sales, discount, buy_guard, customer_required, um (Contact), rewards (add), arbitrations (add), repositories (add)
|
|
160
156
|
|
|
161
157
|
STEP 5: Post-Publish (MODIFY Service — mutable after publish)
|
|
162
158
|
├── description, location
|
|
163
159
|
├── sales (products with WIP) — ⛔ user MUST provide: name, price, stock, WIP
|
|
164
160
|
├── customer_required
|
|
165
|
-
|
|
166
|
-
|
|
161
|
+
├── um — Contact (REUSE existing or CREATE new)
|
|
162
|
+
│ ⚠️ If customer_required is set → um MUST be set
|
|
163
|
+
└── Test Order — verify full flow works
|
|
164
|
+
Tool: "onchain_operations" (service) | order_new: { buy: { items, total_pay } }
|
|
165
|
+
⚠️ Requires Service bPublished=true (else E_NOT_PUBLISHED)
|
|
166
|
+
After order: progress advance → allocation.alloc_by_guard → verify fund distribution
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
### Object Reuse & Immutability
|
|
@@ -181,17 +181,17 @@ STEP 5: Post-Publish (MODIFY Service — mutable after publish)
|
|
|
181
181
|
|
|
182
182
|
Deploy a Service in two phases to handle Guard↔Service circular dependencies via LocalMark names. Both phases call `onchain_operations` (operation_type: "service"); they differ by `publish` flag and binding completeness.
|
|
183
183
|
|
|
184
|
-
**Phase 1 — CREATE (no publish)**: Build the full object graph with LocalMark name references so addresses can resolve later.
|
|
184
|
+
**Phase 1 — CREATE (no publish)**: Build the full object graph with LocalMark name references so addresses can resolve later. Machine must be PUBLISHED before this phase.
|
|
185
185
|
|
|
186
186
|
```
|
|
187
187
|
onchain_operations.service {
|
|
188
|
-
name: "<
|
|
189
|
-
|
|
190
|
-
machine: "<machine_local_mark>", # reference by name
|
|
188
|
+
object: {name: "<service_name>", type_parameter, permission},
|
|
189
|
+
machine: "<published_machine_name_or_address>", # must be published
|
|
191
190
|
order_allocators: [{ guard: "<guard_local_mark>", sharing: [...] }, ...],
|
|
192
191
|
arbitrations: { list: ["<arb_local_mark>", ...] },
|
|
193
|
-
buy_guard: "<buy_guard_local_mark>",
|
|
194
|
-
|
|
192
|
+
buy_guard: "<buy_guard_local_mark>", # LocalMark name — defers resolution
|
|
193
|
+
sales: [{ name, price, stock, wip: "<URL>" }],
|
|
194
|
+
publish: false # CRITICAL: do not publish yet
|
|
195
195
|
}
|
|
196
196
|
```
|
|
197
197
|
|
|
@@ -199,7 +199,7 @@ onchain_operations.service {
|
|
|
199
199
|
|
|
200
200
|
```
|
|
201
201
|
onchain_operations.service {
|
|
202
|
-
object: "<
|
|
202
|
+
object: "<service_name>", # target the existing draft by name
|
|
203
203
|
publish: true
|
|
204
204
|
}
|
|
205
205
|
```
|
|
@@ -244,7 +244,7 @@ Order (per purchase, runtime-created)
|
|
|
244
244
|
└── allocation → Allocation (optional, created at runtime; triggered via Progress.forward)
|
|
245
245
|
|
|
246
246
|
Cross-object references:
|
|
247
|
-
- Guard is referenced by 9 object types via diverse nested paths (
|
|
247
|
+
- Guard is referenced by 9 object types via diverse nested paths (full schema via MCP `schema_query` action='get_guard_design_patterns'):
|
|
248
248
|
- Service.buy_guard (top-level Option<address>)
|
|
249
249
|
- Machine.forward.guard (per-node dynamic table; SDK does not expose — requires query_table)
|
|
250
250
|
- Allocation.allocators[].guard (array element — graph-builder edge fieldName: allocator_guard)
|
|
@@ -314,7 +314,7 @@ Required submission: Order ID (matching the Guard's b_submission identifier)
|
|
|
314
314
|
Immutable product commitment for arbitration evidence.
|
|
315
315
|
|
|
316
316
|
```
|
|
317
|
-
Create: wowok({ tool: "wip_file", data: {
|
|
317
|
+
Create: wowok({ tool: "wip_file", data: { type: "generate", ... } }) → markdown_text + images → outputPath
|
|
318
318
|
Attach: wowok({ tool: "onchain_operations", data: { operation_type: "service", ... } }) → sales.sales[{
|
|
319
319
|
name, price, stock, wip: "<URL>", wip_hash: "" (auto)
|
|
320
320
|
}]
|
|
@@ -325,6 +325,16 @@ Attach: wowok({ tool: "onchain_operations", data: { operation_type: "service", .
|
|
|
325
325
|
- Add: `compensation_fund_add` | Lock: `setting_lock_duration_add` (default 30 days = 2592000000ms, configurable via `setting_lock_duration_add`)
|
|
326
326
|
- **Withdraw**: Pause Service → Wait lock duration → `compensation_fund_receive`
|
|
327
327
|
|
|
328
|
+
### Payment Tokens & Stablecoin Bridging (Mainnet Only)
|
|
329
|
+
|
|
330
|
+
WOW is the default settlement token. For stablecoin-denominated revenue (fiat-pegged pricing, large cross-period escrow), mainnet funds move via `bridge_operation`:
|
|
331
|
+
|
|
332
|
+
- `query_supported_tokens` / `query_supported_evm_chains` — discover supported Bridge tokens (ETH/WETH/WBTC/USDC/USDT) and chains
|
|
333
|
+
- `cross_chain_wow_to_evm` / `cross_chain_evm_to_wow` — WOW↔EVM transfer (mainnet env required; assets route through the auto-managed activeEvmAccount)
|
|
334
|
+
- `query_transfer_status` / `query_transfer_list` — track transfers; `manage_evm_rpc` — handle EVM RPC rate limits (429)
|
|
335
|
+
|
|
336
|
+
> Supported token addresses per network: `wowok_buildin_info` → 'mainnet bridge tokens'. Bridge is mainnet-only — testnet has no cross-chain path.
|
|
337
|
+
|
|
328
338
|
---
|
|
329
339
|
|
|
330
340
|
## Project Iteration: Fork vs In-Place
|
package/wowok-guard/SKILL.md
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wowok-guard
|
|
3
|
-
description: |
|
|
4
|
-
WoWok Guard — on-chain programmable validation rules that control access,
|
|
5
|
-
verify eligibility, and provide dynamic data to objects. Guards serve as
|
|
6
|
-
the trust layer for Services (buy_guard), Arbitration (voting_guard weight,
|
|
7
|
-
usage_guard), Machines (forward validation), Demands (recommendation filtering),
|
|
8
|
-
Rewards (claim eligibility), and Repositories (write validation with data extraction).
|
|
9
|
-
Guards also enable off-chain use cases: generate a Passport via `onchain_operations` (`operation_type: "gen_passport"`) to
|
|
10
|
-
obtain a signed, time-bound credential for off-chain permission verification.
|
|
11
|
-
when_to_use:
|
|
12
|
-
- User wants to create or modify a Guard
|
|
13
|
-
- User asks about Guard logic, validation rules, trust rules, programmable conditions
|
|
14
|
-
- User encounters Guard validation errors or needs to debug a Guard
|
|
15
|
-
- User mentions "guard", "validation", "trust rules", "verify", "condition"
|
|
16
|
-
- User asks about buy_guard, allocator guard, reward guard, machine node guard
|
|
17
|
-
- User asks about arbitration voting_guard or usage_guard
|
|
18
|
-
- User needs identity checks, time-locks, multi-condition verification, or entity queries
|
|
19
|
-
- User wants to understand how Guards integrate with other WoWok objects
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
# WoWok Guard Design Reference
|
|
23
|
-
|
|
24
|
-
> **Role**: Service Provider, Arbitrator, or any builder needing programmable on-chain validation
|
|
25
|
-
> **Prerequisites**: Guards are CREATE-only; frozen on-chain once deployed
|
|
26
|
-
> **Related Skills**: [wowok-machine](../wowok-machine/SKILL.md) (forward guards), [wowok-provider](../wowok-provider/SKILL.md) (buy_guard, allocator guards), [wowok-order](../wowok-order/SKILL.md) (guard submissions), [wowok-arbitrator](../wowok-arbitrator/SKILL.md) (voting_guard, usage_guard), [wowok-messenger](../wowok-messenger/SKILL.md) (encrypted evidence), [wowok-safety](../wowok-safety/SKILL.md) (naming, confirmation), [wowok-tools](../wowok-tools/SKILL.md) (tool reference)
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Core Concepts
|
|
31
|
-
|
|
32
|
-
### What a Guard IS
|
|
33
|
-
|
|
34
|
-
A Guard is an **immutable, on-chain programmable validator** — a single-purpose computational tree that returns a boolean: **pass** or **fail**. Every operation protected by a Guard must satisfy its validation logic before the operation can proceed.
|
|
35
|
-
|
|
36
|
-
Think of a Guard as a **computational tree of typed nodes** that query on-chain data, compare values, perform arithmetic, and compute one final answer. It has no side effects. It stores no mutable state. It exists purely to answer: "Should this action be allowed?"
|
|
37
|
-
|
|
38
|
-
### The Immutability Contract
|
|
39
|
-
|
|
40
|
-
Guards are **CREATE-only**. Once frozen on-chain, logic cannot be altered — this is the foundation of trust. To change a Guard: export via `guard2file`, create a new Guard, and update all references. See wowok-safety skill for naming conventions.
|
|
41
|
-
|
|
42
|
-
### The Three Structural Layers
|
|
43
|
-
|
|
44
|
-
Every Guard is built from three layers, each with a distinct role:
|
|
45
|
-
|
|
46
|
-
| Layer | Component | Role | Immutable? |
|
|
47
|
-
|-------|-----------|------|------------|
|
|
48
|
-
| **Declaration** | `table` | Declares every piece of data the Guard touches — constants and runtime submissions — each with a unique identifier (0–255) | Yes |
|
|
49
|
-
| **Computation** | `root` | A computational tree of GuardNode types that computes the final boolean result by combining data sources, comparisons, arithmetic, and logic | Yes |
|
|
50
|
-
| **Composition** | `rely` (optional) | References to other Guards; the current Guard's result is AND-ed or OR-ed with dependencies, enabling modular Guard composition | Yes |
|
|
51
|
-
|
|
52
|
-
**The table is the contract with callers**: It declares what data they must provide at runtime (`b_submission: true`) versus what the Guard already knows (`b_submission: false`). Every `identifier` node references exactly one table entry. **The root is the question**: It must return Bool; intermediate nodes return numbers/strings/addresses/vectors. Guard is **strongly typed** — type mismatches cause creation failure. **The rely is composition**: Up to 4 dependent Guards (AND by default, OR if `logic_or: true`). A Guard can only depend on Guards with `rep: true` (deterministic `repository.data` queries independent of runtime submissions). `rep: false` Guards cannot appear in `rely` lists — violations caught at creation time.
|
|
53
|
-
|
|
54
|
-
### Data Source 4 Classification — The Foundation of Guard Semantics
|
|
55
|
-
|
|
56
|
-
A Guard is fundamentally a **data computation tree**: deterministic data (on-chain constants + system context) + submitted data (runtime, semi-open) → derived through finite operation rules → a single boolean result. Every leaf node in the computation tree draws data from one of **4 data source classifications**. Understanding these 4 classifications is essential for designing and interpreting Guards.
|
|
57
|
-
|
|
58
|
-
| Type | Name | SDK Manifestation | Native Opcode | Trust Level | Typical Scenario |
|
|
59
|
-
|------|------|-------------------|---------------|-------------|------------------|
|
|
60
|
-
| **Type 1** | OnChainConstant | `query` + `identifier` (`b_submission: false`, no witness) | TYPE_QUERY + TYPE_CONSTANT | Highest | Query fields of already-published Service/Machine/Reward objects |
|
|
61
|
-
| **Type 2** | WitnessDerived | `query` + `identifier` + `convert_witness` (100-108) | TYPE_QUERY + witness_byte | High (source trusted + deterministic derivation) | Order → Progress query via witness=100 |
|
|
62
|
-
| **Type 3** | SubmittedObject | `query` + `identifier` (`b_submission: true`, no witness) | TYPE_QUERY + TYPE_CONSTANT | Medium (requires constraint rules) | User submits Order address for field query |
|
|
63
|
-
| **Type 4** | SystemContext | `context` (Signer/Clock/Guard) | TYPE_SIGNER / TYPE_CLOCK / TYPE_GUARD | Highest | Identity verification, time-locks |
|
|
64
|
-
|
|
65
|
-
**Key insights**: Type 1 and Type 3 are isomorphic at the native layer (both TYPE_QUERY+TYPE_CONSTANT; difference is `b_submission` flag). Type 2 overlays on Type 1 or Type 3 (source object can be constant or submission, then witness derives target). Type 4 is fully independent (no table dependency). Except for Type 4, all data must be declared in the table — the table is the complete data contract: deterministic data (`b_submission: false`, type+value baked at creation) + submitted data (`b_submission: true`, type only, value from caller at runtime — **must have constraint rules designed, otherwise empty data is meaningless**).
|
|
66
|
-
|
|
67
|
-
**Guard essence**: A deterministic data set (Type 1 + Type 4) + submitted data (Type 3, must have constraint rules and defined types) → derived through finite operation rules → a single boolean result. You only need to fill in the "data object source meaning" and "field meaning" (e.g., "the permission address of service A", "the current node time of workflow B").
|
|
68
|
-
|
|
69
|
-
### Verifier Constraint Levels — Designing Who Can Pass
|
|
70
|
-
|
|
71
|
-
Three levels trade off **security** vs **convenience** when using `context(Signer)`:
|
|
72
|
-
|
|
73
|
-
**Level 1 — Single-Identity** (`logic_equal[context(Signer), identifier[N](fixed_address)]`): Only ONE address passes. ⚠️ Avoid — if address unavailable (key loss, rotation), Guard permanently blocks. Risk rule `R-C4-04` flags this.
|
|
74
|
-
|
|
75
|
-
**Level 2 — Identity-Set** (recommended): `logic_or` of multiple identity checks. Key distinction:
|
|
76
|
-
- **Address-returning queries** (`order.owner`, `permission.owner`, `service.permission`): wrap in `logic_equal[query, context(Signer)]`
|
|
77
|
-
- **Bool-returning queries** (suffix "has": `order.agent has`, `permission.admin has`): use directly as `logic_or` child, pass `context(Signer)` as parameter
|
|
78
|
-
- **Dynamic permission** (RECOMMENDED): caller submits permission address; Guard verifies `service.permission == submitted_perm` then checks `permission.owner`/`permission.admin has`. Survives permission rotation.
|
|
79
|
-
|
|
80
|
-
**Level 3 — Scene-Combined** (verify if Signer binding is even needed):
|
|
81
|
-
|
|
82
|
-
| Scene | Signer needed? | Why |
|
|
83
|
-
|-------|---------------|-----|
|
|
84
|
-
| Allocators + `sharing.who=Entity` | NO | Funds to fixed recipient (R-C3-06 safe) |
|
|
85
|
-
| Allocators + `sharing.who=Signer` | YES (Level 2) | Funds to caller — must bind |
|
|
86
|
-
| Machine `forward` guard | MAYBE | `permissionIndex`/`namedOperator` may suffice |
|
|
87
|
-
| `buy_guard` | Usually NO | Customer is caller; whitelist/credentials suffice |
|
|
88
|
-
| `voting_guard` | NO | Weight from EntityRegistrar, not Signer (R-C3-02) |
|
|
89
|
-
|
|
90
|
-
**Decision**: If host object already verifies operator OR `sharing.who` routes to fixed recipient → no Signer binding needed. Only add Level 2 when resources flow to caller AND no other layer verifies identity.
|
|
91
|
-
|
|
92
|
-
#### One Guard One Purpose Principle
|
|
93
|
-
|
|
94
|
-
Each Guard should serve **ONE specific purpose**, documented in its `description`:
|
|
95
|
-
- **Scenario**: where the Guard is attached (which host object, which binding field)
|
|
96
|
-
- **Verification rules**: concise statement of what conditions are checked
|
|
97
|
-
- **Risk notes**: which risks are mitigated (R-C3-01/05/06, etc.) and which trade-offs apply
|
|
98
|
-
- **Verifier constraint level**: which Level (1/2/3) is used and why
|
|
99
|
-
|
|
100
|
-
General-purpose Guards designed for `rely` composition are the exception — they need explicit general rules and composition documentation. All other Guards should be single-purpose.
|
|
101
|
-
|
|
102
|
-
### Where Guards Attach in the Ecosystem
|
|
103
|
-
|
|
104
|
-
Guards are not standalone — they plug into other WoWok objects as validation rules. Understanding these integration points is essential because the **context** of the Guard determines what data is available to it and what happens when it fails.
|
|
105
|
-
|
|
106
|
-
| Host Object | Guard Field | What It Controls | Operator | Who Provides Submission Data |
|
|
107
|
-
|-------------|-------------|-----------------|----------|------------------------------|
|
|
108
|
-
| **Service** | `buy_guard` | Who can purchase from this service | Customer | Customer (signer, credentials) |
|
|
109
|
-
| **Service** | `order_allocators[].guard` | Which fund distribution strategy executes | System (auto-evaluated) | System derives from Progress state |
|
|
110
|
-
| **Machine** | Forward `guard` | Who can advance to the next workflow node | Customer or Provider | The party executing the forward |
|
|
111
|
-
| **Progress** | Submission guard | Whether submitted data satisfies conditions during forward execution | Customer or Provider | The party submitting data |
|
|
112
|
-
| **Reward** | `guard` | Who can claim from the reward pool | Claimant | Claimant (address, credentials) |
|
|
113
|
-
| **Repository** | Write/quote guard | Who can write to or read from on-chain storage | Writer/Reader | Writer/Reader |
|
|
114
|
-
| **Arbitration** | `usage_guard` | Who can file a dispute against this arbitration | Customer | Customer (Passport credential) |
|
|
115
|
-
| **Arbitration** | `voting_guard[]` | Who can vote on arbitration proposals and with what weight | Voters (authenticated via Arbitrator) | Voter (Passport credential with weight data) |
|
|
116
|
-
| **Gen Passport** | Guard verification | Generating verified credentials after successful validation | Passport holder | Passport applicant |
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Phase 1: Design — Analyze the Validation Intent
|
|
121
|
-
|
|
122
|
-
Before constructing any node, articulate **what** you are validating and **why**. Start from the business requirement, not the data structure.
|
|
123
|
-
|
|
124
|
-
### The Central Questions
|
|
125
|
-
|
|
126
|
-
Every Guard answers these questions:
|
|
127
|
-
|
|
128
|
-
1. **What action is being protected?** — Buying a service? Advancing a workflow node? Claiming a reward? Casting a weighted vote? Filing a dispute?
|
|
129
|
-
|
|
130
|
-
2. **What data does the Guard have access to?** — Guards see only:
|
|
131
|
-
- Their own `table` (pre-set constants plus runtime submissions from the caller)
|
|
132
|
-
- On-chain state queried through `query` nodes targeting live WoWok objects
|
|
133
|
-
- Transaction context (the current Clock timestamp, the signer's address, the Guard's own object ID)
|
|
134
|
-
|
|
135
|
-
3. **What should the verdict be?** — A single boolean: pass or fail. The root of every Guard tree must return Bool.
|
|
136
|
-
|
|
137
|
-
### Map Business Requirements to Guard Patterns
|
|
138
|
-
|
|
139
|
-
| Business Requirement | Guard Pattern | Key Mechanism | Implementation Notes |
|
|
140
|
-
|----------------------|---------------|---------------|---------------------|
|
|
141
|
-
| "Only the author can purchase this service" | Identity check | Signer address equals stored authorized address | `context(Signer)` vs table constant via `logic_equal`. Variation: use `vec_contains_address` for allowlists |
|
|
142
|
-
| "Customer must wait 8 hours before completing" | Time-lock | Clock timestamp exceeds progress entry time plus duration | `context(Clock)` vs `calc_number_add` of Progress query + duration constant. Use `convert_witness=100` to derive Progress from submitted Order ID |
|
|
143
|
-
| "Only sunny weather on the activity date" | Repository data check | External data matches expected value | `query` on Repository with policy name and data key. Timestamp keys may need `convert_number_address` |
|
|
144
|
-
| "Customer must confirm delivery via signature" | Progress history check | Specific forward has been accomplished | Chain `query_progress_history_find` → `query_progress_history_session_forward_find`. Check `accomplished` flag with `logic_equal` |
|
|
145
|
-
| "User can only claim reward once" | Reward record count check | No prior claims exist | `query_reward_record_count` with recipient filter; compare count to zero via `logic_equal` |
|
|
146
|
-
| "Order payment > 1,000,000 and reached 'complete' to claim reward" | Multi-condition | Order amount + progress state + service match | Combine multiple `query` nodes with `logic_and`. Use `convert_witness=TypeOrderProgress` to access Progress from Order |
|
|
147
|
-
| "Vote weight equals reputation score" | Dynamic weight | GuardIdentifier extracts numeric value from Passport | Table needs numeric submission entry at referenced index. Guard validates eligibility AND weight range |
|
|
148
|
-
| "Only premium members can file disputes" | Membership verification | Entity registration or tier check | `query` on ENTITY_REGISTRAR_ADDRESS or Repository. Combine entity existence check with tier comparison via `logic_and` |
|
|
149
|
-
|
|
150
|
-
### Quick Decision: What Guard Pattern Fits?
|
|
151
|
-
|
|
152
|
-
```
|
|
153
|
-
Identity check? → context(Signer) + logic_equal (single address) / vec_contains_address (allowlist)
|
|
154
|
-
Time constraint? → context(Clock) + calc_number_* comparisons
|
|
155
|
-
External data? → query + table entry declaring target object address
|
|
156
|
-
Progress state? → query_progress_history_find + convert_witness
|
|
157
|
-
One-time claim? → query_reward_record_count + logic_equal(0)
|
|
158
|
-
Dynamic weight? → GuardIdentifier + numeric table entry (b_submission: true)
|
|
159
|
-
External Repository? → query + table entry declaring Repository address
|
|
160
|
-
Entity reputation? → query + table entry declaring ENTITY_REGISTRAR_ADDRESS(0xaab) / ENTITY_LINKER_ADDRESS(0xaaa)
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### Circular Dependency Handling (Service ↔ Guard)
|
|
164
|
-
|
|
165
|
-
When a Guard needs to query a Service that doesn't exist yet (classic chicken-and-egg: `buy_guard` validates Service fields, but Service creation needs `buy_guard` address), use **LocalMark NAME** (not address) in the Guard's query table. LocalMark is resolved by the SDK at publish time, deferring the address binding until after both objects exist.
|
|
166
|
-
|
|
167
|
-
**Workflow** (4-step safe pattern):
|
|
168
|
-
1. **Create Service (no publish)** — Service exists as draft with a LocalMark name
|
|
169
|
-
2. **Create Guard** — In the Guard table, reference the Service via `name_or_address: "<service_local_mark_name>"` (NOT a hardcoded address)
|
|
170
|
-
3. **Update Service** — Set `service.buy_guard = <guard_address>` (now resolvable since Guard is created)
|
|
171
|
-
4. **Publish Service** — SDK resolves LocalMark → on-chain address; both objects now bound
|
|
172
|
-
|
|
173
|
-
> **Why LocalMark**: A Guard that hardcodes a Service address fails creation if the Service doesn't exist yet. LocalMark defers resolution, allowing the Guard to be created first (or in either order). This pattern also applies to Allocator guards that query Service fields.
|
|
174
|
-
|
|
175
|
-
### Triple Verification Template (withdraw / refund Guards)
|
|
176
|
-
|
|
177
|
-
Withdraw and refund guards protect fund flow — the highest-risk operations. They should verify **three independent conditions** (AND-ed):
|
|
178
|
-
|
|
179
|
-
| # | Verification | What to Check | Typical Query |
|
|
180
|
-
|---|---------------|---------------|---------------|
|
|
181
|
-
| (a) | Order status | Order is in expected state (not cancelled / disputed) | `order.service` + `order.balance` |
|
|
182
|
-
| (b) | Progress node completion | Progress.current == expected node (e.g. "completion" / "refund") | `progress.current` (via witness 100 from Order) |
|
|
183
|
-
| (c) | Permission / role | Caller is authorized (merchant / arbiter / customer) | `permission.owner` / `permission.admin has` (Level 2 identity-set) |
|
|
184
|
-
|
|
185
|
-
> **Why all three**: (a) alone is insufficient — Order may be in correct state but Progress not advanced. (b) alone is insufficient — Progress may be at correct node but Order cancelled. (c) alone is insufficient — caller may be authorized but state wrong. AND-combine all three at the Guard root.
|
|
186
|
-
|
|
187
|
-
### Design Before Building
|
|
188
|
-
|
|
189
|
-
**Design thoroughly before calling the create operation** — there is no edit phase after creation (see The Immutability Contract above).
|
|
190
|
-
|
|
191
|
-
1. **Query available query instructions first**: Before designing any Guard that queries on-chain data, use `wowok_buildin_info` with info `"guard instructions"` to retrieve the complete list of available query instructions. Each query has a specific ID, name, parameters, and return type — you MUST verify these details before constructing your Guard. Never guess query instruction names or parameter types.
|
|
192
|
-
2. List every data dependency — what must the caller provide? What constants are baked in?
|
|
193
|
-
3. Sketch the logic tree — what comparisons, arithmetic, and logical combinations produce the final boolean?
|
|
194
|
-
4. Verify types — does every comparison receive compatible operands? Are all conversions explicit?
|
|
195
|
-
5. Test the tree mentally — what happens with edge case inputs? What happens if a query returns empty?
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## Phase 2: Declare the Data Table
|
|
200
|
-
|
|
201
|
-
The Guard table is the **complete declaration of information** the Guard consumes. Every `identifier` node in the computation tree references exactly one table entry by its index number (0–255). Nothing outside the table is accessible.
|
|
202
|
-
|
|
203
|
-
### Table Entry Fields
|
|
204
|
-
|
|
205
|
-
| Field | Meaning | Required When |
|
|
206
|
-
|-------|---------|---------------|
|
|
207
|
-
| `identifier` | Unique index (0–255). The computation tree uses this number to reference the entry. | Always |
|
|
208
|
-
| `b_submission` | Whether the **caller** must provide this value at runtime. `true` = runtime submission; `false` = pre-set constant. | Always |
|
|
209
|
-
| `value_type` | The type of the value: Bool, Address, String, U8–U256, or vector types. Accepts both string names (preferred, e.g., `"Address"`, `"U64"`) and numeric codes (e.g., `1`, `6`). Use `wowok_buildin_info` with info `"value types"` for the complete mapping. SDK deserialization returns string names. | Always |
|
|
210
|
-
| `value` | The constant value when `b_submission` is false; a placeholder when `b_submission` is true. | When `b_submission` is false |
|
|
211
|
-
| `name` | Human-readable label describing what this entry represents. | Always |
|
|
212
|
-
|
|
213
|
-
### Design Rules
|
|
214
|
-
|
|
215
|
-
- **Every identifier in the tree must exist in the table.** Missing references cause creation to fail.
|
|
216
|
-
- **No duplicate identifiers.** Each index number must appear exactly once.
|
|
217
|
-
- **Non-submission entries must have a value.** These are baked into the Guard immutably.
|
|
218
|
-
- **Submission entries use placeholder values.** The actual value is provided by the caller at runtime.
|
|
219
|
-
- **Query target objects must be of type Address in the table.** The `object_type` field is **automatically filled by the SDK** based on the first query node referencing this identifier (it is NOT a user-provided field). The SDK infers the object type from the query instruction's target object type (Progress, Order, Machine, Reward, etc.).
|
|
220
|
-
- **Querying EntityRegistrar or EntityLinker requires system address table entries.** Add entries for `ENTITY_REGISTRAR_ADDRESS` (`0xaab`) or `ENTITY_LINKER_ADDRESS` (`0xaaa`) to the table as Address-type constants when your query instruction targets these global registries. Without them, creation fails.
|
|
221
|
-
- **Maximum 256 table entries** (identifiers 0–255). The total serialized table size must not exceed 40000 bytes.
|
|
222
|
-
- **Submission entries must have descriptive `name` values.** For `b_submission: true` entries, `name` is the contract between Guard and caller — it tells callers what data they must provide. Use natural language that explains the purpose and necessity: "The order ID that identifies the target Order for verification" not `"order_id"`, "The signer's account address that will be compared against the authorized list" not `"addr"`. This is critical because callers see only this name when submitting data.
|
|
223
|
-
|
|
224
|
-
### The convert_witness Mechanism
|
|
225
|
-
|
|
226
|
-
`convert_witness` transforms a source object ID into its associated target object — enabling queries across object relationships without requiring the caller to submit multiple IDs. This is the **Type 2 (WitnessDerived)** data source.
|
|
227
|
-
|
|
228
|
-
**Core principle**: Witness is a "read the source object's associated field" mechanism (not a lookup table, not an independent index). It is a one-to-one deterministic derivation of object relationships with only 9 derivation types. Caller submits what they have (e.g., Order ID); Guard queries what it needs (e.g., Progress state) via witness conversion.
|
|
229
|
-
|
|
230
|
-
**Rules**:
|
|
231
|
-
- Witness type encodes source→target transformation
|
|
232
|
-
- Table entry's `object_type` (auto-filled by SDK) must match witness source type
|
|
233
|
-
- Query instruction's object type must match witness target type
|
|
234
|
-
- Type mismatches cause Guard creation to fail
|
|
235
|
-
- Multi-hop witnesses (106-108) require intermediate objects to exist
|
|
236
|
-
|
|
237
|
-
**Complete 9 witness types** (defined in `guard.rs#L34-L65`):
|
|
238
|
-
|
|
239
|
-
| Code | Name | Source → Target | Derivation | Hops |
|
|
240
|
-
|------|------|-----------------|------------|------|
|
|
241
|
-
| 100 | TypeOrderProgress | Order → Progress | read order.progress field | 1 |
|
|
242
|
-
| 101 | TypeOrderMachine | Order → Machine | read order.machine field | 1 |
|
|
243
|
-
| 102 | TypeOrderService | Order → Service | read order.service field | 1 |
|
|
244
|
-
| 103 | TypeProgressMachine | Progress → Machine | read progress.machine field | 1 |
|
|
245
|
-
| 104 | TypeArbOrder | Arb → Order | read arb.order field | 1 |
|
|
246
|
-
| 105 | TypeArbArbitration | Arb → Arbitration | read arb.arbitration field | 1 |
|
|
247
|
-
| 106 | TypeArbProgress | Arb → Progress | arb.order → order.progress | 2 (multi-hop) |
|
|
248
|
-
| 107 | TypeArbMachine | Arb → Machine | arb.order → order.machine | 2 (multi-hop) |
|
|
249
|
-
| 108 | TypeArbService | Arb → Service | arb.order → order.service | 2 (multi-hop) |
|
|
250
|
-
|
|
251
|
-
**Key notes**:
|
|
252
|
-
- **Type 2 can overlay on Type 1 or Type 3**: The source object can be a constant (Type 1, `b_submission: false`) or a submission (Type 3, `b_submission: true`). The witness then derives the target object.
|
|
253
|
-
- **Multi-hop witnesses (106-108)**: Arb → Progress/Machine/Service uses two hops (Arb → Order → target). The intermediate Order object must exist for the derivation to succeed.
|
|
254
|
-
- **TypeArbArbitration (105)**: Arb and Arbitration are **different on-chain objects**. The witness queries the Arbitration (parent service) from an Arb (case) address — the binding is set when Arbitration creates the Arb.
|
|
255
|
-
- **Available witness types** are also discoverable via `wowok_buildin_info` with info `"guard instructions"`.
|
|
256
|
-
|
|
257
|
-
---
|
|
258
|
-
|
|
259
|
-
## Phase 3: Build the Computational Tree
|
|
260
|
-
|
|
261
|
-
The root tree is a computational expression whose terminal nodes read data and whose intermediate nodes transform, compare, and combine that data. The root must return Bool.
|
|
262
|
-
|
|
263
|
-
### Tree Principles
|
|
264
|
-
|
|
265
|
-
- **Type safety is enforced at creation time.** Every node validates that its children return types compatible with its operation. A `logic_equal` node that receives a String child and a U64 child will fail validation.
|
|
266
|
-
- **Evaluation order is stack-based.** Children are evaluated in reverse, so the first child in the array appears at the top of the evaluation stack.
|
|
267
|
-
- **Every `identifier` node's index must exist in the table.** This is validated at creation time.
|
|
268
|
-
|
|
269
|
-
### Discovering Available Node Types
|
|
270
|
-
|
|
271
|
-
Query the authoritative `GuardNodeSchema` via `schema_query` (name: `onchain_operations_guard`) — it returns every node type, required fields, input/output types, and validation rules. Categories include: data source nodes (`identifier`, `context`, `query`), logic/arithmetic nodes (`logic_*`, `calc_number_*`), string/conversion/vector nodes (`calc_string_*`, `convert_*`, `vec_*`), and record query nodes (`query_reward_record_*`, `query_progress_history_*`).
|
|
272
|
-
|
|
273
|
-
**Key principle**: Every node declares its return type and the types it expects from children. The schema enforces these constraints at Guard creation time — type mismatches cause creation to fail. All numeric comparisons normalize to U256, enabling cross-type comparisons without explicit conversion. For the `query` node, discover available instructions via `wowok_buildin_info` ("guard instructions") with `filter` to narrow by name/return type/parameter count/object type.
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## Phase 4: Create the Guard
|
|
278
|
-
|
|
279
|
-
Guard creation is a **single atomic operation** — it either succeeds (the Guard is frozen on-chain) or fails (nothing is created). There is no intermediate draft state, no editing phase, and no deletion mechanism.
|
|
280
|
-
|
|
281
|
-
Use `onchain_operations` (`operation_type: "guard"`) with `root.type: "node"` (inline tree) or `root.type: "file"` (load from `guard2file`-exported JSON/MD — use this to iterate on existing Guards: export → edit → create new).
|
|
282
|
-
|
|
283
|
-
---
|
|
284
|
-
|
|
285
|
-
## Phase 5: Test, Export, and Query
|
|
286
|
-
|
|
287
|
-
**Test**: `gen_passport` verifies one or more Guards (AND-ed) and generates an immutable Passport on success. Omit `info` to auto-fetch submissions, or provide explicitly for custom test inputs.
|
|
288
|
-
|
|
289
|
-
**Query**: `query_toolkit` → `onchain_objects` for any Guard. Results include `_guard_node_comments` (human-readable annotations per node). Guards are public consensus — all parties can inspect validation rules.
|
|
290
|
-
|
|
291
|
-
**Iteration**: `guard2file` → edit JSON/MD → create new Guard via `root.type:"file"` → update all references.
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
|
-
## Guard Data Flow: How Objects Read Guard Data
|
|
296
|
-
|
|
297
|
-
Guards are validators AND data sources. When bound, objects read structured data for decisions. Design your Guard table based on what data the target object needs to read — objects don't just validate, they consume Guard submissions as structured data inputs.
|
|
298
|
-
|
|
299
|
-
### Type Requirements by Object
|
|
300
|
-
|
|
301
|
-
Each object extracts Guard data with precise type expectations. Mismatches cause creation or runtime failure:
|
|
302
|
-
|
|
303
|
-
| Object | Extraction Field | Table Index Requirement | Type Constraint |
|
|
304
|
-
|--------|-----------------|------------------------|-----------------|
|
|
305
|
-
| **Arbitration** `voting_guard` | Vote weight via `GuardIdentifier(u8)` | Index must be `b_submission: true` | **Numeric** (U8–U256, cast to u32) |
|
|
306
|
-
| **Demand** `ServiceGuard` | `service_identifier` mapping | Index must be `b_submission: true` | Depends on Service validation |
|
|
307
|
-
| **Machine** Forward | `retained_submission` | Index must be `b_submission: true`; uniquely located by `node→next_node→forward` triple | As declared in table |
|
|
308
|
-
| **Repository** | `id_from_submission` | Index must be `b_submission: true` | **Must be Address** |
|
|
309
|
-
| **Repository** | `data_from_submission` | Index must be `b_submission: true` | **Must match Repository's value_type** |
|
|
310
|
-
|
|
311
|
-
**Notes**: Arbitration uses `usage_guard` for eligibility (pass/fail) and `voting_guard` for weight (fixed or dynamic via `GuardIdentifier`). Demand's `ServiceGuard` passes the submission value at `service_identifier` to the service for validation (if unset, only pass/fail checked). Machine's `retained_submission` stores submission values in Progress for audit. Repository's `id_from_submission`/`data_from_submission` extract structured data from Guard submissions.
|
|
312
|
-
|
|
313
|
-
**⚠️ Critical — impack_list semantics in verify phase**: When a Guard queries Repository data (query 1167 `repository.data`) with a policy that has a `quote_guard` set, the verification checks whether the quote_guard address is in the `impack_list`. However, `impack_list` is **always empty during the `verify_guard` phase** — `Passport.new()` initializes `impack:vector[]` and the verify loop never modifies it; `impack` is only populated in `result_for_permission` (after verify completes). This means a Repository query with `quote_guard = Some(addr)` will always fail with `IMPACK_GUARD_NOT_FOUND` in the gen_passport flow; only `quote_guard = None` passes. Verify the quote_guard mechanism's design intent before relying on it.
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
## Best Practices
|
|
318
|
-
|
|
319
|
-
### Common Pitfalls
|
|
320
|
-
|
|
321
|
-
> The full constraint system has **33 rules: 22 creation-phase + 11 runtime-phase**. The 22 creation-phase constraints below are all enforced by SDK + native `validate_guard_data`; runtime constraints are enforced by native `verify_guard`.
|
|
322
|
-
|
|
323
|
-
#### Creation-Phase Constraints (22 rules, all enforced by SDK + `validate_guard_data`)
|
|
324
|
-
|
|
325
|
-
**Root**: Must return Bool (logic/comparison nodes only).
|
|
326
|
-
**Table**: Unique identifiers (0–255), tree-to-table referential integrity, non-empty constants, max 256 entries / 40KB BCS, submission entries = 1-byte type code.
|
|
327
|
-
**Query**: Discover valid IDs via `wowok_buildin_info` ("guard instructions"); parameter count/types must match; return type must be compatible with parent (use `convert_string_number`/`convert_number_string` for type mismatches; `logic_as_u256_*` for numeric comparisons); `object.identifier` must be Address type.
|
|
328
|
-
**Witness**: 100–108 only; target type must match query's expected object; source type must match table's `object_type`. **Missing `convert_witness`** when accessing Progress from Order ID = runtime failure (looks for Progress at Order's address).
|
|
329
|
-
**Rely**: Max 4; must have `rep:true`; no self-reference.
|
|
330
|
-
**Binding**: `voting_guard` identifier must be numeric (U8–U256); Repository `id_from_submission` must be Address; `data_from_submission` type must match Repository's `value_type`.
|
|
331
|
-
**Immutable**: Guard frozen after `guard::create` — to change, export via `guard2file` and create new.
|
|
332
|
-
|
|
333
|
-
#### Practical Tips (not strict constraints, but strongly recommended)
|
|
334
|
-
|
|
335
|
-
- **Testing with production durations**: Set time-lock durations to small values (e.g., 1000 milliseconds) during testing. Increase to production values only after verifying the logic works correctly. A Guard with a 30-day lock tested with real durations cannot produce results for a month.
|
|
336
|
-
- **Forgetting to export before recreating**: Guards are immutable. If you need to change one, export it first with `guard2file` so you have the exact on-chain definition as a reference. Then create a new Guard with a versioned name and update all references.
|
|
337
|
-
- **Not checking Arbitration pause state**: Even with a valid usage_guard Passport, the dispute fails if the Arbitration is paused (`bPaused: true`). The pause check happens before the guard check — advise customers to verify the Arbitration is active before generating Passports.
|
|
338
|
-
|
|
339
|
-
#### Runtime-Phase Constraints (enforced by native `verify_guard`)
|
|
340
|
-
|
|
341
|
-
These constraints are checked at Guard verification time (gen_passport or actual usage), not at creation. They are often overlooked because creation succeeds but runtime fails:
|
|
342
|
-
|
|
343
|
-
- **RUN_IMMUTABLE_01**: Guard must have `immutable=true` to be verified. A Guard that hasn't been finalized via `guard::create` cannot be used.
|
|
344
|
-
- **RUN_SUB_01**: The submission's `value[0]` (type byte) must match the table declaration. A submission with the wrong type byte is rejected.
|
|
345
|
-
- **RUN_SUB_02**: Every table entry with `b_submission=true` must have a corresponding submission value. Missing submissions cause failure.
|
|
346
|
-
- **RUN_SUB_03**: Total submission bytes must be ≤ `MAX_SUBMISSION_SIZE` (256).
|
|
347
|
-
- **RUN_WITNESS_01/02**: When witness conversion runs, the source object must have the associated field, and the derived target object must exist. Multi-hop witnesses (106-108) require the intermediate Order object to exist.
|
|
348
|
-
- **RUN_QUERY_01**: The query target object must exist and its type must match.
|
|
349
|
-
- **RUN_IMPACK_01/02**: At least one impack guard is required; an impack guard failure fails the entire passport. **Note**: `impack_list` is always empty during verify (see Repository section above), so quote_guard queries will fail unless `quote_guard = None`.
|
|
350
|
-
- **RUN_TX_01**: The Passport's `tx_hash` must match the current transaction.
|
|
351
|
-
- **RUN_RELY_01**: Rely guards must have been added to the passport.
|
|
352
|
-
|
|
353
|
-
### Readability Convention — Prefer String Names
|
|
354
|
-
|
|
355
|
-
**Always use string names** (not numeric IDs) for `query` (`"order.service"` not `1563`), `value_type` (`"Address"` not `1`), `convert_witness` (`"OrderProgress"` not `100`), and `context` (`"Signer"`). Matching is case-insensitive. SDK deserialization (`guard2file`/`query_objects`) returns all constants as strings. Discover valid query names via `wowok_buildin_info` with info `"guard instructions"`.
|
|
356
|
-
|
|
357
|
-
Common allocator-guard queries: `order.service` (theft protection), `order.owner` (refund binding), `progress.current` (node check), `progress.current_time` (time-lock), `service.permission`, `permission.owner`, `permission.admin has` (identity-set).
|
|
358
|
-
|
|
359
|
-
---
|