Skip to content

Deal Type Specification v1.3

Document Purpose: Define the complete structure, semantics, and usage of Deal Types in the Deal Engine architecture revision.

Status: Draft for review

Version: 1.3


1. Overview

1.1 What is a Deal Type?

A Deal Type is a template that guides deal composition by defining:

  • Deal-level schema (parties, dates, territory)
  • Commonly-used clause types for that deal category
  • Deal-level logic for cross-clause aggregation

Deal Types are suggestions, not constraints. They accelerate deal creation by providing sensible defaults, but users can freely deviate—adding clause types, omitting suggestions, or substituting alternatives.

1.2 Deal Type vs. Deal Instance

AspectDeal TypeDeal Instance
PurposeTemplate for creating dealsActual contract
StorageDesign-time catalogRuntime storage
SchemaDefines structureContains actual data
Clause TypesSuggests which to useContains copied logic + data
LogicProvides defaultsSelf-contained snapshot
Versioning**Catalog versioning (for new deals)Instance versioning (audit trail)

Note on versioning: Deal types and deal instances have separate versioning concerns. A deal type may have catalog versions (1.0.0, 1.1.0, 2.0.0) representing template evolution for future deals. A deal instance has its own version chain (1, 2, 3...) representing the runtime evolution of that specific contract through data changes and amendments. See Section 9.4 for details.

When a deal is created from a deal type:

  1. Deal-level schema is instantiated with actual values
  2. Selected clause types are copied (logic + schema) into the instance
  3. Deal-level logic is copied into the instance
  4. Any changes to deal-level logic create a new version of that deal instance
  5. The resulting deal instance has no runtime dependency on the catalog

1.3 The Guiding Principle

Deal Types follow the principle: Suggest, don't dictate.

Deal Type: "Music Touring"
├── Suggests: show-settlement clause
├── Suggests: tour-versus clause  
├── Suggests: travel-reimbursement clause
└── User decides which to include

A user creating a music touring deal might:

  • Use all suggested clause types as-is
  • Omit travel-reimbursement (not in this contract)
  • Add a merchandise clause (not suggested, but needed)
  • Modify show-settlement with custom logic
  • Start from scratch without using any suggestions

All paths are valid.


2. Deal Type Structure

A deal type consists of these sections:

deal_type {
  header { ... }           // Identity and classification
  schema { ... }           // Deal-level data structure
  suggested_clauses { ... } // Commonly-used clause types
  logic { ... }            // Deal-level aggregation and events
  outputs { ... }          // Deal-level computed values
}

2.1 Header Section

header {
  id: music-touring
  version: 1.0.0
  name: "Music Touring Deal"
  description: "Multi-show touring agreement with per-show settlement"
  department: music
  tags: [touring, live-events, settlement]
}
FieldRequiredDescription
idYesUnique identifier (kebab-case)
versionYesSemantic version (e.g., 1.0.0)
nameYesHuman-readable name
descriptionYesBrief description of deal category
departmentYesOrganizational department (music, film, sports, etc.)
tagsNoSearchable keywords

2.2 Schema Section

Defines the JSON Schema for deal-level data—information that applies to the entire deal, not specific clauses.

schema {
  type: object
  required: [parties, dates, currency]
  properties {
    
    // Parties to the deal (references Authoritative Data schemas)
    parties {
      type: object
      required: [talent, buyer]
      properties {
        talent { $ref: "authoritative://schemas/talent" }
        buyer { $ref: "authoritative://schemas/buyer" }
        agency { $ref: "authoritative://schemas/agency" }
      }
    }
    
    // Key dates
    dates {
      type: object
      required: [effective_date]
      properties {
        effective_date { type: string, format: date }
        term_start { type: string, format: date }
        term_end { type: string, format: date }
        execution_date { type: string, format: date }
      }
    }
    
    // Financial defaults
    currency { type: string, enum: [USD, EUR, GBP, CAD, AUD] }
    
    // Territory and exclusivity
    territory {
      type: object
      properties {
        primary { type: string }
        secondary { type: array, items: { type: string } }
        exclusions { type: array, items: { type: string } }
      }
    }
    
    // Deal-level metadata
    metadata {
      type: object
      properties {
        deal_id { type: string }
        created_at { type: string, format: date-time }
        created_by { type: string }
        status { type: string, enum: [draft, pending, active, completed, terminated] }
      }
    }
  }
}

