@wowok/agent-mcp 3.2.2 → 3.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chain-semantics/field-capability.d.ts +11 -0
- package/dist/chain-semantics/field-capability.js +1 -0
- package/dist/chain-semantics/freeze-map.d.ts +11 -0
- package/dist/chain-semantics/freeze-map.js +1 -0
- package/dist/chain-semantics/fund-flow.d.ts +10 -0
- package/dist/chain-semantics/fund-flow.js +1 -0
- package/dist/chain-semantics/guard-verbs.d.ts +22 -0
- package/dist/chain-semantics/guard-verbs.js +1 -0
- package/dist/chain-semantics/index.d.ts +10 -0
- package/dist/chain-semantics/index.js +1 -0
- package/dist/chain-semantics/object-graph.d.ts +18 -0
- package/dist/chain-semantics/object-graph.js +1 -0
- package/dist/composition/audit.d.ts +10 -0
- package/dist/composition/audit.js +1 -0
- package/dist/composition/compile.d.ts +38 -0
- package/dist/composition/compile.js +1 -0
- package/dist/composition/materialize.d.ts +64 -0
- package/dist/composition/materialize.js +1 -0
- package/dist/composition/plan.d.ts +92 -0
- package/dist/composition/plan.js +1 -0
- package/dist/composition/reflux.d.ts +28 -0
- package/dist/composition/reflux.js +1 -0
- package/dist/evaluation/builtins/graph-service.spec.js +1 -1
- package/dist/evaluation/engine.js +1 -1
- package/dist/experience/realtime-feedback.js +1 -1
- package/dist/extensions/business-modules.js +1 -1
- package/dist/extensions/industry-pack.js +1 -1
- package/dist/extensions/modes.js +1 -1
- package/dist/graph/onchain/expand.js +1 -1
- package/dist/graph/onchain/exposure.js +1 -1
- package/dist/graph/onchain/facts.js +1 -1
- package/dist/keeper/detectors.d.ts +7 -0
- package/dist/keeper/detectors.js +1 -1
- package/dist/keeper/types.d.ts +1 -1
- package/dist/keeper/types.js +1 -1
- package/dist/knowledge/allocation-ledger.js +1 -1
- package/dist/knowledge/allocation-puzzle.js +1 -1
- package/dist/knowledge/allocation-risk.js +1 -1
- package/dist/knowledge/allocation-templates.js +1 -1
- package/dist/knowledge/arb-fund-facts.d.ts +31 -0
- package/dist/knowledge/arb-fund-facts.js +1 -0
- package/dist/knowledge/baselines/rules/allocation.json +44 -15
- package/dist/knowledge/baselines/rules/guard.json +27 -8
- package/dist/knowledge/baselines/rules/plan.json +161 -0
- package/dist/knowledge/baselines/semantic-facts.d.ts +12 -0
- package/dist/knowledge/baselines/semantic-facts.js +1 -0
- package/dist/knowledge/builtin-templates.d.ts +1 -1
- package/dist/knowledge/builtin-templates.js +1 -1
- package/dist/knowledge/getting-started.js +1 -1
- package/dist/knowledge/guard-design-patterns.js +1 -1
- package/dist/knowledge/guard-ledger.js +1 -1
- package/dist/knowledge/guard-risk.js +1 -1
- package/dist/knowledge/guard-templates.js +1 -1
- package/dist/knowledge/index.js +1 -1
- package/dist/knowledge/industry-registry.js +1 -1
- package/dist/knowledge/jsonrpc-enum.js +1 -1
- package/dist/knowledge/onchain-constants.d.ts +2 -2
- package/dist/knowledge/onchain-constants.js +1 -1
- package/dist/knowledge/scenario-modes.d.ts +12 -0
- package/dist/knowledge/service-allocation-semantics.js +1 -1
- package/dist/knowledge/service-ledger.js +1 -1
- package/dist/knowledge/service-templates.js +1 -1
- package/dist/knowledge/strategy-manuals.js +1 -1
- package/dist/knowledge/template-loader.d.ts +16 -1
- package/dist/knowledge/template-loader.js +1 -1
- package/dist/knowledge/template-registry.js +1 -1
- package/dist/knowledge/template-scanner.js +1 -1
- package/dist/knowledge/tools-reference.js +1 -1
- package/dist/knowledge/workflow-guidance.js +1 -1
- package/dist/monitor/MonitorLoop.js +1 -1
- package/dist/participation/radar-core.d.ts +6 -0
- package/dist/participation/radar-core.js +1 -1
- package/dist/playbooks/service-build/business-puzzle.js +1 -1
- package/dist/playbooks/service-build/machine-panorama.js +1 -1
- package/dist/playbooks/service-build/merchant-guide.js +1 -1
- package/dist/playbooks/service-build/migration-planner.js +1 -1
- package/dist/playbooks/service-build/object-panorama.js +1 -1
- package/dist/playbooks/service-build/participation-radar.js +1 -1
- package/dist/playbooks/service-build/relationship-profile.js +1 -1
- package/dist/playbooks/service-build/service-panorama.js +1 -1
- package/dist/playbooks/service-build/service-quote.js +1 -1
- package/dist/review/index.js +1 -1
- package/dist/safety/confirm-gate.js +1 -1
- package/dist/schema/call/order.d.ts +60 -0
- package/dist/schema/call/order.js +1 -1
- package/dist/schema/call/semantic.js +1 -1
- package/dist/schema/call/service.d.ts +56 -0
- package/dist/schema/call/service.js +1 -1
- package/dist/schema/common/index.js +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.js +1 -1
- package/dist/schema/industry-pack/index.d.ts +2 -0
- package/dist/schema/industry-pack/index.js +1 -1
- package/dist/schema/local/index.js +1 -1
- package/dist/schema/operations.d.ts +48 -0
- package/dist/schema/query/index.js +1 -1
- package/dist/schema/schema-version.js +1 -1
- package/dist/schema/service-clone/index.d.ts +46 -0
- package/dist/schema/service-clone/index.js +1 -0
- package/dist/schema-query-impl/index.js +1 -1
- package/dist/schemas/index.json +7 -1
- package/dist/schemas/industry_pack_operation.output.json +4 -0
- package/dist/schemas/industry_pack_operation.schema.json +4 -0
- package/dist/schemas/onchain_operations.output.json +1 -1
- package/dist/schemas/onchain_operations.schema.json +405 -94
- package/dist/schemas/onchain_operations_allocation.schema.json +5 -5
- package/dist/schemas/onchain_operations_arbitration.schema.json +2 -2
- package/dist/schemas/onchain_operations_contact.schema.json +1 -1
- package/dist/schemas/onchain_operations_demand.schema.json +3 -3
- package/dist/schemas/onchain_operations_gen_passport.schema.json +1 -1
- package/dist/schemas/onchain_operations_guard.schema.json +59 -59
- package/dist/schemas/onchain_operations_machine.schema.json +1 -1
- package/dist/schemas/onchain_operations_order.schema.json +133 -1
- package/dist/schemas/onchain_operations_progress.schema.json +1 -1
- package/dist/schemas/onchain_operations_proof.schema.json +1 -1
- package/dist/schemas/onchain_operations_repository.schema.json +1 -1
- package/dist/schemas/onchain_operations_reward.schema.json +4 -4
- package/dist/schemas/onchain_operations_service.schema.json +186 -7
- package/dist/schemas/onchain_operations_treasury.schema.json +7 -7
- package/dist/schemas/query_toolkit.output.json +45 -45
- package/dist/schemas/service_clone_operation.output.json +168 -0
- package/dist/schemas/service_clone_operation.schema.json +49 -0
- package/dist/schemas/workflow_operation.schema.json +1 -1
- package/dist/tools/handlers/config.js +1 -1
- package/dist/tools/handlers/industry-pack.js +1 -1
- package/dist/tools/handlers/onchain.js +1 -1
- package/dist/tools/handlers/query.js +1 -1
- package/dist/tools/handlers/service-clone.d.ts +2 -0
- package/dist/tools/handlers/service-clone.js +1 -0
- package/dist/tools/index.js +1 -1
- package/dist/tools/registry/business.js +1 -1
- package/dist/tools/wrap.d.ts +6 -1
- package/dist/tools/wrap.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SourceAnchor } from "./object-graph.js";
|
|
2
|
+
export interface FieldCapability {
|
|
3
|
+
readBy: string[];
|
|
4
|
+
writeBy: string[];
|
|
5
|
+
enforcedBy: string[];
|
|
6
|
+
writeOnly: boolean;
|
|
7
|
+
notes?: string;
|
|
8
|
+
findings?: string[];
|
|
9
|
+
source: SourceAnchor;
|
|
10
|
+
}
|
|
11
|
+
export declare const FIELD_CAPABILITY: Record<string, FieldCapability>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const FIELD_CAPABILITY={'Order.dispute':{'writeBy':['order.dispute\x20(package,\x20via\x20arb\x20dispute\x20flow)'],'readBy':['guard-query:\x20order.dispute\x20count\x20/\x20has'],'enforcedBy':[],'writeOnly':!![],'notes':'dispute\x20filing\x20does\x20NOT\x20check\x20service.arbitrations\x20whitelist\x20(A-11);\x20abort\x20surfaces\x20only\x20when\x20compensation\x20is\x20claimed.','findings':['A-10','A-11'],'source':{'file':'order.move','line':0x45,'pattern':'dispute:\x20vector<address>'}},'Order.required_info':{'writeBy':['owner-only\x20order\x20field\x20update\x20(order.move:77-80)'],'readBy':['guard-query:\x20order.required_info\x20some\x20/\x20value'],'enforcedBy':[],'writeOnly':!![],'notes':'buy\x20path\x20never\x20reads\x20customer_required/required_info\x20(A-1).\x20Owner-write-only\x20field.','findings':['A-1','A-10'],'source':{'file':'order.move','line':0x49,'pattern':'required_info:\x20Option<address>'}},'Order.claimed_by':{'writeBy':['order.compensate\x20(package,\x20order.move:94-97)'],'readBy':['the\x20not-yet-claimed\x20assert\x20on\x20the\x20compensate/dispute\x20path','guard-query:\x20order.claimed_by\x20some\x20/\x20value'],'enforcedBy':['blocks\x20second\x20compensate/dispute'],'writeOnly':![],'notes':'NOT\x20read\x20by\x20allocation.alloc\x20—\x20refund\x20rail\x20must\x20self-check\x20via\x20refund\x20guard\x20(DUAL-RAIL-01).\x20Deliberate\x20design,\x20order.move:199-220.','findings':['A-3'],'source':{'file':'order.move','line':0x48,'pattern':'claimed_by:\x20Option<address>'}},'Order.time':{'writeBy':['order.new\x20(clock::timestamp_ms\x20at\x20creation)'],'readBy':['guard-query:\x20order.time'],'enforcedBy':['template-declared\x20time\x20anchors'],'writeOnly':![],'notes':'Stable\x20anchor\x20for\x20window\x20guards\x20—\x20unlike\x20Progress.current_time\x20it\x20is\x20path-INDEPENDENT.','source':{'file':'order.move','line':0x4a,'pattern':'time:\x20u64'}},'Service.customer_required':{'writeBy':['service\x20settings\x20(pre-publish)'],'readBy':['guard-query'],'enforcedBy':[],'writeOnly':!![],'notes':'A-1:\x20declared\x20but\x20never\x20enforced\x20on\x20buy.\x20Fix\x20=\x20body-level\x20assert\x20in\x20order\x20creation\x20(protocol\x20upgrade).','findings':['A-1'],'source':{'file':'service.move','line':0xcd,'pattern':'customer_required:\x20vector<String>'}},'Service.repositories':{'writeBy':['service\x20settings'],'readBy':['guard-query:\x20service.repository\x20count\x20/\x20has'],'enforcedBy':[],'writeOnly':!![],'findings':['A-10'],'source':{'file':'service.move','line':0xc8,'pattern':'repositories:\x20vector<address>'}},'Service.rewards':{'writeBy':['service\x20settings'],'readBy':['guard-query'],'enforcedBy':[],'writeOnly':!![],'findings':['A-10'],'source':{'file':'service.move','line':0xd3,'pattern':'rewards:\x20vector<address>'}},'Service.order_allocators':{'writeBy':['service\x20settings\x20(pre-publish\x20replace;\x20post-publish\x20append-only)'],'readBy':['buy\x20path\x20(order-bound\x20Allocation\x20creation)','guard-query'],'enforcedBy':['publish\x20requires\x20non-empty\x20(E_NO_ALLOCATOR,\x20service.move:689-700)'],'writeOnly':![],'notes':'Replacement\x20frozen\x20at\x20publish\x20(E_ALREADY_PUBLISHED\x20on\x20the\x20pre-publish\x20replacement\x20path).\x20Append-only\x20additions\x20remain\x20possible\x20via\x20order_allocators_append\x20—\x20prefix\x20allocators\x20+\x20threshold\x20frozen,\x20EALLOCATORS_NOT_EXTENSION=20\x20on\x20violation\x20(J1).\x20Zero\x20allocator\x20rows\x20=\x20no\x20settlement\x20and\x20no\x20refund\x20rail\x20(B-1).','findings':['B-1','A-2'],'source':{'file':'service.move','line':0xd2,'pattern':'order_allocators:\x20Option<Allocators>'}},'Sale.wip':{'writeBy':['service\x20sales\x20mutation'],'readBy':['guard-query'],'enforcedBy':[],'writeOnly':!![],'notes':'wip_hash\x20IS\x20enforced\x20at\x20quote\x20(E_WIP_HASH_NOT_MATCH);\x20wip\x20url\x20itself\x20is\x20not.\x20No\x20on-chain\x20escrow\x20of\x20wip\x20content\x20(A-15).','findings':['A-10','A-15'],'source':{'file':'service.move','line':0x6b,'pattern':'wip:\x20String'}},'Machine.consensus_repositories':{'writeBy':['machine\x20settings\x20(pre-publish)'],'readBy':['guard-query:\x20machine.consensus_repository\x20count\x20/\x20has'],'enforcedBy':[],'writeOnly':!![],'findings':['A-10'],'source':{'file':'machine.move','line':0x13f,'pattern':'consensus_repositories:\x20vector<address>'}},'Machine.nodes':{'writeBy':['machine\x20graph\x20mutation\x20(pre-publish)'],'readBy':['progress\x20node-advance','guard-query'],'enforcedBy':['publish\x20freeze\x20—\x20publishing\x20blocks\x20all\x20later\x20graph\x20changes'],'writeOnly':![],'notes':'Missing\x20edge\x20after\x20publish\x20=\x20permanent\x20brick\x20(A-2);\x20L1\x20must\x20dry-run\x20terminal\x20reachability\x20pre-publish.','findings':['A-2'],'source':{'file':'machine.move','line':0x13e,'pattern':'nodes:\x20ParentLinkedTable<String,\x20vector<NodePair>>'}},'Progress.current_time':{'writeBy':['progress\x20node\x20entry\x20(timestamp\x20refreshed\x20on\x20every\x20advance,\x20progress.move:458)'],'readBy':['guard-query:\x20progress.current_time'],'enforcedBy':['window\x20guards\x20anchored\x20on\x20it'],'writeOnly':![],'notes':'PATH-DEPENDENT:\x20=\x20time\x20of\x20entering\x20CURRENT\x20node.\x20Routing\x20through\x20extra\x20nodes\x20(e.g.\x20reviewed)\x20postpones\x20settlement\x20windows\x20(E-10).\x20TIME-ANCHOR-01\x20checks\x20anchor\x20invariance\x20across\x20paths.','findings':['E-10','D-14'],'source':{'file':'progress.move','line':0x55,'pattern':'current_time:\x20u64'}},'Discount.benchmark':{'writeBy':['service.discounts\x20(creation)'],'readBy':['quote\x20price\x20calc\x20(discount\x20application)'],'enforcedBy':[],'writeOnly':![],'notes':'A-4:\x20below-benchmark\x20coupon\x20does\x20NOT\x20change\x20price\x20but\x20IS\x20still\x20burned\x20(a\x20discounted\x20quote\x20sets\x20discount:some\x20and\x20the\x20buy\x20path\x20destroys\x20the\x20coupon\x20unconditionally).','findings':['A-4'],'source':{'file':'service.move','line':0x85,'pattern':'benchmark:\x20Option<u64>'}},'Allocation.payment_info.for_object':{'writeBy':['buy\x20path\x20(set\x20to\x20the\x20Order\x20anchor\x20at\x20Allocation\x20creation)'],'readBy':['allocation.alloc\x20(ENO_PAYMENT_INFO\x20assert)'],'enforcedBy':['alloc\x20aborts\x20when\x20absent'],'writeOnly':![],'notes':'None\x20+\x20GuardIdentifier\x20recipient\x20=\x20CRITICAL\x20(funds\x20unrouteable)\x20—\x20template_scan\x20R-RECIPIENT-03\x20territory.','source':{'file':'allocation.move','line':0x194,'pattern':'payment_info:\x20Option<PaymentInfo>'}},'Treasury.inflow':{'writeBy':['treasury\x20deposit\x20paths'],'readBy':['guard-query','direct\x20field\x20accessor\x20treasury.inflow'],'enforcedBy':[],'writeOnly':![],'notes':'owner_receive\x20moves\x20value\x20out\x20WITHOUT\x20touching\x20outflow\x20—\x20never\x20re-derive\x20inflow\x20from\x20events\x20(treasury.move:86-88).','source':{'file':'treasury.move','line':0x4f,'pattern':'inflow:\x20u128'}},'Contact.permission':{'writeBy':['contact\x20settings'],'readBy':[],'enforcedBy':[],'writeOnly':![],'notes':'Never\x20consulted\x20anywhere\x20—\x20the\x20contact\x20status-change\x20call\x20(contact.move:33-43)\x20ignores\x20it\x20(A-16).\x20Not\x20part\x20of\x20the\x20A-10\x20guard-query\x20cluster:\x20it\x20has\x20no\x20reader\x20at\x20all.','findings':['A-16'],'source':{'file':'contact.move','line':0x1e,'pattern':'permission:\x20address'}}};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SourceAnchor } from "./object-graph.js";
|
|
2
|
+
export interface FreezeEntry {
|
|
3
|
+
object: string;
|
|
4
|
+
trigger: string;
|
|
5
|
+
frozen: string[];
|
|
6
|
+
preconditions: string[];
|
|
7
|
+
consequence: string;
|
|
8
|
+
findings?: string[];
|
|
9
|
+
sources: SourceAnchor[];
|
|
10
|
+
}
|
|
11
|
+
export declare const FREEZE_MAP: Record<string, FreezeEntry>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const FREEZE_MAP={'service_publish':{'object':'Service<T>','trigger':'service.publish','frozen':['order_allocators:\x20full\x20replacement\x20blocked\x20(E_ALREADY_PUBLISHED);\x20append-only\x20additions\x20remain\x20possible\x20(order_allocators_append,\x20prefix/threshold\x20frozen\x20—\x20EALLOCATORS_NOT_EXTENSION=20)','all\x20settings\x20paths\x20(every\x20mutation\x20aborts\x20once\x20published)'],'preconditions':['order_allocators\x20must\x20be\x20non-empty\x20(E_NO_ALLOCATOR)','compensation_fund\x20>\x200\x20implies\x20arbitrations\x20non-empty'],'consequence':'Wrong/missing\x20allocator\x20or\x20unreachable\x20business-terminal\x20node\x20=\x20permanent\x20brick;\x20the\x20only\x20remedy\x20is\x20a\x20new\x20Service\x20(A-2).','findings':['A-2'],'sources':[{'file':'service.move','line':0x2dd,'pattern':'E_ALREADY_PUBLISHED'},{'file':'service.move','line':0x2be,'pattern':'E_NO_ALLOCATOR'}]},'machine_publish':{'object':'Machine','trigger':'machine.publish','frozen':['entire\x20graph:\x20nodes/pairs/forwards\x20(publish\x20blocks\x20every\x20later\x20graph\x20mutation)'],'preconditions':['publishability\x20checks:\x20E_NO_ENTRY_EDGE(19)\x20E_EDGE_SOURCE_NOT_FOUND(20)\x20E_FORWARD_NO_IDENTITY(21)\x20E_UNREACHABLE_THRESHOLD(22)'],'consequence':'A\x20missing\x20paid->closed_cancel\x20edge\x20can\x20never\x20be\x20added\x20later\x20(A-2/F-2).','findings':['A-2'],'sources':[{'file':'machine.move','line':0x146,'pattern':'assert_not_published'},{'file':'machine.move','line':0x33,'pattern':'E_NO_ENTRY_EDGE'}]},'forward_construction':{'object':'machine.Forward','trigger':'machine\x20forward\x20construction,\x20guarded\x20or\x20plain\x20(pre-publish)','frozen':[],'preconditions':['permissionIndex\x20>=\x201000\x20(USER_DEFINED_PERM_INDEX,\x20machine.move:91,109)\x20—\x20template\x20perm\x202/3\x20aborts\x20on\x20chain\x20(B-8)','retained_submission\x20must\x20be\x20a\x20subset\x20of\x20the\x20guard\x27s\x20submissions\x20(E_RETAINED_SUBMISSION_ERROR,\x20machine.move:95)','one\x20of\x20namedOperator\x20|\x20permissionIndex\x20|\x20guard\x20must\x20be\x20set\x20(E_PERMISSION_NOT_DEFINED)'],'consequence':'Bad\x20forwards\x20fail\x20at\x20build\x20time\x20—\x20but\x20only\x20if\x20the\x20tool\x20layer\x20surfaces\x20the\x20abort\x20reason.','findings':['B-8'],'sources':[{'file':'machine.move','line':0x5b,'pattern':'USER_DEFINED_PERM_INDEX'},{'file':'machine.move','line':0x5f,'pattern':'E_RETAINED_SUBMISSION_ERROR'}]},'repository_no_freeze':{'object':'Repository','trigger':'(none\x20—\x20no\x20publish\x20concept)','frozen':[],'preconditions':['policies\x20mutable\x20post-share\x20via\x20the\x20permission-guarded\x20policy\x20add/set/remove/clear\x20calls\x20(repository.move:695-776)'],'consequence':'Write-policy\x20mistakes\x20are\x20repairable\x20—\x20unlike\x20Machine/Service\x20publish.','sources':[{'file':'repository.move','line':0x2b7,'pattern':'public\x20fun\x20policy_add'}]},'discount_creation':{'object':'Discount','trigger':'service.discounts\x20(creation)','frozen':['all\x20fields\x20including\x20transferable\x20and\x20benchmark'],'preconditions':['discount_type\x20in\x20{0\x20rates,\x201\x20minus};\x20rates\x20requires\x20off\x20<=\x2010000','time_end\x20>=\x20time_start\x20(default\x20now)'],'consequence':'Non-transferable\x20coupon\x20can\x20never\x20be\x20re-homed;\x20benchmark\x20errors\x20burn\x20buyer\x20coupons\x20(A-4).','findings':['A-4'],'sources':[{'file':'service.move','line':0x8d,'pattern':'fun\x20discounts'}]}};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SourceAnchor } from "./object-graph.js";
|
|
2
|
+
export interface FundFlow {
|
|
3
|
+
kind: "entry" | "exit" | "internal" | "fact";
|
|
4
|
+
summary: string;
|
|
5
|
+
path: string[];
|
|
6
|
+
invariants: string[];
|
|
7
|
+
findings?: string[];
|
|
8
|
+
sources: SourceAnchor[];
|
|
9
|
+
}
|
|
10
|
+
export declare const FUND_FLOWS: Record<string, FundFlow>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const FUND_FLOWS={'buy_entry':{'kind':'entry','summary':'Buyer\x20pays:\x20coin\x20split\x20->\x20Order\x20+\x20Allocation\x20escrow\x20anchored\x20to\x20the\x20order.','path':['service\x20buy\x20(creates\x20Order,\x20service.move:441)','order-bound\x20Allocation\x20creation\x20(splits\x20coin,\x20sets\x20payment_info.for_object=order,\x20service.move:390)'],'invariants':['Allocation.balance\x20==\x20order\x20amount\x20at\x20creation','quote.ctx\x20binds\x20quote\x20to\x20tx\x20digest;\x20stock\x20deducted\x20in\x20same\x20tx\x20as\x20buy'],'sources':[{'file':'service.move','line':0x1b9,'pattern':'buy2_imp'},{'file':'service.move','line':0x186,'pattern':'order_allocation'}]},'exit_alloc':{'kind':'exit','summary':'Escrow\x20exit\x201\x20(settlement\x20/\x20refund):\x20guard-matched\x20allocators\x20distribute\x20the\x20pool.','path':['allocation.alloc\x20(allocation.move:408)','per\x20matched\x20allocator:\x20once-slot\x20(OnceKey{guard,\x20allocator\x20index,\x20key})\x20consumed','Payment<T>\x20created;\x20CoinWrapper<T>\x20transferred\x20to\x20each\x20recipient','recipient\x20unwraps\x20via\x20payment.unwrap\x20/\x20order.owner_receive'],'invariants':['balance\x20>=\x20allocators.threshold\x20(EINSUFFICIENT_BALANCE)','balance\x20>\x200\x20(EZERO_DISTRIBUTION)\x20—\x20replay\x20on\x20drained\x20pool\x20aborts','payment_info\x20must\x20be\x20some\x20(ENO_PAYMENT_INFO)','every\x20allocator\x20with\x20matching\x20guard\x20RUNS,\x20in\x20vector\x20order,\x20against\x20the\x20shrinking\x20pool','once-slot\x20per\x20allocator\x20index\x20makes\x20replay\x20of\x20the\x20same\x20guard\x20abort'],'findings':['A-3'],'sources':[{'file':'allocation.move','line':0x198,'pattern':'public\x20fun\x20alloc<T>'},{'file':'allocation.move','line':0x19f,'pattern':'EZERO_DISTRIBUTION'}]},'exit_compensation':{'kind':'exit','summary':'Escrow\x20exit\x202\x20(arbitration\x20indemnity):\x20service\x20compensation_fund\x20pays\x20order\x20owner\x20directly.','path':['service\x20compensation\x20claim\x20(service.move:476;\x20arbitrations\x20whitelist\x20+\x20E33\x20conflict\x20check\x20at\x20:485-487)','arbitration.compensate\x20->\x20order.compensate\x20writes\x20claimed_by','compensation_fund\x20split\x20->\x20public_transfer\x20to\x20order.owner\x20(service.move:494)'],'invariants':['order\x20must\x20not\x20be\x20already\x20claimed\x20(E_ORDER_ALREADY_CLAIMED)','claiming\x20arbitration\x20must\x20be\x20in\x20service.arbitrations\x20whitelist'],'sources':[{'file':'service.move','line':0x1dc,'pattern':'compensation_claim'},{'file':'service.move','line':0x1ee,'pattern':'order::owner(order)'},{'file':'order.move','line':0x5e,'pattern':'public(package)\x20fun\x20compensate'}]},'dual_rail_fact':{'kind':'fact','summary':'A-3\x20dual\x20rail:\x20alloc\x20never\x20reads\x20claimed_by;\x20compensate\x20never\x20touches\x20the\x20escrow\x20balance.','path':['order.move:199-220\x20(deliberate:\x20refund-of-principal\x20+\x20damages\x20in\x20one\x20case\x20is\x20legal)'],'invariants':['Double-pay\x20prevention\x20is\x20delegated\x20to\x20template\x20convention:\x20refund\x20guard\x20MUST\x20assert\x20claimed_by\x20is\x20none','Tool\x20layer\x20MUST\x20enforce\x20this\x20convention\x20via\x20rule\x20DUAL-RAIL-01\x20—\x20the\x20chain\x20will\x20not'],'findings':['A-3'],'sources':[{'file':'order.move','line':0xc7,'pattern':'claimed_by'}]},'buyer_receive':{'kind':'exit','summary':'Buyer\x20claims\x20inbound\x20funds:\x20order.owner_receive\x20unwraps\x20Payment\x20and\x20transfers\x20coin\x20to\x20owner.','path':['order.owner_receive\x20(order.move:226-229,\x20public_transfer\x20to\x20self.owner)'],'invariants':['only\x20order.owner\x20receives'],'sources':[{'file':'order.move','line':0xe2,'pattern':'owner_receive'}]},'reward_claim':{'kind':'exit','summary':'Reward\x20pool\x20exit:\x20guard+passport\x20gated\x20claim\x20transfers\x20coin\x20to\x20recipient.','path':['reward.claim\x20(reward.move:139)\x20->\x20coin\x20to\x20recipient\x20(reward.move:202)'],'invariants':['passport\x20must\x20satisfy\x20the\x20matched\x20RewardGuard'],'sources':[{'file':'reward.move','line':0x8b,'pattern':'public\x20fun\x20claim<T>'}]},'treasury_flows':{'kind':'internal','summary':'Treasury:\x20deposit/withdraw/guard-driven\x20external\x20flows;\x20owner_receive\x20bypasses\x20outflow\x20counter.','path':['treasury.deposit\x20/\x20withdraw\x20(external_*_guard\x20driven\x20variants)','treasury.owner_receive\x20moves\x20value\x20out\x20WITHOUT\x20touching\x20outflow'],'invariants':['inflow\x20and\x20outflow\x20are\x20u128\x20accumulators;\x20conservation\x20audit\x20must\x20read\x20fields,\x20not\x20events'],'sources':[{'file':'treasury.move','line':0x48,'pattern':'public\x20struct\x20Treasury<phantom\x20T>\x20has\x20key'}]},'discount_burn':{'kind':'fact','summary':'A-4:\x20coupon\x20burned\x20unconditionally\x20at\x20buy,\x20even\x20when\x20benchmark\x20unmet\x20(price\x20unchanged).','path':['the\x20discounted\x20quote\x20sets\x20quote.discount=some\x20unconditionally\x20(service.move:351)','the\x20buy\x20path\x20destroys\x20the\x20coupon\x20unconditionally\x20(service.move:451)'],'invariants':['Fix\x20(protocol\x20upgrade,\x20body-level):\x20the\x20discounted\x20quote\x20returns\x20discount:none\x20below\x20benchmark'],'findings':['A-4'],'sources':[{'file':'service.move','line':0x15f,'pattern':'discount'},{'file':'service.move','line':0x1c3,'pattern':'discount_destroy'}]},'conservation_gap':{'kind':'fact','summary':'No\x20on-chain\x20conservation\x20check:\x20accumulator_*\x20are\x20private\x20and\x20sender==@0x0\x20is\x20unreachable.','path':[],'invariants':['Conservation\x20(sum\x20in\x20==\x20sum\x20out\x20+\x20balances)\x20MUST\x20be\x20audited\x20by\x20the\x20tool\x20layer\x20post-materialization\x20(A-14)'],'findings':['A-14'],'sources':[{'file':'service.move','line':0xcf,'pattern':'compensation_fund:\x20Balance<T>'}]}};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SourceAnchor } from "./object-graph.js";
|
|
2
|
+
export declare const GUARD_QUERY_SOURCE: "ts-sdk/packages/wowok/src/w/call/guard-ins.ts#GUARDQUERY";
|
|
3
|
+
export declare const NATIVE_VALIDATION: {
|
|
4
|
+
entry: string;
|
|
5
|
+
semantics: string[];
|
|
6
|
+
sources: SourceAnchor[];
|
|
7
|
+
};
|
|
8
|
+
export declare const PATH_DEPENDENT_TIME_QUERIES: {
|
|
9
|
+
queryPrefix: string;
|
|
10
|
+
semantics: string;
|
|
11
|
+
findings: string[];
|
|
12
|
+
sources: SourceAnchor[];
|
|
13
|
+
}[];
|
|
14
|
+
export declare const STABLE_TIME_QUERIES: {
|
|
15
|
+
queryPrefix: string;
|
|
16
|
+
semantics: string;
|
|
17
|
+
}[];
|
|
18
|
+
export declare const WRITE_ONLY_QUERY_PREFIXES: {
|
|
19
|
+
queryPrefix: string;
|
|
20
|
+
field: string;
|
|
21
|
+
findings: string[];
|
|
22
|
+
}[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const GUARD_QUERY_SOURCE='ts-sdk/packages/wowok/src/w/call/guard-ins.ts#GUARDQUERY';export const NATIVE_VALIDATION={'entry':'the\x20native\x20guard-data\x20validation\x20call\x20(guard.move:15),\x20invoked\x20at\x20guard.move:256','semantics':['Query\x20on\x20absent\x20object\x20/\x20unset\x20Option\x20/\x20missing\x20collection\x20entry\x20aborts\x20with\x20VM\x20error\x20(e.g.\x20W_FIELD_NOT_FOUND)\x20—\x20the\x20Guard\x20does\x20NOT\x20silently\x20return\x200.\x20Safe\x20failure\x20mode,\x20NOT\x20a\x20null-bypass\x20risk.','Guard.rep\x20flag:\x20false\x20means\x20the\x20queried\x20object\x20or\x20first\x20parameter\x20failed\x20validation.','Empty-value\x20table\x20constant\x20crashes\x20with\x20MovePrimitiveRuntimeError\x20(A-5):\x20vector::borrow(&item.value,0)\x20without\x20length\x20check.'],'sources':[{'file':'guard.move','line':0xf,'pattern':'native\x20fun\x20validate_guard_data'},{'file':'guard.move','line':0x100,'pattern':'validate_guard_data(&table_data,\x20input)'},{'file':'guard.move','line':0x76,'pattern':'rep:\x20bool'}]};export const PATH_DEPENDENT_TIME_QUERIES=[{'queryPrefix':'progress.current_time','semantics':'Time\x20of\x20ENTERING\x20the\x20current\x20node\x20(progress.move:458),\x20not\x20of\x20any\x20business\x20event.\x20A\x20buyer\x20leaving\x20a\x20review\x20(detour\x20via\x20reviewed\x20node)\x20postpones\x20merchant\x20settlement\x20windows.','findings':['E-10','D-14'],'sources':[{'file':'progress.move','line':0x55,'pattern':'current_time:\x20u64'}]},{'queryPrefix':'progress.session.forward.time','semantics':'Per-forward\x20last-op\x20time\x20inside\x20the\x20current\x20session;\x20also\x20path-local.','findings':['E-10'],'sources':[{'file':'progress.move','line':0x2d,'pattern':'time:\x20u64'}]}];export const STABLE_TIME_QUERIES=[{'queryPrefix':'order.time','semantics':'Order\x20creation\x20time\x20(order.move:112).\x20Never\x20moves.\x20Preferred\x20anchor\x20for\x20settlement/refund\x20windows.'}];export const WRITE_ONLY_QUERY_PREFIXES=[{'queryPrefix':'order.dispute','field':'Order.dispute','findings':['A-10','A-11']},{'queryPrefix':'order.required_info','field':'Order.required_info','findings':['A-1','A-10']},{'queryPrefix':'order.claimed_by','field':'Order.claimed_by','findings':['A-3']},{'queryPrefix':'service.repository','field':'Service.repositories','findings':['A-10']},{'queryPrefix':'service.reward','field':'Service.rewards','findings':['A-10']},{'queryPrefix':'service.sale.wip','field':'Sale.wip','findings':['A-10','A-15']},{'queryPrefix':'machine.consensus_repository','field':'Machine.consensus_repositories','findings':['A-10']}];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { OBJECT_GRAPH, type ObjectEntry, type ObjectName, type Ownership, type SourceAnchor } from "./object-graph.js";
|
|
2
|
+
export { FIELD_CAPABILITY, type FieldCapability } from "./field-capability.js";
|
|
3
|
+
export { FUND_FLOWS, type FundFlow } from "./fund-flow.js";
|
|
4
|
+
export { FREEZE_MAP, type FreezeEntry } from "./freeze-map.js";
|
|
5
|
+
export { GUARD_QUERY_SOURCE, NATIVE_VALIDATION, PATH_DEPENDENT_TIME_QUERIES, STABLE_TIME_QUERIES, WRITE_ONLY_QUERY_PREFIXES, } from "./guard-verbs.js";
|
|
6
|
+
import { type ObjectName } from "./object-graph.js";
|
|
7
|
+
export declare function isWriteOnlyField(field: string): boolean;
|
|
8
|
+
export declare function isPathDependentTimeQuery(queryName: string): boolean;
|
|
9
|
+
export declare function writeOnlyFieldForQuery(queryName: string): string | undefined;
|
|
10
|
+
export declare function referrersOf(target: string): ObjectName[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{OBJECT_GRAPH}from'./object-graph.js';export{FIELD_CAPABILITY}from'./field-capability.js';export{FUND_FLOWS}from'./fund-flow.js';export{FREEZE_MAP}from'./freeze-map.js';export{GUARD_QUERY_SOURCE,NATIVE_VALIDATION,PATH_DEPENDENT_TIME_QUERIES,STABLE_TIME_QUERIES,WRITE_ONLY_QUERY_PREFIXES}from'./guard-verbs.js';import{FIELD_CAPABILITY}from'./field-capability.js';import{OBJECT_GRAPH}from'./object-graph.js';import{PATH_DEPENDENT_TIME_QUERIES,WRITE_ONLY_QUERY_PREFIXES}from'./guard-verbs.js';export function isWriteOnlyField(a){return FIELD_CAPABILITY[a]?.['writeOnly']===!![];}export function isPathDependentTimeQuery(a){return PATH_DEPENDENT_TIME_QUERIES['some'](b=>a['startsWith'](b['queryPrefix']));}export function writeOnlyFieldForQuery(a){return WRITE_ONLY_QUERY_PREFIXES['find'](b=>a['startsWith'](b['queryPrefix']))?.['field'];}export function referrersOf(a){return Object['keys'](OBJECT_GRAPH)['filter'](b=>Object['values'](OBJECT_GRAPH[b]['references'])['some'](c=>c['includes'](a)));}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface SourceAnchor {
|
|
2
|
+
file: string;
|
|
3
|
+
line: number;
|
|
4
|
+
pattern: string;
|
|
5
|
+
}
|
|
6
|
+
export type Ownership = "shared" | "owned" | "singleton" | "value";
|
|
7
|
+
export interface ObjectEntry {
|
|
8
|
+
module: string;
|
|
9
|
+
ownership: Ownership;
|
|
10
|
+
typeParam?: string;
|
|
11
|
+
references: Record<string, string>;
|
|
12
|
+
valueFields: Record<string, string>;
|
|
13
|
+
notes?: string;
|
|
14
|
+
source: SourceAnchor;
|
|
15
|
+
findings?: string[];
|
|
16
|
+
}
|
|
17
|
+
export declare const OBJECT_GRAPH: Record<string, ObjectEntry>;
|
|
18
|
+
export type ObjectName = keyof typeof OBJECT_GRAPH;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const OBJECT_GRAPH={'Sale':{'module':'service','ownership':'value','references':{},'valueFields':{'name':'String','price':'u64','stock':'u64','suspension':'bool','wip':'String\x20//\x20write-only\x20(A-10)','wip_hash':'String\x20//\x20enforced\x20at\x20quote\x20(E_WIP_HASH_NOT_MATCH)'},'notes':'Value\x20type\x20embedded\x20in\x20Service.sales;\x20no\x20independent\x20identity.','source':{'file':'service.move','line':0x66,'pattern':'public\x20struct\x20Sale\x20has\x20store,\x20drop,\x20copy'},'findings':['A-10','A-15']},'Permission':{'module':'permission','ownership':'shared','references':{'um':'Contact?'},'valueFields':{'owner':'address','admin':'vector<address>','description':'String','remark':'vector<PermissionRemark>','table':'ParentLinkedTable<address,\x20vector<u16>>\x20//\x20entity/guard\x20->\x20perm\x20indexes'},'notes':'USER_DEFINED_PERM_INDEX_START=1000\x20enforced\x20at\x20construction;\x20the\x20permission\x20check\x20grants\x20all\x20indexes\x20to\x20admins.','source':{'file':'permission.move','line':0x21,'pattern':'public\x20struct\x20Permission\x20has\x20key'}},'Guard':{'module':'guard','ownership':'shared','references':{'relies':'address[]\x20//\x20any\x20object'},'valueFields':{'description':'String','table':'vector<TableItem>','validated':'vector<TableItemType>','input':'vector<u8>','relies_logic_and':'bool','immutable':'bool','rep':'bool'},'notes':'rep=false\x20means\x20the\x20queried\x20object/first\x20param\x20failed\x20the\x201167\x20query\x20validation.','source':{'file':'guard.move','line':0x6d,'pattern':'public\x20struct\x20Guard\x20has\x20key'}},'Machine':{'module':'machine','ownership':'shared','references':{'consensus_repositories':'Repository[]','um':'Contact?','permission':'Permission'},'valueFields':{'description':'String','nodes':'ParentLinkedTable<String,\x20vector<NodePair>>','bPaused':'bool','bPublished':'bool'},'notes':'Forward\x20=\x20{namedOperator?\x20|\x20permissionIndex?\x20(pre-check,\x20namedOperator\x20first)}\x20+\x20guard?\x20(post-check).\x20permissionIndex>=1000\x20at\x20construction;\x20retained_submission\x20must\x20be\x20subset\x20of\x20guard\x20submissions.','source':{'file':'machine.move','line':0x13b,'pattern':'public\x20struct\x20Machine\x20has\x20key'}},'Service<T>':{'module':'service','typeParam':'T','ownership':'shared','references':{'repositories':'Repository[]','buy_guard':'Guard?','machine':'Machine?','arbitrations':'Arbitration<T>[]','order_allocators':'Guard\x20(via\x20Allocators.allocators[].guard)','rewards':'Reward<T>[]','um':'Contact?','permission':'Permission'},'valueFields':{'description':'String','location':'String','sales':'vector<Sale>','bPublished':'bool','bPaused':'bool','customer_required':'vector<String>','compensation_fund':'Balance<T>','paused_time':'Option<u64>','setting_lock_duration':'u64'},'notes':'customer_required\x20is\x20write-only,\x20buy\x20path\x20never\x20enforces\x20it\x20(A-1).\x20compensation_fund\x20pays\x20arbitrator\x20indemnity\x20directly\x20to\x20order\x20owner.','source':{'file':'service.move','line':0xc3,'pattern':'public\x20struct\x20Service<phantom\x20T>\x20has\x20key'},'findings':['A-1','A-4','A-9','A-10','A-15']},'Order':{'module':'order','ownership':'shared','references':{'service':'Service<T>','machine':'Machine?','progress':'Progress?','allocation':'Allocation<T>?','discount':'Discount?','claimed_by':'Arb<T>?','required_info':'Contact|Proof?','dispute':'Arb<T>[]','agent':'address[]'},'valueFields':{'items':'vector<SaleItem>','amount':'u64','owner':'address','time':'u64\x20//\x20order\x20creation'},'notes':'claimed_by\x20written\x20by\x20compensate;\x20NOT\x20read\x20by\x20allocation.alloc\x20(dual-rail,\x20A-3\x20deliberate).\x20required_info\x20writable\x20by\x20owner\x20only,\x20enforced\x20nowhere\x20(A-1).','source':{'file':'order.move','line':0x3c,'pattern':'public\x20struct\x20Order\x20has\x20key'},'findings':['A-1','A-3','A-10']},'Progress':{'module':'progress','ownership':'shared','references':{'machine':'Machine','task':'Order?','context_repositories':'Repository[]'},'valueFields':{'current':'String','namedOperator':'vector<NamedOperator>','session':'vector<Session>','history':'ParentTableVec<History>','current_time':'u64\x20//\x20TIME\x20OF\x20ENTERING\x20CURRENT\x20NODE,\x20path-dependent\x20(E-10)'},'notes':'current_time\x20refreshes\x20on\x20every\x20node\x20transition;\x20window\x20guards\x20anchored\x20on\x20it\x20are\x20path-dependent.','source':{'file':'progress.move','line':0x4c,'pattern':'public\x20struct\x20Progress\x20has\x20key'},'findings':['E-10','D-14','A-6']},'Allocation<T>':{'module':'allocation','typeParam':'T','ownership':'shared','references':{'allocators.allocators[].guard':'Guard','payment':'Payment<T>[]','payment_info.for_object':'Order\x20(anchor)'},'valueFields':{'balance':'Balance<T>','allocators':'Allocators','payment_info':'Option<PaymentInfo>'},'notes':'alloc\x20runs\x20EVERY\x20allocator\x20whose\x20guard\x20matches;\x20each\x20consumes\x20a\x20once-slot\x20keyed\x20by\x20allocator\x20index;\x20evaluated\x20in\x20vector\x20order\x20against\x20shrinking\x20pool.','source':{'file':'allocation.move','line':0x190,'pattern':'public\x20struct\x20Allocation<phantom\x20T>\x20has\x20key'},'findings':['A-3']},'Payment<T>':{'module':'payment','typeParam':'T','ownership':'shared','references':{'info.for_object':'object?','info.for_guard':'Guard?','from_object':'object?'},'valueFields':{'amount':'u64','time':'u64','info':'PaymentInfo','signer':'address','record':'vector<Revenue>'},'source':{'file':'payment.move','line':0x5c,'pattern':'public\x20struct\x20Payment<phantom\x20T>\x20has\x20key'}},'CoinWrapper<T>':{'module':'payment','typeParam':'T','ownership':'owned','references':{'payment':'Payment<T>'},'valueFields':{'balance':'Balance<T>'},'notes':'Transferred\x20to\x20each\x20recipient;\x20unwrap\x20yields\x20Coin<T>.','source':{'file':'payment.move','line':0x27,'pattern':'public\x20struct\x20CoinWrapper<phantom\x20T>\x20has\x20key,\x20store'}},'Arbitration<T>':{'module':'arbitration','typeParam':'T','ownership':'shared','references':{'voting_guard[].guard':'Guard','usage_guard':'Guard?','um':'Contact?','permission':'Permission'},'valueFields':{'description':'String','location':'String','fee':'u64','balance':'Balance<T>','bPaused':'bool'},'notes':'Independent\x20arbitrator\x20=\x20independent\x20account\x20+\x20independent\x20Permission.\x20Empty\x20voting_guard\x20=\x20open\x20voting.','source':{'file':'arbitration.move','line':0x2f,'pattern':'public\x20struct\x20Arbitration<phantom\x20T>\x20has\x20key'}},'Arb<T>':{'module':'arb','typeParam':'T','ownership':'shared','references':{'order':'Order','arbitration':'Arbitration<T>'},'valueFields':{'voted':'vector<Voted>','proposition':'vector<Proposition>','fee':'Balance<T>','feedback':'String','indemnity':'Option<Indemnity>','voting_deadline':'Option<u64>','objection':'String','status':'u8\x20//\x200..6\x20Principal_confirming..Withdrawn','compensation_time':'Option<u64>','time':'u64'},'source':{'file':'arb.move','line':0x86,'pattern':'public\x20struct\x20Arb<phantom\x20T>\x20has\x20key'}},'Repository':{'module':'repository','ownership':'shared','references':{'policies[].write_guard[].guard':'Guard','policies[].quote_guard':'Guard?','rewards':'Reward<T>[]','um':'Contact?','permission':'Permission'},'valueFields':{'description':'String','policies':'vector<PolicyRule>','data':'ParentTable<DataKey,\x20vector<u8>>'},'notes':'Policies\x20mutable\x20post-share\x20via\x20the\x20permission-guarded\x20policy\x20add/set/remove/clear\x20calls\x20(repository.move:695-776).\x20The\x20passport-based\x20id-data\x20removal\x20call\x20always\x20aborts\x20(A-8).','source':{'file':'repository.move','line':0x1e2,'pattern':'public\x20struct\x20Repository\x20has\x20key'},'findings':['A-8','A-10']},'Demand':{'module':'demand','ownership':'shared','references':{'rewards':'Reward<T>[]','guards[].guard':'Guard','um':'Contact?','permission':'Permission'},'valueFields':{'description':'String','location':'String','presenters':'ParentTable<address,\x20ServiceInfo>'},'source':{'file':'demand.move','line':0x49,'pattern':'public\x20struct\x20Demand\x20has\x20key'}},'Reward<T>':{'module':'reward','typeParam':'T','ownership':'shared','references':{'guards[].guard':'Guard','um':'Contact?','permission':'Permission'},'valueFields':{'description':'String','balance':'Balance<T>','guard_not_added_expiration_time':'Option<u64>','record':'ParentTable<address,\x20RecipientRecord>'},'source':{'file':'reward.move','line':0x80,'pattern':'public\x20struct\x20Reward<phantom\x20T>\x20has\x20key'}},'Treasury<T>':{'module':'treasury','typeParam':'T','ownership':'shared','references':{'external_deposit_guard[].guard':'Guard','external_withdraw_guard[].guard':'Guard','um':'Contact?','permission':'Permission'},'valueFields':{'balance':'Balance<T>','history':'ParentTable<address,\x20Record>','inflow':'u128','outflow':'u128'},'notes':'owner_receive\x20moves\x20value\x20out\x20WITHOUT\x20touching\x20outflow;\x20read\x20inflow\x20field,\x20never\x20re-derive\x20from\x20events.','source':{'file':'treasury.move','line':0x48,'pattern':'public\x20struct\x20Treasury<phantom\x20T>\x20has\x20key'}},'Contact':{'module':'contact','ownership':'shared','references':{'permission':'Permission'},'valueFields':{'description':'String','location':'String','ims':'vector<Im>'},'notes':'The\x20contact\x20status-change\x20call\x20has\x20NO\x20permission\x20check;\x20the\x20permission\x20field\x20is\x20never\x20consulted\x20by\x20it\x20(A-16).','source':{'file':'contact.move','line':0x19,'pattern':'public\x20struct\x20Contact\x20has\x20key'},'findings':['A-16']},'Proof':{'module':'proof','ownership':'owned','references':{'about':'object?'},'valueFields':{'description':'String','proof':'String','item_count':'Option<u64>','server_pubkey':'String','server_signature':'String','signer':'address','proof_type':'u64','time':'u64'},'notes':'No\x20share_object\x20in\x20module;\x20owned\x20by\x20creator.\x20Carrier\x20for\x20WTS\x20evidence\x20anchors.','source':{'file':'proof.move','line':0xd,'pattern':'public\x20struct\x20Proof\x20has\x20key'}},'Discount':{'module':'service','ownership':'owned','references':{'service':'Service<T>'},'valueFields':{'name':'String','discount_type':'u8\x20//\x200=rates\x201=minus','benchmark':'Option<u64>','off':'u64','time_start':'u64','time_end':'u64','transferable':'bool'},'notes':'Transferred\x20to\x20buyer.\x20Burned\x20unconditionally\x20at\x20buy\x20even\x20when\x20benchmark\x20unmet\x20(A-4).','source':{'file':'service.move','line':0x81,'pattern':'public\x20struct\x20Discount\x20has\x20key'},'findings':['A-4']},'Passport':{'module':'passport','ownership':'owned','references':{'guard[].guard':'Guard','guard[].relies':'address[]','impack':'address[]'},'valueFields':{'result':'bool','tx_hash':'vector<u8>','time':'u64','signer':'address','has_verified':'bool'},'notes':'No\x20share_object\x20in\x20module;\x20carried\x20by\x20signer,\x20mutated\x20across\x20guard\x20checks.','source':{'file':'passport.move','line':0x28,'pattern':'public\x20struct\x20Passport\x20has\x20key'}},'EntityOrders':{'module':'entity_order','ownership':'singleton','references':{},'valueFields':{'table':'ParentTable<address,\x20vector<OrderRoleItem>>'},'notes':'Reverse\x20index\x20entity->orders.\x20FIFO\x20eviction\x20at\x205200\x20entries\x20(entity_order.move:72-78)\x20—\x20silent.','source':{'file':'entity_order.move','line':0x1e,'pattern':'public\x20struct\x20EntityOrders\x20has\x20key'},'findings':['A-13']},'EntityPermission':{'module':'entity_permission','ownership':'singleton','references':{},'valueFields':{'table':'ParentTable<address,\x20vector<PermissionItem>>'},'source':{'file':'entity_permission.move','line':0x1e,'pattern':'public\x20struct\x20EntityPermission\x20has\x20key'}},'EntityContact':{'module':'entity_contact','ownership':'singleton','references':{},'valueFields':{'table':'ParentTable<address,\x20vector<ContactItem>>'},'source':{'file':'entity_contact.move','line':0x18,'pattern':'public\x20struct\x20EntityContact\x20has\x20key'}},'ObjectLinkerCore':{'module':'object_linker','ownership':'singleton','references':{},'valueFields':{'table':'ParentTable<address,\x20vector<CoreLink>>\x20//\x20target\x20->\x20core\x20who[],\x20lossless'},'source':{'file':'object_linker.move','line':0x25,'pattern':'public\x20struct\x20ObjectLinkerCore\x20has\x20key'}},'ObjectLinkerTx':{'module':'object_linker','ownership':'singleton','references':{},'valueFields':{'table':'ParentTable<address,\x20TxBuffer>\x20//\x20target\x20->\x20recent\x20tx\x20who[],\x20lossy\x20FIFO'},'source':{'file':'object_linker.move','line':0x2b,'pattern':'public\x20struct\x20ObjectLinkerTx\x20has\x20key'}},'Registrar':{'module':'registrar','ownership':'singleton','references':{},'valueFields':{'table':'ParentTable<address,\x20Votes>\x20//\x20who\x20->\x20likes/dislikes/favors'},'source':{'file':'registrar.move','line':0xb4,'pattern':'public\x20struct\x20Registrar\x20has\x20key'}},'Entity':{'module':'registrar','ownership':'singleton','references':{},'valueFields':{'table':'ParentTable<address,\x20AddressInfo>'},'source':{'file':'registrar.move','line':0xb9,'pattern':'public\x20struct\x20Entity\x20has\x20key'}},'Messenger':{'module':'registrar','ownership':'singleton','references':{},'valueFields':{'table':'ParentTable<String,\x20PubKeyData>'},'notes':'DEAD:\x20struct\x20declared\x20but\x20share_object\x20commented\x20out\x20(registrar.move:209-212).\x20No\x20on-chain\x20Messenger\x20(A-16).','source':{'file':'registrar.move','line':0x278,'pattern':'public\x20struct\x20Messenger\x20has\x20key'},'findings':['A-16']},'Resource':{'module':'resource','ownership':'shared','references':{},'valueFields':{'table':'ParentTable<address,\x20AddressTag>'},'source':{'file':'resource.move','line':0x11,'pattern':'public\x20struct\x20Resource\x20has\x20key'}}};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Facts, type RuleBookFinding } from "../config/rule-engine.js";
|
|
2
|
+
import { type Plan, type PlanIssue } from "./plan.js";
|
|
3
|
+
export declare function planFacts(plan: Plan): Facts;
|
|
4
|
+
export interface PlanAuditResult {
|
|
5
|
+
issues: PlanIssue[];
|
|
6
|
+
findings: RuleBookFinding[];
|
|
7
|
+
facts: Facts;
|
|
8
|
+
blocking: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function auditPlan(plan: Plan): PlanAuditResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getJudgmentDoc}from'../config/judgment.js';import{evaluateRuleBook}from'../config/rule-engine.js';import{isPathDependentTimeQuery}from'../chain-semantics/index.js';import{createsOf,isRef,refsOf,validatePlan}from'./plan.js';function collectQueries(a,b=[]){if(Array['isArray'](a)){for(const c of a)collectQueries(c,b);}else{if(typeof a==='object'&&a!==null){const d=a;d['type']==='query'&&typeof d['query']==='string'&&b['push']({'query':d['query']});for(const e of Object['values'](d))collectQueries(e,b);}}return b;}function acceptedProgressNodes(a,b){const c=new Map();if(Array['isArray'](b))for(const g of b){if(typeof g==='object'&&g!==null){const h=g;typeof h['identifier']==='number'&&typeof h['value']==='string'&&c['set'](h['identifier'],h['value']);}}const d=i=>{if(typeof i!=='object'||i===null)return undefined;const j=i;if(j['type']==='constant'&&typeof j['value']==='string')return j['value'];if(j['type']==='identifier'&&typeof j['identifier']==='number')return c['get'](j['identifier']);return undefined;},e=[],f=i=>{if(Array['isArray'](i)){for(const l of i)f(l);return;}if(typeof i!=='object'||i===null)return;const j=i,k=j['left'];if(typeof j['type']==='string'&&j['type']['startsWith']('logic')&&k!==undefined&&k['type']==='query'&&k['query']==='progress.current'){const m=d(j['right']);if(m!==undefined)e['push'](m);}for(const n of Object['values'](j))f(n);};return f(a),e;}function guardProjection(a){const b=a['params']['root']??a['params']['logic'],c=collectQueries(b)['map'](d=>d['query']);return{'stepId':a['id'],'queries':c,'acceptedNodes':acceptedProgressNodes(b,a['params']['table'])};}function allocatorRows(a){const b=[],c=d=>{if(typeof d==='object'&&d!==null&&!Array['isArray'](d)){const e=d;if(Array['isArray'](e['allocators']))d=e['allocators'];}if(!Array['isArray'](d))return;for(const f of d){if(typeof f!=='object'||f===null)continue;const g=f,h=g['guard'],i=g['guard_key'];b['push']({'track':typeof g['track']==='string'?g['track']:'settlement','guardStep':isRef(h)?h['$ref']:undefined,'guardKey':typeof i==='string'?i:undefined});}};for(const d of a['steps']){if(d['op']==='create'&&d['object']==='service')c(d['params']['order_allocators']);if(d['op']==='configure'&&d['method']==='order_allocators')c(d['params']['allocators']);}return b;}function machineProjection(a){const b=createsOf(a,'machine')[0x0];if(b===undefined)return undefined;const c=b['params']['nodes'];if(!Array['isArray'](c))return{'nodes':[],'edges':[],'terminals':[]};const d=[],e=[];for(const h of c){if(typeof h!=='object'||h===null)continue;const i=h,j=typeof i['name']==='string'?i['name']:undefined;if(j===undefined)continue;d['push'](j);const k=Array['isArray'](i['pairs'])?i['pairs']:[];for(const l of k){const m=l?.['prev_node'];if(typeof m==='string')e['push']({'prev':m,'next':j});}}const f=b['params']['pairs'];if(Array['isArray'](f))for(const n of f){const o=n;typeof o?.['prev_node']==='string'&&typeof o?.['next_node']==='string'&&e['push']({'prev':o['prev_node'],'next':o['next_node']});}const g=new Set(e['map'](q=>q['prev'])['filter'](q=>q!==''));return{'nodes':d,'edges':e,'terminals':d['filter'](q=>!g['has'](q))};}function pathCountCap2(a,b){const c=new Map();for(const g of a){const h=c['get'](g['prev'])??[];h['push'](g['next']),c['set'](g['prev'],h);}let d=0x0;const f=(i,j)=>{if(d>=0x2)return;if(i===b){d+=0x1;return;}if(j['has'](i))return;const k=new Set(j)['add'](i);for(const l of c['get'](i)??[])f(l,k);};for(const i of c['get']('')??[])f(i,new Set());return d;}const WRITE_ONLY_ENFORCEMENT_SOURCES=[{'object':'service','param':'customer_required','coverQuery':'order.required_info','extract':a=>Array['isArray'](a['params']['customer_required'])&&a['params']['customer_required']['length']>0x0},{'object':'service','param':'sales[].wip','coverQuery':'service.sale.wip','extract':a=>Array['isArray'](a['params']['sales'])&&a['params']['sales']['some'](b=>typeof b==='object'&&b!==null&&typeof b['wip']==='string'&&b['wip']['length']>0x0)}];export function planFacts(a){const b=new Map(createsOf(a,'guard')['map'](z=>[z['id'],guardProjection(z)])),c=allocatorRows(a),d=machineProjection(a),e=createsOf(a,'service')['length']>0x0,f=createsOf(a,'repository')['length']>0x0,h=new Set();for(const z of c){const A=z['guardStep']===undefined?undefined:b['get'](z['guardStep']);for(const B of A?.['acceptedNodes']??[])h['add'](B);}const i=d?.['terminals']??[],j=i['find'](C=>!h['has'](C)),k=a['pending_guards']??[],l=k['filter'](C=>C['site']==='allocator')['length'],m=k['find'](C=>C['site']==='allocator'||C['site']==='machine_edge')?.['key'],o=k['find'](C=>C['site']==='service_buy')?.['key'],p=c['filter'](C=>C['track']==='refund'),q=p['map'](C=>C['guardStep']===undefined?undefined:b['get'](C['guardStep']))['find'](C=>C!==undefined&&!C['queries']['some'](D=>D['startsWith']('order.claimed_by')))?.['stepId'];let s,t=![];for(const C of b['values']()){if(C['queries']['some'](isPathDependentTimeQuery)){s??=C['stepId'];if(d!==undefined)for(const D of C['acceptedNodes']){if(pathCountCap2(d['edges'],D)>=0x2){t=!![],s=C['stepId'];break;}}}if(t)break;}const u=[...b['values']()]['flatMap'](E=>E['queries']);let v;for(const E of WRITE_ONLY_ENFORCEMENT_SOURCES){for(const F of createsOf(a,E['object'])){if(E['extract'](F)&&!u['some'](G=>G['startsWith'](E['coverQuery']))){v=E['param'];break;}}if(v!==undefined)break;}const w=new Set();for(const G of a['steps']){if(G['op']==='create'&&G['object']==='guard')continue;const H=refsOf(G['op']==='publish'?G['target']:G['params']);for(const I of H)w['add'](I);if(G['op']==='configure'){for(const J of refsOf(G['target']))w['add'](J);}}const x=[...b['keys']()]['find'](K=>!w['has'](K)),y=[...b['values']()]['find'](K=>!f&&K['queries']['some'](L=>L['startsWith']('repository.')))?.['stepId'];return{'has_service':e,'has_machine':d!==undefined,'has_repository':f,'allocator_row_count':c['length'],'refund_row_count':p['length'],'terminal_count':i['length'],'terminal_nodes_display':i['join'](',\x20'),'pending_allocator_guard_count':l,...j===undefined?{}:{'first_uncovered_terminal':j},...q===undefined?{}:{'first_refund_guard_missing_claimed_by':q},...s===undefined?{}:{'first_path_dependent_anchor':s},'path_sensitive':t,...v===undefined?{}:{'first_write_only_unenforced_field':v},...x===undefined?{}:{'first_orphan_guard':x},...y===undefined?{}:{'first_repo_query_without_repository':y},...m===undefined?{}:{'first_pending_fund_guard':m},...o===undefined?{}:{'first_pending_buy_guard':o}};}function planRuleBook(){const a=getJudgmentDoc()['rules']['domains']['plan'];if(!a)throw new Error('factory\x20rule\x20pack\x20\x27plan\x27\x20missing\x20—\x20broken\x20installation');return a['rules'];}export function auditPlan(a){const b=validatePlan(a),c=planFacts(a),{findings:d}=evaluateRuleBook(planRuleBook(),c),e=b['length']>0x0||d['some'](g=>g['level']==='critical'||g['level']==='high');return{'issues':b,'findings':d,'facts':c,'blocking':e};}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IndustryTemplate } from "../knowledge/template-loader.js";
|
|
2
|
+
import type { JsonValue, Plan } from "./plan.js";
|
|
3
|
+
export type CompilableTemplate = Pick<IndustryTemplate, "id" | "machine_shape" | "guards" | "allocator" | "fee_params" | "arbitration_mode">;
|
|
4
|
+
export interface GuardSpec {
|
|
5
|
+
key: string;
|
|
6
|
+
template_id: string;
|
|
7
|
+
host: "service" | "machine" | "reward" | "repository" | "arbitration";
|
|
8
|
+
purpose: string;
|
|
9
|
+
step_id?: string;
|
|
10
|
+
}
|
|
11
|
+
export type GuardResolution = {
|
|
12
|
+
kind: "template";
|
|
13
|
+
template_id: string;
|
|
14
|
+
params?: Record<string, unknown>;
|
|
15
|
+
} | {
|
|
16
|
+
kind: "inline";
|
|
17
|
+
description?: string;
|
|
18
|
+
table: unknown[];
|
|
19
|
+
root: unknown;
|
|
20
|
+
};
|
|
21
|
+
export type CompileBlockerCode = "MACHINE_EDGES_MISSING" | "EDGE_UNKNOWN_PREV" | "GUARD_CYCLE" | "GUARD_KEY_UNKNOWN" | "GUARD_TEMPLATE_PARAMS" | "ALLOCATOR_VALUE_MISSING" | "ALLOCATOR_FIX_UNSUPPORTED";
|
|
22
|
+
export interface CompileBlocker {
|
|
23
|
+
code: CompileBlockerCode;
|
|
24
|
+
detail: string;
|
|
25
|
+
}
|
|
26
|
+
export interface CompileOptions {
|
|
27
|
+
nameBase?: string;
|
|
28
|
+
intent?: string;
|
|
29
|
+
merchantPermissionIndex?: number;
|
|
30
|
+
guardResolutions?: Record<string, GuardResolution>;
|
|
31
|
+
}
|
|
32
|
+
export interface CompileResult {
|
|
33
|
+
plan: Plan;
|
|
34
|
+
guardSpecs: GuardSpec[];
|
|
35
|
+
unresolved: GuardSpec[];
|
|
36
|
+
blockers: CompileBlocker[];
|
|
37
|
+
}
|
|
38
|
+
export declare function compileTemplate(template: CompilableTemplate, inputs: Record<string, JsonValue>, options?: CompileOptions): CompileResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{fillGuardTemplate}from'../knowledge/guard-templates.js';import{refsOf}from'./plan.js';const P=a=>a;function safeId(a){return a['replace'](/[^a-zA-Z0-9_]/g,'_');}function ref(a){return{'$ref':a};}const MODE_MAP={'amount':'Amount','rate':'Rate','surplus':'Surplus'};export function compileTemplate(a,b,c={}){const d=c['nameBase']??a['id']['replace'](/\//g,'_'),e=c['merchantPermissionIndex']??0x3e8,f=[],h=[],i=a['guards']['map']((C,D)=>({'key':C['key']??C['template_id']+'#'+D,'template_id':C['template_id'],'host':C['host'],'purpose':C['purpose']})),j=new Map(i['map'](C=>[C['key'],C])),k=new Map(),l=[];for(const C of i){const D='guard_'+safeId(C['key']),E=c['guardResolutions']?.[C['key']];let F=C['purpose'],G,H;if(E?.['kind']==='inline')G=E['table'],H=E['root'],F=E['description']??C['purpose'];else{const I=E?.['kind']==='template'?E['template_id']:C['template_id']['startsWith']('tpl_')?C['template_id']:undefined;if(I!==undefined){const J={...a['fee_params'],...b,...E?.['kind']==='template'?E['params']:{}},K=fillGuardTemplate(I,J);!K['ok']?f['push']({'code':'GUARD_TEMPLATE_PARAMS','detail':'guard\x20\x27'+C['key']+'\x27\x20('+I+'):\x20'+K['error']}):(G=K['table'],H=K['root']);}}G!==undefined?(k['set'](C['key'],{'stepId':D,'description':F,'table':G,'root':H}),C['step_id']=D):l['push'](C);}const m=L=>k['get'](L)!==undefined&&refsOf({'table':k['get'](L)['table'],'root':k['get'](L)['root']})['has']('service'),n=L=>{const M=k['get'](L);return{'op':'create','id':M['stepId'],'object':'guard','params':P({'description':M['description'],'table':M['table'],'root':M['root']}),'notes':j['get'](L)?.['purpose']};};h['push']({'op':'create','id':'permission','object':'permission','params':{'name':d+'_permission'}});const o=a['arbitration_mode']!==undefined&&a['arbitration_mode']!=='none';o&&h['push']({'op':'create','id':'permission_arb','object':'permission','params':{'name':d+'_arb_permission'},'notes':'MUST\x20be\x20created\x20by\x20a\x20different\x20account\x20than\x20the\x20service\x20permission\x20'+'(E_ARBITRATION_PERMISSION_CONFLICT=33):\x20dispute\x20neutrality.'});h['push']({'op':'create','id':'contact','object':'contact','params':{'name':d+'_contact'},'notes':'R8:\x20customer-service\x20channel;\x20mandatory\x20when\x20customer_required\x20is\x20set.'});const p=i['some'](L=>L['host']==='repository'||L['template_id']==='pattern.repository_data_check'||L['template_id']==='pattern.repository_write_authorization');if(p){const L=b['repository_policies'];h['push']({'op':'create','id':'repository','object':'repository','params':{'name':d+'_evidence',...Array['isArray'](L)?{'policies':L}:{}},'notes':'Evidence\x20rows\x20(tracking\x20hash,\x20receipts,\x20WTS\x20proofs).'});}const q=[];for(const [M]of k){m(M)?q['push'](M):h['push'](n(M));}const r=new Set(a['machine_shape']['map'](N=>N['name'])),s=[];for(const N of a['machine_shape']){if(N['from']===undefined||N['from']['length']===0x0){f['push']({'code':'MACHINE_EDGES_MISSING','detail':'machine_shape\x20node\x20\x27'+N['name']+'\x27\x20declares\x20no\x20\x27from\x27\x20edges.\x20Edges\x20are\x20data\x20'+'(REPORT\x20#10\x20A-2:\x20a\x20missing\x20paid->closed_cancel\x20edge\x20bricks\x20the\x20shop\x20at\x20publish).\x20'+'Annotate\x20the\x20node\x20with\x20from:\x20[...]\x20(use\x20prev:\x20\x22\x22\x20for\x20the\x20entry\x20edge).'});continue;}const O=[],Q=new Map();for(const R of N['from']){const S=typeof R==='string'?{'prev':R}:R;if(S['prev']!==''&&!r['has'](S['prev'])){f['push']({'code':'EDGE_UNKNOWN_PREV','detail':'node\x20\x27'+N['name']+'\x27\x20edge\x20prev\x20\x27'+S['prev']+'\x27\x20is\x20not\x20a\x20machine_shape\x20node'});continue;}const T=S['operator']??N['operator']??(S['prev']===''?'order_payer':'merchant'),U={'name':S['forward']??(S['prev']===''?'enter_'+N['name']:S['prev']+'_to_'+N['name']),'weight':0x1,...T==='order_payer'?{'namedOperator':''}:{'permissionIndex':S['permission_index']??e}};if(S['guard_key']!==undefined){const W=j['get'](S['guard_key']);if(W===undefined)f['push']({'code':'GUARD_KEY_UNKNOWN','detail':'edge\x20\x27'+S['prev']+'\x27->\x27'+N['name']+'\x27\x20binds\x20unknown\x20guard_key\x20\x27'+S['guard_key']+'\x27'});else W['step_id']!==undefined&&(m(W['key'])?f['push']({'code':'GUARD_CYCLE','detail':'edge\x20\x27'+S['prev']+'\x27->\x27'+N['name']+'\x27\x20binds\x20guard\x20\x27'+W['key']+'\x27\x20which\x20itself\x20'+'refs\x20the\x20service\x20(created\x20after\x20the\x20machine)\x20—\x20an\x20F-05\x20cycle.\x20Rebind\x20or\x20split\x20the\x20guard.'}):U['guard']=ref(W['step_id']));}const V=Q['get'](S['prev']);V!==undefined?V['push'](U):Q['set'](S['prev'],[U]);}for(const [X,Y]of Q){O['push']({'prev_node':X,'threshold':0x0,'forwards':Y});}s['push']({'name':N['name'],...N['semantic_role']!==undefined?{'role':N['semantic_role']}:{},'pairs':O});}h['push']({'op':'create','id':'machine','object':'machine','params':P({'name':d+'_machine','nodes':s})}),h['push']({'op':'publish','id':'machine_publish','target':ref('machine'),'preflight':[{'check':'machine_publish','status':'pending'}]});const t=typeof b['currency']==='string'?b['currency']:'0x2::wow::WOW',u=i['find'](Z=>Z['host']==='service'&&Z['key']==='buy');h['push']({'op':'create','id':'service','object':'service','params':P({'name':d+'_service','type_parameter':t,'permission':ref('permission'),'machine':ref('machine'),'um':ref('contact'),'description':a['id']+'\x20—\x20compiled\x20by\x20composition/compile',...p?{'repositories':[ref('repository')]}:{},...u?.['step_id']!==undefined?{'buy_guard':ref(u['step_id'])}:{},...Array['isArray'](b['customer_required'])?{'customer_required':b['customer_required']}:{}}),'notes':'Draft\x20only:\x20machine/order_allocators\x20are\x20L1-frozen\x20at\x20publish;\x20allocators\x20attach\x20in\x20the\x20configure\x20step.'});for(const Z of q)h['push'](n(Z));const v=a['allocator']['rows']!==undefined&&a['allocator']['rows']['length']>0x0?a['allocator']['rows']:[{'track':'settlement','recipient':a['allocator']['recipient']==='fixed'?'entity':a['allocator']['recipient'],'recipient_key':a['allocator']['recipient_key'],'mode':a['allocator']['mode'],'value':a['allocator']['mode']==='rate'?0x2710:a['allocator']['mode']==='surplus'?'0':undefined}],w=[],x=new Map();for(const a0 of v){if(a0['guard_key']!==undefined){let a1=x['get'](a0['guard_key']);a1===undefined&&(a1={'key':a0['guard_key'],'rows':[]},x['set'](a0['guard_key'],a1),w['push'](a1)),a1['rows']['push'](a0);}else w['push']({'rows':[a0]});}const y=[];for(const a2 of w){const a3=[];let a4;for(const a6 of a2['rows']){let a7=a6['value'];a7===undefined&&a6['value_from']!==undefined&&(a7=b[a6['value_from']]??a['fee_params'][a6['value_from']]);if(a7===undefined&&a6['mode']!=='surplus'){f['push']({'code':'ALLOCATOR_VALUE_MISSING','detail':'allocator\x20row\x20('+a6['track']+'/'+a6['recipient']+')\x20has\x20neither\x20value\x20nor\x20a\x20resolvable\x20value_from'});continue;}(a6['fix']!==undefined||a6['fix_from']!==undefined)&&f['push']({'code':'ALLOCATOR_FIX_UNSUPPORTED','detail':'allocator\x20row\x20('+a6['track']+'/'+a6['recipient']+')\x20declares\x20fix/fix_from\x20—\x20the\x20chain\x20has\x20no\x20holdback\x20'+'parameter:\x20fix\x20is\x20computed\x20on-chain\x20as\x20the\x20sum\x20of\x20the\x20Amount\x20legs\x20and\x20those\x20legs\x20are\x20PAID\x20'+'(allocation.move:399,540),\x20and\x20the\x20allocator-registration\x20call\x20surface\x20(guard,\x20sharing,\x20max)\x20has\x20no\x20fix\x20'+'argument,\x20so\x20this\x20value\x20never\x20reaches\x20the\x20chain.\x20To\x20keep\x20funds\x20in\x20the\x20pool,\x20do\x20not\x20distribute\x20them\x20'+'(a\x20separate\x20Allocation\x20object,\x20or\x20a\x20later\x20guard-gated\x20allocator);\x20to\x20combine\x20fixed\x20fees\x20with\x20a\x20'+'proportional\x20split,\x20use\x20explicit\x20Amount\x20legs\x20plus\x20Rate\x20legs\x20summing\x2010000.'});a4??=a6['note'];const a8=a6['recipient']==='entity'?{'Entity':{'$late':{'by':'local_name','mark':a6['recipient_key']??'merchant'}}}:a6['recipient']==='guard_identifier'?{'GuardIdentifier':Number(a6['recipient_key']??0x0)}:'Signer';a3['push']({'who':a8,'sharing':String(a7??'0'),'mode':MODE_MAP[a6['mode']]});}if(a3['length']===0x0)continue;const a5=a2['key']!==undefined?j['get'](a2['key'])?.['step_id']:undefined;a2['key']!==undefined&&!j['has'](a2['key'])&&f['push']({'code':'GUARD_KEY_UNKNOWN','detail':'allocator\x20row\x20('+a2['rows'][0x0]['track']+')\x20binds\x20unknown\x20guard_key\x20\x27'+a2['key']+'\x27'}),y['push']({...a5!==undefined?{'guard':ref(a5)}:{},...a2['key']!==undefined?{'guard_key':a2['key']}:{},'track':a2['rows'][0x0]['track'],'sharing':a3,...a4!==undefined?{'note':a4}:{}});}h['push']({'op':'configure','id':'service_allocators','target':ref('service'),'method':'order_allocators','params':P({'description':a['allocator']['description'],'threshold':0x0,'allocators':y}),'requires':['machine_publish']});Array['isArray'](b['sales'])&&b['sales']['length']>0x0&&h['push']({'op':'configure','id':'service_sales','target':ref('service'),'method':'sales','params':{'op':'add','sales':b['sales']}});if(o){h['push']({'op':'create','id':'arbitration','object':'arbitration','params':P({'name':d+'_arbitration','permission':ref('permission_arb'),'type_parameter':t}),'notes':'Independent\x20venue\x20(R2).\x20New\x20arbitrations\x20default\x20bPaused=true\x20—\x20unpause\x20is\x20a\x20separate\x20operator\x20step.'}),h['push']({'op':'configure','id':'service_arbitrations','target':ref('service'),'method':'arbitrations','params':P({'op':'add','objects':[ref('arbitration')]})});const a9=b['compensation_fund'];(typeof a9==='string'||typeof a9==='number')&&h['push']({'op':'configure','id':'service_compensation','target':ref('service'),'method':'compensation_fund_add','params':{'balance':String(a9)}});}h['push']({'op':'publish','id':'service_publish','target':ref('service'),'preflight':[{'check':'service_publish','status':'pending'},{'check':'FUND-EXIT-01','status':'pending'},{'check':'PLAN-ALLOC-01','status':'pending'}]});const z=new Set((a['allocator']['rows']??[])['map'](aa=>aa['guard_key'])['filter'](aa=>typeof aa==='string')),A=new Set(a['machine_shape']['flatMap'](aa=>(aa['from']??[])['map'](ab=>typeof ab==='string'?undefined:ab['guard_key'])['filter'](ab=>typeof ab==='string'))),B=l['flatMap'](aa=>{const ab=z['has'](aa['key'])?'allocator':A['has'](aa['key'])?'machine_edge':aa['host']==='service'&&aa['key']==='buy'?'service_buy':undefined;return ab?[{'key':aa['key'],'template_id':aa['template_id'],'host':aa['host'],'site':ab,'purpose':aa['purpose']}]:[];});return{'plan':{'version':0x1,'intent':c['intent']??'compile\x20'+a['id'],'templateId':a['id'],'inputs':b,'steps':h,...B['length']>0x0?{'pending_guards':B}:{}},'guardSpecs':i,'unresolved':l,'blockers':f};}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type CreateStep, type LateQuery, type Plan } from "./plan.js";
|
|
2
|
+
import { type PlanAuditResult } from "./audit.js";
|
|
3
|
+
export interface ExecOutcome {
|
|
4
|
+
outcome: "executed" | "failed" | "pending_input";
|
|
5
|
+
digest?: string;
|
|
6
|
+
created: {
|
|
7
|
+
object?: string;
|
|
8
|
+
type_raw?: string;
|
|
9
|
+
}[];
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
export type Executor = (operationType: string, data: Record<string, unknown>, env?: unknown) => Promise<ExecOutcome>;
|
|
13
|
+
export type LateResolver = (q: LateQuery) => string;
|
|
14
|
+
export type ObjectReader = (address: string, kind: string, env?: unknown) => Promise<unknown>;
|
|
15
|
+
export interface MaterializeIO {
|
|
16
|
+
execute: Executor;
|
|
17
|
+
resolveLate?: LateResolver;
|
|
18
|
+
read?: ObjectReader;
|
|
19
|
+
env?: unknown;
|
|
20
|
+
}
|
|
21
|
+
export declare function handlerExecutor(env?: unknown): Executor;
|
|
22
|
+
export declare function adaptCreateData(step: CreateStep, resolved: Record<string, unknown>): Record<string, unknown>;
|
|
23
|
+
export declare function preflightPlan(plan: Plan): {
|
|
24
|
+
plan: Plan;
|
|
25
|
+
audit: PlanAuditResult;
|
|
26
|
+
};
|
|
27
|
+
export type StepStatus = "executed" | "failed" | "blocked";
|
|
28
|
+
export interface StepResult {
|
|
29
|
+
stepId: string;
|
|
30
|
+
status: StepStatus;
|
|
31
|
+
digest?: string;
|
|
32
|
+
address?: string;
|
|
33
|
+
error?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface MaterializeResult {
|
|
36
|
+
steps: StepResult[];
|
|
37
|
+
outputs: Record<string, string>;
|
|
38
|
+
completed: boolean;
|
|
39
|
+
preflight: PlanAuditResult;
|
|
40
|
+
readback: ReadbackReport;
|
|
41
|
+
}
|
|
42
|
+
export declare function materializePlan(plan: Plan, io: MaterializeIO): Promise<MaterializeResult>;
|
|
43
|
+
export interface ReadbackCheck {
|
|
44
|
+
name: string;
|
|
45
|
+
ok: boolean;
|
|
46
|
+
detail?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface ReadbackReport {
|
|
49
|
+
ok: boolean;
|
|
50
|
+
checks: ReadbackCheck[];
|
|
51
|
+
}
|
|
52
|
+
interface SharingRow {
|
|
53
|
+
mode?: string;
|
|
54
|
+
sharing?: string | number;
|
|
55
|
+
}
|
|
56
|
+
interface AllocatorRowLike {
|
|
57
|
+
track?: string;
|
|
58
|
+
guard?: unknown;
|
|
59
|
+
sharing?: SharingRow[];
|
|
60
|
+
}
|
|
61
|
+
export declare function planAllocatorRows(plan: Plan): AllocatorRowLike[];
|
|
62
|
+
export declare function conservationCheck(plan: Plan): ReadbackCheck[];
|
|
63
|
+
export declare function verifyMaterialization(plan: Plan, outputs: ReadonlyMap<string, string>, io: Pick<MaterializeIO, "read" | "env">): Promise<ReadbackReport>;
|
|
64
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CREATABLE_OBJECTS,createsOf,isRef,resolveValue}from'./plan.js';import{auditPlan}from'./audit.js';export function handlerExecutor(a){return async(b,c)=>{const {handleOnchainOperations:d}=await import('../tools/handlers/onchain.js'),e=await d({'operation_type':b,'data':c,'env':a}),f=e['structuredContent'],g=f?.['result'];return{'outcome':f?.['outcome']==='executed'?'executed':f?.['outcome']==='pending_input'?'pending_input':'failed','digest':g?.['digest'],'created':Array['isArray'](g?.['created'])?g['created']:[],'error':g?.['error']};};}export function adaptCreateData(a,b){const {name:c,permission:d,type_parameter:e,nodes:f,...g}=b;switch(a['object']){case'service':case'arbitration':return{'object':{'name':c,'type_parameter':e,'permission':d},...g};case'machine':return{'object':{'name':c,...d!==undefined?{'permission':d}:{}},...g['description']!==undefined?{'description':g['description']}:{},'node':{'op':'add','nodes':f,'bReplace':!![]}};case'guard':return b;case'permission':case'contact':case'repository':default:return{'object':{'name':c,...d!==undefined?{'permission':d}:{}},...g};}}export function preflightPlan(a){const b=auditPlan(a),c=new Set(b['findings']['map'](g=>g['rule_id'])),d=b['issues']['length']===0x0&&!b['findings']['some'](g=>g['level']==='critical'),e=a['steps']['map'](f=>{if(f['op']!=='publish')return f;const g=f['preflight']['map'](h=>{const i=h['check']['endsWith']('_publish')?d:!c['has'](h['check']);return{...h,'status':i?'pass':'fail'};});return{...f,'preflight':g};});return{'plan':{...a,'steps':e},'audit':b};}function stripGenerics(a){return a['replace'](/<.*>$/,'');}function matchCreated(a,b){const c=stripGenerics(b);return a['created']['find'](d=>{if(typeof d['type_raw']!=='string'||typeof d['object']!=='string')return![];return stripGenerics(d['type_raw'])['endsWith']('::'+c);})?.['object'];}const DEFAULT_LATE=a=>{if(a['by']==='address')return a['address'];throw new Error('unresolved\x20late\x20binding\x20(no\x20resolver\x20injected):\x20local_name\x20\x27'+a['mark']+'\x27');};export async function materializePlan(a,b){const {plan:c,audit:d}=preflightPlan(a),f=new Map(),g=[],h=b['resolveLate']??DEFAULT_LATE,i=new Map(c['steps']['filter'](m=>m['op']==='create')['map'](m=>[m['id'],m['object']])),j=m=>resolveValue(m,f,h);let k=![];for(const m of c['steps']){if(k){g['push']({'stepId':m['id'],'status':'blocked','error':'halted\x20by\x20earlier\x20failure/blocked\x20publish'});continue;}try{if(m['op']==='publish'){const q=m['preflight']['filter'](t=>t['status']==='fail');if(q['length']>0x0){g['push']({'stepId':m['id'],'status':'blocked','error':'preflight\x20failed:\x20'+q['map'](t=>t['check'])['join'](',\x20')+'\x20(refusing\x20to\x20publish\x20—\x20A-2)'});continue;}const r=j(m['target']),s=await b['execute'](i['get'](m['target']['$ref'])??'',{'object':r,'publish':!![]},b['env']);if(s['outcome']!=='executed'){g['push']({'stepId':m['id'],'status':'failed','error':s['error']??s['outcome']}),k=!![];continue;}g['push']({'stepId':m['id'],'status':'executed','digest':s['digest'],'address':r});continue;}const n=Object['fromEntries'](Object['entries'](m['params'])['map'](([t,u])=>[t,j(u)]));if(m['op']==='create'){const t=adaptCreateData(m,n),u=await b['execute'](m['object'],t,b['env']);if(u['outcome']!=='executed'){g['push']({'stepId':m['id'],'status':'failed','error':u['error']??u['outcome']}),k=!![];continue;}const v=matchCreated(u,CREATABLE_OBJECTS[m['object']]);if(v===undefined){g['push']({'stepId':m['id'],'status':'failed','error':'created\x20'+m['object']+'\x20not\x20found\x20in\x20transaction\x20result'}),k=!![];continue;}f['set'](m['id'],v),g['push']({'stepId':m['id'],'status':'executed','digest':u['digest'],'address':v});continue;}const o=j(m['target']),p=await b['execute'](i['get'](isRef(m['target'])?m['target']['$ref']:'')??'',{'object':o,[m['method']]:n},b['env']);if(p['outcome']!=='executed'){g['push']({'stepId':m['id'],'status':'failed','error':p['error']??p['outcome']}),k=!![];continue;}g['push']({'stepId':m['id'],'status':'executed','digest':p['digest'],'address':o});}catch(w){g['push']({'stepId':m['id'],'status':'failed','error':w instanceof Error?w['message']:String(w)}),k=!![];}}const l=await verifyMaterialization(c,f,b);return{'steps':g,'outputs':Object['fromEntries'](f),'completed':g['every'](x=>x['status']==='executed'),'preflight':d,'readback':l};}export function planAllocatorRows(a){const b=[],c=d=>{if(typeof d==='object'&&d!==null&&!Array['isArray'](d)){const e=d;if(Array['isArray'](e['allocators']))d=e['allocators'];}if(!Array['isArray'](d))return;for(const f of d){if(typeof f==='object'&&f!==null)b['push'](f);}};for(const d of a['steps']){if(d['op']==='create'&&d['object']==='service')c(d['params']['order_allocators']);if(d['op']==='configure'&&d['method']==='order_allocators')c(d['params']['allocators']);}return b;}export function conservationCheck(a){const b=planAllocatorRows(a);if(b['length']===0x0)return[{'name':'allocator_conservation','ok':![],'detail':'no\x20allocator\x20rows\x20(PLAN-ALLOC-01)'}];const c=new Map();for(const e of b){const f=e['track']??'settlement';c['set'](f,[...c['get'](f)??[],e]);}const d=[];for(const [g,h]of c){const i=h['flatMap'](l=>(l['sharing']??[])['map'](m=>m['mode']));if(i['some'](l=>l==='Amount')){d['push']({'name':'conservation:'+g,'ok':!![],'detail':'contains\x20Amount-mode\x20row(s)\x20—\x20fixed\x20payouts\x20are\x20not\x20statically\x20verifiable\x20against\x20the\x20escrow\x20total'});continue;}let j=0x0;for(const l of h){for(const m of l['sharing']??[]){if(m['mode']==='Rate'||m['mode']==='RateGross')j+=Number(m['sharing']??0x0);}}const k=i['some'](n=>n==='Surplus');if(j>0x2710)d['push']({'name':'conservation:'+g,'ok':![],'detail':'rate\x20sum\x20'+j+'\x20>\x2010000\x20—\x20track\x20pays\x20out\x20MORE\x20than\x20it\x20holds'});else j<0x2710&&!k?d['push']({'name':'conservation:'+g,'ok':![],'detail':'rate\x20sum\x20'+j+'\x20<\x2010000\x20and\x20no\x20Surplus\x20row\x20—\x20the\x20remainder\x20has\x20no\x20fund\x20exit'}):d['push']({'name':'conservation:'+g,'ok':!![],'detail':k?'rate\x20sum\x20'+j+'\x20+\x20Surplus\x20row\x20absorbs\x20the\x20remainder':'rate\x20sum\x20'+j+'\x20==\x2010000'});}return d;}export async function verifyMaterialization(a,b,c){const d=[...conservationCheck(a)];if(c['read']!==undefined)for(const f of createsOf(a,'service')){const g=b['get'](f['id']);if(g===undefined)continue;try{const h=await c['read'](g,'service',c['env']);if(h===undefined||h===null){d['push']({'name':'readback:'+f['id'],'ok':![],'detail':'service\x20'+g+'\x20not\x20readable\x20after\x20creation'});continue;}const i=planAllocatorRows(a)['length'],j=h['order_allocators']?.['allocators']?.['length']??(Array['isArray'](h['order_allocators'])?h['order_allocators']['length']:undefined);j!==undefined&&d['push']({'name':'readback:'+f['id']+':allocators','ok':j>=i,'detail':'on-chain\x20allocator\x20rows\x20'+j+'\x20vs\x20plan\x20'+i});}catch(k){d['push']({'name':'readback:'+f['id'],'ok':![],'detail':k instanceof Error?k['message']:String(k)});}}return{'ok':d['every'](l=>l['ok']),'checks':d};}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
2
|
+
[k: string]: JsonValue;
|
|
3
|
+
};
|
|
4
|
+
export type StepId = string;
|
|
5
|
+
export interface RefExpr {
|
|
6
|
+
$ref: StepId;
|
|
7
|
+
path?: string;
|
|
8
|
+
}
|
|
9
|
+
export type LateQuery = {
|
|
10
|
+
by: "local_name";
|
|
11
|
+
mark: string;
|
|
12
|
+
} | {
|
|
13
|
+
by: "address";
|
|
14
|
+
address: string;
|
|
15
|
+
};
|
|
16
|
+
export interface LateExpr {
|
|
17
|
+
$late: LateQuery;
|
|
18
|
+
}
|
|
19
|
+
export type ResolvedValue = JsonValue | RefExpr | LateExpr;
|
|
20
|
+
export type ResolvedParams = Record<string, ResolvedValue>;
|
|
21
|
+
export declare function isRef(v: ResolvedValue): v is RefExpr;
|
|
22
|
+
export declare function isLate(v: ResolvedValue): v is LateExpr;
|
|
23
|
+
export declare const CREATABLE_OBJECTS: {
|
|
24
|
+
readonly permission: "Permission";
|
|
25
|
+
readonly guard: "Guard";
|
|
26
|
+
readonly repository: "Repository";
|
|
27
|
+
readonly machine: "Machine";
|
|
28
|
+
readonly service: "Service<T>";
|
|
29
|
+
readonly arbitration: "Arbitration<T>";
|
|
30
|
+
readonly treasury: "Treasury<T>";
|
|
31
|
+
readonly reward: "Reward<T>";
|
|
32
|
+
readonly demand: "Demand";
|
|
33
|
+
readonly contact: "Contact";
|
|
34
|
+
readonly proof: "Proof";
|
|
35
|
+
readonly resource: "Resource";
|
|
36
|
+
};
|
|
37
|
+
export type CreatableKind = keyof typeof CREATABLE_OBJECTS;
|
|
38
|
+
export declare const PUBLISHABLE_KINDS: readonly ["service", "machine"];
|
|
39
|
+
export type PublishableKind = (typeof PUBLISHABLE_KINDS)[number];
|
|
40
|
+
interface StepBase {
|
|
41
|
+
id: StepId;
|
|
42
|
+
notes?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface CreateStep extends StepBase {
|
|
45
|
+
op: "create";
|
|
46
|
+
object: CreatableKind;
|
|
47
|
+
params: ResolvedParams;
|
|
48
|
+
}
|
|
49
|
+
export interface ConfigureStep extends StepBase {
|
|
50
|
+
op: "configure";
|
|
51
|
+
target: RefExpr | LateExpr;
|
|
52
|
+
method: string;
|
|
53
|
+
params: ResolvedParams;
|
|
54
|
+
requires?: StepId[];
|
|
55
|
+
}
|
|
56
|
+
export interface PreflightEntry {
|
|
57
|
+
check: string;
|
|
58
|
+
status: "pending" | "pass" | "fail";
|
|
59
|
+
detail?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface PublishStep extends StepBase {
|
|
62
|
+
op: "publish";
|
|
63
|
+
target: RefExpr;
|
|
64
|
+
preflight: PreflightEntry[];
|
|
65
|
+
}
|
|
66
|
+
export type PlanStep = CreateStep | ConfigureStep | PublishStep;
|
|
67
|
+
export interface PendingGuard {
|
|
68
|
+
key: string;
|
|
69
|
+
template_id: string;
|
|
70
|
+
host: string;
|
|
71
|
+
site: "allocator" | "machine_edge" | "service_buy";
|
|
72
|
+
purpose: string;
|
|
73
|
+
}
|
|
74
|
+
export interface Plan {
|
|
75
|
+
version: 1;
|
|
76
|
+
intent: string;
|
|
77
|
+
templateId?: string;
|
|
78
|
+
inputs: Record<string, JsonValue>;
|
|
79
|
+
steps: PlanStep[];
|
|
80
|
+
pending_guards?: PendingGuard[];
|
|
81
|
+
}
|
|
82
|
+
export declare function refsOf(value: unknown, out?: Set<StepId>): Set<StepId>;
|
|
83
|
+
export declare function stepById(plan: Plan, id: StepId): PlanStep | undefined;
|
|
84
|
+
export declare function createsOf(plan: Plan, kind: CreatableKind): CreateStep[];
|
|
85
|
+
export declare function resolveValue(value: ResolvedValue, outputs: ReadonlyMap<StepId, string>, resolveLate: (q: LateQuery) => string): JsonValue | string;
|
|
86
|
+
export interface PlanIssue {
|
|
87
|
+
code: "PLAN_DUP_STEP" | "PLAN_UNKNOWN_KIND" | "PLAN_REF_UNKNOWN" | "PLAN_REF_FORWARD" | "PLAN_PUBLISH_TARGET" | "PLAN_PROSE_GUARD" | "PLAN_MACHINE_NODES" | "PLAN_REQUIRES_UNKNOWN";
|
|
88
|
+
step?: StepId;
|
|
89
|
+
detail: string;
|
|
90
|
+
}
|
|
91
|
+
export declare function validatePlan(plan: Plan): PlanIssue[];
|
|
92
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{OBJECT_GRAPH}from'../chain-semantics/index.js';export function isRef(a){return typeof a==='object'&&a!==null&&!Array['isArray'](a)&&typeof a['$ref']==='string'&&Object['keys'](a)['every'](b=>b==='$ref'||b==='path');}export function isLate(a){return typeof a==='object'&&a!==null&&!Array['isArray'](a)&&typeof a['$late']==='object'&&a['$late']!==null&&Object['keys'](a)['every'](b=>b==='$late');}export const CREATABLE_OBJECTS={'permission':'Permission','guard':'Guard','repository':'Repository','machine':'Machine','service':'Service<T>','arbitration':'Arbitration<T>','treasury':'Treasury<T>','reward':'Reward<T>','demand':'Demand','contact':'Contact','proof':'Proof','resource':'Resource'};export const PUBLISHABLE_KINDS=['service','machine'];export function refsOf(a,b=new Set()){if(isRef(a))b['add'](a['$ref']);else{if(Array['isArray'](a)){for(const c of a)refsOf(c,b);}else{if(typeof a==='object'&&a!==null&&!isLate(a)){for(const d of Object['values'](a))refsOf(d,b);}}}return b;}export function stepById(a,b){return a['steps']['find'](c=>c['id']===b);}export function createsOf(a,b){return a['steps']['filter'](c=>c['op']==='create'&&c['object']===b);}export function resolveValue(a,b,c){if(isRef(a)){const d=b['get'](a['$ref']);if(d===undefined)throw new Error('unresolved\x20ref:\x20'+a['$ref']);return a['path']?''+d+a['path']:d;}if(isLate(a))return c(a['$late']);if(Array['isArray'](a))return a['map'](e=>resolveValue(e,b,c));if(typeof a==='object'&&a!==null)return Object['fromEntries'](Object['entries'](a)['map'](([e,f])=>[e,resolveValue(f,b,c)]));return a;}export function validatePlan(a){const b=[],c=new Set(a['steps']['map'](e=>e['id'])),d=new Map();return a['steps']['forEach']((e,f)=>{d['has'](e['id'])&&b['push']({'code':'PLAN_DUP_STEP','step':e['id'],'detail':'duplicate\x20step\x20id\x20at\x20index\x20'+f});d['set'](e['id'],f);if(e['op']==='create'){if(!(e['object']in CREATABLE_OBJECTS))b['push']({'code':'PLAN_UNKNOWN_KIND','step':e['id'],'detail':'unknown\x20object\x20kind:\x20'+e['object']});else!(CREATABLE_OBJECTS[e['object']]in OBJECT_GRAPH)&&b['push']({'code':'PLAN_UNKNOWN_KIND','step':e['id'],'detail':'kind\x20'+e['object']+'\x20not\x20in\x20chain\x20OBJECT_GRAPH'});if(e['object']==='guard'){const h=e['params']['table'];(!Array['isArray'](h)||h['length']===0x0)&&b['push']({'code':'PLAN_PROSE_GUARD','step':e['id'],'detail':'guard\x20requires\x20a\x20non-empty\x20structured\x20`table`\x20param\x20(no\x20prose\x20logic\x20slots)'});}if(e['object']==='machine'){const j=e['params']['nodes'];(!Array['isArray'](j)||j['length']===0x0)&&b['push']({'code':'PLAN_MACHINE_NODES','step':e['id'],'detail':'machine\x20requires\x20a\x20non-empty\x20`nodes`\x20param'});}}if(e['op']==='configure')for(const k of e['requires']??[]){(!d['has'](k)||d['get'](k)===f)&&b['push']({'code':'PLAN_REQUIRES_UNKNOWN','step':e['id'],'detail':'requires\x20unknown/prior-less\x20step:\x20'+k});}if(e['op']==='publish'){const l=d['get'](e['target']['$ref']),m=l===undefined?undefined:a['steps'][l];if(!c['has'](e['target']['$ref']))b['push']({'code':'PLAN_REF_UNKNOWN','step':e['id'],'detail':'publish\x20target\x20unknown:\x20'+e['target']['$ref']});else(m===undefined||m['op']!=='create'||!PUBLISHABLE_KINDS['includes'](m['object']))&&b['push']({'code':'PLAN_PUBLISH_TARGET','step':e['id'],'detail':'publish\x20target\x20must\x20be\x20a\x20created\x20service|machine,\x20got:\x20'+(m?.['op']==='create'?m['object']:m?.['op'])});}const g=e['op']==='create'||e['op']==='configure'?refsOf(e['params']):new Set();if(e['op']==='configure'&&isRef(e['target']))g['add'](e['target']['$ref']);if(e['op']==='publish')g['add'](e['target']['$ref']);for(const n of g){const o=d['get'](n);if(!c['has'](n))b['push']({'code':'PLAN_REF_UNKNOWN','step':e['id'],'detail':'ref\x20to\x20unknown\x20step:\x20'+n});else(o===undefined||o>=f)&&b['push']({'code':'PLAN_REF_FORWARD','step':e['id'],'detail':'ref\x20to\x20non-prior\x20step:\x20'+n});}}),b;}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Severity } from "../config/severity.js";
|
|
2
|
+
import { type PlanAuditResult } from "./audit.js";
|
|
3
|
+
import { type Plan } from "./plan.js";
|
|
4
|
+
export declare const SEVERITY_WEIGHT: Readonly<Record<Severity, number>>;
|
|
5
|
+
export declare function auditScore(audit: PlanAuditResult): number;
|
|
6
|
+
export interface PlanPatch {
|
|
7
|
+
rule_id: string;
|
|
8
|
+
kind: string;
|
|
9
|
+
stepId: string;
|
|
10
|
+
detail: string;
|
|
11
|
+
}
|
|
12
|
+
export interface RefluxBlock {
|
|
13
|
+
rule_id: string;
|
|
14
|
+
level: Severity;
|
|
15
|
+
title: string;
|
|
16
|
+
detail: string;
|
|
17
|
+
}
|
|
18
|
+
export interface RefluxOptions {
|
|
19
|
+
maxIterations?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface RefluxResult {
|
|
22
|
+
plan: Plan;
|
|
23
|
+
applied: PlanPatch[];
|
|
24
|
+
blocks: RefluxBlock[];
|
|
25
|
+
iterations: number;
|
|
26
|
+
audit: PlanAuditResult;
|
|
27
|
+
}
|
|
28
|
+
export declare function reflux(plan: Plan, options?: RefluxOptions): RefluxResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{auditPlan}from'./audit.js';import{createsOf,stepById}from'./plan.js';export const SEVERITY_WEIGHT={'critical':0x64,'high':0x19,'medium':0x5,'low':0x1,'info':0x0};export function auditScore(a){let b=a['issues']['length']*SEVERITY_WEIGHT['critical'];for(const c of a['findings'])b+=SEVERITY_WEIGHT[c['level']];return b;}function uniqueStepId(a,b){if(stepById(a,b)===undefined)return b;for(let c=0x1;;c++){const d=b+'-reflux-'+c;if(stepById(a,d)===undefined)return d;}}const patchMissingRepository=a=>{const b=a['audit']['facts']['first_repo_query_without_repository'];if(typeof b!=='string')return undefined;if(createsOf(a['plan'],'repository')['length']>0x0)return undefined;const c=createsOf(a['plan'],'permission')[0x0];if(c===undefined)return undefined;const d=uniqueStepId(a['plan'],'repository'),e={'op':'create','id':d,'object':'repository','params':{'name':b+'_evidence','permission':{'$ref':c['id']},'description':'auto-inserted:\x20guard\x20'+b+'\x20queries\x20repository\x20data\x20(HOST-GRAPH-01)'},'notes':'reflux:\x20HOST-GRAPH-01\x20mechanical\x20patch'},f=a['plan']['steps']['findIndex'](h=>h['id']===c['id']),g=[...a['plan']['steps']['slice'](0x0,f+0x1),e,...a['plan']['steps']['slice'](f+0x1)];return{'plan':{...a['plan'],'steps':g},'patch':{'rule_id':'HOST-GRAPH-01','kind':'insert_repository','stepId':d,'detail':'guard\x20'+b+'\x20queries\x20repository\x20data;\x20inserted\x20repository\x20create\x20step\x20bound\x20to\x20'+c['id']}};},PATCH_REGISTRY=[patchMissingRepository];function toBlocks(a){const b=[];for(const c of a['issues']){b['push']({'rule_id':c['code'],'level':'critical','title':'structural\x20issue\x20in\x20step\x20'+(c['step']??'?'),'detail':c['detail']});}for(const d of a['findings']){b['push']({'rule_id':d['rule_id'],'level':d['level'],'title':d['title'],'detail':d['mitigation']??d['description']});}return b;}export function reflux(a,b={}){const c=b['maxIterations']??0x8,d=[];let e=a,f=auditPlan(e),g=0x0;while(g<c){const h=new Set(d['map'](j=>j['rule_id']+':'+j['kind']));let i;for(const j of PATCH_REGISTRY){const k=j({'plan':e,'audit':f});if(k!==undefined&&!h['has'](k['patch']['rule_id']+':'+k['patch']['kind'])){i=k;break;}}if(i===undefined)break;e=i['plan'],d['push'](i['patch']),f=auditPlan(e),g+=0x1;}return{'plan':e,'applied':d,'blocks':toBlocks(f),'iterations':g,'audit':f};}
|