@@ -39,8 +39,10 @@ export const DEFAULT_MAX_URL_RELAY_HINTS = 3;
3939export const DEFAULT_MAX_KNOWN_RELAYS = 20 ;
4040
4141/**
42- * Enforce the relay pool cap by keeping all bootstrap entries and the newest
43- * non-bootstrap entries, up to `cap`.
42+ * Enforce the relay pool cap by prioritizing bootstrap entries, then the
43+ * newest non-bootstrap entries, up to `cap`. If bootstrap entries alone
44+ * exceed the cap, the result is truncated to `cap` (some bootstrap entries
45+ * may be dropped).
4446 *
4547 * @param entries - The full set of relay entries.
4648 * @param cap - The maximum pool size.
@@ -118,14 +120,14 @@ async function generateKeyInfo(seedString?: string): Promise<[string, string]> {
118120 * operations) without starting any network communications.
119121 *
120122 * @param kernelStore - The kernel store, for storing persistent key info.
121- * @param options - Options for identity initialization.
122- * @param options.relays - Bootstrap relay addresses. These are merged into
123+ * @param [ options] - Options for identity initialization.
124+ * @param [ options.relays] - Bootstrap relay addresses. These are merged into
123125 * the relay pool, marked as bootstrap (prioritized during eviction and URL
124126 * selection), and persisted. Relays previously marked as bootstrap that are
125127 * no longer in this list have their bootstrap flag cleared.
126- * @param options.mnemonic - BIP39 mnemonic for seed recovery.
127- * @param options.maxUrlRelayHints - Cap on relay hints per OCAP URL.
128- * @param options.maxKnownRelays - Cap on the stored relay pool.
128+ * @param [ options.mnemonic] - BIP39 mnemonic for seed recovery.
129+ * @param [ options.maxUrlRelayHints] - Cap on relay hints per OCAP URL.
130+ * @param [ options.maxKnownRelays] - Cap on the stored relay pool.
129131 * @param logger - The logger to use.
130132 * @param keySeed - Optional seed for key generation.
131133 * @returns the identity object, the key seed, and known relays.
@@ -155,8 +157,20 @@ export async function initRemoteIdentity(
155157 options ?. maxUrlRelayHints ?? DEFAULT_MAX_URL_RELAY_HINTS ;
156158 const maxKnownRelays = options ?. maxKnownRelays ?? DEFAULT_MAX_KNOWN_RELAYS ;
157159
160+ if (
161+ ! Number . isInteger ( maxUrlRelayHints ) ||
162+ maxUrlRelayHints < 1 ||
163+ ! Number . isInteger ( maxKnownRelays ) ||
164+ maxKnownRelays < 1
165+ ) {
166+ throw Error (
167+ `maxUrlRelayHints (${ maxUrlRelayHints } ) and maxKnownRelays (${ maxKnownRelays } ) must be positive integers` ,
168+ ) ;
169+ }
170+
158171 if ( relays . length > 0 ) {
159- // Date.now() is available under SES lockdown (on the intrinsics allow-list).
172+ // Date.now() works here because this code runs in the start compartment,
173+ // which retains the original Date constructor (%InitialDate%).
160174 const now = Date . now ( ) ;
161175 const bootstrapSet = new Set ( relays ) ;
162176
@@ -174,7 +188,7 @@ export async function initRemoteIdentity(
174188 byAddr . set ( addr , { addr, lastSeen : now , isBootstrap : true } ) ;
175189 }
176190 // Clear bootstrap flag on entries no longer in the current bootstrap set
177- // (create new objects to avoid mutating potentially-hardened entries )
191+ // (create new objects to follow immutability conventions )
178192 for ( const [ addr , entry ] of byAddr . entries ( ) ) {
179193 if ( entry . isBootstrap && ! bootstrapSet . has ( addr ) ) {
180194 byAddr . set ( addr , { ...entry , isBootstrap : false } ) ;
@@ -269,15 +283,17 @@ export async function initRemoteIdentity(
269283 /**
270284 * Add relay addresses to the kernel's known relay pool.
271285 * Deduplicates, updates lastSeen on re-observation, and enforces
272- * {@link MAX_KNOWN_RELAYS} by evicting the oldest non-bootstrap entries.
286+ * the configured `maxKnownRelays` cap by evicting the oldest
287+ * non-bootstrap entries.
273288 *
274289 * @param newRelays - Relay multiaddrs to add.
275290 */
276291 function addKnownRelays ( newRelays : string [ ] ) : void {
277292 if ( newRelays . length === 0 ) {
278293 return ;
279294 }
280- // Date.now() is available under SES lockdown (on the intrinsics allow-list).
295+ // Date.now() works here because this code runs in the start compartment,
296+ // which retains the original Date constructor (%InitialDate%).
281297 const now = Date . now ( ) ;
282298 const existing = kernelStore . getRelayEntries ( ) ;
283299 const byAddr = new Map ( existing . map ( ( entry ) => [ entry . addr , entry ] ) ) ;
@@ -286,8 +302,8 @@ export async function initRemoteIdentity(
286302 for ( const addr of newRelays ) {
287303 const entry = byAddr . get ( addr ) ;
288304 if ( entry ) {
289- // Update lastSeen on re-observation (create new object to avoid
290- // mutating potentially-hardened deserialized entries )
305+ // Update lastSeen on re-observation (create new object to follow
306+ // immutability conventions )
291307 if ( entry . lastSeen !== now ) {
292308 byAddr . set ( addr , { ...entry , lastSeen : now } ) ;
293309 changed = true ;
@@ -339,11 +355,16 @@ export async function initRemoteIdentity(
339355 return kref ;
340356 }
341357
342- return {
343- identity : { getPeerId, issueOcapURL, redeemLocalOcapURL, addKnownRelays } ,
358+ return harden ( {
359+ identity : harden ( {
360+ getPeerId,
361+ issueOcapURL,
362+ redeemLocalOcapURL,
363+ addKnownRelays,
364+ } ) ,
344365 keySeed,
345366 knownRelays : kernelStore . getKnownRelayAddresses ( ) ,
346- } ;
367+ } ) ;
347368}
348369
349370/**
@@ -352,7 +373,7 @@ export async function initRemoteIdentity(
352373 * @param kernelStore - The kernel store, for storing persistent key info.
353374 * @param platformServices - The platform services, for accessing network I/O
354375 * operations that are not available within the web worker that the kernel runs in.
355- * @param remoteMessageHandler - Handler to process received inbound communcations .
376+ * @param remoteMessageHandler - Handler to process received inbound communications .
356377 * @param options - Options for remote communications initialization.
357378 * @param logger - The logger to use.
358379 * @param keySeed - Optional seed for libp2p key generation.
@@ -373,16 +394,17 @@ export async function initRemoteComms(
373394 incarnationId ?: string ,
374395 onIncarnationChange ?: OnIncarnationChange ,
375396) : Promise < RemoteComms > {
376- const { relays = [ ] , mnemonic, maxUrlRelayHints, maxKnownRelays } = options ;
397+ const {
398+ relays = [ ] ,
399+ mnemonic,
400+ maxUrlRelayHints,
401+ maxKnownRelays,
402+ ...platformOptions
403+ } = options ;
377404
378405 const result = await initRemoteIdentity (
379406 kernelStore ,
380- {
381- relays,
382- ...( mnemonic === undefined ? { } : { mnemonic } ) ,
383- maxUrlRelayHints,
384- maxKnownRelays,
385- } ,
407+ { relays, mnemonic, maxUrlRelayHints, maxKnownRelays } ,
386408 logger ,
387409 keySeed ,
388410 ) ;
@@ -395,9 +417,11 @@ export async function initRemoteComms(
395417 // called before initializeRemoteComms to capture the pre-restart timestamp.
396418 const wakeDetected = kernelStore . detectWake ( ) ;
397419
420+ // Omit mnemonic (sensitive key material) from the options passed to
421+ // platform services, which only needs network-level configuration.
398422 await platformServices . initializeRemoteComms (
399423 result . keySeed ,
400- { ...options , relays : knownRelays } ,
424+ { ...platformOptions , relays : knownRelays } ,
401425 remoteMessageHandler ,
402426 onRemoteGiveUp ,
403427 incarnationId ,
0 commit comments