@hla4ts/session 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,377 +1,377 @@
1
- # @hla4ts/session
2
-
3
- **HLA 4 Federate Protocol Session Layer**
4
-
5
- This package provides session management for the HLA 4 Federate Protocol, handling connection establishment, state machine, heartbeats, request/response correlation, and session resumption.
6
-
7
- ## Overview
8
-
9
- The session layer sits between the transport layer and the HLA API layer, providing:
10
-
11
- - **Session lifecycle management** - NEW → STARTING → RUNNING ⇄ DROPPED → TERMINATED
12
- - **Request/response correlation** - Matches HLA call responses to requests
13
- - **Heartbeat support** - Keep-alive mechanism for connection health
14
- - **Session resumption** - Reconnect and resume after network drops
15
- - **Timeout management** - Connection and response timeouts
16
-
17
- ## Installation
18
-
19
- ```bash
20
- bun add @hla4ts/session
21
- ```
22
-
23
- ## Quick Start
24
-
25
- ```typescript
26
- import { Session, SessionState } from '@hla4ts/session';
27
- import { TlsTransport } from '@hla4ts/transport';
28
-
29
- // Create transport and session
30
- const transport = new TlsTransport({
31
- host: 'rti.example.com',
32
- port: 15165,
33
- });
34
-
35
- const session = new Session(transport, {
36
- connectionTimeout: 30000,
37
- responseTimeout: 180000,
38
- });
39
-
40
- // Listen for state changes
41
- session.addStateListener({
42
- onStateTransition: (oldState, newState, reason) => {
43
- console.log(`Session: ${oldState} -> ${newState} (${reason})`);
44
-
45
- // Handle connection drops
46
- if (newState === SessionState.DROPPED) {
47
- session.resume().catch((err) => {
48
- console.error('Resume failed:', err);
49
- session.terminate();
50
- });
51
- }
52
- }
53
- });
54
-
55
- // Start the session
56
- await session.start({
57
- onHlaCallbackRequest: (seqNum, callbackData) => {
58
- // Process the callback (decode protobuf, handle it, encode response)
59
- const response = processCallback(callbackData);
60
- session.sendHlaCallbackResponse(seqNum, response);
61
- }
62
- });
63
-
64
- // Send HLA calls
65
- const response = await session.sendHlaCallRequest(encodedCall);
66
-
67
- // When done
68
- await session.terminate();
69
- ```
70
-
71
- ## Sequence Diagram
72
-
73
- ```mermaid
74
- sequenceDiagram
75
- participant App as Federate Code
76
- participant Session
77
- participant Transport
78
- participant RTI
79
- App->>Session: start(callbackListener)
80
- Session->>Transport: CTRL_NEW_SESSION
81
- Transport-->>RTI: framed message
82
- RTI-->>Transport: CTRL_NEW_SESSION_STATUS
83
- Transport-->>Session: onMessage
84
- App->>Session: sendHlaCallRequest(bytes)
85
- Session->>Transport: HLA_CALL_REQUEST
86
- RTI-->>Transport: HLA_CALL_RESPONSE
87
- Transport-->>Session: onMessage
88
- ```
89
-
90
- ## Session States
91
-
92
- The session follows a well-defined state machine:
93
-
94
- ```
95
- ┌───────┐
96
- │ NEW │────────────────────┐
97
- └───┬───┘ │
98
- │ start() │
99
- ▼ │
100
- ┌──────────┐ │
101
- │ STARTING │─────────────────┤
102
- └────┬─────┘ │
103
- │ success │ failure
104
- ▼ │
105
- ┌─────────┐ │
106
- │ RUNNING │◄─────────────┐ │
107
- └────┬────┘ │ │
108
- │ │ │
109
- │ connection lost │ resume()
110
- ▼ │ │
111
- ┌─────────┐ ┌────┴────┐
112
- │ DROPPED │────────►│ RESUMING│
113
- └────┬────┘ └────┬────┘
114
- │ │
115
- │ terminate() │ failure
116
- ▼ │
117
- ┌─────────────┐ │
118
- │ TERMINATING │ │
119
- └──────┬──────┘ │
120
- │ │
121
- ▼ ▼
122
- ┌────────────┐◄──────────┘
123
- │ TERMINATED │
124
- └────────────┘
125
- ```
126
-
127
- ### State Descriptions
128
-
129
- | State | Description |
130
- |-------|-------------|
131
- | `NEW` | Session created but not started |
132
- | `STARTING` | Connecting to RTI, establishing session |
133
- | `RUNNING` | Session active, can send/receive HLA messages |
134
- | `DROPPED` | Connection lost, can attempt resume |
135
- | `RESUMING` | Attempting to resume dropped session |
136
- | `TERMINATING` | Graceful shutdown in progress |
137
- | `TERMINATED` | Session ended, cannot be reused |
138
-
139
- ## API Reference
140
-
141
- ### Session Class
142
-
143
- #### Constructor
144
-
145
- ```typescript
146
- new Session(transport: Transport, options?: SessionOptions)
147
- ```
148
-
149
- **Options:**
150
-
151
- | Option | Type | Default | Description |
152
- |--------|------|---------|-------------|
153
- | `connectionTimeout` | `number` | `30000` | Timeout for initial connection (ms) |
154
- | `responseTimeout` | `number` | `180000` | Timeout for server responses (ms) |
155
- | `maxRetryAttempts` | `number` | `3` | Max connection retry attempts |
156
- | `messageQueueSize` | `number` | `1000` | Size of outgoing message queue |
157
- | `rateLimitEnabled` | `boolean` | `false` | Enable rate limiting |
158
- | `heartbeatInterval` | `number` | `10000` | Heartbeat check interval (ms) |
159
-
160
- #### Properties
161
-
162
- ```typescript
163
- session.id: bigint // Session ID (0 if not established)
164
- session.state: SessionState // Current state
165
- session.isOperational: boolean // True if can send/receive messages
166
- ```
167
-
168
- #### Methods
169
-
170
- ##### `start(callbackListener)`
171
-
172
- Start the session and connect to the RTI.
173
-
174
- ```typescript
175
- await session.start({
176
- onHlaCallbackRequest: (seqNum: number, callback: Uint8Array) => {
177
- // Handle callback
178
- }
179
- });
180
- ```
181
-
182
- ##### `resume()`
183
-
184
- Resume a dropped session.
185
-
186
- ```typescript
187
- const success = await session.resume();
188
- ```
189
-
190
- ##### `sendHeartbeat()`
191
-
192
- Send a heartbeat message (useful for keeping connection alive).
193
-
194
- ```typescript
195
- await session.sendHeartbeat();
196
- ```
197
-
198
- ##### `sendHlaCallRequest(encodedHlaCall)`
199
-
200
- Send an HLA call and wait for the response.
201
-
202
- ```typescript
203
- const response = await session.sendHlaCallRequest(encodedCall);
204
- ```
205
-
206
- ##### `sendHlaCallbackResponse(responseToSequenceNumber, encodedResponse)`
207
-
208
- Send a response to an HLA callback.
209
-
210
- ```typescript
211
- await session.sendHlaCallbackResponse(seqNum, encodedResponse);
212
- ```
213
-
214
- ##### `terminate(timeoutMs?)`
215
-
216
- Gracefully terminate the session.
217
-
218
- ```typescript
219
- await session.terminate();
220
- ```
221
-
222
- ##### `addStateListener(listener)`
223
-
224
- Register a state change listener.
225
-
226
- ```typescript
227
- session.addStateListener({
228
- onStateTransition: (oldState, newState, reason) => {
229
- console.log(`${oldState} -> ${newState}: ${reason}`);
230
- }
231
- });
232
- ```
233
-
234
- ##### `setMessageSentListener(listener)`
235
-
236
- Set a listener for outgoing messages (useful for heartbeat timing).
237
-
238
- ```typescript
239
- session.setMessageSentListener({
240
- onMessageSent: () => {
241
- // Reset heartbeat timer
242
- }
243
- });
244
- ```
245
-
246
- ## Error Handling
247
-
248
- The session layer throws specific errors:
249
-
250
- ```typescript
251
- import {
252
- SessionLostError,
253
- SessionAlreadyTerminatedError,
254
- SessionIllegalStateError,
255
- BadMessageError,
256
- ConnectionTimeoutError,
257
- ResponseTimeoutError,
258
- } from '@hla4ts/session';
259
-
260
- try {
261
- await session.start(listener);
262
- } catch (err) {
263
- if (err instanceof ConnectionTimeoutError) {
264
- console.error('Could not connect to RTI');
265
- } else if (err instanceof SessionLostError) {
266
- console.error('Session lost:', err.message);
267
- }
268
- }
269
- ```
270
-
271
- ## Sequence Numbers
272
-
273
- The package exports utilities for working with Federate Protocol sequence numbers:
274
-
275
- ```typescript
276
- import {
277
- SequenceNumber,
278
- AtomicSequenceNumber,
279
- isValidSequenceNumber,
280
- nextSequenceNumber,
281
- NO_SEQUENCE_NUMBER,
282
- INITIAL_SEQUENCE_NUMBER,
283
- MAX_SEQUENCE_NUMBER,
284
- } from '@hla4ts/session';
285
-
286
- // Mutable sequence number
287
- const seq = new SequenceNumber(0);
288
- seq.increment(); // Returns 1
289
- seq.getAndIncrement(); // Returns 1, then increments to 2
290
-
291
- // For concurrent access
292
- const atomic = new AtomicSequenceNumber(0);
293
- atomic.compareAndSet(0, 1); // Returns true if successful
294
-
295
- // Utilities
296
- isValidSequenceNumber(100); // true
297
- isValidSequenceNumber(-1); // false
298
- nextSequenceNumber(MAX_SEQUENCE_NUMBER); // Returns 0 (wrap-around)
299
- ```
300
-
301
- ## Timers
302
-
303
- The package includes timer utilities for session management:
304
-
305
- ```typescript
306
- import { TimeoutTimer, OneShotTimer } from '@hla4ts/session';
307
-
308
- // Periodic timeout timer
309
- const timer = TimeoutTimer.createLazy(30000); // 30 second timeout
310
- timer.start(() => {
311
- console.log('Timeout!');
312
- });
313
- timer.extend(); // Reset the timeout
314
- timer.pause(); // Stop checking
315
- timer.resume(); // Resume checking
316
- timer.cancel(); // Permanently cancel
317
-
318
- // One-shot timer
319
- const oneShot = new OneShotTimer();
320
- oneShot.schedule(() => {
321
- console.log('Fired!');
322
- }, 5000);
323
- oneShot.clear(); // Cancel before it fires
324
- oneShot.cancel(); // Permanently cancel
325
- ```
326
-
327
- ## Message Encoding (Advanced)
328
-
329
- For advanced use cases, you can encode/decode session control messages directly:
330
-
331
- ```typescript
332
- import {
333
- createNewSessionMessage,
334
- createHeartbeatMessage,
335
- createHlaCallRequestMessage,
336
- decodeHlaCallResponse,
337
- decodeHlaCallbackRequest,
338
- } from '@hla4ts/session';
339
-
340
- // Create a new session message
341
- const newSessionMsg = createNewSessionMessage();
342
-
343
- // Create an HLA call request
344
- const callMsg = createHlaCallRequestMessage(
345
- sequenceNumber,
346
- sessionId,
347
- lastReceivedSequenceNumber,
348
- protobufPayload
349
- );
350
-
351
- // Decode an HLA call response
352
- const response = decodeHlaCallResponse(payload);
353
- console.log(response.responseToSequenceNumber);
354
- console.log(response.hlaServiceReturnValueOrException);
355
- ```
356
-
357
- ## Testing
358
-
359
- ```bash
360
- cd packages/session
361
- bun test
362
- ```
363
-
364
- ## Related Packages
365
-
366
- - [`@hla4ts/transport`](../transport) - Transport layer (TCP/TLS)
367
- - [`@hla4ts/proto`](../proto) - Protocol buffer types
368
- - [`@hla4ts/hla-api`](../hla-api) - High-level HLA API facade
369
-
370
- ## References
371
-
372
- - [IEEE 1516-2025](https://standards.ieee.org/standard/1516-2025.html) - HLA 4 Standard
373
- - [Pitch FedProClient](https://github.com/Pitch-Technologies/FedProClient) - Reference implementation
374
-
375
- ## License
376
-
377
- MIT
1
+ # @hla4ts/session
2
+
3
+ **HLA 4 Federate Protocol Session Layer**
4
+
5
+ This package provides session management for the HLA 4 Federate Protocol, handling connection establishment, state machine, heartbeats, request/response correlation, and session resumption.
6
+
7
+ ## Overview
8
+
9
+ The session layer sits between the transport layer and the HLA API layer, providing:
10
+
11
+ - **Session lifecycle management** - NEW → STARTING → RUNNING ⇄ DROPPED → TERMINATED
12
+ - **Request/response correlation** - Matches HLA call responses to requests
13
+ - **Heartbeat support** - Keep-alive mechanism for connection health
14
+ - **Session resumption** - Reconnect and resume after network drops
15
+ - **Timeout management** - Connection and response timeouts
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ bun add @hla4ts/session
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```typescript
26
+ import { Session, SessionState } from '@hla4ts/session';
27
+ import { TlsTransport } from '@hla4ts/transport';
28
+
29
+ // Create transport and session
30
+ const transport = new TlsTransport({
31
+ host: 'rti.example.com',
32
+ port: 15165,
33
+ });
34
+
35
+ const session = new Session(transport, {
36
+ connectionTimeout: 30000,
37
+ responseTimeout: 180000,
38
+ });
39
+
40
+ // Listen for state changes
41
+ session.addStateListener({
42
+ onStateTransition: (oldState, newState, reason) => {
43
+ console.log(`Session: ${oldState} -> ${newState} (${reason})`);
44
+
45
+ // Handle connection drops
46
+ if (newState === SessionState.DROPPED) {
47
+ session.resume().catch((err) => {
48
+ console.error('Resume failed:', err);
49
+ session.terminate();
50
+ });
51
+ }
52
+ }
53
+ });
54
+
55
+ // Start the session
56
+ await session.start({
57
+ onHlaCallbackRequest: (seqNum, callbackData) => {
58
+ // Process the callback (decode protobuf, handle it, encode response)
59
+ const response = processCallback(callbackData);
60
+ session.sendHlaCallbackResponse(seqNum, response);
61
+ }
62
+ });
63
+
64
+ // Send HLA calls
65
+ const response = await session.sendHlaCallRequest(encodedCall);
66
+
67
+ // When done
68
+ await session.terminate();
69
+ ```
70
+
71
+ ## Sequence Diagram
72
+
73
+ ```mermaid
74
+ sequenceDiagram
75
+ participant App as Federate Code
76
+ participant Session
77
+ participant Transport
78
+ participant RTI
79
+ App->>Session: start(callbackListener)
80
+ Session->>Transport: CTRL_NEW_SESSION
81
+ Transport-->>RTI: framed message
82
+ RTI-->>Transport: CTRL_NEW_SESSION_STATUS
83
+ Transport-->>Session: onMessage
84
+ App->>Session: sendHlaCallRequest(bytes)
85
+ Session->>Transport: HLA_CALL_REQUEST
86
+ RTI-->>Transport: HLA_CALL_RESPONSE
87
+ Transport-->>Session: onMessage
88
+ ```
89
+
90
+ ## Session States
91
+
92
+ The session follows a well-defined state machine:
93
+
94
+ ```
95
+ ┌───────┐
96
+ │ NEW │────────────────────┐
97
+ └───┬───┘ │
98
+ │ start() │
99
+ ▼ │
100
+ ┌──────────┐ │
101
+ │ STARTING │─────────────────┤
102
+ └────┬─────┘ │
103
+ │ success │ failure
104
+ ▼ │
105
+ ┌─────────┐ │
106
+ │ RUNNING │◄─────────────┐ │
107
+ └────┬────┘ │ │
108
+ │ │ │
109
+ │ connection lost │ resume()
110
+ ▼ │ │
111
+ ┌─────────┐ ┌────┴────┐
112
+ │ DROPPED │────────►│ RESUMING│
113
+ └────┬────┘ └────┬────┘
114
+ │ │
115
+ │ terminate() │ failure
116
+ ▼ │
117
+ ┌─────────────┐ │
118
+ │ TERMINATING │ │
119
+ └──────┬──────┘ │
120
+ │ │
121
+ ▼ ▼
122
+ ┌────────────┐◄──────────┘
123
+ │ TERMINATED │
124
+ └────────────┘
125
+ ```
126
+
127
+ ### State Descriptions
128
+
129
+ | State | Description |
130
+ |-------|-------------|
131
+ | `NEW` | Session created but not started |
132
+ | `STARTING` | Connecting to RTI, establishing session |
133
+ | `RUNNING` | Session active, can send/receive HLA messages |
134
+ | `DROPPED` | Connection lost, can attempt resume |
135
+ | `RESUMING` | Attempting to resume dropped session |
136
+ | `TERMINATING` | Graceful shutdown in progress |
137
+ | `TERMINATED` | Session ended, cannot be reused |
138
+
139
+ ## API Reference
140
+
141
+ ### Session Class
142
+
143
+ #### Constructor
144
+
145
+ ```typescript
146
+ new Session(transport: Transport, options?: SessionOptions)
147
+ ```
148
+
149
+ **Options:**
150
+
151
+ | Option | Type | Default | Description |
152
+ |--------|------|---------|-------------|
153
+ | `connectionTimeout` | `number` | `30000` | Timeout for initial connection (ms) |
154
+ | `responseTimeout` | `number` | `180000` | Timeout for server responses (ms) |
155
+ | `maxRetryAttempts` | `number` | `3` | Max connection retry attempts |
156
+ | `messageQueueSize` | `number` | `1000` | Size of outgoing message queue |
157
+ | `rateLimitEnabled` | `boolean` | `false` | Enable rate limiting |
158
+ | `heartbeatInterval` | `number` | `10000` | Heartbeat check interval (ms) |
159
+
160
+ #### Properties
161
+
162
+ ```typescript
163
+ session.id: bigint // Session ID (0 if not established)
164
+ session.state: SessionState // Current state
165
+ session.isOperational: boolean // True if can send/receive messages
166
+ ```
167
+
168
+ #### Methods
169
+
170
+ ##### `start(callbackListener)`
171
+
172
+ Start the session and connect to the RTI.
173
+
174
+ ```typescript
175
+ await session.start({
176
+ onHlaCallbackRequest: (seqNum: number, callback: Uint8Array) => {
177
+ // Handle callback
178
+ }
179
+ });
180
+ ```
181
+
182
+ ##### `resume()`
183
+
184
+ Resume a dropped session.
185
+
186
+ ```typescript
187
+ const success = await session.resume();
188
+ ```
189
+
190
+ ##### `sendHeartbeat()`
191
+
192
+ Send a heartbeat message (useful for keeping connection alive).
193
+
194
+ ```typescript
195
+ await session.sendHeartbeat();
196
+ ```
197
+
198
+ ##### `sendHlaCallRequest(encodedHlaCall)`
199
+
200
+ Send an HLA call and wait for the response.
201
+
202
+ ```typescript
203
+ const response = await session.sendHlaCallRequest(encodedCall);
204
+ ```
205
+
206
+ ##### `sendHlaCallbackResponse(responseToSequenceNumber, encodedResponse)`
207
+
208
+ Send a response to an HLA callback.
209
+
210
+ ```typescript
211
+ await session.sendHlaCallbackResponse(seqNum, encodedResponse);
212
+ ```
213
+
214
+ ##### `terminate(timeoutMs?)`
215
+
216
+ Gracefully terminate the session.
217
+
218
+ ```typescript
219
+ await session.terminate();
220
+ ```
221
+
222
+ ##### `addStateListener(listener)`
223
+
224
+ Register a state change listener.
225
+
226
+ ```typescript
227
+ session.addStateListener({
228
+ onStateTransition: (oldState, newState, reason) => {
229
+ console.log(`${oldState} -> ${newState}: ${reason}`);
230
+ }
231
+ });
232
+ ```
233
+
234
+ ##### `setMessageSentListener(listener)`
235
+
236
+ Set a listener for outgoing messages (useful for heartbeat timing).
237
+
238
+ ```typescript
239
+ session.setMessageSentListener({
240
+ onMessageSent: () => {
241
+ // Reset heartbeat timer
242
+ }
243
+ });
244
+ ```
245
+
246
+ ## Error Handling
247
+
248
+ The session layer throws specific errors:
249
+
250
+ ```typescript
251
+ import {
252
+ SessionLostError,
253
+ SessionAlreadyTerminatedError,
254
+ SessionIllegalStateError,
255
+ BadMessageError,
256
+ ConnectionTimeoutError,
257
+ ResponseTimeoutError,
258
+ } from '@hla4ts/session';
259
+
260
+ try {
261
+ await session.start(listener);
262
+ } catch (err) {
263
+ if (err instanceof ConnectionTimeoutError) {
264
+ console.error('Could not connect to RTI');
265
+ } else if (err instanceof SessionLostError) {
266
+ console.error('Session lost:', err.message);
267
+ }
268
+ }
269
+ ```
270
+
271
+ ## Sequence Numbers
272
+
273
+ The package exports utilities for working with Federate Protocol sequence numbers:
274
+
275
+ ```typescript
276
+ import {
277
+ SequenceNumber,
278
+ AtomicSequenceNumber,
279
+ isValidSequenceNumber,
280
+ nextSequenceNumber,
281
+ NO_SEQUENCE_NUMBER,
282
+ INITIAL_SEQUENCE_NUMBER,
283
+ MAX_SEQUENCE_NUMBER,
284
+ } from '@hla4ts/session';
285
+
286
+ // Mutable sequence number
287
+ const seq = new SequenceNumber(0);
288
+ seq.increment(); // Returns 1
289
+ seq.getAndIncrement(); // Returns 1, then increments to 2
290
+
291
+ // For concurrent access
292
+ const atomic = new AtomicSequenceNumber(0);
293
+ atomic.compareAndSet(0, 1); // Returns true if successful
294
+
295
+ // Utilities
296
+ isValidSequenceNumber(100); // true
297
+ isValidSequenceNumber(-1); // false
298
+ nextSequenceNumber(MAX_SEQUENCE_NUMBER); // Returns 0 (wrap-around)
299
+ ```
300
+
301
+ ## Timers
302
+
303
+ The package includes timer utilities for session management:
304
+
305
+ ```typescript
306
+ import { TimeoutTimer, OneShotTimer } from '@hla4ts/session';
307
+
308
+ // Periodic timeout timer
309
+ const timer = TimeoutTimer.createLazy(30000); // 30 second timeout
310
+ timer.start(() => {
311
+ console.log('Timeout!');
312
+ });
313
+ timer.extend(); // Reset the timeout
314
+ timer.pause(); // Stop checking
315
+ timer.resume(); // Resume checking
316
+ timer.cancel(); // Permanently cancel
317
+
318
+ // One-shot timer
319
+ const oneShot = new OneShotTimer();
320
+ oneShot.schedule(() => {
321
+ console.log('Fired!');
322
+ }, 5000);
323
+ oneShot.clear(); // Cancel before it fires
324
+ oneShot.cancel(); // Permanently cancel
325
+ ```
326
+
327
+ ## Message Encoding (Advanced)
328
+
329
+ For advanced use cases, you can encode/decode session control messages directly:
330
+
331
+ ```typescript
332
+ import {
333
+ createNewSessionMessage,
334
+ createHeartbeatMessage,
335
+ createHlaCallRequestMessage,
336
+ decodeHlaCallResponse,
337
+ decodeHlaCallbackRequest,
338
+ } from '@hla4ts/session';
339
+
340
+ // Create a new session message
341
+ const newSessionMsg = createNewSessionMessage();
342
+
343
+ // Create an HLA call request
344
+ const callMsg = createHlaCallRequestMessage(
345
+ sequenceNumber,
346
+ sessionId,
347
+ lastReceivedSequenceNumber,
348
+ protobufPayload
349
+ );
350
+
351
+ // Decode an HLA call response
352
+ const response = decodeHlaCallResponse(payload);
353
+ console.log(response.responseToSequenceNumber);
354
+ console.log(response.hlaServiceReturnValueOrException);
355
+ ```
356
+
357
+ ## Testing
358
+
359
+ ```bash
360
+ cd packages/session
361
+ bun test
362
+ ```
363
+
364
+ ## Related Packages
365
+
366
+ - [`@hla4ts/transport`](../transport) - Transport layer (TCP/TLS)
367
+ - [`@hla4ts/proto`](../proto) - Protocol buffer types
368
+ - [`@hla4ts/hla-api`](../hla-api) - High-level HLA API facade
369
+
370
+ ## References
371
+
372
+ - [IEEE 1516-2025](https://standards.ieee.org/standard/1516-2025.html) - HLA 4 Standard
373
+ - [Pitch FedProClient](https://github.com/Pitch-Technologies/FedProClient) - Reference implementation
374
+
375
+ ## License
376
+
377
+ MIT