Skip to main content

Extensions

Overview​

Extensions capture configuration parameters, calculated results, and custom data that are not part of the core CODES specification. They further extend the tournament "time capsule" - ensuring what happened during a tournament can be accurately reconstructed.

Key Concepts​

Non-Temporal Data: Unlike Time Items, extensions don't track changes over time
Name-Value Pairs: Each extension has { name, value } structure
Uniqueness: Only one extension with a given name per .extensions array
Hierarchical Scope: Extensions can exist on any CODES document element
Factory Constants: Pre-defined extension names recognized by the factory
Custom Extensions: User-defined extensions for application-specific data

Extension Structure​

type Extension = {
name: string; // Unique identifier within the extensions array
value: any; // Any JSON-serializable data
};

// On any CODES element
{
extensions: Extension[];
}

Location in CODES​

Extensions can be attached to any element in a tournament record:

  • Tournament Record (top level)
  • Events
  • Draw Definitions
  • Structures
  • MatchUps
  • Participants
  • Venues/Courts

Factory-Recognized Extensions​

The factory internally uses and recognizes the following extension names (constants):

Configuration & Policy Extensions​

appliedPolicies - Policies applied to tournament element

Attached to: tournamentRecords, events, drawDefinitions, structures

Purpose: Captures which policies are "in scope" within the object hierarchy. Policies can be attached programmatically or automatically during draw generation.

{
name: 'appliedPolicies',
value: {
seeding: { seedingProfile: 'WTN', ... },
avoidance: { roundsToSeparate: 3, ... }
}
}

schedulingProfile - Auto scheduler configuration

Attached to: tournamentRecords, events

Purpose: Stores iteratively-edited scheduling profile before running the auto scheduler.

{
name: 'schedulingProfile',
value: [
{
scheduleDate: '2024-06-15',
venues: [{ venueId: 'venue-1', rounds: [...] }]
}
]
}

scheduleLimits - Match daily limits override

Attached to: matchUps

Purpose: Overrides policy-defined daily limits for specific matchUps.

{
name: 'scheduleLimits',
value: {
SINGLES: 2,
DOUBLES: 1,
TOTAL: 2
}
}

scheduleTiming - Match format timing override

Attached to: matchUps

Purpose: Overrides policy-defined timing for specific matchUp formats.

{
name: 'scheduleTiming',
value: {
'SET3-S:6/TB7': {
averageMinutes: 90,
recoveryMinutes: 30
}
}
}

Draw Generation & Structure Extensions​

entryProfile - Entry limitations

Attached to: events

Purpose: Stores limitations on accepted entries including qualifiers, wildcards, and maximum draw size.

{
name: 'entryProfile',
value: {
maxDrawSize: 32,
qualifiers: 4,
wildcards: 4
}
}

flightProfile - Flight names and entries

Attached to: events

Purpose: Captures flight configuration when event entries are split into multiple flights before draw generation.

{
name: 'flightProfile',
value: {
flights: [
{ flightNumber: 1, drawEntries: [...] },
{ flightNumber: 2, drawEntries: [...] }
]
}
}

drawProfile - Draw-specific configuration

Attached to: drawDefinitions

Purpose: Stores draw generation parameters and configuration.

{
name: 'drawProfile',
value: {
automated: true,
seedsCount: 8,
drawType: 'ELIMINATION'
}
}

eventProfile - Event-specific configuration

Attached to: events

Purpose: Stores event-level configuration and parameters.

{
name: 'eventProfile',
value: {
category: 'U18',
gender: 'FEMALE',
surfaceType: 'HARD'
}
}

disableLinks - Link disabling for position swaps

Attached to: structures

Purpose: When positioning policies allow draw position swaps in non-MAIN structures, normal progression logic breaks and links must be disabled to avoid data corruption.

{
name: 'disableLinks',
value: true
}

roundTarget - Qualifying feed-in rounds

Attached to: structures, event.entries

Purpose: Supports qualifying structures feeding into different rounds of MAIN structures; also annotates entries for "staggered entry" structures.

{
name: 'roundTarget',
value: {
roundNumber: 2, // Feed into round 2 of main draw
structureId: 'main-structure-id'
}
}

Team Event Extensions​

groupingAttribute - Team generation attribute

Attached to: participants (TEAM type)

Purpose: Stores the person/participant attribute used to generate TEAM participants.

