From 5ed9dbbcb8562b552bcf4f49cd2f731464665348 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 29 Sep 2026 03:26:10 +0200 Subject: [PATCH] cultnet-ts: stop exporting signIdunnRuntimePresence; document two limits The function took state and lease digest from the caller, so anyone holding the authority could sign active without reportHealth or assertWriteLease. It is now private to the signer. Test: the subpath and root do not expose it. Docs: waitForWriteLease throws out of publish if health is already non-warming; MAX_RECENT_WARMING_PROOFS=64 is a recorded limit. Co-Authored-By: Claude Sonnet 5 --- packages/cultnet-ts/src/idunn-odin-presence-publisher.ts | 5 +++++ packages/cultnet-ts/src/idunn-runtime-authority.ts | 4 +++- packages/cultnet-ts/test/idunn-runtime-authority.test.ts | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/cultnet-ts/src/idunn-odin-presence-publisher.ts b/packages/cultnet-ts/src/idunn-odin-presence-publisher.ts index 2e992658..3713363d 100644 --- a/packages/cultnet-ts/src/idunn-odin-presence-publisher.ts +++ b/packages/cultnet-ts/src/idunn-odin-presence-publisher.ts @@ -15,6 +15,11 @@ export type IdunnRuntimePresencePublisher = { readonly requiresWriteLease: boolean; /** Publishes the signer's presence in the health the signer reports. */ publish(detail: string): Promise; + /** + * Publishes warming presence until Idunn's lease names one. Call it before + * `reportHealth('active')`: once the signer reports a non-warming health, + * `publish` inside this loop throws (it needs the lease) instead of polling. + */ waitForWriteLease(options?: { pollIntervalMs?: number; signal?: AbortSignal }): Promise; assertWriteLease(): Promise; }; diff --git a/packages/cultnet-ts/src/idunn-runtime-authority.ts b/packages/cultnet-ts/src/idunn-runtime-authority.ts index cd942cec..7f7b882f 100644 --- a/packages/cultnet-ts/src/idunn-runtime-authority.ts +++ b/packages/cultnet-ts/src/idunn-runtime-authority.ts @@ -29,6 +29,8 @@ const PROVIDER_PROTECTOR_CONTEXT = "gamecult-provider-health-identity-v1"; const ACTIVATION_ID_DOMAIN = Buffer.from("idunn.runtime-activation.id.v1\0", "utf8"); const CULTCACHE_STORE_FORMAT = "cultcache.store.v1"; const ED25519_PKCS8_PREFIX = Buffer.from("302e020100300506032b657004220420", "hex"); +// Limit: more than this many warmings signed between Idunn's observation and +// assertWriteLease would push the leased one out and refuse a valid lease. const MAX_RECENT_WARMING_PROOFS = 64; const authoritiesWithSigner = new WeakSet(); const authorityKeys = new WeakMap(); @@ -195,7 +197,7 @@ export function loadIdunnRuntimeAuthorityFromEnvironment( * Signs the fixed Idunn v2 positional runtime-presence contract with the * provider identity and this launch's Idunn-issued activation key. */ -export function signIdunnRuntimePresence( +function signIdunnRuntimePresence( authority: IdunnRuntimeAuthority, fields: Omit, ): { presence: RuntimePresenceHealth; payload: Uint8Array; canonicalSha256: string } { diff --git a/packages/cultnet-ts/test/idunn-runtime-authority.test.ts b/packages/cultnet-ts/test/idunn-runtime-authority.test.ts index 560f5933..b5c9236a 100644 --- a/packages/cultnet-ts/test/idunn-runtime-authority.test.ts +++ b/packages/cultnet-ts/test/idunn-runtime-authority.test.ts @@ -386,4 +386,6 @@ test("the idunn-runtime subpath loads the signer and loader without loading dgra assert.equal(typeof exported.createIdunnRuntimeSigner, "function"); assert.equal(typeof exported.loadIdunnRuntimeAuthorityFromEnvironment, "function"); assert.equal(exported.createIdunnRuntimePresencePublisher, undefined); + assert.equal(exported.signIdunnRuntimePresence, undefined); + assert.equal((require("cultnet-ts") as Record).signIdunnRuntimePresence, undefined); });