@tangle-network/agent-integrations 0.54.0 → 0.54.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.
|
@@ -71,6 +71,8 @@ interface ManagedNumberOrder {
|
|
|
71
71
|
connectionId?: string;
|
|
72
72
|
status: 'pending' | 'provider_pending' | 'needs_review' | 'ready_for_setup' | 'cancelled';
|
|
73
73
|
errorCode?: string;
|
|
74
|
+
/** HTTP status behind `errorCode`, when the provider gave one. 402, 401 and 422 need different operator work. */
|
|
75
|
+
errorStatus?: number;
|
|
74
76
|
nextAttemptAt?: number;
|
|
75
77
|
}
|
|
76
78
|
interface ManagedNumberOrderStore {
|
|
@@ -189,18 +189,21 @@ function selectedNumber(order, identity) {
|
|
|
189
189
|
return order.transport === "sms" ? identity.sms : identity.imessageEnabled ? identity.imessage : null;
|
|
190
190
|
}
|
|
191
191
|
var IN_FLIGHT_MS = 5 * 6e4;
|
|
192
|
+
var REVIEW_BACKOFF_MS = 6 * 60 * 6e4;
|
|
192
193
|
async function advanceManagedNumber(orderId, ports) {
|
|
193
194
|
let order = await ports.orders.get(orderId);
|
|
194
195
|
if (!order) throw new Error("Managed number order not found");
|
|
195
|
-
if (!order.id || order.id.length > 128 || !/^[a-zA-Z0-9:._-]+$/.test(order.id) || order.id !== orderId || !order.ownerId || !order.organizationId || !order.fundingAuthorizationId || !["sms", "imessage"].includes(order.transport) || !["identity", "number", "credential", "connection", "complete"].includes(order.phase) ||
|
|
196
|
+
if (!order.id || order.id.length > 128 || !/^[a-zA-Z0-9:._-]+$/.test(order.id) || order.id !== orderId || !order.ownerId || !order.organizationId || !order.fundingAuthorizationId || !["sms", "imessage"].includes(order.transport) || !["identity", "number", "credential", "connection", "complete"].includes(order.phase) || // The provider refuses a malformed state; reject it here so it can never reach a purchase.
|
|
197
|
+
order.state !== void 0 && !/^[A-Z]{2}$/.test(order.state) || !Number.isSafeInteger(order.version) || order.version < 0) throw new MessagingProvisionError("invalid_input");
|
|
196
198
|
let mutationRefused = false;
|
|
197
199
|
let mutationSettled = false;
|
|
198
200
|
if (order.phase === "complete" || order.status === "cancelled") return order;
|
|
199
|
-
const
|
|
201
|
+
const clock = ports.now ?? Date.now;
|
|
202
|
+
const now = clock();
|
|
200
203
|
if (order.nextAttemptAt && order.nextAttemptAt > now) return order;
|
|
201
204
|
async function save(patch) {
|
|
202
205
|
const before = order;
|
|
203
|
-
const next = { ...before, ...patch, version: before.version + 1 };
|
|
206
|
+
const next = { ...before, ..."errorCode" in patch && !("errorStatus" in patch) ? { errorStatus: void 0 } : {}, ...patch, version: before.version + 1 };
|
|
204
207
|
if (await ports.orders.saveIfVersion(next, before.version)) {
|
|
205
208
|
order = next;
|
|
206
209
|
return next;
|
|
@@ -231,7 +234,7 @@ async function advanceManagedNumber(orderId, ports) {
|
|
|
231
234
|
try {
|
|
232
235
|
return await call();
|
|
233
236
|
} catch (error) {
|
|
234
|
-
if (error instanceof MessagingProvisionError && error.code === "provider_rejected") mutationRefused = true;
|
|
237
|
+
if (error instanceof MessagingProvisionError && (error.code === "provider_rejected" || error.code === "invalid_input")) mutationRefused = true;
|
|
235
238
|
throw error;
|
|
236
239
|
} finally {
|
|
237
240
|
mutationSettled = true;
|
|
@@ -239,7 +242,7 @@ async function advanceManagedNumber(orderId, ports) {
|
|
|
239
242
|
}
|
|
240
243
|
async function claim() {
|
|
241
244
|
const before = order;
|
|
242
|
-
const claimed = await save({ attempted: true, attemptedAt:
|
|
245
|
+
const claimed = await save({ attempted: true, attemptedAt: clock(), status: "pending", errorCode: void 0, nextAttemptAt: void 0 });
|
|
243
246
|
if (claimed.version !== before.version + 1 || order !== claimed) return false;
|
|
244
247
|
let authorized = false;
|
|
245
248
|
try {
|
|
@@ -263,11 +266,11 @@ async function advanceManagedNumber(orderId, ports) {
|
|
|
263
266
|
const current = await ports.orders.get(orderId);
|
|
264
267
|
if (!current || current.version !== order.version || current.status === "cancelled") return false;
|
|
265
268
|
if (!await ports.canProvision(current)) {
|
|
266
|
-
await save({ status: "provider_pending", errorCode: "activation_not_configured", nextAttemptAt:
|
|
269
|
+
await save({ status: "provider_pending", errorCode: "activation_not_configured", nextAttemptAt: clock() + 6e4 });
|
|
267
270
|
return false;
|
|
268
271
|
}
|
|
269
272
|
if (!await ports.authorizeFunding(current)) {
|
|
270
|
-
await save({ status: "provider_pending", errorCode: "funding_required", nextAttemptAt:
|
|
273
|
+
await save({ status: "provider_pending", errorCode: "funding_required", nextAttemptAt: clock() + 6e4 });
|
|
271
274
|
return false;
|
|
272
275
|
}
|
|
273
276
|
const rechecked = await ports.orders.get(orderId);
|
|
@@ -278,29 +281,29 @@ async function advanceManagedNumber(orderId, ports) {
|
|
|
278
281
|
let identity2 = await ports.provider.getIdentity(order.handle);
|
|
279
282
|
if (!identity2) {
|
|
280
283
|
if (inFlight(order)) return order;
|
|
281
|
-
if (order.attempted) return save({ status: "needs_review", errorCode: "identity_outcome_unknown" });
|
|
284
|
+
if (order.attempted) return save({ status: "needs_review", errorCode: "identity_outcome_unknown", nextAttemptAt: clock() + REVIEW_BACKOFF_MS });
|
|
282
285
|
if (!await claim()) return await ports.orders.get(orderId);
|
|
283
286
|
const handle = order.handle;
|
|
284
287
|
identity2 = await mutate(() => ports.provider.createIdentity(handle));
|
|
285
288
|
} else if (!order.attempted && !order.identityId) {
|
|
286
|
-
return save({ status: "needs_review", errorCode: "identity_already_exists" });
|
|
289
|
+
return save({ status: "needs_review", errorCode: "identity_already_exists", nextAttemptAt: clock() + REVIEW_BACKOFF_MS });
|
|
287
290
|
}
|
|
288
291
|
identityMatches(order, identity2);
|
|
289
292
|
return save({ identityId: identity2.id, phase: "number", attempted: false, status: "pending", errorCode: void 0 });
|
|
290
293
|
}
|
|
291
294
|
if (!order.identityId) throw new MessagingProvisionError("invalid_receipt");
|
|
292
295
|
const identity = await ports.provider.getIdentity(order.handle);
|
|
293
|
-
if (!identity) return save({ status: "needs_review", errorCode: "identity_missing" });
|
|
296
|
+
if (!identity) return save({ status: "needs_review", errorCode: "identity_missing", nextAttemptAt: clock() + REVIEW_BACKOFF_MS });
|
|
294
297
|
identityMatches(order, identity);
|
|
295
298
|
if (order.phase === "number") {
|
|
296
299
|
let number2 = selectedNumber(order, identity);
|
|
297
|
-
if (!number2 && order.number) return save({ status: "needs_review", errorCode: "number_missing" });
|
|
300
|
+
if (!number2 && order.number) return save({ status: "needs_review", errorCode: "number_missing", nextAttemptAt: clock() + REVIEW_BACKOFF_MS });
|
|
298
301
|
if (!number2) {
|
|
299
302
|
if (order.attempted && order.transport === "imessage" && identity.imessageEnabled) {
|
|
300
|
-
return save({ status: "provider_pending", errorCode: "number_pending", nextAttemptAt:
|
|
303
|
+
return save({ status: "provider_pending", errorCode: "number_pending", nextAttemptAt: clock() + 3e4 });
|
|
301
304
|
}
|
|
302
305
|
if (inFlight(order)) return order;
|
|
303
|
-
if (order.attempted) return save({ status: "needs_review", errorCode: "number_outcome_unknown" });
|
|
306
|
+
if (order.attempted) return save({ status: "needs_review", errorCode: "number_outcome_unknown", nextAttemptAt: clock() + REVIEW_BACKOFF_MS });
|
|
304
307
|
if (!await claim()) return await ports.orders.get(orderId);
|
|
305
308
|
const { handle, state, id } = order;
|
|
306
309
|
if (order.transport === "sms") {
|
|
@@ -318,10 +321,10 @@ async function advanceManagedNumber(orderId, ports) {
|
|
|
318
321
|
number2 = selectedNumber(order, receipt);
|
|
319
322
|
}
|
|
320
323
|
}
|
|
321
|
-
if (!number2) return save({ status: "provider_pending", errorCode: "number_pending", nextAttemptAt:
|
|
324
|
+
if (!number2) return save({ status: "provider_pending", errorCode: "number_pending", nextAttemptAt: clock() + 3e4 });
|
|
322
325
|
if (order.number && (order.number.id !== number2.id || order.number.number !== number2.number)) throw new MessagingProvisionError("invalid_receipt");
|
|
323
326
|
if (order.transport === "sms" && (number2.smsStatus !== "ready" || number2.status !== "active")) {
|
|
324
|
-
return save({ number: number2, attempted: false, status: "provider_pending", nextAttemptAt:
|
|
327
|
+
return save({ number: number2, attempted: false, status: "provider_pending", nextAttemptAt: clock() + 3e4, errorCode: "sms_not_ready" });
|
|
325
328
|
}
|
|
326
329
|
return save({ number: number2, phase: "credential", attempted: false, status: "pending", errorCode: void 0, nextAttemptAt: void 0 });
|
|
327
330
|
}
|
|
@@ -331,7 +334,7 @@ async function advanceManagedNumber(orderId, ports) {
|
|
|
331
334
|
let credential2 = await ports.vault.read(order.id);
|
|
332
335
|
if (!credential2) {
|
|
333
336
|
if (inFlight(order)) return order;
|
|
334
|
-
if (order.attempted) return save({ status: "needs_review", errorCode: "credential_receipt_lost" });
|
|
337
|
+
if (order.attempted) return save({ status: "needs_review", errorCode: "credential_receipt_lost", nextAttemptAt: clock() + REVIEW_BACKOFF_MS });
|
|
335
338
|
if (!await claim()) return await ports.orders.get(orderId);
|
|
336
339
|
const { identityId, id } = order;
|
|
337
340
|
const minted = await mutate(() => ports.provider.mintIdentityKey(identityId, `Tangle number ${id}`));
|
|
@@ -352,12 +355,15 @@ async function advanceManagedNumber(orderId, ports) {
|
|
|
352
355
|
const code = error instanceof MessagingProvisionError ? error.code : "outcome_unknown";
|
|
353
356
|
const retryAfter = error instanceof MessagingProvisionError ? error.retryAfterSeconds : void 0;
|
|
354
357
|
const refused = mutationRefused && order.phase !== "credential";
|
|
358
|
+
const review = code === "invalid_receipt";
|
|
359
|
+
const failedAt = clock();
|
|
355
360
|
return save({
|
|
356
|
-
status:
|
|
361
|
+
status: review ? "needs_review" : "provider_pending",
|
|
357
362
|
errorCode: code,
|
|
363
|
+
errorStatus: error instanceof MessagingProvisionError ? error.status : void 0,
|
|
358
364
|
...refused ? { attempted: false } : {},
|
|
359
365
|
...mutationSettled ? { attemptedAt: void 0 } : {},
|
|
360
|
-
nextAttemptAt:
|
|
366
|
+
nextAttemptAt: failedAt + (review ? REVIEW_BACKOFF_MS : Math.max(30, Math.min(retryAfter ?? 30, 86400)) * 1e3)
|
|
361
367
|
});
|
|
362
368
|
}
|
|
363
369
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/managed-messaging/inkbox.ts","../../src/managed-messaging/provision.ts"],"sourcesContent":["export type ManagedMessageTransport = 'sms' | 'imessage'\nexport interface InkboxNumber { id: string; number: string; smsStatus: string | null; status: string | null }\nexport interface InkboxIdentity {\n id: string\n handle: string\n organizationId: string\n status: string\n imessageEnabled: boolean\n sms: InkboxNumber | null\n imessage: InkboxNumber | null\n}\nexport class MessagingProvisionError extends Error {\n constructor(\n readonly code: 'invalid_input' | 'unavailable' | 'provider_rejected' | 'outcome_unknown' | 'invalid_receipt',\n readonly status?: number,\n readonly retryAfterSeconds?: number,\n ) {\n super(`Messaging provisioning: ${code}${status ? ` (HTTP ${status})` : ''}`)\n this.name = 'MessagingProvisionError'\n }\n}\nconst BASE = 'https://inkbox.ai/api/v1'\nconst UUID = /^[a-f\\d]{8}(?:-[a-f\\d]{4}){3}-[a-f\\d]{12}$/i\nconst PHONE = /^\\+[1-9]\\d{6,14}$/\nconst HANDLE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new MessagingProvisionError('invalid_receipt')\n return value as Record<string, unknown>\n}\nfunction readNumber(value: unknown): InkboxNumber | null {\n if (value == null) return null\n const row = record(value)\n if (typeof row.id !== 'string' || !UUID.test(row.id) || typeof row.number !== 'string' || !PHONE.test(row.number)) throw new MessagingProvisionError('invalid_receipt')\n return { id: row.id, number: row.number, smsStatus: typeof row.sms_status === 'string' ? row.sms_status : null, status: typeof row.status === 'string' ? row.status : null }\n}\n/** Project only channel identity. Mailbox, tunnel, credentials and contacts never leave this boundary. */\nexport function parseInkboxIdentity(value: unknown): InkboxIdentity {\n const row = record(value)\n if (typeof row.id !== 'string' || !UUID.test(row.id) || typeof row.agent_handle !== 'string' ||\n row.agent_handle.length < 3 || row.agent_handle.length > 63 || !HANDLE.test(row.agent_handle) ||\n typeof row.organization_id !== 'string' || !row.organization_id || row.organization_id.length > 256 ||\n typeof row.status !== 'string' || !row.status || typeof row.imessage_enabled !== 'boolean') throw new MessagingProvisionError('invalid_receipt')\n return { id: row.id, handle: row.agent_handle, organizationId: row.organization_id, status: row.status,\n imessageEnabled: row.imessage_enabled, sms: readNumber(row.phone_number), imessage: readNumber(row.imessage_number) }\n}\nfunction assertHandle(value: string): void {\n if (value.length < 3 || value.length > 63 || !HANDLE.test(value)) throw new MessagingProvisionError('invalid_input')\n}\nfunction assertOperation(value: string): void {\n if (!value || value.length > 200 || !/^[a-zA-Z0-9:._-]+$/.test(value)) throw new MessagingProvisionError('invalid_input')\n}\nasync function readJson(response: Response): Promise<unknown> {\n if (!response.body) throw new MessagingProvisionError('invalid_receipt')\n const reader = response.body.getReader()\n const chunks: Uint8Array[] = []; let size = 0\n try {\n while (true) {\n const chunk = await reader.read()\n if (chunk.done) break\n size += chunk.value.byteLength\n if (size > 1_048_576) { await reader.cancel(); throw new MessagingProvisionError('invalid_receipt') }\n chunks.push(chunk.value)\n }\n const bytes = new Uint8Array(size); let offset = 0\n for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length }\n return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes)) as unknown\n } catch { throw new MessagingProvisionError('invalid_receipt') }\n finally { reader.releaseLock() }\n}\n\n/**\n * A read that fails transiently is `unavailable`: it says nothing about a\n * mutation that already succeeded. Only a mutation's own definitive 4xx is\n * `provider_rejected`, which is what permits another purchase attempt.\n */\nfunction failureCode(method: string, status: number): MessagingProvisionError['code'] {\n const transient = status >= 500 || status === 408\n if (method === 'GET') return transient || status === 429 ? 'unavailable' : 'provider_rejected'\n return transient ? 'outcome_unknown' : 'provider_rejected'\n}\n\n/** Host-only administrative client; NOT a ConnectorAdapter and never an agent tool. */\nexport class InkboxProvisioner {\n private readonly fetchImpl: typeof fetch\n private readonly timeoutMs: number\n readonly #adminKey: string\n constructor(options: { adminKey: string; fetchImpl?: typeof fetch; timeoutMs?: number }) {\n if (!options.adminKey || options.adminKey.length > 4096 || /[^\\x21-\\x7e]/.test(options.adminKey)) throw new MessagingProvisionError('unavailable')\n this.#adminKey = options.adminKey\n this.fetchImpl = options.fetchImpl ?? fetch.bind(globalThis)\n this.timeoutMs = options.timeoutMs ?? 15_000\n if (!Number.isSafeInteger(this.timeoutMs) || this.timeoutMs < 1 || this.timeoutMs > 120_000) throw new MessagingProvisionError('invalid_input')\n }\n private async request(method: 'GET' | 'POST' | 'PATCH' | 'DELETE', path: string, body?: unknown, operationId?: string, key = this.#adminKey): Promise<unknown> {\n let response: Response\n try {\n response = await this.fetchImpl(`${BASE}${path}`, { method, redirect: 'error', signal: AbortSignal.timeout(this.timeoutMs),\n headers: { 'X-API-Key': key, ...(body === undefined ? {} : { 'Content-Type': 'application/json' }), ...(operationId ? { 'Idempotency-Key': operationId } : {}) },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }) })\n } catch { throw new MessagingProvisionError(method === 'GET' ? 'unavailable' : 'outcome_unknown') }\n if ((method === 'GET' || method === 'DELETE') && response.status === 404) return null\n if (!response.ok) {\n const retry = response.headers.get('retry-after')\n const seconds = retry && /^\\d+$/.test(retry) && Number.isSafeInteger(Number(retry)) ? Number(retry) : undefined\n throw new MessagingProvisionError(failureCode(method, response.status), response.status, seconds)\n }\n if (method === 'DELETE' && response.status === 204) return null\n return readJson(response)\n }\n async verifyAdminKey(): Promise<void> {\n const self = record(await this.request('GET', '/api-keys/self'))\n if (self.scoped_identity_id !== null || self.status !== 'active') throw new MessagingProvisionError('invalid_receipt')\n }\n async getIdentity(agentHandle: string): Promise<InkboxIdentity | null> {\n assertHandle(agentHandle)\n const value = await this.request('GET', `/identities/${encodeURIComponent(agentHandle)}`)\n if (value === null) return null\n return this.identityReceipt(value, agentHandle)\n }\n async createIdentity(agentHandle: string): Promise<InkboxIdentity> {\n assertHandle(agentHandle)\n return this.identityReceipt(await this.request('POST', '/identities', {\n agent_handle: agentHandle, imessage_enabled: false, contact_sharing_enabled: false,\n mailbox: { sending_domain: null },\n }), agentHandle)\n }\n async claimIMessage(agentHandle: string, operationId: string): Promise<InkboxIdentity> {\n assertHandle(agentHandle); assertOperation(operationId)\n return this.identityReceipt(await this.request('PATCH', `/identities/${encodeURIComponent(agentHandle)}`,\n { imessage_enabled: true, claim_imessage_number: true }, operationId), agentHandle)\n }\n async provisionSms(agentHandle: string, operationId: string, state?: string): Promise<InkboxNumber> {\n assertHandle(agentHandle); assertOperation(operationId)\n if (state !== undefined && !/^[A-Z]{2}$/.test(state)) throw new MessagingProvisionError('invalid_input')\n const result = readNumber(await this.request('POST', '/phone/numbers', {\n agent_handle: agentHandle, type: 'local', incoming_call_action: 'auto_reject', ...(state ? { state } : {}),\n }, operationId))\n if (!result) throw new MessagingProvisionError('invalid_receipt')\n return result\n }\n /** Encrypt before any other work. A lost response cannot be repaired by blindly minting another key. */\n async mintIdentityKey(identityId: string, label: string): Promise<{ key: string; keyId: string }> {\n if (!UUID.test(identityId) || !label.trim() || label.length > 255) throw new MessagingProvisionError('invalid_input')\n const result = record(await this.request('POST', '/api-keys', { label, scoped_identity_id: identityId }))\n const meta = record(result.record)\n if (meta.scoped_identity_id !== identityId || typeof result.api_key !== 'string' || !result.api_key || result.api_key.length > 4096 ||\n /[^\\x21-\\x7e]/.test(result.api_key) || typeof meta.id !== 'string' || !meta.id) throw new MessagingProvisionError('invalid_receipt')\n // Only a successful receipt is returned. The host journals this call before sending it.\n return { key: result.api_key, keyId: meta.id }\n }\n /** Safe read after the once-shown key is durable in the host vault. */\n async verifyIdentityKey(key: string, identityId: string, keyId: string): Promise<void> {\n if (!UUID.test(identityId) || !key || /[^\\x21-\\x7e]/.test(key) || key.length > 4096 || !keyId) throw new MessagingProvisionError('invalid_input')\n const self = record(await this.request('GET', '/api-keys/self', undefined, undefined, key))\n if (self.scoped_identity_id !== identityId || self.id !== keyId || self.status !== 'active') throw new MessagingProvisionError('invalid_receipt')\n }\n /** The host must authorize the recorded handle. Dedicated iMessage line release is not attested by this response. */\n async deleteIdentity(agentHandle: string): Promise<void> {\n assertHandle(agentHandle)\n await this.request('DELETE', `/identities/${encodeURIComponent(agentHandle)}`)\n }\n private identityReceipt(value: unknown, expectedHandle: string): InkboxIdentity {\n const identity = parseInkboxIdentity(value)\n if (identity.handle !== expectedHandle) throw new MessagingProvisionError('invalid_receipt')\n return identity\n }\n}\n","import { type InkboxIdentity, type InkboxNumber, InkboxProvisioner, MessagingProvisionError, type ManagedMessageTransport } from './inkbox.js'\n\nexport type NumberPhase = 'identity' | 'number' | 'credential' | 'connection' | 'complete'\nexport interface ManagedNumberOrder {\n id: string\n ownerId: string\n /** Unique to this order. After an attempt, an existing identity with this handle is adopted as the receipt. */\n handle: string\n organizationId: string\n transport: ManagedMessageTransport\n state?: string\n /** Immutable, server-created ledger authorization; never accept a browser-supplied paid flag. */\n fundingAuthorizationId: string\n version: number\n phase: NumberPhase\n attempted: boolean\n /** When the attempt journal was written. Within the in-flight window another worker may still be mid-call. */\n attemptedAt?: number\n identityId?: string\n number?: InkboxNumber\n connectionId?: string\n status: 'pending' | 'provider_pending' | 'needs_review' | 'ready_for_setup' | 'cancelled'\n errorCode?: string\n nextAttemptAt?: number\n}\nexport interface ManagedNumberOrderStore {\n get(id: string): Promise<ManagedNumberOrder | null>\n /** One atomic version check; preserve all rows across host/worker restarts. */\n saveIfVersion(order: ManagedNumberOrder, expectedVersion: number): Promise<boolean>\n}\nexport interface ManagedNumberPorts {\n orders: ManagedNumberOrderStore\n provider: Pick<InkboxProvisioner, 'getIdentity' | 'createIdentity' | 'claimIMessage' | 'provisionSms' | 'mintIdentityKey' | 'verifyIdentityKey'>\n /** Validate/capture through the platform ledger with this order's stable reference. Must be idempotent. */\n authorizeFunding(order: Readonly<ManagedNumberOrder>): Promise<boolean>\n /** Re-read configuration and commercial permission before every mutation, including resumed work. */\n canProvision(order: Readonly<ManagedNumberOrder>): Promise<boolean>\n vault: {\n read(orderId: string): Promise<{ key: string; keyId: string; identityId: string } | null>\n /** Encrypt once under the order and identity; reject an existing, different credential. */\n putIfAbsent(orderId: string, value: { key: string; keyId: string; identityId: string }): Promise<void>\n }\n /** Create/recover exactly this order's owner-scoped Hub connection using the vault reference. Never return its key. */\n bindConnection(order: Readonly<ManagedNumberOrder>): Promise<string>\n now?: () => number\n}\n\nfunction identityMatches(order: ManagedNumberOrder, identity: InkboxIdentity): void {\n if (identity.handle !== order.handle || identity.organizationId !== order.organizationId || identity.status !== 'active' ||\n (order.identityId && identity.id !== order.identityId)) throw new MessagingProvisionError('invalid_receipt')\n}\nfunction selectedNumber(order: ManagedNumberOrder, identity: InkboxIdentity): InkboxNumber | null {\n return order.transport === 'sms' ? identity.sms : identity.imessageEnabled ? identity.imessage : null\n}\n\n/** Longer than one provider mutation plus its ownership read at the maximum client timeout. */\nconst IN_FLIGHT_MS = 5 * 60_000\n\n/** One recoverable provisioning step, called by the host's EXISTING queue.\n * No agent loop, background worker, payment ledger or credential store lives here.\n * A journaled non-idempotent call is reconciled by reading provider state, never blindly repeated. */\nexport async function advanceManagedNumber(orderId: string, ports: ManagedNumberPorts): Promise<ManagedNumberOrder> {\n let order = await ports.orders.get(orderId)\n if (!order) throw new Error('Managed number order not found')\n if (!order.id || order.id.length > 128 || !/^[a-zA-Z0-9:._-]+$/.test(order.id) || order.id !== orderId ||\n !order.ownerId || !order.organizationId || !order.fundingAuthorizationId ||\n !['sms', 'imessage'].includes(order.transport) || !['identity', 'number', 'credential', 'connection', 'complete'].includes(order.phase) ||\n !Number.isSafeInteger(order.version) || order.version < 0) throw new MessagingProvisionError('invalid_input')\n // Set only when a provider mutation itself is definitively refused. A read\n // failing after a successful mutation must never re-open the purchase.\n let mutationRefused = false\n // Set once this tick's provider mutation has returned or thrown: it is no longer in flight.\n let mutationSettled = false\n if (order.phase === 'complete' || order.status === 'cancelled') return order\n const now = (ports.now ?? Date.now)()\n if (order.nextAttemptAt && order.nextAttemptAt > now) return order\n async function save(patch: Partial<ManagedNumberOrder>): Promise<ManagedNumberOrder> {\n const before = order!\n const next = { ...before, ...patch, version: before.version + 1 }\n if (await ports.orders.saveIfVersion(next, before.version)) { order = next; return next }\n return recordReceipt(patch)\n }\n /**\n * The order changed underneath this tick, usually a cancellation racing a\n * provider call. Drop the patch, but keep any provider receipt it carried:\n * a purchased number no order records cannot be released by cleanup.\n */\n async function recordReceipt(patch: Partial<ManagedNumberOrder>): Promise<ManagedNumberOrder> {\n const receipt: Partial<ManagedNumberOrder> = {\n ...(patch.identityId ? { identityId: patch.identityId } : {}),\n ...(patch.number ? { number: patch.number } : {}),\n }\n for (let attempt = 0; attempt < 3; attempt++) {\n const current = await ports.orders.get(orderId)\n if (!current) throw new Error('Managed number order disappeared')\n const missing = (receipt.identityId && !current.identityId) || (receipt.number && !current.number)\n if (!missing) return current\n const merged = {\n ...current,\n ...(current.identityId ? {} : { identityId: receipt.identityId }),\n ...(current.number ? {} : { number: receipt.number }),\n version: current.version + 1,\n }\n if (await ports.orders.saveIfVersion(merged, current.version)) return merged\n }\n throw new MessagingProvisionError('outcome_unknown')\n }\n async function mutate<T>(call: () => Promise<T>): Promise<T> {\n try { return await call() }\n catch (error) {\n if (error instanceof MessagingProvisionError && error.code === 'provider_rejected') mutationRefused = true\n throw error\n }\n finally { mutationSettled = true }\n }\n /** Journal the attempt, then recheck authority. Release the journal if no provider call follows. */\n async function claim(): Promise<boolean> {\n const before = order!\n const claimed = await save({ attempted: true, attemptedAt: now, status: 'pending', errorCode: undefined, nextAttemptAt: undefined })\n if (claimed.version !== before.version + 1 || order !== claimed) return false\n let authorized = false\n try { authorized = await authorize() }\n finally {\n if (!authorized) await releaseClaim()\n }\n return authorized\n }\n async function releaseClaim(): Promise<void> {\n const current = await ports.orders.get(orderId)\n if (!current || !current.attempted || current.status === 'cancelled') return\n if (await ports.orders.saveIfVersion({ ...current, attempted: false, version: current.version + 1 }, current.version)) {\n order = { ...current, attempted: false, version: current.version + 1 }\n }\n }\n /** A concurrent tick (a user's progress check during a sweep) must not judge another worker's live call. */\n function inFlight(current: ManagedNumberOrder): boolean {\n return current.attempted && current.attemptedAt !== undefined && now - current.attemptedAt < IN_FLIGHT_MS\n }\n async function authorize(): Promise<boolean> {\n const current = await ports.orders.get(orderId)\n if (!current || current.version !== order!.version || current.status === 'cancelled') return false\n // Back off: an order that cannot be funded or activated must not stay due\n // and crowd other orders out of the host's bounded reconcile sweep.\n if (!await ports.canProvision(current)) { await save({ status: 'provider_pending', errorCode: 'activation_not_configured', nextAttemptAt: now + 60_000 }); return false }\n if (!await ports.authorizeFunding(current)) { await save({ status: 'provider_pending', errorCode: 'funding_required', nextAttemptAt: now + 60_000 }); return false }\n // The checks above may wait on remote services. Do not act on a stale cancellation snapshot.\n const rechecked = await ports.orders.get(orderId)\n return rechecked?.version === order!.version && rechecked.status !== 'cancelled'\n }\n try {\n // Reads need no funding or activation permission; every provider mutation\n // authorizes through claim(). Reconciling a completed purchase therefore\n // still works after its funding hold expired.\n if (order.phase === 'identity') {\n let identity = await ports.provider.getIdentity(order.handle)\n if (!identity) {\n if (inFlight(order)) return order\n if (order.attempted) return save({ status: 'needs_review', errorCode: 'identity_outcome_unknown' })\n if (!await claim()) return (await ports.orders.get(orderId))!\n const handle = order.handle\n identity = await mutate(() => ports.provider.createIdentity(handle))\n } else if (!order.attempted && !order.identityId) {\n // A pre-existing handle is not evidence this order created the identity.\n return save({ status: 'needs_review', errorCode: 'identity_already_exists' })\n }\n identityMatches(order, identity)\n return save({ identityId: identity.id, phase: 'number', attempted: false, status: 'pending', errorCode: undefined })\n }\n if (!order.identityId) throw new MessagingProvisionError('invalid_receipt')\n const identity = await ports.provider.getIdentity(order.handle)\n if (!identity) return save({ status: 'needs_review', errorCode: 'identity_missing' })\n identityMatches(order, identity)\n if (order.phase === 'number') {\n let number = selectedNumber(order, identity)\n // A recorded number is an ownership receipt. Its absence now is a provider\n // change to review, never a reason to buy another line.\n if (!number && order.number) return save({ status: 'needs_review', errorCode: 'number_missing' })\n if (!number) {\n // An accepted iMessage claim enables the identity before the provider attaches a line.\n if (order.attempted && order.transport === 'imessage' && identity.imessageEnabled) {\n return save({ status: 'provider_pending', errorCode: 'number_pending', nextAttemptAt: now + 30_000 })\n }\n if (inFlight(order)) return order\n if (order.attempted) return save({ status: 'needs_review', errorCode: 'number_outcome_unknown' })\n if (!await claim()) return (await ports.orders.get(orderId))!\n const { handle, state, id } = order\n if (order.transport === 'sms') {\n const purchased = await mutate(() => ports.provider.provisionSms(handle, `${id}:sms`, state))\n // A purchase response alone is not an ownership receipt. Read the\n // exact identity before the host can treat this number as billable.\n const receipt = await ports.provider.getIdentity(order.handle)\n if (!receipt) throw new MessagingProvisionError('invalid_receipt')\n identityMatches(order, receipt)\n number = selectedNumber(order, receipt)\n if (!number || purchased.id !== number.id || purchased.number !== number.number) {\n throw new MessagingProvisionError('invalid_receipt')\n }\n }\n else {\n const receipt = await mutate(() => ports.provider.claimIMessage(handle, `${id}:imessage`))\n identityMatches(order, receipt); number = selectedNumber(order, receipt)\n }\n }\n if (!number) return save({ status: 'provider_pending', errorCode: 'number_pending', nextAttemptAt: now + 30_000 })\n if (order.number && (order.number.id !== number.id || order.number.number !== number.number)) throw new MessagingProvisionError('invalid_receipt')\n if (order.transport === 'sms' && (number.smsStatus !== 'ready' || number.status !== 'active')) {\n // The purchase has completed with an ownership receipt; nothing is in flight while SMS readiness settles.\n return save({ number, attempted: false, status: 'provider_pending', nextAttemptAt: now + 30_000, errorCode: 'sms_not_ready' })\n }\n return save({ number, phase: 'credential', attempted: false, status: 'pending', errorCode: undefined, nextAttemptAt: undefined })\n }\n const number = selectedNumber(order, identity)\n if (!number || number.id !== order.number?.id || number.number !== order.number.number ||\n (order.transport === 'sms' && (number.smsStatus !== 'ready' || number.status !== 'active'))) throw new MessagingProvisionError('invalid_receipt')\n if (order.phase === 'credential') {\n let credential = await ports.vault.read(order.id)\n if (!credential) {\n if (inFlight(order)) return order\n if (order.attempted) return save({ status: 'needs_review', errorCode: 'credential_receipt_lost' })\n if (!await claim()) return (await ports.orders.get(orderId))!\n const { identityId, id } = order\n const minted = await mutate(() => ports.provider.mintIdentityKey(identityId!, `Tangle number ${id}`))\n credential = { ...minted, identityId: order.identityId }\n // No fallible provider read between receiving the secret and durable encryption.\n await ports.vault.putIfAbsent(order.id, credential)\n }\n if (credential.identityId !== order.identityId) throw new MessagingProvisionError('invalid_receipt')\n await ports.provider.verifyIdentityKey(credential.key, order.identityId, credential.keyId)\n return save({ phase: 'connection', attempted: false, status: 'pending', errorCode: undefined })\n }\n const credential = await ports.vault.read(order.id)\n if (!credential || credential.identityId !== order.identityId) throw new MessagingProvisionError('invalid_receipt')\n if (!await authorize()) return (await ports.orders.get(orderId))!\n const connectionId = await ports.bindConnection(order)\n if (!connectionId || connectionId.length > 256) throw new MessagingProvisionError('invalid_receipt')\n return save({ connectionId, phase: 'complete', status: 'ready_for_setup', attempted: false, errorCode: undefined })\n } catch (error) {\n const code = error instanceof MessagingProvisionError ? error.code : 'outcome_unknown'\n const retryAfter = error instanceof MessagingProvisionError ? error.retryAfterSeconds : undefined\n // A definitive 4xx refusal permits another attempt after account setup. An unknown outcome does not.\n const refused = mutationRefused && order.phase !== 'credential'\n return save({ status: code === 'invalid_receipt' ? 'needs_review' : 'provider_pending', errorCode: code,\n ...(refused ? { attempted: false } : {}),\n ...(mutationSettled ? { attemptedAt: undefined } : {}),\n nextAttemptAt: now + Math.max(30, Math.min(retryAfter ?? 30, 86_400)) * 1000 })\n }\n}\n"],"mappings":"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","names":["identity","number","credential"]}
|
|
1
|
+
{"version":3,"sources":["../../src/managed-messaging/inkbox.ts","../../src/managed-messaging/provision.ts"],"sourcesContent":["export type ManagedMessageTransport = 'sms' | 'imessage'\nexport interface InkboxNumber { id: string; number: string; smsStatus: string | null; status: string | null }\nexport interface InkboxIdentity {\n id: string\n handle: string\n organizationId: string\n status: string\n imessageEnabled: boolean\n sms: InkboxNumber | null\n imessage: InkboxNumber | null\n}\nexport class MessagingProvisionError extends Error {\n constructor(\n readonly code: 'invalid_input' | 'unavailable' | 'provider_rejected' | 'outcome_unknown' | 'invalid_receipt',\n readonly status?: number,\n readonly retryAfterSeconds?: number,\n ) {\n super(`Messaging provisioning: ${code}${status ? ` (HTTP ${status})` : ''}`)\n this.name = 'MessagingProvisionError'\n }\n}\nconst BASE = 'https://inkbox.ai/api/v1'\nconst UUID = /^[a-f\\d]{8}(?:-[a-f\\d]{4}){3}-[a-f\\d]{12}$/i\nconst PHONE = /^\\+[1-9]\\d{6,14}$/\nconst HANDLE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new MessagingProvisionError('invalid_receipt')\n return value as Record<string, unknown>\n}\nfunction readNumber(value: unknown): InkboxNumber | null {\n if (value == null) return null\n const row = record(value)\n if (typeof row.id !== 'string' || !UUID.test(row.id) || typeof row.number !== 'string' || !PHONE.test(row.number)) throw new MessagingProvisionError('invalid_receipt')\n return { id: row.id, number: row.number, smsStatus: typeof row.sms_status === 'string' ? row.sms_status : null, status: typeof row.status === 'string' ? row.status : null }\n}\n/** Project only channel identity. Mailbox, tunnel, credentials and contacts never leave this boundary. */\nexport function parseInkboxIdentity(value: unknown): InkboxIdentity {\n const row = record(value)\n if (typeof row.id !== 'string' || !UUID.test(row.id) || typeof row.agent_handle !== 'string' ||\n row.agent_handle.length < 3 || row.agent_handle.length > 63 || !HANDLE.test(row.agent_handle) ||\n typeof row.organization_id !== 'string' || !row.organization_id || row.organization_id.length > 256 ||\n typeof row.status !== 'string' || !row.status || typeof row.imessage_enabled !== 'boolean') throw new MessagingProvisionError('invalid_receipt')\n return { id: row.id, handle: row.agent_handle, organizationId: row.organization_id, status: row.status,\n imessageEnabled: row.imessage_enabled, sms: readNumber(row.phone_number), imessage: readNumber(row.imessage_number) }\n}\nfunction assertHandle(value: string): void {\n if (value.length < 3 || value.length > 63 || !HANDLE.test(value)) throw new MessagingProvisionError('invalid_input')\n}\nfunction assertOperation(value: string): void {\n if (!value || value.length > 200 || !/^[a-zA-Z0-9:._-]+$/.test(value)) throw new MessagingProvisionError('invalid_input')\n}\nasync function readJson(response: Response): Promise<unknown> {\n if (!response.body) throw new MessagingProvisionError('invalid_receipt')\n const reader = response.body.getReader()\n const chunks: Uint8Array[] = []; let size = 0\n try {\n while (true) {\n const chunk = await reader.read()\n if (chunk.done) break\n size += chunk.value.byteLength\n if (size > 1_048_576) { await reader.cancel(); throw new MessagingProvisionError('invalid_receipt') }\n chunks.push(chunk.value)\n }\n const bytes = new Uint8Array(size); let offset = 0\n for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length }\n return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes)) as unknown\n } catch { throw new MessagingProvisionError('invalid_receipt') }\n finally { reader.releaseLock() }\n}\n\n/**\n * A read that fails transiently is `unavailable`: it says nothing about a\n * mutation that already succeeded. Only a mutation's own definitive 4xx is\n * `provider_rejected`, which is what permits another purchase attempt.\n */\nfunction failureCode(method: string, status: number): MessagingProvisionError['code'] {\n const transient = status >= 500 || status === 408\n if (method === 'GET') return transient || status === 429 ? 'unavailable' : 'provider_rejected'\n return transient ? 'outcome_unknown' : 'provider_rejected'\n}\n\n/** Host-only administrative client; NOT a ConnectorAdapter and never an agent tool. */\nexport class InkboxProvisioner {\n private readonly fetchImpl: typeof fetch\n private readonly timeoutMs: number\n readonly #adminKey: string\n constructor(options: { adminKey: string; fetchImpl?: typeof fetch; timeoutMs?: number }) {\n if (!options.adminKey || options.adminKey.length > 4096 || /[^\\x21-\\x7e]/.test(options.adminKey)) throw new MessagingProvisionError('unavailable')\n this.#adminKey = options.adminKey\n this.fetchImpl = options.fetchImpl ?? fetch.bind(globalThis)\n this.timeoutMs = options.timeoutMs ?? 15_000\n if (!Number.isSafeInteger(this.timeoutMs) || this.timeoutMs < 1 || this.timeoutMs > 120_000) throw new MessagingProvisionError('invalid_input')\n }\n private async request(method: 'GET' | 'POST' | 'PATCH' | 'DELETE', path: string, body?: unknown, operationId?: string, key = this.#adminKey): Promise<unknown> {\n let response: Response\n try {\n response = await this.fetchImpl(`${BASE}${path}`, { method, redirect: 'error', signal: AbortSignal.timeout(this.timeoutMs),\n headers: { 'X-API-Key': key, ...(body === undefined ? {} : { 'Content-Type': 'application/json' }), ...(operationId ? { 'Idempotency-Key': operationId } : {}) },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }) })\n } catch { throw new MessagingProvisionError(method === 'GET' ? 'unavailable' : 'outcome_unknown') }\n if ((method === 'GET' || method === 'DELETE') && response.status === 404) return null\n if (!response.ok) {\n const retry = response.headers.get('retry-after')\n const seconds = retry && /^\\d+$/.test(retry) && Number.isSafeInteger(Number(retry)) ? Number(retry) : undefined\n throw new MessagingProvisionError(failureCode(method, response.status), response.status, seconds)\n }\n if (method === 'DELETE' && response.status === 204) return null\n return readJson(response)\n }\n async verifyAdminKey(): Promise<void> {\n const self = record(await this.request('GET', '/api-keys/self'))\n if (self.scoped_identity_id !== null || self.status !== 'active') throw new MessagingProvisionError('invalid_receipt')\n }\n async getIdentity(agentHandle: string): Promise<InkboxIdentity | null> {\n assertHandle(agentHandle)\n const value = await this.request('GET', `/identities/${encodeURIComponent(agentHandle)}`)\n if (value === null) return null\n return this.identityReceipt(value, agentHandle)\n }\n async createIdentity(agentHandle: string): Promise<InkboxIdentity> {\n assertHandle(agentHandle)\n return this.identityReceipt(await this.request('POST', '/identities', {\n agent_handle: agentHandle, imessage_enabled: false, contact_sharing_enabled: false,\n mailbox: { sending_domain: null },\n }), agentHandle)\n }\n async claimIMessage(agentHandle: string, operationId: string): Promise<InkboxIdentity> {\n assertHandle(agentHandle); assertOperation(operationId)\n return this.identityReceipt(await this.request('PATCH', `/identities/${encodeURIComponent(agentHandle)}`,\n { imessage_enabled: true, claim_imessage_number: true }, operationId), agentHandle)\n }\n async provisionSms(agentHandle: string, operationId: string, state?: string): Promise<InkboxNumber> {\n assertHandle(agentHandle); assertOperation(operationId)\n if (state !== undefined && !/^[A-Z]{2}$/.test(state)) throw new MessagingProvisionError('invalid_input')\n const result = readNumber(await this.request('POST', '/phone/numbers', {\n agent_handle: agentHandle, type: 'local', incoming_call_action: 'auto_reject', ...(state ? { state } : {}),\n }, operationId))\n if (!result) throw new MessagingProvisionError('invalid_receipt')\n return result\n }\n /** Encrypt before any other work. A lost response cannot be repaired by blindly minting another key. */\n async mintIdentityKey(identityId: string, label: string): Promise<{ key: string; keyId: string }> {\n if (!UUID.test(identityId) || !label.trim() || label.length > 255) throw new MessagingProvisionError('invalid_input')\n const result = record(await this.request('POST', '/api-keys', { label, scoped_identity_id: identityId }))\n const meta = record(result.record)\n if (meta.scoped_identity_id !== identityId || typeof result.api_key !== 'string' || !result.api_key || result.api_key.length > 4096 ||\n /[^\\x21-\\x7e]/.test(result.api_key) || typeof meta.id !== 'string' || !meta.id) throw new MessagingProvisionError('invalid_receipt')\n // Only a successful receipt is returned. The host journals this call before sending it.\n return { key: result.api_key, keyId: meta.id }\n }\n /** Safe read after the once-shown key is durable in the host vault. */\n async verifyIdentityKey(key: string, identityId: string, keyId: string): Promise<void> {\n if (!UUID.test(identityId) || !key || /[^\\x21-\\x7e]/.test(key) || key.length > 4096 || !keyId) throw new MessagingProvisionError('invalid_input')\n const self = record(await this.request('GET', '/api-keys/self', undefined, undefined, key))\n if (self.scoped_identity_id !== identityId || self.id !== keyId || self.status !== 'active') throw new MessagingProvisionError('invalid_receipt')\n }\n /** The host must authorize the recorded handle. Dedicated iMessage line release is not attested by this response. */\n async deleteIdentity(agentHandle: string): Promise<void> {\n assertHandle(agentHandle)\n await this.request('DELETE', `/identities/${encodeURIComponent(agentHandle)}`)\n }\n private identityReceipt(value: unknown, expectedHandle: string): InkboxIdentity {\n const identity = parseInkboxIdentity(value)\n if (identity.handle !== expectedHandle) throw new MessagingProvisionError('invalid_receipt')\n return identity\n }\n}\n","import { type InkboxIdentity, type InkboxNumber, InkboxProvisioner, MessagingProvisionError, type ManagedMessageTransport } from './inkbox.js'\n\nexport type NumberPhase = 'identity' | 'number' | 'credential' | 'connection' | 'complete'\nexport interface ManagedNumberOrder {\n id: string\n ownerId: string\n /** Unique to this order. After an attempt, an existing identity with this handle is adopted as the receipt. */\n handle: string\n organizationId: string\n transport: ManagedMessageTransport\n state?: string\n /** Immutable, server-created ledger authorization; never accept a browser-supplied paid flag. */\n fundingAuthorizationId: string\n version: number\n phase: NumberPhase\n attempted: boolean\n /** When the attempt journal was written. Within the in-flight window another worker may still be mid-call. */\n attemptedAt?: number\n identityId?: string\n number?: InkboxNumber\n connectionId?: string\n status: 'pending' | 'provider_pending' | 'needs_review' | 'ready_for_setup' | 'cancelled'\n errorCode?: string\n /** HTTP status behind `errorCode`, when the provider gave one. 402, 401 and 422 need different operator work. */\n errorStatus?: number\n nextAttemptAt?: number\n}\nexport interface ManagedNumberOrderStore {\n get(id: string): Promise<ManagedNumberOrder | null>\n /** One atomic version check; preserve all rows across host/worker restarts. */\n saveIfVersion(order: ManagedNumberOrder, expectedVersion: number): Promise<boolean>\n}\nexport interface ManagedNumberPorts {\n orders: ManagedNumberOrderStore\n provider: Pick<InkboxProvisioner, 'getIdentity' | 'createIdentity' | 'claimIMessage' | 'provisionSms' | 'mintIdentityKey' | 'verifyIdentityKey'>\n /** Validate/capture through the platform ledger with this order's stable reference. Must be idempotent. */\n authorizeFunding(order: Readonly<ManagedNumberOrder>): Promise<boolean>\n /** Re-read configuration and commercial permission before every mutation, including resumed work. */\n canProvision(order: Readonly<ManagedNumberOrder>): Promise<boolean>\n vault: {\n read(orderId: string): Promise<{ key: string; keyId: string; identityId: string } | null>\n /** Encrypt once under the order and identity; reject an existing, different credential. */\n putIfAbsent(orderId: string, value: { key: string; keyId: string; identityId: string }): Promise<void>\n }\n /** Create/recover exactly this order's owner-scoped Hub connection using the vault reference. Never return its key. */\n bindConnection(order: Readonly<ManagedNumberOrder>): Promise<string>\n now?: () => number\n}\n\nfunction identityMatches(order: ManagedNumberOrder, identity: InkboxIdentity): void {\n if (identity.handle !== order.handle || identity.organizationId !== order.organizationId || identity.status !== 'active' ||\n (order.identityId && identity.id !== order.identityId)) throw new MessagingProvisionError('invalid_receipt')\n}\nfunction selectedNumber(order: ManagedNumberOrder, identity: InkboxIdentity): InkboxNumber | null {\n return order.transport === 'sms' ? identity.sms : identity.imessageEnabled ? identity.imessage : null\n}\n\n/** Longer than one provider mutation plus its ownership read at the maximum client timeout. */\nconst IN_FLIGHT_MS = 5 * 60_000\n/** An order under review waits for an operator, not for the queue. A self-healing provider\n * state still recovers on its own, but a reviewed row must not hold a slot in the host's\n * bounded sweep, which would starve orders that can still make progress. */\nconst REVIEW_BACKOFF_MS = 6 * 60 * 60_000\n\n/** One recoverable provisioning step, called by the host's EXISTING queue.\n * No agent loop, background worker, payment ledger or credential store lives here.\n * A journaled non-idempotent call is reconciled by reading provider state, never blindly repeated. */\nexport async function advanceManagedNumber(orderId: string, ports: ManagedNumberPorts): Promise<ManagedNumberOrder> {\n let order = await ports.orders.get(orderId)\n if (!order) throw new Error('Managed number order not found')\n if (!order.id || order.id.length > 128 || !/^[a-zA-Z0-9:._-]+$/.test(order.id) || order.id !== orderId ||\n !order.ownerId || !order.organizationId || !order.fundingAuthorizationId ||\n !['sms', 'imessage'].includes(order.transport) || !['identity', 'number', 'credential', 'connection', 'complete'].includes(order.phase) ||\n // The provider refuses a malformed state; reject it here so it can never reach a purchase.\n (order.state !== undefined && !/^[A-Z]{2}$/.test(order.state)) ||\n !Number.isSafeInteger(order.version) || order.version < 0) throw new MessagingProvisionError('invalid_input')\n // Set only when a provider mutation itself is definitively refused. A read\n // failing after a successful mutation must never re-open the purchase.\n let mutationRefused = false\n // Set once this tick's provider mutation has returned or thrown: it is no longer in flight.\n let mutationSettled = false\n if (order.phase === 'complete' || order.status === 'cancelled') return order\n // A tick can spend minutes inside two or three provider calls, so `now` dates only\n // this tick's due check and its in-flight judgement, where a clock that has since\n // advanced could only declare another worker's live call dead too early. Every lease\n // and every backoff reads the clock where it is written.\n const clock = ports.now ?? Date.now\n const now = clock()\n if (order.nextAttemptAt && order.nextAttemptAt > now) return order\n async function save(patch: Partial<ManagedNumberOrder>): Promise<ManagedNumberOrder> {\n const before = order!\n // `errorStatus` only ever qualifies `errorCode`: a new code never inherits the old code's status.\n const next = { ...before, ...('errorCode' in patch && !('errorStatus' in patch) ? { errorStatus: undefined } : {}), ...patch, version: before.version + 1 }\n if (await ports.orders.saveIfVersion(next, before.version)) { order = next; return next }\n return recordReceipt(patch)\n }\n /**\n * The order changed underneath this tick, usually a cancellation racing a\n * provider call. Drop the patch, but keep any provider receipt it carried:\n * a purchased number no order records cannot be released by cleanup.\n */\n async function recordReceipt(patch: Partial<ManagedNumberOrder>): Promise<ManagedNumberOrder> {\n const receipt: Partial<ManagedNumberOrder> = {\n ...(patch.identityId ? { identityId: patch.identityId } : {}),\n ...(patch.number ? { number: patch.number } : {}),\n }\n for (let attempt = 0; attempt < 3; attempt++) {\n const current = await ports.orders.get(orderId)\n if (!current) throw new Error('Managed number order disappeared')\n const missing = (receipt.identityId && !current.identityId) || (receipt.number && !current.number)\n if (!missing) return current\n const merged = {\n ...current,\n ...(current.identityId ? {} : { identityId: receipt.identityId }),\n ...(current.number ? {} : { number: receipt.number }),\n version: current.version + 1,\n }\n if (await ports.orders.saveIfVersion(merged, current.version)) return merged\n }\n throw new MessagingProvisionError('outcome_unknown')\n }\n async function mutate<T>(call: () => Promise<T>): Promise<T> {\n try { return await call() }\n catch (error) {\n // `invalid_input` is raised by argument validation before any HTTP leaves the client:\n // like a definitive refusal, it proves no purchase exists to reconcile.\n if (error instanceof MessagingProvisionError && (error.code === 'provider_rejected' || error.code === 'invalid_input')) mutationRefused = true\n throw error\n }\n finally { mutationSettled = true }\n }\n /** Journal the attempt, then recheck authority. Release the journal if no provider call follows. */\n async function claim(): Promise<boolean> {\n const before = order!\n // The lease starts here, not at the tick's start: reads already made in this tick\n // would otherwise hand a concurrent tick a lease that is spent before the call returns.\n const claimed = await save({ attempted: true, attemptedAt: clock(), status: 'pending', errorCode: undefined, nextAttemptAt: undefined })\n if (claimed.version !== before.version + 1 || order !== claimed) return false\n let authorized = false\n try { authorized = await authorize() }\n finally {\n if (!authorized) await releaseClaim()\n }\n return authorized\n }\n async function releaseClaim(): Promise<void> {\n const current = await ports.orders.get(orderId)\n if (!current || !current.attempted || current.status === 'cancelled') return\n if (await ports.orders.saveIfVersion({ ...current, attempted: false, version: current.version + 1 }, current.version)) {\n order = { ...current, attempted: false, version: current.version + 1 }\n }\n }\n /** A concurrent tick (a user's progress check during a sweep) must not judge another worker's live call. */\n function inFlight(current: ManagedNumberOrder): boolean {\n return current.attempted && current.attemptedAt !== undefined && now - current.attemptedAt < IN_FLIGHT_MS\n }\n async function authorize(): Promise<boolean> {\n const current = await ports.orders.get(orderId)\n if (!current || current.version !== order!.version || current.status === 'cancelled') return false\n // Back off: an order that cannot be funded or activated must not stay due\n // and crowd other orders out of the host's bounded reconcile sweep.\n if (!await ports.canProvision(current)) { await save({ status: 'provider_pending', errorCode: 'activation_not_configured', nextAttemptAt: clock() + 60_000 }); return false }\n if (!await ports.authorizeFunding(current)) { await save({ status: 'provider_pending', errorCode: 'funding_required', nextAttemptAt: clock() + 60_000 }); return false }\n // The checks above may wait on remote services. Do not act on a stale cancellation snapshot.\n const rechecked = await ports.orders.get(orderId)\n return rechecked?.version === order!.version && rechecked.status !== 'cancelled'\n }\n try {\n // Reads need no funding or activation permission; every provider mutation\n // authorizes through claim(). Reconciling a completed purchase therefore\n // still works after its funding hold expired.\n if (order.phase === 'identity') {\n let identity = await ports.provider.getIdentity(order.handle)\n if (!identity) {\n if (inFlight(order)) return order\n if (order.attempted) return save({ status: 'needs_review', errorCode: 'identity_outcome_unknown', nextAttemptAt: clock() + REVIEW_BACKOFF_MS })\n if (!await claim()) return (await ports.orders.get(orderId))!\n const handle = order.handle\n identity = await mutate(() => ports.provider.createIdentity(handle))\n } else if (!order.attempted && !order.identityId) {\n // A pre-existing handle is not evidence this order created the identity.\n return save({ status: 'needs_review', errorCode: 'identity_already_exists', nextAttemptAt: clock() + REVIEW_BACKOFF_MS })\n }\n identityMatches(order, identity)\n return save({ identityId: identity.id, phase: 'number', attempted: false, status: 'pending', errorCode: undefined })\n }\n if (!order.identityId) throw new MessagingProvisionError('invalid_receipt')\n const identity = await ports.provider.getIdentity(order.handle)\n if (!identity) return save({ status: 'needs_review', errorCode: 'identity_missing', nextAttemptAt: clock() + REVIEW_BACKOFF_MS })\n identityMatches(order, identity)\n if (order.phase === 'number') {\n let number = selectedNumber(order, identity)\n // A recorded number is an ownership receipt. Its absence now is a provider\n // change to review, never a reason to buy another line.\n if (!number && order.number) return save({ status: 'needs_review', errorCode: 'number_missing', nextAttemptAt: clock() + REVIEW_BACKOFF_MS })\n if (!number) {\n // An accepted iMessage claim enables the identity before the provider attaches a line.\n if (order.attempted && order.transport === 'imessage' && identity.imessageEnabled) {\n return save({ status: 'provider_pending', errorCode: 'number_pending', nextAttemptAt: clock() + 30_000 })\n }\n if (inFlight(order)) return order\n if (order.attempted) return save({ status: 'needs_review', errorCode: 'number_outcome_unknown', nextAttemptAt: clock() + REVIEW_BACKOFF_MS })\n if (!await claim()) return (await ports.orders.get(orderId))!\n const { handle, state, id } = order\n if (order.transport === 'sms') {\n const purchased = await mutate(() => ports.provider.provisionSms(handle, `${id}:sms`, state))\n // A purchase response alone is not an ownership receipt. Read the\n // exact identity before the host can treat this number as billable.\n const receipt = await ports.provider.getIdentity(order.handle)\n if (!receipt) throw new MessagingProvisionError('invalid_receipt')\n identityMatches(order, receipt)\n number = selectedNumber(order, receipt)\n if (!number || purchased.id !== number.id || purchased.number !== number.number) {\n throw new MessagingProvisionError('invalid_receipt')\n }\n }\n else {\n const receipt = await mutate(() => ports.provider.claimIMessage(handle, `${id}:imessage`))\n identityMatches(order, receipt); number = selectedNumber(order, receipt)\n }\n }\n if (!number) return save({ status: 'provider_pending', errorCode: 'number_pending', nextAttemptAt: clock() + 30_000 })\n if (order.number && (order.number.id !== number.id || order.number.number !== number.number)) throw new MessagingProvisionError('invalid_receipt')\n if (order.transport === 'sms' && (number.smsStatus !== 'ready' || number.status !== 'active')) {\n // The purchase has completed with an ownership receipt; nothing is in flight while SMS readiness settles.\n return save({ number, attempted: false, status: 'provider_pending', nextAttemptAt: clock() + 30_000, errorCode: 'sms_not_ready' })\n }\n return save({ number, phase: 'credential', attempted: false, status: 'pending', errorCode: undefined, nextAttemptAt: undefined })\n }\n const number = selectedNumber(order, identity)\n if (!number || number.id !== order.number?.id || number.number !== order.number.number ||\n (order.transport === 'sms' && (number.smsStatus !== 'ready' || number.status !== 'active'))) throw new MessagingProvisionError('invalid_receipt')\n if (order.phase === 'credential') {\n let credential = await ports.vault.read(order.id)\n if (!credential) {\n if (inFlight(order)) return order\n if (order.attempted) return save({ status: 'needs_review', errorCode: 'credential_receipt_lost', nextAttemptAt: clock() + REVIEW_BACKOFF_MS })\n if (!await claim()) return (await ports.orders.get(orderId))!\n const { identityId, id } = order\n const minted = await mutate(() => ports.provider.mintIdentityKey(identityId!, `Tangle number ${id}`))\n credential = { ...minted, identityId: order.identityId }\n // No fallible provider read between receiving the secret and durable encryption.\n await ports.vault.putIfAbsent(order.id, credential)\n }\n if (credential.identityId !== order.identityId) throw new MessagingProvisionError('invalid_receipt')\n await ports.provider.verifyIdentityKey(credential.key, order.identityId, credential.keyId)\n return save({ phase: 'connection', attempted: false, status: 'pending', errorCode: undefined })\n }\n const credential = await ports.vault.read(order.id)\n if (!credential || credential.identityId !== order.identityId) throw new MessagingProvisionError('invalid_receipt')\n if (!await authorize()) return (await ports.orders.get(orderId))!\n const connectionId = await ports.bindConnection(order)\n if (!connectionId || connectionId.length > 256) throw new MessagingProvisionError('invalid_receipt')\n return save({ connectionId, phase: 'complete', status: 'ready_for_setup', attempted: false, errorCode: undefined })\n } catch (error) {\n const code = error instanceof MessagingProvisionError ? error.code : 'outcome_unknown'\n const retryAfter = error instanceof MessagingProvisionError ? error.retryAfterSeconds : undefined\n // A definitive 4xx refusal permits another attempt after account setup. An unknown outcome does not.\n const refused = mutationRefused && order.phase !== 'credential'\n const review = code === 'invalid_receipt'\n // The failing call spent its own clock, up to the client timeout. A backoff measured\n // from the tick's start clock can land in the past, leaving the order due immediately.\n const failedAt = clock()\n return save({ status: review ? 'needs_review' : 'provider_pending', errorCode: code,\n errorStatus: error instanceof MessagingProvisionError ? error.status : undefined,\n ...(refused ? { attempted: false } : {}),\n ...(mutationSettled ? { attemptedAt: undefined } : {}),\n nextAttemptAt: failedAt + (review ? REVIEW_BACKOFF_MS : Math.max(30, Math.min(retryAfter ?? 30, 86_400)) * 1000) })\n }\n}\n"],"mappings":"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","names":["identity","number","credential"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-integrations",
|
|
3
|
-
"version": "0.54.
|
|
3
|
+
"version": "0.54.1",
|
|
4
4
|
"description": "Vendor-neutral integration contracts and runtime helpers for sandbox and agent apps.",
|
|
5
5
|
"homepage": "https://github.com/tangle-network/agent-integrations#readme",
|
|
6
6
|
"repository": {
|