{
name: 'groupingAttribute',
value: 'club' // Teams generated by club affiliation
}

lineUps - Team lineup defaults

Attached to: structures

Purpose: Stores most recent lineup for each TEAM progressing through structure. Enables default assignments in hydrated SINGLES/DOUBLES tie matchUps before actual lineups are saved.

{
name: 'lineUps',
value: {
'team-1': [
{ participantId: 'player-1', collectionPosition: 1 },
{ participantId: 'player-2', collectionPosition: 2 }
]
}
}

disableAutoCalc - Manual TEAM scoring

Attached to: matchUps (TEAM type)

Purpose: When manual scoring is enabled for TEAM matchUps, disables automatic calculation of team results.

{
name: 'disableAutoCalc',
value: true
}

Scoring & Results Extensions​

delegatedOutcome - Unofficial results

Attached to: matchUps

Purpose: Captures matchUp outcomes sourced from third-party applications for display purposes prior to official result entry.

{
name: 'delegatedOutcome',
value: {
score: {
sets: [
{ side1Score: 6, side2Score: 4, winningSide: 1 },
{ side1Score: 6, side2Score: 2, winningSide: 1 }
]
},
winningSide: 1,
source: 'external-app'
}
}

tally - Round robin results

Attached to: positionAssignments (within structures)

Purpose: Stores calculated participant results for structure positions. Used to determine group order in round robin structures.

{
name: 'tally',
value: {
matchUpsWon: 4,
matchUpsLost: 1,
setsWon: 9,
setsLost: 3,
gamesWon: 54,
gamesLost: 38
}
}

subOrder - Tie-breaking order

Attached to: positionAssignments

Purpose: When ties occur in round robin group order calculation, captures manual determination of order for tied positions.

{
name: 'subOrder',
value: 2 // Second place among tied participants
}

rankingPoints - Points awarded

Attached to: tournamentRecords

Purpose: Enables capturing points generated by event outcomes for real-time display as participants advance through structures.

{
name: 'rankingPoints',
value: {
'player-1': { singles: 250, doubles: 100 },
'player-2': { singles: 150 }
}
}

Scheduling & Venue Extensions​

disabled - Resource disabling

Attached to: courts, venues

Purpose: Indicates resource has been disabled and scheduling methods cannot use it.

{
name: 'disabled',
value: true
}

linkedTournamentsIds - Multi-tournament scheduling

Attached to: tournamentRecords

Purpose: When multiple tournaments share venues, captures the association so client applications know to load all tournament records for scheduling.

{
name: 'linkedTournamentsIds',
value: ['tournament-1', 'tournament-2', 'tournament-3']
}

personRequests - Scheduling requests

Attached to: participants, events, tournamentRecords

Purpose: Captures scheduling requests from participants. Consumed by scheduler to accommodate requests or simply display them.

{
name: 'personRequests',
value: [
{
personId: 'person-1',
requestType: 'DO_NOT_SCHEDULE',
date: '2024-06-15',
startTime: '09:00',
endTime: '11:00'
}
]
}

Participant & Registration Extensions​

registration - Registration data

Attached to: participants

Purpose: Captures registration-related information and metadata.

{
name: 'registration',
value: {
registrationDate: '2024-05-01',
registrationId: 'REG-12345',
paymentStatus: 'PAID'
}
}

participantRepresentatives - Draw witnesses

Attached to: drawDefinitions

Purpose: Records participant representatives present as witnesses during manual draw creation (traditional "hat draw").

{
name: 'participantRepresentatives',
value: [
{ participantId: 'player-1', representativeName: 'John Coach' },
{ participantId: 'player-2', representativeName: 'Jane Manager' }
]
}

statusDetail - Entry status annotation

Attached to: event.entries

Purpose: Third-party extension (not used by factory) for annotating entry status of participants.

{
name: 'statusDetail',
value: {
status: 'CONFIRMED',
notes: 'Paid in full, medical clearance received'
}
}

eventWithdrawalRequests - Withdrawal tracking

Attached to: events

Purpose: Tracks participant withdrawal requests from events.

{
name: 'eventWithdrawalRequests',
value: [
{
participantId: 'player-1',
requestDate: '2024-06-10',
reason: 'Injury'
}
]
}

activeSuspension - Participant suspension

Attached to: participants

Purpose: Indicates participant has active suspension affecting eligibility.