Schema organization principles:

SectionPurposeExamples
partiesWho is involvedTalent, buyer, agency
datesWhenEffective date, term boundaries
currencyFinancial defaultsUSD, EUR
territoryWhereGeographic scope
metadataSystem fieldsDeal ID, status, audit info

2.3 Suggested Clauses Section

Lists clause types commonly used with this deal type. This is guidance, not requirement.

suggested_clauses {
  
  // Core compensation
  show_settlement {
    clause_type: show-settlement
    cardinality: one
    required: false
    description: "Per-show guarantee vs percentage settlement"
  }
  
  // Tour-level versus
  tour_versus {
    clause_type: versus-block
    cardinality: one
    required: false
    depends_on: [show_settlement]
    description: "Tour-level guarantee vs aggregate percentage"
  }
  
  // Travel and expenses
  travel_reimbursement {
    clause_type: reimbursement
    cardinality: many
    required: false
    description: "Travel expense reimbursement"
  }
  
  // Non-financial terms
  exclusivity {
    clause_type: exclusivity
    cardinality: one
    required: false
    description: "Category exclusivity terms"
  }
}
FieldRequiredDescription
clause_typeYesReference to clause type in catalog
cardinalityYesone or many (can multiple instances exist?)
requiredYesIs this clause type suggested as essential? (still not enforced)
depends_onNoOther clauses this one typically works with
descriptionYesWhy this clause type is suggested

Cardinality semantics:

CardinalityMeaningExample
oneTypically one instanceTour-level versus block
manyOften multiple instancesPer-show settlements, bonus groups

Note: required: true is a suggestion to the user, not an enforcement. The system will not prevent deal creation if a "required" clause is omitted.

2.4 Logic Section

Defines deal-level computations that aggregate across clause instances.

logic {
  
  // Deal-level events
  events {
    all_shows_settled {
      description: "All shows in the tour have been settled"
      condition: @show_settlement.all_settled ?? false
    }
    
    deal_complete {
      description: "All compensation finalized"
      condition: all_shows_settled && (@tour_versus.settled ?? true)
    }
  }
  
  // Deal-level computations
  computations {
    // Aggregate earnings across all clause instances
    var total_guaranteed = sum(
      @show_settlement.total_guarantee ?? 0,
      @tour_versus.tour_guarantee ?? 0
    )
    
    var total_earned = sum(
      @show_settlement.total_earned ?? 0,
      @tour_versus.versus_earned ?? 0,
      @travel_reimbursement[*].total ?? 0
    )
    
    var total_received = sum(
      @show_settlement.total_received ?? 0,
      @tour_versus.received ?? 0,
      @travel_reimbursement[*].received ?? 0
    )
    
    // Pending amounts
    var total_pending = total_earned - total_received
    
    // Final outputs
    output total_guaranteed
    output total_earned
    output total_received
    output total_pending
  }
}

Cross-clause reference syntax:

SyntaxMeaning
@clause_name.outputReference output from named clause
@clause_name[*].outputReference output from all instances (cardinality: many)

2.5 Outputs Section

Declares deal-level outputs available for reporting and downstream systems.

outputs {
  // Financial totals
  total_guaranteed: number
  total_earned: number
  total_received: number
  total_pending: number
  
  // Status
  deal_complete: boolean
}

3. Schema Inheritance and Composition

3.1 Authoritative Data Integration

Deal types reference schemas from the Authoritative Data system for master data entities. This ensures consistency across the agency and eliminates schema duplication.

