Skip to content

Conversation

@yilmaztayfun
Copy link
Contributor

@yilmaztayfun yilmaztayfun commented Dec 15, 2025

Introduces new contract approval and document subflow workflows, including associated tasks and C# mapping scripts. Adds test workflows and tasks for Dapr, HTTP, and workflow communication. Updates account opening workflow state types and minor config fixes. Removes obsolete OAuth workflow scripts and adds .gitignore entry for ai-docs/.

Summary by Sourcery

Introduce new contract approval and document subflow workflows alongside a comprehensive task-testing workflow suite, and clean up obsolete OAuth workflow assets.

New Features:

  • Add contract approval and document-processing subflow workflows with supporting mapping scripts and rules for document lifecycle management.
  • Introduce task-test workflows and tasks to exercise HTTP, Dapr service/pubsub, subprocess, start, direct-transition, script, secret/config access, and cross-instance data retrieval.
  • Extend account-opening and payments workflows with updated state/config and new HTTP request definitions for local testing.

Enhancements:

  • Update Mockoon and Postman API definitions to support the new contract and task-test scenarios.
  • Ignore ai-docs/ content in version control.

Chores:

  • Remove obsolete OAuth workflow rules and related upload script.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced contract approval workflow with document rendering, approval notifications, and status tracking.
    • Added scheduled payments workflow with payment execution and cancellation capabilities.
    • Implemented comprehensive task testing framework supporting HTTP, Dapr, and workflow orchestration tests.
    • Enhanced account opening workflow with improved state management.
  • Chores

    • Updated test fixtures and mock server configurations.

✏️ Tip: You can customize this high-level summary in your review settings.

Introduces new contract approval and document subflow workflows, including associated tasks and C# mapping scripts. Adds test workflows and tasks for Dapr, HTTP, and workflow communication. Updates account opening workflow state types and minor config fixes. Removes obsolete OAuth workflow scripts and adds .gitignore entry for ai-docs/.
@gitguardian
Copy link

gitguardian bot commented Dec 15, 2025

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
23400359 Triggered Username Password bce9141 core/Workflows/oauth/oauth-authentication-workflow.http View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@yilmaztayfun yilmaztayfun merged commit 895bf80 into master Dec 15, 2025
0 of 3 checks passed
@sourcery-ai
Copy link

sourcery-ai bot commented Dec 15, 2025

Reviewer's Guide

