@wowok/agent-mcp 3.2.6 → 3.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chain-semantics/field-capability.js +1 -1
- package/dist/chain-semantics/freeze-map.js +1 -1
- package/dist/chain-semantics/fund-flow.js +1 -1
- package/dist/chain-semantics/guard-verbs.js +1 -1
- package/dist/chain-semantics/object-graph.js +1 -1
- package/dist/communication/wts-attestation.js +1 -1
- package/dist/composition/audit.js +1 -1
- package/dist/composition/compile.d.ts +3 -2
- package/dist/composition/compile.js +1 -1
- package/dist/composition/inflight.d.ts +27 -0
- package/dist/composition/inflight.js +1 -0
- package/dist/config/config-audit.spec.js +1 -1
- package/dist/customer/account-events.js +1 -1
- package/dist/customer/order-monitor.js +1 -1
- package/dist/evaluation/builtins/graph-service.spec.js +1 -1
- package/dist/evaluation/engine.js +1 -1
- package/dist/experience/realtime-feedback.js +1 -1
- package/dist/extensions/business-modules.d.ts +1 -1
- package/dist/extensions/business-modules.js +1 -1
- package/dist/extensions/constraint-registry.d.ts +6 -1
- package/dist/extensions/constraint-registry.js +1 -1
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/index.js +1 -1
- package/dist/extensions/industry-pack.d.ts +5 -0
- package/dist/extensions/industry-pack.js +1 -1
- package/dist/extensions/mode-evaluator.d.ts +3 -2
- package/dist/extensions/mode-evaluator.js +1 -1
- package/dist/extensions/modes.js +1 -1
- package/dist/graph/onchain/analyze.js +1 -1
- package/dist/graph/onchain/analyze.spec.js +1 -1
- package/dist/graph/onchain/anti-cheat.d.ts +32 -2
- package/dist/graph/onchain/anti-cheat.js +1 -1
- package/dist/graph/onchain/anti-cheat.spec.js +1 -1
- package/dist/graph/onchain/edge-schema.js +1 -1
- package/dist/graph/onchain/expand.js +1 -1
- package/dist/graph/onchain/exposure.js +1 -1
- package/dist/graph/onchain/extract.js +1 -1
- package/dist/graph/onchain/graph-policy.spec.js +1 -1
- package/dist/graph/onchain/index.d.ts +2 -2
- package/dist/graph/onchain/index.js +1 -1
- package/dist/graph/onchain/project-relationship.js +1 -1
- package/dist/graph/onchain/table-ledger.spec.js +1 -1
- package/dist/graph/onchain/types.d.ts +3 -0
- package/dist/harness/index.d.ts +1 -0
- package/dist/harness/index.js +1 -1
- package/dist/harness/operation-id.d.ts +1 -0
- package/dist/harness/operation-id.js +1 -0
- package/dist/harness/recover.js +1 -1
- package/dist/index.js +1 -1
- package/dist/knowledge/arbitration-ledger.js +1 -1
- package/dist/knowledge/arbitration-venue-order.d.ts +25 -0
- package/dist/knowledge/arbitration-venue-order.js +1 -0
- package/dist/knowledge/audit-rules.d.ts +10 -0
- package/dist/knowledge/audit-rules.js +1 -1
- package/dist/knowledge/baselines/risk-baselines.spec.js +1 -1
- package/dist/knowledge/baselines/rules/graph.json +81 -0
- package/dist/knowledge/baselines/rules/guard.json +96 -1
- package/dist/knowledge/baselines/rules/machine.json +3 -3
- package/dist/knowledge/baselines/rules/plan.json +109 -8
- package/dist/knowledge/baselines/semantic-facts.js +1 -1
- package/dist/knowledge/builtin-templates.d.ts +17 -2
- package/dist/knowledge/builtin-templates.js +1 -1
- package/dist/knowledge/discount-threshold.d.ts +11 -0
- package/dist/knowledge/discount-threshold.js +1 -1
- package/dist/knowledge/event-semantics.js +1 -1
- package/dist/knowledge/fund-layer.js +1 -1
- package/dist/knowledge/getting-started.js +1 -1
- package/dist/knowledge/guard-bindings.js +1 -1
- package/dist/knowledge/guard-design-patterns.d.ts +1 -1
- package/dist/knowledge/guard-design-patterns.js +1 -1
- package/dist/knowledge/guard-field-cognition.js +1 -1
- package/dist/knowledge/guard-ledger.js +1 -1
- package/dist/knowledge/guard-lint.d.ts +1 -0
- package/dist/knowledge/guard-lint.js +1 -1
- package/dist/knowledge/guard-node-gates.d.ts +4 -0
- package/dist/knowledge/guard-node-gates.js +1 -0
- package/dist/knowledge/guard-puzzle.js +1 -1
- package/dist/knowledge/guard-render.js +1 -1
- package/dist/knowledge/guard-risk.d.ts +1 -0
- package/dist/knowledge/guard-risk.js +1 -1
- package/dist/knowledge/guard-submission-brief.d.ts +6 -0
- package/dist/knowledge/guard-submission-brief.js +1 -1
- package/dist/knowledge/guard-submission-prompt.d.ts +1 -0
- package/dist/knowledge/guard-submission-prompt.js +1 -1
- package/dist/knowledge/guard-templates.d.ts +2 -1
- package/dist/knowledge/guard-templates.js +1 -1
- package/dist/knowledge/guard-translation.js +1 -1
- package/dist/knowledge/index.d.ts +2 -2
- package/dist/knowledge/index.js +1 -1
- package/dist/knowledge/industry-registry.js +1 -1
- package/dist/knowledge/jsonrpc-enum.js +1 -1
- package/dist/knowledge/machine-topology.d.ts +6 -0
- package/dist/knowledge/machine-topology.js +1 -1
- package/dist/knowledge/order-ledger.js +1 -1
- package/dist/knowledge/reputation-rules.d.ts +3 -9
- package/dist/knowledge/reputation-rules.js +1 -1
- package/dist/knowledge/reward-ledger.js +1 -1
- package/dist/knowledge/safety-rules.d.ts +10 -1
- package/dist/knowledge/safety-rules.js +1 -1
- package/dist/knowledge/scenario-modes.js +1 -1
- package/dist/knowledge/settlement-semantics.d.ts +1 -0
- package/dist/knowledge/settlement-semantics.js +1 -0
- package/dist/knowledge/template-loader.d.ts +22 -0
- package/dist/knowledge/template-loader.js +1 -1
- package/dist/knowledge/template-registry.js +1 -1
- package/dist/knowledge/template-scanner.d.ts +16 -0
- package/dist/knowledge/template-scanner.js +1 -1
- package/dist/knowledge/tool-constraints.js +1 -1
- package/dist/knowledge/tools-reference.js +1 -1
- package/dist/knowledge/workflow-guidance.d.ts +8 -3
- package/dist/knowledge/workflow-guidance.js +1 -1
- package/dist/monitor/MonitorLoop.js +1 -1
- package/dist/participation/allocation-advice.js +1 -1
- package/dist/participation/customer-interest.js +1 -1
- package/dist/participation/radar-core.d.ts +7 -2
- package/dist/participation/radar-core.js +1 -1
- package/dist/playbooks/service-build/business-puzzle.js +1 -1
- package/dist/playbooks/service-build/machine-panorama.js +1 -1
- package/dist/playbooks/service-build/merchant-guide.d.ts +46 -15
- package/dist/playbooks/service-build/merchant-guide.js +1 -1
- package/dist/playbooks/service-build/migration-planner.d.ts +7 -0
- package/dist/playbooks/service-build/migration-planner.js +1 -1
- package/dist/playbooks/service-build/object-panorama.d.ts +28 -1
- package/dist/playbooks/service-build/object-panorama.js +1 -1
- package/dist/playbooks/service-build/participation-radar.d.ts +2 -0
- package/dist/playbooks/service-build/participation-radar.js +1 -1
- package/dist/playbooks/service-build/pipeline-actions.d.ts +1 -1
- package/dist/playbooks/service-build/pipeline-actions.js +1 -1
- package/dist/playbooks/service-build/relationship-profile.js +1 -1
- package/dist/playbooks/service-build/reverse-mapping-nk4.spec.js +1 -1
- package/dist/playbooks/service-build/reverse-mapping.js +1 -1
- package/dist/playbooks/service-build/risk-aggregator.d.ts +1 -1
- package/dist/playbooks/service-build/risk-aggregator.js +1 -1
- package/dist/playbooks/service-build/service-panorama.js +1 -1
- package/dist/playbooks/service-build/service-quote.js +1 -1
- package/dist/playbooks/service-build/service-quote.spec.js +1 -1
- package/dist/relationship/derivation.d.ts +1 -0
- package/dist/review/index.js +1 -1
- package/dist/runtime/instance-registry.d.ts +8 -0
- package/dist/runtime/instance-registry.js +1 -0
- package/dist/safety/confirm-gate.js +1 -1
- package/dist/safety/preview.d.ts +1 -0
- package/dist/safety/preview.js +1 -1
- package/dist/schema/benchmark-migration/index.d.ts +28 -0
- package/dist/schema/benchmark-migration/index.js +1 -1
- package/dist/schema/call/allocation.d.ts +1 -1
- package/dist/schema/call/arbitration.d.ts +4 -4
- package/dist/schema/call/arbitration.js +1 -1
- package/dist/schema/call/base.d.ts +122 -5
- package/dist/schema/call/base.js +1 -1
- package/dist/schema/call/bridge.d.ts +16 -0
- package/dist/schema/call/contact.d.ts +1 -1
- package/dist/schema/call/contact.js +1 -1
- package/dist/schema/call/demand.d.ts +1 -1
- package/dist/schema/call/error-codes.d.ts +1 -1
- package/dist/schema/call/error-codes.js +1 -1
- package/dist/schema/call/guard.d.ts +10 -3
- package/dist/schema/call/guard.js +1 -1
- package/dist/schema/call/handler.js +1 -1
- package/dist/schema/call/machine.d.ts +8 -1
- package/dist/schema/call/machine.js +1 -1
- package/dist/schema/call/order.d.ts +1 -1
- package/dist/schema/call/order.js +1 -1
- package/dist/schema/call/payment.js +1 -1
- package/dist/schema/call/permission-handler.js +1 -1
- package/dist/schema/call/permission.d.ts +1 -1
- package/dist/schema/call/personal.d.ts +4 -4
- package/dist/schema/call/progress.d.ts +47 -1
- package/dist/schema/call/progress.js +1 -1
- package/dist/schema/call/proof.js +1 -1
- package/dist/schema/call/repository.d.ts +5 -5
- package/dist/schema/call/repository.js +1 -1
- package/dist/schema/call/reward.d.ts +1 -1
- package/dist/schema/call/reward.js +1 -1
- package/dist/schema/call/semantic.js +1 -1
- package/dist/schema/call/service.d.ts +12 -9
- package/dist/schema/call/service.js +1 -1
- package/dist/schema/call/treasury.d.ts +1 -1
- package/dist/schema/common/index.d.ts +4 -4
- package/dist/schema/common/index.js +1 -1
- package/dist/schema/goal/index.d.ts +23 -0
- package/dist/schema/goal/planning.d.ts +50 -1
- package/dist/schema/goal/planning.js +1 -1
- package/dist/schema/industry-pack/index.d.ts +40 -0
- package/dist/schema/industry-pack/index.js +1 -1
- package/dist/schema/keeper/index.d.ts +13 -0
- package/dist/schema/local/index.d.ts +96 -0
- package/dist/schema/local/index.js +1 -1
- package/dist/schema/messenger/index.d.ts +17 -0
- package/dist/schema/messenger/index.js +1 -1
- package/dist/schema/operations.d.ts +61 -23
- package/dist/schema/operations.js +1 -1
- package/dist/schema/query/bi.d.ts +70 -6
- package/dist/schema/query/bi.js +1 -1
- package/dist/schema/query/index.d.ts +206 -54
- package/dist/schema/query/index.js +1 -1
- package/dist/schema/schema-query/index.d.ts +1 -0
- package/dist/schema/schema-query/index.js +1 -1
- package/dist/schema/schema-version.d.ts +1 -1
- package/dist/schema/schema-version.js +1 -1
- package/dist/schema/utils/permission-machine-check.d.ts +2 -0
- package/dist/schema/utils/permission-machine-check.js +1 -1
- package/dist/schema/workflow/index.d.ts +1 -1
- package/dist/schema/workspace/index.d.ts +1 -1
- package/dist/schema-query-impl/index.js +1 -1
- package/dist/schemas/account_operation.output.json +47 -0
- package/dist/schemas/account_operation.schema.json +3 -3
- package/dist/schemas/benchmark_migration_operation.output.json +66 -4
- package/dist/schemas/benchmark_migration_operation.schema.json +83 -0
- package/dist/schemas/bridge_operation.output.json +47 -0
- package/dist/schemas/goal_operation.schema.json +104 -0
- package/dist/schemas/guard2file.output.json +6 -1
- package/dist/schemas/guard2file.schema.json +9 -0
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/industry_pack_operation.output.json +91 -0
- package/dist/schemas/industry_pack_operation.schema.json +19 -1
- package/dist/schemas/keeper_operation.output.json +44 -0
- package/dist/schemas/local_cache_operation.output.json +47 -0
- package/dist/schemas/local_history_operation.output.json +47 -0
- package/dist/schemas/local_info_operation.output.json +47 -0
- package/dist/schemas/local_mark_operation.output.json +47 -0
- package/dist/schemas/machineNode2file.output.json +6 -1
- package/dist/schemas/machineNode2file.schema.json +9 -0
- package/dist/schemas/messenger_operation.output.json +52 -0
- package/dist/schemas/messenger_operation.schema.json +4 -4
- package/dist/schemas/monitor_events.output.json +44 -0
- package/dist/schemas/monitor_subscription.output.json +44 -0
- package/dist/schemas/onchain_events.output.json +44 -0
- package/dist/schemas/onchain_operations.output.json +140 -5
- package/dist/schemas/onchain_operations.schema.json +180 -107
- package/dist/schemas/onchain_operations_allocation.schema.json +5 -5
- package/dist/schemas/onchain_operations_arbitration.schema.json +12 -9
- package/dist/schemas/onchain_operations_contact.schema.json +8 -7
- package/dist/schemas/onchain_operations_demand.schema.json +6 -5
- package/dist/schemas/onchain_operations_gen_passport.schema.json +5 -5
- package/dist/schemas/onchain_operations_gen_proof.schema.json +1 -1
- package/dist/schemas/onchain_operations_guard.schema.json +6 -6
- package/dist/schemas/onchain_operations_machine.schema.json +9 -8
- package/dist/schemas/onchain_operations_order.schema.json +8 -7
- package/dist/schemas/onchain_operations_payment.schema.json +1 -1
- package/dist/schemas/onchain_operations_permission.schema.json +1 -0
- package/dist/schemas/onchain_operations_personal.schema.json +2 -2
- package/dist/schemas/onchain_operations_progress.schema.json +64 -6
- package/dist/schemas/onchain_operations_proof.schema.json +6 -6
- package/dist/schemas/onchain_operations_repository.schema.json +10 -9
- package/dist/schemas/onchain_operations_reward.schema.json +8 -7
- package/dist/schemas/onchain_operations_service.schema.json +23 -19
- package/dist/schemas/onchain_operations_treasury.schema.json +6 -5
- package/dist/schemas/onchain_table_data.output.json +88 -20
- package/dist/schemas/onchain_table_data.schema.json +21 -21
- package/dist/schemas/query_toolkit.output.json +249 -39
- package/dist/schemas/query_toolkit.schema.json +51 -27
- package/dist/schemas/schema_query.schema.json +4 -0
- package/dist/schemas/workflow_operation.schema.json +5 -5
- package/dist/schemas/wowok_buildin_info.output.json +220 -4
- package/dist/schemas/wowok_buildin_info.schema.json +2 -2
- package/dist/tools/handlers/benchmark-migration.d.ts +22 -0
- package/dist/tools/handlers/benchmark-migration.js +1 -1
- package/dist/tools/handlers/config.js +1 -1
- package/dist/tools/handlers/dispatch-expectations.d.ts +0 -1
- package/dist/tools/handlers/dispatch-expectations.js +1 -1
- package/dist/tools/handlers/file-export.js +1 -1
- package/dist/tools/handlers/industry-pack.js +1 -1
- package/dist/tools/handlers/local.js +1 -1
- package/dist/tools/handlers/messenger.js +1 -1
- package/dist/tools/handlers/onchain.js +1 -1
- package/dist/tools/handlers/query.d.ts +1 -0
- package/dist/tools/handlers/query.js +1 -1
- package/dist/tools/handlers/review-chain.d.ts +22 -0
- package/dist/tools/handlers/review-chain.js +1 -0
- package/dist/tools/handlers/schema-query.js +1 -1
- package/dist/tools/index.js +1 -1
- package/dist/tools/move-fn-index.gen.js +1 -1
- package/dist/tools/registry/agent.js +1 -1
- package/dist/tools/registry/business.js +1 -1
- package/dist/tools/registry/config.js +1 -1
- package/dist/tools/registry/evaluation.js +1 -1
- package/dist/tools/registry/files.js +1 -1
- package/dist/tools/registry/identity.js +1 -1
- package/dist/tools/registry/local.js +1 -1
- package/dist/tools/registry/messenger.js +1 -1
- package/dist/tools/registry/monitor.js +1 -1
- package/dist/tools/registry/onchain.js +1 -1
- package/dist/tools/registry/query.js +1 -1
- package/dist/tools/rules-hook.js +1 -1
- package/dist/tools/runtime-health.d.ts +10 -0
- package/dist/tools/runtime-health.js +1 -0
- package/dist/tools/upgrade-check.d.ts +33 -1
- package/dist/tools/upgrade-check.js +1 -1
- package/dist/tools/wip-deploy-assist.d.ts +6 -0
- package/dist/tools/wip-deploy-assist.js +1 -1
- package/dist/tools/wrap.d.ts +3 -0
- package/dist/tools/wrap.js +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export type AuditSeverity = "error" | "warning" | "info";
|
|
2
|
+
declare function numericAmount(v: unknown): number | undefined;
|
|
3
|
+
export { numericAmount };
|
|
2
4
|
export interface AuditFinding {
|
|
3
5
|
rule_id: string;
|
|
4
6
|
severity: AuditSeverity;
|
|
@@ -30,11 +32,19 @@ export declare function typeParameterOf(d: any): string | undefined;
|
|
|
30
32
|
export declare const DISPUTE_FAMILY_NODE_REGEX: RegExp;
|
|
31
33
|
export declare const FUND_TERMINAL_NODE_REGEX: RegExp;
|
|
32
34
|
export declare const ANTI_PATTERN_NODE_REGEX: RegExp;
|
|
35
|
+
export declare const REMEDY_FAMILY_NODE_REGEX: RegExp;
|
|
36
|
+
export declare function isRemedyLoopEdge(fromNode: string, toNode: string): boolean;
|
|
37
|
+
export type LoopTier = "renewal" | "remedy" | "charge";
|
|
38
|
+
export declare function classifyLoopCycle(cycleNodes: string[]): LoopTier;
|
|
33
39
|
export interface MachineNodeAudit {
|
|
34
40
|
critical: string[];
|
|
35
41
|
warnings: string[];
|
|
36
42
|
}
|
|
37
43
|
export declare function auditMachineNodes(nodes: unknown[]): MachineNodeAudit;
|
|
44
|
+
export declare function computeTerminalReachability(nodes: unknown[]): {
|
|
45
|
+
terminals: string[];
|
|
46
|
+
unreachable: string[];
|
|
47
|
+
};
|
|
38
48
|
export declare const AUDIT_RULES: AuditRule[];
|
|
39
49
|
export declare function auditService(data: any, context?: AuditContext): AuditFinding[];
|
|
40
50
|
export declare function hasBlockingErrors(findings: AuditFinding[]): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MAX_INDEMNITY_MULTIPLE}from'./onchain-constants.js';import{lintForwardAmbiguity}from'./machine-topology.js';function numericAmount(a){if(typeof a==='number')return Number['isFinite'](a)?a:undefined;if(typeof a==='string'){const b=a['trim']();if(/^\d+$/['test'](b))return Number(b);}return undefined;}export function salesItemsOf(a){if(Array['isArray'](a?.['sales']))return a['sales'];if(Array['isArray'](a?.['sales']?.['sales']))return a['sales']['sales'];return[];}export function allocatorCountOf(a){const b=a?.['order_allocators'];if(Array['isArray'](b))return b['length'];if(Array['isArray'](b?.['allocators']))return b['allocators']['length'];return 0x0;}export function arbitrationRefsOf(b){const c=b?.['arbitrations'];if(Array['isArray'](c))return c['filter'](e=>typeof e==='string');if(Array['isArray'](c?.['objects']))return c['objects']['filter'](e=>typeof e==='string');return[];}export function compensationFundOf(a){if(a?.['compensation_fund_add']?.['balance']!=null)return a['compensation_fund_add']['balance'];if(a?.['compensation_fund']!=null)return a['compensation_fund'];return undefined;}export function serviceNameOf(a){if(typeof a?.['object']==='string')return a['object'];if(typeof a?.['object']?.['name']==='string'&&a['object']['name'])return a['object']['name'];if(typeof a?.['namedNew']?.['name']==='string'&&a['namedNew']['name'])return a['namedNew']['name'];return undefined;}export function typeParameterOf(a){if(typeof a?.['type_parameter']==='string'&&a['type_parameter'])return a['type_parameter'];if(typeof a?.['object']?.['type_parameter']==='string'&&a['object']['type_parameter'])return a['object']['type_parameter'];if(typeof a?.['namedNew']?.['type_parameter']==='string'&&a['namedNew']['type_parameter'])return a['namedNew']['type_parameter'];return undefined;}export const DISPUTE_FAMILY_NODE_REGEX=/(^|_)(disputed?|arbitration|arb)(_|$)/i;export const FUND_TERMINAL_NODE_REGEX=/^(refund|refunded|deposit_refunded|deposit_deducted|cancel|cancelled)$/i;export const ANTI_PATTERN_NODE_REGEX=new RegExp(DISPUTE_FAMILY_NODE_REGEX['source']+'|'+FUND_TERMINAL_NODE_REGEX['source'],'i');export function auditMachineNodes(a){const b=[],c=[];if(!Array['isArray'](a)||a['length']===0x0)return c['push']('pre_publish:\x20machine\x20node\x20set\x20unavailable\x20—\x20topology\x20not\x20verifiable;\x20'+'verify\x20via\x20machineNode2file\x20BEFORE\x20publish\x20(immutable\x20after\x20publish,\x20IMMUT-001)'),{'critical':b,'warnings':c};const d=a;for(const r of d){const s=typeof r?.['name']==='string'?r['name']:'';s&&ANTI_PATTERN_NODE_REGEX['test'](s)&&b['push']('R-M1-11:\x20machine\x20node\x20\x22'+s+'\x22\x20models\x20dispute/refund\x20flow\x20—\x20'+'refunds\x20must\x20route\x20via\x20an\x20Allocator\x20triggered\x20by\x20business\x20states,\x20'+'disputes\x20via\x20the\x20separate\x20Arbitration\x20object\x20(off-Machine)');}const e=new Set();for(const t of d){const u=typeof t?.['name']==='string'?t['name']:'';if(!u)continue;e['has'](u)&&b['push']('MC-C-04:\x20duplicate\x20machine\x20node\x20name\x20\x22'+u+'\x22\x20—\x20on-chain\x20will\x20reject\x20the\x20publish\x20transaction'),e['add'](u);}const g=d['some'](v=>Array['isArray'](v?.['pairs'])&&v['pairs']['some'](w=>w?.['prev_node']===''));!g&&b['push']('Machine\x20has\x20no\x20entry\x20pair\x20(prev_node=\x22\x22)\x20—\x20Progress\x20can\x20never\x20advance\x20'+'from\x20the\x20initial\x20state;\x20orders\x20are\x20permanently\x20stuck');const h=new Map();for(const v of d){const w=typeof v?.['name']==='string'?v['name']:'';if(!w)continue;if(!h['has'](w))h['set'](w,[]);for(const x of v?.['pairs']??[]){const y=x?.['prev_node'];if(typeof y==='string'&&y!==''){const z=h['get'](y);if(z)z['push'](w);else h['set'](y,[w]);}}}const i=0x0,j=0x1,k=0x2,l=new Map(),m=[],o=A=>{l['set'](A,j);for(const B of h['get'](A)??[]){const C=l['get'](B)??i;if(C===j)m['push'](A+'->'+B);else C===i&&o(B);}l['set'](A,k);};for(const A of h['keys']()){if((l['get'](A)??i)===i)o(A);}m['length']>0x0&&c['push']('pre_publish:\x20machine\x20contains\x20loop\x20back-edge(s)\x20'+m['join'](',\x20')+'\x20—\x20on-chain\x20a\x20revisit\x20'+'is\x20NOT\x20verified\x20to\x20re-fund\x20the\x20Allocation.\x20Every\x20renewal/loop\x20forward\x20MUST\x20carry\x20the\x20new-period\x20'+'payment\x20into\x20the\x20order\x20escrow\x20atomically\x20(create\x20the\x20period\x20payment,\x20receive\x20it\x20into\x20the\x20'+'allocation,\x20and\x20advance\x20the\x20progress\x20—\x20all\x20in\x20one\x20transaction),\x20or\x20the\x20loop\x20allows\x20zero-value\x20'+'re-delivery\x20cycles\x20(test/11\x20R2-F3).\x20'+'Recommended:\x20bind\x20a\x20fund-gate\x20Guard\x20on\x20the\x20loop\x20forward\x20(allocation\x20balance\x20>=\x20period\x20price)\x20—\x20'+'note\x20the\x20allocation.balance\x20query\x20is\x20not\x20yet\x20available\x20on-chain,\x20so\x20per-period\x20NEW\x20Orders\x20remain\x20'+'the\x20safe\x20default\x20for\x20long\x20subscriptions.');for(const B of d){const C=typeof B?.['name']==='string'?B['name']:'?';for(const D of B?.['pairs']??[]){for(const E of D?.['forwards']??[]){const F=E?.['namedOperator']!==undefined&&E?.['namedOperator']!==null,G=E?.['permissionIndex']!==undefined&&E?.['permissionIndex']!==null,H=E?.['guard']!==undefined&&E?.['guard']!==null;!F&&!G&&!H&&c['push']('pre_publish:\x20node\x20\x22'+C+'\x22\x20forward\x20\x22'+String(E?.['name']??'?')+'\x22\x20has\x20no\x20executor\x20binding\x20(namedOperator\x20/\x20permissionIndex\x20/\x20guard)\x20—\x20no\x20one\x20can\x20advance\x20it');}}}const q=lintForwardAmbiguity(a,'pre_publish');return b['push'](...q['critical']),c['push'](...q['warnings']),{'critical':b,'warnings':c};}export const AUDIT_RULES=[{'id':'audit_machine_bound','description':'Service\x20should\x20have\x20a\x20Machine\x20workflow\x20bound\x20before\x20publish','severity':'warning','fields':['machine'],'check':(a,b)=>{if(!a?.['publish'])return!![];return!!a?.['machine'];},'message':()=>'Publishing\x20a\x20service\x20without\x20a\x20Machine\x20workflow.\x20Customers\x20won\x27t\x20have\x20a\x20structured\x20order\x20process.','recommendation':'Create\x20a\x20Machine\x20(workflow\x20template)\x20and\x20bind\x20it\x20to\x20the\x20service\x20before\x20publishing.\x20The\x20machine\x20field\x20becomes\x20IMMUTABLE\x20after\x20publish.'},{'id':'audit_order_allocators','description':'Service\x20should\x20have\x20order_allocators\x20for\x20fund\x20distribution','severity':'warning','fields':['order_allocators'],'check':a=>{if(!a?.['publish'])return!![];return allocatorCountOf(a)>0x0;},'message':()=>'Publishing\x20a\x20service\x20without\x20order_allocators.\x20Order\x20funds\x20cannot\x20be\x20auto-distributed\x20to\x20suppliers.','recommendation':'Configure\x20order_allocators\x20before\x20publishing\x20—\x20this\x20field\x20becomes\x20IMMUTABLE\x20after\x20publish.'},{'id':'audit_buy_guard','description':'Service\x20should\x20have\x20a\x20buy_guard\x20for\x20customer\x20screening','severity':'info','fields':['buy_guard'],'check':a=>!!a?.['buy_guard'],'message':()=>'No\x20buy_guard\x20configured\x20—\x20anyone\x20can\x20purchase\x20this\x20service\x20without\x20verification.','recommendation':'Consider\x20adding\x20a\x20Guard\x20to\x20verify\x20customer\x20eligibility\x20(e.g.,\x20identity,\x20wallet\x20balance,\x20location).'},{'id':'audit_arb_alloc_boundary','description':'Arbitration\x20and\x20Allocator\x20coexist\x20→\x20surface\x20the\x20two-system\x20boundary\x20reminder','severity':'warning','fields':['arbitrations','compensation_fund_add','compensation_fund','order_allocators'],'check':a=>{if(!a?.['publish'])return!![];const b=arbitrationRefsOf(a)['length']>0x0||compensationFundOf(a)!==undefined;return!(b&&allocatorCountOf(a)>0x0);},'message':()=>'Arbitration\x20and\x20Allocator\x20are\x20INDEPENDENT\x20systems\x20by\x20design:\x20a\x20ruling\x20records\x20the\x20case\x20and\x20pays\x20from\x20the\x20service\x20compensation\x20fund\x20—\x20it\x20never\x20moves\x20escrow\x20and\x20never\x20advances\x20the\x20workflow.\x20With\x20both\x20configured,\x20a\x20buyer\x20can\x20receive\x20BOTH\x20the\x20arbitration\x20compensation\x20AND\x20a\x20full\x20escrow\x20refund\x20unless\x20the\x20refund/settlement\x20path\x20is\x20gated.\x20This\x20is\x20a\x20boundary\x20reminder,\x20not\x20a\x20defect\x20—\x20verify\x20the\x20coupling\x20check\x20was\x20done\x20deliberately.','recommendation':'Gate\x20the\x20refund/settlement\x20allocator\x27s\x20Guard\x20on\x20order.claimed_by\x20(read-only\x20cross-system\x20evidence\x20—\x20the\x20sanctioned\x20link),\x20or\x20hold\x20the\x20final\x20settlement\x20forward\x20until\x20the\x20case\x20closes.\x20Do\x20NOT\x20couple\x20the\x20systems\x20the\x20other\x20way\x20(no\x20dispute\x20state\x20on\x20the\x20order\x20flow,\x20no\x20workflow\x20step\x20into\x20arbitration):\x20coupling\x20opens\x20the\x20double-pay\x20path.\x20For\x20per-case\x20fund\x20actions,\x20the\x20deposit-reimbursement\x20pattern\x20(guard-design\x20patterns)\x20is\x20the\x20supported\x20route.'},{'id':'audit_compensation_fund','description':'Service\x20should\x20have\x20a\x20compensation_fund\x20for\x20trust','severity':'warning','fields':['compensation_fund_add','compensation_fund'],'check':a=>compensationFundOf(a)!==undefined,'message':()=>'No\x20compensation_fund\x20configured.\x20Customers\x20have\x20no\x20financial\x20protection\x20if\x20you\x20fail\x20to\x20deliver.','recommendation':'Deposit\x20via\x20compensation_fund_add\x20{balance}\x20to\x20enable\x20arbitration\x20payouts.\x20The\x20fund\x20deters\x20fraud\x20and\x20enables\x20arbitration\x20claims.'},{'id':'audit_arbitrations','description':'Service\x20should\x20have\x20arbitration\x20options\x20for\x20dispute\x20resolution','severity':'info','fields':['arbitrations'],'check':a=>arbitrationRefsOf(a)['length']>0x0,'message':()=>'No\x20arbitration\x20configured.\x20Disputes\x20cannot\x20be\x20resolved\x20through\x20a\x20third\x20party.','recommendation':'Add\x20at\x20least\x20one\x20Arbitration\x20object\x20via\x20arbitrations:{op:\x27add\x27,\x20objects:[...]}\x20to\x20enable\x20on-chain\x20dispute\x20resolution.'},{'id':'audit_arbitration_removal_strands_awards','description':'Removing\x20an\x20authorized\x20venue\x20can\x20strand\x20an\x20award\x20it\x20already\x20ruled\x20on','severity':'error','fields':['arbitrations'],'check':a=>{const b=a?.['arbitrations']?.['remove']??a?.['arbitrations']?.['clear'],c=Array['isArray'](b)?b['length']>0x0:a?.['arbitrations']?.['op']==='clear';if(!c)return!![];if(arbitrationRefsOf(a)['length']>0x0)return!![];return compensationFundOf(a)===undefined;},'message':a=>{const b=a?.['arbitrations']?.['clear']?'every\x20authorized\x20venue':'venue(s)\x20'+(a?.['arbitrations']?.['remove']??[])['join'](',\x20');return'Removing\x20'+b+'\x20while\x20a\x20compensation\x20fund\x20is\x20configured\x20makes\x20any\x20award\x20it\x20already\x20ruled\x20on\x20UNPAYABLE:\x20an\x20on-chain\x20payout\x20now\x20requires\x20the\x20deciding\x20venue\x20to\x20still\x20be\x20on\x20the\x20Service\x27s\x20allowlist,\x20so\x20paying\x20out\x20aborts\x20with\x20E_ARBITRATION_NOT_ALLOWED=39\x20and\x20the\x20escrowed\x20funds\x20stay\x20stranded.';},'recommendation':'Before\x20removing\x20a\x20venue,\x20confirm\x20no\x20case\x20it\x20ruled\x20on\x20is\x20still\x20awaiting\x20compensation\x20payout\x20(query\x20the\x20Arb\x20objects\x20for\x20status\x20Arbitrated,\x20not\x20Finished).\x20Add\x20the\x20replacement\x20venue\x20FIRST,\x20drain\x20the\x20old\x20venue\x27s\x20cases,\x20and\x20only\x20then\x20remove\x20it.\x20A\x20buyer\x20should\x20never\x20be\x20left\x20holding\x20an\x20uncollectable\x20award.'},{'id':'audit_price','description':'Service\x20should\x20have\x20at\x20least\x20one\x20priced\x20sale\x20item','severity':'error','fields':['sales'],'check':a=>{const b=salesItemsOf(a);if(b['length']===0x0)return!![];return b['some'](c=>c?.['price']!==undefined&&c?.['price']!==null);},'message':()=>'Sales\x20list\x20present\x20but\x20no\x20item\x20has\x20a\x20price.\x20Customers\x20cannot\x20place\x20orders\x20without\x20knowing\x20the\x20cost.','recommendation':'Set\x20price\x20on\x20each\x20sales\x20item\x20(smallest-unit\x20string\x20or\x20display\x20form\x20like\x20\x272.5WOW\x27).'},{'id':'audit_compensation_fund_covers_award_ceiling','description':'compensation_fund\x20must\x20cover\x20the\x203x\x20award\x20ceiling\x20of\x20the\x20largest\x20sale','severity':'warning','fields':['compensation_fund_add','compensation_fund','sales'],'check':a=>{if(!a?.['publish'])return!![];const b=compensationFundOf(a);if(b===undefined)return!![];const c=numericAmount(b);if(c===undefined)return!![];if(c===0x0)return![];const e=salesItemsOf(a)['map'](g=>numericAmount(g?.['price']))['filter'](g=>g!==undefined&&g>0x0);if(e['length']===0x0)return!![];const f=e['reduce']((g,h)=>g+h,0x0);return c>=MAX_INDEMNITY_MULTIPLE*f;},'message':()=>'compensation_fund\x20does\x20not\x20cover\x20the\x20award\x20ceiling.\x20An\x20award\x20is\x20hard-capped\x20at\x20'+MAX_INDEMNITY_MULTIPLE+'x\x20'+'the\x20order\x20amount\x20(arb.move\x20MAX_INDEMNITY_MULTIPLE,\x20enforced\x20at\x20ruling\x20time),\x20so\x20a\x20ruling\x20at\x20the\x20ceiling\x20'+'would\x20abort\x20the\x20buyer\x27s\x20claim\x20with\x2027\x20(E_COMPENSATION_NOT_MATCH)\x20—\x20the\x20ruling\x20stands\x20but\x20is\x20unpayable\x20'+'until\x20you\x20deposit,\x20and\x20the\x20abort\x20does\x20NOT\x20consume\x20the\x20claim.','recommendation':'Top\x20up\x20to\x20at\x20least\x20'+MAX_INDEMNITY_MULTIPLE+'x\x20your\x20largest\x20single\x20order\x20via\x20compensation_fund_add.\x20Above\x20'+(MAX_INDEMNITY_MULTIPLE+'x\x20is\x20optional:\x20it\x20only\x20buys\x20tolerance\x20for\x20several\x20CONCURRENT\x20claims\x20against\x20the\x20')+'one\x20per-Service\x20pool\x20(there\x20is\x20no\x20on-chain\x20concurrency\x20limit),\x20which\x20is\x20a\x20capital-allocation\x20choice.'},{'id':'audit_description','description':'Service\x20should\x20have\x20a\x20description','severity':'warning','fields':['description'],'check':a=>typeof a?.['description']==='string'&&a['description']['length']>0x0,'message':()=>'Service\x20has\x20no\x20description.\x20Customers\x20won\x27t\x20understand\x20what\x20you\x27re\x20offering.','recommendation':'Write\x20a\x20clear\x20description\x20of\x20the\x20service,\x20including\x20deliverables,\x20timelines,\x20and\x20terms.'},{'id':'audit_named_new_name','description':'Service\x20being\x20created\x20should\x20have\x20a\x20name','severity':'warning','check':a=>serviceNameOf(a)!==undefined,'message':()=>'Creating\x20a\x20service\x20without\x20a\x20name\x20makes\x20it\x20hard\x20to\x20reference\x20and\x20organize.','recommendation':'Set\x20object:{name:\x20...}\x20(or\x20namedNew.name)\x20following\x20the\x20convention:\x20<projectPrefix>_<service>_<purpose>.'},{'id':'audit_customer_required_needs_um','description':'customer_required\x20requires\x20a\x20Contact\x20bound\x20via\x20um\x20(SDK-enforced\x20hard\x20link;\x20mirrored\x20here)','severity':'error','fields':['customer_required','um'],'check':a=>{const b=Array['isArray'](a?.['customer_required'])?a['customer_required']:[];if(b['length']===0x0)return!![];return!!a?.['um'];},'message':()=>'customer_required\x20is\x20set\x20but\x20no\x20Contact\x20is\x20bound\x20via\x20um\x20—\x20customers\x20cannot\x20deliver\x20the\x20required\x20private\x20information\x20through\x20end-to-end\x20encrypted\x20Messenger.','recommendation':'Bind\x20um:{Contact\x20name/id}\x20in\x20the\x20same\x20call\x20(SDK\x20order_new\x20will\x20fail\x20the\x20buyer\x20otherwise).'},{'id':'audit_customer_required_is_declared_not_enforced','description':'customer_required\x20has\x20no\x20on-chain\x20enforcement\x20at\x20buy\x20time\x20—\x20a\x20Guard\x20must\x20gate\x20fulfilment','severity':'warning','fields':['customer_required'],'check':a=>{const b=Array['isArray'](a?.['customer_required'])?a['customer_required']:[];return b['length']===0x0;},'message':a=>{const b=Array['isArray'](a?.['customer_required'])?a['customer_required']:[];return'customer_required\x20('+b['length']+'\x20field(s):\x20'+b['join'](',\x20')+')\x20is\x20DECLARATIVE\x20ONLY:\x20the\x20on-chain\x20purchase\x20entry\x20never\x20reads\x20this\x20list,\x20so\x20an\x20order\x20that\x20supplies\x20none\x20of\x20these\x20fields\x20is\x20still\x20created\x20and\x20progresses.\x20Nothing\x20on-chain\x20will\x20stop\x20it.';},'recommendation':'Bind\x20pattern.required_info_evidence_gate\x20(schema_query\x20action=get_guard_design_patterns)\x20on\x20the\x20first\x20forward\x20that\x20needs\x20the\x20information:\x20query\x20\x27order.required_info\x20some\x27\x20(1572)\x20over\x20the\x20Order.\x20The\x20buyer\x20records\x20the\x20credential\x20via\x20order_required_info_update:\x20EITHER\x20the\x20merchant\x27s\x20IM\x20user\x20address\x20resolved\x20from\x20the\x20Service\x27s\x20Contact\x20(zero\x20cost,\x20address\x20record\x20only)\x20OR\x20an\x20on-chain\x20WTS\x20Proof\x20object\x20address\x20(embeds\x20the\x20merchant\x20IM\x20address\x20and\x20the\x20last-message\x20timestamp;\x20costs\x20gas,\x20publicly\x20verifiable).\x20\x27order.required_info\x27\x20(1573)\x20returns\x20the\x20recorded\x20address\x20but\x20aborts\x20while\x20nothing\x20is\x20recorded\x20—\x20gate\x20on\x201572\x20first.'},{'id':'audit_dangling_deps','description':'Service\x20dependencies\x20should\x20be\x20fully\x20created','severity':'error','check':(a,b)=>{if(!a?.['publish'])return!![];if(!b?.['graph'])return!![];const c=b['graph']['findDanglingDependencies']()??[];return c['length']===0x0;},'message':()=>'Service\x20references\x20objects\x20that\x20are\x20not\x20yet\x20created.\x20Publishing\x20will\x20lock\x20these\x20references.','recommendation':'Ensure\x20all\x20referenced\x20objects\x20(machine,\x20allocators,\x20guards)\x20are\x20created\x20and\x20finalized\x20before\x20publishing.'},{'id':'audit_type_parameter','description':'Service\x20should\x20have\x20a\x20token\x20type\x20specified','severity':'info','fields':['type_parameter','namedNew'],'check':a=>typeParameterOf(a)!==undefined,'message':()=>'No\x20payment\x20token\x20type\x20specified.\x20Defaulting\x20to\x20WOW\x20(0x2::wow::WOW).','recommendation':'Explicitly\x20set\x20type_parameter\x20(inside\x20object:{...})\x20if\x20you\x20want\x20to\x20accept\x20non-WOW\x20tokens\x20(e.g.,\x20USDT,\x20ETH).'}];const RULE_INDEX=new Map(AUDIT_RULES['map'](a=>[a['id'],a]));function readSeverityOverrides(){try{const {getJudgmentDoc:a}=require('../config/judgment.js');if(typeof a!=='function')return{};const b=a()?.['rules']?.['domains'];if(!b||typeof b!=='object')return{};const c={};for(const d of Object['values'](b)){const e=d?.['severity_overrides'];if(!e||typeof e!=='object')continue;for(const [f,g]of Object['entries'](e)){if(g==='error'||g==='warning'||g==='info')c[f]=g;}}return c;}catch{return{};}}export function auditService(a,b){const c=[],d=a?.['publish']===!![]&&typeof a?.['object']==='string',e=readSeverityOverrides();for(const f of AUDIT_RULES){try{if(d&&f['fields']&&!f['fields']['some'](g=>a[g]!==undefined))continue;!f['check'](a,b)&&c['push']({'rule_id':f['id'],'severity':e[f['id']]??f['severity'],'message':f['message'](a),'recommendation':f['recommendation']});}catch{}}return c;}export function hasBlockingErrors(a){return a['some'](b=>b['severity']==='error');}export function getErrors(a){return a['filter'](b=>b['severity']==='error');}export function getWarnings(a){return a['filter'](b=>b['severity']==='warning');}export function summarizeFindings(a){if(a['length']===0x0)return'All\x20audit\x20checks\x20passed.';const b=getErrors(a),c=getWarnings(a),d=a['filter'](g=>g['severity']==='info'),e=[];if(b['length']>0x0)e['push'](b['length']+'\x20error(s)');if(c['length']>0x0)e['push'](c['length']+'\x20warning(s)');if(d['length']>0x0)e['push'](d['length']+'\x20info');return'Audit:\x20'+e['join'](',\x20')+'.\x20Review\x20before\x20publishing.';}export const AUDIT_RULES_VERSION=0x5;
|
|
1
|
+
import{MAX_INDEMNITY_MULTIPLE}from'./onchain-constants.js';import{lintForwardAmbiguity,findLoopCycles}from'./machine-topology.js';import{isRenewalLoopEdge}from'../participation/radar-core.js';function numericAmount(a){if(typeof a==='number')return Number['isFinite'](a)?a:undefined;if(typeof a==='string'){const b=a['trim']();if(/^\d+$/['test'](b))return Number(b);}return undefined;}export{numericAmount};export function salesItemsOf(a){if(Array['isArray'](a?.['sales']))return a['sales'];if(Array['isArray'](a?.['sales']?.['sales']))return a['sales']['sales'];return[];}export function allocatorCountOf(a){const b=a?.['order_allocators'];if(Array['isArray'](b))return b['length'];if(Array['isArray'](b?.['allocators']))return b['allocators']['length'];return 0x0;}export function arbitrationRefsOf(b){const c=b?.['arbitrations'];if(Array['isArray'](c))return c['filter'](e=>typeof e==='string');if(Array['isArray'](c?.['objects']))return c['objects']['filter'](e=>typeof e==='string');return[];}export function compensationFundOf(a){if(a?.['compensation_fund_add']?.['balance']!=null)return a['compensation_fund_add']['balance'];if(a?.['compensation_fund']!=null)return a['compensation_fund'];return undefined;}export function serviceNameOf(a){if(typeof a?.['object']==='string')return a['object'];if(typeof a?.['object']?.['name']==='string'&&a['object']['name'])return a['object']['name'];if(typeof a?.['namedNew']?.['name']==='string'&&a['namedNew']['name'])return a['namedNew']['name'];return undefined;}export function typeParameterOf(a){if(typeof a?.['type_parameter']==='string'&&a['type_parameter'])return a['type_parameter'];if(typeof a?.['object']?.['type_parameter']==='string'&&a['object']['type_parameter'])return a['object']['type_parameter'];if(typeof a?.['namedNew']?.['type_parameter']==='string'&&a['namedNew']['type_parameter'])return a['namedNew']['type_parameter'];return undefined;}export const DISPUTE_FAMILY_NODE_REGEX=/(^|_)(disputed?|arbitration|arb)(_|$)/i;export const FUND_TERMINAL_NODE_REGEX=/^(refund|refunded|deposit_refunded|deposit_deducted|cancel|cancelled)$/i;export const ANTI_PATTERN_NODE_REGEX=new RegExp(DISPUTE_FAMILY_NODE_REGEX['source']+'|'+FUND_TERMINAL_NODE_REGEX['source'],'i');export const REMEDY_FAMILY_NODE_REGEX=/(revision|refund|cancel|return|claim)/i;export function isRemedyLoopEdge(a,b){return REMEDY_FAMILY_NODE_REGEX['test'](a)||REMEDY_FAMILY_NODE_REGEX['test'](b);}export function classifyLoopCycle(a){for(let b=0x0;b<a['length'];b++){if(isRenewalLoopEdge(a[b],a[(b+0x1)%a['length']]))return'renewal';}if(a['some'](c=>REMEDY_FAMILY_NODE_REGEX['test'](c)))return'remedy';return'charge';}export function auditMachineNodes(a){const b=[],c=[];if(!Array['isArray'](a)||a['length']===0x0)return c['push']('pre_publish:\x20machine\x20node\x20set\x20unavailable\x20—\x20topology\x20not\x20verifiable;\x20'+'verify\x20via\x20machineNode2file\x20BEFORE\x20publish\x20(immutable\x20after\x20publish,\x20IMMUT-001)'),{'critical':b,'warnings':c};const d=a;for(const q of d){const r=typeof q?.['name']==='string'?q['name']:'';if(!r)continue;if(DISPUTE_FAMILY_NODE_REGEX['test'](r))b['push']('R-M1-11:\x20machine\x20node\x20\x22'+r+'\x22\x20models\x20dispute\x20flow\x20—\x20'+'disputes\x20must\x20route\x20via\x20the\x20separate\x20Arbitration\x20object\x20(off-Machine);\x20'+'rename\x20the\x20node\x20to\x20the\x20business\x20state\x20that\x20triggers\x20it');else FUND_TERMINAL_NODE_REGEX['test'](r)&&c['push']('R-M1-11:\x20machine\x20node\x20\x22'+r+'\x22\x20uses\x20a\x20bare\x20fund-terminal\x20name\x20—\x20reaching\x20'+'it\x20moves\x20no\x20funds\x20by\x20itself.\x20This\x20is\x20legitimate\x20ONLY\x20when\x20a\x20refund\x20allocator\x20'+'rail\x27s\x20guard\x20anchors\x20to\x20this\x20node\x20(per-node\x20refund\x20tracks);\x20otherwise\x20rename\x20it\x20'+'to\x20the\x20business\x20state\x20(e.g.\x20cancel_requested\x20/\x20closed_cancel)\x20and\x20route\x20the\x20'+'refund\x20via\x20an\x20Allocator\x20triggered\x20by\x20that\x20state.\x20The\x20template\x20scanner\x20verifies\x20'+'the\x20anchoring\x20when\x20a\x20template\x20is\x20present.');}const e=new Set();for(const s of d){const t=typeof s?.['name']==='string'?s['name']:'';if(!t)continue;e['has'](t)&&b['push']('MC-C-04:\x20duplicate\x20machine\x20node\x20name\x20\x22'+t+'\x22\x20—\x20on-chain\x20will\x20reject\x20the\x20publish\x20transaction'),e['add'](t);}const g=d['some'](u=>Array['isArray'](u?.['pairs'])&&u['pairs']['some'](v=>v?.['prev_node']===''));!g&&b['push']('Machine\x20has\x20no\x20entry\x20pair\x20(prev_node=\x22\x22)\x20—\x20Progress\x20can\x20never\x20advance\x20'+'from\x20the\x20initial\x20state;\x20orders\x20are\x20permanently\x20stuck');const h=new Map();for(const u of d){const v=typeof u?.['name']==='string'?u['name']:'';if(!v)continue;if(!h['has'](v))h['set'](v,[]);for(const w of u?.['pairs']??[]){const x=w?.['prev_node'];if(typeof x==='string'&&x!==''){const y=h['get'](x);if(y)y['push'](v);else h['set'](x,[v]);}}}const i=findLoopCycles(h)['map'](z=>({'c':z,'tier':classifyLoopCycle(z['cycle'])})),j=i['filter'](z=>z['tier']==='renewal'),k=i['filter'](z=>z['tier']==='remedy'),l=i['filter'](z=>z['tier']==='charge');l['length']>0x0&&b['push']('pre_publish:\x20machine\x20contains\x20charge-bearing\x20loop\x20cycle(s)\x20'+l['map'](z=>'['+z['c']['cycle']['join']('\x20->\x20')+']')['join'](',\x20')+'\x20—\x20'+'on-chain\x20a\x20revisit\x20is\x20NOT\x20verified\x20to\x20re-fund\x20the\x20Allocation,\x20and\x20this\x20static\x20pass\x20sees\x20only\x20the\x20forward\x27s\x20guard\x20reference\x20'+'(never\x20the\x20guard\x20table),\x20so\x20a\x20per-revisit-fee\x20cycle\x20(retake\x20/\x20session-card\x20shape)\x20is\x20UNPROVABLE\x20here\x20even\x20though\x20the\x20'+'allocation.balance\x20Guard\x20query\x20(1051,\x20witness\x20OrderAllocation\x20109)\x20makes\x20the\x20fee\x20enforceable\x20at\x20the\x20guard\x20layer\x20'+'(zero-value\x20re-delivery\x20cycles,\x20test/11\x20R2-F3\x20/\x20crs\x20P2-3).\x20Remedy:\x20bind\x20the\x20fund-gate\x20Guard\x20on\x20the\x20loop\x20forward\x20'+'(constant\x20=\x20order\x20address,\x20convert_witness\x20OrderAllocation,\x20allocation.balance\x20>=\x20revisit\x20fee)\x20AND\x20publish\x20through\x20a\x20template\x20'+'carrying\x20that\x20convention,\x20or\x20replace\x20the\x20loop\x20with\x20per-period\x20NEW\x20Orders\x20(REUSE\x20pattern,\x20Machine\x20stays\x20a\x20DAG).\x20'+'A\x20funded\x20renewal\x20loop\x20(post-period\x20node\x20back\x20into\x20a\x20charging\x20node,\x20advanced\x20via\x20the\x20one-PTB\x20order_renew\x20call)\x20'+'is\x20the\x20only\x20sanctioned\x20charge-bearing\x20cycle\x20shape.');j['length']>0x0&&c['push']('pre_publish:\x20machine\x20contains\x20renewal\x20loop\x20cycle(s)\x20'+j['map'](z=>'['+z['c']['cycle']['join']('\x20->\x20')+']')['join'](',\x20')+'\x20—\x20on-chain\x20a\x20revisit\x20'+'is\x20NOT\x20verified\x20to\x20re-fund\x20the\x20Allocation.\x20Every\x20renewal/loop\x20forward\x20MUST\x20carry\x20the\x20new-period\x20'+'payment\x20into\x20the\x20order\x20escrow\x20atomically\x20(use\x20the\x20order\x20call\x27s\x20order_renew\x20field:\x20create\x20the\x20period\x20payment,\x20receive\x20it\x20into\x20the\x20'+'allocation,\x20and\x20advance\x20the\x20progress\x20—\x20all\x20in\x20one\x20transaction),\x20or\x20the\x20loop\x20allows\x20zero-value\x20'+'re-delivery\x20cycles\x20(test/11\x20R2-F3).\x20'+'Recommended:\x20bind\x20a\x20fund-gate\x20Guard\x20on\x20the\x20loop\x20forward\x20(constant\x20=\x20order\x20address,\x20convert_witness\x20OrderAllocation(109),\x20'+'allocation.balance\x20query\x201051\x20>=\x20period\x20price)\x20—\x20the\x20query\x20is\x20live\x20on-chain,\x20so\x20a\x20guarded\x20renewal\x20loop\x20is\x20now\x20the\x20'+'expressible\x20alternative\x20to\x20per-period\x20NEW\x20Orders\x20for\x20long\x20subscriptions.');k['length']>0x0&&c['push']('pre_publish:\x20machine\x20contains\x20remedy\x20loop\x20cycle(s)\x20'+k['map'](z=>'['+z['c']['cycle']['join']('\x20->\x20')+']')['join'](',\x20')+'\x20—\x20'+'a\x20same-order\x20revisit\x20(revision/refund/cancel\x20family)\x20implies\x20NO\x20new\x20charge,\x20so\x20no\x20fund\x20gate\x20is\x20needed\x20on\x20it\x20'+'(the\x20allocation.balance\x20query\x20exists\x20but\x20is\x20irrelevant\x20here).\x20Visible\x20by\x20design\x20(crs\x20P2-3):\x20if\x20the\x20business\x20EVER\x20intends\x20'+'a\x20revisit\x20to\x20cost\x20money,\x20that\x20fee\x20IS\x20enforceable\x20via\x20the\x20balance\x20query\x20(1051)\x20—\x20but\x20that\x20reshapes\x20the\x20cycle\x20into\x20the\x20'+'charge\x20tier\x20above;\x20keep\x20remedy\x20revisits\x20free\x20or\x20restructure\x20as\x20per-period\x20NEW\x20Orders.');for(const z of d){const A=typeof z?.['name']==='string'?z['name']:'?';for(const B of z?.['pairs']??[]){for(const C of B?.['forwards']??[]){const D=C?.['namedOperator']!==undefined&&C?.['namedOperator']!==null,E=C?.['permissionIndex']!==undefined&&C?.['permissionIndex']!==null,F=C?.['guard']!==undefined&&C?.['guard']!==null;!D&&!E&&!F&&c['push']('pre_publish:\x20node\x20\x22'+A+'\x22\x20forward\x20\x22'+String(C?.['name']??'?')+'\x22\x20has\x20no\x20executor\x20binding\x20(namedOperator\x20/\x20permissionIndex\x20/\x20guard)\x20—\x20no\x20one\x20can\x20advance\x20it');}}}const m=lintForwardAmbiguity(a,'pre_publish');b['push'](...m['critical']),c['push'](...m['warnings']);const o=computeTerminalReachability(a);return o['unreachable']['length']>0x0&&c['push']('pre_publish:\x20unreachable\x20machine\x20node(s)\x20'+o['unreachable']['map'](G=>'\x22'+G+'\x22')['join'](',\x20')+'\x20—\x20'+'no\x20path\x20from\x20the\x20entry\x20pair\x20reaches\x20them;\x20dead\x20topology\x20is\x20frozen\x20at\x20publish\x20(IMMUT-001).\x20'+'Wire\x20them\x20into\x20the\x20flow\x20or\x20remove\x20them\x20before\x20publish'),{'critical':b,'warnings':c};}export function computeTerminalReachability(a){const b=[],c=[];if(!Array['isArray'](a)||a['length']===0x0)return{'terminals':b,'unreachable':c};const d=a,e=new Map(),f=[],g=[];for(const j of d){const k=typeof j?.['name']==='string'?j['name']:'';if(!k)continue;f['push'](k);if(!e['has'](k))e['set'](k,[]);let l=![];for(const m of j?.['pairs']??[]){const o=m?.['prev_node'];if(o==='')l=!![];else{if(typeof o==='string'&&o!==''){const q=e['get'](o);if(q)q['push'](k);else e['set'](o,[k]);}}}if(l)g['push'](k);}if(f['length']===0x0||g['length']===0x0)return{'terminals':b,'unreachable':c};const h=new Set(),i=[...g];while(i['length']>0x0){const r=i['pop']();if(h['has'](r))continue;h['add'](r);for(const s of e['get'](r)??[])i['push'](s);}for(const t of f){if(!h['has'](t))c['push'](t);else{if((e['get'](t)??[])['length']===0x0)b['push'](t);}}return{'terminals':b,'unreachable':c};}export const AUDIT_RULES=[{'id':'audit_machine_bound','description':'Service\x20should\x20have\x20a\x20Machine\x20workflow\x20bound\x20before\x20publish','severity':'warning','fields':['machine'],'check':(a,b)=>{if(!a?.['publish'])return!![];return!!a?.['machine'];},'message':()=>'Publishing\x20a\x20service\x20without\x20a\x20Machine\x20workflow.\x20Customers\x20won\x27t\x20have\x20a\x20structured\x20order\x20process.','recommendation':'Create\x20a\x20Machine\x20(workflow\x20template)\x20and\x20bind\x20it\x20to\x20the\x20service\x20before\x20publishing.\x20The\x20machine\x20field\x20becomes\x20IMMUTABLE\x20after\x20publish.'},{'id':'audit_order_allocators','description':'Service\x20should\x20have\x20order_allocators\x20for\x20fund\x20distribution','severity':'warning','fields':['order_allocators'],'check':a=>{if(!a?.['publish'])return!![];return allocatorCountOf(a)>0x0;},'message':()=>'Publishing\x20a\x20service\x20without\x20order_allocators.\x20Order\x20funds\x20cannot\x20be\x20auto-distributed\x20to\x20suppliers.','recommendation':'Configure\x20order_allocators\x20before\x20publishing\x20—\x20this\x20field\x20becomes\x20IMMUTABLE\x20after\x20publish.'},{'id':'audit_buy_guard','description':'Service\x20should\x20have\x20a\x20buy_guard\x20for\x20customer\x20screening','severity':'info','fields':['buy_guard'],'check':a=>!!a?.['buy_guard'],'message':()=>'No\x20buy_guard\x20configured\x20—\x20anyone\x20can\x20purchase\x20this\x20service\x20without\x20verification.','recommendation':'Consider\x20adding\x20a\x20Guard\x20to\x20verify\x20customer\x20eligibility\x20(e.g.,\x20identity,\x20wallet\x20balance,\x20location).'},{'id':'audit_arb_alloc_boundary','description':'Arbitration\x20and\x20Allocator\x20coexist\x20→\x20surface\x20the\x20two-system\x20boundary\x20reminder','severity':'warning','fields':['arbitrations','compensation_fund_add','compensation_fund','order_allocators'],'check':a=>{if(!a?.['publish'])return!![];const b=arbitrationRefsOf(a)['length']>0x0||compensationFundOf(a)!==undefined;return!(b&&allocatorCountOf(a)>0x0);},'message':()=>'Arbitration\x20and\x20Allocator\x20are\x20INDEPENDENT\x20systems\x20by\x20design:\x20a\x20ruling\x20records\x20the\x20case\x20and\x20pays\x20from\x20the\x20service\x20compensation\x20fund\x20—\x20it\x20never\x20moves\x20escrow\x20and\x20never\x20advances\x20the\x20workflow.\x20With\x20both\x20configured,\x20a\x20buyer\x20can\x20receive\x20BOTH\x20the\x20arbitration\x20compensation\x20AND\x20a\x20full\x20escrow\x20refund\x20unless\x20the\x20refund/settlement\x20path\x20is\x20gated.\x20This\x20is\x20a\x20boundary\x20reminder,\x20not\x20a\x20defect\x20—\x20verify\x20the\x20coupling\x20check\x20was\x20done\x20deliberately.','recommendation':'Gate\x20the\x20refund/settlement\x20allocator\x27s\x20Guard\x20on\x20order.claimed_by\x20(read-only\x20cross-system\x20evidence\x20—\x20the\x20sanctioned\x20link),\x20or\x20hold\x20the\x20final\x20settlement\x20forward\x20until\x20the\x20case\x20closes.\x20Do\x20NOT\x20couple\x20the\x20systems\x20the\x20other\x20way\x20(no\x20dispute\x20state\x20on\x20the\x20order\x20flow,\x20no\x20workflow\x20step\x20into\x20arbitration):\x20coupling\x20opens\x20the\x20double-pay\x20path.\x20For\x20per-case\x20fund\x20actions,\x20the\x20deposit-reimbursement\x20pattern\x20(guard-design\x20patterns)\x20is\x20the\x20supported\x20route.'},{'id':'audit_compensation_fund','description':'Service\x20should\x20have\x20a\x20compensation_fund\x20for\x20trust','severity':'warning','fields':['compensation_fund_add','compensation_fund'],'check':a=>compensationFundOf(a)!==undefined,'message':()=>'No\x20compensation_fund\x20configured.\x20Customers\x20have\x20no\x20financial\x20protection\x20if\x20you\x20fail\x20to\x20deliver.','recommendation':'Deposit\x20via\x20compensation_fund_add\x20{balance}\x20to\x20enable\x20arbitration\x20payouts.\x20The\x20fund\x20deters\x20fraud\x20and\x20enables\x20arbitration\x20claims.'},{'id':'audit_arbitrations','description':'Service\x20should\x20have\x20arbitration\x20options\x20for\x20dispute\x20resolution','severity':'info','fields':['arbitrations'],'check':a=>arbitrationRefsOf(a)['length']>0x0,'message':()=>'No\x20arbitration\x20configured.\x20Disputes\x20cannot\x20be\x20resolved\x20through\x20a\x20third\x20party.','recommendation':'Add\x20at\x20least\x20one\x20Arbitration\x20object\x20via\x20arbitrations:{op:\x27add\x27,\x20objects:[...]}\x20to\x20enable\x20on-chain\x20dispute\x20resolution.'},{'id':'audit_arbitration_removal_strands_awards','description':'Removing\x20an\x20authorized\x20venue\x20can\x20strand\x20an\x20award\x20it\x20already\x20ruled\x20on','severity':'error','fields':['arbitrations'],'check':a=>{const b=a?.['arbitrations']?.['remove']??a?.['arbitrations']?.['clear'],c=Array['isArray'](b)?b['length']>0x0:a?.['arbitrations']?.['op']==='clear';if(!c)return!![];if(arbitrationRefsOf(a)['length']>0x0)return!![];return compensationFundOf(a)===undefined;},'message':a=>{const b=a?.['arbitrations']?.['clear']?'every\x20authorized\x20venue':'venue(s)\x20'+(a?.['arbitrations']?.['remove']??[])['join'](',\x20');return'Removing\x20'+b+'\x20while\x20a\x20compensation\x20fund\x20is\x20configured\x20makes\x20any\x20award\x20it\x20already\x20ruled\x20on\x20UNPAYABLE:\x20an\x20on-chain\x20payout\x20now\x20requires\x20the\x20deciding\x20venue\x20to\x20still\x20be\x20on\x20the\x20Service\x27s\x20allowlist,\x20so\x20paying\x20out\x20aborts\x20with\x20E_ARBITRATION_NOT_ALLOWED=39\x20and\x20the\x20escrowed\x20funds\x20stay\x20stranded.';},'recommendation':'Before\x20removing\x20a\x20venue,\x20confirm\x20no\x20case\x20it\x20ruled\x20on\x20is\x20still\x20awaiting\x20compensation\x20payout\x20(query\x20the\x20Arb\x20objects\x20for\x20status\x20Arbitrated,\x20not\x20Finished).\x20Add\x20the\x20replacement\x20venue\x20FIRST,\x20drain\x20the\x20old\x20venue\x27s\x20cases,\x20and\x20only\x20then\x20remove\x20it.\x20A\x20buyer\x20should\x20never\x20be\x20left\x20holding\x20an\x20uncollectable\x20award.'},{'id':'audit_price','description':'Service\x20should\x20have\x20at\x20least\x20one\x20priced\x20sale\x20item','severity':'error','fields':['sales'],'check':a=>{const b=salesItemsOf(a);if(b['length']===0x0)return!![];return b['some'](c=>c?.['price']!==undefined&&c?.['price']!==null);},'message':()=>'Sales\x20list\x20present\x20but\x20no\x20item\x20has\x20a\x20price.\x20Customers\x20cannot\x20place\x20orders\x20without\x20knowing\x20the\x20cost.','recommendation':'Set\x20price\x20on\x20each\x20sales\x20item\x20(smallest-unit\x20string\x20or\x20display\x20form\x20like\x20\x272.5WOW\x27).'},{'id':'audit_compensation_fund_covers_award_ceiling','description':'compensation_fund\x20must\x20cover\x20the\x203x\x20award\x20ceiling\x20of\x20the\x20largest\x20sale','severity':'error','fields':['compensation_fund_add','compensation_fund','sales'],'check':a=>{if(!a?.['publish'])return!![];const b=compensationFundOf(a);if(b===undefined)return!![];const c=numericAmount(b);if(c===undefined)return!![];if(c===0x0)return![];const e=salesItemsOf(a)['map'](g=>numericAmount(g?.['price']))['filter'](g=>g!==undefined&&g>0x0);if(e['length']===0x0)return!![];const f=e['reduce']((g,h)=>g+h,0x0);return c>=MAX_INDEMNITY_MULTIPLE*f;},'message':()=>'compensation_fund\x20does\x20not\x20cover\x20the\x20award\x20ceiling.\x20An\x20award\x20is\x20hard-capped\x20at\x20'+MAX_INDEMNITY_MULTIPLE+'x\x20'+'the\x20order\x20amount\x20(arb.move\x20MAX_INDEMNITY_MULTIPLE,\x20enforced\x20at\x20ruling\x20time),\x20so\x20a\x20ruling\x20at\x20the\x20ceiling\x20'+'would\x20abort\x20the\x20buyer\x27s\x20claim\x20with\x2027\x20(E_COMPENSATION_NOT_MATCH)\x20—\x20the\x20ruling\x20stands\x20but\x20is\x20unpayable\x20'+'until\x20you\x20deposit,\x20and\x20the\x20abort\x20does\x20NOT\x20consume\x20the\x20claim.','recommendation':'Top\x20up\x20to\x20at\x20least\x20'+MAX_INDEMNITY_MULTIPLE+'x\x20your\x20largest\x20single\x20order\x20via\x20compensation_fund_add.\x20Above\x20'+(MAX_INDEMNITY_MULTIPLE+'x\x20is\x20optional:\x20it\x20only\x20buys\x20tolerance\x20for\x20several\x20CONCURRENT\x20claims\x20against\x20the\x20')+'one\x20per-Service\x20pool\x20(there\x20is\x20no\x20on-chain\x20concurrency\x20limit),\x20which\x20is\x20a\x20capital-allocation\x20choice.'},{'id':'audit_description','description':'Service\x20should\x20have\x20a\x20description','severity':'warning','fields':['description'],'check':a=>typeof a?.['description']==='string'&&a['description']['length']>0x0,'message':()=>'Service\x20has\x20no\x20description.\x20Customers\x20won\x27t\x20understand\x20what\x20you\x27re\x20offering.','recommendation':'Write\x20a\x20clear\x20description\x20of\x20the\x20service,\x20including\x20deliverables,\x20timelines,\x20and\x20terms.'},{'id':'audit_named_new_name','description':'Service\x20being\x20created\x20should\x20have\x20a\x20name','severity':'warning','check':a=>serviceNameOf(a)!==undefined,'message':()=>'Creating\x20a\x20service\x20without\x20a\x20name\x20makes\x20it\x20hard\x20to\x20reference\x20and\x20organize.','recommendation':'Set\x20object:{name:\x20...}\x20(or\x20namedNew.name)\x20following\x20the\x20convention:\x20<projectPrefix>_<service>_<purpose>.'},{'id':'audit_customer_required_needs_um','description':'customer_required\x20requires\x20a\x20Contact\x20bound\x20via\x20um\x20(SDK-enforced\x20hard\x20link;\x20mirrored\x20here)','severity':'error','fields':['customer_required','um'],'check':a=>{const b=Array['isArray'](a?.['customer_required'])?a['customer_required']:[];if(b['length']===0x0)return!![];return!!a?.['um'];},'message':()=>'customer_required\x20is\x20set\x20but\x20no\x20Contact\x20is\x20bound\x20via\x20um\x20—\x20customers\x20cannot\x20deliver\x20the\x20required\x20private\x20information\x20through\x20end-to-end\x20encrypted\x20Messenger.','recommendation':'Bind\x20um:{Contact\x20name/id}\x20in\x20the\x20same\x20call\x20(SDK\x20order_new\x20will\x20fail\x20the\x20buyer\x20otherwise).'},{'id':'audit_customer_required_is_declared_not_enforced','description':'customer_required\x20has\x20no\x20on-chain\x20enforcement\x20at\x20buy\x20time\x20—\x20a\x20Guard\x20must\x20gate\x20fulfilment','severity':'warning','fields':['customer_required'],'check':a=>{const b=Array['isArray'](a?.['customer_required'])?a['customer_required']:[];return b['length']===0x0;},'message':a=>{const b=Array['isArray'](a?.['customer_required'])?a['customer_required']:[];return'customer_required\x20('+b['length']+'\x20field(s):\x20'+b['join'](',\x20')+')\x20is\x20DECLARATIVE\x20ONLY:\x20the\x20on-chain\x20purchase\x20entry\x20never\x20reads\x20this\x20list,\x20so\x20an\x20order\x20that\x20supplies\x20none\x20of\x20these\x20fields\x20is\x20still\x20created\x20and\x20progresses.\x20Nothing\x20on-chain\x20will\x20stop\x20it.';},'recommendation':'Bind\x20pattern.required_info_evidence_gate\x20(schema_query\x20action=get_guard_design_patterns)\x20on\x20the\x20first\x20forward\x20that\x20needs\x20the\x20information:\x20query\x20\x27order.required_info\x20some\x27\x20(1572)\x20over\x20the\x20Order.\x20The\x20buyer\x20records\x20the\x20credential\x20via\x20order_required_info_update:\x20EITHER\x20the\x20merchant\x27s\x20IM\x20user\x20address\x20resolved\x20from\x20the\x20Service\x27s\x20Contact\x20(zero\x20cost,\x20address\x20record\x20only)\x20OR\x20an\x20on-chain\x20WTS\x20Proof\x20object\x20address\x20(embeds\x20the\x20merchant\x20IM\x20address\x20and\x20the\x20last-message\x20timestamp;\x20costs\x20gas,\x20publicly\x20verifiable).\x20\x27order.required_info\x27\x20(1573)\x20returns\x20the\x20recorded\x20address\x20but\x20aborts\x20while\x20nothing\x20is\x20recorded\x20—\x20gate\x20on\x201572\x20first.\x20When\x20the\x20listing\x20genuinely\x20promises\x20a\x20PER-ORDER\x20credential,\x20prefer\x20the\x20controlled\x20bind\x20entry\x20(order_required_info_bind):\x20the\x20chain\x20verifies\x20the\x20Proof\x20is\x20about\x20THIS\x20order\x20and\x20owner-created\x20at\x20write\x20time\x20and\x20rejects\x20a\x20mismatch\x20—\x20no\x20guard\x20needed\x20to\x20catch\x20a\x20wrong-proof\x20record.'},{'id':'audit_dangling_deps','description':'Service\x20dependencies\x20should\x20be\x20fully\x20created','severity':'error','check':(a,b)=>{if(!a?.['publish'])return!![];if(!b?.['graph'])return!![];const c=b['graph']['findDanglingDependencies']()??[];return c['length']===0x0;},'message':()=>'Service\x20references\x20objects\x20that\x20are\x20not\x20yet\x20created.\x20Publishing\x20will\x20lock\x20these\x20references.','recommendation':'Ensure\x20all\x20referenced\x20objects\x20(machine,\x20allocators,\x20guards)\x20are\x20created\x20and\x20finalized\x20before\x20publishing.'},{'id':'audit_type_parameter','description':'Service\x20should\x20have\x20a\x20token\x20type\x20specified','severity':'info','fields':['type_parameter','namedNew'],'check':a=>typeParameterOf(a)!==undefined,'message':()=>'No\x20payment\x20token\x20type\x20specified.\x20Defaulting\x20to\x20WOW\x20(0x2::wow::WOW).','recommendation':'Explicitly\x20set\x20type_parameter\x20(inside\x20object:{...})\x20if\x20you\x20want\x20to\x20accept\x20non-WOW\x20tokens\x20(e.g.,\x20USDT,\x20ETH).'}];const RULE_INDEX=new Map(AUDIT_RULES['map'](a=>[a['id'],a]));function readSeverityOverrides(){try{const {getJudgmentDoc:a}=require('../config/judgment.js');if(typeof a!=='function')return{};const b=a()?.['rules']?.['domains'];if(!b||typeof b!=='object')return{};const c={};for(const d of Object['values'](b)){const e=d?.['severity_overrides'];if(!e||typeof e!=='object')continue;for(const [f,g]of Object['entries'](e)){if(g==='error'||g==='warning'||g==='info')c[f]=g;}}return c;}catch{return{};}}export function auditService(a,b){const c=[],d=a?.['publish']===!![]&&typeof a?.['object']==='string',e=readSeverityOverrides();for(const f of AUDIT_RULES){try{if(d&&f['fields']&&!f['fields']['some'](g=>a[g]!==undefined))continue;!f['check'](a,b)&&c['push']({'rule_id':f['id'],'severity':e[f['id']]??f['severity'],'message':f['message'](a),'recommendation':f['recommendation']});}catch{}}return c;}export function hasBlockingErrors(a){return a['some'](b=>b['severity']==='error');}export function getErrors(a){return a['filter'](b=>b['severity']==='error');}export function getWarnings(a){return a['filter'](b=>b['severity']==='warning');}export function summarizeFindings(a){if(a['length']===0x0)return'All\x20audit\x20checks\x20passed.';const b=getErrors(a),c=getWarnings(a),d=a['filter'](g=>g['severity']==='info'),e=[];if(b['length']>0x0)e['push'](b['length']+'\x20error(s)');if(c['length']>0x0)e['push'](c['length']+'\x20warning(s)');if(d['length']>0x0)e['push'](d['length']+'\x20info');return'Audit:\x20'+e['join'](',\x20')+'.\x20Review\x20before\x20publishing.';}export const AUDIT_RULES_VERSION=0x5;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{describe,expect,it}from'vitest';import{readFileSync,writeFileSync}from'node:fs';import{fileURLToPath}from'node:url';import{dirname,join}from'node:path';import{RISK_CASES}from'./risk-cases.js';import{aggregateProjectRisks}from'../../playbooks/service-build/risk-aggregator.js';import{assessTreasuryRisks}from'../treasury-risk.js';import{assessRewardRisks}from'../reward-risk.js';function toArray(a){if(Array['isArray'](a))return a;if(a&&typeof a==='object')for(const b of['risks','detected_risks']){const c=a[b];if(Array['isArray'](c))return c;}return[];}function normalize(a){return toArray(a)['map'](b=>{const c=b??{};return{'id':String(c['id']??c['risk_rule_id']??c['rule_id']??'?'),'level':String(c['level']??c['severity']??'?')['toLowerCase'](),...c['evidence']!=null?{'evidence':String(c['evidence'])}:{}};})['sort']((c,d)=>c['id']===d['id']?(c['evidence']??'')['localeCompare'](d['evidence']??''):c['id']['localeCompare'](d['id']));}function runCase(a,b){try{return{'risks':normalize(a(b)),'threw':![]};}catch(c){return{'risks':[],'threw':!![]};}}function collect(){const a={};for(const b of RISK_CASES){const d=runCase(b['run'],b['empty']),e=runCase(b['run'],b['trigger']);a[b['pack']]={'objectType':b['objectType'],'empty':d['risks'],'emptyThrew':d['threw'],'trigger':e['risks']};}return a;}const here=dirname(fileURLToPath(import.meta.url)),SNAPSHOT=join(here,'risk-baselines.json'),AGG_SNAPSHOT=join(here,'aggregator-baselines.json');function puzzlesFrom(a){const b={};for(const d of RISK_CASES){if(d['pack']==='arb')continue;b[d['objectType']]={'puzzle':a(d)};}return b;}async function runAggregator(a){const b=await aggregateProjectRisks({'project_prefix':'baseline','version':'v1','industry':'general','puzzles':puzzlesFrom(a)});return{'severity_summary':b['severity_summary'],'status':b['status'],'findings':b['findings']['map'](c=>({'risk_rule_id':c['risk_rule_id'],'object_type':c['object_type'],'severity':c['severity']})),'warnings':b['warnings']};}describe('write-side\x20risk\x20packs\x20—\x20pre-migration\x20baseline',()=>{it('every\x20pack\x20trigger\x20context\x20fires\x20at\x20least\x20one\x20pack-specific\x20rule',()=>{for(const a of RISK_CASES){const {risks:b}=runCase(a['run'],a['trigger']);expect(b['length'],'pack\x20'+a['pack']+'\x20trigger\x20fired\x20nothing')['toBeGreaterThan'](0x0);}}),it('matches\x20the\x20committed\x20snapshot\x20(regenerate\x20only\x20with\x20--update)',()=>{const a=collect();if(process['env']['UPDATE_RISK_BASELINE']==='1'){writeFileSync(SNAPSHOT,JSON['stringify'](a,null,0x2)+'\x0a','utf8');return;}const b=JSON['parse'](readFileSync(SNAPSHOT,'utf8'));expect(new Set(Object['keys'](a)))['toEqual'](new Set(Object['keys'](b)));for(const c of Object['keys'](a)['sort']()){expect(a[c],'pack\x20'+c+'\x20drifted')['toEqual'](b[c]);}});}),describe('risk\x20aggregator\x20—\x20Task\x2026\x20parity\x20(id/severity/status)',()=>{const a=[['empty',b=>b['empty']],['trigger',b=>b['trigger']]];it('matches\x20the\x20committed\x20snapshot\x20(regenerate\x20only\x20with\x20--update)',async()=>{const b={};for(const [d,e]of a)b[d]=await runAggregator(e);if(process['env']['UPDATE_RISK_BASELINE']==='1'){writeFileSync(AGG_SNAPSHOT,JSON['stringify'](b,null,0x2)+'\x0a','utf8');return;}const c=JSON['parse'](readFileSync(AGG_SNAPSHOT,'utf8'));expect(b)['toEqual'](c);}),it('trigger\x20row\x20produces\x20CRITICAL\x20blockers\x20(sanity:\x20status\x20machine\x20alive)',async()=>{const b=await runAggregator(d=>d['trigger']);expect(b['findings']['some'](c=>c['severity']==='critical'))['toBe'](!![]),expect(b['status'])['not']['toBe']('
|
|
1
|
+
import{describe,expect,it}from'vitest';import{readFileSync,writeFileSync}from'node:fs';import{fileURLToPath}from'node:url';import{dirname,join}from'node:path';import{RISK_CASES}from'./risk-cases.js';import{aggregateProjectRisks}from'../../playbooks/service-build/risk-aggregator.js';import{assessTreasuryRisks}from'../treasury-risk.js';import{assessRewardRisks}from'../reward-risk.js';function toArray(a){if(Array['isArray'](a))return a;if(a&&typeof a==='object')for(const b of['risks','detected_risks']){const c=a[b];if(Array['isArray'](c))return c;}return[];}function normalize(a){return toArray(a)['map'](b=>{const c=b??{};return{'id':String(c['id']??c['risk_rule_id']??c['rule_id']??'?'),'level':String(c['level']??c['severity']??'?')['toLowerCase'](),...c['evidence']!=null?{'evidence':String(c['evidence'])}:{}};})['sort']((c,d)=>c['id']===d['id']?(c['evidence']??'')['localeCompare'](d['evidence']??''):c['id']['localeCompare'](d['id']));}function runCase(a,b){try{return{'risks':normalize(a(b)),'threw':![]};}catch(c){return{'risks':[],'threw':!![]};}}function collect(){const a={};for(const b of RISK_CASES){const d=runCase(b['run'],b['empty']),e=runCase(b['run'],b['trigger']);a[b['pack']]={'objectType':b['objectType'],'empty':d['risks'],'emptyThrew':d['threw'],'trigger':e['risks']};}return a;}const here=dirname(fileURLToPath(import.meta.url)),SNAPSHOT=join(here,'risk-baselines.json'),AGG_SNAPSHOT=join(here,'aggregator-baselines.json');function puzzlesFrom(a){const b={};for(const d of RISK_CASES){if(d['pack']==='arb')continue;b[d['objectType']]={'puzzle':a(d)};}return b;}async function runAggregator(a){const b=await aggregateProjectRisks({'project_prefix':'baseline','version':'v1','industry':'general','puzzles':puzzlesFrom(a)});return{'severity_summary':b['severity_summary'],'status':b['status'],'findings':b['findings']['map'](c=>({'risk_rule_id':c['risk_rule_id'],'object_type':c['object_type'],'severity':c['severity']})),'warnings':b['warnings']};}describe('write-side\x20risk\x20packs\x20—\x20pre-migration\x20baseline',()=>{it('every\x20pack\x20trigger\x20context\x20fires\x20at\x20least\x20one\x20pack-specific\x20rule',()=>{for(const a of RISK_CASES){const {risks:b}=runCase(a['run'],a['trigger']);expect(b['length'],'pack\x20'+a['pack']+'\x20trigger\x20fired\x20nothing')['toBeGreaterThan'](0x0);}}),it('matches\x20the\x20committed\x20snapshot\x20(regenerate\x20only\x20with\x20--update)',()=>{const a=collect();if(process['env']['UPDATE_RISK_BASELINE']==='1'){writeFileSync(SNAPSHOT,JSON['stringify'](a,null,0x2)+'\x0a','utf8');return;}const b=JSON['parse'](readFileSync(SNAPSHOT,'utf8'));expect(new Set(Object['keys'](a)))['toEqual'](new Set(Object['keys'](b)));for(const c of Object['keys'](a)['sort']()){expect(a[c],'pack\x20'+c+'\x20drifted')['toEqual'](b[c]);}});}),describe('risk\x20aggregator\x20—\x20Task\x2026\x20parity\x20(id/severity/status)',()=>{const a=[['empty',b=>b['empty']],['trigger',b=>b['trigger']]];it('matches\x20the\x20committed\x20snapshot\x20(regenerate\x20only\x20with\x20--update)',async()=>{const b={};for(const [d,e]of a)b[d]=await runAggregator(e);if(process['env']['UPDATE_RISK_BASELINE']==='1'){writeFileSync(AGG_SNAPSHOT,JSON['stringify'](b,null,0x2)+'\x0a','utf8');return;}const c=JSON['parse'](readFileSync(AGG_SNAPSHOT,'utf8'));expect(b)['toEqual'](c);}),it('trigger\x20row\x20produces\x20CRITICAL\x20blockers\x20(sanity:\x20status\x20machine\x20alive)',async()=>{const b=await runAggregator(d=>d['trigger']);expect(b['findings']['some'](c=>c['severity']==='critical'))['toBe'](!![]),expect(b['status'])['not']['toBe']('STATIC_ANALYZERS_CLEAN');}),it('TR-26.2\x20every\x20finding\x20carries\x20its\x20proposal-graph\x20path\x20(explainability)',async()=>{const b=await aggregateProjectRisks({'project_prefix':'baseline','version':'v1','industry':'general','puzzles':puzzlesFrom(d=>d['trigger'])});expect(b['findings']['length'])['toBeGreaterThan'](0x0);for(const c of b['findings']){expect(c['details']?.['proposal_node'],'finding\x20'+c['risk_rule_id']+'\x20has\x20no\x20proposal\x20node')['toMatch'](/^proposal::/),expect(c['details']?.['rule_source'],'finding\x20'+c['risk_rule_id']+'\x20has\x20no\x20analyzer\x20source')['not']['toBe']('');}});}),describe('R-T-2-04\x20—\x20external_withdraw\x20pays\x20only\x20the\x20transaction\x20sender',()=>{const a={'withdraw':{'amount_by_external_withdraw_guard':'release-guard','recipient':'0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'}};it('flags\x20HIGH\x20(code\x2010\x20abort\x20ahead)\x20when\x20recipient\x20!=\x20known\x20sender',()=>{const {risks:b}=assessTreasuryRisks({...a,'sender_address':'0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'}),c=b['find'](d=>d['id']==='R-T-2-04');expect(c?.['level'])['toBe']('high'),expect(c?.['description']??'')['toContain']('code\x2010');}),it('stays\x20silent\x20when\x20recipient\x20equals\x20the\x20sender',()=>{const {risks:b}=assessTreasuryRisks({...a,'sender_address':'0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'});expect(b['some'](c=>c['id']==='R-T-2-04'))['toBe'](![]);}),it('advises\x20MEDIUM\x20when\x20the\x20sender\x20is\x20not\x20known\x20at\x20analysis\x20time',()=>{const {risks:b}=assessTreasuryRisks(a),c=b['find'](d=>d['id']==='R-T-2-04');expect(c?.['level'])['toBe']('medium');}),it('does\x20not\x20fire\x20on\x20the\x20fixed\x20(permissioned)\x20withdraw\x20path',()=>{const {risks:b}=assessTreasuryRisks({'withdraw':{'amount_fixed':'1000','recipient':'0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'},'sender_address':'0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'});expect(b['some'](c=>c['id']==='R-T-2-04'))['toBe'](![]);});}),describe('R-T-4-04\x20—\x20mounting\x20external\x20Guards\x20(owner\x20diligence\x20reminder)',()=>{it('flags\x20MEDIUM\x20when\x20mounting\x20external\x20withdraw\x20Guards',()=>{const {risks:a}=assessTreasuryRisks({'external_withdraw_guard':{'op':'add','guards':[{'guard':'0xg1','identifier':0x0}]}}),b=a['find'](c=>c['id']==='R-T-4-04');expect(b?.['level'])['toBe']('medium'),expect(b?.['description']??'')['toContain']('code\x2010');}),it('flags\x20LOW\x20when\x20mounting\x20external\x20deposit\x20Guards',()=>{const {risks:a}=assessTreasuryRisks({'external_deposit_guard':{'op':'add','guards':[{'guard':'0xg2'}]}}),b=a['find'](c=>c['id']==='R-T-4-04');expect(b?.['level'])['toBe']('low');}),it('stays\x20silent\x20on\x20remove/clear',()=>{const {risks:a}=assessTreasuryRisks({'external_withdraw_guard':{'op':'remove','guards':['0xg1']}});expect(a['some'](b=>b['id']==='R-T-4-04'))['toBe'](![]);});}),describe('R-R-2-05\x20—\x20mounting\x20a\x20claim\x20Guard\x20with\x20a\x20GuardIdentifier\x20payout\x20slot',()=>{const a={'guard':'0xg1','amount':{'type':'fixed','value':'100'}};it('flags\x20MEDIUM\x20when\x20the\x20recipient\x20is\x20a\x20GuardIdentifier\x20slot',()=>{const {risks:b}=assessRewardRisks({'guard_add':[{...a,'recipient':{'GuardIdentifier':0x0}}]}),c=b['find'](d=>d['id']==='R-R-2-05');expect(c?.['level'])['toBe']('medium'),expect(c?.['description']??'')['toContain']('GuardIdentifier');}),it('stays\x20silent\x20for\x20Entity/Signer\x20recipients',()=>{const {risks:b}=assessRewardRisks({'guard_add':[{...a,'recipient':{'Entity':'0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'}}]});expect(b['some'](c=>c['id']==='R-R-2-05'))['toBe'](![]);});});
|
|
@@ -448,6 +448,87 @@
|
|
|
448
448
|
}
|
|
449
449
|
}
|
|
450
450
|
]
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"rule_id": "AC5",
|
|
454
|
+
"dimension": "integrity",
|
|
455
|
+
"trigger": "Freshly-registered accounts casting registrar votes in a burst (voter-side, V-PROF)",
|
|
456
|
+
"cases": [
|
|
457
|
+
{
|
|
458
|
+
"when": { "field": "kernel_fired", "op": "truthy" },
|
|
459
|
+
"level": "fact:ac_signal_level",
|
|
460
|
+
"title": "Vote-noise suspicion: freshly-registered accounts are casting votes in a burst",
|
|
461
|
+
"description": "New accounts voting in volume read as an organized reputation push, not organic discovery.",
|
|
462
|
+
"exposure": {
|
|
463
|
+
"loss_parties": [
|
|
464
|
+
{ "role": "system", "basis": "Account-level vote aggregates absorb coordinated pushes, distorting the discovery signals every participant ranks on." },
|
|
465
|
+
{ "role": "buyer", "basis": "Buyers reading like/favor counts as social proof are shown a manufactured signal." }
|
|
466
|
+
],
|
|
467
|
+
"gain_paths": [
|
|
468
|
+
{
|
|
469
|
+
"role": "merchant",
|
|
470
|
+
"path": "A burst of fresh-account votes inflates the account-level reputation of the targets the push favors.",
|
|
471
|
+
"viability": "viable",
|
|
472
|
+
"gate": "Registrar votes cost only gas and carry no order binding — the gate is detection and de-weighting, not the chain."
|
|
473
|
+
}
|
|
474
|
+
]
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
]
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
"rule_id": "AC6",
|
|
481
|
+
"dimension": "integrity",
|
|
482
|
+
"trigger": "Mutual votes between address pairs (voter-side, V-PROF)",
|
|
483
|
+
"cases": [
|
|
484
|
+
{
|
|
485
|
+
"when": { "field": "kernel_fired", "op": "truthy" },
|
|
486
|
+
"level": "fact:ac_signal_level",
|
|
487
|
+
"title": "Vote-ring suspicion: mutual votes between address pairs",
|
|
488
|
+
"description": "Symmetric voting pairs are the cheapest way to manufacture mutual account-level reputation.",
|
|
489
|
+
"exposure": {
|
|
490
|
+
"loss_parties": [
|
|
491
|
+
{ "role": "system", "basis": "Ring votes correlate accounts that read as independent reputations, polluting pairwise trust statistics." },
|
|
492
|
+
{ "role": "buyer", "basis": "Rings inflate the accounts buyers compare against, skewing discovery." }
|
|
493
|
+
],
|
|
494
|
+
"gain_paths": [
|
|
495
|
+
{
|
|
496
|
+
"role": "merchant",
|
|
497
|
+
"path": "Each ring member gains a like-backed reputation at pure gas cost — the reciprocity is the whole scheme.",
|
|
498
|
+
"viability": "viable",
|
|
499
|
+
"gate": "No on-chain primitive binds a vote to an order; only correlation analysis reveals the ring."
|
|
500
|
+
}
|
|
501
|
+
]
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
]
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
"rule_id": "AC7",
|
|
508
|
+
"dimension": "integrity",
|
|
509
|
+
"trigger": "One target's votes dominated by low-credibility accounts (voter-side, V-PROF)",
|
|
510
|
+
"cases": [
|
|
511
|
+
{
|
|
512
|
+
"when": { "field": "kernel_fired", "op": "truthy" },
|
|
513
|
+
"level": "fact:ac_signal_level",
|
|
514
|
+
"title": "Vote-noise suspicion: an address's votes are dominated by low-credibility accounts",
|
|
515
|
+
"description": "The account-level aggregate may be noise rather than signal; rank by the order-backed layer instead.",
|
|
516
|
+
"exposure": {
|
|
517
|
+
"loss_parties": [
|
|
518
|
+
{ "role": "system", "basis": "A flooded vote ring makes the target's account-level reputation meaningless as a ranking input." },
|
|
519
|
+
{ "role": "buyer", "basis": "Buyers trusting the flooded account's like count are misled at decision time." }
|
|
520
|
+
],
|
|
521
|
+
"gain_paths": [
|
|
522
|
+
{
|
|
523
|
+
"role": "merchant",
|
|
524
|
+
"path": "Flooding a target (a competitor or one's own account) with fresh/zero-history votes rewrites its social proof at gas cost.",
|
|
525
|
+
"viability": "viable",
|
|
526
|
+
"gate": "The vote ring has no order gate — the flood is undetectable on-chain, only by voter-credibility re-projection."
|
|
527
|
+
}
|
|
528
|
+
]
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
]
|
|
451
532
|
}
|
|
452
533
|
]
|
|
453
534
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"comment": "Guard rule pack (R-C/R-X) — declarative form of the retired in-code Guard risk rules (the guard condition-tree lint pack:
|
|
2
|
+
"comment": "Guard rule pack (R-C/R-X) — declarative form of the retired in-code Guard risk rules (the guard condition-tree lint pack: 39 rules over the serialized root, table classification and the scene ledger). Facts are produced by the kernel extractor (guard-risk.ts, bound to the GUARDQUERY invariant catalog, the witness chain table, the certain-outcome folder and the per-scene reentrancy specs); rules only reference fact names. Levels/wording can be retuned per rule and rules can be disabled (enabled=false, trace left) via the judgment document — factory rules can never be deleted or invented here.",
|
|
3
3
|
"facts": {
|
|
4
4
|
"has_signer_check": "KERNEL — the serialized root contains a context(Signer) check.",
|
|
5
5
|
"has_clock_check": "KERNEL — the serialized root contains a context(Clock) node.",
|
|
@@ -39,6 +39,12 @@
|
|
|
39
39
|
"rc2_04_has_conversion": "KERNEL — the root already uses a type-conversion node (convert_number_address / convert_address_number / convert_u256 / convert_string).",
|
|
40
40
|
"rc2_04_conversion_note": "KERNEL — final description tail for the conversion-present vs conversion-missing branches.",
|
|
41
41
|
"rc2_04_conversion_evidence": "KERNEL — final evidence for the conversion-present vs conversion-missing branches.",
|
|
42
|
+
"rc2_05_mismatch_count": "KERNEL — query prefixes that contradict their convert_witness target type (the witness matrix is directional; zrmn-261012 R-WITNESS-01).",
|
|
43
|
+
"rc2_05_evidence_lines": "KERNEL — the prefix-mismatch list rendered as ' - <detail>' lines, newline joined.",
|
|
44
|
+
"rc2_06_issue_count": "KERNEL — progress.* queries on a source without convert_witness that cannot be proven to be a Progress (no PROGRESS→ORDER reverse edge).",
|
|
45
|
+
"rc2_06_has_hard_mismatch": "KERNEL — at least one such source is explicitly annotated as a non-Progress (hard violation; unannotated sources grade soft).",
|
|
46
|
+
"rc2_06_evidence_lines": "KERNEL — the reverse-edge issue list rendered as ' - <detail>' lines, newline joined.",
|
|
47
|
+
"rc2_07_keys_where_count": "KERNEL — number of 'keys where' predicate occurrences in the serialized root (native verifier abort on all networks, upw-mn-261012 F-28).",
|
|
42
48
|
"has_submission": "KERNEL — the table has at least one b_submission=true entry.",
|
|
43
49
|
"scene_present": "KERNEL — a binding scene was supplied.",
|
|
44
50
|
"scene_id": "KERNEL — the binding scene id (e.g. service_order_allocators_guard).",
|
|
@@ -46,6 +52,7 @@
|
|
|
46
52
|
"scene_binding_field": "KERNEL — the binding scene binding field (buy_guard/order_allocators/...).",
|
|
47
53
|
"scene_mutable_after_publish": "KERNEL — whether the scene binding can be modified after the host object is published.",
|
|
48
54
|
"rc3_01_sharing_exempt": "KERNEL — allocators scene with Entity/GuardIdentifier-only sharing (Signer binding advice does not apply; R-C3-06 owns the semantics).",
|
|
55
|
+
"rc3_01_order_anchored": "KERNEL — allocators scene where EVERY submission slot is unread by the root: submitted values cannot influence the verdict, and the chain binds GuardIdentifier recipients to the paying order via payment_info.for_object (ptrn-mn-261013 F-03).",
|
|
49
56
|
"rc3_02_numeric_count": "KERNEL — submitted numeric table entries (U8..U256) in the voting_guard scene.",
|
|
50
57
|
"rc3_02_numeric_list": "KERNEL — submitted numeric entries rendered as '#id(TYPE)', comma joined.",
|
|
51
58
|
"rc3_03_submitted_addr_count": "KERNEL — submitted Address table entries (b_submission=true, value_type=Address).",
|
|
@@ -83,6 +90,8 @@
|
|
|
83
90
|
"rx1_12_vague_csv": "KERNEL — unnamed entries rendered 'identifier=N, name=\"…\"', '; ' joined.",
|
|
84
91
|
"rx1_13_detected": "KERNEL — a table Address constant's object_type equals the scene host object (circular reference pattern).",
|
|
85
92
|
"rx1_13_identifier": "KERNEL — identifier of the circular-reference table entry.",
|
|
93
|
+
"rx1_19_order_query_count": "KERNEL — order.* query occurrences in a buy-scene guard root (the Order does not exist at buy time, zrmn-261012 R-BUY-GUARD-CIRCULAR).",
|
|
94
|
+
"rx1_19_evidence_csv": "KERNEL — the matched order.* query JSON fragments, comma-space joined.",
|
|
86
95
|
"reentry_applicable": "KERNEL — the scene has a reentrancy spec (ALLOWED scenes stay silent).",
|
|
87
96
|
"reentry_state": "KERNEL — anti-reentrancy protection state: 'protected' / 'pseudo' / 'absent'.",
|
|
88
97
|
"reentry_scene_id": "KERNEL — reentrancy scene id from the spec table.",
|
|
@@ -182,6 +191,23 @@
|
|
|
182
191
|
}
|
|
183
192
|
]
|
|
184
193
|
},
|
|
194
|
+
{
|
|
195
|
+
"rule_id": "R-X1-19",
|
|
196
|
+
"dimension": "logic_gap",
|
|
197
|
+
"trigger": "A buy-scene guard queries order.* — the Order does not exist at buy time (zrmn-261012 R-BUY-GUARD-CIRCULAR)",
|
|
198
|
+
"cases": [
|
|
199
|
+
{
|
|
200
|
+
"when": { "field": "rx1_19_order_query_count", "op": "gt", "value": 0 },
|
|
201
|
+
"level": "critical",
|
|
202
|
+
"title": "Buy guard queries order.* (${rx1_19_evidence_csv}) — the Order does not exist yet, creation aborts",
|
|
203
|
+
"description": "The buy guard evaluates BEFORE the Order object exists (it gates the transaction that creates it), so every order.* query inside it is circular and cannot resolve. The ziroom mainnet run (zrmn-261012) shipped exactly this shape: a buy guard querying order.item has / order.amount — creation failed at name resolution.",
|
|
204
|
+
"scenario": "Circular buy gate: guard creation or first purchase aborts because the queried Order is the one being created",
|
|
205
|
+
"mitigation": "1) Buy-time state lives on the SERVICE, not the Order: query service.* fields (e.g. service.paused) or use table constants;\n2) Post-purchase invariants (amount, item) belong on forward/allocator guards, which run after the Order exists;\n3) ${rx1_19_evidence_csv}",
|
|
206
|
+
"evidence": "order.* queries in buy-scene guard: ${rx1_19_evidence_csv}",
|
|
207
|
+
"stakeholders": ["provider"]
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
},
|
|
185
211
|
{
|
|
186
212
|
"rule_id": "R-C1-01",
|
|
187
213
|
"dimension": "data_source_trust",
|
|
@@ -319,6 +345,66 @@
|
|
|
319
345
|
}
|
|
320
346
|
]
|
|
321
347
|
},
|
|
348
|
+
{
|
|
349
|
+
"rule_id": "R-C2-05",
|
|
350
|
+
"dimension": "data_source_trust",
|
|
351
|
+
"trigger": "Guard uses convert_witness but the query path prefix does not live on the witness target type (zrmn-261012 R-WITNESS-01: 17 mainnet guards rejected)",
|
|
352
|
+
"cases": [
|
|
353
|
+
{
|
|
354
|
+
"when": { "field": "rc2_05_mismatch_count", "op": "gt", "value": 0 },
|
|
355
|
+
"level": "critical",
|
|
356
|
+
"title": "Query path contradicts the witness target type — the chain rejects this guard",
|
|
357
|
+
"description": "convert_witness resolves the object reference to the edge's TARGET type, and the query path prefix must exist on that type. The on-chain witness matrix (common.move) is directional and has NO reverse edges.\n${rc2_05_evidence_lines}\nThis shape aborts at guard creation (native verifier type check) or silently gates on nothing — both are deterministic failures.",
|
|
358
|
+
"scenario": "Witness misuse: convert to Progress then query order.* — type mismatch rejects the guard",
|
|
359
|
+
"mitigation": "1) Make the query prefix match the witness target: 100 OrderProgress→progress.*, 101 OrderMachine→machine.*, 102 OrderService→service.*, 103 ProgressMachine→machine.*, 104 ArbOrder→order.*, 105 ArbArbitration→arb.*, 106-108 Arb→progress./service./machine.*, 109 OrderAllocation→allocation.*;\n2) If you meant to read Order fields, DROP the convert_witness (query order.* directly on the submitted Order);\n3) Run analyze_guard_semantics before creation",
|
|
360
|
+
"evidence": "${rc2_05_evidence_lines}",
|
|
361
|
+
"stakeholders": ["provider"]
|
|
362
|
+
}
|
|
363
|
+
]
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"rule_id": "R-C2-06",
|
|
367
|
+
"dimension": "data_source_trust",
|
|
368
|
+
"trigger": "Guard queries progress.* without convert_witness on an object that is not a Progress (no PROGRESS→ORDER reverse edge)",
|
|
369
|
+
"cases": [
|
|
370
|
+
{
|
|
371
|
+
"when": { "all": [{ "field": "rc2_06_issue_count", "op": "gt", "value": 0 }, { "field": "rc2_06_has_hard_mismatch", "op": "eq", "value": true }] },
|
|
372
|
+
"level": "critical",
|
|
373
|
+
"title": "progress.* queried on a non-Progress object without conversion — unresolvable on-chain",
|
|
374
|
+
"description": "The chain has NO PROGRESS→ORDER reverse edge: the only legal way to read progress fields from an Order submission is convert_witness 100 (OrderProgress).\n${rc2_06_evidence_lines}",
|
|
375
|
+
"scenario": "Reverse-edge misuse: order submitted, progress.current queried without conversion — query returns empty or aborts",
|
|
376
|
+
"mitigation": "1) Add convert_witness 100 (or the string name 'OrderProgress') to the query's object ref;\n2) Keep the query path as progress.* after conversion;\n3) Alternatively submit the Progress object itself and annotate object_type=Progress",
|
|
377
|
+
"evidence": "${rc2_06_evidence_lines}",
|
|
378
|
+
"stakeholders": ["provider"]
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"when": { "all": [{ "field": "rc2_06_issue_count", "op": "gt", "value": 0 }, { "field": "rc2_06_has_hard_mismatch", "op": "eq", "value": false }] },
|
|
382
|
+
"level": "high",
|
|
383
|
+
"title": "progress.* queried on an annotated submission without object_type — verify the source type",
|
|
384
|
+
"description": "A query reads progress.* from a submission without convert_witness, and the table entry lacks an object_type annotation, so the source type cannot be validated statically.\n${rc2_06_evidence_lines}\nIf the submitted value is the ORDER address, the query is unresolvable (no PROGRESS→ORDER reverse edge).",
|
|
385
|
+
"scenario": "Unverifiable source type: progress query on an unannotated submission may target the Order",
|
|
386
|
+
"mitigation": "1) Annotate the table entry's object_type (Progress/Order/Arb);\n2) If the submission is the Order, add convert_witness 100 (OrderProgress);\n3) Verify with analyze_guard_semantics before creation",
|
|
387
|
+
"evidence": "${rc2_06_evidence_lines}",
|
|
388
|
+
"stakeholders": ["provider"]
|
|
389
|
+
}
|
|
390
|
+
]
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"rule_id": "R-C2-07",
|
|
394
|
+
"dimension": "data_source_trust",
|
|
395
|
+
"trigger": "Guard uses a repository.data 'keys where' predicate (upw-mn-261012 F-28: native verifier abort on ALL networks)",
|
|
396
|
+
"cases": [
|
|
397
|
+
{
|
|
398
|
+
"when": { "field": "rc2_07_keys_where_count", "op": "gt", "value": 0 },
|
|
399
|
+
"level": "high",
|
|
400
|
+
"title": "repository.data 'keys where' predicate aborts in the native verifier — use the write-side threshold pattern instead",
|
|
401
|
+
"description": "The 'keys where' predicate form aborts with MovePrimitiveRuntimeError inside the native guard verifier on ALL networks (upw-mn-261012 F-28, live A/B verified: bare has() succeeds, keys-where aborts). ${rc2_07_keys_where_count} occurrence(s) found.",
|
|
402
|
+
"scenario": "Native abort: guard creation or verification fails with MovePrimitiveRuntimeError on every network",
|
|
403
|
+
"mitigation": "1) Move the threshold to the WRITE side: a Repository write policy enforces the value floor at write time (live-proven ptrn4 pattern — e.g. a rating >= 4 write policy aborts the non-conforming write at passport submission);\n2) The guard then reads presence only (bare 'repository.data has' or vec_contains_string on the keys vector without the where clause);\n3) See guard-design-patterns pattern.repository_data_check for the proven shape",
|
|
404
|
+
"stakeholders": ["provider", "customer"]
|
|
405
|
+
}
|
|
406
|
+
]
|
|
407
|
+
},
|
|
322
408
|
{
|
|
323
409
|
"rule_id": "R-C3-01",
|
|
324
410
|
"dimension": "submission_forgery",
|
|
@@ -333,6 +419,15 @@
|
|
|
333
419
|
"mitigation": "1) If the submitted data should belong to the operator (e.g. the operator's address), it is still recommended to add context(Signer) binding;2) If the submitted data is a public credential (e.g. Merkle Root string), the current risk is acceptable;3) Use retained_submission to retain submitted data for later audit",
|
|
334
420
|
"stakeholders": ["customer", "provider"]
|
|
335
421
|
},
|
|
422
|
+
{
|
|
423
|
+
"when": { "all": [{ "field": "has_submission", "op": "eq", "value": true }, { "field": "rc3_01_order_anchored", "op": "eq", "value": true }, { "field": "rc3_01_sharing_exempt", "op": "eq", "value": false }, { "field": "has_signer_check", "op": "eq", "value": false }] },
|
|
424
|
+
"level": "info",
|
|
425
|
+
"title": "Order-anchored recipient slots — Signer binding is structurally inapplicable",
|
|
426
|
+
"description": "Every submission slot is unread by the condition tree, so submitted values cannot influence the verdict. In the order_allocators scene the only consumption is the chain-side GuardIdentifier recipient read, which payment_info.for_object hard-binds to the paying order: order-created allocations always bind, and submitted != for_object aborts (ERECIPIENT_NOT_FOR_OBJECT). Adding a Signer binding here would BREAK keeper/service-triggered rails — a merchant-triggered refund cannot satisfy Signer==recipient. Verified live on mainnet: a merchant-triggered refund still paid the buyer (ptrn-mn-261013 F-03).",
|
|
427
|
+
"scenario": "Order-anchored payout rails (refund / recovery / settlement allocators resolved through a GuardIdentifier recipient).",
|
|
428
|
+
"mitigation": "No change needed. Residual: only standalone (non-order) Allocation runs with an unbound payment_info let the passport builder choose the recipient — that surface is the allocation owner's policy decision, not a guard defect. If a submitted slot is later READ by the condition tree, the normal R-C3-01 binding rules resume.",
|
|
429
|
+
"stakeholders": ["provider", "customer"]
|
|
430
|
+
},
|
|
336
431
|
{
|
|
337
432
|
"when": { "all": [{ "field": "has_submission", "op": "eq", "value": true }, { "field": "scene_binding_field", "op": "neq", "value": "voting_guard" }, { "field": "rc3_01_sharing_exempt", "op": "eq", "value": false }, { "field": "has_signer_check", "op": "eq", "value": false }] },
|
|
338
433
|
"level": "high",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"first_missing_guard_forward_name": "First-offender — name of the first Forward referencing a Guard outside the published set (absent when none).",
|
|
23
23
|
"first_missing_guard_guard": "That Forward's Guard address.",
|
|
24
24
|
"first_retained_no_guard_forward_name": "First-offender — name of the first Forward carrying retained_submission without any Guard (absent when none).",
|
|
25
|
-
"first_noperm_forward_name": "First-offender — name of the first Forward with NONE of namedOperator, permissionIndex, or Guard (absent when none). Note: a Guard-only forward is
|
|
25
|
+
"first_noperm_forward_name": "First-offender — name of the first Forward with NONE of namedOperator, permissionIndex, or Guard (absent when none). Note: since N-8-B a Guard-only forward is rejected by the chain at CONSTRUCTION (forward_with_guard aborts E_FORWARD_NO_IDENTITY 21) and re-checked at publish — both constructors require namedOperator or permissionIndex on EVERY forward; treat Guard as a post-verification addition, never the sole binding.",
|
|
26
26
|
"first_noperm_prev": "That Forward's Pair prev_node.",
|
|
27
27
|
"first_noperm_next": "That Forward's Pair next_node.",
|
|
28
28
|
"first_both_forward_name": "First-offender — name of the first Forward with BOTH namedOperator and permissionIndex set (absent when none).",
|
|
@@ -387,14 +387,14 @@
|
|
|
387
387
|
{
|
|
388
388
|
"rule_id": "R-M3-01",
|
|
389
389
|
"dimension": "permission",
|
|
390
|
-
"trigger": "Check each forward has at least one executor binding: namedOperator, permissionIndex, or Guard (a Guard-only forward
|
|
390
|
+
"trigger": "Check each forward has at least one executor binding: namedOperator, permissionIndex, or Guard (the chain rejects a Guard-only forward at construction and again at publish with E_FORWARD_NO_IDENTITY — Guard is a post-verification addition, never the sole binding)",
|
|
391
391
|
"cases": [
|
|
392
392
|
{
|
|
393
393
|
"when": { "field": "first_noperm_forward_name", "op": "present" },
|
|
394
394
|
"level": "critical",
|
|
395
395
|
"title": "Forward without permission",
|
|
396
396
|
"description": "Forward has no executor binding at all — neither namedOperator, permissionIndex, nor Guard. Cannot be executed (the plain forward constructor aborts E_PERMISSION_NOT_DEFINED).",
|
|
397
|
-
"mitigation": "Set namedOperator='' for OrderHolder, or set permissionIndex. Binding a Guard alone
|
|
397
|
+
"mitigation": "Set namedOperator='' for OrderHolder, or set permissionIndex. Binding a Guard alone is rejected (E_FORWARD_NO_IDENTITY aborts in both constructors and again at publish): a Guard is a post-verification addition on top of an identity field, never a replacement.",
|
|
398
398
|
"evidence": "Forward \"${first_noperm_forward_name}\" in Pair (${first_noperm_prev} -> ${first_noperm_next}) has no executor binding.",
|
|
399
399
|
"exposure": {
|
|
400
400
|
"loss_parties": [
|