Reference syntax:

$ref: "authoritative://schemas/talent"
$ref: "authoritative://schemas/buyer"
$ref: "authoritative://schemas/agency"
$ref: "authoritative://schemas/venue"

Example: Talent schema from Authoritative Data

// Provided by authoritative://schemas/talent
{
  type: object
  properties {
    id { type: string, description: "Authoritative Data ID" }
    name { type: string }
    legal_entity { type: string }
    representative { type: string }
    // Additional fields defined by Authoritative Data...
  }
}

3.2 Common Schema Patterns

Beyond Authoritative Data entities, deal types share common patterns for deal-specific structures:

Standard dates schema:

dates_schema {
  effective_date: date (required)
  term_start: date
  term_end: date
  execution_date: date
}

Standard territory schema:

territory_schema {
  primary: string
  secondary: array of string
  exclusions: array of string
}

3.3 Extension Pattern

Deal types can extend common patterns with deal-specific fields:

schema {
  // Include common patterns
  include: [dates_schema, territory_schema]
  
  // Reference Authoritative Data for parties
  properties {
    parties {
      talent { $ref: "authoritative://schemas/talent" }
      buyer { $ref: "authoritative://schemas/buyer" }
    }
    
    // Add deal-specific fields
    tour_info {
      type: object
      properties {
        tour_name { type: string }
        total_shows { type: integer }
        tour_region { type: string }
      }
    }
  }
}

3.4 Department-Specific Patterns

Different departments extend base patterns with specific needs:

DepartmentSpecific Schema ElementsAuthoritative Data Refs
MusicTour info, venue types, ticket pricingtalent, venue, promoter
FilmProduction info, release windowstalent, studio, distributor
SportsLeague info, team, seasonathlete, team, brand
FashionBrand info, product categoriestalent, brand, agency

4. Logic Patterns

4.1 Aggregation Across Clauses

The most common deal-level logic pattern: summing outputs from multiple clause instances.

logic {
  computations {
    // Sum from single instance
    var base_from_settlement = @show_settlement.total_earned ?? 0
    
    // Sum from multiple instances (cardinality: many)
    var bonus_total = sum(@bonus_groups[*].earned ?? 0)
    
    // Combined total
    output total_earned = base_from_settlement + bonus_total
  }
}

4.2 Conditional Aggregation

Filter clause outputs based on conditions:

logic {
  computations {
    // Only settled shows
    var settled_earnings = sum(
      @show_settlement.shows where show.settled == true,
      show.earned
    )
    
    // Only earnings (exclude reimbursements)
    var earnings_only = sum(
      @clauses where clause.value_type == "earning",
      clause.amount
    )
    
    output total_earnings = earnings_only
  }
}

4.3 Deal-Level Events

Events that depend on clause states:

logic {
  events {
    // All clause instances in settled state
    all_settled {
      description: "All financial clauses settled"
      condition: @show_settlement.all_settled 
             && (@tour_versus.settled ?? true)
    }
    
    // Revenue threshold crossed
    revenue_milestone {
      description: "Total earnings exceed milestone"
      condition: total_earned >= deal.metadata.revenue_milestone
    }
    
    // Compound event
    deal_can_close {
      description: "All conditions met to close deal"
      condition: all_settled && revenue_milestone
    }
  }
}

4.4 Value Type Aggregation

Aggregate by value type for downstream systems:

logic {
  computations {
    // Separate earnings from reimbursements
    var total_earnings = sum(
      @clauses where clause.value_type == "earning",
      clause.amount
    )
    
    var total_reimbursements = sum(
      @clauses where clause.value_type == "reimbursement",
      clause.amount
    )
    
    var total_third_party = sum(
      @clauses where clause.value_type == "third_party",
      clause.amount
    )
    
    output total_earnings
    output total_reimbursements
    output total_third_party
    output grand_total = total_earnings + total_reimbursements + total_third_party
  }
}

