@serfab/cadre-core 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +252 -0
  2. package/dist/arachnode-stub.d.ts +60 -0
  3. package/dist/arachnode-stub.js +120 -0
  4. package/dist/arachnode-stub.js.map +1 -0
  5. package/dist/cadre-node.d.ts +252 -0
  6. package/dist/cadre-node.js +753 -0
  7. package/dist/cadre-node.js.map +1 -0
  8. package/dist/control-database.d.ts +62 -0
  9. package/dist/control-database.js +295 -0
  10. package/dist/control-database.js.map +1 -0
  11. package/dist/enrollment.d.ts +76 -0
  12. package/dist/enrollment.js +126 -0
  13. package/dist/enrollment.js.map +1 -0
  14. package/dist/hibernation-manager.d.ts +68 -0
  15. package/dist/hibernation-manager.js +212 -0
  16. package/dist/hibernation-manager.js.map +1 -0
  17. package/dist/index.d.ts +12 -0
  18. package/dist/index.js +24 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/seed-bootstrap.d.ts +164 -0
  21. package/dist/seed-bootstrap.js +554 -0
  22. package/dist/seed-bootstrap.js.map +1 -0
  23. package/dist/strand-database.d.ts +39 -0
  24. package/dist/strand-database.js +108 -0
  25. package/dist/strand-database.js.map +1 -0
  26. package/dist/strand-formation-manager.d.ts +87 -0
  27. package/dist/strand-formation-manager.js +168 -0
  28. package/dist/strand-formation-manager.js.map +1 -0
  29. package/dist/strand-instance-manager.d.ts +60 -0
  30. package/dist/strand-instance-manager.js +209 -0
  31. package/dist/strand-instance-manager.js.map +1 -0
  32. package/dist/strand-solicitation.d.ts +145 -0
  33. package/dist/strand-solicitation.js +180 -0
  34. package/dist/strand-solicitation.js.map +1 -0
  35. package/dist/strand-watcher.d.ts +70 -0
  36. package/dist/strand-watcher.js +136 -0
  37. package/dist/strand-watcher.js.map +1 -0
  38. package/dist/types.d.ts +484 -0
  39. package/dist/types.js +26 -0
  40. package/dist/types.js.map +1 -0
  41. package/package.json +67 -0
  42. package/src/arachnode-stub.ts +160 -0
  43. package/src/cadre-node.ts +923 -0
  44. package/src/control-database.ts +376 -0
  45. package/src/enrollment.ts +199 -0
  46. package/src/hibernation-manager.ts +268 -0
  47. package/src/index.ts +71 -0
  48. package/src/seed-bootstrap.ts +753 -0
  49. package/src/strand-database.ts +168 -0
  50. package/src/strand-formation-manager.ts +277 -0
  51. package/src/strand-instance-manager.ts +281 -0
  52. package/src/strand-solicitation.ts +318 -0
  53. package/src/strand-watcher.ts +197 -0
  54. package/src/types.ts +553 -0
