@wowok/agent-mcp 2.7.1 → 2.7.2
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/config/index.js +1 -1
- package/dist/config/runtime.js +1 -238
- package/dist/customer/customer-advice.js +1 -130
- package/dist/customer/index.js +1 -11
- package/dist/customer/industry-risks.js +1 -438
- package/dist/customer/info-puzzle.js +1 -681
- package/dist/customer/order-monitor.js +1 -328
- package/dist/customer/order-strategy.js +1 -373
- package/dist/customer/post-purchase.js +1 -351
- package/dist/customer/preorder-compare.js +1 -34
- package/dist/customer/reminder-system.js +1 -316
- package/dist/customer/risk-assessment.js +1 -397
- package/dist/customer/types.js +1 -13
- package/dist/customer/user-preferences.js +1 -460
- package/dist/evaluation/arbitration-game.d.ts +9 -2
- package/dist/evaluation/arbitration-game.js +1 -48
- package/dist/evaluation/builtins/demand-match.js +1 -153
- package/dist/evaluation/builtins/index.js +1 -10
- package/dist/evaluation/builtins/service-risk.js +1 -55
- package/dist/evaluation/capability.js +1 -13
- package/dist/evaluation/composer.js +1 -40
- package/dist/evaluation/engine.js +1 -175
- package/dist/evaluation/extract.js +1 -115
- package/dist/evaluation/game-strategy.d.ts +27 -0
- package/dist/evaluation/game-strategy.js +1 -0
- package/dist/evaluation/gap.js +1 -100
- package/dist/evaluation/index.d.ts +1 -0
- package/dist/evaluation/index.js +1 -11
- package/dist/evaluation/node-game.d.ts +31 -3
- package/dist/evaluation/node-game.js +1 -57
- package/dist/evaluation/region.js +1 -36
- package/dist/evaluation/types.d.ts +1 -0
- package/dist/evaluation/types.js +1 -1
- package/dist/evaluation/user-injection.js +1 -27
- package/dist/experience/experience-reuse.js +1 -103
- package/dist/experience/index.js +1 -5
- package/dist/experience/intent-distill.js +1 -83
- package/dist/experience/realtime-feedback.js +1 -94
- package/dist/experience/types.js +1 -1
- package/dist/experience/user-profile.js +1 -171
- package/dist/extensions/business-modules.js +1 -287
- package/dist/extensions/capability-manifest.js +1 -781
- package/dist/extensions/constraint-registry.js +1 -198
- package/dist/extensions/index.js +1 -6
- package/dist/extensions/metric-registry.js +1 -257
- package/dist/extensions/mode-evaluator.js +1 -170
- package/dist/extensions/modes.js +1 -499
- package/dist/extensions/registry.js +1 -717
- package/dist/extensions/types.js +1 -1
- package/dist/harness/auto-escalation.js +1 -68
- package/dist/harness/checkpoint.js +1 -129
- package/dist/harness/index.js +1 -78
- package/dist/harness/plan.js +1 -315
- package/dist/harness/recover.js +1 -139
- package/dist/harness/types.js +1 -1
- package/dist/harness/verify.js +1 -237
- package/dist/index.js +1 -273
- package/dist/intent/enrich.js +1 -67
- package/dist/intent/index.js +1 -60
- package/dist/intent/matcher.js +1 -81
- package/dist/intent/store.js +1 -55
- package/dist/intent/types.js +1 -10
- package/dist/knowledge/acquisition-flywheel.js +1 -192
- package/dist/knowledge/allocation-confirm.js +1 -534
- package/dist/knowledge/allocation-context.js +1 -249
- package/dist/knowledge/allocation-ledger.js +1 -463
- package/dist/knowledge/allocation-puzzle.js +1 -298
- package/dist/knowledge/allocation-risk.js +1 -568
- package/dist/knowledge/allocation-templates.js +1 -970
- package/dist/knowledge/allocation-translation.js +1 -585
- package/dist/knowledge/arb-risk.js +1 -210
- package/dist/knowledge/arbitration-confirm.js +1 -559
- package/dist/knowledge/arbitration-context.js +1 -505
- package/dist/knowledge/arbitration-ledger.js +1 -521
- package/dist/knowledge/arbitration-puzzle.js +1 -304
- package/dist/knowledge/arbitration-risk.js +1 -423
- package/dist/knowledge/arbitration-templates.js +1 -276
- package/dist/knowledge/arbitration-translation.js +1 -487
- package/dist/knowledge/arbitration-trust.js +1 -117
- package/dist/knowledge/audit-rules.js +1 -141
- package/dist/knowledge/bridge-risk.js +1 -263
- package/dist/knowledge/contact-risk.js +1 -200
- package/dist/knowledge/contact-templates.js +1 -60
- package/dist/knowledge/demand-confirm.js +1 -206
- package/dist/knowledge/demand-matching.js +1 -132
- package/dist/knowledge/demand-risk.js +1 -240
- package/dist/knowledge/demand-translation.js +1 -354
- package/dist/knowledge/deployment-scanner.js +1 -823
- package/dist/knowledge/dynamic-pricing.js +1 -87
- package/dist/knowledge/examples-scanner-cli.js +1 -26
- package/dist/knowledge/examples-scanner.js +1 -843
- package/dist/knowledge/flywheel-loop.js +1 -404
- package/dist/knowledge/fund-layer.js +1 -973
- package/dist/knowledge/glossary.js +1 -211
- package/dist/knowledge/guard-confirm.js +1 -406
- package/dist/knowledge/guard-context.js +1 -287
- package/dist/knowledge/guard-design-patterns.js +1 -360
- package/dist/knowledge/guard-ledger.js +1 -260
- package/dist/knowledge/guard-lint.js +1 -670
- package/dist/knowledge/guard-migration.js +1 -228
- package/dist/knowledge/guard-puzzle.js +1 -805
- package/dist/knowledge/guard-render.js +1 -700
- package/dist/knowledge/guard-risk.js +1 -1879
- package/dist/knowledge/guard-submission-prompt.js +1 -171
- package/dist/knowledge/guard-templates.js +1 -1105
- package/dist/knowledge/guard-translation.js +1 -1119
- package/dist/knowledge/index.js +1 -436
- package/dist/knowledge/industry-evolution.js +1 -323
- package/dist/knowledge/industry-generalizer.js +1 -381
- package/dist/knowledge/industry-registry.js +1 -174
- package/dist/knowledge/intent-metrics.d.ts +4 -3
- package/dist/knowledge/intent-metrics.js +1 -566
- package/dist/knowledge/machine-confirm.js +1 -559
- package/dist/knowledge/machine-context.js +1 -833
- package/dist/knowledge/machine-ledger.js +1 -338
- package/dist/knowledge/machine-puzzle.js +1 -494
- package/dist/knowledge/machine-render.js +1 -565
- package/dist/knowledge/machine-risk.js +1 -669
- package/dist/knowledge/machine-templates.js +1 -1597
- package/dist/knowledge/machine-topology.js +1 -234
- package/dist/knowledge/machine-translation.js +1 -513
- package/dist/knowledge/mcp-schema-audit-cli.js +1 -45
- package/dist/knowledge/mcp-schema-audit.js +1 -777
- package/dist/knowledge/onchain-constants.js +1 -35
- package/dist/knowledge/order-confirm.js +1 -573
- package/dist/knowledge/order-context.js +1 -390
- package/dist/knowledge/order-ledger.js +1 -341
- package/dist/knowledge/order-puzzle.js +1 -255
- package/dist/knowledge/order-risk.js +1 -653
- package/dist/knowledge/order-templates.js +1 -368
- package/dist/knowledge/order-translation.js +1 -550
- package/dist/knowledge/overrides-loader.js +1 -65
- package/dist/knowledge/passport-confirm.js +1 -531
- package/dist/knowledge/passport-context.js +1 -306
- package/dist/knowledge/passport-ledger.js +1 -282
- package/dist/knowledge/passport-puzzle.js +1 -333
- package/dist/knowledge/passport-risk.js +1 -450
- package/dist/knowledge/passport-templates.js +1 -568
- package/dist/knowledge/passport-translation.js +1 -516
- package/dist/knowledge/payment-risk.js +1 -249
- package/dist/knowledge/permission-confirm.js +1 -426
- package/dist/knowledge/permission-context.js +1 -224
- package/dist/knowledge/permission-ledger.js +1 -403
- package/dist/knowledge/permission-puzzle.js +1 -173
- package/dist/knowledge/permission-risk.js +1 -411
- package/dist/knowledge/permission-templates.js +1 -234
- package/dist/knowledge/permission-translation.js +1 -350
- package/dist/knowledge/personal-risk.js +1 -212
- package/dist/knowledge/process-model.js +1 -160
- package/dist/knowledge/progress-confirm.js +1 -456
- package/dist/knowledge/progress-context.js +1 -452
- package/dist/knowledge/progress-ledger.js +1 -330
- package/dist/knowledge/progress-puzzle.js +1 -219
- package/dist/knowledge/progress-risk.js +1 -461
- package/dist/knowledge/progress-templates.js +1 -228
- package/dist/knowledge/progress-translation.js +1 -405
- package/dist/knowledge/proof-confirm.js +1 -187
- package/dist/knowledge/proof-risk.js +1 -207
- package/dist/knowledge/proof-translation.js +1 -283
- package/dist/knowledge/registrar-risk.js +1 -217
- package/dist/knowledge/repository-confirm.js +1 -286
- package/dist/knowledge/repository-risk.js +1 -373
- package/dist/knowledge/repository-translation.js +1 -445
- package/dist/knowledge/reputation-rules.js +1 -99
- package/dist/knowledge/resource-risk.js +1 -157
- package/dist/knowledge/reward-confirm.js +1 -526
- package/dist/knowledge/reward-context.js +1 -504
- package/dist/knowledge/reward-ledger.js +1 -502
- package/dist/knowledge/reward-puzzle.js +1 -300
- package/dist/knowledge/reward-risk.js +1 -627
- package/dist/knowledge/reward-templates.js +1 -197
- package/dist/knowledge/reward-translation.js +1 -501
- package/dist/knowledge/safety-rules.js +1 -404
- package/dist/knowledge/scenario-modes.js +1 -321
- package/dist/knowledge/service-confirm.js +1 -807
- package/dist/knowledge/service-context.js +1 -403
- package/dist/knowledge/service-ledger.js +1 -609
- package/dist/knowledge/service-puzzle.js +1 -236
- package/dist/knowledge/service-risk.js +1 -651
- package/dist/knowledge/service-templates.js +1 -456
- package/dist/knowledge/service-translation.js +1 -622
- package/dist/knowledge/template-registry.js +1 -353
- package/dist/knowledge/tool-constraints.js +1 -195
- package/dist/knowledge/tools-reference.js +1 -178
- package/dist/knowledge/treasury-confirm.js +1 -512
- package/dist/knowledge/treasury-context.js +1 -363
- package/dist/knowledge/treasury-ledger.js +1 -300
- package/dist/knowledge/treasury-puzzle.js +1 -216
- package/dist/knowledge/treasury-risk.js +1 -440
- package/dist/knowledge/treasury-templates.js +1 -358
- package/dist/knowledge/treasury-translation.js +1 -498
- package/dist/knowledge/trust-metrics.js +1 -198
- package/dist/knowledge/util-risk.js +1 -135
- package/dist/loop-engineering/aggregate.js +1 -132
- package/dist/loop-engineering/context-collect.js +1 -83
- package/dist/loop-engineering/diagnose.js +1 -273
- package/dist/loop-engineering/improve.js +1 -405
- package/dist/loop-engineering/index.js +1 -4
- package/dist/loop-engineering/pipeline.js +1 -56
- package/dist/mode-market/index.js +1 -3
- package/dist/mode-market/registry.js +1 -124
- package/dist/mode-market/review.js +1 -214
- package/dist/mode-market/submission.js +1 -85
- package/dist/participation/collaborator-interest.d.ts +23 -0
- package/dist/participation/collaborator-interest.js +1 -0
- package/dist/participation/customer-interest.d.ts +25 -0
- package/dist/participation/customer-interest.js +1 -0
- package/dist/participation/merchant-interest.js +1 -100
- package/dist/participation/radar-core.d.ts +13 -3
- package/dist/participation/radar-core.js +1 -269
- package/dist/participation/supplier-interest.d.ts +25 -0
- package/dist/participation/supplier-interest.js +1 -0
- package/dist/persona/analyzer.js +1 -66
- package/dist/persona/bridge.js +1 -86
- package/dist/persona/defaults.js +1 -195
- package/dist/persona/experience-bridge.js +1 -23
- package/dist/persona/index.js +1 -71
- package/dist/persona/model.js +1 -111
- package/dist/persona/store.js +1 -62
- package/dist/persona/types.d.ts +3 -1
- package/dist/persona/types.js +1 -5
- package/dist/project/business-puzzle.js +1 -383
- package/dist/project/context-assembly.js +1 -254
- package/dist/project/deployment-bridge.js +1 -120
- package/dist/project/deployment-doc.js +1 -1126
- package/dist/project/edit-planner.js +1 -1342
- package/dist/project/evaluation.js +1 -2011
- package/dist/project/game-theory.js +1 -177
- package/dist/project/graph-builder.js +1 -656
- package/dist/project/graph.js +1 -340
- package/dist/project/handlers.js +1 -1784
- package/dist/project/index.d.ts +1 -0
- package/dist/project/index.js +1 -301
- package/dist/project/intent-analyzer.js +1 -149
- package/dist/project/machine-nodes.js +1 -36
- package/dist/project/merchant-guide.js +1 -264
- package/dist/project/migration.js +1 -125
- package/dist/project/mode-actions.js +1 -309
- package/dist/project/namespace.js +1 -206
- package/dist/project/participation-radar.js +1 -428
- package/dist/project/pipeline-actions.js +1 -109
- package/dist/project/project-store.js +1 -422
- package/dist/project/query.js +1 -153
- package/dist/project/reverse-mapping.d.ts +34 -0
- package/dist/project/reverse-mapping.js +1 -0
- package/dist/project/risk-aggregator.js +1 -295
- package/dist/project/rollback-policy.js +1 -290
- package/dist/project/semantic-assembler.js +1 -345
- package/dist/project/semantic-graph.js +1 -292
- package/dist/project/stage-gate.js +1 -369
- package/dist/project/substep-trace.js +1 -332
- package/dist/project/task-tracker.js +1 -78
- package/dist/role/derivation.d.ts +18 -0
- package/dist/role/derivation.js +1 -0
- package/dist/role/index.d.ts +5 -0
- package/dist/role/index.js +1 -0
- package/dist/role/model.d.ts +8 -0
- package/dist/role/model.js +1 -0
- package/dist/role/resolution.d.ts +11 -0
- package/dist/role/resolution.js +1 -0
- package/dist/role/types.d.ts +11 -0
- package/dist/role/types.js +1 -0
- package/dist/rules.js +1 -52
- package/dist/safety/confirm-gate.js +1 -88
- package/dist/safety/index.js +1 -3
- package/dist/safety/preview.js +1 -52
- package/dist/schema/call/allocation.js +1 -34
- package/dist/schema/call/arbitration.js +1 -113
- package/dist/schema/call/base.d.ts +15 -15
- package/dist/schema/call/base.js +1 -370
- package/dist/schema/call/bridge-handler.js +1 -265
- package/dist/schema/call/bridge.d.ts +7 -7
- package/dist/schema/call/bridge.js +1 -458
- package/dist/schema/call/contact.js +1 -37
- package/dist/schema/call/demand.js +1 -47
- package/dist/schema/call/guard.js +1 -161
- package/dist/schema/call/handler.js +1 -322
- package/dist/schema/call/index.js +1 -20
- package/dist/schema/call/machine.js +1 -193
- package/dist/schema/call/order.js +1 -35
- package/dist/schema/call/payment.js +1 -37
- package/dist/schema/call/permission-handler.js +1 -54
- package/dist/schema/call/permission.js +1 -105
- package/dist/schema/call/personal.js +1 -78
- package/dist/schema/call/progress.js +1 -47
- package/dist/schema/call/proof.js +1 -33
- package/dist/schema/call/repository.js +1 -77
- package/dist/schema/call/reward.js +1 -30
- package/dist/schema/call/semantic.js +1 -1679
- package/dist/schema/call/service.js +1 -184
- package/dist/schema/call/treasury.js +1 -71
- package/dist/schema/common/index.js +1 -407
- package/dist/schema/config/index.js +1 -68
- package/dist/schema/evaluation/index.d.ts +213 -16
- package/dist/schema/evaluation/index.js +1 -356
- package/dist/schema/index.js +1 -17
- package/dist/schema/intent-radar/index.d.ts +13 -13
- package/dist/schema/intent-radar/index.js +1 -89
- package/dist/schema/local/index.d.ts +21 -21
- package/dist/schema/local/index.js +1 -927
- package/dist/schema/local/wip.js +1 -187
- package/dist/schema/messenger/index.d.ts +7 -7
- package/dist/schema/messenger/index.js +1 -475
- package/dist/schema/operations.d.ts +7 -7
- package/dist/schema/operations.js +1 -520
- package/dist/schema/persona/index.d.ts +54 -54
- package/dist/schema/persona/index.js +1 -148
- package/dist/schema/project/index.d.ts +94 -48
- package/dist/schema/project/index.js +1 -2057
- package/dist/schema/query/index.d.ts +423 -7
- package/dist/schema/query/index.js +1 -1646
- package/dist/schema/schema-query/index.js +1 -104
- package/dist/schema/schema-version.js +1 -76
- package/dist/schema/sync-layer4.js +1 -286
- package/dist/schema/task-status.js +1 -36
- package/dist/schema/trust/index.js +1 -314
- package/dist/schema/utils/guard-parser.js +1 -419
- package/dist/schema/utils/guard-query-utils.js +1 -46
- package/dist/schema/utils/node-parser.js +1 -369
- package/dist/schema/utils/object-type-utils.js +1 -35
- package/dist/schema/utils/permission-index-utils.js +1 -7
- package/dist/schema/utils/permission-machine-check.js +1 -121
- package/dist/schema/utils/skills-recommendation.js +1 -77
- package/dist/schema-query/index.js +1 -810
- package/dist/schemas/account_operation.output.json +5 -2
- package/dist/schemas/bridge_operation.output.json +5 -2
- package/dist/schemas/evaluation_operation.output.json +112 -7
- package/dist/schemas/evaluation_operation.schema.json +93 -6
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/intent_radar.output.json +4 -1
- package/dist/schemas/intent_radar.schema.json +4 -1
- package/dist/schemas/local_info_operation.output.json +5 -2
- package/dist/schemas/local_mark_operation.output.json +5 -2
- package/dist/schemas/messenger_operation.output.json +5 -2
- package/dist/schemas/onchain_events.output.json +5 -2
- package/dist/schemas/onchain_operations.output.json +5 -2
- package/dist/schemas/onchain_operations.schema.json +4 -4
- package/dist/schemas/onchain_operations_allocation.schema.json +1 -1
- package/dist/schemas/onchain_operations_machine.schema.json +2 -2
- package/dist/schemas/onchain_operations_service.schema.json +1 -1
- package/dist/schemas/onchain_table_data.output.json +6 -3
- package/dist/schemas/persona_operation.output.json +4 -1
- package/dist/schemas/persona_operation.schema.json +4 -1
- package/dist/schemas/project_operation.output.json +28 -8
- package/dist/schemas/query_toolkit.output.json +8 -5
- package/dist/schemas/wowok_buildin_info.output.json +132 -0
- package/dist/schemas/wowok_buildin_info.schema.json +14 -0
- package/dist/telemetry/index.js +1 -112
- package/dist/telemetry/redact.js +1 -23
- package/dist/telemetry/storage.js +1 -80
- package/dist/tools/handlers/bridge.js +1 -1
- package/dist/tools/handlers/config.js +1 -74
- package/dist/tools/handlers/evaluation.js +1 -123
- package/dist/tools/handlers/file-export.js +1 -90
- package/dist/tools/handlers/intent-radar.js +1 -76
- package/dist/tools/handlers/local.js +1 -53
- package/dist/tools/handlers/messenger.js +1 -188
- package/dist/tools/handlers/onchain.js +1 -1180
- package/dist/tools/handlers/persona.js +1 -89
- package/dist/tools/handlers/project.js +1 -211
- package/dist/tools/handlers/query.js +1 -434
- package/dist/tools/handlers/schema-query.js +1 -176
- package/dist/tools/handlers/task-status.js +1 -26
- package/dist/tools/handlers/trust.js +1 -380
- package/dist/tools/handlers/wip.js +1 -90
- package/dist/tools/index.js +1 -1382
- package/dist/tools/retry.js +1 -85
- package/dist/tools/rules-hook.js +1 -23
- package/dist/tools/shared.js +1 -130
- package/dist/tools/types.js +1 -1
- package/dist/tools/upgrade-check.d.ts +19 -0
- package/dist/tools/upgrade-check.js +1 -0
- package/dist/tools/wip-deploy-assist.js +1 -306
- package/dist/tools/wrap.js +1 -500
- package/package.json +4 -2
|
@@ -1,568 +1 @@
|
|
|
1
|
-
import { MAX_ALLOCATOR_COUNT, RATE_TOTAL_FULL, ALLOCATION_ERROR_CODES, } from "./allocation-ledger.js";
|
|
2
|
-
const R_A_1_01 = {
|
|
3
|
-
id: "R-A-1-01",
|
|
4
|
-
category: "structural",
|
|
5
|
-
trigger: "allocators is empty or sharing arrays are empty",
|
|
6
|
-
check: (ctx) => {
|
|
7
|
-
if (!ctx.allocators_config)
|
|
8
|
-
return null;
|
|
9
|
-
const allocators = ctx.allocators_config.allocators;
|
|
10
|
-
if (allocators.length === 0) {
|
|
11
|
-
return {
|
|
12
|
-
id: "R-A-1-01",
|
|
13
|
-
level: "CRITICAL",
|
|
14
|
-
category: "structural",
|
|
15
|
-
title: "Empty allocators — funds will be permanently locked",
|
|
16
|
-
description: "Allocation has empty allocators.allocators. Service publish with empty order_allocators causes order funds to be permanently locked in the Allocation object.",
|
|
17
|
-
affected_stakeholders: ["owner", "service_provider", "system"],
|
|
18
|
-
scenario: "Service published without configuring any Allocator",
|
|
19
|
-
mitigation: "Configure at least 1 Allocator. If no distribution is needed yet, use a single Allocator with Rate=10000 to the merchant address.",
|
|
20
|
-
evidence: "allocators.length=0",
|
|
21
|
-
related_move_error: "EALLOCATORS_EMPTY (8) / ENO_ALLOCATOR (3)",
|
|
22
|
-
auto_fixable: false,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
for (let i = 0; i < allocators.length; i++) {
|
|
26
|
-
if (allocators[i].sharing.length === 0) {
|
|
27
|
-
return {
|
|
28
|
-
id: "R-A-1-01",
|
|
29
|
-
level: "CRITICAL",
|
|
30
|
-
category: "structural",
|
|
31
|
-
title: `Allocator ${i} has empty sharing — will never distribute`,
|
|
32
|
-
description: `Allocator at index ${i} (guard=${allocators[i].guard}) has empty sharing array. Even if its Guard passes verification, no funds will be distributed.`,
|
|
33
|
-
affected_stakeholders: ["owner", "recipient"],
|
|
34
|
-
scenario: "Allocator with empty sharing vector",
|
|
35
|
-
mitigation: `Add at least 1 sharing entry to Allocator ${i}`,
|
|
36
|
-
evidence: `allocator[${i}].sharing.length=0`,
|
|
37
|
-
related_move_error: "ENO_ALLOCATOR (3)",
|
|
38
|
-
auto_fixable: false,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return null;
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
const R_A_1_02 = {
|
|
46
|
-
id: "R-A-1-02",
|
|
47
|
-
category: "structural",
|
|
48
|
-
trigger: "Pure Rate mode sum != 10000 or Rate+Surplus sum > 10000",
|
|
49
|
-
check: (ctx) => {
|
|
50
|
-
if (!ctx.allocators_config)
|
|
51
|
-
return null;
|
|
52
|
-
for (let i = 0; i < ctx.allocators_config.allocators.length; i++) {
|
|
53
|
-
const a = ctx.allocators_config.allocators[i];
|
|
54
|
-
const rateSum = a.sharing
|
|
55
|
-
.filter(s => s.mode === "Rate")
|
|
56
|
-
.reduce((sum, s) => sum + Number(s.sharing), 0);
|
|
57
|
-
const hasSurplus = a.sharing.some(s => s.mode === "Surplus");
|
|
58
|
-
if (!hasSurplus && rateSum > 0 && rateSum !== RATE_TOTAL_FULL) {
|
|
59
|
-
return {
|
|
60
|
-
id: "R-A-1-02",
|
|
61
|
-
level: "HIGH",
|
|
62
|
-
category: "structural",
|
|
63
|
-
title: `Pure Rate mode sum ${rateSum} != ${RATE_TOTAL_FULL}`,
|
|
64
|
-
description: `Allocator ${i} (guard=${a.guard}) uses pure Rate mode (no Surplus), but sum(rates)=${rateSum} ≠ ${RATE_TOTAL_FULL}. Funds will be permanently locked (if sum<10000) or Move will abort with ERATE_NOT_10000 (if sum != 10000 exactly).`,
|
|
65
|
-
affected_stakeholders: ["owner", "recipient"],
|
|
66
|
-
scenario: "Misconfigured rate proportions",
|
|
67
|
-
mitigation: `Adjust sharing.sharing values so sum(rates)=${RATE_TOTAL_FULL}, OR add 1 Surplus sharing to absorb the remainder.`,
|
|
68
|
-
evidence: `rateSum=${rateSum}, expected=${RATE_TOTAL_FULL}`,
|
|
69
|
-
related_move_error: "ERATE_NOT_10000 (4)",
|
|
70
|
-
auto_fixable: true,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
if (hasSurplus && rateSum > RATE_TOTAL_FULL) {
|
|
74
|
-
return {
|
|
75
|
-
id: "R-A-1-02",
|
|
76
|
-
level: "HIGH",
|
|
77
|
-
category: "structural",
|
|
78
|
-
title: `Rate + Surplus sum ${rateSum} > ${RATE_TOTAL_FULL}`,
|
|
79
|
-
description: `Allocator ${i} (guard=${a.guard}) uses Rate+Surplus mode, but sum(rates)=${rateSum} > ${RATE_TOTAL_FULL}. Move will abort with ERATE_EXCEEDS_10000.`,
|
|
80
|
-
affected_stakeholders: ["owner"],
|
|
81
|
-
scenario: "Rate percentages exceed 100% before Surplus",
|
|
82
|
-
mitigation: `Reduce sum(rates) to ≤ ${RATE_TOTAL_FULL}.`,
|
|
83
|
-
evidence: `rateSum=${rateSum}, max=${RATE_TOTAL_FULL}`,
|
|
84
|
-
related_move_error: "ERATE_EXCEEDS_10000 (6)",
|
|
85
|
-
auto_fixable: true,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return null;
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
const R_A_1_03 = {
|
|
93
|
-
id: "R-A-1-03",
|
|
94
|
-
category: "structural",
|
|
95
|
-
trigger: "Multiple Surplus sharing in one Allocator, or Amount sum violates threshold/max",
|
|
96
|
-
check: (ctx) => {
|
|
97
|
-
if (!ctx.allocators_config)
|
|
98
|
-
return null;
|
|
99
|
-
for (let i = 0; i < ctx.allocators_config.allocators.length; i++) {
|
|
100
|
-
const a = ctx.allocators_config.allocators[i];
|
|
101
|
-
const surplusCount = a.sharing.filter(s => s.mode === "Surplus").length;
|
|
102
|
-
if (surplusCount > 1) {
|
|
103
|
-
return {
|
|
104
|
-
id: "R-A-1-03",
|
|
105
|
-
level: "MEDIUM",
|
|
106
|
-
category: "structural",
|
|
107
|
-
title: `Allocator ${i} has ${surplusCount} Surplus sharing — at most 1 allowed`,
|
|
108
|
-
description: `Allocator ${i} (guard=${a.guard}) has ${surplusCount} Surplus sharing entries. Move will abort with EMULTIPLE_SURPLUS at alloc() time.`,
|
|
109
|
-
affected_stakeholders: ["owner"],
|
|
110
|
-
scenario: "Multiple Surplus entries in one Allocator",
|
|
111
|
-
mitigation: "Keep at most 1 Surplus per Allocator. Use Rate mode for multi-party remainder distribution.",
|
|
112
|
-
evidence: `surplusCount=${surplusCount}`,
|
|
113
|
-
related_move_error: "EMULTIPLE_SURPLUS (5)",
|
|
114
|
-
auto_fixable: true,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
const amountSum = a.sharing
|
|
118
|
-
.filter(s => s.mode === "Amount")
|
|
119
|
-
.reduce((sum, s) => sum + Number(s.sharing), 0);
|
|
120
|
-
const threshold = Number(ctx.allocators_config.threshold);
|
|
121
|
-
if (amountSum > 0 && amountSum < threshold) {
|
|
122
|
-
return {
|
|
123
|
-
id: "R-A-1-03",
|
|
124
|
-
level: "HIGH",
|
|
125
|
-
category: "structural",
|
|
126
|
-
title: `Amount sum ${amountSum} < threshold ${threshold}`,
|
|
127
|
-
description: `Allocator ${i} pure Amount mode fix=${amountSum} < threshold=${threshold}. Move will abort with EAMOUNT_BELOW_THRESHOLD at allocator_add time.`,
|
|
128
|
-
affected_stakeholders: ["owner"],
|
|
129
|
-
scenario: "Amount sum insufficient to trigger alloc",
|
|
130
|
-
mitigation: "Either lower threshold to <= fix, or increase Amount sharing values.",
|
|
131
|
-
evidence: `fix=${amountSum}, threshold=${threshold}`,
|
|
132
|
-
related_move_error: "EAMOUNT_BELOW_THRESHOLD (12)",
|
|
133
|
-
auto_fixable: false,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
if (a.max != null && amountSum > Number(a.max)) {
|
|
137
|
-
return {
|
|
138
|
-
id: "R-A-1-03",
|
|
139
|
-
level: "MEDIUM",
|
|
140
|
-
category: "structural",
|
|
141
|
-
title: `Amount sum ${amountSum} > max ${Number(a.max)}`,
|
|
142
|
-
description: `Allocator ${i} Amount sum exceeds max. Move will abort with EAMOUNT_EXCEEDS_MAX.`,
|
|
143
|
-
affected_stakeholders: ["owner"],
|
|
144
|
-
scenario: "Amount sum exceeds max cap",
|
|
145
|
-
mitigation: "Increase max or reduce Amount sharing values.",
|
|
146
|
-
evidence: `fix=${amountSum}, max=${Number(a.max)}`,
|
|
147
|
-
related_move_error: "EAMOUNT_EXCEEDS_MAX (13)",
|
|
148
|
-
auto_fixable: true,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return null;
|
|
153
|
-
},
|
|
154
|
-
};
|
|
155
|
-
const R_A_2_01 = {
|
|
156
|
-
id: "R-A-2-01",
|
|
157
|
-
category: "semantic",
|
|
158
|
-
trigger: "sharing.who=Signer without Guard Signer binding — fund theft risk",
|
|
159
|
-
check: (ctx) => {
|
|
160
|
-
if (!ctx.allocators_config)
|
|
161
|
-
return null;
|
|
162
|
-
for (let i = 0; i < ctx.allocators_config.allocators.length; i++) {
|
|
163
|
-
const a = ctx.allocators_config.allocators[i];
|
|
164
|
-
const hasSignerRecipient = a.sharing.some(s => "Signer" in s.who);
|
|
165
|
-
if (!hasSignerRecipient)
|
|
166
|
-
continue;
|
|
167
|
-
const guardBound = ctx.guard_signer_bindings?.[a.guard] === true;
|
|
168
|
-
if (!guardBound) {
|
|
169
|
-
return {
|
|
170
|
-
id: "R-A-2-01",
|
|
171
|
-
level: "CRITICAL",
|
|
172
|
-
category: "semantic",
|
|
173
|
-
title: "sharing.who=Signer without Guard Signer binding — fund theft risk",
|
|
174
|
-
description: `Allocator ${i} (guard=${a.guard}) has sharing.who=Signer, but the Guard does not bind context(Signer)==authorized. Anyone who passes the Guard can steal 100% of funds. This is the most severe Allocation risk (linked to guard-risk.ts R-C3-06).`,
|
|
175
|
-
affected_stakeholders: ["owner", "recipient", "service_provider"],
|
|
176
|
-
scenario: "Signer recipient without Guard Signer authentication",
|
|
177
|
-
mitigation: "Option A (preferred): change sharing.who to Entity (Treasury or fixed address). Option B: add Signer-binding check to the Guard (context(Signer)==authorized_address).",
|
|
178
|
-
evidence: `guard=${a.guard}, guardSignerBound=${guardBound}`,
|
|
179
|
-
related_guard_risk: "R-C3-06",
|
|
180
|
-
auto_fixable: false,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return null;
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
const R_A_2_02 = {
|
|
188
|
-
id: "R-A-2-02",
|
|
189
|
-
category: "semantic",
|
|
190
|
-
trigger: "sharing.who=GuardIdentifier but Passport table entry is not address type",
|
|
191
|
-
check: (ctx) => {
|
|
192
|
-
if (!ctx.allocators_config)
|
|
193
|
-
return null;
|
|
194
|
-
if (!ctx.passport_identifier_types)
|
|
195
|
-
return null;
|
|
196
|
-
for (let i = 0; i < ctx.allocators_config.allocators.length; i++) {
|
|
197
|
-
const a = ctx.allocators_config.allocators[i];
|
|
198
|
-
const guardIdSharing = a.sharing.find(s => "GuardIdentifier" in s.who);
|
|
199
|
-
if (!guardIdSharing)
|
|
200
|
-
continue;
|
|
201
|
-
const identifier = guardIdSharing.who.GuardIdentifier;
|
|
202
|
-
const idType = ctx.passport_identifier_types[identifier];
|
|
203
|
-
if (idType !== undefined && idType !== "address") {
|
|
204
|
-
return {
|
|
205
|
-
id: "R-A-2-02",
|
|
206
|
-
level: "MEDIUM",
|
|
207
|
-
category: "semantic",
|
|
208
|
-
title: `GuardIdentifier ${identifier} resolves to non-address type (${idType})`,
|
|
209
|
-
description: `Allocator ${i} uses sharing.who=GuardIdentifier(${identifier}), but Passport table[${identifier}] is of type ${idType}, not address. Move will abort with ERECIPIENT_IDENTIFIER_NOT_ADDRESS at alloc() time.`,
|
|
210
|
-
affected_stakeholders: ["recipient"],
|
|
211
|
-
scenario: "Passport table entry type mismatch",
|
|
212
|
-
mitigation: `Ensure Passport table[${identifier}] is address-typed, OR use sharing.who=Entity with a static address.`,
|
|
213
|
-
evidence: `identifier=${identifier}, type=${idType}`,
|
|
214
|
-
related_move_error: "ERECIPIENT_IDENTIFIER_NOT_ADDRESS (1)",
|
|
215
|
-
auto_fixable: false,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return null;
|
|
220
|
-
},
|
|
221
|
-
};
|
|
222
|
-
const R_A_2_03 = {
|
|
223
|
-
id: "R-A-2-03",
|
|
224
|
-
category: "semantic",
|
|
225
|
-
trigger: "Duplicate Guard addresses in allocators (alloc_by_guard address match only hits the first one)",
|
|
226
|
-
check: (ctx) => {
|
|
227
|
-
if (!ctx.allocators_config)
|
|
228
|
-
return null;
|
|
229
|
-
const guards = ctx.allocators_config.allocators.map(a => a.guard);
|
|
230
|
-
const unique = new Set(guards);
|
|
231
|
-
if (unique.size !== guards.length) {
|
|
232
|
-
const dupes = guards.filter((g, i) => guards.indexOf(g) !== i);
|
|
233
|
-
return {
|
|
234
|
-
id: "R-A-2-03",
|
|
235
|
-
level: "MEDIUM",
|
|
236
|
-
category: "semantic",
|
|
237
|
-
title: "Duplicate Guard addresses in allocators",
|
|
238
|
-
description: `Multiple Allocators reference the same Guard object: ${dupes.join(", ")}. alloc_by_guard locates the Allocator by iterating guard addresses; duplicate addresses only match the first one, so subsequent duplicate Allocators are unreachable (dead code).`,
|
|
239
|
-
affected_stakeholders: ["owner", "allocator"],
|
|
240
|
-
scenario: "Reusing same Guard object across multiple Allocators",
|
|
241
|
-
mitigation: "Create independent Guard objects for each Allocator (they may share root/table but must differ in description).",
|
|
242
|
-
evidence: `total=${guards.length}, unique=${unique.size}, dupes=${dupes.join(",")}`,
|
|
243
|
-
auto_fixable: true,
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
return null;
|
|
247
|
-
},
|
|
248
|
-
};
|
|
249
|
-
const R_A_3_01 = {
|
|
250
|
-
id: "R-A-3-01",
|
|
251
|
-
category: "authority",
|
|
252
|
-
trigger: "Service already published — order_allocators is immutable",
|
|
253
|
-
check: (ctx) => {
|
|
254
|
-
if (!ctx.host_service_published)
|
|
255
|
-
return null;
|
|
256
|
-
return {
|
|
257
|
-
id: "R-A-3-01",
|
|
258
|
-
level: "HIGH",
|
|
259
|
-
category: "authority",
|
|
260
|
-
title: "order_allocators immutable after Service publish",
|
|
261
|
-
description: "Service is already published. order_allocators field is now immutable (safety-rules.ts:170-174). Any configuration error (wrong Guard, wrong sharing proportion, wrong Entity address) will affect ALL subsequent orders and cannot be fixed without creating a new Service.",
|
|
262
|
-
affected_stakeholders: ["owner", "service_provider"],
|
|
263
|
-
scenario: "Attempting to modify order_allocators after Service publish",
|
|
264
|
-
mitigation: "1) Verify the configuration is correct before publish. 2) Use deploy-scanner pre-publish validation. 3) If already published with errors, create a new Service to replace.",
|
|
265
|
-
evidence: `host_service_published=${ctx.host_service_published}`,
|
|
266
|
-
auto_fixable: false,
|
|
267
|
-
};
|
|
268
|
-
},
|
|
269
|
-
};
|
|
270
|
-
const R_A_3_02 = {
|
|
271
|
-
id: "R-A-3-02",
|
|
272
|
-
category: "authority",
|
|
273
|
-
trigger: "Treasury Permission inconsistent with Service Permission",
|
|
274
|
-
check: (ctx) => {
|
|
275
|
-
if (!ctx.allocators_config)
|
|
276
|
-
return null;
|
|
277
|
-
if (!ctx.referenced_treasuries_permissions)
|
|
278
|
-
return null;
|
|
279
|
-
if (!ctx.host_service_permission)
|
|
280
|
-
return null;
|
|
281
|
-
for (const allocator of ctx.allocators_config.allocators) {
|
|
282
|
-
for (const s of allocator.sharing) {
|
|
283
|
-
if (!("Entity" in s.who))
|
|
284
|
-
continue;
|
|
285
|
-
const entityAddr = s.who.Entity;
|
|
286
|
-
const treasuryPerm = ctx.referenced_treasuries_permissions[entityAddr];
|
|
287
|
-
if (treasuryPerm && treasuryPerm !== ctx.host_service_permission) {
|
|
288
|
-
return {
|
|
289
|
-
id: "R-A-3-02",
|
|
290
|
-
level: "MEDIUM",
|
|
291
|
-
category: "authority",
|
|
292
|
-
title: "Treasury Permission inconsistent with Service Permission",
|
|
293
|
-
description: `sharing.who=Entity points to Treasury ${entityAddr} whose Permission (${treasuryPerm}) differs from Service Permission (${ctx.host_service_permission}). Two different permission organizations control fund flow, creating potential authority conflicts.`,
|
|
294
|
-
affected_stakeholders: ["owner", "service_provider"],
|
|
295
|
-
scenario: "Treasury owned by different party than Service",
|
|
296
|
-
mitigation: "Create Treasury with the same Permission object as the Service, OR ensure both are owned by the same address.",
|
|
297
|
-
evidence: `treasury=${entityAddr}, treasuryPerm=${treasuryPerm}, servicePerm=${ctx.host_service_permission}`,
|
|
298
|
-
auto_fixable: false,
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return null;
|
|
304
|
-
},
|
|
305
|
-
};
|
|
306
|
-
const R_A_3_03 = {
|
|
307
|
-
id: "R-A-3-03",
|
|
308
|
-
category: "authority",
|
|
309
|
-
trigger: "No ALLOCATION_* builtin permission index — Allocation has no independent access control",
|
|
310
|
-
check: (ctx) => {
|
|
311
|
-
if (ctx.operation_type !== "create")
|
|
312
|
-
return null;
|
|
313
|
-
const isStandalone = ctx.trigger_source === "standalone";
|
|
314
|
-
return {
|
|
315
|
-
id: "R-A-3-03",
|
|
316
|
-
level: "LOW",
|
|
317
|
-
category: "authority",
|
|
318
|
-
title: "Allocation has no builtin permission index (passive-object design)",
|
|
319
|
-
description: isStandalone
|
|
320
|
-
? "BuiltinPermissionIndex has no ALLOCATION_* entries. Allocation's access control is fully delegated to Guard + Passport. In standalone mode (trigger_source=standalone), there is no Service/Arbitration layer to enforce caller authorization — Guard MUST provide sufficient access control (see R-A-3-04). This is the 'passive object' design philosophy, not a defect, but standalone mode shifts full responsibility to the Guard configuration."
|
|
321
|
-
: "BuiltinPermissionIndex has no ALLOCATION_* entries. Allocation's access control is fully delegated to Service (SERVICE_ORDER_ALLOCATOR=313) or Arbitration (ARBITRATION_FEES_ALLOC=365). This is the 'passive object' design philosophy, not a defect. In embedded mode, the host Service/Arbitration provides an additional access-control layer on top of Guard + Passport.",
|
|
322
|
-
affected_stakeholders: ["system"],
|
|
323
|
-
scenario: isStandalone
|
|
324
|
-
? "Standalone Allocation creation (user-initiated, no Service context)"
|
|
325
|
-
: "Embedded Allocation creation (via Service order_allocators or Arbitration fees_alloc)",
|
|
326
|
-
mitigation: isStandalone
|
|
327
|
-
? "For standalone Allocation, ensure Guard binds Signer or enforces time-lock (see R-A-3-04). Document this design choice explicitly."
|
|
328
|
-
: "For embedded Allocation, ensure Service/Arbitration permission configuration is correct. Document this design choice explicitly.",
|
|
329
|
-
evidence: `BuiltinPermissionIndex has no ALLOCATION_* entries; trigger_source=${ctx.trigger_source ?? "unknown"}`,
|
|
330
|
-
auto_fixable: false,
|
|
331
|
-
};
|
|
332
|
-
},
|
|
333
|
-
};
|
|
334
|
-
const R_A_3_04 = {
|
|
335
|
-
id: "R-A-3-04",
|
|
336
|
-
category: "authority",
|
|
337
|
-
trigger: "Standalone Allocation (trigger_source=standalone) with Guard lacking both Signer binding and time-lock",
|
|
338
|
-
check: (ctx) => {
|
|
339
|
-
if (ctx.trigger_source !== "standalone")
|
|
340
|
-
return null;
|
|
341
|
-
if (!ctx.allocators_config)
|
|
342
|
-
return null;
|
|
343
|
-
const weakGuards = [];
|
|
344
|
-
for (const a of ctx.allocators_config.allocators) {
|
|
345
|
-
const signerBound = ctx.guard_signer_bindings?.[a.guard] === true;
|
|
346
|
-
const hasTimeLock = ctx.guard_has_time_lock?.[a.guard] === true;
|
|
347
|
-
if (!signerBound && !hasTimeLock) {
|
|
348
|
-
weakGuards.push(a.guard);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
if (weakGuards.length === 0)
|
|
352
|
-
return null;
|
|
353
|
-
return {
|
|
354
|
-
id: "R-A-3-04",
|
|
355
|
-
level: "HIGH",
|
|
356
|
-
category: "authority",
|
|
357
|
-
title: `Standalone Allocation: ${weakGuards.length} Guard(s) lack Signer binding AND time-lock`,
|
|
358
|
-
description: `Standalone Allocation (trigger_source=standalone) has no Service-layer access control. The following Guard(s) lack both Signer binding (context(Signer)==authorized) and time-lock (context(Clock).timestamp>=unlock): ${weakGuards.join(", ")}. Anyone who passes these Guards can trigger alloc() and receive funds, with no additional authorization layer. This is the most severe standalone-mode risk.`,
|
|
359
|
-
affected_stakeholders: ["owner", "recipient", "system"],
|
|
360
|
-
scenario: "Standalone Allocation created with weak Guard (no Signer binding, no time-lock)",
|
|
361
|
-
mitigation: "Option A (preferred): configure Guard to bind context(Signer)==authorized_address, so only the owner can trigger alloc(). Option B: configure Guard with time-lock (context(Clock).timestamp>=unlock_time) for vesting-style releases. Option C: switch to embedded mode (via Service) to leverage Service-layer access control. Until fixed, this Allocation should not receive funds.",
|
|
362
|
-
evidence: `trigger_source=standalone, weakGuards=${weakGuards.join(",")}`,
|
|
363
|
-
related_guard_risk: "R-C3-06 (Signer binding) / time-lock patterns",
|
|
364
|
-
auto_fixable: false,
|
|
365
|
-
};
|
|
366
|
-
},
|
|
367
|
-
};
|
|
368
|
-
const R_A_4_01 = {
|
|
369
|
-
id: "R-A-4-01",
|
|
370
|
-
category: "lifecycle",
|
|
371
|
-
trigger: "caller-specified guard with no matching Allocator — silent return causes funds to be stuck",
|
|
372
|
-
check: (ctx) => {
|
|
373
|
-
if (!ctx.allocators_config)
|
|
374
|
-
return null;
|
|
375
|
-
if (ctx.allocators_config.allocators.length <= 1)
|
|
376
|
-
return null;
|
|
377
|
-
if (ctx.has_fallback_allocator)
|
|
378
|
-
return null;
|
|
379
|
-
return {
|
|
380
|
-
id: "R-A-4-01",
|
|
381
|
-
level: "CRITICAL",
|
|
382
|
-
category: "lifecycle",
|
|
383
|
-
title: "caller-specified guard with no matching Allocator — silent return causes funds to be stuck",
|
|
384
|
-
description: `Multi-Allocation configuration (${ctx.allocators_config.allocators.length} Allocators) without alternative Allocator. alloc() is driven by the caller explicitly specifying an Allocator via alloc_by_guard: if the guard address does not match any allocators[].guard, alloc() silently returns (no error, no distribution), funds remain stuck in Allocation.balance, and the caller gets no immediate signal. Linked to guard-risk.ts R-X1-05.`,
|
|
385
|
-
affected_stakeholders: ["owner", "service_provider", "system"],
|
|
386
|
-
scenario: "Caller passes a guard address not present in allocators[] (e.g. wrong Guard object, or order state not matching any terminal node)",
|
|
387
|
-
mitigation: "1) The caller should verify alloc_by_guard ∈ allocators[].guard address set before calling alloc(). 2) Provide an alternative Allocator and document the caller's retry strategy. 3) Caller should check balance==0 after alloc() to detect no-match.",
|
|
388
|
-
evidence: `allocators=${ctx.allocators_config.allocators.length}, hasFallback=${ctx.has_fallback_allocator ?? false}`,
|
|
389
|
-
related_guard_risk: "R-X1-05",
|
|
390
|
-
auto_fixable: false,
|
|
391
|
-
};
|
|
392
|
-
},
|
|
393
|
-
};
|
|
394
|
-
const R_A_4_02 = {
|
|
395
|
-
id: "R-A-4-02",
|
|
396
|
-
category: "lifecycle",
|
|
397
|
-
trigger: "Multi-Allocation without mutually exclusive Guard conditions (design clarity issue, not a correctness requirement)",
|
|
398
|
-
check: (ctx) => {
|
|
399
|
-
if (!ctx.allocators_config)
|
|
400
|
-
return null;
|
|
401
|
-
if (ctx.allocators_config.allocators.length <= 1)
|
|
402
|
-
return null;
|
|
403
|
-
if (ctx.guard_conditions_mutually_exclusive)
|
|
404
|
-
return null;
|
|
405
|
-
return {
|
|
406
|
-
id: "R-A-4-02",
|
|
407
|
-
level: "MEDIUM",
|
|
408
|
-
category: "lifecycle",
|
|
409
|
-
title: "Multi-Allocation without mutually exclusive Guard conditions",
|
|
410
|
-
description: `Multi-Allocation (${ctx.allocators_config.allocators.length} Allocators) without verified mutual exclusion. Under caller-specified guard semantics, the caller explicitly selects an Allocator via alloc_by_guard, so there is no correctness problem of "the latter is unreachable"; however, if two Guard conditions can both pass simultaneously and the caller has no explicit selection strategy, the caller may be confused or bind to an unexpected path.`,
|
|
411
|
-
affected_stakeholders: ["owner"],
|
|
412
|
-
scenario: "Two Guard conditions overlap (e.g. amount<1000 and amount<500), caller Passport satisfies both",
|
|
413
|
-
mitigation: "It is recommended that Guard conditions be strictly mutually exclusive (e.g. amount<1000 vs amount>=1000) to avoid caller confusion; alternatively, document explicitly which path the caller should prefer.",
|
|
414
|
-
evidence: `allocators=${ctx.allocators_config.allocators.length}, mutuallyExclusive=${ctx.guard_conditions_mutually_exclusive ?? false}`,
|
|
415
|
-
auto_fixable: false,
|
|
416
|
-
};
|
|
417
|
-
},
|
|
418
|
-
};
|
|
419
|
-
const R_A_4_03 = {
|
|
420
|
-
id: "R-A-4-03",
|
|
421
|
-
category: "lifecycle",
|
|
422
|
-
trigger: "Pure Amount mode without Surplus — residual balance reentrancy",
|
|
423
|
-
check: (ctx) => {
|
|
424
|
-
if (!ctx.allocators_config)
|
|
425
|
-
return null;
|
|
426
|
-
for (let i = 0; i < ctx.allocators_config.allocators.length; i++) {
|
|
427
|
-
const a = ctx.allocators_config.allocators[i];
|
|
428
|
-
const hasOnlyAmount = a.sharing.length > 0 && a.sharing.every(s => s.mode === "Amount");
|
|
429
|
-
if (!hasOnlyAmount)
|
|
430
|
-
continue;
|
|
431
|
-
return {
|
|
432
|
-
id: "R-A-4-03",
|
|
433
|
-
level: "LOW",
|
|
434
|
-
category: "lifecycle",
|
|
435
|
-
title: "Pure Amount mode without Surplus — residual balance reentrancy",
|
|
436
|
-
description: `Allocator ${i} uses pure Amount mode (no Rate, no Surplus). After alloc(), if fix < balance, residual funds remain in Allocation.balance and can be claimed by re-triggering alloc(). Linked to guard-risk.ts reentrancy LOW.`,
|
|
437
|
-
affected_stakeholders: ["owner", "system"],
|
|
438
|
-
scenario: "Pure Amount mode leaves residual balance",
|
|
439
|
-
mitigation: "1) Preferred: add a Surplus sharing to absorb remainder. 2) Or use Rate mode. 3) Or add anti-reentrancy Guard check: logic_not(query('order.allocation some', object=order)).",
|
|
440
|
-
evidence: `allocator[${i}].mode=pure-amount`,
|
|
441
|
-
related_guard_risk: "reentrancy LOW",
|
|
442
|
-
auto_fixable: false,
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
return null;
|
|
446
|
-
},
|
|
447
|
-
};
|
|
448
|
-
const R_A_5_01 = {
|
|
449
|
-
id: "R-A-5-01",
|
|
450
|
-
category: "cross_object",
|
|
451
|
-
trigger: "Order already has an Allocation bound (1:1 constraint)",
|
|
452
|
-
check: (ctx) => {
|
|
453
|
-
if (!ctx.order_already_has_allocation)
|
|
454
|
-
return null;
|
|
455
|
-
return {
|
|
456
|
-
id: "R-A-5-01",
|
|
457
|
-
level: "HIGH",
|
|
458
|
-
category: "cross_object",
|
|
459
|
-
title: "Order already has an Allocation — 1:1 constraint violation",
|
|
460
|
-
description: `Order ${ctx.bound_order ?? "(unknown)"} already has an Allocation bound. Move layer will abort with E_ALLOCATION_ALREADY_SPECIFIED (order.move) when attempting to bind a second Allocation.`,
|
|
461
|
-
affected_stakeholders: ["owner", "service_provider"],
|
|
462
|
-
scenario: "Attempting to bind a second Allocation to the same Order",
|
|
463
|
-
mitigation: "Use the existing Allocation, or unbind it first (if supported), or create a new Order.",
|
|
464
|
-
evidence: `bound_order=${ctx.bound_order ?? "unknown"}, alreadyHasAllocation=${ctx.order_already_has_allocation}`,
|
|
465
|
-
related_move_error: "E_ALLOCATION_ALREADY_SPECIFIED (order.move)",
|
|
466
|
-
auto_fixable: false,
|
|
467
|
-
};
|
|
468
|
-
},
|
|
469
|
-
};
|
|
470
|
-
const R_A_5_02 = {
|
|
471
|
-
id: "R-A-5-02",
|
|
472
|
-
category: "cross_object",
|
|
473
|
-
trigger: "payment_info missing for alloc() — ENO_PAYMENT_INFO",
|
|
474
|
-
check: (ctx) => {
|
|
475
|
-
if (ctx.has_payment_info)
|
|
476
|
-
return null;
|
|
477
|
-
if (ctx.operation_type !== "alloc_by_guard")
|
|
478
|
-
return null;
|
|
479
|
-
return {
|
|
480
|
-
id: "R-A-5-02",
|
|
481
|
-
level: "HIGH",
|
|
482
|
-
category: "cross_object",
|
|
483
|
-
title: "payment_info missing — alloc() will abort with ENO_PAYMENT_INFO",
|
|
484
|
-
description: "Allocation has no payment_info set. Move alloc() requires payment_info.is_some() at step 1 (pre_check). The entire alloc() transaction will revert, funds remain in Allocation.",
|
|
485
|
-
affected_stakeholders: ["owner"],
|
|
486
|
-
scenario: "Triggering alloc() before setting payment_info",
|
|
487
|
-
mitigation: "Ensure payment_info is set during Allocation creation (CallAllocation_Create requires payment_info field).",
|
|
488
|
-
evidence: `has_payment_info=${ctx.has_payment_info ?? false}`,
|
|
489
|
-
related_move_error: "ENO_PAYMENT_INFO (9)",
|
|
490
|
-
auto_fixable: false,
|
|
491
|
-
};
|
|
492
|
-
},
|
|
493
|
-
};
|
|
494
|
-
const R_A_5_03 = {
|
|
495
|
-
id: "R-A-5-03",
|
|
496
|
-
category: "cross_object",
|
|
497
|
-
trigger: "MAX_ALLOCATOR_COUNT not synced to onchain-constants.ts",
|
|
498
|
-
check: (_ctx) => {
|
|
499
|
-
return {
|
|
500
|
-
id: "R-A-5-03",
|
|
501
|
-
level: "LOW",
|
|
502
|
-
category: "cross_object",
|
|
503
|
-
title: "MAX_ALLOCATOR_COUNT not synced to onchain-constants.ts",
|
|
504
|
-
description: `Move layer allocation.move:16 defines MAX_ALLOCATOR_COUNT=${MAX_ALLOCATOR_COUNT}, but onchain-constants.ts does NOT export this constant. SDK allocation.ts:318 defines it locally, creating a double-definition risk. MCP knowledge imports the local definition.`,
|
|
505
|
-
affected_stakeholders: ["system"],
|
|
506
|
-
scenario: "Constant sync drift between Move / SDK / MCP",
|
|
507
|
-
mitigation: "1) Add MAX_ALLOCATOR_COUNT=100 to onchain-constants.ts. 2) Update SDK allocation.ts to import from onchain-constants.js. 3) Delete local definition.",
|
|
508
|
-
evidence: `MAX_ALLOCATOR_COUNT=${MAX_ALLOCATOR_COUNT} (local), not in onchain-constants.ts`,
|
|
509
|
-
auto_fixable: true,
|
|
510
|
-
};
|
|
511
|
-
},
|
|
512
|
-
};
|
|
513
|
-
const ALL_RULES = [
|
|
514
|
-
R_A_1_01, R_A_1_02, R_A_1_03,
|
|
515
|
-
R_A_2_01, R_A_2_02, R_A_2_03,
|
|
516
|
-
R_A_3_01, R_A_3_02, R_A_3_03, R_A_3_04,
|
|
517
|
-
R_A_4_01, R_A_4_02, R_A_4_03,
|
|
518
|
-
R_A_5_01, R_A_5_02, R_A_5_03,
|
|
519
|
-
];
|
|
520
|
-
export const ALLOCATION_RISK_VERSION = "1.0.0";
|
|
521
|
-
export function getAllRiskRules() {
|
|
522
|
-
return [...ALL_RULES];
|
|
523
|
-
}
|
|
524
|
-
export function getRiskRulesCount() {
|
|
525
|
-
return ALL_RULES.length;
|
|
526
|
-
}
|
|
527
|
-
export function getRiskRulesByCategory(category) {
|
|
528
|
-
return ALL_RULES.filter(r => r.category === category);
|
|
529
|
-
}
|
|
530
|
-
export function assessAllocationRisks(ctx) {
|
|
531
|
-
const risks = [];
|
|
532
|
-
for (const rule of ALL_RULES) {
|
|
533
|
-
const r = rule.check(ctx);
|
|
534
|
-
if (r)
|
|
535
|
-
risks.push(r);
|
|
536
|
-
}
|
|
537
|
-
const overall = risks.length === 0
|
|
538
|
-
? "LOW"
|
|
539
|
-
: risks.some(r => r.level === "CRITICAL") ? "CRITICAL"
|
|
540
|
-
: risks.some(r => r.level === "HIGH") ? "HIGH"
|
|
541
|
-
: risks.some(r => r.level === "MEDIUM") ? "MEDIUM"
|
|
542
|
-
: "LOW";
|
|
543
|
-
const byCategory = {};
|
|
544
|
-
const byLevel = {};
|
|
545
|
-
for (const r of risks) {
|
|
546
|
-
byCategory[r.category] = (byCategory[r.category] ?? 0) + 1;
|
|
547
|
-
byLevel[r.level] = (byLevel[r.level] ?? 0) + 1;
|
|
548
|
-
}
|
|
549
|
-
const advice = {};
|
|
550
|
-
for (const r of risks) {
|
|
551
|
-
for (const s of r.affected_stakeholders) {
|
|
552
|
-
if (!advice[s])
|
|
553
|
-
advice[s] = [];
|
|
554
|
-
advice[s].push(`${r.id}: ${r.mitigation}`);
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
return {
|
|
558
|
-
summary: `Assessed ${risks.length} risk(s) across ${Object.keys(byCategory).length} categories`,
|
|
559
|
-
risks,
|
|
560
|
-
overall_risk: overall,
|
|
561
|
-
risks_by_category: byCategory,
|
|
562
|
-
risks_by_level: byLevel,
|
|
563
|
-
stakeholder_advice: advice,
|
|
564
|
-
needs_human_review: risks.some(r => r.level === "CRITICAL" || r.level === "HIGH"),
|
|
565
|
-
blocks_publish: risks.some(r => r.level === "CRITICAL"),
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
export { ALLOCATION_ERROR_CODES };
|
|
1
|
+
import{MAX_ALLOCATOR_COUNT,RATE_TOTAL_FULL,ALLOCATION_ERROR_CODES}from'./allocation-ledger.js';const R_A_1_01={'id':'R-A-1-01','category':'structural','trigger':'allocators\x20is\x20empty\x20or\x20sharing\x20arrays\x20are\x20empty','check':a=>{if(!a['allocators_config'])return null;const b=a['allocators_config']['allocators'];if(b['length']===0x0)return{'id':'R-A-1-01','level':'CRITICAL','category':'structural','title':'Empty\x20allocators\x20—\x20funds\x20will\x20be\x20permanently\x20locked','description':'Allocation\x20has\x20empty\x20allocators.allocators.\x20Service\x20publish\x20with\x20empty\x20order_allocators\x20causes\x20order\x20funds\x20to\x20be\x20permanently\x20locked\x20in\x20the\x20Allocation\x20object.','affected_stakeholders':['owner','service_provider','system'],'scenario':'Service\x20published\x20without\x20configuring\x20any\x20Allocator','mitigation':'Configure\x20at\x20least\x201\x20Allocator.\x20If\x20no\x20distribution\x20is\x20needed\x20yet,\x20use\x20a\x20single\x20Allocator\x20with\x20Rate=10000\x20to\x20the\x20merchant\x20address.','evidence':'allocators.length=0','related_move_error':'EALLOCATORS_EMPTY\x20(8)\x20/\x20ENO_ALLOCATOR\x20(3)','auto_fixable':![]};for(let c=0x0;c<b['length'];c++){if(b[c]['sharing']['length']===0x0)return{'id':'R-A-1-01','level':'CRITICAL','category':'structural','title':'Allocator\x20'+c+'\x20has\x20empty\x20sharing\x20—\x20will\x20never\x20distribute','description':'Allocator\x20at\x20index\x20'+c+'\x20(guard='+b[c]['guard']+')\x20has\x20empty\x20sharing\x20array.\x20Even\x20if\x20its\x20Guard\x20passes\x20verification,\x20no\x20funds\x20will\x20be\x20distributed.','affected_stakeholders':['owner','recipient'],'scenario':'Allocator\x20with\x20empty\x20sharing\x20vector','mitigation':'Add\x20at\x20least\x201\x20sharing\x20entry\x20to\x20Allocator\x20'+c,'evidence':'allocator['+c+'].sharing.length=0','related_move_error':'ENO_ALLOCATOR\x20(3)','auto_fixable':![]};}return null;}},R_A_1_02={'id':'R-A-1-02','category':'structural','trigger':'Pure\x20Rate\x20mode\x20sum\x20!=\x2010000\x20or\x20Rate+Surplus\x20sum\x20>\x2010000','check':b=>{if(!b['allocators_config'])return null;for(let c=0x0;c<b['allocators_config']['allocators']['length'];c++){const d=b['allocators_config']['allocators'][c],e=d['sharing']['filter'](g=>g['mode']==='Rate')['reduce']((g,h)=>g+Number(h['sharing']),0x0),f=d['sharing']['some'](g=>g['mode']==='Surplus');if(!f&&e>0x0&&e!==RATE_TOTAL_FULL)return{'id':'R-A-1-02','level':'HIGH','category':'structural','title':'Pure\x20Rate\x20mode\x20sum\x20'+e+'\x20!=\x20'+RATE_TOTAL_FULL,'description':'Allocator\x20'+c+'\x20(guard='+d['guard']+')\x20uses\x20pure\x20Rate\x20mode\x20(no\x20Surplus),\x20but\x20sum(rates)='+e+'\x20≠\x20'+RATE_TOTAL_FULL+'.\x20Funds\x20will\x20be\x20permanently\x20locked\x20(if\x20sum<10000)\x20or\x20Move\x20will\x20abort\x20with\x20ERATE_NOT_10000\x20(if\x20sum\x20!=\x2010000\x20exactly).','affected_stakeholders':['owner','recipient'],'scenario':'Misconfigured\x20rate\x20proportions','mitigation':'Adjust\x20sharing.sharing\x20values\x20so\x20sum(rates)='+RATE_TOTAL_FULL+',\x20OR\x20add\x201\x20Surplus\x20sharing\x20to\x20absorb\x20the\x20remainder.','evidence':'rateSum='+e+',\x20expected='+RATE_TOTAL_FULL,'related_move_error':'ERATE_NOT_10000\x20(4)','auto_fixable':!![]};if(f&&e>RATE_TOTAL_FULL)return{'id':'R-A-1-02','level':'HIGH','category':'structural','title':'Rate\x20+\x20Surplus\x20sum\x20'+e+'\x20>\x20'+RATE_TOTAL_FULL,'description':'Allocator\x20'+c+'\x20(guard='+d['guard']+')\x20uses\x20Rate+Surplus\x20mode,\x20but\x20sum(rates)='+e+'\x20>\x20'+RATE_TOTAL_FULL+'.\x20Move\x20will\x20abort\x20with\x20ERATE_EXCEEDS_10000.','affected_stakeholders':['owner'],'scenario':'Rate\x20percentages\x20exceed\x20100%\x20before\x20Surplus','mitigation':'Reduce\x20sum(rates)\x20to\x20≤\x20'+RATE_TOTAL_FULL+'.','evidence':'rateSum='+e+',\x20max='+RATE_TOTAL_FULL,'related_move_error':'ERATE_EXCEEDS_10000\x20(6)','auto_fixable':!![]};}return null;}},R_A_1_03={'id':'R-A-1-03','category':'structural','trigger':'Multiple\x20Surplus\x20sharing\x20in\x20one\x20Allocator,\x20or\x20Amount\x20sum\x20violates\x20threshold/max','check':b=>{if(!b['allocators_config'])return null;for(let c=0x0;c<b['allocators_config']['allocators']['length'];c++){const d=b['allocators_config']['allocators'][c],e=d['sharing']['filter'](h=>h['mode']==='Surplus')['length'];if(e>0x1)return{'id':'R-A-1-03','level':'MEDIUM','category':'structural','title':'Allocator\x20'+c+'\x20has\x20'+e+'\x20Surplus\x20sharing\x20—\x20at\x20most\x201\x20allowed','description':'Allocator\x20'+c+'\x20(guard='+d['guard']+')\x20has\x20'+e+'\x20Surplus\x20sharing\x20entries.\x20Move\x20will\x20abort\x20with\x20EMULTIPLE_SURPLUS\x20at\x20alloc()\x20time.','affected_stakeholders':['owner'],'scenario':'Multiple\x20Surplus\x20entries\x20in\x20one\x20Allocator','mitigation':'Keep\x20at\x20most\x201\x20Surplus\x20per\x20Allocator.\x20Use\x20Rate\x20mode\x20for\x20multi-party\x20remainder\x20distribution.','evidence':'surplusCount='+e,'related_move_error':'EMULTIPLE_SURPLUS\x20(5)','auto_fixable':!![]};const f=d['sharing']['filter'](h=>h['mode']==='Amount')['reduce']((h,j)=>h+Number(j['sharing']),0x0),g=Number(b['allocators_config']['threshold']);if(f>0x0&&f<g)return{'id':'R-A-1-03','level':'HIGH','category':'structural','title':'Amount\x20sum\x20'+f+'\x20<\x20threshold\x20'+g,'description':'Allocator\x20'+c+'\x20pure\x20Amount\x20mode\x20fix='+f+'\x20<\x20threshold='+g+'.\x20Move\x20will\x20abort\x20with\x20EAMOUNT_BELOW_THRESHOLD\x20at\x20allocator_add\x20time.','affected_stakeholders':['owner'],'scenario':'Amount\x20sum\x20insufficient\x20to\x20trigger\x20alloc','mitigation':'Either\x20lower\x20threshold\x20to\x20<=\x20fix,\x20or\x20increase\x20Amount\x20sharing\x20values.','evidence':'fix='+f+',\x20threshold='+g,'related_move_error':'EAMOUNT_BELOW_THRESHOLD\x20(12)','auto_fixable':![]};if(d['max']!=null&&f>Number(d['max']))return{'id':'R-A-1-03','level':'MEDIUM','category':'structural','title':'Amount\x20sum\x20'+f+'\x20>\x20max\x20'+Number(d['max']),'description':'Allocator\x20'+c+'\x20Amount\x20sum\x20exceeds\x20max.\x20Move\x20will\x20abort\x20with\x20EAMOUNT_EXCEEDS_MAX.','affected_stakeholders':['owner'],'scenario':'Amount\x20sum\x20exceeds\x20max\x20cap','mitigation':'Increase\x20max\x20or\x20reduce\x20Amount\x20sharing\x20values.','evidence':'fix='+f+',\x20max='+Number(d['max']),'related_move_error':'EAMOUNT_EXCEEDS_MAX\x20(13)','auto_fixable':!![]};}return null;}},R_A_2_01={'id':'R-A-2-01','category':'semantic','trigger':'sharing.who=Signer\x20without\x20Guard\x20Signer\x20binding\x20—\x20fund\x20theft\x20risk','check':b=>{if(!b['allocators_config'])return null;for(let c=0x0;c<b['allocators_config']['allocators']['length'];c++){const d=b['allocators_config']['allocators'][c],e=d['sharing']['some'](g=>'Signer'in g['who']);if(!e)continue;const f=b['guard_signer_bindings']?.[d['guard']]===!![];if(!f)return{'id':'R-A-2-01','level':'CRITICAL','category':'semantic','title':'sharing.who=Signer\x20without\x20Guard\x20Signer\x20binding\x20—\x20fund\x20theft\x20risk','description':'Allocator\x20'+c+'\x20(guard='+d['guard']+')\x20has\x20sharing.who=Signer,\x20but\x20the\x20Guard\x20does\x20not\x20bind\x20context(Signer)==authorized.\x20Anyone\x20who\x20passes\x20the\x20Guard\x20can\x20steal\x20100%\x20of\x20funds.\x20This\x20is\x20the\x20most\x20severe\x20Allocation\x20risk\x20(linked\x20to\x20guard-risk.ts\x20R-C3-06).','affected_stakeholders':['owner','recipient','service_provider'],'scenario':'Signer\x20recipient\x20without\x20Guard\x20Signer\x20authentication','mitigation':'Option\x20A\x20(preferred):\x20change\x20sharing.who\x20to\x20Entity\x20(Treasury\x20or\x20fixed\x20address).\x20Option\x20B:\x20add\x20Signer-binding\x20check\x20to\x20the\x20Guard\x20(context(Signer)==authorized_address).','evidence':'guard='+d['guard']+',\x20guardSignerBound='+f,'related_guard_risk':'R-C3-06','auto_fixable':![]};}return null;}},R_A_2_02={'id':'R-A-2-02','category':'semantic','trigger':'sharing.who=GuardIdentifier\x20but\x20Passport\x20table\x20entry\x20is\x20not\x20address\x20type','check':b=>{if(!b['allocators_config'])return null;if(!b['passport_identifier_types'])return null;for(let c=0x0;c<b['allocators_config']['allocators']['length'];c++){const d=b['allocators_config']['allocators'][c],e=d['sharing']['find'](h=>'GuardIdentifier'in h['who']);if(!e)continue;const f=e['who']['GuardIdentifier'],g=b['passport_identifier_types'][f];if(g!==undefined&&g!=='address')return{'id':'R-A-2-02','level':'MEDIUM','category':'semantic','title':'GuardIdentifier\x20'+f+'\x20resolves\x20to\x20non-address\x20type\x20('+g+')','description':'Allocator\x20'+c+'\x20uses\x20sharing.who=GuardIdentifier('+f+'),\x20but\x20Passport\x20table['+f+']\x20is\x20of\x20type\x20'+g+',\x20not\x20address.\x20Move\x20will\x20abort\x20with\x20ERECIPIENT_IDENTIFIER_NOT_ADDRESS\x20at\x20alloc()\x20time.','affected_stakeholders':['recipient'],'scenario':'Passport\x20table\x20entry\x20type\x20mismatch','mitigation':'Ensure\x20Passport\x20table['+f+']\x20is\x20address-typed,\x20OR\x20use\x20sharing.who=Entity\x20with\x20a\x20static\x20address.','evidence':'identifier='+f+',\x20type='+g,'related_move_error':'ERECIPIENT_IDENTIFIER_NOT_ADDRESS\x20(1)','auto_fixable':![]};}return null;}},R_A_2_03={'id':'R-A-2-03','category':'semantic','trigger':'Duplicate\x20Guard\x20addresses\x20in\x20allocators\x20(alloc_by_guard\x20address\x20match\x20only\x20hits\x20the\x20first\x20one)','check':a=>{if(!a['allocators_config'])return null;const b=a['allocators_config']['allocators']['map'](d=>d['guard']),c=new Set(b);if(c['size']!==b['length']){const d=b['filter']((e,f)=>b['indexOf'](e)!==f);return{'id':'R-A-2-03','level':'MEDIUM','category':'semantic','title':'Duplicate\x20Guard\x20addresses\x20in\x20allocators','description':'Multiple\x20Allocators\x20reference\x20the\x20same\x20Guard\x20object:\x20'+d['join'](',\x20')+'.\x20alloc_by_guard\x20locates\x20the\x20Allocator\x20by\x20iterating\x20guard\x20addresses;\x20duplicate\x20addresses\x20only\x20match\x20the\x20first\x20one,\x20so\x20subsequent\x20duplicate\x20Allocators\x20are\x20unreachable\x20(dead\x20code).','affected_stakeholders':['owner','allocator'],'scenario':'Reusing\x20same\x20Guard\x20object\x20across\x20multiple\x20Allocators','mitigation':'Create\x20independent\x20Guard\x20objects\x20for\x20each\x20Allocator\x20(they\x20may\x20share\x20root/table\x20but\x20must\x20differ\x20in\x20description).','evidence':'total='+b['length']+',\x20unique='+c['size']+',\x20dupes='+d['join'](','),'auto_fixable':!![]};}return null;}},R_A_3_01={'id':'R-A-3-01','category':'authority','trigger':'Service\x20already\x20published\x20—\x20order_allocators\x20is\x20immutable','check':a=>{if(!a['host_service_published'])return null;return{'id':'R-A-3-01','level':'HIGH','category':'authority','title':'order_allocators\x20immutable\x20after\x20Service\x20publish','description':'Service\x20is\x20already\x20published.\x20order_allocators\x20field\x20is\x20now\x20immutable\x20(safety-rules.ts:170-174).\x20Any\x20configuration\x20error\x20(wrong\x20Guard,\x20wrong\x20sharing\x20proportion,\x20wrong\x20Entity\x20address)\x20will\x20affect\x20ALL\x20subsequent\x20orders\x20and\x20cannot\x20be\x20fixed\x20without\x20creating\x20a\x20new\x20Service.','affected_stakeholders':['owner','service_provider'],'scenario':'Attempting\x20to\x20modify\x20order_allocators\x20after\x20Service\x20publish','mitigation':'1)\x20Verify\x20the\x20configuration\x20is\x20correct\x20before\x20publish.\x202)\x20Use\x20deploy-scanner\x20pre-publish\x20validation.\x203)\x20If\x20already\x20published\x20with\x20errors,\x20create\x20a\x20new\x20Service\x20to\x20replace.','evidence':'host_service_published='+a['host_service_published'],'auto_fixable':![]};}},R_A_3_02={'id':'R-A-3-02','category':'authority','trigger':'Treasury\x20Permission\x20inconsistent\x20with\x20Service\x20Permission','check':a=>{if(!a['allocators_config'])return null;if(!a['referenced_treasuries_permissions'])return null;if(!a['host_service_permission'])return null;for(const b of a['allocators_config']['allocators']){for(const c of b['sharing']){if(!('Entity'in c['who']))continue;const d=c['who']['Entity'],e=a['referenced_treasuries_permissions'][d];if(e&&e!==a['host_service_permission'])return{'id':'R-A-3-02','level':'MEDIUM','category':'authority','title':'Treasury\x20Permission\x20inconsistent\x20with\x20Service\x20Permission','description':'sharing.who=Entity\x20points\x20to\x20Treasury\x20'+d+'\x20whose\x20Permission\x20('+e+')\x20differs\x20from\x20Service\x20Permission\x20('+a['host_service_permission']+').\x20Two\x20different\x20permission\x20organizations\x20control\x20fund\x20flow,\x20creating\x20potential\x20authority\x20conflicts.','affected_stakeholders':['owner','service_provider'],'scenario':'Treasury\x20owned\x20by\x20different\x20party\x20than\x20Service','mitigation':'Create\x20Treasury\x20with\x20the\x20same\x20Permission\x20object\x20as\x20the\x20Service,\x20OR\x20ensure\x20both\x20are\x20owned\x20by\x20the\x20same\x20address.','evidence':'treasury='+d+',\x20treasuryPerm='+e+',\x20servicePerm='+a['host_service_permission'],'auto_fixable':![]};}}return null;}},R_A_3_03={'id':'R-A-3-03','category':'authority','trigger':'No\x20ALLOCATION_*\x20builtin\x20permission\x20index\x20—\x20Allocation\x20has\x20no\x20independent\x20access\x20control','check':a=>{if(a['operation_type']!=='create')return null;const b=a['trigger_source']==='standalone';return{'id':'R-A-3-03','level':'LOW','category':'authority','title':'Allocation\x20has\x20no\x20builtin\x20permission\x20index\x20(passive-object\x20design)','description':b?'BuiltinPermissionIndex\x20has\x20no\x20ALLOCATION_*\x20entries.\x20Allocation\x27s\x20access\x20control\x20is\x20fully\x20delegated\x20to\x20Guard\x20+\x20Passport.\x20In\x20standalone\x20mode\x20(trigger_source=standalone),\x20there\x20is\x20no\x20Service/Arbitration\x20layer\x20to\x20enforce\x20caller\x20authorization\x20—\x20Guard\x20MUST\x20provide\x20sufficient\x20access\x20control\x20(see\x20R-A-3-04).\x20This\x20is\x20the\x20\x27passive\x20object\x27\x20design\x20philosophy,\x20not\x20a\x20defect,\x20but\x20standalone\x20mode\x20shifts\x20full\x20responsibility\x20to\x20the\x20Guard\x20configuration.':'BuiltinPermissionIndex\x20has\x20no\x20ALLOCATION_*\x20entries.\x20Allocation\x27s\x20access\x20control\x20is\x20fully\x20delegated\x20to\x20Service\x20(SERVICE_ORDER_ALLOCATOR=313)\x20or\x20Arbitration\x20(ARBITRATION_FEES_ALLOC=365).\x20This\x20is\x20the\x20\x27passive\x20object\x27\x20design\x20philosophy,\x20not\x20a\x20defect.\x20In\x20embedded\x20mode,\x20the\x20host\x20Service/Arbitration\x20provides\x20an\x20additional\x20access-control\x20layer\x20on\x20top\x20of\x20Guard\x20+\x20Passport.','affected_stakeholders':['system'],'scenario':b?'Standalone\x20Allocation\x20creation\x20(user-initiated,\x20no\x20Service\x20context)':'Embedded\x20Allocation\x20creation\x20(via\x20Service\x20order_allocators\x20or\x20Arbitration\x20fees_alloc)','mitigation':b?'For\x20standalone\x20Allocation,\x20ensure\x20Guard\x20binds\x20Signer\x20or\x20enforces\x20time-lock\x20(see\x20R-A-3-04).\x20Document\x20this\x20design\x20choice\x20explicitly.':'For\x20embedded\x20Allocation,\x20ensure\x20Service/Arbitration\x20permission\x20configuration\x20is\x20correct.\x20Document\x20this\x20design\x20choice\x20explicitly.','evidence':'BuiltinPermissionIndex\x20has\x20no\x20ALLOCATION_*\x20entries;\x20trigger_source='+(a['trigger_source']??'unknown'),'auto_fixable':![]};}},R_A_3_04={'id':'R-A-3-04','category':'authority','trigger':'Standalone\x20Allocation\x20(trigger_source=standalone)\x20with\x20Guard\x20lacking\x20both\x20Signer\x20binding\x20and\x20time-lock','check':b=>{if(b['trigger_source']!=='standalone')return null;if(!b['allocators_config'])return null;const c=[];for(const d of b['allocators_config']['allocators']){const e=b['guard_signer_bindings']?.[d['guard']]===!![],f=b['guard_has_time_lock']?.[d['guard']]===!![];!e&&!f&&c['push'](d['guard']);}if(c['length']===0x0)return null;return{'id':'R-A-3-04','level':'HIGH','category':'authority','title':'Standalone\x20Allocation:\x20'+c['length']+'\x20Guard(s)\x20lack\x20Signer\x20binding\x20AND\x20time-lock','description':'Standalone\x20Allocation\x20(trigger_source=standalone)\x20has\x20no\x20Service-layer\x20access\x20control.\x20The\x20following\x20Guard(s)\x20lack\x20both\x20Signer\x20binding\x20(context(Signer)==authorized)\x20and\x20time-lock\x20(context(Clock).timestamp>=unlock):\x20'+c['join'](',\x20')+'.\x20Anyone\x20who\x20passes\x20these\x20Guards\x20can\x20trigger\x20alloc()\x20and\x20receive\x20funds,\x20with\x20no\x20additional\x20authorization\x20layer.\x20This\x20is\x20the\x20most\x20severe\x20standalone-mode\x20risk.','affected_stakeholders':['owner','recipient','system'],'scenario':'Standalone\x20Allocation\x20created\x20with\x20weak\x20Guard\x20(no\x20Signer\x20binding,\x20no\x20time-lock)','mitigation':'Option\x20A\x20(preferred):\x20configure\x20Guard\x20to\x20bind\x20context(Signer)==authorized_address,\x20so\x20only\x20the\x20owner\x20can\x20trigger\x20alloc().\x20Option\x20B:\x20configure\x20Guard\x20with\x20time-lock\x20(context(Clock).timestamp>=unlock_time)\x20for\x20vesting-style\x20releases.\x20Option\x20C:\x20switch\x20to\x20embedded\x20mode\x20(via\x20Service)\x20to\x20leverage\x20Service-layer\x20access\x20control.\x20Until\x20fixed,\x20this\x20Allocation\x20should\x20not\x20receive\x20funds.','evidence':'trigger_source=standalone,\x20weakGuards='+c['join'](','),'related_guard_risk':'R-C3-06\x20(Signer\x20binding)\x20/\x20time-lock\x20patterns','auto_fixable':![]};}},R_A_4_01={'id':'R-A-4-01','category':'lifecycle','trigger':'caller-specified\x20guard\x20with\x20no\x20matching\x20Allocator\x20—\x20silent\x20return\x20causes\x20funds\x20to\x20be\x20stuck','check':a=>{if(!a['allocators_config'])return null;if(a['allocators_config']['allocators']['length']<=0x1)return null;if(a['has_fallback_allocator'])return null;return{'id':'R-A-4-01','level':'CRITICAL','category':'lifecycle','title':'caller-specified\x20guard\x20with\x20no\x20matching\x20Allocator\x20—\x20silent\x20return\x20causes\x20funds\x20to\x20be\x20stuck','description':'Multi-Allocation\x20configuration\x20('+a['allocators_config']['allocators']['length']+'\x20Allocators)\x20without\x20alternative\x20Allocator.\x20alloc()\x20is\x20driven\x20by\x20the\x20caller\x20explicitly\x20specifying\x20an\x20Allocator\x20via\x20alloc_by_guard:\x20if\x20the\x20guard\x20address\x20does\x20not\x20match\x20any\x20allocators[].guard,\x20alloc()\x20silently\x20returns\x20(no\x20error,\x20no\x20distribution),\x20funds\x20remain\x20stuck\x20in\x20Allocation.balance,\x20and\x20the\x20caller\x20gets\x20no\x20immediate\x20signal.\x20Linked\x20to\x20guard-risk.ts\x20R-X1-05.','affected_stakeholders':['owner','service_provider','system'],'scenario':'Caller\x20passes\x20a\x20guard\x20address\x20not\x20present\x20in\x20allocators[]\x20(e.g.\x20wrong\x20Guard\x20object,\x20or\x20order\x20state\x20not\x20matching\x20any\x20terminal\x20node)','mitigation':'1)\x20The\x20caller\x20should\x20verify\x20alloc_by_guard\x20∈\x20allocators[].guard\x20address\x20set\x20before\x20calling\x20alloc().\x202)\x20Provide\x20an\x20alternative\x20Allocator\x20and\x20document\x20the\x20caller\x27s\x20retry\x20strategy.\x203)\x20Caller\x20should\x20check\x20balance==0\x20after\x20alloc()\x20to\x20detect\x20no-match.','evidence':'allocators='+a['allocators_config']['allocators']['length']+',\x20hasFallback='+(a['has_fallback_allocator']??![]),'related_guard_risk':'R-X1-05','auto_fixable':![]};}},R_A_4_02={'id':'R-A-4-02','category':'lifecycle','trigger':'Multi-Allocation\x20without\x20mutually\x20exclusive\x20Guard\x20conditions\x20(design\x20clarity\x20issue,\x20not\x20a\x20correctness\x20requirement)','check':a=>{if(!a['allocators_config'])return null;if(a['allocators_config']['allocators']['length']<=0x1)return null;if(a['guard_conditions_mutually_exclusive'])return null;return{'id':'R-A-4-02','level':'MEDIUM','category':'lifecycle','title':'Multi-Allocation\x20without\x20mutually\x20exclusive\x20Guard\x20conditions','description':'Multi-Allocation\x20('+a['allocators_config']['allocators']['length']+'\x20Allocators)\x20without\x20verified\x20mutual\x20exclusion.\x20Under\x20caller-specified\x20guard\x20semantics,\x20the\x20caller\x20explicitly\x20selects\x20an\x20Allocator\x20via\x20alloc_by_guard,\x20so\x20there\x20is\x20no\x20correctness\x20problem\x20of\x20\x22the\x20latter\x20is\x20unreachable\x22;\x20however,\x20if\x20two\x20Guard\x20conditions\x20can\x20both\x20pass\x20simultaneously\x20and\x20the\x20caller\x20has\x20no\x20explicit\x20selection\x20strategy,\x20the\x20caller\x20may\x20be\x20confused\x20or\x20bind\x20to\x20an\x20unexpected\x20path.','affected_stakeholders':['owner'],'scenario':'Two\x20Guard\x20conditions\x20overlap\x20(e.g.\x20amount<1000\x20and\x20amount<500),\x20caller\x20Passport\x20satisfies\x20both','mitigation':'It\x20is\x20recommended\x20that\x20Guard\x20conditions\x20be\x20strictly\x20mutually\x20exclusive\x20(e.g.\x20amount<1000\x20vs\x20amount>=1000)\x20to\x20avoid\x20caller\x20confusion;\x20alternatively,\x20document\x20explicitly\x20which\x20path\x20the\x20caller\x20should\x20prefer.','evidence':'allocators='+a['allocators_config']['allocators']['length']+',\x20mutuallyExclusive='+(a['guard_conditions_mutually_exclusive']??![]),'auto_fixable':![]};}},R_A_4_03={'id':'R-A-4-03','category':'lifecycle','trigger':'Pure\x20Amount\x20mode\x20without\x20Surplus\x20—\x20residual\x20balance\x20reentrancy','check':b=>{if(!b['allocators_config'])return null;for(let c=0x0;c<b['allocators_config']['allocators']['length'];c++){const d=b['allocators_config']['allocators'][c],e=d['sharing']['length']>0x0&&d['sharing']['every'](f=>f['mode']==='Amount');if(!e)continue;return{'id':'R-A-4-03','level':'LOW','category':'lifecycle','title':'Pure\x20Amount\x20mode\x20without\x20Surplus\x20—\x20residual\x20balance\x20reentrancy','description':'Allocator\x20'+c+'\x20uses\x20pure\x20Amount\x20mode\x20(no\x20Rate,\x20no\x20Surplus).\x20After\x20alloc(),\x20if\x20fix\x20<\x20balance,\x20residual\x20funds\x20remain\x20in\x20Allocation.balance\x20and\x20can\x20be\x20claimed\x20by\x20re-triggering\x20alloc().\x20Linked\x20to\x20guard-risk.ts\x20reentrancy\x20LOW.','affected_stakeholders':['owner','system'],'scenario':'Pure\x20Amount\x20mode\x20leaves\x20residual\x20balance','mitigation':'1)\x20Preferred:\x20add\x20a\x20Surplus\x20sharing\x20to\x20absorb\x20remainder.\x202)\x20Or\x20use\x20Rate\x20mode.\x203)\x20Or\x20add\x20anti-reentrancy\x20Guard\x20check:\x20logic_not(query(\x27order.allocation\x20some\x27,\x20object=order)).','evidence':'allocator['+c+'].mode=pure-amount','related_guard_risk':'reentrancy\x20LOW','auto_fixable':![]};}return null;}},R_A_5_01={'id':'R-A-5-01','category':'cross_object','trigger':'Order\x20already\x20has\x20an\x20Allocation\x20bound\x20(1:1\x20constraint)','check':a=>{if(!a['order_already_has_allocation'])return null;return{'id':'R-A-5-01','level':'HIGH','category':'cross_object','title':'Order\x20already\x20has\x20an\x20Allocation\x20—\x201:1\x20constraint\x20violation','description':'Order\x20'+(a['bound_order']??'(unknown)')+'\x20already\x20has\x20an\x20Allocation\x20bound.\x20Move\x20layer\x20will\x20abort\x20with\x20E_ALLOCATION_ALREADY_SPECIFIED\x20(order.move)\x20when\x20attempting\x20to\x20bind\x20a\x20second\x20Allocation.','affected_stakeholders':['owner','service_provider'],'scenario':'Attempting\x20to\x20bind\x20a\x20second\x20Allocation\x20to\x20the\x20same\x20Order','mitigation':'Use\x20the\x20existing\x20Allocation,\x20or\x20unbind\x20it\x20first\x20(if\x20supported),\x20or\x20create\x20a\x20new\x20Order.','evidence':'bound_order='+(a['bound_order']??'unknown')+',\x20alreadyHasAllocation='+a['order_already_has_allocation'],'related_move_error':'E_ALLOCATION_ALREADY_SPECIFIED\x20(order.move)','auto_fixable':![]};}},R_A_5_02={'id':'R-A-5-02','category':'cross_object','trigger':'payment_info\x20missing\x20for\x20alloc()\x20—\x20ENO_PAYMENT_INFO','check':a=>{if(a['has_payment_info'])return null;if(a['operation_type']!=='alloc_by_guard')return null;return{'id':'R-A-5-02','level':'HIGH','category':'cross_object','title':'payment_info\x20missing\x20—\x20alloc()\x20will\x20abort\x20with\x20ENO_PAYMENT_INFO','description':'Allocation\x20has\x20no\x20payment_info\x20set.\x20Move\x20alloc()\x20requires\x20payment_info.is_some()\x20at\x20step\x201\x20(pre_check).\x20The\x20entire\x20alloc()\x20transaction\x20will\x20revert,\x20funds\x20remain\x20in\x20Allocation.','affected_stakeholders':['owner'],'scenario':'Triggering\x20alloc()\x20before\x20setting\x20payment_info','mitigation':'Ensure\x20payment_info\x20is\x20set\x20during\x20Allocation\x20creation\x20(CallAllocation_Create\x20requires\x20payment_info\x20field).','evidence':'has_payment_info='+(a['has_payment_info']??![]),'related_move_error':'ENO_PAYMENT_INFO\x20(9)','auto_fixable':![]};}},R_A_5_03={'id':'R-A-5-03','category':'cross_object','trigger':'MAX_ALLOCATOR_COUNT\x20not\x20synced\x20to\x20onchain-constants.ts','check':a=>{return{'id':'R-A-5-03','level':'LOW','category':'cross_object','title':'MAX_ALLOCATOR_COUNT\x20not\x20synced\x20to\x20onchain-constants.ts','description':'Move\x20layer\x20allocation.move:16\x20defines\x20MAX_ALLOCATOR_COUNT='+MAX_ALLOCATOR_COUNT+',\x20but\x20onchain-constants.ts\x20does\x20NOT\x20export\x20this\x20constant.\x20SDK\x20allocation.ts:318\x20defines\x20it\x20locally,\x20creating\x20a\x20double-definition\x20risk.\x20MCP\x20knowledge\x20imports\x20the\x20local\x20definition.','affected_stakeholders':['system'],'scenario':'Constant\x20sync\x20drift\x20between\x20Move\x20/\x20SDK\x20/\x20MCP','mitigation':'1)\x20Add\x20MAX_ALLOCATOR_COUNT=100\x20to\x20onchain-constants.ts.\x202)\x20Update\x20SDK\x20allocation.ts\x20to\x20import\x20from\x20onchain-constants.js.\x203)\x20Delete\x20local\x20definition.','evidence':'MAX_ALLOCATOR_COUNT='+MAX_ALLOCATOR_COUNT+'\x20(local),\x20not\x20in\x20onchain-constants.ts','auto_fixable':!![]};}},ALL_RULES=[R_A_1_01,R_A_1_02,R_A_1_03,R_A_2_01,R_A_2_02,R_A_2_03,R_A_3_01,R_A_3_02,R_A_3_03,R_A_3_04,R_A_4_01,R_A_4_02,R_A_4_03,R_A_5_01,R_A_5_02,R_A_5_03];export const ALLOCATION_RISK_VERSION='1.0.0';export function getAllRiskRules(){return[...ALL_RULES];}export function getRiskRulesCount(){return ALL_RULES['length'];}export function getRiskRulesByCategory(a){return ALL_RULES['filter'](b=>b['category']===a);}export function assessAllocationRisks(a){const b=[];for(const g of ALL_RULES){const h=g['check'](a);if(h)b['push'](h);}const c=b['length']===0x0?'LOW':b['some'](i=>i['level']==='CRITICAL')?'CRITICAL':b['some'](i=>i['level']==='HIGH')?'HIGH':b['some'](i=>i['level']==='MEDIUM')?'MEDIUM':'LOW',d={},e={};for(const i of b){d[i['category']]=(d[i['category']]??0x0)+0x1,e[i['level']]=(e[i['level']]??0x0)+0x1;}const f={};for(const j of b){for(const k of j['affected_stakeholders']){if(!f[k])f[k]=[];f[k]['push'](j['id']+':\x20'+j['mitigation']);}}return{'summary':'Assessed\x20'+b['length']+'\x20risk(s)\x20across\x20'+Object['keys'](d)['length']+'\x20categories','risks':b,'overall_risk':c,'risks_by_category':d,'risks_by_level':e,'stakeholder_advice':f,'needs_human_review':b['some'](l=>l['level']==='CRITICAL'||l['level']==='HIGH'),'blocks_publish':b['some'](l=>l['level']==='CRITICAL')};}export{ALLOCATION_ERROR_CODES};
|