5. Complete Examples

5.1 Music Touring Deal Type

deal_type {
  header {
    id: music-touring
    version: 1.0.0
    name: "Music Touring Deal"
    description: "Multi-show touring agreement with per-show settlement and tour-level versus"
    department: music
    tags: [touring, live-events, settlement, versus]
  }
  
  schema {
    type: object
    required: [parties, dates, currency]
    properties {
      parties {
        type: object
        required: [talent, promoter]
        properties {
          talent { $ref: "authoritative://schemas/talent" }
          promoter { $ref: "authoritative://schemas/promoter" }
          agency { $ref: "authoritative://schemas/agency" }
        }
      }
      dates {
        type: object
        required: [effective_date]
        properties {
          effective_date { type: string, format: date }
          tour_start { type: string, format: date }
          tour_end { type: string, format: date }
        }
      }
      currency { type: string, default: USD }
      tour_info {
        type: object
        properties {
          tour_name { type: string }
          tour_region { type: string }
          headliner { type: boolean, default: true }
        }
      }
    }
  }
  
  suggested_clauses {
    show_settlement {
      clause_type: show-settlement
      cardinality: one
      required: true
      description: "Per-show guarantee vs percentage settlement for all tour dates"
    }
    
    tour_versus {
      clause_type: versus-block
      cardinality: one
      required: false
      depends_on: [show_settlement]
      description: "Tour-level guarantee vs aggregate box office percentage"
    }
    
    tour_bonus {
      clause_type: tiered-bonus
      cardinality: one
      required: false
      description: "Bonus tiers based on ticket sales or revenue thresholds"
    }
    
    travel_expenses {
      clause_type: reimbursement
      cardinality: many
      required: false
      description: "Travel, accommodation, and production expense reimbursement"
    }
    
    merchandise {
      clause_type: merchandise-split
      cardinality: one
      required: false
      description: "Merchandise revenue sharing"
    }
  }
  
  logic {
    events {
      all_shows_occurred {
        description: "All scheduled shows have occurred"
        condition: @show_settlement.all_occurred ?? false
      }
      
      all_shows_settled {
        description: "All shows have been settled with promoter"
        condition: @show_settlement.all_settled ?? false
      }
      
      tour_complete {
        description: "Tour fully settled including versus"
        condition: all_shows_settled && (@tour_versus.settled ?? true)
      }
    }
    
    computations {
      // Show-level aggregates
      var total_show_guarantees = @show_settlement.total_guarantee ?? 0
      var total_show_earned = @show_settlement.total_earned ?? 0
      
      // Tour-level versus
      var tour_guarantee = @tour_versus.tour_guarantee ?? 0
      var tour_versus_earned = @tour_versus.versus_earned ?? 0
      
      // Combined compensation
      var total_guaranteed = total_show_guarantees + tour_guarantee
      var total_earned = total_show_earned + tour_versus_earned
      
      // Add bonuses if present
      var bonus_earned = @tour_bonus.earned ?? 0
      var total_with_bonus = total_earned + bonus_earned
      
      // Receipts tracking
      var total_received = sum(
        @show_settlement.total_received ?? 0,
        @tour_versus.received ?? 0,
        @tour_bonus.received ?? 0
      )
      
      // Reimbursements (tracked separately by value_type)
      var total_reimbursements = sum(@travel_expenses[*].total ?? 0)
      
      // Outputs
      output total_guaranteed
      output total_earned = total_with_bonus
      output total_received
      output total_pending = total_earned - total_received
      output total_reimbursements
    }
  }
  
  outputs {
    total_guaranteed: number
    total_earned: number
    total_received: number
    total_pending: number
    total_reimbursements: number
    tour_complete: boolean
  }
}

5.2 Sports Endorsement Deal Type

