@wowok/agent-mcp 2.4.3 → 2.5.0
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/runtime.d.ts +4 -0
- package/dist/config/runtime.js +29 -5
- package/dist/harness/auto-escalation.d.ts +27 -0
- package/dist/harness/auto-escalation.js +68 -0
- package/dist/index.js +21 -0
- package/dist/knowledge/allocation-confirm.d.ts +115 -0
- package/dist/knowledge/allocation-confirm.js +534 -0
- package/dist/knowledge/allocation-context.d.ts +58 -0
- package/dist/knowledge/allocation-context.js +249 -0
- package/dist/knowledge/allocation-ledger.d.ts +67 -0
- package/dist/knowledge/allocation-ledger.js +463 -0
- package/dist/knowledge/allocation-puzzle.d.ts +135 -0
- package/dist/knowledge/allocation-puzzle.js +298 -0
- package/dist/knowledge/allocation-risk.d.ts +78 -0
- package/dist/knowledge/allocation-risk.js +568 -0
- package/dist/knowledge/allocation-templates.d.ts +38 -0
- package/dist/knowledge/allocation-templates.js +970 -0
- package/dist/knowledge/allocation-translation.d.ts +72 -0
- package/dist/knowledge/allocation-translation.js +585 -0
- package/dist/knowledge/arb-risk.d.ts +37 -0
- package/dist/knowledge/arb-risk.js +210 -0
- package/dist/knowledge/arbitration-confirm.d.ts +135 -0
- package/dist/knowledge/arbitration-confirm.js +559 -0
- package/dist/knowledge/arbitration-context.d.ts +81 -0
- package/dist/knowledge/arbitration-context.js +505 -0
- package/dist/knowledge/arbitration-ledger.d.ts +62 -0
- package/dist/knowledge/arbitration-ledger.js +521 -0
- package/dist/knowledge/arbitration-puzzle.d.ts +84 -0
- package/dist/knowledge/arbitration-puzzle.js +304 -0
- package/dist/knowledge/arbitration-risk.d.ts +112 -0
- package/dist/knowledge/arbitration-risk.js +433 -0
- package/dist/knowledge/arbitration-templates.d.ts +38 -0
- package/dist/knowledge/arbitration-templates.js +276 -0
- package/dist/knowledge/arbitration-translation.d.ts +91 -0
- package/dist/knowledge/arbitration-translation.js +487 -0
- package/dist/knowledge/bridge-risk.d.ts +36 -0
- package/dist/knowledge/bridge-risk.js +263 -0
- package/dist/knowledge/contact-risk.d.ts +32 -0
- package/dist/knowledge/contact-risk.js +200 -0
- package/dist/knowledge/demand-confirm.d.ts +32 -0
- package/dist/knowledge/demand-confirm.js +206 -0
- package/dist/knowledge/demand-risk.d.ts +30 -0
- package/dist/knowledge/demand-risk.js +240 -0
- package/dist/knowledge/demand-translation.d.ts +55 -0
- package/dist/knowledge/demand-translation.js +354 -0
- package/dist/knowledge/deployment-scanner.d.ts +63 -0
- package/dist/knowledge/deployment-scanner.js +762 -0
- package/dist/knowledge/examples-scanner-cli.d.ts +1 -0
- package/dist/knowledge/examples-scanner-cli.js +26 -0
- package/dist/knowledge/examples-scanner.d.ts +121 -0
- package/dist/knowledge/examples-scanner.js +825 -0
- package/dist/knowledge/flywheel-loop.d.ts +3 -0
- package/dist/knowledge/flywheel-loop.js +32 -3
- package/dist/knowledge/glossary.js +3 -1
- package/dist/knowledge/guard-confirm.d.ts +86 -0
- package/dist/knowledge/guard-confirm.js +406 -0
- package/dist/knowledge/guard-context.d.ts +56 -0
- package/dist/knowledge/guard-context.js +287 -0
- package/dist/knowledge/guard-design-patterns.d.ts +37 -0
- package/dist/knowledge/guard-design-patterns.js +257 -0
- package/dist/knowledge/guard-puzzle.js +3 -2
- package/dist/knowledge/guard-risk.d.ts +1 -1
- package/dist/knowledge/guard-risk.js +12 -14
- package/dist/knowledge/guard-templates.js +1 -1
- package/dist/knowledge/guard-translation.js +6 -5
- package/dist/knowledge/index.d.ts +342 -0
- package/dist/knowledge/index.js +344 -0
- package/dist/knowledge/machine-confirm.d.ts +102 -0
- package/dist/knowledge/machine-confirm.js +559 -0
- package/dist/knowledge/machine-context.d.ts +160 -0
- package/dist/knowledge/machine-context.js +812 -0
- package/dist/knowledge/machine-ledger.d.ts +41 -0
- package/dist/knowledge/machine-ledger.js +315 -0
- package/dist/knowledge/machine-puzzle.d.ts +206 -0
- package/dist/knowledge/machine-puzzle.js +494 -0
- package/dist/knowledge/machine-risk.d.ts +75 -0
- package/dist/knowledge/machine-risk.js +644 -0
- package/dist/knowledge/machine-templates.d.ts +92 -0
- package/dist/knowledge/machine-templates.js +1592 -0
- package/dist/knowledge/machine-topology.d.ts +57 -0
- package/dist/knowledge/machine-topology.js +234 -0
- package/dist/knowledge/machine-translation.d.ts +96 -0
- package/dist/knowledge/machine-translation.js +513 -0
- package/dist/knowledge/mcp-schema-audit-cli.d.ts +1 -0
- package/dist/knowledge/mcp-schema-audit-cli.js +45 -0
- package/dist/knowledge/mcp-schema-audit.d.ts +90 -0
- package/dist/knowledge/mcp-schema-audit.js +772 -0
- package/dist/knowledge/onchain-constants.d.ts +4 -0
- package/dist/knowledge/onchain-constants.js +35 -0
- package/dist/knowledge/order-confirm.d.ts +115 -0
- package/dist/knowledge/order-confirm.js +573 -0
- package/dist/knowledge/order-context.d.ts +66 -0
- package/dist/knowledge/order-context.js +390 -0
- package/dist/knowledge/order-ledger.d.ts +69 -0
- package/dist/knowledge/order-ledger.js +341 -0
- package/dist/knowledge/order-puzzle.d.ts +159 -0
- package/dist/knowledge/order-puzzle.js +255 -0
- package/dist/knowledge/order-risk.d.ts +66 -0
- package/dist/knowledge/order-risk.js +653 -0
- package/dist/knowledge/order-templates.d.ts +50 -0
- package/dist/knowledge/order-templates.js +368 -0
- package/dist/knowledge/order-translation.d.ts +78 -0
- package/dist/knowledge/order-translation.js +550 -0
- package/dist/knowledge/passport-confirm.d.ts +130 -0
- package/dist/knowledge/passport-confirm.js +531 -0
- package/dist/knowledge/passport-context.d.ts +59 -0
- package/dist/knowledge/passport-context.js +306 -0
- package/dist/knowledge/passport-ledger.d.ts +48 -0
- package/dist/knowledge/passport-ledger.js +282 -0
- package/dist/knowledge/passport-puzzle.d.ts +108 -0
- package/dist/knowledge/passport-puzzle.js +333 -0
- package/dist/knowledge/passport-risk.d.ts +70 -0
- package/dist/knowledge/passport-risk.js +450 -0
- package/dist/knowledge/passport-templates.d.ts +40 -0
- package/dist/knowledge/passport-templates.js +568 -0
- package/dist/knowledge/passport-translation.d.ts +68 -0
- package/dist/knowledge/passport-translation.js +516 -0
- package/dist/knowledge/payment-risk.d.ts +33 -0
- package/dist/knowledge/payment-risk.js +182 -0
- package/dist/knowledge/permission-confirm.d.ts +110 -0
- package/dist/knowledge/permission-confirm.js +426 -0
- package/dist/knowledge/permission-context.d.ts +58 -0
- package/dist/knowledge/permission-context.js +224 -0
- package/dist/knowledge/permission-ledger.d.ts +38 -0
- package/dist/knowledge/permission-ledger.js +403 -0
- package/dist/knowledge/permission-puzzle.d.ts +122 -0
- package/dist/knowledge/permission-puzzle.js +173 -0
- package/dist/knowledge/permission-risk.d.ts +76 -0
- package/dist/knowledge/permission-risk.js +411 -0
- package/dist/knowledge/permission-templates.d.ts +38 -0
- package/dist/knowledge/permission-templates.js +234 -0
- package/dist/knowledge/permission-translation.d.ts +57 -0
- package/dist/knowledge/permission-translation.js +350 -0
- package/dist/knowledge/personal-risk.d.ts +36 -0
- package/dist/knowledge/personal-risk.js +212 -0
- package/dist/knowledge/progress-confirm.d.ts +108 -0
- package/dist/knowledge/progress-confirm.js +456 -0
- package/dist/knowledge/progress-context.d.ts +123 -0
- package/dist/knowledge/progress-context.js +452 -0
- package/dist/knowledge/progress-ledger.d.ts +63 -0
- package/dist/knowledge/progress-ledger.js +327 -0
- package/dist/knowledge/progress-puzzle.d.ts +82 -0
- package/dist/knowledge/progress-puzzle.js +219 -0
- package/dist/knowledge/progress-risk.d.ts +74 -0
- package/dist/knowledge/progress-risk.js +461 -0
- package/dist/knowledge/progress-templates.d.ts +38 -0
- package/dist/knowledge/progress-templates.js +228 -0
- package/dist/knowledge/progress-translation.d.ts +52 -0
- package/dist/knowledge/progress-translation.js +401 -0
- package/dist/knowledge/proof-confirm.d.ts +31 -0
- package/dist/knowledge/proof-confirm.js +187 -0
- package/dist/knowledge/proof-risk.d.ts +33 -0
- package/dist/knowledge/proof-risk.js +207 -0
- package/dist/knowledge/proof-translation.d.ts +52 -0
- package/dist/knowledge/proof-translation.js +283 -0
- package/dist/knowledge/registrar-risk.d.ts +34 -0
- package/dist/knowledge/registrar-risk.js +217 -0
- package/dist/knowledge/repository-confirm.d.ts +36 -0
- package/dist/knowledge/repository-confirm.js +242 -0
- package/dist/knowledge/repository-risk.d.ts +40 -0
- package/dist/knowledge/repository-risk.js +312 -0
- package/dist/knowledge/repository-translation.d.ts +58 -0
- package/dist/knowledge/repository-translation.js +422 -0
- package/dist/knowledge/resource-risk.d.ts +32 -0
- package/dist/knowledge/resource-risk.js +157 -0
- package/dist/knowledge/reward-confirm.d.ts +113 -0
- package/dist/knowledge/reward-confirm.js +496 -0
- package/dist/knowledge/reward-context.d.ts +127 -0
- package/dist/knowledge/reward-context.js +504 -0
- package/dist/knowledge/reward-ledger.d.ts +96 -0
- package/dist/knowledge/reward-ledger.js +502 -0
- package/dist/knowledge/reward-puzzle.d.ts +97 -0
- package/dist/knowledge/reward-puzzle.js +288 -0
- package/dist/knowledge/reward-risk.d.ts +84 -0
- package/dist/knowledge/reward-risk.js +545 -0
- package/dist/knowledge/reward-translation.d.ts +58 -0
- package/dist/knowledge/reward-translation.js +501 -0
- package/dist/knowledge/safety-rules.js +11 -3
- package/dist/knowledge/scenario-modes.d.ts +53 -0
- package/dist/knowledge/scenario-modes.js +302 -0
- package/dist/knowledge/service-confirm.d.ts +152 -0
- package/dist/knowledge/service-confirm.js +699 -0
- package/dist/knowledge/service-context.d.ts +66 -0
- package/dist/knowledge/service-context.js +403 -0
- package/dist/knowledge/service-ledger.d.ts +71 -0
- package/dist/knowledge/service-ledger.js +609 -0
- package/dist/knowledge/service-puzzle.d.ts +158 -0
- package/dist/knowledge/service-puzzle.js +236 -0
- package/dist/knowledge/service-risk.d.ts +108 -0
- package/dist/knowledge/service-risk.js +615 -0
- package/dist/knowledge/service-templates.d.ts +39 -0
- package/dist/knowledge/service-templates.js +418 -0
- package/dist/knowledge/service-translation.d.ts +103 -0
- package/dist/knowledge/service-translation.js +622 -0
- package/dist/knowledge/tools-reference.d.ts +17 -0
- package/dist/knowledge/tools-reference.js +151 -0
- package/dist/knowledge/treasury-confirm.d.ts +133 -0
- package/dist/knowledge/treasury-confirm.js +512 -0
- package/dist/knowledge/treasury-context.d.ts +64 -0
- package/dist/knowledge/treasury-context.js +363 -0
- package/dist/knowledge/treasury-ledger.d.ts +42 -0
- package/dist/knowledge/treasury-ledger.js +300 -0
- package/dist/knowledge/treasury-puzzle.d.ts +163 -0
- package/dist/knowledge/treasury-puzzle.js +216 -0
- package/dist/knowledge/treasury-risk.d.ts +86 -0
- package/dist/knowledge/treasury-risk.js +440 -0
- package/dist/knowledge/treasury-templates.d.ts +38 -0
- package/dist/knowledge/treasury-templates.js +316 -0
- package/dist/knowledge/treasury-translation.d.ts +78 -0
- package/dist/knowledge/treasury-translation.js +498 -0
- package/dist/knowledge/util-risk.d.ts +30 -0
- package/dist/knowledge/util-risk.js +135 -0
- package/dist/project/business-puzzle.d.ts +47 -0
- package/dist/project/business-puzzle.js +372 -0
- package/dist/project/deployment-doc.d.ts +61 -0
- package/dist/project/deployment-doc.js +432 -0
- package/dist/project/risk-aggregator.d.ts +50 -0
- package/dist/project/risk-aggregator.js +280 -0
- package/dist/project/substep-trace.d.ts +130 -0
- package/dist/project/substep-trace.js +332 -0
- package/dist/schema/call/allocation.d.ts +34 -34
- package/dist/schema/call/arbitration.d.ts +141 -141
- package/dist/schema/call/base.d.ts +386 -386
- package/dist/schema/call/base.js +3 -3
- package/dist/schema/call/bridge-handler.d.ts +5 -2
- package/dist/schema/call/bridge.d.ts +159 -159
- package/dist/schema/call/contact.d.ts +110 -110
- package/dist/schema/call/demand.d.ts +76 -76
- package/dist/schema/call/handler.d.ts +2 -3
- package/dist/schema/call/handler.js +1 -1
- package/dist/schema/call/machine.d.ts +58 -58
- package/dist/schema/call/order.d.ts +98 -110
- package/dist/schema/call/permission-handler.d.ts +5 -0
- package/dist/schema/call/permission-handler.js +54 -0
- package/dist/schema/call/permission.d.ts +108 -108
- package/dist/schema/call/personal.d.ts +14 -14
- package/dist/schema/call/progress.d.ts +57 -72
- package/dist/schema/call/progress.js +7 -4
- package/dist/schema/call/proof.d.ts +18 -18
- package/dist/schema/call/proof.js +12 -7
- package/dist/schema/call/repository.d.ts +154 -154
- package/dist/schema/call/reward.d.ts +55 -55
- package/dist/schema/call/service.d.ts +231 -231
- package/dist/schema/call/treasury.d.ts +93 -93
- package/dist/schema/config/index.d.ts +178 -5
- package/dist/schema/config/index.js +52 -1
- package/dist/schema/local/index.d.ts +3554 -836
- package/dist/schema/local/index.js +2 -1
- package/dist/schema/messenger/index.d.ts +162 -162
- package/dist/schema/operations.d.ts +1058 -1074
- package/dist/schema/operations.js +7 -1
- package/dist/schema/project/index.d.ts +1392 -6
- package/dist/schema/project/index.js +426 -2
- package/dist/schema/query/index.d.ts +672 -672
- package/dist/schema/schema-query/index.d.ts +23 -3
- package/dist/schema/schema-query/index.js +13 -2
- package/dist/schema/sync-layer4.d.ts +21 -0
- package/dist/schema/sync-layer4.js +261 -0
- package/dist/schema/trust/index.d.ts +26 -26
- package/dist/schemas/account_operation.output.json +718 -0
- package/dist/schemas/config_operation.output.json +173 -0
- package/dist/schemas/index.json +9 -1
- package/dist/schemas/local_info_operation.output.json +718 -0
- package/dist/schemas/local_mark_operation.output.json +718 -0
- package/dist/schemas/onchain_operations.output.json +3 -2
- package/dist/schemas/onchain_operations.schema.json +1802 -313
- package/dist/schemas/onchain_operations_allocation.schema.json +2 -1
- package/dist/schemas/onchain_operations_arbitration.schema.json +2 -1
- package/dist/schemas/onchain_operations_contact.schema.json +2 -1
- package/dist/schemas/onchain_operations_demand.schema.json +2 -1
- package/dist/schemas/onchain_operations_gen_passport.schema.json +878 -872
- package/dist/schemas/onchain_operations_gen_proof.schema.json +273 -0
- package/dist/schemas/onchain_operations_guard.schema.json +584 -70
- package/dist/schemas/onchain_operations_machine.schema.json +2 -1
- package/dist/schemas/onchain_operations_order.schema.json +13 -9
- package/dist/schemas/onchain_operations_payment.schema.json +2 -1
- package/dist/schemas/onchain_operations_permission.schema.json +2 -1
- package/dist/schemas/onchain_operations_personal.schema.json +2 -1
- package/dist/schemas/onchain_operations_progress.schema.json +14 -10
- package/dist/schemas/onchain_operations_proof.schema.json +699 -0
- package/dist/schemas/onchain_operations_repository.schema.json +2 -1
- package/dist/schemas/onchain_operations_reward.schema.json +2 -1
- package/dist/schemas/onchain_operations_service.schema.json +2 -1
- package/dist/schemas/onchain_operations_treasury.schema.json +2 -1
- package/dist/schemas/onchain_table_data.schema.json +32 -1
- package/dist/schemas/project_operation.output.json +879 -0
- package/dist/schemas/project_operation.schema.json +473 -2
- package/dist/schemas/query_toolkit.output.json +14906 -6
- package/dist/schemas/schema_query.output.json +38 -1
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/tools/handlers/config.d.ts +1 -1
- package/dist/tools/handlers/config.js +21 -18
- package/dist/tools/handlers/file-export.d.ts +2 -2
- package/dist/tools/handlers/local.d.ts +3 -30
- package/dist/tools/handlers/local.js +14 -3
- package/dist/tools/handlers/messenger.d.ts +1 -1
- package/dist/tools/handlers/messenger.js +2 -1
- package/dist/tools/handlers/onchain.d.ts +1 -1
- package/dist/tools/handlers/onchain.js +24 -22
- package/dist/tools/handlers/project.d.ts +1 -1
- package/dist/tools/handlers/project.js +258 -18
- package/dist/tools/handlers/query.d.ts +4 -4
- package/dist/tools/handlers/schema-query.d.ts +1 -1
- package/dist/tools/handlers/schema-query.js +21 -20
- package/dist/tools/handlers/trust.d.ts +1 -1
- package/dist/tools/handlers/trust.js +2 -2
- package/dist/tools/handlers/wip.d.ts +1 -1
- package/dist/tools/handlers/wip.js +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +55 -8
- package/dist/tools/rules-hook.d.ts +1 -1
- package/dist/tools/rules-hook.js +3 -2
- package/dist/tools/shared.d.ts +13 -22
- package/dist/tools/types.d.ts +5 -5
- package/dist/tools/wrap.d.ts +10 -2
- package/dist/tools/wrap.js +212 -0
- package/package.json +3 -3
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { MAX_REWARD_COUNT, MAX_GUARD_COUNT_DEMAND, MAX_DESCRIPTION_LENGTH, MAX_LONG_NAME_LENGTH, } from "@wowok/wowok";
|
|
2
|
+
const MAX_FEEDBACK_COUNT = 20;
|
|
3
|
+
function checkDescription(input) {
|
|
4
|
+
const len = input.description?.length ?? 0;
|
|
5
|
+
const passed = len > 0 && len <= MAX_DESCRIPTION_LENGTH;
|
|
6
|
+
return {
|
|
7
|
+
id: "C-DEM-01",
|
|
8
|
+
severity: passed ? "info" : (len === 0 ? "warn" : "block"),
|
|
9
|
+
title: `description non-empty and within MAX_DESCRIPTION_LENGTH (${MAX_DESCRIPTION_LENGTH} chars)`,
|
|
10
|
+
description: "description is a REQUIRED field. Move contract validates via common::DESCRIPTION (demand.move:157,177). " +
|
|
11
|
+
"Empty string is technically rejected by common::DESCRIPTION only if NAME_ALLOW_EMPTY is not used; the new_imp " +
|
|
12
|
+
"path uses common::DESCRIPTION which allows empty but enforces the 4000-char limit. Non-empty descriptions are " +
|
|
13
|
+
"strongly recommended for Demand discoverability.",
|
|
14
|
+
passed,
|
|
15
|
+
evidence: input.description === undefined ? "undefined" : `length=${len}, limit=${MAX_DESCRIPTION_LENGTH}`,
|
|
16
|
+
fix_hint: passed ? undefined : `Provide a description of 1..${MAX_DESCRIPTION_LENGTH} characters.`,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function checkLocation(input) {
|
|
20
|
+
const len = input.location?.length ?? 0;
|
|
21
|
+
const passed = len <= MAX_LONG_NAME_LENGTH;
|
|
22
|
+
return {
|
|
23
|
+
id: "C-DEM-02",
|
|
24
|
+
severity: passed ? "info" : "block",
|
|
25
|
+
title: `location within MAX_LONG_NAME_LENGTH (${MAX_LONG_NAME_LENGTH} chars)`,
|
|
26
|
+
description: "location is set via location_set_imp (demand.move:179-182) which validates via common::LONG_NAME. " +
|
|
27
|
+
"Move aborts with E_LONG_NAME_LENGTH_EXCEEDED (11) on overflow. Empty location (\"\") is valid — new_imp " +
|
|
28
|
+
"initializes location to empty string. Use location_set to update after creation.",
|
|
29
|
+
passed,
|
|
30
|
+
evidence: input.location === undefined ? "undefined" : `length=${len}, limit=${MAX_LONG_NAME_LENGTH}`,
|
|
31
|
+
fix_hint: passed ? undefined : `Trim location to ≤ ${MAX_LONG_NAME_LENGTH} characters.`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function checkRewards(input) {
|
|
35
|
+
const count = input.rewards?.length ?? 0;
|
|
36
|
+
const passed = count <= MAX_REWARD_COUNT;
|
|
37
|
+
return {
|
|
38
|
+
id: "C-DEM-03",
|
|
39
|
+
severity: passed ? "info" : "block",
|
|
40
|
+
title: `rewards count within MAX_REWARD_COUNT (${MAX_REWARD_COUNT})`,
|
|
41
|
+
description: "Each reward_add_imp (demand.move:184-191) checks `vector::length(&self.rewards) < MAX_REWARD_COUNT` " +
|
|
42
|
+
"before pushing (after de-duplication). Move aborts with E_MAX_REWARD_COUNT_EXCEEDED (1) on overflow. " +
|
|
43
|
+
"Rewards are affiliated via the Registrar — adding/removing triggers affiliation/disaffiliation.",
|
|
44
|
+
passed,
|
|
45
|
+
evidence: `count=${count}, limit=${MAX_REWARD_COUNT}`,
|
|
46
|
+
fix_hint: passed ? undefined : `Remove rewards before adding new ones. Limit=${MAX_REWARD_COUNT}.`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function checkGuards(input) {
|
|
50
|
+
const count = input.guards?.length ?? 0;
|
|
51
|
+
const passed = count <= MAX_GUARD_COUNT_DEMAND;
|
|
52
|
+
return {
|
|
53
|
+
id: "C-DEM-04",
|
|
54
|
+
severity: passed ? "info" : "block",
|
|
55
|
+
title: `guards count within MAX_GUARD_COUNT_DEMAND (${MAX_GUARD_COUNT_DEMAND})`,
|
|
56
|
+
description: "Each guard_add_imp (demand.move:213-242) checks `vector::length(&self.guards) < MAX_GUARD_COUNT` " +
|
|
57
|
+
"before pushing (after duplicate check — duplicates update service_identifier in place). " +
|
|
58
|
+
"Move aborts with E_MAX_GUARD_COUNT_EXCEEDED (2) on overflow. Guards are affiliated via the Registrar.",
|
|
59
|
+
passed,
|
|
60
|
+
evidence: `count=${count}, limit=${MAX_GUARD_COUNT_DEMAND}`,
|
|
61
|
+
fix_hint: passed ? undefined : `Remove guards before adding new ones. Limit=${MAX_GUARD_COUNT_DEMAND}.`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function checkFeedback(input) {
|
|
65
|
+
const count = input.feedback?.length ?? 0;
|
|
66
|
+
const passed = count <= MAX_FEEDBACK_COUNT;
|
|
67
|
+
return {
|
|
68
|
+
id: "C-DEM-05",
|
|
69
|
+
severity: passed ? "info" : "block",
|
|
70
|
+
title: `feedback batch count within MAX_FEEDBACK_COUNT (${MAX_FEEDBACK_COUNT})`,
|
|
71
|
+
description: "Move feedback (demand.move:352) updates ONE presenter per call — feedback_imp writes to a single " +
|
|
72
|
+
"ServiceInfo record. The SDK batches multiple feedback calls and caps the batch at MAX_FEEDBACK_COUNT=" +
|
|
73
|
+
`${MAX_FEEDBACK_COUNT} (SDK-only limit, NOT in onchain-constants.ts). Exceeding the SDK batch limit is ` +
|
|
74
|
+
"rejected before transaction building. Each feedback string is validated by common::DESCRIPTION (4000 chars).",
|
|
75
|
+
passed,
|
|
76
|
+
evidence: `count=${count}, limit=${MAX_FEEDBACK_COUNT}`,
|
|
77
|
+
fix_hint: passed ? undefined : `Split feedback into batches of ≤ ${MAX_FEEDBACK_COUNT} entries.`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function checkServiceIdentifier(input) {
|
|
81
|
+
const sid = input.service_identifier;
|
|
82
|
+
if (sid === null || sid === undefined) {
|
|
83
|
+
return {
|
|
84
|
+
id: "C-DEM-06",
|
|
85
|
+
severity: "info",
|
|
86
|
+
title: "service_identifier is null/undefined → Option::none (use supplied service address)",
|
|
87
|
+
description: "When service_identifier is None, guard_add_imp stores Option::none in ServiceGuard. At present_with_passport " +
|
|
88
|
+
"time, present_with_passport_imp uses the service parameter (or Option::none for plain present_with_passport). " +
|
|
89
|
+
"Use None when the Demand does not need to route presentations through a specific Service submission.",
|
|
90
|
+
passed: true,
|
|
91
|
+
evidence: "null/undefined → Option::none",
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const isU8 = typeof sid === "number" && Number.isInteger(sid) && sid >= 0 && sid <= 255;
|
|
95
|
+
return {
|
|
96
|
+
id: "C-DEM-06",
|
|
97
|
+
severity: isU8 ? "info" : "block",
|
|
98
|
+
title: "service_identifier is a valid u8 (0-255) when provided",
|
|
99
|
+
description: "When provided, service_identifier must be a u8 index into the Guard's submission registry. " +
|
|
100
|
+
"guard_add_imp (demand.move:218-222) calls guard::get_submission_object_type(guard, *i) and " +
|
|
101
|
+
"common::assert_service_object_type(t) — the submission at that index MUST exist and have type " +
|
|
102
|
+
"ObjectType::Service. At present_with_passport time, the submission address is extracted from the Passport " +
|
|
103
|
+
"via passport::submission_get(passport, &g, *service_identifier).",
|
|
104
|
+
passed: isU8,
|
|
105
|
+
evidence: `service_identifier=${sid}`,
|
|
106
|
+
fix_hint: isU8 ? undefined : "Provide an integer in [0, 255] that indexes a Service-typed submission in the Guard.",
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function checkByGuard(input) {
|
|
110
|
+
const byGuard = input.by_guard;
|
|
111
|
+
if (byGuard === null || byGuard === undefined) {
|
|
112
|
+
return {
|
|
113
|
+
id: "C-DEM-07",
|
|
114
|
+
severity: "info",
|
|
115
|
+
title: "by_guard is null → use plain present (requires empty guards vector)",
|
|
116
|
+
description: "When by_guard is None, the caller uses plain present (demand.move:100) which asserts " +
|
|
117
|
+
"`vector::is_empty(&self.guards)` — aborts with E_NEED_PASSPORT (3) if guards exist. Use this path " +
|
|
118
|
+
"for open Demands (no guards).",
|
|
119
|
+
passed: true,
|
|
120
|
+
evidence: "null/undefined → plain present path",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (input.guards === undefined) {
|
|
124
|
+
return {
|
|
125
|
+
id: "C-DEM-07",
|
|
126
|
+
severity: "info",
|
|
127
|
+
title: "by_guard provided (cannot verify membership — guards list not supplied)",
|
|
128
|
+
description: "present_with_passport_imp (demand.move:110-129) iterates the guards vector looking for a matching " +
|
|
129
|
+
"guard address. If not found, it aborts with E_GUARD_NOT_FOUND (4). The caller must ensure by_guard " +
|
|
130
|
+
"is in Demand.guards — this check could not verify because the guards list was not supplied.",
|
|
131
|
+
passed: true,
|
|
132
|
+
evidence: `by_guard=${byGuard.substring(0, 10)}... (guards list not supplied)`,
|
|
133
|
+
fix_hint: "Pass input.guards to enable membership verification.",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const isInGuards = input.guards.includes(byGuard);
|
|
137
|
+
return {
|
|
138
|
+
id: "C-DEM-07",
|
|
139
|
+
severity: isInGuards ? "info" : "block",
|
|
140
|
+
title: "by_guard exists in Demand.guards (when specified)",
|
|
141
|
+
description: "When by_guard is specified, present_with_passport_imp (demand.move:110-129) iterates the guards vector " +
|
|
142
|
+
"looking for a matching guard address. If not found, it aborts with E_GUARD_NOT_FOUND (4). The caller " +
|
|
143
|
+
"MUST ensure by_guard was previously added via guard_add.",
|
|
144
|
+
passed: isInGuards,
|
|
145
|
+
evidence: `by_guard=${byGuard.substring(0, 10)}..., in guards=${isInGuards}`,
|
|
146
|
+
fix_hint: isInGuards ? undefined : "Call guard_add(permission, guard, service_identifier) first.",
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function checkPermissionSetAvailable(input) {
|
|
150
|
+
const available = input.permission_set_available !== false;
|
|
151
|
+
return {
|
|
152
|
+
id: "C-DEM-08",
|
|
153
|
+
severity: available ? "info" : "warn",
|
|
154
|
+
title: "permission_set available via CallPermission.apply (DE-D-2=A)",
|
|
155
|
+
description: "The Move permission_set function (demand.move:286) is exposed in the SDK via the CallPermission.apply " +
|
|
156
|
+
"mechanism (DE-D-2=A). It calls permission::assert_owner(old) and registrar::affiliation_change to migrate " +
|
|
157
|
+
"the affiliation. Permission indices for Demand (demand.move:20): 400=DEMAND_NEW, 401=DEMAND_DESCRIPTION, " +
|
|
158
|
+
"402=DEMAND_LOCATION, 404=DEMAND_GUARD, 405=DEMAND_REWARD, 406=DEMAND_FEEDBACK, 407=DEMAND_OWNER_RECEIVE, " +
|
|
159
|
+
"408=DEMAND_UM. This is an info check — it confirms the capability is available, not a creation prerequisite.",
|
|
160
|
+
passed: available,
|
|
161
|
+
evidence: available ? "exposed via CallPermission.apply" : "not available (regression)",
|
|
162
|
+
fix_hint: available ? undefined : "Restore the CallPermission.apply path for permission_set.",
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
export function preCheckDemandCreation(input) {
|
|
166
|
+
return [
|
|
167
|
+
checkDescription(input),
|
|
168
|
+
checkLocation(input),
|
|
169
|
+
checkRewards(input),
|
|
170
|
+
checkGuards(input),
|
|
171
|
+
checkFeedback(input),
|
|
172
|
+
checkServiceIdentifier(input),
|
|
173
|
+
checkByGuard(input),
|
|
174
|
+
checkPermissionSetAvailable(input),
|
|
175
|
+
];
|
|
176
|
+
}
|
|
177
|
+
export function canCreateDemand(input) {
|
|
178
|
+
const items = preCheckDemandCreation(input);
|
|
179
|
+
return {
|
|
180
|
+
canCreate: items.every(i => i.severity !== "block" || i.passed),
|
|
181
|
+
blockers: items.filter(i => i.severity === "block" && !i.passed),
|
|
182
|
+
warnings: items.filter(i => i.severity === "warn" && !i.passed),
|
|
183
|
+
info: items.filter(i => i.severity === "info"),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
export function formatDemandCreationSummary(input) {
|
|
187
|
+
const { canCreate, blockers, warnings, info } = canCreateDemand(input);
|
|
188
|
+
const lines = [];
|
|
189
|
+
lines.push(canCreate ? "✓ Demand pre-check PASSED" : "✗ Demand pre-check FAILED");
|
|
190
|
+
lines.push("");
|
|
191
|
+
if (blockers.length > 0) {
|
|
192
|
+
lines.push("BLOCKERS (must fix before operation):");
|
|
193
|
+
blockers.forEach(b => lines.push(` [${b.id}] ${b.title} — ${b.evidence ?? ""}`));
|
|
194
|
+
lines.push("");
|
|
195
|
+
}
|
|
196
|
+
if (warnings.length > 0) {
|
|
197
|
+
lines.push("WARNINGS (review recommended):");
|
|
198
|
+
warnings.forEach(w => lines.push(` [${w.id}] ${w.title} — ${w.evidence ?? ""}`));
|
|
199
|
+
lines.push("");
|
|
200
|
+
}
|
|
201
|
+
if (info.length > 0) {
|
|
202
|
+
lines.push("INFO:");
|
|
203
|
+
info.forEach(i => lines.push(` [${i.id}] ${i.title}`));
|
|
204
|
+
}
|
|
205
|
+
return lines.join("\n");
|
|
206
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type DemandRiskLevel = "CRITICAL" | "HIGH" | "MEDIUM" | "LOW" | "INFO";
|
|
2
|
+
export type DemandRiskCategory = "structural" | "semantic" | "lifecycle" | "knowledge";
|
|
3
|
+
export type DemandStakeholder = "creator" | "presenter" | "consumer" | "system";
|
|
4
|
+
export interface DemandRisk {
|
|
5
|
+
id: string;
|
|
6
|
+
level: DemandRiskLevel;
|
|
7
|
+
category: DemandRiskCategory;
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
affected_stakeholders: DemandStakeholder[];
|
|
11
|
+
scenario: string;
|
|
12
|
+
mitigation: string;
|
|
13
|
+
evidence?: string;
|
|
14
|
+
related_move_error?: string;
|
|
15
|
+
auto_fixable: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface DemandRiskCheckContext {
|
|
18
|
+
reward_count?: number;
|
|
19
|
+
guard_count?: number;
|
|
20
|
+
feedback_count?: number;
|
|
21
|
+
using_present_without_passport?: boolean;
|
|
22
|
+
guards_non_empty?: boolean;
|
|
23
|
+
constants_synced?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare const DEMAND_RISK_RULES: {
|
|
26
|
+
rule: DemandRisk;
|
|
27
|
+
check: (ctx: DemandRiskCheckContext) => DemandRisk | null;
|
|
28
|
+
}[];
|
|
29
|
+
export declare function checkDemandRisks(ctx: DemandRiskCheckContext): DemandRisk[];
|
|
30
|
+
export declare function getDemandRiskById(id: string): DemandRisk | undefined;
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { MAX_REWARD_COUNT, MAX_GUARD_COUNT_DEMAND, } from "@wowok/wowok";
|
|
2
|
+
const MAX_FEEDBACK_COUNT = 20;
|
|
3
|
+
const R_DEM_1_01 = {
|
|
4
|
+
rule: {
|
|
5
|
+
id: "R-DEM-01",
|
|
6
|
+
level: "HIGH",
|
|
7
|
+
category: "structural",
|
|
8
|
+
title: `rewards count exceeds MAX_REWARD_COUNT (${MAX_REWARD_COUNT})`,
|
|
9
|
+
description: `The 'rewards' vector is bounded by MAX_REWARD_COUNT=${MAX_REWARD_COUNT} (Move source: demand.move:21). ` +
|
|
10
|
+
`Exceeding this limit aborts with E_MAX_REWARD_COUNT_EXCEEDED (1). Each reward is affiliated via the Registrar, ` +
|
|
11
|
+
`so adding a reward also triggers registrar::affiliation. Use reward_remove/reward_clear to free slots before ` +
|
|
12
|
+
`adding new ones if the limit is reached.`,
|
|
13
|
+
affected_stakeholders: ["creator"],
|
|
14
|
+
scenario: "Caller calls reward_add when 20 rewards are already affiliated",
|
|
15
|
+
mitigation: "Track the current reward count. Before adding a new reward, call reward_remove or reward_clear to " +
|
|
16
|
+
"free a slot. Consider consolidating rewards into a single Reward object with multiple tiers if the " +
|
|
17
|
+
" Demand needs to offer more than 20 distinct reward paths.",
|
|
18
|
+
related_move_error: "E_MAX_REWARD_COUNT_EXCEEDED (1)",
|
|
19
|
+
auto_fixable: false,
|
|
20
|
+
},
|
|
21
|
+
check: (ctx) => {
|
|
22
|
+
if (ctx.reward_count === undefined)
|
|
23
|
+
return null;
|
|
24
|
+
if (ctx.reward_count <= MAX_REWARD_COUNT)
|
|
25
|
+
return null;
|
|
26
|
+
return { ...R_DEM_1_01.rule, evidence: `reward_count=${ctx.reward_count}, limit=${MAX_REWARD_COUNT}` };
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
const R_DEM_1_02 = {
|
|
30
|
+
rule: {
|
|
31
|
+
id: "R-DEM-02",
|
|
32
|
+
level: "HIGH",
|
|
33
|
+
category: "structural",
|
|
34
|
+
title: `guards count exceeds MAX_GUARD_COUNT_DEMAND (${MAX_GUARD_COUNT_DEMAND})`,
|
|
35
|
+
description: `The 'guards' vector is bounded by MAX_GUARD_COUNT_DEMAND=${MAX_GUARD_COUNT_DEMAND} (Move source: demand.move:22). ` +
|
|
36
|
+
`Exceeding this limit aborts with E_MAX_GUARD_COUNT_EXCEEDED (2). Each guard carries an optional ` +
|
|
37
|
+
`service_identifier (u8) that routes present_with_passport submissions to a specific Service submission ` +
|
|
38
|
+
`extracted from the Passport. Adding a duplicate guard updates the service_identifier instead of pushing.`,
|
|
39
|
+
affected_stakeholders: ["creator", "presenter"],
|
|
40
|
+
scenario: "Caller calls guard_add when 20 guards are already affiliated and the address is new",
|
|
41
|
+
mitigation: "Track the current guard count. Before adding a new guard, call guard_remove or guard_clear. " +
|
|
42
|
+
"If updating an existing guard's service_identifier, call guard_add with the same address (it updates " +
|
|
43
|
+
"in place rather than pushing).",
|
|
44
|
+
related_move_error: "E_MAX_GUARD_COUNT_EXCEEDED (2)",
|
|
45
|
+
auto_fixable: false,
|
|
46
|
+
},
|
|
47
|
+
check: (ctx) => {
|
|
48
|
+
if (ctx.guard_count === undefined)
|
|
49
|
+
return null;
|
|
50
|
+
if (ctx.guard_count <= MAX_GUARD_COUNT_DEMAND)
|
|
51
|
+
return null;
|
|
52
|
+
return { ...R_DEM_1_02.rule, evidence: `guard_count=${ctx.guard_count}, limit=${MAX_GUARD_COUNT_DEMAND}` };
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
const R_DEM_1_03 = {
|
|
56
|
+
rule: {
|
|
57
|
+
id: "R-DEM-03",
|
|
58
|
+
level: "MEDIUM",
|
|
59
|
+
category: "structural",
|
|
60
|
+
title: `feedback batch exceeds MAX_FEEDBACK_COUNT (${MAX_FEEDBACK_COUNT})`,
|
|
61
|
+
description: `The 'feedback' Move function (demand.move:352) updates ONE presenter per call (feedback_imp iterates ` +
|
|
62
|
+
`no vector). The SDK batches multiple feedback calls and caps the batch at MAX_FEEDBACK_COUNT=${MAX_FEEDBACK_COUNT} ` +
|
|
63
|
+
`(SDK-only limit, NOT in onchain-constants.ts — Move has no aggregate feedback-count check). Exceeding the ` +
|
|
64
|
+
`SDK batch limit causes the SDK to refuse the call before transaction building. Each feedback entry writes ` +
|
|
65
|
+
`a String (bounded by common::DESCRIPTION, 4000 chars) and an optional u8 acceptance_score to a presenter's ` +
|
|
66
|
+
`ServiceInfo record.`,
|
|
67
|
+
affected_stakeholders: ["creator"],
|
|
68
|
+
scenario: "Caller attempts to submit 21 feedback entries in a single SDK call",
|
|
69
|
+
mitigation: "Split the feedback batch into chunks of ≤ 20 entries. If the Demand has more than 20 presenters to " +
|
|
70
|
+
"give feedback on, submit multiple transactions. Consider whether bulk feedback is appropriate — " +
|
|
71
|
+
"individualized feedback per presenter is often more meaningful.",
|
|
72
|
+
auto_fixable: false,
|
|
73
|
+
},
|
|
74
|
+
check: (ctx) => {
|
|
75
|
+
if (ctx.feedback_count === undefined)
|
|
76
|
+
return null;
|
|
77
|
+
if (ctx.feedback_count <= MAX_FEEDBACK_COUNT)
|
|
78
|
+
return null;
|
|
79
|
+
return { ...R_DEM_1_03.rule, evidence: `feedback_count=${ctx.feedback_count}, limit=${MAX_FEEDBACK_COUNT}` };
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
const R_DEM_2_01 = {
|
|
83
|
+
rule: {
|
|
84
|
+
id: "R-DEM-04",
|
|
85
|
+
level: "HIGH",
|
|
86
|
+
category: "semantic",
|
|
87
|
+
title: "present called without passport when guards vector is non-empty",
|
|
88
|
+
description: "The Move present function (demand.move:100) asserts `vector::is_empty(&self.guards)` and aborts with " +
|
|
89
|
+
"E_NEED_PASSPORT (3) if the guards vector is non-empty. When guards exist, every presenter MUST go through " +
|
|
90
|
+
"present_with_passport (or present_service_with_passport), which routes through present_with_passport_imp. " +
|
|
91
|
+
"That function looks up the specified Guard in the guards vector, calls passport::result_for_guard to " +
|
|
92
|
+
"verify the Passport, and (if service_identifier is set) extracts the submission address from the Passport. " +
|
|
93
|
+
"Calling plain `present` on a guarded Demand always aborts — there is no fallback path.",
|
|
94
|
+
affected_stakeholders: ["presenter", "creator"],
|
|
95
|
+
scenario: "Demand has 2 guards; a presenter calls present() instead of present_with_passport()",
|
|
96
|
+
mitigation: "Before presenting, query the Demand's guards vector. If non-empty, use present_with_passport and " +
|
|
97
|
+
"supply a Guard + Passport. The Guard address must already be in the guards vector (otherwise " +
|
|
98
|
+
"E_GUARD_NOT_FOUND (4) aborts). If service_identifier is set on the matching guard, the submission " +
|
|
99
|
+
"address is extracted from the Passport — do not pass a separate service parameter.",
|
|
100
|
+
related_move_error: "E_NEED_PASSPORT (3)",
|
|
101
|
+
auto_fixable: false,
|
|
102
|
+
},
|
|
103
|
+
check: (ctx) => {
|
|
104
|
+
if (!ctx.using_present_without_passport)
|
|
105
|
+
return null;
|
|
106
|
+
if (!ctx.guards_non_empty)
|
|
107
|
+
return null;
|
|
108
|
+
return { ...R_DEM_2_01.rule, evidence: `guards_non_empty=true, using present (no passport)` };
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
const R_DEM_3_01 = {
|
|
112
|
+
rule: {
|
|
113
|
+
id: "R-DEM-05",
|
|
114
|
+
level: "INFO",
|
|
115
|
+
category: "lifecycle",
|
|
116
|
+
title: "um_set_imp Registrar dependency leak — RESOLVED (P-DEM-P1-1)",
|
|
117
|
+
description: "PREVIOUS RISK: um_set_imp (demand.move:139-147) previously set self.um to the new Contact address " +
|
|
118
|
+
"BEFORE disaffiliating the old um, causing the old Contact to retain a stale affiliation record in the " +
|
|
119
|
+
"Registrar. Affiliation_change was not called for the old um, leading to a Registrar dependency leak.\n\n" +
|
|
120
|
+
"FIX (P-DEM-P1-1): um_set_imp now disaffiliates the old um via registrar::disaffiliation BEFORE setting " +
|
|
121
|
+
"the new one. The new um is then affiliated via registrar::affiliation. This matches the pattern used " +
|
|
122
|
+
"by permission_set (which uses affiliation_change). um_none_imp also disaffiliates before clearing.\n\n" +
|
|
123
|
+
"This rule is retained for historical audit and to detect regressions.",
|
|
124
|
+
affected_stakeholders: ["creator", "system"],
|
|
125
|
+
scenario: "Future regression: someone reorders um_set_imp to set new before disaffiliating old",
|
|
126
|
+
mitigation: "Keep the disaffiliate-then-set ordering. The Move invariant: any path that mutates self.um MUST call " +
|
|
127
|
+
"registrar::disaffiliation on the old value before assigning a new one.",
|
|
128
|
+
auto_fixable: false,
|
|
129
|
+
},
|
|
130
|
+
check: (ctx) => {
|
|
131
|
+
if (ctx.constants_synced)
|
|
132
|
+
return null;
|
|
133
|
+
return { ...R_DEM_3_01.rule, evidence: "constants_synced=false (regression check)" };
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
const R_DEM_2_02 = {
|
|
137
|
+
rule: {
|
|
138
|
+
id: "R-DEM-06",
|
|
139
|
+
level: "INFO",
|
|
140
|
+
category: "semantic",
|
|
141
|
+
title: "guard_add_imp service_identifier type check skipped on early return — RESOLVED (P-DEM-P1-2)",
|
|
142
|
+
description: "PREVIOUS RISK: guard_add_imp (demand.move:213-242) previously had the service_identifier type check " +
|
|
143
|
+
"AFTER the early-return path that updates an existing guard's service_identifier. When a guard with " +
|
|
144
|
+
"the same address already existed, the function returned before validating the new service_identifier " +
|
|
145
|
+
"against guard::get_submission_object_type. This allowed setting an invalid service_identifier that " +
|
|
146
|
+
"would later fail at present_with_passport time with E_INVALID_SERVICE_OBJECT_TYPE (common.move:13).\n\n" +
|
|
147
|
+
"FIX (P-DEM-P1-2): The service_identifier type check now runs FIRST (demand.move:218-222), BEFORE the " +
|
|
148
|
+
"duplicate-detection loop. common::assert_service_object_type is called for any non-None service_identifier, " +
|
|
149
|
+
"ensuring both the insert and update paths validate the type.\n\n" +
|
|
150
|
+
"This rule is retained for historical audit and to detect regressions.",
|
|
151
|
+
affected_stakeholders: ["creator", "presenter"],
|
|
152
|
+
scenario: "Future regression: someone moves the type check back to after the duplicate-detection loop",
|
|
153
|
+
mitigation: "Keep the type check at the top of guard_add_imp. The Move invariant: any service_identifier provided " +
|
|
154
|
+
"to guard_add MUST be validated via guard::get_submission_object_type + common::assert_service_object_type " +
|
|
155
|
+
"BEFORE any mutation of the guards vector.",
|
|
156
|
+
auto_fixable: false,
|
|
157
|
+
},
|
|
158
|
+
check: (ctx) => {
|
|
159
|
+
if (ctx.constants_synced)
|
|
160
|
+
return null;
|
|
161
|
+
return { ...R_DEM_2_02.rule, evidence: "constants_synced=false (regression check)" };
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
const R_DEM_4_01 = {
|
|
165
|
+
rule: {
|
|
166
|
+
id: "R-DEM-07",
|
|
167
|
+
level: "INFO",
|
|
168
|
+
category: "knowledge",
|
|
169
|
+
title: "extractDemandInfo expects non-existent Move fields — RESOLVED (P-DEM-P1-3)",
|
|
170
|
+
description: "PREVIOUS RISK: extractDemandInfo in demand-matching.ts previously read fields (tags, maxPrice, " +
|
|
171
|
+
"scenario, minTrustScore, keywords) that do NOT exist on the Move Demand struct. The Move struct only " +
|
|
172
|
+
"has: description, location, rewards, guards, presenters, um, permission. This caused the matching " +
|
|
173
|
+
"engine to silently produce undefined values when fed raw on-chain query results.\n\n" +
|
|
174
|
+
"FIX (P-DEM-P1-3): extractDemandInfo now documents the caller-enrichment contract. Only `location` maps " +
|
|
175
|
+
"directly to the Move Demand struct; all other fields (tags, maxPrice, scenario, minTrustScore, keywords) " +
|
|
176
|
+
"MUST be injected by the caller before calling matchDemand. The caller is responsible for sourcing " +
|
|
177
|
+
"this data from Service tags, Reward objects, user input, or NLP on the description.\n\n" +
|
|
178
|
+
"This rule is retained for historical audit and to detect regressions.",
|
|
179
|
+
affected_stakeholders: ["system"],
|
|
180
|
+
scenario: "Future regression: someone removes the caller-enrichment contract docs from extractDemandInfo",
|
|
181
|
+
mitigation: "Keep the [caller-enriched] / [on-chain] annotations on DemandInfo fields. The matching engine must " +
|
|
182
|
+
"never query on-chain data directly — it is a pure scoring function over caller-injected data.",
|
|
183
|
+
auto_fixable: false,
|
|
184
|
+
},
|
|
185
|
+
check: (ctx) => {
|
|
186
|
+
if (ctx.constants_synced)
|
|
187
|
+
return null;
|
|
188
|
+
return { ...R_DEM_4_01.rule, evidence: "constants_synced=false (regression check)" };
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
const R_DEM_4_02 = {
|
|
192
|
+
rule: {
|
|
193
|
+
id: "R-DEM-08",
|
|
194
|
+
level: "INFO",
|
|
195
|
+
category: "knowledge",
|
|
196
|
+
title: "permission_set not exposed in SDK — RESOLVED (DE-D-2=A)",
|
|
197
|
+
description: "PREVIOUS GAP: The Move permission_set function (demand.move:286) was not exposed as a standalone " +
|
|
198
|
+
"function in the SDK's call/demand.ts. Callers could not change the Permission object bound to a Demand " +
|
|
199
|
+
"after creation.\n\n" +
|
|
200
|
+
"RESOLUTION (DE-D-2=A): permission_set is now exposed via the CallPermission.apply mechanism. The SDK " +
|
|
201
|
+
"wraps permission_set by routing it through CallPermission, which performs the assert_owner check on the " +
|
|
202
|
+
"old Permission and updates the Demand's bound permission. The Registrar's affiliation_change is called " +
|
|
203
|
+
"to migrate the affiliation from the old Permission to the new one.\n\n" +
|
|
204
|
+
"Permission indices for Demand (demand.move:20): 400=DEMAND_NEW, 401=DEMAND_DESCRIPTION, 402=DEMAND_LOCATION, " +
|
|
205
|
+
"404=DEMAND_GUARD, 405=DEMAND_REWARD, 406=DEMAND_FEEDBACK, 407=DEMAND_OWNER_RECEIVE, 408=DEMAND_UM.\n\n" +
|
|
206
|
+
"This rule is retained for historical audit and to detect regressions.",
|
|
207
|
+
affected_stakeholders: ["creator", "system"],
|
|
208
|
+
scenario: "Future regression: someone removes the CallPermission.apply path for permission_set",
|
|
209
|
+
mitigation: "Keep permission_set exposed via CallPermission.apply. The Move invariant: permission_set requires " +
|
|
210
|
+
"permission::assert_owner(old) and MUST call registrar::affiliation_change to migrate the affiliation.",
|
|
211
|
+
auto_fixable: false,
|
|
212
|
+
},
|
|
213
|
+
check: (ctx) => {
|
|
214
|
+
if (ctx.constants_synced)
|
|
215
|
+
return null;
|
|
216
|
+
return { ...R_DEM_4_02.rule, evidence: "constants_synced=false (regression check)" };
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
export const DEMAND_RISK_RULES = [
|
|
220
|
+
R_DEM_1_01,
|
|
221
|
+
R_DEM_1_02,
|
|
222
|
+
R_DEM_1_03,
|
|
223
|
+
R_DEM_2_01,
|
|
224
|
+
R_DEM_3_01,
|
|
225
|
+
R_DEM_2_02,
|
|
226
|
+
R_DEM_4_01,
|
|
227
|
+
R_DEM_4_02,
|
|
228
|
+
];
|
|
229
|
+
export function checkDemandRisks(ctx) {
|
|
230
|
+
const risks = [];
|
|
231
|
+
for (const rule of DEMAND_RISK_RULES) {
|
|
232
|
+
const r = rule.check(ctx);
|
|
233
|
+
if (r)
|
|
234
|
+
risks.push(r);
|
|
235
|
+
}
|
|
236
|
+
return risks;
|
|
237
|
+
}
|
|
238
|
+
export function getDemandRiskById(id) {
|
|
239
|
+
return DEMAND_RISK_RULES.find(r => r.rule.id === id)?.rule;
|
|
240
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface SemanticToDemandSchemaRule {
|
|
2
|
+
id: string;
|
|
3
|
+
pattern_name: string;
|
|
4
|
+
configuration_classification: "open" | "guarded" | "um_managed";
|
|
5
|
+
semantic_intent: string;
|
|
6
|
+
match_keywords: string[];
|
|
7
|
+
schema_elements: {
|
|
8
|
+
required_fields: string[];
|
|
9
|
+
optional_fields: string[];
|
|
10
|
+
presentation_path: "plain_present" | "present_with_passport" | "either";
|
|
11
|
+
um_recommendation: string;
|
|
12
|
+
};
|
|
13
|
+
constraints: string[];
|
|
14
|
+
example: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
export declare const SEMANTIC_TO_DEMAND_SCHEMA_RULES: SemanticToDemandSchemaRule[];
|
|
17
|
+
export interface DemandFieldTranslation {
|
|
18
|
+
field_name: string;
|
|
19
|
+
move_field?: string;
|
|
20
|
+
value_type: string;
|
|
21
|
+
semantic: string;
|
|
22
|
+
format_example: string;
|
|
23
|
+
validation_rules: string[];
|
|
24
|
+
}
|
|
25
|
+
export declare const DEMAND_FIELD_TRANSLATIONS: DemandFieldTranslation[];
|
|
26
|
+
export interface DemandConstraintRule {
|
|
27
|
+
id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
validation_logic: string;
|
|
31
|
+
failure_message: string;
|
|
32
|
+
related_field: string;
|
|
33
|
+
}
|
|
34
|
+
export declare const DEMAND_CONSTRAINT_RULES: DemandConstraintRule[];
|
|
35
|
+
export interface DemandExplainInput {
|
|
36
|
+
description?: string;
|
|
37
|
+
location?: string;
|
|
38
|
+
rewards?: string[];
|
|
39
|
+
guards?: {
|
|
40
|
+
guard: string;
|
|
41
|
+
service_identifier?: number | null;
|
|
42
|
+
}[];
|
|
43
|
+
um?: string | null;
|
|
44
|
+
permission?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface DemandExplanation {
|
|
47
|
+
summary: string;
|
|
48
|
+
configuration_classification: string;
|
|
49
|
+
presentation_path: string;
|
|
50
|
+
binding_status: string;
|
|
51
|
+
size_status: string;
|
|
52
|
+
warnings: string[];
|
|
53
|
+
recommendations: string[];
|
|
54
|
+
}
|
|
55
|
+
export declare function explainDemand(input: DemandExplainInput): DemandExplanation;
|