@wowok/agent-mcp 3.4.0 → 3.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/chain-semantics/composition-truth.d.ts +102 -0
- package/dist/chain-semantics/composition-truth.js +1 -0
- package/dist/chain-semantics/eval-order.js +1 -1
- package/dist/chain-semantics/fund-flow.js +1 -1
- package/dist/chain-semantics/index.d.ts +1 -0
- package/dist/chain-semantics/index.js +1 -1
- package/dist/composition/audit.js +1 -1
- package/dist/composition/blueprint-view.d.ts +3 -3
- package/dist/composition/blueprint-view.js +1 -1
- package/dist/composition/compile.d.ts +24 -3
- package/dist/composition/compile.js +1 -1
- package/dist/composition/emit-phases.d.ts +206 -0
- package/dist/composition/emit-phases.js +1 -0
- package/dist/composition/generate.d.ts +40 -0
- package/dist/composition/generate.js +1 -0
- package/dist/composition/guard-fill.d.ts +44 -0
- package/dist/composition/guard-fill.js +1 -0
- package/dist/composition/inflight.d.ts +20 -2
- package/dist/composition/inflight.js +1 -1
- package/dist/composition/input-normalize.d.ts +15 -0
- package/dist/composition/input-normalize.js +1 -0
- package/dist/composition/materialize.d.ts +18 -13
- package/dist/composition/materialize.js +1 -1
- package/dist/composition/mode-gates.d.ts +35 -0
- package/dist/composition/mode-gates.js +1 -0
- package/dist/composition/param-disclosure.js +1 -1
- package/dist/composition/plan-retry-ledger.d.ts +21 -0
- package/dist/composition/plan-retry-ledger.js +1 -0
- package/dist/composition/plan.d.ts +7 -2
- package/dist/composition/plan.js +1 -1
- package/dist/composition/product-card.d.ts +94 -0
- package/dist/composition/product-card.js +1 -0
- package/dist/composition/supply-chain-emit.d.ts +46 -0
- package/dist/composition/supply-chain-emit.js +1 -0
- package/dist/config/config-audit.spec.js +1 -1
- package/dist/config/config-warnings.d.ts +2 -0
- package/dist/config/config-warnings.js +1 -0
- package/dist/config/exposure.d.ts +2 -2
- package/dist/config/judgment.d.ts +31 -5
- package/dist/config/judgment.js +1 -1
- package/dist/config/judgment.spec.js +1 -1
- package/dist/config/match-policy-file.d.ts +34 -0
- package/dist/config/match-policy-file.js +1 -0
- package/dist/config/match-policy-file.spec.d.ts +1 -0
- package/dist/config/match-policy-file.spec.js +1 -0
- package/dist/config/rule-engine.d.ts +5 -5
- package/dist/config/rule-engine.js +1 -1
- package/dist/config/runtime.d.ts +0 -1
- package/dist/config/runtime.js +1 -1
- package/dist/config/severity.d.ts +0 -2
- package/dist/config/severity.js +1 -1
- package/dist/config/store-policy.spec.js +1 -1
- package/dist/config/template-params.d.ts +42 -0
- package/dist/config/template-params.js +1 -0
- package/dist/config/template-params.spec.d.ts +1 -0
- package/dist/config/template-params.spec.js +1 -0
- package/dist/data/api/api.spec.js +1 -1
- package/dist/data/api/server.js +1 -1
- package/dist/data/projection/store.d.ts +2 -1
- package/dist/data/projection/store.js +1 -1
- package/dist/data/projection/types.d.ts +22 -0
- package/dist/data/sync/cdc.d.ts +1 -2
- package/dist/data/sync/cdc.js +1 -1
- package/dist/evaluation/acceptance.d.ts +8 -0
- package/dist/evaluation/acceptance.js +1 -1
- package/dist/evaluation/builtins/demand-match.js +1 -1
- package/dist/evaluation/builtins/graph-service.spec.js +1 -1
- package/dist/evaluation/capability.d.ts +2 -0
- package/dist/evaluation/category-match-rules.d.ts +0 -1
- package/dist/evaluation/category-match-rules.js +1 -1
- package/dist/evaluation/composer.d.ts +25 -0
- package/dist/evaluation/composer.js +1 -1
- package/dist/evaluation/engine.js +1 -1
- package/dist/evaluation/extract.d.ts +7 -0
- package/dist/evaluation/extract.js +1 -1
- package/dist/evaluation/game-strategy.d.ts +0 -3
- package/dist/evaluation/game-strategy.js +1 -1
- package/dist/evaluation/match-operation.d.ts +9 -0
- package/dist/evaluation/match-operation.js +1 -1
- package/dist/evaluation/match-policy-resolver.d.ts +9 -0
- package/dist/evaluation/match-policy-resolver.js +1 -0
- package/dist/evaluation/match-policy.d.ts +3 -1
- package/dist/evaluation/match-policy.js +1 -1
- package/dist/evaluation/region.d.ts +0 -6
- package/dist/evaluation/region.js +1 -1
- package/dist/evaluation/standards.d.ts +2 -1
- package/dist/evaluation/standards.js +1 -1
- package/dist/evaluation/structured-lines.d.ts +8 -0
- package/dist/evaluation/structured-lines.js +1 -0
- package/dist/evaluation/types.d.ts +6 -0
- package/dist/experience/realtime-feedback.js +1 -1
- package/dist/extensions/capability-manifest.d.ts +1 -0
- package/dist/extensions/capability-manifest.js +1 -1
- package/dist/extensions/capability.d.ts +91 -0
- package/dist/extensions/capability.js +1 -0
- package/dist/extensions/industry-audit.spec.js +1 -1
- package/dist/extensions/industry-pack.d.ts +13 -0
- package/dist/extensions/industry-pack.js +1 -1
- package/dist/extensions/modes.js +1 -1
- package/dist/extensions/registry.d.ts +0 -2
- package/dist/extensions/registry.js +1 -1
- package/dist/goal/GoalEngine.js +1 -1
- package/dist/graph/onchain/analyze.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/graph/onchain/order-status.d.ts +0 -1
- package/dist/graph/onchain/order-status.js +1 -1
- package/dist/harness/recover.js +1 -1
- package/dist/harness/verify.d.ts +0 -3
- package/dist/harness/verify.js +1 -1
- package/dist/intent/types.d.ts +0 -1
- package/dist/intent/types.js +1 -1
- package/dist/keeper/detectors.js +1 -1
- package/dist/keeper/types.d.ts +0 -1
- package/dist/keeper/types.js +1 -1
- package/dist/knowledge/allocation-risk.d.ts +1 -0
- package/dist/knowledge/allocation-risk.js +1 -1
- package/dist/knowledge/allocator-rail-verifier.d.ts +6 -1
- package/dist/knowledge/allocator-rail-verifier.js +1 -1
- package/dist/knowledge/arbitration-ledger.js +1 -1
- package/dist/knowledge/arbitration-puzzle.js +1 -1
- package/dist/knowledge/arbitration-templates.js +1 -1
- package/dist/knowledge/audit-rules.d.ts +4 -3
- package/dist/knowledge/audit-rules.js +1 -1
- package/dist/knowledge/baselines/judgment-baselines.json +21 -2
- package/dist/knowledge/baselines/rules/oracle.json +120 -0
- package/dist/knowledge/baselines/rules/plan.json +384 -17
- package/dist/knowledge/baselines/rules/progress.json +20 -2
- package/dist/knowledge/builtin-templates.d.ts +28 -1
- package/dist/knowledge/builtin-templates.js +1 -1
- package/dist/knowledge/component-schema.js +1 -1
- package/dist/knowledge/contact-templates.d.ts +0 -1
- package/dist/knowledge/contact-templates.js +1 -1
- package/dist/knowledge/dynamic-pricing.js +1 -1
- package/dist/knowledge/fee-param-bindings.js +1 -1
- package/dist/knowledge/fund-layer.d.ts +1 -0
- package/dist/knowledge/fund-layer.js +1 -1
- package/dist/knowledge/game-scenarios.js +1 -1
- package/dist/knowledge/getting-started.js +1 -1
- package/dist/knowledge/guard-binding-table.d.ts +52 -0
- package/dist/knowledge/guard-binding-table.js +1 -0
- package/dist/knowledge/guard-binding-verifier.d.ts +30 -0
- package/dist/knowledge/guard-binding-verifier.js +1 -0
- package/dist/knowledge/guard-bindings.js +1 -1
- package/dist/knowledge/guard-blueprint.d.ts +68 -0
- package/dist/knowledge/guard-blueprint.js +1 -0
- 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-host-context.d.ts +24 -0
- package/dist/knowledge/guard-host-context.js +1 -0
- package/dist/knowledge/guard-lint.js +1 -1
- package/dist/knowledge/guard-node-gates.d.ts +3 -0
- package/dist/knowledge/guard-node-gates.js +1 -1
- package/dist/knowledge/guard-puzzle.js +1 -1
- package/dist/knowledge/guard-render.js +1 -1
- package/dist/knowledge/guard-risk.js +1 -1
- package/dist/knowledge/guard-submission-prompt.d.ts +11 -0
- package/dist/knowledge/guard-submission-prompt.js +1 -1
- package/dist/knowledge/guard-templates.d.ts +1 -1
- package/dist/knowledge/guard-templates.js +1 -1
- package/dist/knowledge/guard-translation.js +1 -1
- package/dist/knowledge/index.d.ts +1 -1
- package/dist/knowledge/index.js +1 -1
- package/dist/knowledge/industry-generalizer.d.ts +6 -1
- package/dist/knowledge/industry-generalizer.js +1 -1
- package/dist/knowledge/industry-registry.js +1 -1
- package/dist/knowledge/jsonrpc-enum.d.ts +38 -0
- package/dist/knowledge/jsonrpc-enum.js +1 -1
- package/dist/knowledge/machine-topology.js +1 -1
- package/dist/knowledge/machine-translation.js +1 -1
- package/dist/knowledge/object-dependency.d.ts +31 -0
- package/dist/knowledge/object-dependency.js +1 -0
- package/dist/knowledge/onchain-constants.d.ts +2 -0
- package/dist/knowledge/onchain-constants.js +1 -1
- package/dist/knowledge/param-schema.d.ts +23 -0
- package/dist/knowledge/param-schema.js +1 -1
- package/dist/knowledge/param-tiers.js +1 -1
- package/dist/knowledge/passport-ledger.js +1 -1
- package/dist/knowledge/path-oracle/coverage.d.ts +16 -0
- package/dist/knowledge/path-oracle/coverage.js +1 -0
- package/dist/knowledge/path-oracle/index.d.ts +5 -0
- package/dist/knowledge/path-oracle/index.js +1 -0
- package/dist/knowledge/path-oracle/products/food-delivery.d.ts +2 -0
- package/dist/knowledge/path-oracle/products/food-delivery.js +1 -0
- package/dist/knowledge/path-oracle/schema.d.ts +188 -0
- package/dist/knowledge/path-oracle/schema.js +1 -0
- package/dist/knowledge/pattern-resolutions.d.ts +2 -0
- package/dist/knowledge/pattern-resolutions.js +1 -1
- package/dist/knowledge/progress-ledger.js +1 -1
- package/dist/knowledge/progress-risk.js +1 -1
- package/dist/knowledge/projection.spec.js +1 -1
- package/dist/knowledge/protocol-facts.js +1 -1
- package/dist/knowledge/requirement-families.d.ts +13 -0
- package/dist/knowledge/requirement-families.js +1 -0
- package/dist/knowledge/reward-ledger.js +1 -1
- package/dist/knowledge/scenario-modes.d.ts +1 -0
- package/dist/knowledge/scenario-modes.js +1 -1
- package/dist/knowledge/semantic-ir.d.ts +4 -0
- package/dist/knowledge/semantic-ir.js +1 -1
- package/dist/knowledge/service-ledger.d.ts +1 -1
- package/dist/knowledge/service-ledger.js +1 -1
- package/dist/knowledge/sku-name-gate.d.ts +17 -0
- package/dist/knowledge/sku-name-gate.js +1 -0
- package/dist/knowledge/supply-chain.d.ts +9 -0
- package/dist/knowledge/supply-chain.js +1 -1
- package/dist/knowledge/template-loader.d.ts +14 -6
- package/dist/knowledge/template-loader.js +1 -1
- package/dist/knowledge/template-nav.d.ts +3 -1
- package/dist/knowledge/template-nav.js +1 -1
- package/dist/knowledge/template-prose.d.ts +1 -1
- package/dist/knowledge/template-registry.js +1 -1
- package/dist/knowledge/template-scanner.d.ts +62 -0
- package/dist/knowledge/template-scanner.js +1 -1
- package/dist/knowledge/template-test-profiles.js +1 -1
- package/dist/knowledge/tools-reference.js +1 -1
- package/dist/knowledge/workflow-guidance.d.ts +5 -0
- package/dist/knowledge/workflow-guidance.js +1 -1
- package/dist/monitor/MonitorLoop.js +1 -1
- package/dist/participation/customer-interest.d.ts +4 -0
- package/dist/participation/customer-interest.js +1 -1
- package/dist/participation/node-action-advisor.d.ts +4 -0
- package/dist/participation/node-action-advisor.js +1 -1
- package/dist/participation/radar-core.js +1 -1
- package/dist/participation/time-window.d.ts +11 -0
- package/dist/participation/time-window.js +1 -1
- package/dist/persona/address-format.d.ts +0 -1
- package/dist/persona/address-format.js +1 -1
- package/dist/persona/bridge.js +1 -1
- package/dist/persona/index.d.ts +0 -2
- package/dist/persona/index.js +1 -1
- package/dist/persona/model.js +1 -1
- package/dist/persona/persona-audit.spec.js +1 -1
- package/dist/persona/types.d.ts +6 -0
- package/dist/playbooks/service-build/business-puzzle.js +1 -1
- package/dist/playbooks/service-build/game-theory.d.ts +2 -2
- package/dist/playbooks/service-build/intent-analyzer.js +1 -1
- package/dist/playbooks/service-build/machine-panorama.js +1 -1
- package/dist/playbooks/service-build/merchant-guide.d.ts +50 -23
- package/dist/playbooks/service-build/merchant-guide.js +1 -1
- package/dist/playbooks/service-build/migration-planner.d.ts +2 -0
- package/dist/playbooks/service-build/migration-planner.js +1 -1
- package/dist/playbooks/service-build/mode-actions.js +1 -1
- package/dist/playbooks/service-build/object-panorama.d.ts +8 -0
- 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/reverse-mapping.d.ts +6 -0
- package/dist/playbooks/service-build/reverse-mapping.js +1 -1
- package/dist/playbooks/service-build/service-panorama.d.ts +1 -0
- 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/playbooks/service-build/workflow-design-assessment.d.ts +10 -1
- package/dist/playbooks/service-build/workflow-design-assessment.js +1 -1
- package/dist/review/index.js +1 -1
- package/dist/review/repository.js +1 -1
- package/dist/safety/confirm-gate.js +1 -1
- package/dist/schema/benchmark-migration/index.d.ts +104 -0
- package/dist/schema/benchmark-migration/index.js +1 -1
- package/dist/schema/call/allocation.d.ts +15 -6
- package/dist/schema/call/allocation.js +1 -1
- package/dist/schema/call/base.d.ts +256 -0
- package/dist/schema/call/base.js +1 -1
- package/dist/schema/call/bridge.d.ts +32 -6
- package/dist/schema/call/demand.d.ts +15 -6
- package/dist/schema/call/demand.js +1 -1
- package/dist/schema/call/guard.d.ts +8 -8
- package/dist/schema/call/guard.js +1 -1
- package/dist/schema/call/handler.d.ts +3 -0
- package/dist/schema/call/handler.js +1 -1
- package/dist/schema/call/machine.d.ts +32 -8
- package/dist/schema/call/machine.js +1 -1
- package/dist/schema/call/order.d.ts +26 -8
- package/dist/schema/call/order.js +1 -1
- package/dist/schema/call/payment.d.ts +20 -8
- package/dist/schema/call/payment.js +1 -1
- package/dist/schema/call/permission-handler.js +1 -1
- package/dist/schema/call/permission.d.ts +330 -114
- package/dist/schema/call/permission.js +1 -1
- package/dist/schema/call/personal.d.ts +10 -4
- package/dist/schema/call/personal.js +1 -1
- package/dist/schema/call/progress.d.ts +16 -4
- package/dist/schema/call/proof.js +1 -1
- package/dist/schema/call/reward.d.ts +10 -4
- package/dist/schema/call/reward.js +1 -1
- package/dist/schema/call/semantic.d.ts +1 -0
- package/dist/schema/call/semantic.js +1 -1
- package/dist/schema/call/service.d.ts +143 -45
- package/dist/schema/call/service.js +1 -1
- package/dist/schema/call/treasury.d.ts +15 -6
- package/dist/schema/call/treasury.js +1 -1
- package/dist/schema/common/index.js +1 -1
- package/dist/schema/config/index.d.ts +61 -0
- package/dist/schema/config/index.js +1 -1
- package/dist/schema/envelope-unify.d.ts +4 -0
- package/dist/schema/envelope-unify.js +1 -0
- package/dist/schema/evaluation/index.d.ts +216 -19
- package/dist/schema/evaluation/index.js +1 -1
- package/dist/schema/goal/index.d.ts +47 -0
- package/dist/schema/goal/planning.d.ts +115 -1
- package/dist/schema/goal/planning.js +1 -1
- package/dist/schema/industry-pack/index.d.ts +137 -6
- package/dist/schema/industry-pack/index.js +1 -1
- package/dist/schema/industry-pack/modes.d.ts +6 -6
- package/dist/schema/keeper/index.d.ts +26 -0
- package/dist/schema/local/index.d.ts +137 -0
- package/dist/schema/local/index.js +1 -1
- package/dist/schema/local/wip.d.ts +6 -0
- package/dist/schema/local/wip.js +1 -1
- package/dist/schema/messenger/index.d.ts +26 -0
- package/dist/schema/operations.d.ts +345 -84
- package/dist/schema/operations.js +1 -1
- package/dist/schema/persona/index.d.ts +2907 -640
- package/dist/schema/persona/index.js +1 -1
- package/dist/schema/query/bi.d.ts +145 -4
- package/dist/schema/query/bi.js +1 -1
- package/dist/schema/query/index.d.ts +266 -73
- package/dist/schema/query/index.js +1 -1
- package/dist/schema/schema-query/index.d.ts +1 -1
- package/dist/schema/schema-query/index.js +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/watch/index.d.ts +16 -0
- package/dist/schema/watch/index.js +1 -1
- package/dist/schema/workflow/index.d.ts +2 -2
- package/dist/schema/workflow/index.js +1 -1
- package/dist/schema-query-impl/index.d.ts +1 -1
- package/dist/schema-query-impl/index.js +1 -1
- package/dist/schemas/account_operation.output.json +94 -0
- package/dist/schemas/benchmark_migration_operation.output.json +338 -9
- package/dist/schemas/benchmark_migration_operation.schema.json +27 -2
- package/dist/schemas/bridge_operation.output.json +94 -0
- package/dist/schemas/config_operation.output.json +352 -0
- package/dist/schemas/config_operation.schema.json +20 -2
- package/dist/schemas/evaluation_operation.output.json +570 -4
- package/dist/schemas/evaluation_operation.schema.json +194 -3
- package/dist/schemas/goal_operation.schema.json +183 -0
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/industry_pack_operation.output.json +621 -0
- package/dist/schemas/industry_pack_operation.schema.json +20 -2
- package/dist/schemas/keeper_operation.output.json +94 -0
- package/dist/schemas/local_cache_operation.output.json +94 -0
- package/dist/schemas/local_history_operation.output.json +94 -0
- package/dist/schemas/local_info_operation.output.json +94 -0
- package/dist/schemas/local_mark_operation.output.json +94 -0
- package/dist/schemas/messenger_operation.output.json +94 -0
- package/dist/schemas/monitor_events.output.json +94 -0
- package/dist/schemas/monitor_subscription.output.json +94 -0
- package/dist/schemas/onchain_events.output.json +94 -0
- package/dist/schemas/onchain_operations.output.json +313 -1
- package/dist/schemas/onchain_operations.schema.json +1265 -671
- package/dist/schemas/onchain_operations_allocation.schema.json +30 -15
- package/dist/schemas/onchain_operations_arbitration.schema.json +9 -2
- package/dist/schemas/onchain_operations_contact.schema.json +8 -1
- package/dist/schemas/onchain_operations_demand.schema.json +29 -14
- package/dist/schemas/onchain_operations_gen_passport.schema.json +8 -1
- package/dist/schemas/onchain_operations_guard.schema.json +290 -105
- package/dist/schemas/onchain_operations_machine.schema.json +49 -34
- package/dist/schemas/onchain_operations_order.schema.json +63 -40
- package/dist/schemas/onchain_operations_payment.schema.json +26 -11
- package/dist/schemas/onchain_operations_permission.schema.json +362 -235
- package/dist/schemas/onchain_operations_personal.schema.json +27 -15
- package/dist/schemas/onchain_operations_progress.schema.json +45 -30
- package/dist/schemas/onchain_operations_proof.schema.json +9 -2
- package/dist/schemas/onchain_operations_repository.schema.json +8 -1
- package/dist/schemas/onchain_operations_reward.schema.json +32 -17
- package/dist/schemas/onchain_operations_service.schema.json +232 -125
- package/dist/schemas/onchain_operations_treasury.schema.json +32 -17
- package/dist/schemas/onchain_table_data.output.json +258 -6
- package/dist/schemas/onchain_table_data.schema.json +92 -52
- package/dist/schemas/persona_operation.output.json +7752 -0
- package/dist/schemas/persona_operation.schema.json +1232 -4
- package/dist/schemas/query_toolkit.output.json +756 -116
- package/dist/schemas/query_toolkit.schema.json +138 -7
- package/dist/schemas/schema_query.schema.json +1 -1
- package/dist/schemas/watch_operation.output.json +83 -0
- package/dist/schemas/wip_file.output.json +8 -0
- package/dist/schemas/workflow_operation.schema.json +2 -2
- package/dist/tools/handlers/benchmark-migration.d.ts +20 -3
- package/dist/tools/handlers/benchmark-migration.js +1 -1
- package/dist/tools/handlers/config.js +1 -1
- package/dist/tools/handlers/evaluation.js +1 -1
- package/dist/tools/handlers/evaluation.spec.js +1 -1
- package/dist/tools/handlers/industry-pack.js +1 -1
- package/dist/tools/handlers/onchain.d.ts +30 -0
- package/dist/tools/handlers/onchain.js +1 -1
- package/dist/tools/handlers/persona.js +1 -1
- package/dist/tools/handlers/query.d.ts +8 -0
- package/dist/tools/handlers/query.js +1 -1
- package/dist/tools/handlers/winner-derivation.d.ts +20 -0
- package/dist/tools/handlers/winner-derivation.js +1 -0
- package/dist/tools/handlers/wip-upload.js +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.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/identity.js +1 -1
- package/dist/tools/registry/query.js +1 -1
- package/dist/tools/transport-integrity.d.ts +7 -0
- package/dist/tools/transport-integrity.js +1 -0
- package/dist/tools/upgrade-check.js +1 -1
- package/dist/tools/wrap.d.ts +5 -0
- package/dist/tools/wrap.js +1 -1
- package/package.json +2 -2
- package/dist/extensions/business-modules.d.ts +0 -54
- package/dist/extensions/business-modules.js +0 -1
- package/dist/schemas/guard-templates.json +0 -379
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"comment": "Plan-domain rules (L1 composition kernel). Facts are produced by composition/audit.ts planFacts() from a Plan AST. Each rule names a verified failure class (TRAILHAVEN wiki/test/10, booking-85981 + amz-7f3a2c91 audits, upwc-cat-261017 CAT-A1): zero allocator rows passing silently, an unsellable sales-less catalog, prose guard logic, dual-rail double-pay, path-dependent settlement windows, write-only enforcement, dropped guard/repository hosts, missing task-binding slot declarations and GuardIdentifier slot mismatches that strand escrow permanently.",
|
|
3
3
|
"facts": {
|
|
4
|
+
"composition_primitives_emitted": "Sorted comma-joined list of the composition primitives the plan actually emits (P1 repository rendezvous / P2 foreign-order slot / P3 sub-Service commitment or retained_submission / P4 more than one allocator row / P5 Formula sharing / P6 Reward pool) - chain-semantics/composition-truth.ts",
|
|
5
|
+
"composition_cross_order_guard_count": "Guard steps that read order.* on a slot other than host slot 0 (the P2 cross-order shape)",
|
|
6
|
+
"first_cross_order_guard": "First guard step id reading a foreign order slot",
|
|
7
|
+
"cross_order_slots_display": "Foreign order slot identifiers read by that guard",
|
|
8
|
+
"first_cross_order_guard_unpaired": "First cross-order guard with NO pairing key: neither a repository.data rendezvous leg nor a declared {identifier: 255, b_submission: true} once row (COMPOSE-PAIR-01)",
|
|
9
|
+
"cross_order_unpaired_count": "How many cross-order guards lack a pairing key",
|
|
10
|
+
"first_cross_order_guard_unpinned": "First cross-order guard that does not read order.service on the foreign slot against a constant Address row (COMPOSE-PROVIDER-PIN-01)",
|
|
11
|
+
"first_cross_order_guard_no_owner_cross": "First cross-order guard that does not read order.owner on BOTH the host slot and the foreign slot (COMPOSE-OWNER-CROSS-01). Not emitted on the merchant_procured axis, where the buyer never owns the sub order, so the equality cannot hold",
|
|
12
|
+
"cross_order_owner_tie_not_expressible": "A cross-order guard exists on the merchant_procured axis, where order.owner cannot tie the two orders (the merchant owns the sub order, the buyer owns the host order) - the expressible ties are the provider pin and a byte-keyed pairing slot",
|
|
13
|
+
"third_party_fulfilment_present": "The plan gates on a foreign order or declares a procuring fulfillment_axis, so a third party performs part of the service",
|
|
14
|
+
"third_party_payout_leg_present": "At least one payout path reachable by a third party exists: an Entity/Signer sharing leg or a Reward pool",
|
|
15
|
+
"third_party_leg_count": "Sharing legs whose recipient is Entity or Signer (the only legs not bound by payment_info.for_object)",
|
|
16
|
+
"reward_pool_present": "The plan creates a Reward object (P6, the only permissionless third-party payout channel)",
|
|
17
|
+
"third_party_fulfilment_without_payout": "A third party fulfils but no payout path was pre-set before publish (COMPOSE-LIABILITY-01, S4, RD-C4)",
|
|
18
|
+
"fulfillment_axis": "Fulfillment axis: self | internal_staff | merchant_procured | user_procured (replaces the conflated logistics_mode). Taken from the declared axis, else derived from the declared composition variant, which fixes its axis 1:1.",
|
|
19
|
+
"composition_variant": "Declared commercial variant V1 | V2 | V3 | V4",
|
|
20
|
+
"composition_variant_known": "The declared variant is one of V1-V4",
|
|
21
|
+
"composition_variant_missing_primitives": "Primitives the declared variant requires but the plan does not emit (COMPOSE-VARIANT-01)",
|
|
22
|
+
"composition_variant_missing_count": "How many required primitives are missing",
|
|
23
|
+
"composition_dual_refund_unblockable": "V3 declared: two escrow pools answer to the SAME buyer and the chain cannot block the second refund (COMPOSE-DUALREFUND-01, S2/S3, RD-C3)",
|
|
24
|
+
"composition_disclosure_count": "Number of disclosures the declared variant owes the buyer before purchase",
|
|
25
|
+
"first_pii_public_face": "First build-time public face (service/contact/proof/repository/demand description or location, sales copy, repository data constant) whose text matches a language-neutral PII shape (PRIV-PUBLICFACE-01, S5)",
|
|
26
|
+
"first_pii_public_face_step": "Step id writing that face",
|
|
27
|
+
"first_pii_kind": "PII shape matched: email | street_number | phone | national_id",
|
|
28
|
+
"first_raw_tracking_value_step": "Configure step writing a RAW carrier tracking number as a repository data value (PRIV-TRACKING-RAW-01)",
|
|
29
|
+
"first_raw_tracking_value": "The raw tracking value found",
|
|
30
|
+
"per_order_proof_binding_step": "Proof bound to the ORDER (or a required_info bind referencing a proof), which publicly associates the order with the contact record (PRIV-PROOF-PERORDER-01)",
|
|
4
31
|
"has_service": "Plan creates a service object",
|
|
5
32
|
"has_machine": "Plan creates a machine object",
|
|
6
33
|
"has_repository": "Plan creates a repository object",
|
|
@@ -9,6 +36,14 @@
|
|
|
9
36
|
"terminal_count": "Fund-bearing machine terminal nodes (never a non-entry prev_node); v32 optional pure-side-action leaves are exempt — order completion never routes through them and they never gate money (upw F-06, 6939_upwork-261016)",
|
|
10
37
|
"terminal_nodes_display": "Comma-joined fund-bearing terminal node names",
|
|
11
38
|
"first_uncovered_terminal": "First fund-bearing terminal node no allocator guard accepts — either by pinning the terminal directly (alloc runs as a standalone call on the resting order) or via a node-free allocator guard riding the entry forward (a dual-host settlement key: its edge leg evaluates BEFORE the node move, so a progress.current pin on it would be a NODE-MATCH-01 deadlock and only the node-free shape fires on both hosts) (FUND-EXIT-01; optional leaves exempt)",
|
|
39
|
+
"first_uncovered_final_node": "First final/cancelled semantic-role node no allocator guard accepts — a money sink by business meaning even when graph topology gives it an outgoing edge (W5-12, ks7 F-02/A-02: return_rejected exited topologically but stranded the escrow) (FUND-EXIT-02)",
|
|
40
|
+
"first_cancelled_review_bridge": "First review/reward-class advance (forward or target node name matches review|reward) mounted ON a cancelled-role terminal — the refund-then-claim arbitrage bridge: the order took the full refund AND can still reach the bounty (W5-03, pdd F-03 / ddmc4 B-26 D8: withdraw + full refund + 5★ bounty in one session) (STATE-REFUNDED-REWARD-01)",
|
|
41
|
+
"first_roster_null_perm_edge": "First money-edge forward declaring a NON-EMPTY namedOperator roster with NO permissionIndex — permissionNeeded reads false, the Permission assert is skipped entirely and the roster stays pure decoration (it authorizes members, never denies non-members), so ANYONE can push the fund/terminal forward (W5-14, ddmc4 B-24 verified progress.move:266-310: an outsider fired ReturnReceived/CompensateBadItem) (EDGE-ROSTER-NULL-PERM-01)",
|
|
42
|
+
"coarse_perm_bucket_index": "First permission index shared by >= 2 money edges of DIFFERENT rail classes (settle / recover|award / refund|return / arb) — one bucket grants one entity every heterogeneous fund action at once (W5-14, ddmc4 B-25: 9 heterogeneous fund edges on bucket 1002 let the arbiter execute the merchant's rails) (PERM-COARSE-BUCKET-01)",
|
|
43
|
+
"coarse_perm_bucket_classes": "Comma-joined rail classes sharing that bucket",
|
|
44
|
+
"first_pinned_away_exit_node": "First non-terminal machine node whose EVERY outgoing edge is guard-pinned to OTHER nodes — exhaust every exit guard and no edge can fire while the order rests here, so a never-ruling arb case strands the escrow at a mid-flow node (W5-02, ddmc4 B-29: dismissed fails closed on a None indemnity and withdraw/reset leave both ruling roots silent; NODE-MATCH-01 reports each dead edge, this is the node-level rollup; a node with NO edge at all is a terminal — its coverage stays FUND-EXIT-01/02, entry stranding stays ENTRY-ABANDON-01) (FUND-EXIT-COMPLETENESS-01)",
|
|
45
|
+
"direction_blind_pay_edge_count": "Fund-track pay rows (refund / settle / recover) whose guard carries NO beneficiary-anchoring leg: no progress node pin, no machine-edge binding, no dispute freeze leg (query 1576), and no order identity leg (order.owner / order.agent has / order.service)",
|
|
46
|
+
"first_direction_blind_pay_edge": "First such direction-blind pay row — the payee is fixed by the row shape alone, indifferent to order state and identity, so the residual principal sweeps merchant-ward even when the buyer WON the award (ktt4 RT-01) and an outsider can drive the rail (W5-01 b: h1w9 F-01/F-04/F-09, ddmc4 B-26/B-27, pdd F-01/F-05, tbpr7 F-V3-01/16, ks7 F-21) (FUND-DIRECTION-BLIND-01)",
|
|
12
47
|
"first_refund_guard_missing_claimed_by": "First refund-track guard step id whose queries never read order.claimed_by (DUAL-RAIL-01, A-3)",
|
|
13
48
|
"first_path_dependent_anchor": "First guard step id using a path-dependent time query (TIME-ANCHOR-01, E-10)",
|
|
14
49
|
"path_sensitive": "The anchored node is reachable by more than one path, so the anchor can shift",
|
|
@@ -60,6 +95,9 @@
|
|
|
60
95
|
"first_repo_gate_key_unbacked": "First unbacked gate key, rendered as 'key' in guard 'step-id'",
|
|
61
96
|
"repo_gate_key_unbacked_display": "Comma-joined list of ALL unbacked gate keys",
|
|
62
97
|
"sales_step_present": "The plan materializes at least one sellable SKU (a service create with a non-empty sales list, or a configure step with method 'sales') — the order entry's existence predicate (PLAN-SALES-01)",
|
|
98
|
+
"dead_sku_count": "Sales whose name exceeds the on-chain 64-byte BUY limit (the listing path accepts up to 256 bytes but the buy path caps buyer-sent item names at 64 and matches EXACTLY — a 65..256-byte name is publishable yet every order_new aborts E_NAME_LENGTH_EXCEEDED) — present only when at least one dead SKU is listed (SKU-NAME-64 advisory, F-RQ-01 / rqd3-tn-261030)",
|
|
99
|
+
"first_dead_sku_name": "First over-limit sale name",
|
|
100
|
+
"first_dead_sku_bytes": "That name's UTF-8 byte length",
|
|
63
101
|
"guard_reach_contradiction_count": "Root-AND-chain legs carrying proof-level structural unreachability (ordering interval crossing; == to two different numeric constants or to opposite Bools; == X conjoined with a strict ordering past X; same-binding self-comparison with a strict direction) — the guard predicate is unsatisfiable by construction (GUARD-REACH-01, S3 plane)",
|
|
64
102
|
"first_guard_reach_contradiction": "First contradiction, rendered as: guard 'step-id' (channel): OP X contradicts OP X — unsatisfiable",
|
|
65
103
|
"guard_reach_contradiction_display": "Semicolon-joined list of ALL proof-level unreachability contradictions in the plan's guard roots"
|
|
@@ -80,6 +118,21 @@
|
|
|
80
118
|
}
|
|
81
119
|
]
|
|
82
120
|
},
|
|
121
|
+
{
|
|
122
|
+
"rule_id": "SKU-NAME-64",
|
|
123
|
+
"dimension": "composition",
|
|
124
|
+
"trigger": "A plan lists a sale whose name exceeds the on-chain 64-byte BUY limit. Listing accepts up to 256 bytes (common::LONG_NAME, service.move:158) but the buy path caps buyer-sent item names at 64 (common::NAME_ALLOW_EMPTY, service.move:311) and resolves items by EXACT name (service.move:520-563) — a 65..256-byte name is publishable yet EVERY order_new aborts E_NAME_LENGTH_EXCEEDED before anything runs. Advisory only (protocol-train ruling: the 256-byte listing stays legal; renaming is impossible — a new name is a NEW SKU), so this fires info and never blocks publish (F-RQ-01, rqd3-tn-261030: 3 of 4 merchants published shops whose SKUs could never be bought).",
|
|
125
|
+
"cases": [
|
|
126
|
+
{
|
|
127
|
+
"when": { "all": [ { "field": "dead_sku_count", "op": "gt", "value": 0 } ] },
|
|
128
|
+
"level": "info",
|
|
129
|
+
"title": "SKU '${first_dead_sku_name}' (${first_dead_sku_bytes} bytes) can be listed but never bought",
|
|
130
|
+
"description": "${dead_sku_count} sale name(s) exceed the 64-byte buy limit while the listing path accepted them (first: '${first_dead_sku_name}' at ${first_dead_sku_bytes} bytes). The buy path re-quotes every basket line's name and aborts E_NAME_LENGTH_EXCEEDED, so this SKU is PERMANENTLY unbuyable — buyers see a catalog they can never order from.",
|
|
131
|
+
"mitigation": "Add a purchasable twin SKU whose name is within 64 bytes (UTF-8) BEFORE publish; renaming the dead SKU is not possible after listing (exact-name matching makes a new name a new SKU). Non-blocking advisory: the listing itself is protocol-legal.",
|
|
132
|
+
"stakeholders": ["merchant", "customer"]
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
},
|
|
83
136
|
{
|
|
84
137
|
"rule_id": "PLAN-ALLOC-01",
|
|
85
138
|
"dimension": "fund_flow",
|
|
@@ -118,6 +171,62 @@
|
|
|
118
171
|
}
|
|
119
172
|
]
|
|
120
173
|
},
|
|
174
|
+
{
|
|
175
|
+
"rule_id": "FUND-EXIT-02",
|
|
176
|
+
"dimension": "fund_flow",
|
|
177
|
+
"cases": [
|
|
178
|
+
{
|
|
179
|
+
"when": { "all": [ { "field": "first_uncovered_final_node", "op": "present" } ] },
|
|
180
|
+
"level": "critical",
|
|
181
|
+
"title": "Final/cancelled node '${first_uncovered_final_node}' has no allocator fund exit",
|
|
182
|
+
"description": "'${first_uncovered_final_node}' carries a final/cancelled semantic role — by business meaning the order's money journey STOPS here, even if a graph edge leaves the node. No allocator guard accepts it, so escrow reaching this state strands permanently (W5-12, ks7 F-02: return_rejected had a topological exit yet neither settle nor recover could move the funds). Graph-sink checks miss this shape; the semantic role does not.",
|
|
183
|
+
"mitigation": "Add an allocator row whose guard accepts '${first_uncovered_final_node}' (progress.current pin or node-free entry-forward shape), or give the node a genuine settlement/refund exit. For rejected terminals, keep a dispute or settle_after_grace rail.",
|
|
184
|
+
"stakeholders": ["merchant", "customer"]
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"rule_id": "STATE-REFUNDED-REWARD-01",
|
|
190
|
+
"dimension": "fund_flow",
|
|
191
|
+
"cases": [
|
|
192
|
+
{
|
|
193
|
+
"when": { "all": [ { "field": "first_cancelled_review_bridge", "op": "present" } ] },
|
|
194
|
+
"level": "critical",
|
|
195
|
+
"title": "Review/reward advance mounted on cancelled terminal '${first_cancelled_review_bridge}' — refund-then-claim arbitrage",
|
|
196
|
+
"description": "A review/reward-class advance departs a cancelled-role terminal (${first_cancelled_review_bridge}): the order can take the FULL refund and still walk to the bounty — 'refund + 5★ claim' double collection (W5-03, pdd F-03 T3/T7: full refund then review bounty; ddmc4 B-26 D8: withdraw + full refund + top-rating bounty in one session; tbpr7 F-V3-03: rebate window inside the return window). The claim guard's node set carries no cancelled node, so this bridge is the ONLY route a refunded order has back to the reward — and the machine shell happily mounts it because nothing forbade it until now.",
|
|
197
|
+
"mitigation": "Remove the review/reward-class edge from the cancelled terminal. Mutual exclusion is structural: the bounty's claim set carries final-role nodes ONLY and the claim window opens after the after-sales window closes (tbs7 F-04) — a cancelled order must stay outside that set. (A chain-level 'was ever refunded' boolean does not exist — protocol train.)",
|
|
198
|
+
"stakeholders": ["merchant", "customer"]
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"rule_id": "FUND-EXIT-COMPLETENESS-01",
|
|
204
|
+
"dimension": "fund_flow",
|
|
205
|
+
"cases": [
|
|
206
|
+
{
|
|
207
|
+
"when": { "all": [ { "field": "first_pinned_away_exit_node", "op": "present" } ] },
|
|
208
|
+
"level": "critical",
|
|
209
|
+
"title": "Every exit of '${first_pinned_away_exit_node}' is guard-pinned to other nodes — the order strands here",
|
|
210
|
+
"description": "While the order rests at '${first_pinned_away_exit_node}', none of its outgoing edges can fire: every edge guard pins progress.current to a DIFFERENT node (NODE-MATCH-01 already reports each such edge; this is the node-level rollup — exhaust every exit guard, find no live exit). The order and its escrow are unreachable-by-construction from here on (W5-02, ddmc4 B-29 D6: the never-ruling arb case — tpl_forward_arb_ruling_won needs a positive award and dismissed fails closed on a None indemnity, so withdraw/reset leave BOTH ruling roots silent and an arb waypoint gated only by rulings is this same deadlock expressed through guard pins; ETSY-T1 catalog deadEndLock is the catalog-level twin). Exit coverage is evaluated ONLY on fund-exit grounds (R2-01 lesson): node-level rollup, no whole-graph topology walk. A node with NO outgoing edge at all is a terminal — its coverage is FUND-EXIT-01/02's face, not this gate.",
|
|
211
|
+
"mitigation": "Re-pin the guards so at least one edge accepts the node the order actually rests on, or add an unpinned escape edge. For an arb waypoint the canonical shape is the buyer's void escape: { prev: <waypoint>, forward: 'WithdrawClaim', operator: 'order_payer', guard_key: 'withdraw_claim_<leg>' } with a pattern.identity_check_order_holder guard — no ruling means arb.claimed_by is none, the order stays put, and the FULL escrow returns through the untouched node-gated refund track (decision 11 two-rail independence). A ForceSettleExpired clock edge (buyer-directed) is the acceptable fallback; never gate the only live exit on a ruling that can fail closed. A live exit means: an edge whose guards are empty, or whose guard's acceptedNodes includes this node.",
|
|
212
|
+
"stakeholders": ["merchant", "customer"]
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"rule_id": "FUND-DIRECTION-BLIND-01",
|
|
218
|
+
"dimension": "fund_flow",
|
|
219
|
+
"cases": [
|
|
220
|
+
{
|
|
221
|
+
"when": { "all": [ { "field": "first_direction_blind_pay_edge", "op": "present" } ] },
|
|
222
|
+
"level": "critical",
|
|
223
|
+
"title": "Pay row '${first_direction_blind_pay_edge}' — the beneficiary is a constant, not a state function",
|
|
224
|
+
"description": "A fund-track pay row is bound to a guard that anchors NOTHING: no progress node pin, no machine-edge binding, no dispute freeze leg (query 1576 order.dispute.open), and no order identity leg (order.owner / order.agent has / order.service). The payee is fixed by the row shape alone, so the pay direction is blind to who won and where the order rests — the claimed_by direction-blind family (W5-01, five of five reports): the residual principal sweeps merchant-ward even when the buyer WON the award (ktt4 RT-01: 300M award from the compensation pool, then the 600M escrow principal swept to the merchant), and an outsider can drive the rail (h1w9: an unrelated address fired the merchant's recover three times and closed the case; ddmc4 D10: the buyer executed the merchant's sweep). Machine/Service/Allocation freeze at publish — a wrong pay direction is unfixable after publish.",
|
|
225
|
+
"mitigation": "Anchor the rail's guard to a beneficiary-tying leg: the terminal-node gate (progress.current in the rail's node set — decision 11 node-gated, NEVER order.claimed_by) plus the order.service binding (1563 == this service) and, on the identity face, order.owner (1562) / order.agent has (1567). The canonical recover rail is guard-catalog tpl_allocator_node_gate_recover: terminal-node-gated + order.service + dispute freeze (logic_not[1576]). If merchant-exit is the intended disposition, state it (the canonical 'merchant-side sweep' row note) so the scan records the conscious choice; a buyer-win principal return needs a separate buyer-ward row (recipient slot 0 — the Order address; owner.receive credits the buyer).",
|
|
226
|
+
"stakeholders": ["merchant", "customer"]
|
|
227
|
+
}
|
|
228
|
+
]
|
|
229
|
+
},
|
|
121
230
|
{
|
|
122
231
|
"rule_id": "FUND-ZERO-01",
|
|
123
232
|
"dimension": "fund_flow",
|
|
@@ -293,21 +402,6 @@
|
|
|
293
402
|
}
|
|
294
403
|
]
|
|
295
404
|
},
|
|
296
|
-
{
|
|
297
|
-
"rule_id": "DUAL-RAIL-01",
|
|
298
|
-
"dimension": "fund_flow",
|
|
299
|
-
"trigger": "Refund-track guard does not read order.claimed_by — the dual rail (A-3) is deliberate on chain: alloc never reads claimed_by, compensate never touches the escrow. Double-pay prevention is a TEMPLATE convention; this rule is its only enforcement.",
|
|
300
|
-
"cases": [
|
|
301
|
-
{
|
|
302
|
-
"when": { "field": "first_refund_guard_missing_claimed_by", "op": "present" },
|
|
303
|
-
"level": "high",
|
|
304
|
-
"title": "Refund guard '${first_refund_guard_missing_claimed_by}' does not check claimed_by",
|
|
305
|
-
"description": "Chain semantics keep the allocation rail and the compensation rail independent (A-3, deliberate). A refund guard that does not assert claimed_by is none allows double payment: arbitration indemnity AND escrow refund.",
|
|
306
|
-
"mitigation": "Add the order.claimed_by some == false query to the refund guard. This is a structural fund-safety invariant, not a documentation choice — a double-compensation policy note does not seal the rail and is NOT an accepted alternative. Pair the refund guard with the polarity-twin merchant-recovery allocator (guard asserts order.claimed_by some == true, pays Rate 10000 to the merchant Entity) so the escrow principal of an awarded order still exits: exactly one of the two legs can ever pass.",
|
|
307
|
-
"stakeholders": ["merchant"]
|
|
308
|
-
}
|
|
309
|
-
]
|
|
310
|
-
},
|
|
311
405
|
{
|
|
312
406
|
"rule_id": "TIME-ANCHOR-01",
|
|
313
407
|
"dimension": "time_anchor",
|
|
@@ -376,6 +470,81 @@
|
|
|
376
470
|
}
|
|
377
471
|
]
|
|
378
472
|
},
|
|
473
|
+
{
|
|
474
|
+
"rule_id": "EDGE-ROSTER-NULL-PERM-01",
|
|
475
|
+
"dimension": "fund_flow",
|
|
476
|
+
"trigger": "A forward on a MONEY machine edge (destination is a final/cancelled-role node or an allocator-covered one) declares a NON-EMPTY namedOperator roster with NO permissionIndex. Verified kernel truth (ddmc4 B-24, progress.move:266-310): the permission pre-check computes permissionNeeded=false for that shape and skips the Permission assert entirely — the roster is pure decoration (the namedOperator rail only AUTHORIZES roster members and never DENIES non-members), so ANYONE with a valid order passport can push the fund/terminal forward. ddmc4 live: an outside account triggered ReturnReceived and CompensateBadItem through exactly this shape.",
|
|
477
|
+
"cases": [
|
|
478
|
+
{
|
|
479
|
+
"when": { "field": "first_roster_null_perm_edge", "op": "present" },
|
|
480
|
+
"level": "critical",
|
|
481
|
+
"title": "Money edge '${first_roster_null_perm_edge}' rides a decoration-only roster rail — anyone can push the fund forward",
|
|
482
|
+
"description": "The forward on ${first_roster_null_perm_edge} names a roster but binds no permission index. On chain the permission pre-check needs a permissionIndex to DENY: with none bound, permissionNeeded reads false, the assert is skipped, and the named-operator roster never excludes anyone (it only authorizes members — verified progress.move:266-310, ddmc4 B-24: an outsider executed ReturnReceived/CompensateBadItem). A roster rail alone on a fund/terminal edge is a world-executable payout.",
|
|
483
|
+
"mitigation": "Bind ONE denying rail on this forward: a permission_index (>= 1000; the namedOperator rail is checked first, so pick ONE rail per forward — compile rejects both), or keep the roster rail and mount the kernel roster predicate query(1575 order.named_operator member) on the edge's guard so membership actually EXCLUDES non-members (1575 is gated by the v138 flag enable_order_named_operator_member — check upgrade_check (DEPLOY-K1); on old binaries it reads false, so also tighten the rail).",
|
|
484
|
+
"stakeholders": ["merchant", "customer"]
|
|
485
|
+
}
|
|
486
|
+
]
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
"rule_id": "PERM-COARSE-BUCKET-01",
|
|
490
|
+
"dimension": "fund_flow",
|
|
491
|
+
"trigger": "One permission index is bound on >= 2 money edges (final/cancelled or allocator-covered destinations) whose rail classes DIFFER — settle vs recover|award vs refund|return vs arb, classified by destination node name, forward names, and the edge guards' queries (ddmc4 B-25: 9 heterogeneous fund edges shared bucket 1002, so the arbiter entity could execute the merchant's settle AND refund rails — the coarse bucket turns one compromised permission entity into every fund action at once). A shared bucket inside ONE class is a capacity choice, not a widening.",
|
|
492
|
+
"cases": [
|
|
493
|
+
{
|
|
494
|
+
"when": { "field": "coarse_perm_bucket_index", "op": "present" },
|
|
495
|
+
"level": "medium",
|
|
496
|
+
"title": "Permission index ${coarse_perm_bucket_index} spans rail classes [${coarse_perm_bucket_classes}] — one coarse bucket plays every fund rail",
|
|
497
|
+
"description": "Money edges of DIFFERENT rail classes (${coarse_perm_bucket_classes}) all bind permission index ${coarse_perm_bucket_index}, so the entity holding that one slot can execute every heterogeneous fund action (ddmc4 B-25: the arbiter bucket rode the merchant's settle and refund edges alike). Compromise or misuse of that single permission entity is no longer contained to one rail class.",
|
|
498
|
+
"mitigation": "Split the bucket per rail class: give settle, recover/award, refund/return and arbitration-facing edges DISTINCT permission indexes held by disjoint entities (least privilege — the arbiter should hold only the arb-class slot). If one entity legitimately must span classes, document the shared custody in the build notes so the scan disclosure is a conscious choice.",
|
|
499
|
+
"stakeholders": ["merchant", "customer"]
|
|
500
|
+
}
|
|
501
|
+
]
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
"rule_id": "WRITE-GUARD-TAUTOLOGY-01",
|
|
505
|
+
"dimension": "field_capability",
|
|
506
|
+
"trigger": "A repository policy's write_guard whose only Signer legs are TAUTOLOGIES — Signer == a self-reported (b_submission) address the caller fills with their own, or Signer != the Entity system object 0xaab that no human wallet equals — while the policy routes rows caller-keyed (id_from none/unset, the row key also caller-supplied). Identity chosen at WRITE time is not identity: anyone may write a row under ANY order key, and before write_once anyone may OVERWRITE anyone's (pdd F-18 live: arbitrary order evidence rewritten by an outsider; h1w9 F-03 live: an outsider pre-wrote the report row and front-ran the real hunter's bounty). Guards freeze at publish (IMMUT-001).",
|
|
507
|
+
"cases": [
|
|
508
|
+
{
|
|
509
|
+
"when": { "field": "first_tautology_write_guard", "op": "present" },
|
|
510
|
+
"level": "critical",
|
|
511
|
+
"title": "Write guard ${first_tautology_write_guard} admits EVERYONE — the policy is world-writable",
|
|
512
|
+
"description": "${first_tautology_write_guard} compiles legs that prove nothing: a caller always 'equals' the writer address they themselves submitted, and no wallet equals the 0xaab system object. Combined with caller-keyed rows (id_from none), any address can author — and, absent write_once, rewrite — rows under any key, so evidence, reports and receipts carry zero attribution weight (pdd F-18: an outsider overwrote a live order's evidence). A defence that authorizes everyone is worse than none: downstream readers treat the row as verified.",
|
|
513
|
+
"mitigation": "Bind the writer set to values FIXED before publish: swap the guard to tpl_repository_write_allowlist (Signer ∈ a VecAddress allowlist frozen at publish) or tpl_repository_write_order_holder (order-keyed rows: Signer must hold the row's own Order), and arm policy write_once on final evidence so even an allowlisted writer cannot rewrite history (one evidence KIND per policy — pdd F-04: two kinds on one order-keyed policy share the row id and overwrite each other). Chain residual registered for protocol review: writer ∈ permission-entity membership as a native write-guard primitive (staff rotation today needs a guard rebuild).",
|
|
514
|
+
"stakeholders": ["merchant", "customer"]
|
|
515
|
+
}
|
|
516
|
+
]
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
"rule_id": "WRITE-GUARD-TAUTOLOGY-KEYED-01",
|
|
520
|
+
"dimension": "field_capability",
|
|
521
|
+
"trigger": "Same tautology shape (only self-reported / system-constant Signer legs) on a WALLET-keyed policy (id_from signer/clock): each wallet can write only its own row, so the blast radius is smaller than the caller-keyed critical, but the written CONTENT is still unverified self-assertion — the guard validates nothing beyond 'the writer is who their wallet says' (no institutional sign-off, no order binding).",
|
|
522
|
+
"cases": [
|
|
523
|
+
{
|
|
524
|
+
"when": { "field": "first_keyed_tautology_write_guard", "op": "present" },
|
|
525
|
+
"level": "medium",
|
|
526
|
+
"title": "Write guard ${first_keyed_tautology_write_guard} verifies only the wallet, never the claim",
|
|
527
|
+
"description": "${first_keyed_tautology_write_guard} constrains WHERE a row lands (the writer's own wallet key) but not WHO may assert it or WHAT it may say: any wallet authors self-serving rows about itself under a guard that reads as a credential check. Consumers of the row get no verification signal — the policy name suggests an institutional gate the legs never encode.",
|
|
528
|
+
"mitigation": "If the rows represent an institution's attestation, pin the INSTITUTION's signer: tpl_repository_write_allowlist with the institution addresses (or the pinned single-signer twin tpl_identity_check_single) so only the attesting writer can author rows under this policy. If self-asserted rows are the intent, say so in the policy description — never borrow credential vocabulary for an unverified rail.",
|
|
529
|
+
"stakeholders": ["merchant", "customer"]
|
|
530
|
+
}
|
|
531
|
+
]
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
"rule_id": "WRITE-GUARD-PROMISE-GAP-01",
|
|
535
|
+
"dimension": "privacy",
|
|
536
|
+
"trigger": "A TAUTOLOGY write guard whose policy description PROMISES an authorization bound the compiled legs never encode — authorization vocabulary ('only ... signed', 'must bind the writer', 'allowlist', 'restricted to ...') over a guard whose Signer legs admit everyone. The description-vs-legs divergence is the trust failure itself (h1w9 F-03: the catalog prose said hunter-bound while the root verified nothing, so an outsider's pre-written report row outranked the real hunter's). Judged ONLY on tautology guards — a guard with one binding leg is never flagged, so pinned rails get zero false positives. A description that DISCLOSES its own tautology shape ('these legs are a TAUTOLOGY', 'the self-report shape') is exempt: prose stating the ACTUAL guarantee does not diverge from the legs — only divergence is the failure.",
|
|
537
|
+
"cases": [
|
|
538
|
+
{
|
|
539
|
+
"when": { "field": "first_promise_gap_write_guard", "op": "present" },
|
|
540
|
+
"level": "critical",
|
|
541
|
+
"title": "Policy description promises a bound writer, the guard encodes none: ${first_promise_gap_write_guard}",
|
|
542
|
+
"description": "${first_promise_gap_write_guard}: the policy text promises authorization vocabulary while the compiled guard legs admit every caller — the documented trust model and the enforced one diverge. Anything built on the prose (buyer due diligence, dispute framing, downstream automation) inherits a guarantee the chain does not deliver. Fix the LEGS or fix the PROSE — shipping both as-is is the exact failure h1w9 F-03 recorded.",
|
|
543
|
+
"mitigation": "Encode the promised bound for real: swap to tpl_repository_write_allowlist (Signer ∈ a publish-time allowlist vector) or tpl_repository_write_order_holder (order-keyed rows) and pair with policy write_once on final evidence. If the bound is genuinely not expressible today, rewrite the description to state the ACTUAL guarantee (who writes, what stays unverified) — never keep authorization vocabulary over an open guard. Three residual asks are registered for protocol review: writer ∈ permission-entity membership as a native write-guard primitive, composite row keys (order + kind), and data_remove refusing write_once rows with an event (repository.move:178-183 checks neither today).",
|
|
544
|
+
"stakeholders": ["merchant", "customer"]
|
|
545
|
+
}
|
|
546
|
+
]
|
|
547
|
+
},
|
|
379
548
|
{
|
|
380
549
|
"rule_id": "NODE-MATCH-01",
|
|
381
550
|
"dimension": "fund_flow",
|
|
@@ -417,13 +586,13 @@
|
|
|
417
586
|
{
|
|
418
587
|
"rule_id": "REPO-GATE-KEY-01",
|
|
419
588
|
"dimension": "composition",
|
|
420
|
-
"trigger": "A guard's composite where-query scans a PLAN-LOCAL repository under a static policy key that no repository policy declares (ZR-32, ziroom-mn-261013: the review gate queried a key the write side never wrote — the count stayed 0 forever and the benefit was unreachable; policies
|
|
589
|
+
"trigger": "A guard's composite where-query scans a PLAN-LOCAL repository under a static policy key that no repository policy declares (ZR-32, ziroom-mn-261013: the review gate queried a key the write side never wrote — the count stayed 0 forever and the benefit was unreachable; note policies are NOT chain-frozen: permission 102 (policy_add/policy_set) can add or replace them in place post-publish, so the divergence is repairable by adding the missing policy — but the plan must not ship it). Runtime key rows and external repository addresses are unknowable at plan time and are judged by the chain-side round-trip (analyze_guard_semantics compare_with) instead.",
|
|
421
590
|
"cases": [
|
|
422
591
|
{
|
|
423
592
|
"when": { "field": "repo_gate_key_unbacked_count", "op": "gt", "value": 0 },
|
|
424
593
|
"level": "high",
|
|
425
594
|
"title": "Repository gate key ${first_repo_gate_key_unbacked} is written by no policy",
|
|
426
|
-
"description": "Unbacked scans: ${repo_gate_key_unbacked_display}. The plan declares these repository policies: ${repo_policy_keys_display}. A where-scan over an undeclared key reads an empty table
|
|
595
|
+
"description": "Unbacked scans: ${repo_gate_key_unbacked_display}. The plan declares these repository policies: ${repo_policy_keys_display}. A where-scan over an undeclared key reads an empty table as built — count/sum stay 0 and find/keys return empty — so the gated path can never pass. Repository policies are NOT chain-frozen (permission 102 can add/replace them in place post-publish; already-written rows stay bound by write_once/write_guard), so the divergence is repaired by ADDING the missing policy via permission 102 or by aligning names before publish — not by rebuilding the repository. Guards DO freeze at creation: a guard-side key literal cannot self-heal.",
|
|
427
596
|
"mitigation": "Reconcile the two sides before publish: change the guard's static key row to a declared policy name (${repo_policy_keys_display}), or rename the repository policy to the queried key. After fixing, re-verify the resolved guard with analyze_guard_semantics compare_with after creation.",
|
|
428
597
|
"stakeholders": ["merchant", "customer"]
|
|
429
598
|
}
|
|
@@ -473,6 +642,204 @@
|
|
|
473
642
|
"stakeholders": ["merchant", "customer"]
|
|
474
643
|
}
|
|
475
644
|
]
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
"rule_id": "COMPOSE-PAIR-01",
|
|
648
|
+
"dimension": "composition",
|
|
649
|
+
"trigger": "A guard reads order.* on a slot other than the host slot 0 (the P2 cross-order shape from chain-semantics/composition-truth.ts) but carries NO pairing key. Owner equality plus a provider pin proves only that this buyer has another order at that provider - it does NOT prove that order served THIS order, so one delivery order can unlock settlement on every order the same buyer ever placed. Allocation is append-only after publish and the Guard freezes at creation, so the missing key can never be added later.",
|
|
650
|
+
"cases": [
|
|
651
|
+
{
|
|
652
|
+
"when": {
|
|
653
|
+
"all": [
|
|
654
|
+
{
|
|
655
|
+
"field": "first_cross_order_guard_unpaired",
|
|
656
|
+
"op": "present"
|
|
657
|
+
}
|
|
658
|
+
]
|
|
659
|
+
},
|
|
660
|
+
"level": "critical",
|
|
661
|
+
"title": "Cross-order gate has no pairing key (one fulfilment order can unlock many host orders)",
|
|
662
|
+
"description": "Guard '${first_cross_order_guard_unpaired}' reads a foreign order slot (${cross_order_slots_display}) with neither a repository.data rendezvous leg nor a declared 255 ONCE row. ${cross_order_unpaired_count} cross-order guard(s) are unpaired. A buyer who orders food twice and delivery once can present the same delivery order twice; the chain accepts it both times because nothing binds the fulfilment order to one host order.",
|
|
663
|
+
"mitigation": "Emit a pairing key. Preferred: a shared Repository row keyed by the HOST order address (P1) read via `repository.data has`, with write_once set on that policy rule so the fulfilment fact cannot be rewritten after settlement. Cheapest: declare {identifier: 255, b_submission: true} on the guard so the once-key includes the submitted bytes and the same foreign order address can only be consumed once.",
|
|
664
|
+
"stakeholders": ["merchant", "customer"]
|
|
665
|
+
}
|
|
666
|
+
]
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
"rule_id": "COMPOSE-PROVIDER-PIN-01",
|
|
670
|
+
"dimension": "composition",
|
|
671
|
+
"trigger": "A cross-order gate does not pin the foreign order's Service to a constant address. Without the pin any order the caller happens to own - at any merchant, for any amount, in any state - satisfies the gate.",
|
|
672
|
+
"cases": [
|
|
673
|
+
{
|
|
674
|
+
"when": {
|
|
675
|
+
"all": [
|
|
676
|
+
{
|
|
677
|
+
"field": "first_cross_order_guard_unpinned",
|
|
678
|
+
"op": "present"
|
|
679
|
+
}
|
|
680
|
+
]
|
|
681
|
+
},
|
|
682
|
+
"level": "high",
|
|
683
|
+
"title": "Cross-order gate does not pin the fulfilment provider",
|
|
684
|
+
"description": "Guard '${first_cross_order_guard_unpinned}' reads a foreign order slot but never compares order.service on that slot against a constant Address row. The native evaluator enforces the submitted object's TYPE (a Progress or Service submitted as an Order aborts) but it cannot know WHICH service was intended, so the caller supplies that fact and the gate believes it.",
|
|
685
|
+
"mitigation": "Add a non-submission Address table row holding the sub-Service address as a constant, plus a leg comparing order.service(foreignSlot) to it. That constant is the merchant's own commitment (P3) and is what makes the cross-order read meaningful.",
|
|
686
|
+
"stakeholders": ["merchant", "customer"]
|
|
687
|
+
}
|
|
688
|
+
]
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
"rule_id": "COMPOSE-OWNER-CROSS-01",
|
|
692
|
+
"dimension": "composition",
|
|
693
|
+
"trigger": "A cross-order gate does not cross-check order.owner between the host slot and the foreign slot, so a stranger's order can satisfy it.",
|
|
694
|
+
"cases": [
|
|
695
|
+
{
|
|
696
|
+
"when": {
|
|
697
|
+
"all": [
|
|
698
|
+
{
|
|
699
|
+
"field": "first_cross_order_guard_no_owner_cross",
|
|
700
|
+
"op": "present"
|
|
701
|
+
}
|
|
702
|
+
]
|
|
703
|
+
},
|
|
704
|
+
"level": "high",
|
|
705
|
+
"title": "Cross-order gate does not tie the two orders to one buyer",
|
|
706
|
+
"description": "Guard '${first_cross_order_guard_no_owner_cross}' reads a foreign order slot without reading order.owner on BOTH slots. Any sufficiently-shaped order from any buyer then passes, which turns a per-buyer fulfilment condition into a global one.",
|
|
707
|
+
"mitigation": "Add the leg order.owner(hostSlot) == order.owner(foreignSlot). Note this alone is still not a pairing key - see COMPOSE-PAIR-01.",
|
|
708
|
+
"stakeholders": ["merchant", "customer"]
|
|
709
|
+
}
|
|
710
|
+
]
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
"rule_id": "COMPOSE-LIABILITY-01",
|
|
714
|
+
"dimension": "composition",
|
|
715
|
+
"trigger": "A third party fulfils part of the service but no payout path for that party was pre-set before publish. arbitration compensation_claim transfers to order::owner(order) - the recipient is hard-bound - and indemnity is capped at MAX_INDEMNITY_MULTIPLE (3) times the order amount, so a ruling in the fulfilment party's favour has NO on-chain execution path. Allocation rows are append-only after publish, so this cannot be repaired later (chain-semantics/composition-truth.ts S4; RD-C4 ruled 2026-10-29: block, do not warn).",
|
|
716
|
+
"cases": [
|
|
717
|
+
{
|
|
718
|
+
"when": {
|
|
719
|
+
"all": [
|
|
720
|
+
{
|
|
721
|
+
"field": "third_party_fulfilment_without_payout",
|
|
722
|
+
"op": "truthy"
|
|
723
|
+
}
|
|
724
|
+
]
|
|
725
|
+
},
|
|
726
|
+
"level": "critical",
|
|
727
|
+
"title": "Third-party fulfilment with no pre-set payout path (a ruling for the rider is unexecutable)",
|
|
728
|
+
"description": "This plan procures fulfilment from a third party (a cross-order gate is present; declared axis '${fulfillment_axis}') but declares no Entity/Signer sharing leg and creates no Reward pool. If an arbitration finds the fulfilment party was wronged - or the merchant wants to pay a rider directly - no leg can carry the money, and the only remaining channel is an off-chain transfer with no on-chain evidence.",
|
|
729
|
+
"mitigation": "Pre-set one of two paths before publish. (a) An arbitration-triggered sharing leg with Recipient::Entity or Recipient::Signer: those legs are NOT constrained by payment_info.for_object, so they can pay a party who is not the order owner; gate it with the same identity pattern the refund rails already use. (b) A Reward pool (P6) the fulfilment party claims itself - claim asserts recipient == tx sender, the only permissionless channel that reaches a third party - with store_from pinned so one fulfilment pays once.",
|
|
730
|
+
"stakeholders": ["supplier", "merchant", "customer"]
|
|
731
|
+
}
|
|
732
|
+
]
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
"rule_id": "COMPOSE-DUALREFUND-01",
|
|
736
|
+
"dimension": "composition",
|
|
737
|
+
"trigger": "V3 (the buyer procures fulfilment as a separate order) puts two escrow pools behind the SAME buyer address with different counterparties. Neither Service can read the other's claimed_by, so the chain cannot block a refund on both - a reachable 200% window. This is an inherent property to disclose, not a defect to fix (chain-semantics/composition-truth.ts S2/S3; RD-C3 ruled 2026-10-29: offer V3 as a first-class variant with mandatory disclosure).",
|
|
738
|
+
"cases": [
|
|
739
|
+
{
|
|
740
|
+
"when": {
|
|
741
|
+
"all": [
|
|
742
|
+
{
|
|
743
|
+
"field": "composition_dual_refund_unblockable",
|
|
744
|
+
"op": "truthy"
|
|
745
|
+
}
|
|
746
|
+
]
|
|
747
|
+
},
|
|
748
|
+
"level": "medium",
|
|
749
|
+
"title": "V3 double refund cannot be blocked on chain - disclosure required",
|
|
750
|
+
"description": "The plan declares V3. The buyer owns both orders, the two pools have different counterparties, and each refund rail can only read its own order's claimed_by. Refunding on both orders is technically reachable, and the buyer's disputes must be filed twice with two fees and two panels that may rule contradictorily. ${composition_disclosure_count} disclosures are owed before purchase.",
|
|
751
|
+
"mitigation": "Surface all three V3 disclosures at build time and at the purchase gate, and require the buyer to confirm each one: (1) double refund is not blockable and is the buyer's own liability; (2) disputes cannot be merged - two filings, two fees, possibly contradictory rulings; (3) the merchant has no recourse against and no visibility into the buyer's fulfilment order. Never describe the two orders as linked on chain.",
|
|
752
|
+
"stakeholders": ["customer", "merchant"]
|
|
753
|
+
}
|
|
754
|
+
]
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
"rule_id": "COMPOSE-VARIANT-01",
|
|
758
|
+
"dimension": "composition",
|
|
759
|
+
"trigger": "A commercial variant is declared but the plan does not emit the primitives that variant requires, so the declared business model and the materialized chain objects disagree.",
|
|
760
|
+
"cases": [
|
|
761
|
+
{
|
|
762
|
+
"when": {
|
|
763
|
+
"all": [
|
|
764
|
+
{
|
|
765
|
+
"field": "composition_variant_missing_primitives",
|
|
766
|
+
"op": "present"
|
|
767
|
+
}
|
|
768
|
+
]
|
|
769
|
+
},
|
|
770
|
+
"level": "medium",
|
|
771
|
+
"title": "Declared variant is not backed by the primitives it needs",
|
|
772
|
+
"description": "Variant ${composition_variant} requires primitives this plan does not emit: ${composition_variant_missing_primitives}. The listing will promise a composition the published objects cannot gate - for example a merchant-procured delivery with no cross-order gate means the main order settles whether or not the sub-order was ever fulfilled.",
|
|
773
|
+
"mitigation": "Either emit the missing primitives (chain-semantics/composition-truth.ts gives the shape of each) or declare the variant the emitted topology actually supports. Emitted primitives for this plan: ${composition_primitives_emitted}.",
|
|
774
|
+
"stakeholders": ["merchant", "customer"]
|
|
775
|
+
}
|
|
776
|
+
]
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
"rule_id": "PRIV-PUBLICFACE-01",
|
|
780
|
+
"dimension": "privacy",
|
|
781
|
+
"trigger": "A build-time public face carries text matching a language-neutral PII shape. The chain has no confidentiality primitive at all: Contact, Proof, Repository data, Entity records and listing copy are public and permanent, and the Messenger type is commented out of the registrar. The write is therefore the ONLY defence (chain-semantics/composition-truth.ts S5; RD-C5 ruled: hard gate at build time and on runtime submission).",
|
|
782
|
+
"cases": [
|
|
783
|
+
{
|
|
784
|
+
"when": {
|
|
785
|
+
"all": [
|
|
786
|
+
{
|
|
787
|
+
"field": "first_pii_public_face",
|
|
788
|
+
"op": "present"
|
|
789
|
+
}
|
|
790
|
+
]
|
|
791
|
+
},
|
|
792
|
+
"level": "critical",
|
|
793
|
+
"title": "PII on a permanent public face (cannot be retracted after creation)",
|
|
794
|
+
"description": "Step '${first_pii_public_face_step}' writes ${first_pii_public_face} and the text matches the '${first_pii_kind}' shape. Once created, this value is publicly readable forever - there is no delete, no redaction and no read-permission primitive. A delivery address, phone number or identity number published here is published to every indexer and every competitor.",
|
|
795
|
+
"mitigation": "Move the value off chain: PII travels only through Messenger (E2EE), and the chain carries a presence gate instead - `order.required_info some` proves the buyer supplied it without publishing it. If a proof of the value is genuinely needed on chain, store a hash. Contact.location should stay city-level.",
|
|
796
|
+
"stakeholders": ["customer", "merchant"]
|
|
797
|
+
}
|
|
798
|
+
]
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
"rule_id": "PRIV-TRACKING-RAW-01",
|
|
802
|
+
"dimension": "privacy",
|
|
803
|
+
"trigger": "A repository data value is a RAW carrier tracking number rather than a hash. Repository data is publicly readable with no author field, and a tracking number is a quasi-identifier: the carrier's own public lookup resolves it to a recipient name and address, so the raw number republishes the delivery address by reference.",
|
|
804
|
+
"cases": [
|
|
805
|
+
{
|
|
806
|
+
"when": {
|
|
807
|
+
"all": [
|
|
808
|
+
{
|
|
809
|
+
"field": "first_raw_tracking_value",
|
|
810
|
+
"op": "present"
|
|
811
|
+
}
|
|
812
|
+
]
|
|
813
|
+
},
|
|
814
|
+
"level": "high",
|
|
815
|
+
"title": "Raw tracking number stored in a public repository row",
|
|
816
|
+
"description": "Step '${first_raw_tracking_value_step}' writes '${first_raw_tracking_value}' as a repository data value. Anyone reading the row can resolve it at the carrier to a recipient and an address, and the row can be correlated with the order it was written for.",
|
|
817
|
+
"mitigation": "Store a salted hash of the tracking number and hand the raw value to the buyer and the carrier over Messenger. If the row must stay human-readable for support, store the last four characters only.",
|
|
818
|
+
"stakeholders": ["customer", "supplier"]
|
|
819
|
+
}
|
|
820
|
+
]
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
"rule_id": "PRIV-PROOF-PERORDER-01",
|
|
824
|
+
"dimension": "privacy",
|
|
825
|
+
"trigger": "required_info is attested through a Proof bound to the ORDER, which publicly associates that order with the contact record. The reusable shape (about = the contact) carries the same attestation without the per-order link.",
|
|
826
|
+
"cases": [
|
|
827
|
+
{
|
|
828
|
+
"when": {
|
|
829
|
+
"all": [
|
|
830
|
+
{
|
|
831
|
+
"field": "per_order_proof_binding_step",
|
|
832
|
+
"op": "present"
|
|
833
|
+
}
|
|
834
|
+
]
|
|
835
|
+
},
|
|
836
|
+
"level": "low",
|
|
837
|
+
"title": "Per-order Proof binding publicly links the order to a contact record",
|
|
838
|
+
"description": "Step '${per_order_proof_binding_step}' binds a Proof to the order (or binds required_info through a proof). The binding is verifiable by anyone and permanently ties that order address to that contact record, widening what an observer can correlate.",
|
|
839
|
+
"mitigation": "Prefer the reusable Proof shape whose `about` is the contact rather than the order, unless per-order binding is a deliberate requirement of the flow.",
|
|
840
|
+
"stakeholders": ["customer", "merchant"]
|
|
841
|
+
}
|
|
842
|
+
]
|
|
476
843
|
}
|
|
477
844
|
]
|
|
478
845
|
}
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"operate_next_node_name": "The target node name of the operate op (display form).",
|
|
26
26
|
"forward_named_operator": "The namedOperator governing the forward being advanced (echo).",
|
|
27
27
|
"forward_named_op_bypass": "True when the forward advance rides the namedOperator short-circuit, skipping the 220-225 permission-index check.",
|
|
28
|
+
"forward_payer_scope": "True when the forward being advanced has namedOperator=\"\" (the reserved order-payer namespace) — payer-only authority: off the order-bound entry the advance asserts order-payer power, and a taskless Progress fails closed (E_ORDER_PAYER_REQUIRED).",
|
|
28
29
|
"forward_has_guard_display": "Echo of whether the forward carries a Guard (display form).",
|
|
29
30
|
"guard_passport_required": "True when the forward has a Guard but no permission index — a Passport is required for the advance (E_NEED_PASSPORT ahead).",
|
|
30
31
|
"machine_published_false": "True when the context explicitly marks the Machine as unpublished (strict false).",
|
|
@@ -225,6 +226,23 @@
|
|
|
225
226
|
}
|
|
226
227
|
]
|
|
227
228
|
},
|
|
229
|
+
{
|
|
230
|
+
"rule_id": "R-PR-3-04",
|
|
231
|
+
"dimension": "permission",
|
|
232
|
+
"trigger": "Forward namedOperator=\"\" (order-payer namespace) — payer-only authority; taskless fail-closed (E_ORDER_PAYER_REQUIRED)",
|
|
233
|
+
"cases": [
|
|
234
|
+
{
|
|
235
|
+
"when": { "field": "forward_payer_scope", "op": "eq", "value": true },
|
|
236
|
+
"level": "high",
|
|
237
|
+
"title": "Forward names the order payer — generic-entry advance aborts E_ORDER_PAYER_REQUIRED",
|
|
238
|
+
"description": "Forward \"${operate_forward}\" has namedOperator=\"\" — the reserved order-payer namespace. Only the payer of the bound Order (or an address holding op-permission on that Order) may drive it: generic entries (next/hold, with or without passport) assert payer authority and abort with E_ORDER_PAYER_REQUIRED otherwise. On a taskless Progress (task=null) the assertion fails closed — no payer exists to name, so the forward is un-executable by design.",
|
|
239
|
+
"scenario": "An operator presses a buyer-owned (order-payer) edge from a generic entry, or a standalone machine is designed with \"\" forwards",
|
|
240
|
+
"mitigation": "Drive the step as the order payer via the order-bound path (the SDK auto-routes progress.operate to the order entries when the task is an Order), or grant the address op-permission on the bound Order. For standalone Progress workflows, declare forwards with a non-empty namedOperator or a permissionIndex instead of \"\".",
|
|
241
|
+
"evidence": "named_operator=\"\", forward=${operate_forward}",
|
|
242
|
+
"stakeholders": ["submitter", "owner"]
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
},
|
|
228
246
|
{
|
|
229
247
|
"rule_id": "R-PR-4-01",
|
|
230
248
|
"dimension": "lifecycle",
|
|
@@ -334,9 +352,9 @@
|
|
|
334
352
|
"when": { "field": "orderless_operate", "op": "eq", "value": true },
|
|
335
353
|
"level": "medium",
|
|
336
354
|
"title": "operate without bound Order — order-holder advance/hold unavailable",
|
|
337
|
-
"description": "Progress has no bound task (task=null). The order-holder advance and hold paths require progress.task == order address (E_ORDER_NOT_MATCH). Use plain next()/hold() instead.",
|
|
355
|
+
"description": "Progress has no bound task (task=null). The order-holder advance and hold paths require progress.task == order address (E_ORDER_NOT_MATCH). Use plain next()/hold() instead — except for forwards with namedOperator=\"\": with no bound Order there is no payer to name, so those abort fail-closed (E_ORDER_PAYER_REQUIRED) on any entry.",
|
|
338
356
|
"scenario": "User tries order variant on a task-less Progress",
|
|
339
|
-
"mitigation": "Use non-order next()/hold() variant, OR submit the task first to bind an Order",
|
|
357
|
+
"mitigation": "Use non-order next()/hold() variant (non-empty-namedOperator or permissionIndex forwards), OR submit the task first to bind an Order; \"\"-scoped forwards on a taskless Progress are un-executable by design",
|
|
340
358
|
"evidence": "task=null",
|
|
341
359
|
"stakeholders": ["submitter"]
|
|
342
360
|
}
|
|
@@ -24,6 +24,11 @@ export interface ArchetypeTemplate {
|
|
|
24
24
|
role_rationale: string;
|
|
25
25
|
differences: string[];
|
|
26
26
|
user_inputs: string[];
|
|
27
|
+
user_input_specs?: {
|
|
28
|
+
question: string;
|
|
29
|
+
param_key: string;
|
|
30
|
+
note?: string;
|
|
31
|
+
}[];
|
|
27
32
|
key_risk: string;
|
|
28
33
|
compensation_fund_policy?: "allowed" | "forbidden";
|
|
29
34
|
settlement_window_merge?: readonly string[];
|
|
@@ -53,7 +58,7 @@ export interface ArchetypeTemplate {
|
|
|
53
58
|
logistics_mode?: "none" | "carrier" | "merchant_managed" | "courier" | "pickup_point";
|
|
54
59
|
crowdfunding_mode?: "none" | "threshold" | "flexible";
|
|
55
60
|
}
|
|
56
|
-
export declare const BUILTIN_TEMPLATES_VERSION =
|
|
61
|
+
export declare const BUILTIN_TEMPLATES_VERSION = 161;
|
|
57
62
|
export declare const BUILTIN_TEMPLATES: ArchetypeTemplate[];
|
|
58
63
|
export declare const TEMPLATE_KEYWORDS: Record<string, string[]>;
|
|
59
64
|
export declare const TEMPLATE_TAGS: Record<string, string[]>;
|
|
@@ -82,3 +87,25 @@ export interface OnceSlotAdvisory {
|
|
|
82
87
|
message: string;
|
|
83
88
|
}
|
|
84
89
|
export declare function auditTemplateOnceSlotArms(entries?: ArchetypeTemplate[]): OnceSlotAdvisory[];
|
|
90
|
+
export interface NodeOperatorAdvisory {
|
|
91
|
+
template_id: string;
|
|
92
|
+
kind: "node_operator_overwritten";
|
|
93
|
+
message: string;
|
|
94
|
+
}
|
|
95
|
+
export declare function auditTemplateNodeOperatorOverwrite(entries?: ArchetypeTemplate[]): NodeOperatorAdvisory[];
|
|
96
|
+
export interface ReturnNoExitAdvisory {
|
|
97
|
+
template_id: string;
|
|
98
|
+
rule_id: "R-RETURN-NO-EXIT";
|
|
99
|
+
severity: "high";
|
|
100
|
+
stranded_nodes: string[];
|
|
101
|
+
remediation: string;
|
|
102
|
+
}
|
|
103
|
+
export declare function auditTemplateReturnNoExit(entries?: ArchetypeTemplate[]): ReturnNoExitAdvisory[];
|
|
104
|
+
export interface AutoAcceptNoRemedyAdvisory {
|
|
105
|
+
template_id: string;
|
|
106
|
+
rule_id: "R-AUTOACCEPT-NO-REMEDY";
|
|
107
|
+
severity: "high";
|
|
108
|
+
accept_node: string;
|
|
109
|
+
remediation: string;
|
|
110
|
+
}
|
|
111
|
+
export declare function auditTemplateAutoAcceptNoRemedy(entries?: ArchetypeTemplate[]): AutoAcceptNoRemedyAdvisory[];
|