deal_type {
  header {
    id: sports-endorsement
    version: 1.0.0
    name: "Sports Endorsement Deal"
    description: "Athlete endorsement with base compensation and performance bonuses"
    department: sports
    tags: [endorsement, athlete, bonuses, performance]
  }
  
  schema {
    type: object
    required: [parties, dates, currency, sport_info]
    properties {
      parties {
        type: object
        required: [talent, brand]
        properties {
          talent { $ref: "authoritative://schemas/athlete" }
          brand { $ref: "authoritative://schemas/brand" }
          agency { $ref: "authoritative://schemas/agency" }
        }
      }
      dates {
        type: object
        required: [effective_date, term_end]
        properties {
          effective_date { type: string, format: date }
          term_start { type: string, format: date }
          term_end { type: string, format: date }
        }
      }
      currency { type: string, default: USD }
      sport_info {
        type: object
        required: [sport, league]
        properties {
          sport { type: string }
          league { type: string }
          season { type: string }
        }
      }
      endorsement_scope {
        type: object
        properties {
          product_categories { type: array, items: { type: string } }
          usage_rights { type: array, items: { type: string } }
          appearance_obligations { type: integer }
        }
      }
    }
  }
  
  suggested_clauses {
    base_compensation {
      clause_type: base-guarantee
      cardinality: one
      required: true
      description: "Guaranteed base compensation over contract term"
    }
    
    performance_bonuses {
      clause_type: tiered-bonus
      cardinality: many
      required: false
      description: "Performance-based bonus groups (awards, stats, playoffs)"
    }
    
    appearance_fee {
      clause_type: per-event-fee
      cardinality: one
      required: false
      description: "Fee per promotional appearance"
    }
    
    product_allowance {
      clause_type: in-kind-benefit
      cardinality: many
      required: false
      description: "Product and equipment allowances"
    }
    
    exclusivity {
      clause_type: exclusivity
      cardinality: one
      required: true
      description: "Category exclusivity and competitive restrictions"
    }
  }
  
  logic {
    events {
      contract_year_complete {
        description: "Contract year has ended"
        condition: current_date >= deal.dates.term_end
      }
      
      all_bonuses_determined {
        description: "All bonus eligibility has been determined"
        condition: count(@performance_bonuses[*] where bonus.determined == true) 
               == count(@performance_bonuses[*])
      }
      
      deal_complete {
        description: "All compensation finalized"
        condition: contract_year_complete && all_bonuses_determined
      }
    }
    
    computations {
      // Base compensation
      var base_guaranteed = @base_compensation.amount ?? 0
      var base_earned = @base_compensation.earned ?? 0
      var base_received = @base_compensation.received ?? 0
      
      // Performance bonuses
      var bonus_potential = sum(@performance_bonuses[*].potential ?? 0)
      var bonus_earned = sum(@performance_bonuses[*].earned ?? 0)
      var bonus_received = sum(@performance_bonuses[*].received ?? 0)
      
      // Appearance fees
      var appearance_earned = @appearance_fee.earned ?? 0
      var appearance_received = @appearance_fee.received ?? 0
      
      // Totals
      var total_guaranteed = base_guaranteed
      var total_potential = base_guaranteed + bonus_potential
      var total_earned = base_earned + bonus_earned + appearance_earned
      var total_received = base_received + bonus_received + appearance_received
      
      // Outputs
      output total_guaranteed
      output total_potential
      output total_earned
      output total_received
      output total_pending = total_earned - total_received
      output bonus_earned
    }
  }
  
  outputs {
    total_guaranteed: number
    total_potential: number
    total_earned: number
    total_received: number
    total_pending: number
    bonus_earned: number
    deal_complete: boolean
  }
}

5.3 Influencer Endorsement Deal Type