{
name: 'activeSuspension',
value: {
startDate: '2024-05-01',
endDate: '2024-08-31',
reason: 'Code violation'
}
}

Concurrency & Access Control Extensions​

mutationLocks - Mutation lock enforcement

Attached to: tournamentRecords, events, drawDefinitions, venues

Purpose: Controls concurrent access to scoped mutations. The tournament-level extension includes an enabled flag that acts as a feature gate; element-level extensions store the locks themselves. See Mutation Locks for full details.

// Tournament-level (feature gate + tournament locks)
{
name: 'mutationLocks',
value: {
enabled: true,
locks: [
{
lockId: 'uuid-1',
lockToken: 'opaque-token',
scope: 'SCHEDULING',
expiresAt: '2026-03-01T12:00:00.000Z',
createdAt: '2026-02-27T10:00:00.000Z',
}
]
}
}

// Element-level (draw, event, or venue)
{
name: 'mutationLocks',
value: {
locks: [
{
lockId: 'uuid-2',
lockToken: 'scorer-token',
scope: 'SCORING',
expiresAt: null,
createdAt: '2026-02-27T10:00:00.000Z',
}
]
}
}

Auditing & System Extensions​

factory - Factory version tracking

Attached to: tournamentRecords

Purpose: Captures version of factory (and other CODES processors) that created/mutated the tournament record.

Since 7.7.0 the stamp is a first-class tournamentRecord.factory attribute (the extension form is written only under LEGACY write mode), and it carries three fields: createdVersion (the factory that created the record), version (the factory that last wrote it) and timeStamp (the engine clock at that write). createTournamentRecord stamps all three; every later write refreshes version and timeStamp and keeps createdVersion. A record created before 7.7.0 has no createdVersion, and nothing backfills one: the first factory to touch an old record did not create it. The internal readers accept either form.

// first-class (7.7.0)
tournamentRecord.factory = { createdVersion: '7.7.0', version: '7.7.0', timeStamp: 1759795200000 };

// extension form, as records written before 7.7.0 (or under LEGACY write mode) carry it
{
name: 'factory',
value: {
version: '2.2.49',
lastModified: '2024-06-15T10:30:00Z'
}
}

drawDeletions - Deleted draw audit

Attached to: tournamentRecords

Purpose: When no external auditing service is available, stores deleted draw definitions for audit purposes.

{
name: 'drawDeletions',
value: [
{
drawId: 'draw-123',
drawName: 'Main Draw',
deletedAt: '2024-06-14T15:00:00Z',
deletedBy: 'user-456'
}
]
}

positionActions - Position action telemetry

Attached to: tournamentRecords

Purpose: When no external auditing service is available, stores position action telemetry.

{
name: 'positionActions',
value: [
{
action: 'ASSIGN_PARTICIPANT',
drawPosition: 1,
participantId: 'player-1',
timestamp: '2024-06-14T14:00:00Z'
}
]
}

tieFormatModifications - Tie format audit

Attached to: tournamentRecords

Purpose: When no external auditing service is available, captures modifications to tie formats during the course of an event.

{
name: 'tieFormatModifications',
value: [
{
tieFormatId: 'format-1',
modifiedAt: '2024-06-15T09:00:00Z',
changes: { collectionDefinitions: [...] }
}
]
}

context - Creation context

Attached to: venues, courts, and other elements

Purpose: Captures context in which a resource was added (metadata about creation).

{
name: 'context',
value: {
createdBy: 'user-123',
createdAt: '2024-06-01T10:00:00Z',
source: 'mobile-app'
}
}

Display & UI Extensions​

display - Display preferences

Attached to: events, drawDefinitions, structures

Purpose: Client application-specific storage for display preferences.

{
name: 'display',
value: {
viewMode: 'bracket',
showSeeds: true,
highlightedParticipants: ['player-1', 'player-2']
}
}

Custom Extensions​

Applications can define custom extensions for application-specific data not covered by factory constants.

Naming Conventions​

Use descriptive, unique names that won't conflict with factory extensions:

// ✓ GOOD - Clear, specific names
{ name: 'broadcastSchedule', value: { ... } }
{ name: 'sponsorData', value: { ... } }
{ name: 'mediaRequirements', value: { ... } }
{ name: 'facilityAccess', value: { ... } }

// ✗ AVOID - Generic or conflicting names
{ name: 'data', value: { ... } }
{ name: 'info', value: { ... } }
{ name: 'config', value: { ... } }

