@wowok/agent-mcp 2.4.1 → 2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -1624
- package/dist/knowledge/guard-ledger.js +14 -0
- package/dist/knowledge/guard-lint.d.ts +1 -0
- package/dist/knowledge/guard-lint.js +83 -3
- package/dist/knowledge/guard-migration.d.ts +48 -0
- package/dist/knowledge/guard-migration.js +228 -0
- package/dist/knowledge/guard-risk.d.ts +2 -0
- package/dist/knowledge/guard-risk.js +827 -57
- package/dist/knowledge/guard-templates.d.ts +1 -0
- package/dist/knowledge/guard-templates.js +278 -2
- package/dist/project/graph.d.ts +1 -0
- package/dist/project/graph.js +27 -1
- package/dist/project/index.d.ts +1 -0
- package/dist/project/index.js +39 -2
- package/dist/project/namespace.d.ts +11 -1
- package/dist/project/namespace.js +27 -2
- package/dist/project/query.d.ts +2 -0
- package/dist/project/query.js +56 -15
- package/dist/rules.d.ts +12 -0
- package/dist/rules.js +9 -0
- package/dist/schema/call/allocation.d.ts +10 -10
- package/dist/schema/call/base.js +3 -3
- package/dist/schema/call/machine.d.ts +38 -38
- package/dist/schema/call/semantic.js +1 -1
- package/dist/schema/call/service.d.ts +7 -7
- package/dist/schema/operations.d.ts +48 -48
- package/dist/schema/query/index.d.ts +146 -146
- package/dist/schema/query/index.js +15 -9
- package/dist/schema/utils/guard-query-utils.d.ts +7 -0
- package/dist/schema/utils/guard-query-utils.js +14 -1
- package/dist/schemas/bridge_operation.output.json +1 -1
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/messenger_operation.output.json +1 -1
- package/dist/schemas/onchain_events.output.json +1 -1
- package/dist/schemas/onchain_operations.output.json +2 -2
- package/dist/schemas/onchain_operations.schema.json +11 -20
- package/dist/schemas/onchain_operations_allocation.schema.json +7 -10
- package/dist/schemas/onchain_operations_machine.schema.json +2 -5
- package/dist/schemas/onchain_operations_service.schema.json +2 -5
- package/dist/schemas/onchain_table_data.output.json +6 -12
- package/dist/tools/handlers/bridge.d.ts +1 -0
- package/dist/tools/handlers/bridge.js +1 -0
- package/dist/tools/handlers/config.d.ts +2 -0
- package/dist/tools/handlers/config.js +71 -0
- package/dist/tools/handlers/file-export.d.ts +3 -0
- package/dist/tools/handlers/file-export.js +90 -0
- package/dist/tools/handlers/local.d.ts +30 -0
- package/dist/tools/handlers/local.js +27 -0
- package/dist/tools/handlers/messenger.d.ts +16 -0
- package/dist/tools/handlers/messenger.js +187 -0
- package/dist/tools/handlers/onchain.d.ts +2 -0
- package/dist/tools/handlers/onchain.js +246 -0
- package/dist/tools/handlers/project.d.ts +2 -0
- package/dist/tools/handlers/project.js +53 -0
- package/dist/tools/handlers/query.d.ts +5 -0
- package/dist/tools/handlers/query.js +256 -0
- package/dist/tools/handlers/schema-query.d.ts +2 -0
- package/dist/tools/handlers/schema-query.js +92 -0
- package/dist/tools/handlers/trust.d.ts +2 -0
- package/dist/tools/handlers/trust.js +194 -0
- package/dist/tools/handlers/wip.d.ts +2 -0
- package/dist/tools/handlers/wip.js +44 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.js +479 -0
- package/dist/tools/rules-hook.d.ts +2 -0
- package/dist/tools/rules-hook.js +22 -0
- package/dist/tools/shared.d.ts +29 -0
- package/dist/tools/shared.js +130 -0
- package/dist/tools/types.d.ts +35 -0
- package/dist/tools/types.js +1 -0
- package/dist/tools/wrap.d.ts +6 -0
- package/dist/tools/wrap.js +55 -0
- package/package.json +19 -5
|
@@ -20,6 +20,7 @@ export interface GuardTemplate {
|
|
|
20
20
|
relevant_risks: string[];
|
|
21
21
|
creation_notes: string[];
|
|
22
22
|
example_use_case: string;
|
|
23
|
+
verifier_constraint_level?: "level1_strict" | "level2_identity_set" | "level3_scene_combined";
|
|
23
24
|
}
|
|
24
25
|
export declare const GUARD_TEMPLATES: GuardTemplate[];
|
|
25
26
|
export declare function getTemplatesByScene(sceneId: string): GuardTemplate[];
|
|
@@ -26,6 +26,7 @@ export const GUARD_TEMPLATES = [
|
|
|
26
26
|
"If the Service is already published, the table can use the address directly; otherwise use the name (P16 circular reference)",
|
|
27
27
|
],
|
|
28
28
|
example_use_case: "Internal testing phase for camera equipment rental, allowing only the first 50 seed users to place rental orders.",
|
|
29
|
+
verifier_constraint_level: "level2_identity_set",
|
|
29
30
|
},
|
|
30
31
|
{
|
|
31
32
|
id: "tpl_allocator_threshold",
|
|
@@ -55,6 +56,202 @@ export const GUARD_TEMPLATES = [
|
|
|
55
56
|
"Threshold boundary must be tested: behavior when exactly equal to the threshold (> vs >=)",
|
|
56
57
|
],
|
|
57
58
|
example_use_case: "E-commerce platform: order amount > 1000 WOW triggers 3-way allocation (platform + merchant + logistics); otherwise 2-way allocation (platform + merchant).",
|
|
59
|
+
verifier_constraint_level: "level3_scene_combined",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "tpl_allocator_treasury_personal",
|
|
63
|
+
scene_id: "service_order_allocators_guard",
|
|
64
|
+
name: "Treasury + personal address allocation (Entity sharing)",
|
|
65
|
+
description: "2 allocators representing 2 merchant collection approaches: (1) named Treasury address for public fund aggregation, (2) fixed personal address. " +
|
|
66
|
+
"Uses sharing.who=Entity so funds always flow to the legitimate recipient regardless of caller — no Signer binding needed in Guard. " +
|
|
67
|
+
"Guards verify the order is at the Complete node + belongs to the service (project binding).",
|
|
68
|
+
recommended_patterns: ["P02", "P10", "P16"],
|
|
69
|
+
parameters: [
|
|
70
|
+
{ name: "service_name", type: "string", description: "Service object name (circular ref via P16 — resolved after Service publish)", required: true,
|
|
71
|
+
constraint: "Must be a name, not an address (the Service is not yet published when the Guard is created)" },
|
|
72
|
+
{ name: "complete_node_name", type: "string", description: "Expected node name that triggers allocation (e.g. 'Complete')", required: true,
|
|
73
|
+
default: "Complete", constraint: "Must exactly match the Machine node name (case-sensitive)" },
|
|
74
|
+
{ name: "treasury_name", type: "string", description: "Named Treasury object (created with the Service's permission)", required: true,
|
|
75
|
+
constraint: "Treasury must be created before the Service; use the SAME permission as the Service for consistency" },
|
|
76
|
+
{ name: "personal_address", type: "address", description: "Fixed personal collection address (e.g. the permission creator's address)", required: true },
|
|
77
|
+
],
|
|
78
|
+
example_table: [
|
|
79
|
+
{ identifier: 0, b_submission: true, value_type: "Address", object_type: "Order",
|
|
80
|
+
name: "order_id (Order object submitted at runtime)" },
|
|
81
|
+
{ identifier: 1, b_submission: false, value_type: "String", value: "${complete_node_name}",
|
|
82
|
+
name: "Expected Complete node name (case-sensitive)" },
|
|
83
|
+
{ identifier: 2, b_submission: false, value_type: "Address", value: "${service_name}",
|
|
84
|
+
name: "Service object (project binding, circular ref via name)" },
|
|
85
|
+
],
|
|
86
|
+
example_root: {
|
|
87
|
+
type: "logic_and",
|
|
88
|
+
nodes: [
|
|
89
|
+
{
|
|
90
|
+
type: "logic_equal",
|
|
91
|
+
nodes: [
|
|
92
|
+
{ type: "query", query: "progress.current", object: { identifier: 0, convert_witness: "OrderProgress" }, parameters: [] },
|
|
93
|
+
{ type: "identifier", identifier: 1 },
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "logic_equal",
|
|
98
|
+
nodes: [
|
|
99
|
+
{ type: "query", query: "order.service", object: { identifier: 0 }, parameters: [] },
|
|
100
|
+
{ type: "identifier", identifier: 2 },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
applicable_industries: ["insurance", "ecommerce", "travel", "rental", "subscription"],
|
|
106
|
+
relevant_risks: ["R-C3-05", "R-C3-06", "R-X1-05", "R-X1-01"],
|
|
107
|
+
creation_notes: [
|
|
108
|
+
"2 Guard objects with IDENTICAL root/table but DIFFERENT descriptions (allocators require unique guard addresses — no two allocators may reference the same Guard).",
|
|
109
|
+
"sharing.who=Entity (Treasury/personal) — no Signer binding needed in the Guard (R-C3-06 safe).",
|
|
110
|
+
"First-match-wins: only the first allocator (Treasury) executes; the personal allocator is an alternative (swap the allocators order to activate personal collection).",
|
|
111
|
+
"Treasury should be created with the SAME permission as the Service (permission consistency — different permissions = minor risk).",
|
|
112
|
+
"order.service binding (query 1563) suppresses R-C3-05 (cross-project bypass prevents premature allocation on foreign orders).",
|
|
113
|
+
"order_allocators is immutable after Service publish — verify the Guard logic and sharing config before publishing.",
|
|
114
|
+
],
|
|
115
|
+
example_use_case: "Insurance service: after a claim reaches the Complete node, order funds are allocated to the insurance Treasury " +
|
|
116
|
+
"(approach 1, for operational fund aggregation) or to the provider's personal address (approach 2, for direct income).",
|
|
117
|
+
verifier_constraint_level: "level3_scene_combined",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "tpl_allocator_identity_set_order_holder",
|
|
121
|
+
scene_id: "service_order_allocators_guard",
|
|
122
|
+
name: "Order-holder identity-set allocation (Level 2)",
|
|
123
|
+
description: "Level 2 identity-set binding: Signer is order.owner (1562, Address) OR order.agent (1567, Bool with [Signer] param). " +
|
|
124
|
+
"Demonstrates the mixed return-type construction pattern — Address-returning queries are wrapped in logic_equal, " +
|
|
125
|
+
"while Bool-returning queries (suffix 'has') are used directly as logic_or children. " +
|
|
126
|
+
"Combined with order.service binding (R-C3-05) for cross-service theft prevention. " +
|
|
127
|
+
"Use when either the order owner or an authorized agent should be able to trigger allocation (e.g. refund to caller).",
|
|
128
|
+
recommended_patterns: ["P02", "P10", "P16"],
|
|
129
|
+
parameters: [
|
|
130
|
+
{ name: "service_name", type: "string", description: "Service object name (circular ref via P16)", required: true,
|
|
131
|
+
constraint: "Must be a name, not an address (the Service is not yet published when the Guard is created)" },
|
|
132
|
+
],
|
|
133
|
+
example_table: [
|
|
134
|
+
{ identifier: 0, b_submission: true, value_type: "Address", object_type: "Order",
|
|
135
|
+
name: "order_id (Order object submitted at runtime)" },
|
|
136
|
+
{ identifier: 1, b_submission: false, value_type: "Address", value: "${service_name}",
|
|
137
|
+
name: "Service object (project binding, circular ref via name)" },
|
|
138
|
+
],
|
|
139
|
+
example_root: {
|
|
140
|
+
type: "logic_and",
|
|
141
|
+
nodes: [
|
|
142
|
+
{
|
|
143
|
+
type: "logic_or",
|
|
144
|
+
nodes: [
|
|
145
|
+
{
|
|
146
|
+
type: "logic_equal",
|
|
147
|
+
nodes: [
|
|
148
|
+
{ type: "query", query: "order.owner", object: { identifier: 0 }, parameters: [] },
|
|
149
|
+
{ type: "context", context: "Signer" },
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
type: "query",
|
|
154
|
+
query: "order.agent has",
|
|
155
|
+
object: { identifier: 0 },
|
|
156
|
+
parameters: [{ type: "context", context: "Signer" }],
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: "logic_equal",
|
|
162
|
+
nodes: [
|
|
163
|
+
{ type: "query", query: "order.service", object: { identifier: 0 }, parameters: [] },
|
|
164
|
+
{ type: "identifier", identifier: 1 },
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
applicable_industries: ["ecommerce", "rental", "travel", "subscription"],
|
|
170
|
+
relevant_risks: ["R-C3-01", "R-C3-05", "R-C3-06", "R-C4-04"],
|
|
171
|
+
creation_notes: [
|
|
172
|
+
"MIXED RETURN-TYPE CONSTRUCTION (key Level 2 pattern): query 1562 (order.owner) returns Address → wrap in logic_equal with context(Signer); query 1567 (order.agent has) returns Bool → use directly as logic_or child with parameters: [context(Signer)].",
|
|
173
|
+
"logic_or wrapping of the Signer check suppresses R-C4-04 (Level 1 strict binding convenience warning) — this is the recommended Level 2 alternative.",
|
|
174
|
+
"Use this pattern when sharing.who=Signer (funds flow to caller) AND either the owner or an agent should be authorized to trigger allocation.",
|
|
175
|
+
"order.service binding (query 1563) suppresses R-C3-05 (cross-project bypass).",
|
|
176
|
+
"If agents are not needed, use the simpler Level 2 dynamic pattern: logic_equal[query(1562), context(Signer)] without logic_or.",
|
|
177
|
+
],
|
|
178
|
+
example_use_case: "Refund allocation: when an order is cancelled, either the order owner or an authorized agent can trigger the refund. " +
|
|
179
|
+
"The Guard verifies Signer is order.owner OR order.agent, and that the order belongs to this service.",
|
|
180
|
+
verifier_constraint_level: "level2_identity_set",
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: "tpl_allocator_identity_set_service_provider_dynamic",
|
|
184
|
+
scene_id: "service_order_allocators_guard",
|
|
185
|
+
name: "Service-provider identity-set allocation with dynamic permission (Level 2)",
|
|
186
|
+
description: "Level 2 identity-set binding with DYNAMIC permission address: Signer is permission.owner (1002, Address) OR " +
|
|
187
|
+
"has admin (1004, Bool with [Signer] param). The permission address is submitted by the caller and verified " +
|
|
188
|
+
"against service.permission (1488) — this survives permission rotation without rebuilding the Guard. " +
|
|
189
|
+
"Use when the Service may rotate its permission (like a company changing its board) and a static permission " +
|
|
190
|
+
"address would break the Guard.",
|
|
191
|
+
recommended_patterns: ["P02", "P10", "P16"],
|
|
192
|
+
parameters: [
|
|
193
|
+
{ name: "service_name", type: "string", description: "Service object name (circular ref via P16)", required: true,
|
|
194
|
+
constraint: "Must be a name, not an address (the Service is not yet published when the Guard is created)" },
|
|
195
|
+
],
|
|
196
|
+
example_table: [
|
|
197
|
+
{ identifier: 0, b_submission: true, value_type: "Address", object_type: "Order",
|
|
198
|
+
name: "order_id (Order object submitted at runtime)" },
|
|
199
|
+
{ identifier: 1, b_submission: false, value_type: "Address", value: "${service_name}",
|
|
200
|
+
name: "Service object (project binding, circular ref via name)" },
|
|
201
|
+
{ identifier: 2, b_submission: true, value_type: "Address", object_type: "Permission",
|
|
202
|
+
name: "permission_id (Permission object submitted by caller — must equal service.permission)" },
|
|
203
|
+
],
|
|
204
|
+
example_root: {
|
|
205
|
+
type: "logic_and",
|
|
206
|
+
nodes: [
|
|
207
|
+
{
|
|
208
|
+
type: "logic_equal",
|
|
209
|
+
nodes: [
|
|
210
|
+
{ type: "query", query: "order.service", object: { identifier: 0 }, parameters: [] },
|
|
211
|
+
{ type: "identifier", identifier: 1 },
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
type: "logic_equal",
|
|
216
|
+
nodes: [
|
|
217
|
+
{ type: "query", query: "service.permission", object: { identifier: 1 }, parameters: [] },
|
|
218
|
+
{ type: "identifier", identifier: 2 },
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
type: "logic_or",
|
|
223
|
+
nodes: [
|
|
224
|
+
{
|
|
225
|
+
type: "logic_equal",
|
|
226
|
+
nodes: [
|
|
227
|
+
{ type: "query", query: "permission.owner", object: { identifier: 2 }, parameters: [] },
|
|
228
|
+
{ type: "context", context: "Signer" },
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
type: "query",
|
|
233
|
+
query: "permission.admin has",
|
|
234
|
+
object: { identifier: 2 },
|
|
235
|
+
parameters: [{ type: "context", context: "Signer" }],
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
},
|
|
241
|
+
applicable_industries: ["ecommerce", "rental", "insurance", "travel", "subscription"],
|
|
242
|
+
relevant_risks: ["R-C3-01", "R-C3-05", "R-C3-06", "R-C4-04"],
|
|
243
|
+
creation_notes: [
|
|
244
|
+
"DYNAMIC PERMISSION VERIFICATION (key pattern): caller submits a Permission address (identifier 2); Guard verifies query(1488: service.permission) == submitted permission, then checks 1002/1004 against the submitted permission. This survives permission rotation — if the Service changes its permission, the Guard still works without rebuilding.",
|
|
245
|
+
"MIXED RETURN-TYPE CONSTRUCTION: query 1002 (permission.owner) returns Address → wrap in logic_equal; query 1004 (permission.admin has) returns Bool → use directly as logic_or child with parameters: [context(Signer)].",
|
|
246
|
+
"logic_or wrapping of the Signer check suppresses R-C4-04 (Level 1 strict binding convenience warning).",
|
|
247
|
+
"THREE conditions in logic_and: (1) order.service binding (R-C3-05), (2) dynamic permission verification, (3) identity set (owner OR admin).",
|
|
248
|
+
"Static permission alternative (simpler but breaks on rotation): use a table constant for the permission address instead of b_submission=true + 1488 verification.",
|
|
249
|
+
"Repository-based address set (most flexible, most complex): store the permission address set in a Repository and query dynamically — only for extreme flexibility needs.",
|
|
250
|
+
],
|
|
251
|
+
example_use_case: "Merchant allocation: the Service may rotate its permission (like a company changing its board). " +
|
|
252
|
+
"The caller submits the current permission address; the Guard verifies it matches service.permission (1488), " +
|
|
253
|
+
"then checks that Signer is the permission owner or has admin rights.",
|
|
254
|
+
verifier_constraint_level: "level2_identity_set",
|
|
58
255
|
},
|
|
59
256
|
{
|
|
60
257
|
id: "tpl_forward_node_check",
|
|
@@ -75,8 +272,8 @@ export const GUARD_TEMPLATES = [
|
|
|
75
272
|
example_root: {
|
|
76
273
|
type: "logic_equal",
|
|
77
274
|
left: {
|
|
78
|
-
type: "query", query: "progress.
|
|
79
|
-
object: { identifier: 0, convert_witness:
|
|
275
|
+
type: "query", query: "progress.current",
|
|
276
|
+
object: { identifier: 0, convert_witness: "OrderProgress" },
|
|
80
277
|
parameters: [],
|
|
81
278
|
},
|
|
82
279
|
right: { type: "identifier", identifier: 1 },
|
|
@@ -89,6 +286,79 @@ export const GUARD_TEMPLATES = [
|
|
|
89
286
|
"Node names are case-sensitive; query returns a String type",
|
|
90
287
|
],
|
|
91
288
|
example_use_case: "Camera equipment rental flow: the user must be at the 'pending return' node to perform the return operation.",
|
|
289
|
+
verifier_constraint_level: "level3_scene_combined",
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
id: "tpl_forward_privacy_delivery_proof",
|
|
293
|
+
scene_id: "machine_forward_guard",
|
|
294
|
+
name: "Privacy-delivery Proof verification (strict mode, Messenger → on-chain Proof)",
|
|
295
|
+
description: "Strict-mode guard for 'privacy information delivered via Messenger but not suitable for on-chain publication' " +
|
|
296
|
+
"(e.g. shipping details, return addresses, private credentials). The verifier submits BOTH a Proof object address " +
|
|
297
|
+
"(generated by messenger.submitChainProof) AND the Order object address. Three conditions verify: " +
|
|
298
|
+
"(1) Signer == proof.signer (submitter accountability — 'whoever benefits bears the burden of proof'), " +
|
|
299
|
+
"(2) proof.time > order.time (proof created after the order — freshness, prevents stale-proof replay), " +
|
|
300
|
+
"(3) order.service == service (project binding, suppresses R-C3-05 cross-project bypass). " +
|
|
301
|
+
"No content verification — only submission responsibility. The counterparty can dispute by checking their own " +
|
|
302
|
+
"Messenger conversation. Broad-mode alternative (verify Merkle Root string length == 66 via P15) is documented " +
|
|
303
|
+
"in creation_notes — broad mode trusts the submitter's honesty and is suitable when the Guard is mainly an " +
|
|
304
|
+
"arbitration basis rather than a fund-flow gate.",
|
|
305
|
+
recommended_patterns: ["P10", "P15"],
|
|
306
|
+
parameters: [
|
|
307
|
+
{ name: "service_name", type: "string", description: "Service object name (circular ref via P16 — resolved after Service publish)", required: true,
|
|
308
|
+
constraint: "Must be a name, not an address (the Service is not yet published when the Guard is created)" },
|
|
309
|
+
],
|
|
310
|
+
example_table: [
|
|
311
|
+
{ identifier: 0, b_submission: true, value_type: "Address", object_type: "Proof",
|
|
312
|
+
name: "proof_object (Proof address generated by messenger.submitChainProof, submitted by verifier at runtime)",
|
|
313
|
+
binding_constraint: "Must be a Proof object created AFTER the order; signer must equal the transaction Signer" },
|
|
314
|
+
{ identifier: 1, b_submission: true, value_type: "Address", object_type: "Order",
|
|
315
|
+
name: "order_object (Order address submitted by verifier at runtime)",
|
|
316
|
+
binding_constraint: "Must belong to the service declared in identifier 2 (order.service == service)" },
|
|
317
|
+
{ identifier: 2, b_submission: false, value_type: "Address", value: "${service_name}",
|
|
318
|
+
name: "Service object (project binding, circular ref via name)" },
|
|
319
|
+
],
|
|
320
|
+
example_root: {
|
|
321
|
+
type: "logic_and",
|
|
322
|
+
nodes: [
|
|
323
|
+
{
|
|
324
|
+
type: "logic_equal",
|
|
325
|
+
nodes: [
|
|
326
|
+
{ type: "context", context: "Signer" },
|
|
327
|
+
{ type: "query", query: "proof.signer", object: { identifier: 0 }, parameters: [] },
|
|
328
|
+
],
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
type: "logic_as_u256_greater",
|
|
332
|
+
nodes: [
|
|
333
|
+
{ type: "query", query: "proof.time", object: { identifier: 0 }, parameters: [] },
|
|
334
|
+
{ type: "query", query: "order.time", object: { identifier: 1 }, parameters: [] },
|
|
335
|
+
],
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
type: "logic_equal",
|
|
339
|
+
nodes: [
|
|
340
|
+
{ type: "query", query: "order.service", object: { identifier: 1 }, parameters: [] },
|
|
341
|
+
{ type: "identifier", identifier: 2 },
|
|
342
|
+
],
|
|
343
|
+
},
|
|
344
|
+
],
|
|
345
|
+
},
|
|
346
|
+
applicable_industries: ["ecommerce", "logistics", "service", "privacy delivery"],
|
|
347
|
+
relevant_risks: ["R-C3-01", "R-C3-05", "R-X1-12"],
|
|
348
|
+
creation_notes: [
|
|
349
|
+
"STRICT MODE (this template): verifier submits Proof + Order addresses. Three conditions: Signer==proof.signer (submitter accountability), proof.time>order.time (freshness), order.service==service (project binding). No content verification — only submission responsibility ('谁得利谁举证' principle).",
|
|
350
|
+
"BROAD MODE ALTERNATIVE: use P15 retained_submission with a String submission (the Merkle Root) and verify calc_string_length == 66 (0x prefix + 64 hex chars). Broad mode trusts the submitter's honesty; the counterparty can dispute by checking their own Messenger conversation. Broad mode is suitable when the Guard is mainly an arbitration basis, not a fund-flow gate.",
|
|
351
|
+
"Guard table supports MULTIPLE b_submission=true Address identifiers (no submission count limit) — this template uses two: Proof (identifier 0) and Order (identifier 1).",
|
|
352
|
+
"submitChainProof(env, peerAddress, description?) sets Proof.about = peerAddress (the counterparty's address). Pass the order_id as a string in the description parameter to associate the Proof with an order (e.g. description: 'order:0x123...').",
|
|
353
|
+
"Query IDs (all zero-parameter): proof.signer=1958, proof.time=1960 (invariant clock_derived, always >0), order.time=1574, order.service=1563.",
|
|
354
|
+
"Forward.guard is immutable after Machine publish — choose broad vs strict before publishing.",
|
|
355
|
+
"The same strict Guard can be reused across ALL Machine forwards that need merkle-root verification (shipping, lost, returns, etc.) — the verifier just submits the relevant Proof + Order each time.",
|
|
356
|
+
"Condition (1) Signer==proof.signer suppresses R-C3-01 (submission not bound to Signer). Condition (3) order.service==service suppresses R-C3-05 (cross-project submission bypass).",
|
|
357
|
+
],
|
|
358
|
+
example_use_case: "MyShop e-commerce: after delivering shipping details / return addresses via Messenger (privacy info not suitable for on-chain publication), " +
|
|
359
|
+
"the provider generates a Proof via submitChainProof and submits it with the Order address to advance the Machine forward. " +
|
|
360
|
+
"The Guard verifies the submitter is the Proof's signer, the Proof was created after the order, and the order belongs to this service.",
|
|
361
|
+
verifier_constraint_level: "level3_scene_combined",
|
|
92
362
|
},
|
|
93
363
|
{
|
|
94
364
|
id: "tpl_submission_signer_binding",
|
|
@@ -126,6 +396,7 @@ export const GUARD_TEMPLATES = [
|
|
|
126
396
|
"Providing a binding_constraint field describing value rules is recommended (R-X1-12)",
|
|
127
397
|
],
|
|
128
398
|
example_use_case: "On equipment return, the user submits the 'return' operation; the Guard verifies that the submitter is the service provider and that the operation type is correct.",
|
|
399
|
+
verifier_constraint_level: "level1_strict",
|
|
129
400
|
},
|
|
130
401
|
{
|
|
131
402
|
id: "tpl_reward_one_time_claim",
|
|
@@ -160,6 +431,7 @@ export const GUARD_TEMPLATES = [
|
|
|
160
431
|
"Reward guard is iterable; duplicate-claim protection requires rebuilding the Guard to update the Repository address",
|
|
161
432
|
],
|
|
162
433
|
example_use_case: "New-user first-order reward: query the user's historical order count via Repository; allow claim only when record_count==0.",
|
|
434
|
+
verifier_constraint_level: "level3_scene_combined",
|
|
163
435
|
},
|
|
164
436
|
{
|
|
165
437
|
id: "tpl_write_guard_type_check",
|
|
@@ -201,6 +473,7 @@ export const GUARD_TEMPLATES = [
|
|
|
201
473
|
"EntityRegistrar (0xaab) and EntityLinker (0xaaa) are fixed system addresses",
|
|
202
474
|
],
|
|
203
475
|
example_use_case: "E-commerce platform merchant writes product review data; the Guard verifies that the writer is a registered Entity and not a system address.",
|
|
476
|
+
verifier_constraint_level: "level1_strict",
|
|
204
477
|
},
|
|
205
478
|
{
|
|
206
479
|
id: "tpl_usage_guard_threshold",
|
|
@@ -231,6 +504,7 @@ export const GUARD_TEMPLATES = [
|
|
|
231
504
|
"When Arbitration bPaused=true, blocking takes priority (checked before Guard)",
|
|
232
505
|
],
|
|
233
506
|
example_use_case: "Rental service dispute: only disputes with order amount ≥ 10 WOW are accepted, filtering out small-amount conflicts.",
|
|
507
|
+
verifier_constraint_level: "level3_scene_combined",
|
|
234
508
|
},
|
|
235
509
|
{
|
|
236
510
|
id: "tpl_voting_guard_numeric_weight",
|
|
@@ -261,6 +535,7 @@ export const GUARD_TEMPLATES = [
|
|
|
261
535
|
"Deriving weights from the Arb object via witness is recommended, rather than submitting them directly",
|
|
262
536
|
],
|
|
263
537
|
example_use_case: "3-person arbitration panel: chief arbitrator weight 3, regular arbitrators weight 1, majority vote decision.",
|
|
538
|
+
verifier_constraint_level: "level2_identity_set",
|
|
264
539
|
},
|
|
265
540
|
{
|
|
266
541
|
id: "tpl_gen_passport_identity",
|
|
@@ -291,6 +566,7 @@ export const GUARD_TEMPLATES = [
|
|
|
291
566
|
"The generated Passport can be used as submission data for subsequent operations",
|
|
292
567
|
],
|
|
293
568
|
example_use_case: "After the user passes identity verification, a Passport is generated; this Passport is then submitted as an identity credential in subsequent service purchases.",
|
|
569
|
+
verifier_constraint_level: "level1_strict",
|
|
294
570
|
},
|
|
295
571
|
];
|
|
296
572
|
export function getTemplatesByScene(sceneId) {
|
package/dist/project/graph.d.ts
CHANGED
package/dist/project/graph.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
function matchesProjectFilter(nodeProject, filter) {
|
|
2
|
+
if (nodeProject === filter)
|
|
3
|
+
return true;
|
|
4
|
+
if (!filter.includes("_v")) {
|
|
5
|
+
const m = nodeProject.match(/^(.+)_v\d+$/);
|
|
6
|
+
if (m && m[1] === filter)
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
1
11
|
export class ProjectGraph {
|
|
2
12
|
nodes = new Map();
|
|
3
13
|
edges = [];
|
|
@@ -8,12 +18,17 @@ export class ProjectGraph {
|
|
|
8
18
|
upsertNode(node) {
|
|
9
19
|
const existing = this.nodes.get(node.id);
|
|
10
20
|
if (existing) {
|
|
21
|
+
const mergedProjects = new Set([
|
|
22
|
+
...(existing.projects ?? []),
|
|
23
|
+
...(node.projects ?? []),
|
|
24
|
+
]);
|
|
11
25
|
this.nodes.set(node.id, {
|
|
12
26
|
...existing,
|
|
13
27
|
...node,
|
|
14
28
|
project: node.project ?? existing.project,
|
|
15
29
|
type: node.type ?? existing.type,
|
|
16
30
|
address: node.address ?? existing.address,
|
|
31
|
+
projects: mergedProjects.size > 0 ? Array.from(mergedProjects) : (existing.projects ?? node.projects),
|
|
17
32
|
});
|
|
18
33
|
return this.nodes.get(node.id);
|
|
19
34
|
}
|
|
@@ -79,7 +94,18 @@ export class ProjectGraph {
|
|
|
79
94
|
const all = Array.from(this.nodes.values());
|
|
80
95
|
if (!projectPrefix)
|
|
81
96
|
return all;
|
|
82
|
-
return all.filter((n) =>
|
|
97
|
+
return all.filter((n) => {
|
|
98
|
+
if (n.projects && n.projects.length > 0) {
|
|
99
|
+
return n.projects.some((p) => matchesProjectFilter(p, projectPrefix));
|
|
100
|
+
}
|
|
101
|
+
if (!n.project)
|
|
102
|
+
return false;
|
|
103
|
+
if (n.project === projectPrefix)
|
|
104
|
+
return true;
|
|
105
|
+
if (projectPrefix.startsWith(n.project + "_v"))
|
|
106
|
+
return true;
|
|
107
|
+
return false;
|
|
108
|
+
});
|
|
83
109
|
}
|
|
84
110
|
getDependencies(id) {
|
|
85
111
|
const idxs = this.outEdges.get(id);
|
package/dist/project/index.d.ts
CHANGED
package/dist/project/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { normalizeForProject, extractProjectPrefix, TAG_PREFIX, } from "./namespace.js";
|
|
1
|
+
import { normalizeForProject, extractProjectPrefix, extractAllProjectVersions, TAG_PREFIX, } from "./namespace.js";
|
|
2
2
|
import { ProjectGraph, extractReferences, nodeIdOf, } from "./graph.js";
|
|
3
3
|
import { listProjects, listProjectObjects, listShareableObjects, traceDependencies, traceReferencedBy, prePublishCheck, findCrossProjectReferences, } from "./query.js";
|
|
4
4
|
import { isEnabled as isRuntimeEnabled } from "../config/index.js";
|
|
5
|
+
import { LocalMark } from "@wowok/wowok";
|
|
5
6
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
6
7
|
import { dirname, join } from "path";
|
|
7
8
|
import { homedir } from "os";
|
|
@@ -11,6 +12,33 @@ export * from "./query.js";
|
|
|
11
12
|
export function isProjectServiceEnabled() {
|
|
12
13
|
return isRuntimeEnabled("project_service");
|
|
13
14
|
}
|
|
15
|
+
function scheduleHiddenStep(sourceNodeId, sourceTags, references) {
|
|
16
|
+
const versionedTags = extractAllProjectVersions(sourceTags)
|
|
17
|
+
.filter((p) => p.version !== undefined)
|
|
18
|
+
.map((p) => `${TAG_PREFIX.project}${p.prefix}_${p.version}`);
|
|
19
|
+
if (versionedTags.length === 0 || references.length === 0)
|
|
20
|
+
return;
|
|
21
|
+
const run = async () => {
|
|
22
|
+
const localMark = LocalMark.Instance();
|
|
23
|
+
for (const ref of references) {
|
|
24
|
+
try {
|
|
25
|
+
await localMark.add_tags(ref.target, versionedTags);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
if (typeof setImmediate === "function") {
|
|
32
|
+
setImmediate(() => {
|
|
33
|
+
run().catch(() => { });
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
Promise.resolve().then(() => {
|
|
38
|
+
run().catch(() => { });
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
14
42
|
let GRAPH_INSTANCE = null;
|
|
15
43
|
let GRAPH_HYDRATED = false;
|
|
16
44
|
function isAutoHydrateEnabled() {
|
|
@@ -63,12 +91,21 @@ export function observe(operation_type, data, result) {
|
|
|
63
91
|
const project = extractProjectPrefix(tags);
|
|
64
92
|
const typeTag = tags?.find((t) => t.startsWith(TAG_PREFIX.type));
|
|
65
93
|
const type = typeTag?.slice(TAG_PREFIX.type.length);
|
|
66
|
-
const
|
|
94
|
+
const projectEntries = extractAllProjectVersions(tags);
|
|
95
|
+
const projects = projectEntries.map((p) => p.version ? `${p.prefix}_${p.version}` : p.prefix);
|
|
96
|
+
const node = {
|
|
97
|
+
id: nodeId,
|
|
98
|
+
project,
|
|
99
|
+
projects: projects.length > 0 ? projects : undefined,
|
|
100
|
+
type,
|
|
101
|
+
address,
|
|
102
|
+
};
|
|
67
103
|
graph.upsertNode(node);
|
|
68
104
|
const refs = extractReferences(operation_type, data);
|
|
69
105
|
for (const r of refs) {
|
|
70
106
|
graph.addEdge(nodeId, r.target, r.kind);
|
|
71
107
|
}
|
|
108
|
+
scheduleHiddenStep(nodeId, tags, refs);
|
|
72
109
|
if (isRuntimeEnabled("graph_persist")) {
|
|
73
110
|
try {
|
|
74
111
|
saveGraph();
|
|
@@ -39,6 +39,16 @@ export interface TagInjectionOptions {
|
|
|
39
39
|
existingTags?: string[];
|
|
40
40
|
}
|
|
41
41
|
export declare function buildProjectTags(opts: TagInjectionOptions): string[];
|
|
42
|
+
export declare function parseProjectTagValue(value: string): {
|
|
43
|
+
prefix: string;
|
|
44
|
+
version?: string;
|
|
45
|
+
};
|
|
46
|
+
export interface ProjectTagEntry {
|
|
47
|
+
prefix: string;
|
|
48
|
+
version?: string;
|
|
49
|
+
raw: string;
|
|
50
|
+
}
|
|
51
|
+
export declare function extractAllProjectVersions(tags: string[] | undefined): ProjectTagEntry[];
|
|
42
52
|
export declare function extractProjectPrefix(tags: string[] | undefined): string | undefined;
|
|
43
53
|
export interface NormalizeResult {
|
|
44
54
|
data: any;
|
|
@@ -59,4 +69,4 @@ export interface NormalizeInput {
|
|
|
59
69
|
shareable?: boolean;
|
|
60
70
|
}
|
|
61
71
|
export declare function normalizeForProject(input: NormalizeInput): NormalizeResult;
|
|
62
|
-
export declare const NAMESPACE_VERSION =
|
|
72
|
+
export declare const NAMESPACE_VERSION = 2;
|
|
@@ -101,6 +101,9 @@ export function buildProjectTags(opts) {
|
|
|
101
101
|
const tags = new Set(opts.existingTags ?? []);
|
|
102
102
|
if (opts.projectPrefix) {
|
|
103
103
|
tags.add(`${TAG_PREFIX.project}${opts.projectPrefix}`);
|
|
104
|
+
if (opts.version) {
|
|
105
|
+
tags.add(`${TAG_PREFIX.project}${opts.projectPrefix}_${opts.version}`);
|
|
106
|
+
}
|
|
104
107
|
}
|
|
105
108
|
if (opts.type) {
|
|
106
109
|
tags.add(`${TAG_PREFIX.type}${opts.type}`);
|
|
@@ -119,12 +122,34 @@ export function buildProjectTags(opts) {
|
|
|
119
122
|
}
|
|
120
123
|
return Array.from(tags);
|
|
121
124
|
}
|
|
125
|
+
export function parseProjectTagValue(value) {
|
|
126
|
+
const m = value.match(/^(.+?)_(v\d+)$/);
|
|
127
|
+
if (m) {
|
|
128
|
+
return { prefix: m[1], version: m[2] };
|
|
129
|
+
}
|
|
130
|
+
return { prefix: value };
|
|
131
|
+
}
|
|
132
|
+
export function extractAllProjectVersions(tags) {
|
|
133
|
+
if (!tags)
|
|
134
|
+
return [];
|
|
135
|
+
const result = [];
|
|
136
|
+
for (const t of tags) {
|
|
137
|
+
if (!t.startsWith(TAG_PREFIX.project))
|
|
138
|
+
continue;
|
|
139
|
+
const value = t.slice(TAG_PREFIX.project.length);
|
|
140
|
+
const parsed = parseProjectTagValue(value);
|
|
141
|
+
result.push({ ...parsed, raw: t });
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
122
145
|
export function extractProjectPrefix(tags) {
|
|
123
146
|
if (!tags)
|
|
124
147
|
return undefined;
|
|
125
148
|
for (const t of tags) {
|
|
126
149
|
if (t.startsWith(TAG_PREFIX.project)) {
|
|
127
|
-
|
|
150
|
+
const value = t.slice(TAG_PREFIX.project.length);
|
|
151
|
+
const parsed = parseProjectTagValue(value);
|
|
152
|
+
return parsed.prefix;
|
|
128
153
|
}
|
|
129
154
|
}
|
|
130
155
|
return undefined;
|
|
@@ -178,4 +203,4 @@ export function normalizeForProject(input) {
|
|
|
178
203
|
project: { prefix, type: inferredType, version },
|
|
179
204
|
};
|
|
180
205
|
}
|
|
181
|
-
export const NAMESPACE_VERSION =
|
|
206
|
+
export const NAMESPACE_VERSION = 2;
|
package/dist/project/query.d.ts
CHANGED
|
@@ -3,10 +3,12 @@ export interface ProjectInfo {
|
|
|
3
3
|
prefix: string;
|
|
4
4
|
objectCount: number;
|
|
5
5
|
types: string[];
|
|
6
|
+
versions?: string[];
|
|
6
7
|
objects: Array<{
|
|
7
8
|
name?: string;
|
|
8
9
|
address?: string;
|
|
9
10
|
type?: string;
|
|
11
|
+
version?: string;
|
|
10
12
|
}>;
|
|
11
13
|
}
|
|
12
14
|
export interface DependencyTrace {
|