deal_type {
  header {
    id: influencer-endorsement
    version: 1.0.0
    name: "Influencer Endorsement Deal"
    description: "Brand partnership with milestone-based payments and optional extensions"
    department: digital
    tags: [influencer, social-media, brand-partnership, milestones]
  }
  
  schema {
    type: object
    required: [parties, dates, currency, campaign_info]
    properties {
      parties {
        type: object
        required: [talent, brand]
        properties {
          talent { $ref: "authoritative://schemas/talent" }
          brand { $ref: "authoritative://schemas/brand" }
          agency { $ref: "authoritative://schemas/agency" }
        }
      }
      dates {
        type: object
        required: [effective_date, term_end]
        properties {
          effective_date { type: string, format: date }
          term_start { type: string, format: date }
          term_end { type: string, format: date }
        }
      }
      currency { type: string, default: USD }
      campaign_info {
        type: object
        required: [product_category]
        properties {
          campaign_name { type: string }
          product_category { type: string }
          deliverables_count { type: integer }
          platforms { type: array, items: { type: string } }
        }
      }
    }
  }
  
  suggested_clauses {
    base_fee {
      clause_type: milestone-payment
      cardinality: one
      required: true
      description: "Base fee paid on contract execution and work completion milestones"
    }
    
    deliverable_fee {
      clause_type: per-deliverable-fee
      cardinality: one
      required: false
      description: "Fee per social post or content deliverable"
    }
    
    optional_usage {
      clause_type: optional-extension
      cardinality: many
      required: false
      description: "Optional extended usage rights for additional fee"
    }
    
    exclusivity {
      clause_type: exclusivity
      cardinality: one
      required: true
      description: "Category and competitor exclusivity"
    }
    
    usage_rights {
      clause_type: usage-rights
      cardinality: one
      required: true
      description: "Content usage rights and territories"
    }
  }
  
  logic {
    events {
      contract_executed {
        description: "Contract signed by all parties"
        condition: @base_fee.contract_executed ?? false
      }
      
      work_complete {
        description: "All deliverables completed"
        condition: @base_fee.work_complete ?? false
             && (@deliverable_fee.all_delivered ?? true)
      }
      
      deal_complete {
        description: "All compensation finalized"
        condition: work_complete 
             && (count(@optional_usage[*] where option.determined == true)
                 == count(@optional_usage[*]))
      }
    }
    
    computations {
      // Base compensation
      var base_amount = @base_fee.amount ?? 0
      var base_earned = @base_fee.earned ?? 0
      var base_received = @base_fee.received ?? 0
      
      // Deliverable fees
      var deliverable_earned = @deliverable_fee.earned ?? 0
      var deliverable_received = @deliverable_fee.received ?? 0
      
      // Optional extensions
      var optional_potential = sum(@optional_usage[*].amount ?? 0)
      var optional_earned = sum(@optional_usage[*].earned ?? 0)
      var optional_received = sum(@optional_usage[*].received ?? 0)
      
      // Totals
      var total_guaranteed = base_amount
      var total_potential = base_amount + optional_potential
      var total_earned = base_earned + deliverable_earned + optional_earned
      var total_received = base_received + deliverable_received + optional_received
      
      // Outputs
      output total_guaranteed
      output total_potential
      output total_earned
      output total_received
      output total_pending = total_earned - total_received
      output optional_earned
    }
  }
  
  outputs {
    total_guaranteed: number
    total_potential: number
    total_earned: number
    total_received: number
    total_pending: number
    optional_earned: number
    deal_complete: boolean
  }
}

6. How Deal Types Guide Composition

6.1 The Composition Process

When creating a deal from a deal type:

1. USER selects deal type (e.g., "Music Touring")

2. SYSTEM presents:
   - Deal-level schema to fill out
   - List of suggested clause types

3. USER decides for each suggested clause:
   - Include as-is
   - Include with modifications
   - Skip / don't include

4. USER can also:
   - Add clause types not in suggestions
   - Create custom clause logic inline
   - Remove suggestions marked "required"

5. SYSTEM creates deal instance:
   - Copies deal-level schema with user data
   - Copies selected clause types (logic + schema)
   - Copies deal-level logic
   - Result is self-contained instance