Introduces new contract approval and task-test workflows (with supporting tasks, rules, and C# mapping scripts), wires them to Mockoon/Dapr for integration-style tests, adjusts existing account-opening/payment workflows, and removes obsolete OAuth workflow artifacts while tightening repo ignores.

Sequence diagram for contract approval workflow and document subflow interaction

sequenceDiagram
    participant Client as Client
    participant WorkflowEngine as WorkflowEngine
    participant ContractApprovalWorkflow as ContractApprovalWorkflow
    participant ContractDocumentSubflow as ContractDocumentSubflow
    participant MockoonApi as MockoonApi

    Client->>WorkflowEngine: Start contract_approval_workflow (groupCode)
    WorkflowEngine->>ContractApprovalWorkflow: Initialize instance
    ContractApprovalWorkflow->>InitContractApprovalMapping: OutputHandler
    InitContractApprovalMapping-->>ContractApprovalWorkflow: init-success (groupCode, counters)

    ContractApprovalWorkflow->>GetContractDocumentsMapping: InputHandler
    GetContractDocumentsMapping-->>ContractApprovalWorkflow: HTTP body, headers
    ContractApprovalWorkflow->>MockoonApi: POST /contracts (groupCode)
    MockoonApi-->>ContractApprovalWorkflow: contracts list, totalContracts
    ContractApprovalWorkflow->>GetContractDocumentsMapping: OutputHandler
    GetContractDocumentsMapping-->>ContractApprovalWorkflow: documents[], totalDocuments, currentDocumentIndex=0

    loop For each document while HasMoreDocumentsRule==true
        ContractApprovalWorkflow->>StartDocumentSubprocessMapping: InputHandler
        StartDocumentSubprocessMapping-->>ContractApprovalWorkflow: subprocess key, body (document, indices)
        ContractApprovalWorkflow->>ContractDocumentSubflow: Start subprocess (document, parent ids)
        ContractDocumentSubflow-->>ContractApprovalWorkflow: subprocess-started via StartDocumentSubprocessMapping.OutputHandler
        ContractApprovalWorkflow->>AllDocumentsReadyRule: Handler
        AllDocumentsReadyRule-->>ContractApprovalWorkflow: currentDocumentIndex>=totalDocuments?
    end

    ContractApprovalWorkflow->>MoreApprovalsPendingRule: Handler
    MoreApprovalsPendingRule-->>ContractApprovalWorkflow: approvedCount<totalDocuments?
    alt AllApprovedRule==true
        ContractApprovalWorkflow->>AllApprovedRule: Handler
        AllApprovedRule-->>ContractApprovalWorkflow: true
        ContractApprovalWorkflow-->>Client: Workflow completed (all documents approved)
    else Pending approvals
        ContractApprovalWorkflow-->>Client: Waiting for document approval transitions
    end
Loading

Sequence diagram for contract document subflow rendering and parent notification

sequenceDiagram
    participant ContractApprovalWorkflow as ContractApprovalWorkflow
    participant ContractDocumentSubflow as ContractDocumentSubflow
    participant MockoonApi as MockoonApi
    participant NotifyReadyMapping as NotifyDocumentReadyMapping
    participant NotifyApprovedMapping as NotifyDocumentApprovedMapping
    participant NotifyRejectedMapping as NotifyDocumentRejectedMapping

    ContractApprovalWorkflow->>ContractDocumentSubflow: Start subprocess (document, parent ids)
    ContractDocumentSubflow->>InitDocumentMapping: OutputHandler
    InitDocumentMapping-->>ContractDocumentSubflow: init-document-success (renderStatus=pending)

    ContractDocumentSubflow->>RenderDocumentMapping: InputHandler
    RenderDocumentMapping-->>ContractDocumentSubflow: HTTP body, headers
    ContractDocumentSubflow->>MockoonApi: POST /render (document)
    MockoonApi-->>ContractDocumentSubflow: render response
    ContractDocumentSubflow->>RenderDocumentMapping: OutputHandler
    RenderDocumentMapping-->>ContractDocumentSubflow: render-success or render-failed

    alt RenderSuccessRule==true
        ContractDocumentSubflow->>RenderSuccessRule: Handler
        RenderSuccessRule-->>ContractDocumentSubflow: true
        ContractDocumentSubflow->>NotifyReadyMapping: InputHandler
        NotifyReadyMapping-->>ContractDocumentSubflow: configured DirectTriggerTask to parent
        ContractDocumentSubflow->>ContractApprovalWorkflow: Direct transition document-ready
        ContractApprovalWorkflow->>IncrementReadyCountMapping: OutputHandler
        IncrementReadyCountMapping-->>ContractApprovalWorkflow: ready-count-incremented
    else RenderFailedRule==true
        ContractDocumentSubflow->>RenderFailedRule: Handler
        RenderFailedRule-->>ContractDocumentSubflow: true
        ContractDocumentSubflow-->>ContractApprovalWorkflow: Error path or compensation
    end

    opt User approves document in subprocess
        ContractDocumentSubflow->>NotifyApprovedMapping: InputHandler
        NotifyApprovedMapping-->>ContractDocumentSubflow: DirectTriggerTask configured
        ContractDocumentSubflow->>ContractApprovalWorkflow: Direct transition document-approved
        ContractApprovalWorkflow->>IncrementApprovedCountMapping: OutputHandler
        IncrementApprovedCountMapping-->>ContractApprovalWorkflow: approved-count-incremented
    end

    opt User rejects document in subprocess
        ContractDocumentSubflow->>NotifyRejectedMapping: InputHandler
        NotifyRejectedMapping-->>ContractDocumentSubflow: DirectTriggerTask configured
        ContractDocumentSubflow->>ContractApprovalWorkflow: Direct transition document-rejected
    end
Loading

Class diagram for new contract workflow mappings and rules

classDiagram
    class ScriptContext
    class WorkflowTask
    class HttpTask
    class SubProcessTask
    class DirectTriggerTask
    class ScriptResponse
    class IMapping {
        <<interface>>
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }
    class IConditionMapping {
        <<interface>>
        +Task~bool~ Handler(ScriptContext context)
    }

    class InitContractApprovalMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class GetContractDocumentsMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class StartDocumentSubprocessMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class InitDocumentMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class RenderDocumentMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class NotifyDocumentReadyMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class NotifyDocumentApprovedMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class NotifyDocumentRejectedMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class IncrementReadyCountMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class IncrementApprovedCountMapping {
        +Task~ScriptResponse~ InputHandler(WorkflowTask task, ScriptContext context)
        +Task~ScriptResponse~ OutputHandler(ScriptContext context)
    }

    class DocumentsLoadedRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    class NoDocumentsRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    class HasMoreDocumentsRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    class AllDocumentsReadyRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    class RenderSuccessRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    class RenderFailedRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    class MoreApprovalsPendingRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    class AllApprovedRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    class AlwaysTrueRule {
        +Task~bool~ Handler(ScriptContext context)
    }

    IMapping <|.. InitContractApprovalMapping
    IMapping <|.. GetContractDocumentsMapping
    IMapping <|.. StartDocumentSubprocessMapping
    IMapping <|.. InitDocumentMapping
    IMapping <|.. RenderDocumentMapping
    IMapping <|.. NotifyDocumentReadyMapping
    IMapping <|.. NotifyDocumentApprovedMapping
    IMapping <|.. NotifyDocumentRejectedMapping
    IMapping <|.. IncrementReadyCountMapping
    IMapping <|.. IncrementApprovedCountMapping

    IConditionMapping <|.. DocumentsLoadedRule
    IConditionMapping <|.. NoDocumentsRule
    IConditionMapping <|.. HasMoreDocumentsRule
    IConditionMapping <|.. AllDocumentsReadyRule
    IConditionMapping <|.. RenderSuccessRule
    IConditionMapping <|.. RenderFailedRule
    IConditionMapping <|.. MoreApprovalsPendingRule
    IConditionMapping <|.. AllApprovedRule
    IConditionMapping <|.. AlwaysTrueRule

    WorkflowTask <|-- HttpTask
    WorkflowTask <|-- SubProcessTask
    WorkflowTask <|-- DirectTriggerTask

    InitContractApprovalMapping ..> ScriptContext
    InitContractApprovalMapping ..> ScriptResponse
    GetContractDocumentsMapping ..> HttpTask
    GetContractDocumentsMapping ..> ScriptContext
    StartDocumentSubprocessMapping ..> SubProcessTask
    RenderDocumentMapping ..> HttpTask
    NotifyDocumentReadyMapping ..> DirectTriggerTask
    NotifyDocumentApprovedMapping ..> DirectTriggerTask
    NotifyDocumentRejectedMapping ..> DirectTriggerTask
    IncrementReadyCountMapping ..> ScriptContext
    IncrementApprovedCountMapping ..> ScriptContext
    DocumentsLoadedRule ..> ScriptContext
    NoDocumentsRule ..> ScriptContext
    HasMoreDocumentsRule ..> ScriptContext
    AllDocumentsReadyRule ..> ScriptContext
    RenderSuccessRule ..> ScriptContext
    RenderFailedRule ..> ScriptContext
    MoreApprovalsPendingRule ..> ScriptContext
    AllApprovedRule ..> ScriptContext
    AlwaysTrueRule ..> ScriptContext
Loading

Flow diagram for contract approval workflow decision rules

flowchart TD
    Start["Start contract-approval-workflow"] --> Init["InitContractApprovalMapping OutputHandler\nset counters, groupCode"]
    Init --> GetDocs["GetContractDocumentsMapping\nHTTP to Mockoon contracts API"]
    GetDocs --> CheckLoaded{DocumentsLoadedRule}

    CheckLoaded -- true --> HasDocs["totalDocuments > 0"]
    CheckLoaded -- false --> NoDocs["NoDocumentsRule\ncomplete with no documents"]

    HasDocs --> LoopCheck{HasMoreDocumentsRule}
    LoopCheck -- true --> StartSub["StartDocumentSubprocessMapping\nstart contract-document-subflow"]
    StartSub --> IncIndex["Update currentDocumentIndex"]
    IncIndex --> LoopCheck

    LoopCheck -- false --> ReadyCheck{AllDocumentsReadyRule}

    ReadyCheck -- true --> ApprovalsPending{MoreApprovalsPendingRule}
    ReadyCheck -- false --> ErrorPath["Unexpected state or wait"]

    ApprovalsPending -- true --> WaitTransitions["Wait for document-approved or document-rejected transitions"]
    WaitTransitions --> ApprovalsPending

    ApprovalsPending -- false --> AllApproved{AllApprovedRule}

    AllApproved -- true --> CompleteSuccess["All contracts approved\nworkflow success"]
    AllApproved -- false --> MixedOutcome["Some rejected or failed"]

    NoDocs --> EndNoDocs["End: no documents"]
    ErrorPath --> EndError["End: error or manual intervention"]
    CompleteSuccess --> EndSuccess["End: success"]
    MixedOutcome --> EndMixed["End: mixed result"]
Loading

File-Level Changes

Change Details Files
Add contract approval and document subflow workflows with supporting rules and mapping scripts.
  • Create main contract-approval workflow and document subprocess workflow JSON definitions plus HTTP examples and diagram metadata.
  • Implement C# mapping scripts to initialize contract approval state, fetch contract documents via HTTP, start a document subprocess, render documents, and notify the parent workflow on ready/approved/rejected events.
  • Add rule scripts to drive contract workflow branching (documents loaded/no-documents, per-document progression, render success/failure, and overall approval completion).
core/Workflows/contract/contract-approval-workflow.json
core/Workflows/contract/contract-document-subflow.json
core/Workflows/contract/contract-approval-workflow.http
core/Workflows/contract/.meta/contract-approval-workflow.diagram.json
core/Workflows/contract/.meta/contract-document-subflow.diagram.json
core/Workflows/contract/src/InitContractApprovalMapping.csx
core/Workflows/contract/src/GetContractDocumentsMapping.csx
core/Workflows/contract/src/StartDocumentSubprocessMapping.csx
core/Workflows/contract/src/InitDocumentMapping.csx
core/Workflows/contract/src/RenderDocumentMapping.csx
core/Workflows/contract/src/NotifyDocumentReadyMapping.csx
core/Workflows/contract/src/NotifyDocumentApprovedMapping.csx
core/Workflows/contract/src/NotifyDocumentRejectedMapping.csx
core/Workflows/contract/src/IncrementReadyCountMapping.csx
core/Workflows/contract/src/IncrementApprovedCountMapping.csx
core/Workflows/contract/src/DocumentsLoadedRule.csx
core/Workflows/contract/src/NoDocumentsRule.csx
core/Workflows/contract/src/HasMoreDocumentsRule.csx
core/Workflows/contract/src/AllDocumentsReadyRule.csx
core/Workflows/contract/src/MoreApprovalsPendingRule.csx
core/Workflows/contract/src/AllApprovedRule.csx
core/Workflows/contract/src/RenderSuccessRule.csx
core/Workflows/contract/src/RenderFailedRule.csx
core/Workflows/contract/src/AlwaysTrueRule.csx
Define contract-related workflow tasks to integrate with Mockoon APIs and parent/child workflows.
  • Add HTTP-based tasks for contract document retrieval and rendering, aligned with Mockoon API payloads.
  • Add DirectTrigger and SubProcess tasks for notifying parent workflows about document status and starting document subprocesses.
core/Tasks/contract/get-contract-documents.json
core/Tasks/contract/render-document.json
core/Tasks/contract/start-document-subprocess.json
core/Tasks/contract/notify-document-ready.json
core/Tasks/contract/notify-document-approved.json
Introduce task-test workflows and mappings to exercise Dapr, HTTP, workflow orchestration, config and secret access.
  • Create main task-test workflow and subflow JSON definitions, HTTP example, and diagrams to cover multiple task types.
  • Implement mapping scripts for HTTP, Dapr PubSub, Dapr service invocation, ScriptTask, GetInstanceData, DirectTrigger, StartTask, SubProcess, and TaskResponse usage.
  • Add helper mappings for initial state seeding plus config and secret retrieval demos.
  • Define corresponding task JSONs for each test case.
core/Workflows/task-test/task-test-workflow.json
core/Workflows/task-test/task-test-subflow.json
core/Workflows/task-test/task-test-workflow.http
core/Workflows/task-test/.meta/task-test-workflow.diagram.json
core/Workflows/task-test/.meta/task-test-subflow.diagram.json
core/Workflows/task-test/src/InitialTransitionMapping.csx
core/Workflows/task-test/src/HttpTaskMapping.csx
core/Workflows/task-test/src/HttpTaskItemsMapping.csx
core/Workflows/task-test/src/DaprPubSubMapping.csx
core/Workflows/task-test/src/DaprServiceTaskMapping.csx
core/Workflows/task-test/src/ScriptTaskMapping.csx
core/Workflows/task-test/src/GetInstanceDataMapping.csx
core/Workflows/task-test/src/DirectTransitionMapping.csx
core/Workflows/task-test/src/StartWorkflowMapping.csx
core/Workflows/task-test/src/SubProcessMapping.csx
core/Workflows/task-test/src/GetConfigValueMapping.csx
core/Workflows/task-test/src/GetSecretAsyncMapping.csx
core/Workflows/task-test/src/TaskResponseUsageMapping.csx
core/Workflows/task-test/src/AlwaysTrueRule.csx
core/Tasks/task-test/test-http-task.json
core/Tasks/task-test/test-http-items.json
core/Tasks/task-test/test-dapr-pubsub.json
core/Tasks/task-test/test-dapr-service-task.json
core/Tasks/task-test/test-get-instance-data.json
core/Tasks/task-test/test-direct-transition.json
core/Tasks/task-test/test-start-workflow.json
core/Tasks/task-test/test-subprocess.json
Adjust existing account-opening and payments workflows for new state shapes and tooling support.
  • Update account-opening workflow JSON, its extension state, and related tasks (e.g., get-data-from-workflow, trigger-scheduled-payments) to align with new state/contract structures.
  • Add HTTP examples and diagram metadata for account-opening and scheduled-payments workflows.
  • Update payment notification subflow definition to be consistent with new patterns.
core/Extensions/account-opening/extension-user-session.json
core/Tasks/account-opening/get-data-from-workflow.json
core/Tasks/account-opening/trigger-scheduled-payments.json
core/Workflows/account-opening/account-opening-workflow.json
core/Workflows/account-opening/.meta/account-opening-workflow.diagram.json
core/Workflows/account-opening/account-opening-workflow.http
core/Workflows/payments/payment-notification-subflow.json
core/Workflows/payments/.meta/payment-notification-subflow.diagram.json
core/Workflows/payments/scheduled-payments-workflow.http
Update tooling/configuration artifacts and clean up obsolete OAuth workflow code.
  • Extend .gitignore to exclude ai-docs/ artifacts.
  • Align Mockoon migration API and Postman collection with the new contract/task-test endpoints and payloads.
  • Remove unused OAuth workflow rules and associated HTTP upload script.
  • Add HTTP example for oauth-authentication workflow while dropping old rule scripts.
.gitignore
mockoon/migration-api.json
postman/vNext Example Runtime.postman_collection.json
core/Workflows/oauth/oauth-authentication-workflow.http
core/Workflows/oauth/src/PushDeniedRule.csx
core/Workflows/oauth/src/PushPendingContinueRule.csx
mockoon/upload-to-mockoon.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link

coderabbitai bot commented Dec 15, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This PR introduces a comprehensive contract approval workflow system featuring multilingual state machines, document processing subflows, and conditional rule-based transitions. It updates existing account-opening and payment workflows with state type modifications, adds extensive task test configurations across multiple task types (HTTP, Dapr, scripting), and updates mock API endpoints and test collections.

Changes

Cohort / File(s) Summary
Contract Approval Workflow System
core/Workflows/contract/contract-approval-workflow.json, core/Workflows/contract/contract-document-subflow.json, core/Workflows/contract/.meta/contract-approval-workflow.diagram.json, core/Workflows/contract/.meta/contract-document-subflow.diagram.json
New contract approval workflow with multilingual labels, document fetching, processing per-document subflows, and approval tracking. Includes document rendering, approval/rejection handlers, and state transition rules.
Contract Workflow Rules & Mappings
core/Workflows/contract/src/AllApprovedRule.csx, AllDocumentsReadyRule.csx, AlwaysTrueRule.csx, DocumentsLoadedRule.csx, HasMoreDocumentsRule.csx, MoreApprovalsPendingRule.csx, NoDocumentsRule.csx, RenderFailedRule.csx, RenderSuccessRule.csx
Condition rules for document approval workflow transitions: tracks approval/readiness counts, validates document loads, and determines multi-document processing completion.
Contract Workflow Data Mappings
core/Workflows/contract/src/GetContractDocumentsMapping.csx, InitContractApprovalMapping.csx, InitDocumentMapping.csx, IncrementApprovedCountMapping.csx, IncrementReadyCountMapping.csx, NotifyDocumentApprovedMapping.csx, NotifyDocumentReadyMapping.csx, NotifyDocumentRejectedMapping.csx, RenderDocumentMapping.csx, StartDocumentSubprocessMapping.csx
Input/output handlers for HTTP document retrieval, document rendering, approval notifications to parent workflow, document subprocess orchestration, and approval count increments.
Contract Task Definitions
core/Tasks/contract/get-contract-documents.json, notify-document-approved.json, notify-document-ready.json, render-document.json, start-document-subprocess.json
Task configuration files for document retrieval HTTP endpoint, document rendering, and approval/ready notifications with direct-trigger type support.
Account-Opening Updates
core/Workflows/account-opening/account-opening-workflow.json, core/Workflows/account-opening/account-opening-workflow.http, core/Workflows/account-opening/.meta/account-opening-workflow.diagram.json, core/Extensions/account-opening/extension-user-session.json, core/Tasks/account-opening/get-data-from-workflow.json, core/Tasks/account-opening/trigger-scheduled-payments.json
Modified state types (1→2) for account-details-input and account-confirmation states; updated task config fields (removed empty instanceId, renamed key→flow); added workflow diagram and HTTP test file.
Task-Test Workflow System
core/Workflows/task-test/task-test-workflow.json, core/Workflows/task-test/task-test-subflow.json, core/Workflows/task-test/task-test-workflow.http, core/Workflows/task-test/.meta/task-test-workflow.diagram.json, core/Workflows/task-test/.meta/task-test-subflow.diagram.json
Comprehensive workflow testing suite covering multiple task types, state definitions, and test flow orchestration with diagram metadata.
Task-Test Mappings & Rules
core/Workflows/task-test/src/AlwaysTrueRule.csx, DaprPubSubMapping.csx, DaprServiceTaskMapping.csx, DirectTransitionMapping.csx, GetConfigValueMapping.csx, GetInstanceDataMapping.csx, GetSecretAsyncMapping.csx, HttpTaskItemsMapping.csx, HttpTaskMapping.csx, InitialTransitionMapping.csx, ScriptTaskMapping.csx, StartWorkflowMapping.csx, SubProcessMapping.csx, TaskResponseUsageMapping.csx
Task mapping implementations for testing HTTP requests, Dapr services/pub-sub, script execution, workflow instance data retrieval, subprocess launching, and inter-workflow transitions.
Task-Test Task Definitions
core/Tasks/task-test/test-dapr-pubsub.json, test-dapr-service-task.json, test-direct-transition.json, test-get-instance-data.json, test-http-items.json, test-http-task.json, test-start-workflow.json, test-subprocess.json
Task configurations for testing Dapr pub/sub, service invocation, HTTP requests, direct transitions, and subprocess execution.
Payment Workflow Updates
core/Workflows/payments/payment-notification-subflow.json, core/Workflows/payments/scheduled-payments-workflow.http, core/Workflows/payments/.meta/payment-notification-subflow.diagram.json
Modified state type (1→2) for send-notifications state; added HTTP test file and diagram metadata for payment notification subflow.
OAuth Workflow
core/Workflows/oauth/oauth-authentication-workflow.http, core/Workflows/oauth/src/PushDeniedRule.csx, core/Workflows/oauth/src/PushPendingContinueRule.csx
Added OAuth2 authentication test file; removed MFA-related condition rules (PushDeniedRule, PushPendingContinueRule).
Mock & Test Configuration
mockoon/migration-api.json, mockoon/upload-to-mockoon.sh, postman/vNext Example Runtime.postman_collection.json, .gitignore
Updated Mockoon API routes (contract endpoint renaming, new task-test routes); removed upload script; extensive Postman collection restructuring with new flows, state endpoints, and test harness; .gitignore cleanup for ai-docs/ folder.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Client
    participant ContractApprovalWF as Contract Approval<br/>Workflow
    participant DocStore as Document<br/>API
    participant DocSubflow as Document<br/>Subflow
    participant Approver as Approver<br/>System

    User->>Client: Start contract approval
    Client->>ContractApprovalWF: POST /start
    ContractApprovalWF->>ContractApprovalWF: Initialize state,<br/>counters

    ContractApprovalWF->>DocStore: GET documents
    DocStore-->>ContractApprovalWF: Return documents[]
    ContractApprovalWF->>ContractApprovalWF: Set totalDocuments,<br/>currentIndex=0

    loop For each document
        ContractApprovalWF->>DocSubflow: Start subprocess
        Note over DocSubflow: Document Instance
        
        DocSubflow->>DocStore: POST render-document
        DocStore-->>DocSubflow: Return URL, metadata
        DocSubflow->>DocSubflow: Update renderStatus
        
        DocSubflow->>ContractApprovalWF: Notify document-ready
        ContractApprovalWF->>ContractApprovalWF: Increment readyCount
        
        Approver->>DocSubflow: Approve/Reject document
        alt Document Approved
            DocSubflow->>ContractApprovalWF: Notify document-approved
            ContractApprovalWF->>ContractApprovalWF: Increment approvedCount
            DocSubflow->>DocSubflow: End (completed)
        else Document Rejected
            DocSubflow->>ContractApprovalWF: Notify document-rejected
            ContractApprovalWF->>ContractApprovalWF: Increment rejectedCount
            DocSubflow->>DocSubflow: End (rejected)
        end
        
        ContractApprovalWF->>ContractApprovalWF: Increment currentIndex
    end

    alt All approved
        ContractApprovalWF->>ContractApprovalWF: State → contract-completed
    else Some rejected
        ContractApprovalWF->>ContractApprovalWF: State → contract-rejected
    end

    ContractApprovalWF-->>Client: Return final state
    Client-->>User: Show result
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Areas requiring extra attention:

  • Contract approval workflow logic (contract-approval-workflow.json): Complex multi-state machine with nested mappings, subprocess orchestration, and document tracking counters; verify state transitions, rule conditions, and data flow through approval cycle
  • Document subflow orchestration (contract-document-subflow.json, StartDocumentSubprocessMapping.csx): Subprocess creation, parent instance linking, and bidirectional notification handling between parent and child workflows
  • Rule evaluation consistency (AllApprovedRule, AllDocumentsReadyRule, HasMoreDocumentsRule, etc.): Ensure counter logic correctly tracks document states and prevents off-by-one or uninitialized value errors
  • Data mapping and inter-workflow communication (NotifyDocumentApprovedMapping, NotifyDocumentReadyMapping, etc.): Verify request/response payloads, field mappings, and error handling across workflow boundaries
  • Task-test workflow comprehensiveness (task-test-workflow.json + 14 mapping files): Large interconnected test system; verify all task types map correctly and test scenarios validate expected behaviors
  • Postman collection restructuring (vNext Example Runtime.postman_collection.json): Large JSON diff with URL path changes, query parameter alterations, and payload updates; cross-check against actual endpoint implementations for consistency

Possibly Related PRs

  • vnext-example#1: Touches same account-opening task configuration files (get-data-from-workflow.json, trigger-scheduled-payments.json) with compatible field adjustments and state modifications; may provide context for related changes

Suggested Reviewers

  • middt

Poem

🐰 Contracts flow through workflows now,
Documents cascade with rules of how,
States approve and substeps test,
A hoppy hop through vNext's quest!

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch f/sprint24

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 483da54 and bce9141.

📒 Files selected for processing (72)
  • .gitignore (1 hunks)
  • core/Extensions/account-opening/extension-user-session.json (1 hunks)
  • core/Tasks/account-opening/get-data-from-workflow.json (1 hunks)
  • core/Tasks/account-opening/trigger-scheduled-payments.json (1 hunks)
  • core/Tasks/contract/get-contract-documents.json (1 hunks)
  • core/Tasks/contract/notify-document-approved.json (1 hunks)
  • core/Tasks/contract/notify-document-ready.json (1 hunks)
  • core/Tasks/contract/render-document.json (1 hunks)
  • core/Tasks/contract/start-document-subprocess.json (1 hunks)
  • core/Tasks/task-test/test-dapr-pubsub.json (1 hunks)
  • core/Tasks/task-test/test-dapr-service-task.json (1 hunks)
  • core/Tasks/task-test/test-direct-transition.json (1 hunks)
  • core/Tasks/task-test/test-get-instance-data.json (1 hunks)
  • core/Tasks/task-test/test-http-items.json (1 hunks)
  • core/Tasks/task-test/test-http-task.json (1 hunks)
  • core/Tasks/task-test/test-start-workflow.json (1 hunks)
  • core/Tasks/task-test/test-subprocess.json (1 hunks)
  • core/Workflows/account-opening/.meta/account-opening-workflow.diagram.json (1 hunks)
  • core/Workflows/account-opening/account-opening-workflow.http (1 hunks)
  • core/Workflows/account-opening/account-opening-workflow.json (2 hunks)
  • core/Workflows/contract/.meta/contract-approval-workflow.diagram.json (1 hunks)
  • core/Workflows/contract/.meta/contract-document-subflow.diagram.json (1 hunks)
  • core/Workflows/contract/contract-approval-workflow.http (1 hunks)
  • core/Workflows/contract/contract-approval-workflow.json (1 hunks)
  • core/Workflows/contract/contract-document-subflow.json (1 hunks)
  • core/Workflows/contract/src/AllApprovedRule.csx (1 hunks)
  • core/Workflows/contract/src/AllDocumentsReadyRule.csx (1 hunks)
  • core/Workflows/contract/src/AlwaysTrueRule.csx (1 hunks)
  • core/Workflows/contract/src/DocumentsLoadedRule.csx (1 hunks)
  • core/Workflows/contract/src/GetContractDocumentsMapping.csx (1 hunks)
  • core/Workflows/contract/src/HasMoreDocumentsRule.csx (1 hunks)
  • core/Workflows/contract/src/IncrementApprovedCountMapping.csx (1 hunks)
  • core/Workflows/contract/src/IncrementReadyCountMapping.csx (1 hunks)
  • core/Workflows/contract/src/InitContractApprovalMapping.csx (1 hunks)
  • core/Workflows/contract/src/InitDocumentMapping.csx (1 hunks)
  • core/Workflows/contract/src/MoreApprovalsPendingRule.csx (1 hunks)
  • core/Workflows/contract/src/NoDocumentsRule.csx (1 hunks)
  • core/Workflows/contract/src/NotifyDocumentApprovedMapping.csx (1 hunks)
  • core/Workflows/contract/src/NotifyDocumentReadyMapping.csx (1 hunks)
  • core/Workflows/contract/src/NotifyDocumentRejectedMapping.csx (1 hunks)
  • core/Workflows/contract/src/RenderDocumentMapping.csx (1 hunks)
  • core/Workflows/contract/src/RenderFailedRule.csx (1 hunks)
  • core/Workflows/contract/src/RenderSuccessRule.csx (1 hunks)
  • core/Workflows/contract/src/StartDocumentSubprocessMapping.csx (1 hunks)
  • core/Workflows/oauth/oauth-authentication-workflow.http (1 hunks)
  • core/Workflows/oauth/src/PushDeniedRule.csx (0 hunks)
  • core/Workflows/oauth/src/PushPendingContinueRule.csx (0 hunks)
  • core/Workflows/payments/.meta/payment-notification-subflow.diagram.json (1 hunks)
  • core/Workflows/payments/payment-notification-subflow.json (1 hunks)
  • core/Workflows/payments/scheduled-payments-workflow.http (1 hunks)
  • core/Workflows/task-test/.meta/task-test-subflow.diagram.json (1 hunks)
  • core/Workflows/task-test/.meta/task-test-workflow.diagram.json (1 hunks)
  • core/Workflows/task-test/src/AlwaysTrueRule.csx (1 hunks)
  • core/Workflows/task-test/src/DaprPubSubMapping.csx (1 hunks)
  • core/Workflows/task-test/src/DaprServiceTaskMapping.csx (1 hunks)
  • core/Workflows/task-test/src/DirectTransitionMapping.csx (1 hunks)
  • core/Workflows/task-test/src/GetConfigValueMapping.csx (1 hunks)
  • core/Workflows/task-test/src/GetInstanceDataMapping.csx (1 hunks)
  • core/Workflows/task-test/src/GetSecretAsyncMapping.csx (1 hunks)
  • core/Workflows/task-test/src/HttpTaskItemsMapping.csx (1 hunks)
  • core/Workflows/task-test/src/HttpTaskMapping.csx (1 hunks)
  • core/Workflows/task-test/src/InitialTransitionMapping.csx (1 hunks)
  • core/Workflows/task-test/src/ScriptTaskMapping.csx (1 hunks)
  • core/Workflows/task-test/src/StartWorkflowMapping.csx (1 hunks)
  • core/Workflows/task-test/src/SubProcessMapping.csx (1 hunks)
  • core/Workflows/task-test/src/TaskResponseUsageMapping.csx (1 hunks)
  • core/Workflows/task-test/task-test-subflow.json (1 hunks)
  • core/Workflows/task-test/task-test-workflow.http (1 hunks)
  • core/Workflows/task-test/task-test-workflow.json (1 hunks)
  • mockoon/migration-api.json (5 hunks)
  • mockoon/upload-to-mockoon.sh (0 hunks)
  • postman/vNext Example Runtime.postman_collection.json (21 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @yilmaztayfun, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the system's workflow capabilities by introducing a new contract approval process and a robust testing framework for various task types. The contract workflow streamlines document management, while the task-test workflow provides valuable examples and validation for integration with Dapr, HTTP services, and inter-workflow communication. These additions enhance both business process automation and the maintainability of the workflow system.

Highlights

  • New Contract Approval Workflow: Introduced a comprehensive contract approval workflow (contract-approval-workflow) and its associated subflow (contract-document-subflow). This includes new tasks for fetching, rendering, approving, and rejecting documents, along with C# mapping and rule scripts to manage the process and communicate with external services.
  • New Task Test Workflow: Added a dedicated workflow (task-test-workflow) and a helper subflow (task-test-subflow) to demonstrate and test various task types. This includes examples for Dapr PubSub, Dapr Service Invocation, HTTP tasks, script tasks, and different workflow communication patterns like starting new instances, getting instance data, and direct transitions.
  • Updated Account Opening Workflow: Modified the existing account opening workflow to adjust state types for 'account-details-input' and 'account-confirmation' states, and refined configurations for related tasks.
  • Removed Obsolete OAuth Workflow Scripts: Cleaned up the OAuth workflow by removing two obsolete C# rule scripts, PushDeniedRule.csx and PushPendingContinueRule.csx.
  • Mockoon and Postman Updates: The Mockoon API environment has been updated with new endpoints for contract and task-test functionalities, and the Postman collection has been revised to include new test requests for the contract and task-test workflows, alongside minor adjustments to existing requests.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Several mappings (e.g. GetContractDocumentsMapping, StartDocumentSubprocessMapping, IncrementApprovedCountMapping, etc.) cast dynamic values with (int)(context.Instance?.Data?... ?? 0), which will throw if the underlying value is not exactly an int; consider using Convert.ToInt32 with null/format checks or pattern matching to make these conversions more robust.
  • Some condition rules and mappings swallow exceptions by returning a default boolean (e.g. AllApprovedRule returns true on error, NoDocumentsRule returns true on error); you may want to either log these failures or choose a safer default (typically false) so that unexpected data does not silently drive transitions.
  • A few handlers are declared async but never await (e.g. many OutputHandler implementations), and there is duplicated HTTP/Dapr setup logic between mappings (HttpTaskMapping vs HttpTaskItemsMapping, several DirectTriggerTask usages); consider either removing async where unnecessary or extracting shared helpers to reduce duplication and make the behavior easier to maintain.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Several mappings (e.g. GetContractDocumentsMapping, StartDocumentSubprocessMapping, IncrementApprovedCountMapping, etc.) cast dynamic values with `(int)(context.Instance?.Data?... ?? 0)`, which will throw if the underlying value is not exactly an int; consider using `Convert.ToInt32` with null/format checks or pattern matching to make these conversions more robust.
- Some condition rules and mappings swallow exceptions by returning a default boolean (e.g. AllApprovedRule returns true on error, NoDocumentsRule returns true on error); you may want to either log these failures or choose a safer default (typically false) so that unexpected data does not silently drive transitions.
- A few handlers are declared `async` but never `await` (e.g. many `OutputHandler` implementations), and there is duplicated HTTP/Dapr setup logic between mappings (HttpTaskMapping vs HttpTaskItemsMapping, several DirectTriggerTask usages); consider either removing `async` where unnecessary or extracting shared helpers to reduce duplication and make the behavior easier to maintain.

## Individual Comments

### Comment 1
<location> `core/Workflows/contract/src/GetContractDocumentsMapping.csx:63-72` </location>
<code_context>
+                var contracts = response?.data?.data?.contracts ?? new object[] { };
</code_context>

<issue_to_address>
**issue (bug_risk):** Casting totalContracts to int directly can throw at runtime if the API returns a non-int numeric type.

Given `totalContracts` comes from `response?.data?.data?.totalContracts`, its runtime type depends on the Mockoon response. If it’s `long`, `double`, or a string, `(int)totalContracts` will raise `InvalidCastException` and hit the exception handler. Please switch to a safer approach (e.g., `Convert.ToInt32`, pattern matching, or a type check) and apply the same hardening to similar casts in the rules (e.g., `DocumentsLoadedRule`, `AllApprovedRule`).
</issue_to_address>

### Comment 2
<location> `core/Workflows/contract/src/DocumentsLoadedRule.csx:13-14` </location>
<code_context>
+    {
+        try
+        {
+            var totalDocuments = context.Instance?.Data?.totalDocuments ?? 0;
+            return (int)totalDocuments > 0;
+        }
+        catch (Exception)
</code_context>

<issue_to_address>
**issue (bug_risk):** Direct cast of totalDocuments to int in a dynamic context may cause exceptions and force the rule’s fallback behavior.

Since `context.Instance?.Data` is effectively dynamic, `totalDocuments` may not actually be an `int` at runtime (it could be `long`, `string`, etc.). The direct `(int)totalDocuments` cast would then throw and force the `catch` to return `false`. To avoid this unintended fallback, consider normalizing the value with something like `Convert.ToInt32` (and handling invalid formats) instead of a direct cast.
</issue_to_address>

### Comment 3
<location> `core/Workflows/contract/src/AllApprovedRule.csx:11-22` </location>
<code_context>
+    {
+        try
+        {
+            var approvedCount = (int)(context.Instance?.Data?.approvedCount ?? 0);
+            var totalDocuments = (int)(context.Instance?.Data?.totalDocuments ?? 0);
+            
+            // All approved when approved count equals total documents
+            return approvedCount >= totalDocuments;
+        }
+        catch (Exception)
</code_context>

<issue_to_address>
**suggestion (bug_risk):** The rule returns true on any exception, which may prematurely signal that all documents are approved.

Because the `catch` block returns `true`, any data or casting issue (e.g., when reading `approvedCount` / `totalDocuments`) will incorrectly treat the state as "all approved". For a critical transition, consider a safer default (e.g., `false`) or explicitly distinguishing data errors from the valid "all approved" case.

```suggestion
        try
        {
            var approvedCount = (int)(context.Instance?.Data?.approvedCount ?? 0);
            var totalDocuments = (int)(context.Instance?.Data?.totalDocuments ?? 0);

            // All approved when approved count equals total documents
            // NOTE: If there's any data/casting issue, we fall back to "not all approved" in the catch block.
            return approvedCount >= totalDocuments;
        }
        catch (Exception)
        {
            // Safer default: on any data or casting error, do NOT treat as "all approved"
            return false;
        }
```
</issue_to_address>

### Comment 4
<location> `core/Workflows/task-test/src/GetConfigValueMapping.csx:62` </location>
<code_context>
+                Key = "get-config-success",
+                Data = new
+                {
+                    getConfigResult = new
+                    {
+                        success = true,
</code_context>

<issue_to_address>
**issue (testing):** Config test output does not reflect whether the config value was actually retrieved

Here `success` is always set to `true`, even though the input handler derives a `configRetrieved` flag from `apiBaseUrl`. This means tests will pass even when the config is missing or invalid. Consider propagating `configRetrieved` into the instance data (or tags) and using it to set `success` and choose the response key (`get-config-success` vs `get-config-failed`). Optionally expose `configRetrieved` in the output payload so callers can assert on it directly.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +63 to +72
var contracts = response?.data?.data?.contracts ?? new object[] { };
var contractList = new List<object>();

if (contracts != null)
{
foreach (var contract in contracts)
{
contractList.Add(contract);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Casting totalContracts to int directly can throw at runtime if the API returns a non-int numeric type.

Given totalContracts comes from response?.data?.data?.totalContracts, its runtime type depends on the Mockoon response. If it’s long, double, or a string, (int)totalContracts will raise InvalidCastException and hit the exception handler. Please switch to a safer approach (e.g., Convert.ToInt32, pattern matching, or a type check) and apply the same hardening to similar casts in the rules (e.g., DocumentsLoadedRule, AllApprovedRule).

Comment on lines +13 to +14
var totalDocuments = context.Instance?.Data?.totalDocuments ?? 0;
return (int)totalDocuments > 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Direct cast of totalDocuments to int in a dynamic context may cause exceptions and force the rule’s fallback behavior.

Since context.Instance?.Data is effectively dynamic, totalDocuments may not actually be an int at runtime (it could be long, string, etc.). The direct (int)totalDocuments cast would then throw and force the catch to return false. To avoid this unintended fallback, consider normalizing the value with something like Convert.ToInt32 (and handling invalid formats) instead of a direct cast.

Comment on lines +11 to +22
try
{
var approvedCount = (int)(context.Instance?.Data?.approvedCount ?? 0);
var totalDocuments = (int)(context.Instance?.Data?.totalDocuments ?? 0);

// All approved when approved count equals total documents
return approvedCount >= totalDocuments;
}
catch (Exception)
{
return true;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): The rule returns true on any exception, which may prematurely signal that all documents are approved.

Because the catch block returns true, any data or casting issue (e.g., when reading approvedCount / totalDocuments) will incorrectly treat the state as "all approved". For a critical transition, consider a safer default (e.g., false) or explicitly distinguishing data errors from the valid "all approved" case.

Suggested change
try
{
var approvedCount = (int)(context.Instance?.Data?.approvedCount ?? 0);
var totalDocuments = (int)(context.Instance?.Data?.totalDocuments ?? 0);
// All approved when approved count equals total documents
return approvedCount >= totalDocuments;
}
catch (Exception)
{
return true;
}
try
{
var approvedCount = (int)(context.Instance?.Data?.approvedCount ?? 0);
var totalDocuments = (int)(context.Instance?.Data?.totalDocuments ?? 0);
// All approved when approved count equals total documents
// NOTE: If there's any data/casting issue, we fall back to "not all approved" in the catch block.
return approvedCount >= totalDocuments;
}
catch (Exception)
{
// Safer default: on any data or casting error, do NOT treat as "all approved"
return false;
}

Key = "get-config-success",
Data = new
{
getConfigResult = new
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (testing): Config test output does not reflect whether the config value was actually retrieved

Here success is always set to true, even though the input handler derives a configRetrieved flag from apiBaseUrl. This means tests will pass even when the config is missing or invalid. Consider propagating configRetrieved into the instance data (or tags) and using it to set success and choose the response key (get-config-success vs get-config-failed). Optionally expose configRetrieved in the output payload so callers can assert on it directly.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant new functionality with contract approval and task-testing workflows. The changes are extensive and well-structured. My review focuses on improving configuration management, enhancing code clarity and maintainability, and fixing a few potential bugs related to state management, error handling, and script encoding. I've identified several instances of hardcoded configuration values that should be externalized, a critical issue with an incorrectly encoded C# script, and some unsafe error handling in rule scripts. Addressing these points will improve the robustness and flexibility of the new workflows.

Comment on lines +590 to +594
"mapping": {
"location": "./src/StartWorkflowMapping.csx",
"code": "using System;\nusing System.Threading.Tasks;\nusing BBT.Workflow.Definitions;\nusing BBT.Workflow.Scripting;\n\n/// <summary>\n/// Start Workflow Task Mapping - Starts a new workflow instance\n/// Test case: Verify starting new workflow instances\n/// </summary>\npublic class StartWorkflowMapping : IMapping\n{\n public Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)\n {\n try\n {\n var startTask = task as StartTask;\n if (startTask == null)\n {\n throw new InvalidOperationException(\"Task must be a StartTask\");\n }\n\n // Configure target workflow\n startTask.SetDomain(\"core\");\n startTask.SetFlow(\"task-test-subflow\");\n startTask.SetSync(true);\n startTask.SetVersion(\"1.0.0\");\n startTask.SetKey(Guid.NewGuid().ToString());\n startTask.SetTags(new[] { \"task-test\", \"start-workflow\", \"success\" });\n \n // Prepare initialization body\n var initBody = new\n {\n parentInstanceId = context.Instance?.Id,\n parentWorkflowId = context.Workflow?.Key,\n testId = context.Instance?.Data?.testId ?? Guid.NewGuid().ToString(),\n startedAt = DateTime.UtcNow,\n startedBy = \"task-test-workflow\",\n message = \"StartTask test - new instance created\"\n };\n startTask.SetBody(initBody);\n\n return Task.FromResult(new ScriptResponse());\n }\n catch (Exception ex)\n {\n return Task.FromResult(new ScriptResponse\n {\n Key = \"start-workflow-input-error\",\n Data = new { error = ex.Message }\n });\n }\n }\n\n public async Task<ScriptResponse> OutputHandler(ScriptContext context)\n {\n try\n {\n var response = context.Body;\n\n if (response?.isSuccess == true)\n {\n return new ScriptResponse\n {\n Key = \"start-workflow-success\",\n Data = new\n {\n startWorkflowResult = new\n {\n success = true,\n newInstanceId = response?.data?.id,\n status = response?.data?.status,\n startedAt = DateTime.UtcNow,\n taskType = \"Start\"\n },\n // Store instance ID for later use\n subflowInstanceId = response?.data?.id\n },\n Tags = new[] { \"task-test\", \"start-workflow\", \"success\" }\n };\n }\n\n return new ScriptResponse\n {\n Key = \"start-workflow-failed\",\n Data = new\n {\n startWorkflowResult = new\n {\n success = false,\n error = response?.errorMessage ?? \"Failed to start workflow\",\n failedAt = DateTime.UtcNow,\n taskType = \"Start\"\n }\n },\n Tags = new[] { \"task-test\", \"start-workflow\", \"failed\" }\n };\n }\n catch (Exception ex)\n {\n return new ScriptResponse\n {\n Key = \"start-workflow-exception\",\n Data = new\n {\n startWorkflowResult = new\n {\n success = false,\n error = ex.Message,\n taskType = \"Start\"\n }\n }\n };\n }\n }\n}",
"encoding": "NAT"
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The code for StartWorkflowMapping.csx is not Base64 encoded, and an encoding: "NAT" property has been added. This is inconsistent with all other script mappings in the project and will cause a parsing error at runtime. The C# code must be Base64 encoded and assigned to the code property, and the encoding property should be removed.

Comment on lines +19 to +22
catch (Exception)
{
return true;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The catch block swallows any exception and returns true. This is dangerous because it can cause the workflow to proceed incorrectly if there's an issue reading the instance data (e.g., a typo in a property name). The rule should fail safe by returning false.

        catch (Exception)
        {
            return false;
        }

{
"key": "account-details-input",
"stateType": 1,
"stateType": 2,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The stateType for account-details-input has been changed to 2 (System), but this state has a view defined and requires user interaction. A state with user interaction should have stateType: 1 (Interaction). This change will likely prevent the UI from being displayed for this step.

Suggested change
"stateType": 2,
"stateType": 1,

{
"key": "account-confirmation",
"stateType": 1,
"stateType": 2,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The stateType for account-confirmation has been changed to 2 (System). Since this state has a view and requires user confirmation, it should be an Interaction state (stateType: 1).

Suggested change
"stateType": 2,
"stateType": 1,

Comment on lines +19 to +22
catch (Exception)
{
return true;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The catch block returns true on any exception. This could cause the workflow to prematurely move to the next state, assuming all documents are ready when they might not be. It should return false to be safe.

        catch (Exception)
        {
            return false;
        }

{
"order": 1,
"task": {
"key": "notify-document-approved",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The task with key notify-document-approved is being reused in the notify-parent-rejected state. While the mapping script correctly sets the transition name to document-rejected, reusing a task with a name indicating approval for a rejection action is confusing and harms maintainability. A dedicated task definition for rejection, e.g., notify-document-rejected, should be created for clarity.

"attributes": {
"type": "6",
"config": {
"url": "http://localhost:3001/api/contract/get-documents",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The URL is hardcoded to localhost. This is not suitable for different environments (development, staging, production). It's better to retrieve this URL from a configuration source to allow for environment-specific endpoints.

var startTask = task as SubProcessTask;
if (startTask == null)
{
throw new InvalidOperationException("Task must be a StartTask");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The exception message is incorrect. The code checks for SubProcessTask but the error message refers to StartTask. This can be misleading during debugging.

                throw new InvalidOperationException("Task must be a SubProcessTask");

Comment on lines +1 to +119
using System;
using System.Threading.Tasks;
using BBT.Workflow.Definitions;
using BBT.Workflow.Scripting;

/// <summary>
/// HTTP Task Mapping - Makes external API calls
/// Test case: Verify HTTP requests to external services via Mockoon
/// </summary>
public class HttpTaskItemsMapping : IMapping
{
public Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
{
try
{
var httpTask = task as HttpTask;
if (httpTask == null)
{
throw new InvalidOperationException("Task must be an HttpTask");
}

// Prepare request body
var requestBody = new
{
testId = context.Instance?.Data?.testId ?? Guid.NewGuid().ToString(),
workflowId = context.Workflow.Key,
instanceId = context.Instance?.Id,
timestamp = DateTime.UtcNow,
action = "http-task-test"
};

httpTask.SetBody(requestBody);

// Set headers
var headers = new Dictionary<string, string?>
{
["Content-Type"] = "application/json",
["X-Test-Id"] = context.Instance?.Data?.testId?.ToString(),
["X-Request-Id"] = Guid.NewGuid().ToString(),
["X-Correlation-Id"] = context.Instance.Id.ToString()
};
httpTask.SetHeaders(headers);

return Task.FromResult(new ScriptResponse());
}
catch (Exception ex)
{
return Task.FromResult(new ScriptResponse
{
Key = "http-task-input-error",
Data = new { error = ex.Message }
});
}
}

public async Task<ScriptResponse> OutputHandler(ScriptContext context)
{
try
{
var response = context.Body;
var statusCode = response?.statusCode ?? 500;

if (statusCode >= 200 && statusCode < 300)
{
return new ScriptResponse
{
Key = "http-task-success",
Data = new
{
httpTaskItemsResult = new
{
success = true,
statusCode = statusCode,
data = response?.data,
executionTime = response?.executionDurationMs,
processedAt = DateTime.UtcNow,
taskType = "HttpTask"
}
},
Tags = new[] { "task-test", "http-task", "success" }
};
}

return new ScriptResponse
{
Key = "http-task-failed",
Data = new
{
httpTaskItemsResult = new
{
success = false,
statusCode = statusCode,
error = response?.errorMessage ?? "HTTP request failed",
failedAt = DateTime.UtcNow,
taskType = "HttpTask"
}
},
Tags = new[] { "task-test", "http-task", "failed" }
};
}
catch (Exception ex)
{
return new ScriptResponse
{
Key = "http-task-exception",
Data = new
{
httpTaskItemsResult = new
{
success = false,
error = ex.Message,
taskType = "HttpTask"
}
}
};
}
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This mapping script is almost identical to HttpTaskMapping.csx. The only significant difference is the key used in the output data (httpTaskItemsResult vs httpTaskResult). This code duplication makes maintenance harder. Consider creating a single, more generic mapping script that can be used for both HTTP tasks.

"attributes": {
"type": "6",
"config": {
"url": "http://localhost:3001/api/contract/render-document",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The URL is hardcoded to localhost. This should be made configurable to support different environments. Hardcoding URLs makes it difficult to deploy and test the application in different stages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants