Ship DM connect delivery, fleet pubkey lookup, OpenClaw Infonet agent, and relay auto-wormhole.

Auto-relay connect DMs with End Contact severing, signed fleet prekey lookup,
OpenClaw private Infonet channel intents, headless relay Tor bootstrap on redeploy,
and swarm/DM live verification scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
BigBodyCobain
2026-06-12 02:15:56 -06:00
co-authored by Cursor
parent d48a0cdace
commit 89d6bb8fb9
52 changed files with 4211 additions and 339 deletions
+49
View File
@@ -0,0 +1,49 @@
/**
* Signal-style DM connect helpers — paste a short address or full invite blob.
*/
export function isLikelyDmShortAddress(value: string): boolean {
const trimmed = value.trim();
return (
!trimmed.startsWith('{') &&
!trimmed.startsWith('[') &&
/^[a-zA-Z0-9_.:-]{16,}$/.test(trimmed)
);
}
export function parseDmInviteImportBlob(raw: string): Record<string, unknown> {
const trimmed = raw.trim();
if (!trimmed) {
throw new Error('Paste a contact address first.');
}
if (isLikelyDmShortAddress(trimmed)) {
return { short_address: trimmed };
}
try {
const parsed = JSON.parse(trimmed) as unknown;
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
throw new Error('Contact address must be a signed address object.');
}
return parsed as Record<string, unknown>;
} catch (error) {
if (error instanceof SyntaxError) {
throw new Error('That does not look like a contact address. Paste what they copied from Secure Messages.');
}
throw error;
}
}
export function inviteFromParsedBlob(parsed: Record<string, unknown>): Record<string, unknown> {
const nested = parsed.invite;
if (nested && typeof nested === 'object' && !Array.isArray(nested)) {
return nested as Record<string, unknown>;
}
return parsed;
}
export function shortHandle(peerId: string): string {
const value = String(peerId || '').trim();
if (!value) return 'unknown';
if (value.length <= 18) return value;
return `${value.slice(0, 10)}${value.slice(-6)}`;
}
+40
View File
@@ -0,0 +1,40 @@
import type { Contact } from '@/mesh/meshIdentity';
import type { DmSendResponse } from '@/mesh/meshDmClient';
import { updatePrivateDeliveryAction } from '@/mesh/wormholeClient';
export type DmConnectIntent =
| 'invite_short_address'
| 'invite_import'
| 'contact_request'
| 'contact_accept'
| 'contact_offer';
export function connectDeliveryMeta(options: {
intent: DmConnectIntent;
lookupPeerUrl?: string;
contact?: Partial<Contact> | null;
}): { connectIntent: DmConnectIntent; lookupPeerUrl?: string } {
const lookupPeerUrl = String(
options.lookupPeerUrl || options.contact?.invitePinnedLookupPeerUrl || '',
)
.trim()
.replace(/\/$/, '');
return {
connectIntent: options.intent,
...(lookupPeerUrl ? { lookupPeerUrl } : {}),
};
}
/** Fallback when the server queued connect traffic but UI still shows a manual relay step. */
export async function ensureDmOutboxReleased(sent: DmSendResponse): Promise<DmSendResponse> {
if (!sent.ok) return sent;
const outboxId = String(sent.outbox_id || '').trim();
if (!outboxId) return sent;
if (!sent.queued && !sent.private_transport_pending) return sent;
try {
await updatePrivateDeliveryAction(outboxId, 'relay');
} catch {
// Backend auto-release may have already approved this outbox item.
}
return sent;
}
+67 -3
View File
@@ -89,6 +89,13 @@ export type DmSendResponse = {
private_transport_pending?: boolean;
};
export type DmConnectIntent =
| 'invite_short_address'
| 'invite_import'
| 'contact_request'
| 'contact_accept'
| 'contact_offer';
export type DmSendRequest = {
apiBase: string;
identity: NodeIdentity;
@@ -102,6 +109,8 @@ export type DmSendRequest = {
useSealedSender?: boolean;
format?: 'mls1' | 'dm1';
sessionWelcome?: string;
connectIntent?: DmConnectIntent;
lookupPeerUrl?: string;
};
const KEY_DM_BUNDLE_FINGERPRINT = 'sb_dm_bundle_fingerprint';
@@ -373,14 +382,54 @@ export async function ensureRegisteredDmKey(
};
}
function prekeyBundleToPublicKey(data: Record<string, unknown>): DmPublicKeyBundle | null {
if (!data?.ok) return null;
const bundle = (data.bundle && typeof data.bundle === 'object' ? data.bundle : data) as Record<
string,
unknown
>;
const dhPubKey = String(
bundle.identity_dh_pub_key || data.identity_dh_pub_key || data.dh_pub_key || '',
).trim();
const agentId = String(data.agent_id || '').trim();
if (!dhPubKey || !agentId) return null;
return {
ok: true,
agent_id: agentId,
lookup_mode: String(data.lookup_mode || 'invite_lookup_handle'),
dh_pub_key: dhPubKey,
dh_algo: String(data.dh_algo || bundle.dh_algo || 'X25519'),
timestamp: Number(data.timestamp || 0) || undefined,
signature: String(data.signature || ''),
public_key: String(data.public_key || ''),
public_key_algo: String(data.public_key_algo || ''),
sequence: Number(data.sequence || 0) || undefined,
prekey_transparency_head: String(data.prekey_transparency_head || ''),
prekey_transparency_size: Number(data.prekey_transparency_size || 0) || undefined,
};
}
async function fetchDmPublicKeyFromPrekeyBundle(
apiBase: string,
lookupToken: string,
): Promise<DmPublicKeyBundle | null> {
const params = new URLSearchParams({ lookup_token: lookupToken });
const res = await fetch(`${apiBase}/api/mesh/dm/prekey-bundle?${params.toString()}`);
const data = (await res.json()) as Record<string, unknown>;
return prekeyBundleToPublicKey(data);
}
export async function fetchDmPublicKey(
apiBase: string,
agentId: string,
lookupToken?: string,
options?: { allowLegacyAgentId?: boolean },
options?: { allowLegacyAgentId?: boolean; lookupPeerUrl?: string },
): Promise<DmPublicKeyBundle | null> {
const normalizedLookupToken = String(lookupToken || '').trim();
const normalizedAgentId = String(agentId || '').trim();
const normalizedLookupPeerUrl = String(options?.lookupPeerUrl || '')
.trim()
.replace(/\/$/, '');
if (!normalizedLookupToken && !options?.allowLegacyAgentId) {
return null;
}
@@ -388,12 +437,25 @@ export async function fetchDmPublicKey(
if (normalizedLookupToken) {
params.set('lookup_token', normalizedLookupToken);
}
if (normalizedLookupPeerUrl) {
params.set('lookup_peer_url', normalizedLookupPeerUrl);
}
if (normalizedAgentId && !normalizedLookupToken && options?.allowLegacyAgentId) {
params.set('agent_id', normalizedAgentId);
}
const res = await fetch(`${apiBase}/api/mesh/dm/pubkey?${params.toString()}`);
const data = await res.json();
return data.ok ? data : null;
const data = (await res.json()) as DmPublicKeyBundle;
if (data.ok && data.dh_pub_key) {
if (!data.agent_id && normalizedLookupToken) {
const fromPrekey = await fetchDmPublicKeyFromPrekeyBundle(apiBase, normalizedLookupToken);
if (fromPrekey) return fromPrekey;
}
return data;
}
if (normalizedLookupToken) {
return fetchDmPublicKeyFromPrekeyBundle(apiBase, normalizedLookupToken);
}
return null;
}
function spreadClaimPositions(totalClaims: number, spreadClaims: number): Set<number> {
@@ -684,6 +746,8 @@ export async function sendDmMessage(request: DmSendRequest): Promise<DmSendRespo
signature: signed.signature,
sequence: signed.sequence,
protocol_version: senderSeal && senderToken ? '' : signed.protocolVersion,
...(request.connectIntent ? { connect_intent: request.connectIntent } : {}),
...(request.lookupPeerUrl ? { lookup_peer_url: request.lookupPeerUrl } : {}),
}),
});
return res.json();
+31
View File
@@ -1350,6 +1350,7 @@ export interface Contact {
invitePinnedDhPubKey?: string;
invitePinnedDhAlgo?: string;
invitePinnedPrekeyLookupHandle?: string;
invitePinnedLookupPeerUrl?: string;
invitePinnedRootFingerprint?: string;
invitePinnedRootManifestFingerprint?: string;
invitePinnedRootWitnessPolicyFingerprint?: string;
@@ -1441,6 +1442,7 @@ function sanitizeContact(contact: Partial<Contact> | undefined): Contact {
invitePinnedDhPubKey: String(contact?.invitePinnedDhPubKey || ''),
invitePinnedDhAlgo: String(contact?.invitePinnedDhAlgo || ''),
invitePinnedPrekeyLookupHandle: String(contact?.invitePinnedPrekeyLookupHandle || ''),
invitePinnedLookupPeerUrl: String(contact?.invitePinnedLookupPeerUrl || ''),
invitePinnedRootFingerprint: String(contact?.invitePinnedRootFingerprint || ''),
invitePinnedRootManifestFingerprint: String(contact?.invitePinnedRootManifestFingerprint || ''),
invitePinnedRootWitnessPolicyFingerprint: String(
@@ -1775,6 +1777,35 @@ export function removeContact(agentId: string): void {
}
}
export async function severContact(
agentId: string,
options: { block?: boolean } = {},
): Promise<void> {
const peerId = String(agentId || '').trim();
if (!peerId) return;
await controlPlaneJson(`/api/wormhole/dm/contact/${encodeURIComponent(peerId)}/sever`, {
method: 'POST',
requireAdminSession: false,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ block: Boolean(options.block) }),
});
const contacts = getContacts();
if (!(peerId in contacts)) return;
contacts[peerId] = sanitizeContact({
...contacts[peerId],
sharedAlias: undefined,
previousSharedAliases: [],
pendingSharedAlias: undefined,
sharedAliasGraceUntil: undefined,
sharedAliasRotatedAt: undefined,
...(options.block ? { blocked: true } : {}),
});
saveContacts(contacts);
if (shouldUseWormholeContacts()) {
await persistContactToWormhole(peerId, contacts[peerId]);
}
}
export function isBlocked(agentId: string): boolean {
return getContacts()[agentId]?.blocked || false;
}
@@ -2016,6 +2016,18 @@ export async function deleteWormholeDmContact(
});
}
export async function severWormholeDmContact(
peerId: string,
options: { block?: boolean } = {},
): Promise<{ ok: boolean; peer_id: string; severed?: boolean; blocked?: boolean }> {
return controlPlaneJson(`/api/wormhole/dm/contact/${encodeURIComponent(peerId)}/sever`, {
method: 'POST',
requireAdminSession: false,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ block: Boolean(options.block) }),
});
}
export async function getActiveSigningContext(): Promise<ActiveSigningContext | null> {
const secureRequired = await isWormholeSecureRequired();
if (await isWormholeReady()) {