6.2 Flexibility Examples

Example 1: Using suggestions as-is

User creates Music Touring deal:
- Includes show_settlement (suggested, required: true)
- Includes tour_versus (suggested)
- Includes travel_expenses (suggested)
- Skips merchandise (suggested)

Result: Standard touring deal

Example 2: Partial use

User creates Music Touring deal:
- Includes show_settlement
- Skips tour_versus (not applicable)
- Adds custom-production-fee (not suggested)

Result: Customized touring deal

Example 3: Starting fresh

User creates deal without deal type:
- Adds base-guarantee clause
- Adds custom-bonus clause
- Defines deal-level logic manually

Result: Fully custom deal

6.3 What "Required" Really Means

The required: true flag on suggested clauses is advisory only:

What it ISWhat it is NOT
A strong suggestionA system enforcement
Guidance for typical dealsA validation rule
Default selection in UIA blocker for deal creation

The system may:

  • Pre-select "required" clauses in the UI
  • Show a warning if "required" clause is omitted
  • Allow creation regardless of warnings

7. Validation Rules

7.1 Deal Type Structure Validation

RuleDescription
DT-1id must be unique across catalog
DT-2version must be valid semver
DT-3department must be valid department identifier
DT-4All clause_type references must exist in catalog

7.2 Schema Validation

RuleDescription
DS-1parties section required
DS-2dates section required
DS-3currency field required
DS-4Schema must be valid JSON Schema
DS-5Authoritative Data references must be valid

7.3 Logic Validation

RuleDescription
DL-1Cross-clause references (@clause.output) must target declared outputs
DL-2Event conditions must evaluate to boolean
DL-3No circular dependencies in computations
DL-4All outputs must be computed

7.4 Suggested Clauses Validation

RuleDescription
SC-1cardinality must be one or many
SC-2depends_on references must be valid clause names

8. Design Rationale

8.1 Why Suggestions, Not Requirements?

Entertainment contracts are highly variable. Even within the same deal category:

  • Music touring deals vary by artist tier, region, deal structure
  • Some tours have versus, others don't
  • Some have merchandise splits, others don't

Rigid templates would require constant exceptions. Suggestions provide guidance while respecting real-world variability.

8.2 Why Copy Logic at Instantiation?

When a deal is created, clause logic is copied into the instance because:

  • Immutability: Contract terms shouldn't change if clause type is updated
  • Auditability: The exact logic that computed results is preserved
  • Independence: Deal instances have no external dependencies
  • Legal validity: Frozen logic matches contractual agreement

8.3 Why Deal-Level Aggregation?

Individual clauses compute their own amounts, schedules, and states. But business needs require aggregated views:

  • "What's the total earned across all clauses?"
  • "What's still pending?"
  • "Is the entire deal complete?"

Deal-level logic provides this without burdening individual clause types.

8.4 Why Two Cardinalities?

one vs many cardinality guides both UI and logic:

  • one: UI shows single instance form; logic uses @clause.output
  • many: UI allows adding instances; logic uses @clause[*].output with aggregation

8.5 Why Authoritative Data Integration?

Party information (talent, buyer, brand, etc.) is master data managed by the Authoritative Data system. Referencing these schemas:

  • Ensures consistency across all deals
  • Eliminates schema duplication
  • Keeps Deal Engine focused on deal logic, not entity management
  • Enables entity linking and reporting across systems

8.6 Why Deal Types Don't Version Instances

Deal Types define the starting point for deals. They suggest structure, provide defaults, and guide composition. However, once a deal instance is created, it evolves independently through its own versioning system.

ConcernHandled By
Template structureDeal Type
Suggested clausesDeal Type
Initial deal-level logicDeal Type
Runtime data changesDeal Instance versioning
Contract amendmentsDeal Instance versioning
Clause replacementDeal Instance versioning
Audit historyDeal Instance versioning

