@wowok/agent-mcp 3.2.2 → 3.2.4
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/chain-semantics/field-capability.d.ts +11 -0
- package/dist/chain-semantics/field-capability.js +1 -0
- package/dist/chain-semantics/freeze-map.d.ts +11 -0
- package/dist/chain-semantics/freeze-map.js +1 -0
- package/dist/chain-semantics/fund-flow.d.ts +10 -0
- package/dist/chain-semantics/fund-flow.js +1 -0
- package/dist/chain-semantics/guard-verbs.d.ts +22 -0
- package/dist/chain-semantics/guard-verbs.js +1 -0
- package/dist/chain-semantics/index.d.ts +10 -0
- package/dist/chain-semantics/index.js +1 -0
- package/dist/chain-semantics/object-graph.d.ts +18 -0
- package/dist/chain-semantics/object-graph.js +1 -0
- package/dist/communication/proof-reuse.d.ts +9 -0
- package/dist/communication/proof-reuse.js +1 -0
- package/dist/composition/audit.d.ts +10 -0
- package/dist/composition/audit.js +1 -0
- package/dist/composition/compile.d.ts +38 -0
- package/dist/composition/compile.js +1 -0
- package/dist/composition/materialize.d.ts +64 -0
- package/dist/composition/materialize.js +1 -0
- package/dist/composition/plan.d.ts +92 -0
- package/dist/composition/plan.js +1 -0
- package/dist/composition/reflux.d.ts +28 -0
- package/dist/composition/reflux.js +1 -0
- package/dist/evaluation/builtins/graph-service.spec.js +1 -1
- package/dist/evaluation/engine.js +1 -1
- package/dist/experience/realtime-feedback.js +1 -1
- package/dist/extensions/business-modules.js +1 -1
- package/dist/extensions/industry-pack.js +1 -1
- package/dist/extensions/modes.js +1 -1
- package/dist/graph/onchain/expand.js +1 -1
- package/dist/graph/onchain/exposure.js +1 -1
- package/dist/graph/onchain/facts.js +1 -1
- package/dist/harness/recover.js +1 -1
- package/dist/keeper/detectors.d.ts +7 -0
- package/dist/keeper/detectors.js +1 -1
- package/dist/keeper/types.d.ts +1 -1
- package/dist/keeper/types.js +1 -1
- package/dist/knowledge/allocation-ledger.js +1 -1
- package/dist/knowledge/allocation-puzzle.js +1 -1
- package/dist/knowledge/allocation-risk.js +1 -1
- package/dist/knowledge/allocation-templates.js +1 -1
- package/dist/knowledge/arb-fund-facts.d.ts +31 -0
- package/dist/knowledge/arb-fund-facts.js +1 -0
- package/dist/knowledge/baselines/rules/allocation.json +44 -15
- package/dist/knowledge/baselines/rules/guard.json +27 -8
- package/dist/knowledge/baselines/rules/plan.json +161 -0
- package/dist/knowledge/baselines/semantic-facts.d.ts +12 -0
- package/dist/knowledge/baselines/semantic-facts.js +1 -0
- package/dist/knowledge/builtin-templates.d.ts +1 -1
- package/dist/knowledge/builtin-templates.js +1 -1
- package/dist/knowledge/getting-started.js +1 -1
- package/dist/knowledge/guard-bindings.js +1 -1
- package/dist/knowledge/guard-design-patterns.d.ts +1 -1
- package/dist/knowledge/guard-design-patterns.js +1 -1
- package/dist/knowledge/guard-ledger.js +1 -1
- package/dist/knowledge/guard-risk.js +1 -1
- package/dist/knowledge/guard-templates.js +1 -1
- package/dist/knowledge/index.js +1 -1
- package/dist/knowledge/industry-registry.js +1 -1
- package/dist/knowledge/jsonrpc-enum.js +1 -1
- package/dist/knowledge/machine-ledger.js +1 -1
- package/dist/knowledge/machine-templates.js +1 -1
- package/dist/knowledge/onchain-constants.d.ts +2 -2
- package/dist/knowledge/onchain-constants.js +1 -1
- package/dist/knowledge/progress-ledger.js +1 -1
- package/dist/knowledge/scenario-modes.d.ts +13 -0
- package/dist/knowledge/service-allocation-semantics.js +1 -1
- package/dist/knowledge/service-ledger.js +1 -1
- package/dist/knowledge/service-templates.js +1 -1
- package/dist/knowledge/strategy-manuals.js +1 -1
- package/dist/knowledge/template-loader.d.ts +17 -1
- package/dist/knowledge/template-loader.js +1 -1
- package/dist/knowledge/template-registry.js +1 -1
- package/dist/knowledge/template-scanner.js +1 -1
- package/dist/knowledge/tools-reference.js +1 -1
- package/dist/knowledge/workflow-guidance.js +1 -1
- package/dist/monitor/MonitorLoop.js +1 -1
- package/dist/participation/radar-core.d.ts +6 -0
- package/dist/participation/radar-core.js +1 -1
- package/dist/playbooks/service-build/business-puzzle.js +1 -1
- package/dist/playbooks/service-build/machine-panorama.js +1 -1
- package/dist/playbooks/service-build/merchant-guide.js +1 -1
- package/dist/playbooks/service-build/migration-planner.js +1 -1
- package/dist/playbooks/service-build/object-panorama.js +1 -1
- package/dist/playbooks/service-build/participation-radar.js +1 -1
- package/dist/playbooks/service-build/relationship-profile.js +1 -1
- package/dist/playbooks/service-build/service-panorama.js +1 -1
- package/dist/playbooks/service-build/service-quote.js +1 -1
- package/dist/playbooks/service-build/service-quote.spec.d.ts +1 -0
- package/dist/playbooks/service-build/service-quote.spec.js +1 -0
- package/dist/review/index.js +1 -1
- package/dist/safety/confirm-gate.js +1 -1
- package/dist/schema/call/arbitration.js +1 -1
- package/dist/schema/call/base.d.ts +4 -0
- package/dist/schema/call/base.js +1 -1
- package/dist/schema/call/bridge.d.ts +1 -0
- package/dist/schema/call/error-codes.d.ts +1 -1
- package/dist/schema/call/error-codes.js +1 -1
- package/dist/schema/call/machine.js +1 -1
- package/dist/schema/call/order.d.ts +60 -0
- package/dist/schema/call/order.js +1 -1
- package/dist/schema/call/semantic.js +1 -1
- package/dist/schema/call/service.d.ts +56 -0
- package/dist/schema/call/service.js +1 -1
- package/dist/schema/common/index.js +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.js +1 -1
- package/dist/schema/industry-pack/index.d.ts +2 -0
- package/dist/schema/industry-pack/index.js +1 -1
- package/dist/schema/interaction/index.d.ts +1 -1
- package/dist/schema/local/index.d.ts +10 -0
- package/dist/schema/local/index.js +1 -1
- package/dist/schema/operations.d.ts +48 -0
- package/dist/schema/query/bi.d.ts +26 -0
- package/dist/schema/query/bi.js +1 -1
- package/dist/schema/query/index.js +1 -1
- package/dist/schema/schema-version.js +1 -1
- package/dist/schema/service-clone/index.d.ts +46 -0
- package/dist/schema/service-clone/index.js +1 -0
- package/dist/schema-query-impl/index.js +1 -1
- package/dist/schemas/account_operation.output.json +1 -0
- package/dist/schemas/bridge_operation.output.json +1 -0
- package/dist/schemas/index.json +7 -1
- package/dist/schemas/industry_pack_operation.output.json +4 -0
- package/dist/schemas/industry_pack_operation.schema.json +4 -0
- package/dist/schemas/local_cache_operation.output.json +1 -0
- package/dist/schemas/local_history_operation.output.json +1 -0
- package/dist/schemas/local_info_operation.output.json +1 -0
- package/dist/schemas/local_mark_operation.output.json +1 -0
- package/dist/schemas/onchain_operations.output.json +2 -1
- package/dist/schemas/onchain_operations.schema.json +408 -97
- package/dist/schemas/onchain_operations_allocation.schema.json +5 -5
- package/dist/schemas/onchain_operations_arbitration.schema.json +3 -3
- package/dist/schemas/onchain_operations_contact.schema.json +1 -1
- package/dist/schemas/onchain_operations_demand.schema.json +3 -3
- package/dist/schemas/onchain_operations_gen_passport.schema.json +1 -1
- package/dist/schemas/onchain_operations_guard.schema.json +59 -59
- package/dist/schemas/onchain_operations_machine.schema.json +2 -2
- package/dist/schemas/onchain_operations_order.schema.json +133 -1
- package/dist/schemas/onchain_operations_progress.schema.json +1 -1
- package/dist/schemas/onchain_operations_proof.schema.json +1 -1
- package/dist/schemas/onchain_operations_repository.schema.json +1 -1
- package/dist/schemas/onchain_operations_reward.schema.json +4 -4
- package/dist/schemas/onchain_operations_service.schema.json +187 -8
- package/dist/schemas/onchain_operations_treasury.schema.json +7 -7
- package/dist/schemas/query_toolkit.output.json +136 -52
- package/dist/schemas/service_clone_operation.output.json +168 -0
- package/dist/schemas/service_clone_operation.schema.json +49 -0
- package/dist/schemas/workflow_operation.schema.json +1 -1
- package/dist/tools/handlers/config.js +1 -1
- package/dist/tools/handlers/industry-pack.js +1 -1
- package/dist/tools/handlers/messenger.js +1 -1
- package/dist/tools/handlers/onchain.js +1 -1
- package/dist/tools/handlers/query.js +1 -1
- package/dist/tools/handlers/service-clone.d.ts +2 -0
- package/dist/tools/handlers/service-clone.js +1 -0
- package/dist/tools/index.js +1 -1
- package/dist/tools/move-fn-index.gen.js +1 -1
- package/dist/tools/registry/business.js +1 -1
- package/dist/tools/wrap.d.ts +6 -1
- package/dist/tools/wrap.js +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"comment": "Guard rule pack (R-C/R-X) — declarative form of the retired in-code Guard risk rules (the guard condition-tree lint pack:
|
|
2
|
+
"comment": "Guard rule pack (R-C/R-X) — declarative form of the retired in-code Guard risk rules (the guard condition-tree lint pack: 35 rules over the serialized root, table classification and the scene ledger). Facts are produced by the kernel extractor (guard-risk.ts, bound to the GUARDQUERY invariant catalog, the witness chain table, the certain-outcome folder and the per-scene reentrancy specs); rules only reference fact names. Levels/wording can be retuned per rule and rules can be disabled (enabled=false, trace left) via the judgment document — factory rules can never be deleted or invented here.",
|
|
3
3
|
"facts": {
|
|
4
4
|
"has_signer_check": "KERNEL — the serialized root contains a context(Signer) check.",
|
|
5
5
|
"has_clock_check": "KERNEL — the serialized root contains a context(Clock) node.",
|
|
@@ -96,7 +96,9 @@
|
|
|
96
96
|
"tree_folds_always_false_reason": "KERNEL — the decisive always-false pattern rendered for the evidence line.",
|
|
97
97
|
"write_guard_scene": "KERNEL — the Guard is bound as a Repository policy write_guard (scene binding_field=write_guard / id repository_write_guard).",
|
|
98
98
|
"write_guard_no_identity_check": "KERNEL — write_guard scene AND no context(Signer) leaf anywhere in the root: the gate binds a STATE, never the WRITER, so any caller satisfying it may write or overwrite any row.",
|
|
99
|
-
"write_guard_open": "KERNEL — write_guard scene AND (the tree folds true OR it binds no caller identity): the Repository write is effectively unauthenticated even though the policy has a guard."
|
|
99
|
+
"write_guard_open": "KERNEL — write_guard scene AND (the tree folds true OR it binds no caller identity): the Repository write is effectively unauthenticated even though the policy has a guard.",
|
|
100
|
+
"bare_bool_query_count": "KERNEL — number of DISTINCT query nodes sitting directly under logic_and/logic_or (bare Bool clause position; absent when zero).",
|
|
101
|
+
"bare_bool_query_csv_sp": "KERNEL — those bare-clause queries rendered '#<id>' or by name, comma-space joined."
|
|
100
102
|
},
|
|
101
103
|
"rules": [
|
|
102
104
|
{
|
|
@@ -163,6 +165,23 @@
|
|
|
163
165
|
}
|
|
164
166
|
]
|
|
165
167
|
},
|
|
168
|
+
{
|
|
169
|
+
"rule_id": "R-X1-18",
|
|
170
|
+
"dimension": "logic_gap",
|
|
171
|
+
"trigger": "A query node sits directly under logic_and/logic_or — a bare Bool clause asserting the POSITIVE state of whatever it reads (OFN mainnet #P-01)",
|
|
172
|
+
"cases": [
|
|
173
|
+
{
|
|
174
|
+
"when": { "field": "bare_bool_query_count", "op": "present" },
|
|
175
|
+
"level": "medium",
|
|
176
|
+
"title": "Bare Bool query clause (${bare_bool_query_csv_sp}) asserts the POSITIVE state — polarity unchecked",
|
|
177
|
+
"description": "A query placed directly under logic_and/logic_or must return Bool and asserts that the condition IS true ('is set / exists / claimed'). OFN mainnet #P-01: a refund guard used a bare order.claimed_by-some query (id 1570) — it reads 'already claimed', so it is FALSE on every fresh order; all five refund rails aborted (code 7), and order_allocators is immutable after publish (service.move asserts !bPublished), so the Service had to be rebuilt from scratch. When the intent is the NEGATIVE — the common refund/double-spend guard pattern ('not yet claimed', 'no allocation yet') — a bare clause expresses the exact opposite of what the author meant.",
|
|
178
|
+
"scenario": "Refund guard with a bare claimed_by query: every refund call aborts on a fresh order, and publish freezes the misconfiguration permanently",
|
|
179
|
+
"mitigation": "Wrap the query in logic_equal with an explicit Bool constant so the polarity is stated: logic_equal[query(order.claimed_by some), Bool false] for 'not yet claimed' (the refund pattern); logic_equal[query(...), Bool true] when the positive state is genuinely required. Re-run the Guard analyzer after the edit.",
|
|
180
|
+
"evidence": "Bare query clause(s) under logic_and/logic_or: ${bare_bool_query_csv_sp}",
|
|
181
|
+
"stakeholders": ["provider", "customer"]
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
},
|
|
166
185
|
{
|
|
167
186
|
"rule_id": "R-C1-01",
|
|
168
187
|
"dimension": "data_source_trust",
|
|
@@ -488,7 +507,7 @@
|
|
|
488
507
|
"title": "allocators Guard without Signer binding — ${rc3_06_title_suffix}",
|
|
489
508
|
"description": "Guard is bound to Service order_allocators but does NOT verify context(Signer). In the allocators scene, sharing.who determines the fund recipient:\n - sharing.who=Signer → funds flow to the CALLER (transaction signer)\n - sharing.who=Entity → funds flow to a FIXED address (Treasury/personal)\n - sharing.who=GuardIdentifier → funds flow to the submitted constrained object (e.g. an Order), receivable only by that object's owner (object receipt = owner receipt); see RC-FIND-03 residual in the recipient constraint audit\n\nWhen sharing.who=Signer and the Guard does not bind Signer, ANY caller who passes the Guard receives the order funds — a direct theft. Even an authorized caller is unnecessary: the attacker only needs to pass the Guard's condition (e.g. submit any completed order_id), then the funds go to their own address.\n\nThis is distinct from R-C3-01 (generic Signer binding) and R-C3-05 (cross-project bypass). R-C3-06 addresses the allocators-specific Guard+sharing coupling: the SAFE design uses sharing.who=Entity so the recipient is fixed, making Guard Signer binding unnecessary.\n\nsharing_recipients hint: ${rc3_06_recipients_label}",
|
|
490
509
|
"scenario": "Fund theft: attacker passes the allocators Guard (e.g. submits a completed order_id) and sharing.who=Signer routes 100% of the order funds to the attacker's address",
|
|
491
|
-
"mitigation": "TWO mitigation options:\n (A) Traditional: add context(Signer) binding to the Guard root (logic_equal[context(Signer), identifier[N](authorized_address)]) so only the authorized recipient can trigger allocation.\n (B) PREFERRED: use sharing.who=Entity (Treasury object or fixed personal address) in the Allocator's sharing config. Funds then always flow to the designated recipient regardless of who triggers allocation — the Guard does NOT need to bind Signer. This is more robust because it does not depend on Guard correctness.\n\nDesign checklist when using sharing.who=Entity:\n - If Entity points to a Treasury object, verify the Treasury's permission is consistent with the Service's permission (different permissions = different permission organizations = minor risk).\n - allocators require unique guard addresses: create separate Guard objects (identical root/table, different descriptions) for each allocator.\n -
|
|
510
|
+
"mitigation": "TWO mitigation options:\n (A) Traditional: add context(Signer) binding to the Guard root (logic_equal[context(Signer), identifier[N](authorized_address)]) so only the authorized recipient can trigger allocation.\n (B) PREFERRED: use sharing.who=Entity (Treasury object or fixed personal address) in the Allocator's sharing config. Funds then always flow to the designated recipient regardless of who triggers allocation — the Guard does NOT need to bind Signer. This is more robust because it does not depend on Guard correctness.\n\nDesign checklist when using sharing.who=Entity:\n - If Entity points to a Treasury object, verify the Treasury's permission is consistent with the Service's permission (different permissions = different permission organizations = minor risk).\n - allocators require unique guard addresses: create separate Guard objects (identical root/table, different descriptions) for each allocator.\n - Each allocator is bound to a DIFFERENT guard — the caller's submitted guard selects which path fires. Same-guard allocators fire sequentially on the same call (waterfall); different-guard allocators are alternative paths.\n - Still add order.service project binding (query 1563) to prevent cross-project bypass (R-C3-05) triggering premature allocation.",
|
|
492
511
|
"evidence": "Scene: service_order_allocators_guard. Guard binds Signer: no. sharing_recipients: ${rc3_06_recipients_label}. Level rationale: ${rc3_06_level_rationale}.",
|
|
493
512
|
"stakeholders": ["provider", "customer"],
|
|
494
513
|
"exposure": {
|
|
@@ -512,7 +531,7 @@
|
|
|
512
531
|
"title": "allocators Guard without Signer binding — ${rc3_06_title_suffix}",
|
|
513
532
|
"description": "Guard is bound to Service order_allocators but does NOT verify context(Signer). In the allocators scene, sharing.who determines the fund recipient:\n - sharing.who=Signer → funds flow to the CALLER (transaction signer)\n - sharing.who=Entity → funds flow to a FIXED address (Treasury/personal)\n - sharing.who=GuardIdentifier → funds flow to the submitted constrained object (e.g. an Order), receivable only by that object's owner (object receipt = owner receipt); see RC-FIND-03 residual in the recipient constraint audit\n\nWhen sharing.who=Signer and the Guard does not bind Signer, ANY caller who passes the Guard receives the order funds — a direct theft. Even an authorized caller is unnecessary: the attacker only needs to pass the Guard's condition (e.g. submit any completed order_id), then the funds go to their own address.\n\nThis is distinct from R-C3-01 (generic Signer binding) and R-C3-05 (cross-project bypass). R-C3-06 addresses the allocators-specific Guard+sharing coupling: the SAFE design uses sharing.who=Entity so the recipient is fixed, making Guard Signer binding unnecessary.\n\nsharing_recipients hint: ${rc3_06_recipients_label}",
|
|
514
533
|
"scenario": "Fund theft: attacker passes the allocators Guard (e.g. submits a completed order_id) and sharing.who=Signer routes 100% of the order funds to the attacker's address",
|
|
515
|
-
"mitigation": "TWO mitigation options:\n (A) Traditional: add context(Signer) binding to the Guard root (logic_equal[context(Signer), identifier[N](authorized_address)]) so only the authorized recipient can trigger allocation.\n (B) PREFERRED: use sharing.who=Entity (Treasury object or fixed personal address) in the Allocator's sharing config. Funds then always flow to the designated recipient regardless of who triggers allocation — the Guard does NOT need to bind Signer. This is more robust because it does not depend on Guard correctness.\n\nDesign checklist when using sharing.who=Entity:\n - If Entity points to a Treasury object, verify the Treasury's permission is consistent with the Service's permission (different permissions = different permission organizations = minor risk).\n - allocators require unique guard addresses: create separate Guard objects (identical root/table, different descriptions) for each allocator.\n -
|
|
534
|
+
"mitigation": "TWO mitigation options:\n (A) Traditional: add context(Signer) binding to the Guard root (logic_equal[context(Signer), identifier[N](authorized_address)]) so only the authorized recipient can trigger allocation.\n (B) PREFERRED: use sharing.who=Entity (Treasury object or fixed personal address) in the Allocator's sharing config. Funds then always flow to the designated recipient regardless of who triggers allocation — the Guard does NOT need to bind Signer. This is more robust because it does not depend on Guard correctness.\n\nDesign checklist when using sharing.who=Entity:\n - If Entity points to a Treasury object, verify the Treasury's permission is consistent with the Service's permission (different permissions = different permission organizations = minor risk).\n - allocators require unique guard addresses: create separate Guard objects (identical root/table, different descriptions) for each allocator.\n - Each allocator is bound to a DIFFERENT guard — the caller's submitted guard selects which path fires. Same-guard allocators fire sequentially on the same call (waterfall); different-guard allocators are alternative paths.\n - Still add order.service project binding (query 1563) to prevent cross-project bypass (R-C3-05) triggering premature allocation.",
|
|
516
535
|
"evidence": "Scene: service_order_allocators_guard. Guard binds Signer: no. sharing_recipients: ${rc3_06_recipients_label}. Level rationale: ${rc3_06_level_rationale}.",
|
|
517
536
|
"stakeholders": ["provider", "customer"]
|
|
518
537
|
}
|
|
@@ -668,10 +687,10 @@
|
|
|
668
687
|
{
|
|
669
688
|
"when": { "field": "scene_binding_field", "op": "eq", "value": "order_allocators" },
|
|
670
689
|
"level": "medium",
|
|
671
|
-
"title": "order_allocators
|
|
672
|
-
"description": "
|
|
673
|
-
"scenario": "Allocation
|
|
674
|
-
"mitigation": "1)
|
|
690
|
+
"title": "order_allocators multi-guard paths may cause unfair allocation",
|
|
691
|
+
"description": "A distribution call submits ONE guard; every allocator bound to that guard fires in vector order against the shrinking pool (allocation.move:366-368). If a single guard binds multiple allocators with overlapping conditions, the pool is split repeatedly and later allocators may receive less than intended or abort on insufficient balance. For alternative business paths (settle vs refund), use DIFFERENT guards so the caller's guard choice selects exactly one path.",
|
|
692
|
+
"scenario": "Allocation path overlap: multiple allocators bound to the same guard all fire, draining the pool in unexpected order",
|
|
693
|
+
"mitigation": "1) Bind each business path (settle/refund/damage) to its OWN Guard object; 2) Make guard conditions mutually exclusive via guard logic, not list order; 3) When a waterfall IS intended (fee first, then split remainder), keep the shared guard and verify the vector order matches the intended payout sequence",
|
|
675
694
|
"stakeholders": ["provider"]
|
|
676
695
|
}
|
|
677
696
|
]
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
{
|
|
2
|
+
"comment": "Plan-domain rules (L1 composition kernel). Facts are produced by composition/audit.ts planFacts() from a Plan AST. These six rules exist because each one names a verified mainnet failure class from wiki/test/10 (TRAILHAVEN): zero allocator rows passing silently, prose guard logic, dual-rail double-pay, path-dependent settlement windows, write-only enforcement, dropped guard/repository hosts.",
|
|
3
|
+
"facts": {
|
|
4
|
+
"has_service": "Plan creates a service object",
|
|
5
|
+
"has_machine": "Plan creates a machine object",
|
|
6
|
+
"has_repository": "Plan creates a repository object",
|
|
7
|
+
"allocator_row_count": "Total allocator rows across service create param and order_allocators configure steps",
|
|
8
|
+
"refund_row_count": "Allocator rows on the refund track",
|
|
9
|
+
"terminal_count": "Machine terminal nodes (never a non-entry prev_node)",
|
|
10
|
+
"terminal_nodes_display": "Comma-joined terminal node names",
|
|
11
|
+
"first_uncovered_terminal": "First terminal node no allocator guard accepts via progress.current equality (FUND-EXIT-01)",
|
|
12
|
+
"first_refund_guard_missing_claimed_by": "First refund-track guard step id whose queries never read order.claimed_by (DUAL-RAIL-01, A-3)",
|
|
13
|
+
"first_path_dependent_anchor": "First guard step id using a path-dependent time query (TIME-ANCHOR-01, E-10)",
|
|
14
|
+
"path_sensitive": "The anchored node is reachable by more than one path, so the anchor can shift",
|
|
15
|
+
"first_write_only_unenforced_field": "First write-only param set with no guard query covering it (WRITE-ONLY-01, A-1/A-10)",
|
|
16
|
+
"first_orphan_guard": "First guard step id never referenced by any host binding (HOST-GRAPH-01, B-2)",
|
|
17
|
+
"first_repo_query_without_repository": "First guard step id querying repository.* while the plan creates no repository (HOST-GRAPH-01, B-2)",
|
|
18
|
+
"pending_allocator_guard_count": "Unresolved guard designs bound to allocator rows (compile-time judgment surface; >0 downgrades FUND-EXIT-01 from critical to medium)",
|
|
19
|
+
"first_pending_fund_guard": "First unresolved guard design bound to an allocator row or machine edge (UNRESOLVED-GUARD-01) — publishing now ships that path UNGUARDED",
|
|
20
|
+
"first_pending_buy_guard": "First unresolved guard design bound to the service buy path (UNRESOLVED-GUARD-01 warning tier)"
|
|
21
|
+
},
|
|
22
|
+
"rules": [
|
|
23
|
+
{
|
|
24
|
+
"rule_id": "PLAN-ALLOC-01",
|
|
25
|
+
"dimension": "fund_flow",
|
|
26
|
+
"trigger": "Service plan materializes zero allocator rows — the TRAILHAVEN failure: migration_apply emitted plan_allocation: [] with no critical, and the shop could neither settle nor refund.",
|
|
27
|
+
"cases": [
|
|
28
|
+
{
|
|
29
|
+
"when": { "all": [ { "field": "has_service", "op": "truthy" }, { "field": "allocator_row_count", "op": "eq", "value": 0 } ] },
|
|
30
|
+
"level": "critical",
|
|
31
|
+
"title": "Service plan has no allocator rows",
|
|
32
|
+
"description": "The plan creates a service but materializes zero allocator rows. On chain, publish aborts with E_NO_ALLOCATOR; worse, a plan that reaches materialization without rows means the shop cannot settle or refund anything.",
|
|
33
|
+
"mitigation": "Add at least one settlement-track allocator row (guard + recipient + mode). If the business has a refund path, add a refund-track row too.",
|
|
34
|
+
"stakeholders": ["merchant", "customer"]
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"rule_id": "FUND-EXIT-01",
|
|
40
|
+
"dimension": "fund_flow",
|
|
41
|
+
"trigger": "A business-terminal machine node is accepted by no allocator guard — funds that reach it are stranded forever (Machine/Service freeze at publish, A-2). Two tiers: with zero pending guard designs the money has NO declared exit (critical); with pending designs the exit is DECLARED but unverifiable until the judgment layer resolves them (medium).",
|
|
42
|
+
"cases": [
|
|
43
|
+
{
|
|
44
|
+
"when": { "all": [ { "field": "terminal_count", "op": "gt", "value": 0 }, { "field": "first_uncovered_terminal", "op": "present" }, { "field": "pending_allocator_guard_count", "op": "eq", "value": 0 } ] },
|
|
45
|
+
"level": "critical",
|
|
46
|
+
"title": "Terminal node '${first_uncovered_terminal}' has no fund exit",
|
|
47
|
+
"description": "Terminal nodes (${terminal_nodes_display}) are where orders rest forever. '${first_uncovered_terminal}' is accepted by no allocator guard and no pending guard design exists that could cover it, so escrowed funds reaching it can never leave. This must be proven impossible BEFORE publish — the graph and allocators freeze permanently.",
|
|
48
|
+
"mitigation": "Add an allocator whose guard accepts the terminal node (progress.current == '${first_uncovered_terminal}'), or add an outgoing edge so the node is no longer terminal.",
|
|
49
|
+
"stakeholders": ["merchant", "customer"]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"when": { "all": [ { "field": "terminal_count", "op": "gt", "value": 0 }, { "field": "first_uncovered_terminal", "op": "present" }, { "field": "pending_allocator_guard_count", "op": "gt", "value": 0 } ] },
|
|
53
|
+
"level": "medium",
|
|
54
|
+
"title": "Terminal node '${first_uncovered_terminal}' fund exit is declared but unverified",
|
|
55
|
+
"description": "Terminal nodes (${terminal_nodes_display}) are where orders rest forever. '${first_uncovered_terminal}' is accepted by no RESOLVED allocator guard; pending guard designs exist that may cover it, but until they are resolved into structured guards the coverage cannot be verified.",
|
|
56
|
+
"mitigation": "Resolve the pending guard designs (judgment layer / guardResolutions) so the allocator guard verifiably accepts '${first_uncovered_terminal}' before publish.",
|
|
57
|
+
"stakeholders": ["merchant", "customer"]
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"rule_id": "UNRESOLVED-GUARD-01",
|
|
63
|
+
"dimension": "composition",
|
|
64
|
+
"trigger": "A guard design requirement (pattern.* spec) is bound to a fund path or buy path but was never resolved into a structured guard — publishing now ships that path UNGUARDED.",
|
|
65
|
+
"cases": [
|
|
66
|
+
{
|
|
67
|
+
"when": { "field": "first_pending_fund_guard", "op": "present" },
|
|
68
|
+
"level": "critical",
|
|
69
|
+
"title": "Guard design '${first_pending_fund_guard}' is unresolved and bound to a fund path",
|
|
70
|
+
"description": "The allocator row or machine edge referencing this guard_key will carry NO guard at publish: the settlement/refund/forward it was designed to gate executes unconditionally. This is a publish-freeze blocker — the freeze gate refuses to go live with fund-path guards pending.",
|
|
71
|
+
"mitigation": "Resolve the guard design into a structured guard (guardResolutions with kind 'template' or 'inline'), or remove the binding.",
|
|
72
|
+
"stakeholders": ["merchant", "customer"]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"when": { "field": "first_pending_buy_guard", "op": "present" },
|
|
76
|
+
"level": "medium",
|
|
77
|
+
"title": "Buy-guard design '${first_pending_buy_guard}' is unresolved",
|
|
78
|
+
"description": "The service buy path was designed to screen purchasers, but the guard was never resolved; the service publishes without a buy_guard, so anyone can order.",
|
|
79
|
+
"mitigation": "Resolve the buy-guard design into a structured guard, or accept an unscreened buy path deliberately.",
|
|
80
|
+
"stakeholders": ["merchant"]
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"rule_id": "DUAL-RAIL-01",
|
|
86
|
+
"dimension": "fund_flow",
|
|
87
|
+
"trigger": "Refund-track guard does not read order.claimed_by — the dual rail (A-3) is deliberate on chain: alloc never reads claimed_by, compensate never touches the escrow. Double-pay prevention is a TEMPLATE convention; this rule is its only enforcement.",
|
|
88
|
+
"cases": [
|
|
89
|
+
{
|
|
90
|
+
"when": { "field": "first_refund_guard_missing_claimed_by", "op": "present" },
|
|
91
|
+
"level": "high",
|
|
92
|
+
"title": "Refund guard '${first_refund_guard_missing_claimed_by}' does not check claimed_by",
|
|
93
|
+
"description": "Chain semantics keep the allocation rail and the compensation rail independent (A-3, deliberate). A refund guard that does not assert claimed_by is none allows double payment: arbitration indemnity AND escrow refund.",
|
|
94
|
+
"mitigation": "Add a query on order.claimed_by (must be none) to the refund guard, or document an explicit double-compensation policy.",
|
|
95
|
+
"stakeholders": ["merchant"]
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"rule_id": "TIME-ANCHOR-01",
|
|
101
|
+
"dimension": "time_anchor",
|
|
102
|
+
"trigger": "A window guard anchors on a path-dependent time query (progress.current_time refreshes on every node entry) while the gated node is reachable by more than one path — detour nodes shift the settlement base (E-10: a buyer leaving a review postponed merchant settlement by the review window).",
|
|
103
|
+
"cases": [
|
|
104
|
+
{
|
|
105
|
+
"when": { "all": [ { "field": "first_path_dependent_anchor", "op": "present" }, { "field": "path_sensitive", "op": "truthy" } ] },
|
|
106
|
+
"level": "high",
|
|
107
|
+
"title": "Window guard '${first_path_dependent_anchor}' anchors on a path-dependent time",
|
|
108
|
+
"description": "progress.current_time is the time of ENTERING the current node, not of any business event. The gated node has multiple inbound paths, so an optional detour (e.g. a review node) silently extends the window. This is an exploitable merchant-side funds-lockup.",
|
|
109
|
+
"mitigation": "Anchor the window on order.time (path-independent), or restructure the machine so the anchored node has exactly one inbound path.",
|
|
110
|
+
"stakeholders": ["merchant", "customer"]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"when": { "field": "first_path_dependent_anchor", "op": "present" },
|
|
114
|
+
"level": "medium",
|
|
115
|
+
"title": "Window guard '${first_path_dependent_anchor}' uses a path-dependent time anchor",
|
|
116
|
+
"description": "The anchor is currently unambiguous (single-path), but any later template edit adding a bypass node silently shifts the window base.",
|
|
117
|
+
"mitigation": "Prefer order.time for settlement/refund windows.",
|
|
118
|
+
"stakeholders": ["merchant"]
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"rule_id": "WRITE-ONLY-01",
|
|
124
|
+
"dimension": "field_capability",
|
|
125
|
+
"trigger": "Plan sets a write-only field (only the native Guard engine ever reads it) with no guard query covering it — the enforcement the merchant believes in does not exist (A-1: customer_required was collected but never enforced on the buy path).",
|
|
126
|
+
"cases": [
|
|
127
|
+
{
|
|
128
|
+
"when": { "field": "first_write_only_unenforced_field", "op": "present" },
|
|
129
|
+
"level": "critical",
|
|
130
|
+
"title": "Field '${first_write_only_unenforced_field}' is set but never enforced",
|
|
131
|
+
"description": "Write-only fields are read ONLY by guard queries. Setting '${first_write_only_unenforced_field}' without a covering guard query creates the illusion of enforcement: the buy path will not check it.",
|
|
132
|
+
"mitigation": "Add a guard whose table queries the field (see chain-semantics WRITE_ONLY_QUERY_PREFIXES), bound to the enforcing forward or buy path — or remove the field.",
|
|
133
|
+
"stakeholders": ["merchant", "customer"]
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"rule_id": "HOST-GRAPH-01",
|
|
139
|
+
"dimension": "composition",
|
|
140
|
+
"trigger": "A guard exists but is bound to no host, or a guard queries repository data while the plan has no repository — the TRAILHAVEN B-2 failure: the Repository object and the third guard were silently dropped, leaving the shipping-evidence gate with nothing to check.",
|
|
141
|
+
"cases": [
|
|
142
|
+
{
|
|
143
|
+
"when": { "field": "first_repo_query_without_repository", "op": "present" },
|
|
144
|
+
"level": "critical",
|
|
145
|
+
"title": "Guard '${first_repo_query_without_repository}' queries a repository the plan never creates",
|
|
146
|
+
"description": "The guard reads repository.* data, but no repository step exists in the plan. On chain the query aborts on missing data — the forward it gates can never pass.",
|
|
147
|
+
"mitigation": "Add the repository create step and bind the guard to it, or remove the repository queries.",
|
|
148
|
+
"stakeholders": ["merchant"]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"when": { "field": "first_orphan_guard", "op": "present" },
|
|
152
|
+
"level": "high",
|
|
153
|
+
"title": "Guard '${first_orphan_guard}' is bound to no host",
|
|
154
|
+
"description": "The guard is created but never referenced by any machine forward, service buy_guard, allocator row, repository policy, arbitration, or reward. It is dead weight — usually a sign that a host binding was silently dropped during composition.",
|
|
155
|
+
"mitigation": "Wire the guard into its intended host binding, or delete the step.",
|
|
156
|
+
"stakeholders": ["merchant"]
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface SemanticFact {
|
|
2
|
+
fact_id: string;
|
|
3
|
+
subject: string;
|
|
4
|
+
authoritative: string;
|
|
5
|
+
falsehoods: string[];
|
|
6
|
+
harm: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const SEMANTIC_FACTS: SemanticFact[];
|
|
9
|
+
export declare function scanContent(filePath: string, content: string): Array<{
|
|
10
|
+
fact_id: string;
|
|
11
|
+
phrasing: string;
|
|
12
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SEMANTIC_FACTS=[{'fact_id':'FACT-ALLOC-01','subject':'Allocator\x20guard-matching\x20and\x20firing\x20semantics','authoritative':'A\x20distribution\x20call\x20submits\x20ONE\x20guard\x20address;\x20every\x20allocator\x20whose\x20bound\x20guard\x20equals\x20the\x20submitted\x20address\x20fires,\x20in\x20vector\x20order,\x20each\x20against\x20the\x20balance\x20left\x20by\x20the\x20previous\x20(allocation.move:366-368\x20—\x20the\x20loop\x20has\x20no\x20early\x20exit).\x20'+'Allocators\x20with\x20DIFFERENT\x20guards\x20are\x20alternative\x20paths\x20selected\x20by\x20the\x20caller\x27s\x20guard\x20choice,\x20not\x20by\x20list\x20position.\x20Mutual\x20exclusion\x20must\x20be\x20expressed\x20inside\x20the\x20guard\x20conditions.','falsehoods':['first-match-wins','first\x20Allocator\x20whose\x20Guard\x20returns\x20true','first\x20allocator\x20whose\x20guard\x20passes\x20wins','the\x20first\x20Allocator\x20whose\x20Guard\x20returns\x20true\x20wins','first-match\x20allocator\x20semantics','only\x20the\x20first\x20one','only\x20the\x20first\x20one\x20matches','duplicate\x20addresses\x20only\x20match\x20the\x20first','the\x20first\x20one\x20wins','the\x20first\x20allocator\x20whose\x20guard'],'harm':'Templates\x20built\x20on\x20\x27first-match\x27\x20semantics\x20silently\x20stack\x20distributions\x20or\x20leave\x20refund\x20paths\x20unreachable,\x20because\x20the\x20contract\x20fires\x20ALL\x20allocators\x20bound\x20to\x20the\x20submitted\x20guard.'},{'fact_id':'FACT-ALLOC-02','subject':'Surplus\x20semantics\x20—\x20drains\x20the\x20entire\x20remaining\x20pool','authoritative':'Surplus\x20mode\x20distributes\x20the\x20ENTIRE\x20remaining\x20balance\x20of\x20the\x20order\x27s\x20allocation\x20pool,\x20not\x20just\x20the\x20amount\x20earmarked\x20for\x20a\x20specific\x20track.\x20If\x20a\x20refund-path\x20allocator\x20uses\x20Surplus\x20while\x20the\x20settlement\x20path\x20has\x20unpaid\x20fixed-amount\x20legs,\x20the\x20Surplus\x20takes\x20everything,\x20including\x20the\x20settlement\x20money.','falsehoods':['Surplus\x20takes\x20only\x20what\x20is\x20left','Surplus\x20returns\x20the\x20remainder\x20after\x20other\x20tracks','Surplus\x20is\x20safe\x20because\x20it\x20only\x20takes\x20leftovers'],'harm':'A\x20refund/deposit\x20allocator\x20using\x20Surplus\x20will\x20over-refund\x20the\x20buyer\x20and\x20starve\x20the\x20merchant\x20when\x20the\x20settlement\x20track\x20has\x20not\x20yet\x20fired\x20(ziroom\x20T5:\x20585/525\x20WOW\x20fully\x20refunded,\x20merchant\x20received\x200).'},{'fact_id':'FACT-ALLOC-03','subject':'Allocator\x20fix\x20semantics\x20—\x20computed\x20Amount-leg\x20total,\x20PAID,\x20never\x20a\x20holdback','authoritative':'fix\x20is\x20not\x20a\x20settable\x20parameter:\x20the\x20allocator-registration\x20call\x20computes\x20it\x20internally\x20as\x20the\x20sum\x20of\x20the\x20allocator\x27s\x20Amount-mode\x20legs\x20(allocation.move:399\x20fix:\x20total_amount),\x20and\x20alloc()\x20PAYS\x20every\x20Amount\x20leg\x20(allocation.move:540\x20balance::split)\x20while\x20subtracting\x20fix\x20only\x20from\x20the\x20net-Rate\x20base\x20(allocation.move:485\x20total_rates\x20=\x20balance\x20-\x20fix).\x20A\x20pure-Rate\x20allocator\x20therefore\x20has\x20fix=0\x20and\x20drains\x20100%\x20of\x20the\x20pool;\x20adding\x20Amount\x20legs\x20raises\x20outflow,\x20it\x20never\x20withholds.\x20The\x20allocator-registration\x20call\x20surface\x20takes\x20only\x20(guard,\x20sharing,\x20max)\x20—\x20no\x20fix\x20argument\x20at\x20all\x20—\x20so\x20a\x20template-side\x20fix\x20value\x20is\x20silently\x20dropped\x20before\x20the\x20transaction\x20is\x20built.\x20The\x20chain\x20has\x20NO\x20holdback/reserve\x20primitive;\x20the\x20only\x20way\x20to\x20leave\x20funds\x20in\x20a\x20pool\x20is\x20to\x20not\x20distribute\x20them\x20(no\x20allocator\x20fires,\x20or\x20a\x20max-capped\x20Surplus\x20stops\x20at\x20the\x20cap).','falsehoods':['the\x20reserve\x20never\x20leaves','reserve\x20never\x20leaves\x20the\x20pool','the\x20reserve\x20stays\x20in\x20the\x20pool','reserve\x20physically\x20stays\x20in\x20the\x20pool','the\x20fix\x20retains\x20the\x20reserve','fix-retained\x20claim\x20reserve','leaves\x20the\x20reserve\x20in\x20the\x20pool','fix=reserve','only\x20on-chain\x20holdback'],'harm':'Templates\x20that\x20declare\x20fix=reserve\x20ship\x20a\x20payout\x20rail\x20that\x20drains\x20100%\x20of\x20the\x20escrow\x20at\x20the\x20first\x20release;\x20the\x20claim/refund\x20legs\x20behind\x20it\x20are\x20dead\x20by\x20construction\x20and\x20the\x20money\x20is\x20gone\x20(airbnb\x20mainnet\x20audit\x202026-10-07:\x20ABNB_STAY_SERVICE\x20allocators[0]\x20fix=\x220\x22,\x20full\x20drain\x20at\x20payout_24h).'},{'fact_id':'FACT-GUARD-01','subject':'GuardIdentifier\x20recipient\x20+\x20for_object\x20binding','authoritative':'ERECIPIENT_NOT_FOR_OBJECT\x20is\x20enforced\x20ONLY\x20when\x20the\x20recipient\x20kind\x20is\x20GuardIdentifier\x20AND\x20payment_info.for_object\x20is\x20Some(binding).\x20Pure\x20Entity\x20recipients\x20and\x20unbound\x20GuardIdentifier\x20legs\x20skip\x20this\x20check\x20entirely\x20—\x20the\x20tooling\x20layer\x20(scanner,\x20template\x20compiler)\x20must\x20flag\x20them\x20(allocation.move:434-443).','falsehoods':['the\x20contract\x20checks\x20all\x20recipients\x20against\x20for_object','GuardIdentifier\x20recipients\x20are\x20always\x20safe','the\x20contract\x20validates\x20every\x20recipient\x20binding'],'harm':'An\x20unbound\x20GuardIdentifier\x20or\x20pure\x20Entity\x20recipient\x20can\x20redirect\x20funds\x20to\x20the\x20deploying\x20account\x20or\x20an\x20arbitrary\x20address\x20without\x20any\x20on-chain\x20error.'},{'fact_id':'FACT-MACHINE-01','subject':'Machine\x20edge\x20\x27from\x27\x20semantics','authoritative':'A\x20machine\x20edge\x20declares\x20a\x20single\x20source\x20node\x20in\x20its\x20\x27from\x27\x20field.\x20Multiple\x20edges\x20from\x20the\x20same\x20source\x20node\x20are\x20allowed\x20and\x20represent\x20alternative\x20paths;\x20they\x20are\x20NOT\x20merged.\x20An\x20edge\x20without\x20\x27from\x27\x20is\x20invalid\x20in\x20the\x20new\x20topology\x20format\x20and\x20causes\x20compile-time\x20blockers.','falsehoods':['edges\x20without\x20from\x20are\x20auto-derived','missing\x20from\x20means\x20any\x20node','from\x20is\x20optional\x20for\x20backward\x20compatibility'],'harm':'Old\x20flat\x20machine_shape\x20without\x20from\x20fields\x20compiles\x20into\x20an\x20incomplete\x20topology,\x20leaving\x20nodes\x20unreachable\x20and\x20fund\x20paths\x20missing.'},{'fact_id':'FACT-ENTITY-01','subject':'Entity\x20recipient\x20fallback\x20to\x20deployer','authoritative':'When\x20an\x20Entity\x20recipient\x27s\x20name_or_address\x20is\x20empty,\x20omitted,\x20or\x20resolves\x20to\x20the\x20deploying\x20account,\x20the\x20share\x20is\x20paid\x20to\x20the\x20DEPLOYING\x20ACCOUNT\x20(allocation.move:434-443).\x20This\x20is\x20a\x20silent\x20fallback\x20—\x20no\x20error\x20is\x20raised.','falsehoods':['empty\x20Entity\x20names\x20are\x20rejected','the\x20contract\x20validates\x20Entity\x20recipients','an\x20unnamed\x20Entity\x20recipient\x20causes\x20an\x20abort'],'harm':'A\x20template\x20with\x20a\x20placeholder\x20Entity\x20recipient\x20silently\x20pays\x20the\x20share\x20to\x20whoever\x20deploys\x20the\x20service,\x20which\x20is\x20almost\x20never\x20the\x20intended\x20recipient.'}];export function scanContent(a,b){const c=[],d=b['toLowerCase']();for(const e of SEMANTIC_FACTS){for(const f of e['falsehoods']){const g=f['toLowerCase']();let h=0x0;while((h=d['indexOf'](g,h))!==-0x1){const i=d['slice'](Math['max'](0x0,h-0xc),h),j=/(?:^|[\s"'])not\s+$/['test'](i)||/never\s+$/['test'](i);!j&&c['push']({'fact_id':e['fact_id'],'phrasing':f}),h+=g['length'];}}}return c;}
|
|
@@ -23,7 +23,7 @@ export interface ArchetypeTemplate {
|
|
|
23
23
|
arbitration_mode?: "none" | "merchant_pick" | "mutual_pick" | "third_party";
|
|
24
24
|
time_anchors?: Record<string, string>;
|
|
25
25
|
}
|
|
26
|
-
export declare const BUILTIN_TEMPLATES_VERSION =
|
|
26
|
+
export declare const BUILTIN_TEMPLATES_VERSION = 33;
|
|
27
27
|
export declare const BUILTIN_TEMPLATES: ArchetypeTemplate[];
|
|
28
28
|
export declare const TEMPLATE_KEYWORDS: Record<string, string[]>;
|
|
29
29
|
export declare function getBuiltinTemplate(id: string): ArchetypeTemplate | undefined;
|