Custom Extension Examples​

Broadcast Information:

tournamentEngine.addExtension({
matchUpId: 'match-123',
drawId: 'draw-456',
extension: {
name: 'broadcastSchedule',
value: {
channel: 'ESPN',
broadcastTime: '14:00',
commentators: ['John Smith', 'Jane Doe'],
},
},
});

Facility Requirements:

tournamentEngine.addEventExtension({
eventId: 'singles-main',
extension: {
name: 'facilityRequirements',
value: {
courtSurface: 'HARD',
lighting: 'REQUIRED',
spectatorCapacity: 500,
},
},
});

Sponsor Data:

tournamentEngine.addTournamentExtension({
extension: {
name: 'sponsorData',
value: {
titleSponsor: 'Acme Corp',
courtSponsors: {
'court-1': 'Beta LLC',
'court-2': 'Gamma Inc',
},
},
},
});

Working with Extensions​

Adding Extensions​

// Add to tournament
tournamentEngine.addTournamentExtension({
extension: {
name: 'customData',
value: { ... }
}
});

// Add to event
tournamentEngine.addEventExtension({
eventId: 'singles-main',
extension: {
name: 'eventCustomData',
value: { ... }
}
});

// Add to draw
tournamentEngine.addDrawDefinitionExtension({
drawId: 'draw-123',
extension: {
name: 'drawCustomData',
value: { ... }
}
});

// Add to matchUp
tournamentEngine.addExtension({
matchUpId: 'match-456',
drawId: 'draw-123',
extension: {
name: 'matchUpCustomData',
value: { ... }
}
});

Updating Extensions​

Extensions are updated by removing the old one and adding the new one (or using update methods):

// Remove extension
tournamentEngine.removeTournamentExtension({
name: 'customData',
});

// Add updated version
tournamentEngine.addTournamentExtension({
extension: {
name: 'customData',
value: updatedValue,
},
});

Extension Hydration​

When retrieving data with inContext: true, extensions are automatically converted to underscore-prefixed attributes:

// MatchUp has extension
{
extensions: [
{
name: 'broadcastSchedule',
value: { channel: 'ESPN' },
},
];
}

// When hydrated
const { matchUps } = tournamentEngine.allTournamentMatchUps({
inContext: true,
});

console.log(matchUps[0]._broadcastSchedule); // { channel: 'ESPN' }
console.log(matchUps[0].extensions); // Original array still present

See: MatchUp Context for details on extension hydration.

Extensions vs Time Items​

Choose the appropriate mechanism for your data:

FeatureExtensionsTime Items
PurposeConfiguration, calculated results, custom dataTemporal data with effective dates
HistorySingle value (current state)Multiple values over time
TimestampsNo timestampsitemDate and createdAt
Use CasesPolicies, profiles, preferences, metadataRankings, ratings, schedule changes, status transitions
HydrationUnderscore-prefixed attributesExtracted to .schedule for matchUps

Example Decision:

  • Use Extension: Store broadcast channel assignment (doesn't change over time)
  • Use Time Item: Track court assignments (may change, need history)

Best Practices​

Uniqueness​

Only one extension with a given name per element:

API Reference: allTournamentMatchUps

// ✓ CORRECT - One extension per name
{
extensions: [{ name: 'customData', value: { field1: 'value1', field2: 'value2' } }];
}

// ✗ WRONG - Duplicate names
{
extensions: [
{ name: 'customData', value: { field1: 'value1' } },
{ name: 'customData', value: { field2: 'value2' } }, // Duplicate!
];
}

Value Types​

Use appropriate JSON-serializable types:

// ✓ GOOD - JSON-serializable
{ name: 'config', value: { enabled: true, count: 5, items: ['a', 'b'] } }
{ name: 'timestamp', value: '2024-06-15T10:00:00Z' }

// ✗ AVOID - Non-serializable
{ name: 'config', value: new Date() } // Date object
{ name: 'callback', value: function() {} } // Function

Factory Constant Names​

Avoid using factory-recognized extension names for custom extensions:

// ✗ AVOID - Conflicts with factory constants
{ name: 'appliedPolicies', value: myCustomValue }
{ name: 'schedulingProfile', value: myCustomValue }

// ✓ GOOD - Unique custom names
{ name: 'myApp_policies', value: myCustomValue }
{ name: 'myApp_schedule', value: myCustomValue }