@@ -0,0 +1,268 @@
1
+ import debug from 'debug';
2
+ import type {
3
+ StrandInstance,
4
+ LatencyHint,
5
+ HibernationTimeouts,
6
+ HibernationConfig
7
+ } from './types.js';
8
+ import { HIBERNATION_TIMEOUTS } from './types.js';
9
+
10
+ const log = debug('sereus:cadre:hibernation');
11
+
12
+ /**
13
+ * Callbacks for hibernation state changes
14
+ */
15
+ export interface HibernationCallbacks {
16
+ onIdle: (strandId: string) => Promise<void>;
17
+ onHibernate: (strandId: string) => Promise<void>;
18
+ onWake: (strandId: string) => Promise<void>;
19
+ }
20
+
21
+ /**
22
+ * Manages strand hibernation state transitions based on activity.
23
+ *
24
+ * State machine:
25
+ * active → idle (after idleTimeout with no activity)
26
+ * idle → hibernating (after hibernateTimeout with no activity)
27
+ * idle → active (on activity)
28
+ * hibernating → active (on wake signal or check-in with pending activity)
29
+ */
30
+ export class HibernationManager {
31
+ private readonly config: HibernationConfig;
32
+ private readonly callbacks: HibernationCallbacks;
33
+ private readonly timers: Map<string, ReturnType<typeof setTimeout>> = new Map();
34
+ private readonly checkInTimers: Map<string, ReturnType<typeof setInterval>> = new Map();
35
+ private running = false;
36
+
37
+ constructor(config: HibernationConfig, callbacks: HibernationCallbacks) {
38
+ this.config = config;
39
+ this.callbacks = callbacks;
40
+ log('HibernationManager created, enabled=%s', config.enabled);
41
+ }
42
+
43
+ /**
44
+ * Get effective timeouts for a latency hint
45
+ */
46
+ private getTimeouts(hint: LatencyHint): HibernationTimeouts {
47
+ const defaults = HIBERNATION_TIMEOUTS[hint];
48
+ const custom = this.config.customTimeouts?.[hint];
49
+
50
+ if (!custom) return defaults;
51
+
52
+ return {
53
+ idleTimeout: custom.idleTimeout ?? defaults.idleTimeout,
54
+ hibernateTimeout: custom.hibernateTimeout ?? defaults.hibernateTimeout,
55
+ checkInInterval: custom.checkInInterval ?? defaults.checkInInterval
56
+ };
57
+ }
58
+
59
+ /**
60
+ * Start managing hibernation for all strands
61
+ */
62
+ start(): void {
63
+ if (this.running) return;
64
+ this.running = true;
65
+ log('HibernationManager started');
66
+ }
67
+
68
+ /**
69
+ * Stop managing hibernation
70
+ */
71
+ stop(): void {
72
+ if (!this.running) return;
73
+ this.running = false;
74
+
75
+ // Clear all timers
76
+ for (const timer of this.timers.values()) {
77
+ clearTimeout(timer);
78
+ }
79
+ this.timers.clear();
80
+
81
+ for (const timer of this.checkInTimers.values()) {
82
+ clearInterval(timer);
83
+ }
84
+ this.checkInTimers.clear();
85
+
86
+ log('HibernationManager stopped');
87
+ }
88
+
89
+ /**
90
+ * Register a strand for hibernation management
91
+ */
92
+ trackStrand(instance: StrandInstance): void {
93
+ if (!this.config.enabled || !this.running) return;
94
+
95
+ const { strandId, latencyHint } = instance;
96
+ const timeouts = this.getTimeouts(latencyHint);
97
+
98
+ // Don't track strands that never hibernate
99
+ if (timeouts.idleTimeout === Infinity) {
100
+ log('Strand %s has realtime latency hint - no hibernation', strandId);
101
+ return;
102
+ }
103
+
104
+ log('Tracking strand %s for hibernation (hint=%s)', strandId, latencyHint);
105
+ this.scheduleIdleTransition(instance);
106
+ }
107
+
108
+ /**
109
+ * Untrack a strand from hibernation management
110
+ */
111
+ untrackStrand(strandId: string): void {
112
+ this.clearTimers(strandId);
113
+ log('Untracked strand %s from hibernation', strandId);
114
+ }
115
+
116
+ /**
117
+ * Record activity on a strand - resets idle timer
118
+ */
119
+ recordActivity(instance: StrandInstance): void {
120
+ if (!this.config.enabled || !this.running) return;
121
+
122
+ const { strandId, status, latencyHint } = instance;
123
+ instance.lastActivity = new Date();
124
+
125
+ // If idle or hibernating, wake up
126
+ if (status === 'idle' || status === 'hibernating') {
127
+ log('Activity on %s strand %s - waking', status, strandId);
128
+ this.clearTimers(strandId);
129
+ void this.callbacks.onWake(strandId);
130
+ }
131
+
132
+ // Reschedule idle transition if active
133
+ if (status === 'active') {
134
+ const timeouts = this.getTimeouts(latencyHint);
135
+ if (timeouts.idleTimeout !== Infinity) {
136
+ this.scheduleIdleTransition(instance);
137
+ }
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Force wake a hibernating strand
143
+ */
144
+ async wakeStrand(strandId: string): Promise<void> {
145
+ this.clearTimers(strandId);
146
+ await this.callbacks.onWake(strandId);
147
+ }
148
+
149
+ private scheduleIdleTransition(instance: StrandInstance): void {
150
+ const { strandId, latencyHint } = instance;
151
+ const timeouts = this.getTimeouts(latencyHint);
152
+
153
+ // Clear existing timer
154
+ this.clearTimer(strandId);
155
+
156
+ // Schedule idle transition
157
+ const timer = setTimeout(() => {
158
+ this.handleIdleTimeout(instance);
159
+ }, timeouts.idleTimeout);
160
+
161
+ this.timers.set(strandId, timer);
162
+ }
163
+
164
+ private handleIdleTimeout(instance: StrandInstance): void {
165
+ const { strandId, latencyHint } = instance;
166
+
167
+ if (!this.running) return;
168
+
169
+ log('Idle timeout for strand %s', strandId);
170
+
171
+ // Transition to idle
172
+ void this.callbacks.onIdle(strandId).then(() => {
173
+ // Schedule hibernate transition
174
+ const timeouts = this.getTimeouts(latencyHint);
175
+ if (timeouts.hibernateTimeout !== Infinity) {
176
+ this.scheduleHibernateTransition(instance);
177
+ }
178
+ });
179
+ }
180
+
181
+ private scheduleHibernateTransition(instance: StrandInstance): void {
182
+ const { strandId, latencyHint } = instance;
183
+ const timeouts = this.getTimeouts(latencyHint);
184
+
185
+ // Clear existing timer
186
+ this.clearTimer(strandId);
187
+
188
+ // Schedule hibernate transition
189
+ const timer = setTimeout(() => {
190
+ this.handleHibernateTimeout(instance);
191
+ }, timeouts.hibernateTimeout);
192
+
193
+ this.timers.set(strandId, timer);
194
+ }
195
+
196
+ private handleHibernateTimeout(instance: StrandInstance): void {
197
+ const { strandId, latencyHint } = instance;
198
+
199
+ if (!this.running) return;
200
+
201
+ log('Hibernate timeout for strand %s', strandId);
202
+
203
+ // Transition to hibernating
204
+ void this.callbacks.onHibernate(strandId).then(() => {
205
+ // Schedule periodic check-ins
206
+ const timeouts = this.getTimeouts(latencyHint);
207
+ if (timeouts.checkInInterval !== Infinity) {
208
+ this.scheduleCheckIn(instance);
209
+ }
210
+ });
211
+ }
212
+
213
+ private scheduleCheckIn(instance: StrandInstance): void {
214
+ const { strandId, latencyHint } = instance;
215
+ const timeouts = this.getTimeouts(latencyHint);
216
+
217
+ // Clear existing check-in timer
218
+ const existing = this.checkInTimers.get(strandId);
219
+ if (existing) {
220
+ clearInterval(existing);
221
+ }
222
+
223
+ // Schedule periodic check-ins
224
+ const timer = setInterval(() => {
225
+ if (!this.running) {
226
+ clearInterval(timer);
227
+ return;
228
+ }
229
+
230
+ log('Check-in for hibernating strand %s', strandId);
231
+ instance.nextCheckIn = new Date(Date.now() + timeouts.checkInInterval);
232
+
233
+ // In a real implementation, this would query the cohort for pending activity
234
+ // For now, we just update the nextCheckIn timestamp
235
+ }, timeouts.checkInInterval);
236
+
237
+ this.checkInTimers.set(strandId, timer);
238
+ instance.nextCheckIn = new Date(Date.now() + timeouts.checkInInterval);
239
+ }
240
+
241
+ private clearTimer(strandId: string): void {
242
+ const timer = this.timers.get(strandId);
243
+ if (timer) {
244
+ clearTimeout(timer);
245
+ this.timers.delete(strandId);
246
+ }
247
+ }
248
+
249
+ private clearTimers(strandId: string): void {
250
+ this.clearTimer(strandId);
251
+
252
+ const checkInTimer = this.checkInTimers.get(strandId);
253
+ if (checkInTimer) {
254
+ clearInterval(checkInTimer);
255
+ this.checkInTimers.delete(strandId);
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Get the current status of hibernation tracking
261
+ */
262
+ getStatus(): { enabled: boolean; trackedStrands: number } {
263
+ return {
264
+ enabled: this.config.enabled && this.running,
265
+ trackedStrands: this.timers.size + this.checkInTimers.size
266
+ };
267
+ }
268
+ }
package/src/index.ts ADDED
@@ -0,0 +1,71 @@
1
+ // Core types
2
+ export * from './types.js';
3
+
4
+ // Main CadreNode class
5
+ export { CadreNode } from './cadre-node.js';
6
+
7
+ // Control database
8
+ export { ControlDatabase, type ControlDatabaseConfig } from './control-database.js';
9
+
10
+ // Strand database
11
+ export { StrandDatabase, type StrandDatabaseConfig } from './strand-database.js';
12
+
13
+ // Strand management
14
+ export {
15
+ StrandWatcher,
16
+ type StrandWatcherCallbacks,
17
+ type StrandQueryable,
18
+ type SAppIdLookup,
19
+ type StrandRowWithApp
20
+ } from './strand-watcher.js';
21
+ export {
22
+ StrandInstanceManager,
23
+ type StartStrandConfig,
24
+ getStrandStoragePath
25
+ } from './strand-instance-manager.js';
26
+
27
+ // Hibernation
28
+ export {
29
+ HibernationManager,
30
+ type HibernationCallbacks
31
+ } from './hibernation-manager.js';
32
+
33
+ // Arachnode (stub)
34
+ export {
35
+ ArachnodeStub,
36
+ createArachnodeStub,
37
+ type RingConfig
38
+ } from './arachnode-stub.js';
39
+
40
+ // Enrollment
41
+ export {
42
+ EnrollmentService,
43
+ type MemberVerifier,
44
+ type MemberRegistry
45
+ } from './enrollment.js';
46
+
47
+ // Strand Solicitation
48
+ export {
49
+ StrandSolicitationService,
50
+ type DisclosureValidator,
51
+ type FormationUsageRecorder,
52
+ type StrandProvisioner,
53
+ type FormationSigner,
54
+ type StrandSolicitationServiceOptions
55
+ } from './strand-solicitation.js';
56
+
57
+ // Seed Bootstrap
58
+ export {
59
+ SeedBootstrapService,
60
+ SEED_PROTOCOL,
61
+ type SeedBootstrapConfig,
62
+ type SeedEventCallbacks
63
+ } from './seed-bootstrap.js';
64
+
65
+ // Strand Formation (strand-proto integration)
66
+ export {
67
+ StrandFormationManager,
68
+ createStrandFormationManager,
69
+ type StrandFormationManagerConfig,
70
+ type StrandFormationManagerOptions
71
+ } from './strand-formation-manager.js';