The separation is intentional:

  1. Deal Types are stable templates. Updating a deal type (e.g., adding a new suggested clause) doesn't affect existing deals — they already have their logic frozen.

  2. Deal Instances evolve. Each deal has its own version history reflecting its unique amendments, settlements, and changes.

  3. No retroactive changes. If a deal type is updated to version 2.0, existing deals created from version 1.0 continue unchanged. New deals can use either version.

This mirrors how legal templates work: updating a contract template doesn't modify already-signed contracts.

8.7 The "Deal Must Compile" Principle

When deal-level logic references clause outputs via @clause.output syntax, those references must resolve to actual declared outputs. This is validated when:

  1. A deal is first created from a deal type
  2. A clause is added to an existing deal
  3. A clause is replaced in an existing deal
  4. Deal-level logic is amended

If references cannot resolve — for example, a clause was removed but deal logic still references its outputs — the deal will not compile and the change is rejected.

Implications for deal type design:

  • Use null coalescing (??) for optional clauses: @optional_bonus.earned ?? 0
  • Document which outputs are required vs. optional in suggested_clauses descriptions
  • Consider output interface stability when designing clause types

9. Relationship to Other Specifications

9.1 Clause Type Specification

Deal types reference clause types by ID. The clause type specification defines:

  • What outputs a clause type exposes (for @clause.output references)
  • What schema a clause type expects
  • What category/value_type the clause has

9.2 Deal Instance Specification

When a deal is created from a deal type:

  • Deal type schema → Deal instance deal-level data
  • Selected clause types → Deal instance clause instances
  • Deal type logic → Deal instance deal-level logic

The deal instance specification defines the runtime structure.

9.3 Authoritative Data

Deal types reference Authoritative Data schemas for master data entities:

  • authoritative://schemas/talent
  • authoritative://schemas/brand
  • authoritative://schemas/agency
  • etc.

The Authoritative Data system owns these schemas; Deal Engine consumes them.

9.4: Deal Instance Versioning

Deal Types guide creation, but Deal Instances have their own lifecycle. After a deal is created from a deal type, it evolves through versioning:

Deal Type                    Deal Instance
─────────────────           ─────────────────────────────────────
                            
  music-touring        ──▶   deal-2024-001234
  v1.0.0                     ├── Version 1 (created from deal type)
                             ├── Version 2 (show 1 settled)
  [template remains          ├── Version 3 (show 2 settled)  
   unchanged]                ├── Version 4 (bonus clause replaced)
                             └── Version 5 (show 3 settled)

What Triggers Instance Versions

ChangeCreates New Version
Data update (settlement, event)Yes
Clause logic amendedYes
Clause addedYes
Clause replacedYes
Clause removedYes
Deal-level logic amendedYes

Key Versioning Concepts

ConceptDescription
Immutable versionsEach version is a complete, frozen snapshot
Effective datesVersions have effective dates for point-in-time queries
Archived clausesReplaced clauses are archived with frozen final state
Full recalculationAny change triggers complete recalculation of active clauses

Relationship to Deal Types

AspectDeal Type RoleDeal Instance Role
Initial structureDefinesReceives at creation
Ongoing changesNoneManages via versioning
Logic updatesNew deal type version (for future deals)New instance version (for this deal)
Audit trailN/AComplete version history

Reference: See Deal Instance Specification Section 4-6 for complete versioning details.


Document History

  • v1.3 (2026-01-XX) - Deal instance version changes
  • v1.2 (2026-01-XX) - Initial specification
    • Deal type structure: header, schema, suggested_clauses, logic, outputs
    • Suggestion model (guide, not constrain)
    • Cross-clause reference syntax (@clause.output)
    • Authoritative Data schema integration
    • Aggregation patterns (by value_type for downstream systems)
    • Three complete examples (music touring, sports endorsement, influencer)
    • Validation rules
    • Design rationale

Confidential. For internal use only.