@tangle-network/agent-integrations 0.2.0 → 0.2.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.
- package/dist/index.js +13 -80
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { createHmac as
|
|
2
|
+
import { createHmac as createHmac3, randomUUID, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
3
3
|
|
|
4
4
|
// src/connectors/types.ts
|
|
5
5
|
var ResourceContention = class extends Error {
|
|
@@ -2525,43 +2525,6 @@ function signHeaders(creds, body, idempotencyKey) {
|
|
|
2525
2525
|
}
|
|
2526
2526
|
|
|
2527
2527
|
// src/connectors/adapters/stripe-webhook-receiver.ts
|
|
2528
|
-
import { createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
2529
|
-
var SIGNATURE_TOLERANCE_SECONDS = 5 * 60;
|
|
2530
|
-
function parseStripeHeader(header) {
|
|
2531
|
-
const t = { sigs: [] };
|
|
2532
|
-
for (const part of header.split(",")) {
|
|
2533
|
-
const idx = part.indexOf("=");
|
|
2534
|
-
if (idx < 0) continue;
|
|
2535
|
-
const key = part.slice(0, idx).trim();
|
|
2536
|
-
const val = part.slice(idx + 1).trim();
|
|
2537
|
-
if (key === "t") {
|
|
2538
|
-
const n = Number(val);
|
|
2539
|
-
if (Number.isFinite(n)) t.ts = n;
|
|
2540
|
-
} else if (key === "v1") {
|
|
2541
|
-
t.sigs.push(val);
|
|
2542
|
-
}
|
|
2543
|
-
}
|
|
2544
|
-
if (t.ts === void 0 || t.sigs.length === 0) return null;
|
|
2545
|
-
return { t: t.ts, sigs: t.sigs };
|
|
2546
|
-
}
|
|
2547
|
-
function verifyStripeSignature2(rawBody, header, secret, now) {
|
|
2548
|
-
const parsed = parseStripeHeader(header);
|
|
2549
|
-
if (!parsed) return false;
|
|
2550
|
-
if (Math.abs(now - parsed.t) > SIGNATURE_TOLERANCE_SECONDS) return false;
|
|
2551
|
-
const expected = createHmac3("sha256", secret).update(`${parsed.t}.${rawBody}`).digest("hex");
|
|
2552
|
-
const expectedBuf = Buffer.from(expected, "utf8");
|
|
2553
|
-
for (const sig of parsed.sigs) {
|
|
2554
|
-
const sigBuf = Buffer.from(sig, "utf8");
|
|
2555
|
-
if (sigBuf.length !== expectedBuf.length) continue;
|
|
2556
|
-
if (timingSafeEqual2(sigBuf, expectedBuf)) return true;
|
|
2557
|
-
}
|
|
2558
|
-
return false;
|
|
2559
|
-
}
|
|
2560
|
-
function firstHeader2(h, name) {
|
|
2561
|
-
const v = h[name] ?? h[name.toLowerCase()];
|
|
2562
|
-
if (Array.isArray(v)) return v[0];
|
|
2563
|
-
return typeof v === "string" ? v : void 0;
|
|
2564
|
-
}
|
|
2565
2528
|
var stripeWebhookReceiverConnector = {
|
|
2566
2529
|
manifest: {
|
|
2567
2530
|
kind: "stripe",
|
|
@@ -2569,23 +2532,17 @@ var stripeWebhookReceiverConnector = {
|
|
|
2569
2532
|
description: "Receive Stripe webhook events from your own Stripe account. Paste your endpoint signing secret (whsec_*) at connect time; we'll verify every push and feed events to your agent's runtime.",
|
|
2570
2533
|
auth: { kind: "hmac" },
|
|
2571
2534
|
category: "commerce",
|
|
2572
|
-
// Inbound-only
|
|
2573
|
-
//
|
|
2574
|
-
//
|
|
2535
|
+
// Inbound-only. Stripe events are advisory in this incarnation — the
|
|
2536
|
+
// agent reacts to them but doesn't compete for writes against the same
|
|
2537
|
+
// resource.
|
|
2575
2538
|
defaultConsistencyModel: "advisory",
|
|
2576
2539
|
capabilities: []
|
|
2577
2540
|
},
|
|
2578
|
-
async executeRead(_inv) {
|
|
2579
|
-
throw new Error("not_implemented: stripe outbound read is scaffolded \u2014 use stripe-customers connector when shipped");
|
|
2580
|
-
},
|
|
2581
|
-
async executeMutation(_inv) {
|
|
2582
|
-
throw new Error("not_implemented: stripe outbound mutation is scaffolded \u2014 use stripe-customers connector when shipped");
|
|
2583
|
-
},
|
|
2584
2541
|
verifySignature({ rawBody, headers, source }) {
|
|
2585
2542
|
if (source.credentials.kind !== "hmac") return { valid: false, reason: "missing_hmac_secret" };
|
|
2586
|
-
const sig =
|
|
2543
|
+
const sig = firstHeader(headers, "stripe-signature");
|
|
2587
2544
|
if (!sig) return { valid: false, reason: "missing_stripe_signature_header" };
|
|
2588
|
-
const ok =
|
|
2545
|
+
const ok = verifyStripeSignature(rawBody, sig, source.credentials.secret);
|
|
2589
2546
|
return ok ? { valid: true } : { valid: false, reason: "invalid_signature" };
|
|
2590
2547
|
},
|
|
2591
2548
|
async handleInboundEvent({ rawBody }) {
|
|
@@ -2619,24 +2576,6 @@ var stripeWebhookReceiverConnector = {
|
|
|
2619
2576
|
};
|
|
2620
2577
|
|
|
2621
2578
|
// src/connectors/adapters/slack-events.ts
|
|
2622
|
-
import { createHmac as createHmac4, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
2623
|
-
var SIGNATURE_TOLERANCE_SECONDS2 = 5 * 60;
|
|
2624
|
-
function firstHeader3(h, name) {
|
|
2625
|
-
const v = h[name] ?? h[name.toLowerCase()];
|
|
2626
|
-
if (Array.isArray(v)) return v[0];
|
|
2627
|
-
return typeof v === "string" ? v : void 0;
|
|
2628
|
-
}
|
|
2629
|
-
function verifySlackSignature2(rawBody, signatureHeader, timestampHeader, secret, now) {
|
|
2630
|
-
if (!signatureHeader.startsWith("v0=")) return false;
|
|
2631
|
-
const ts = Number(timestampHeader);
|
|
2632
|
-
if (!Number.isFinite(ts)) return false;
|
|
2633
|
-
if (Math.abs(now - ts) > SIGNATURE_TOLERANCE_SECONDS2) return false;
|
|
2634
|
-
const expected = "v0=" + createHmac4("sha256", secret).update(`v0:${ts}:${rawBody}`).digest("hex");
|
|
2635
|
-
const expectedBuf = Buffer.from(expected, "utf8");
|
|
2636
|
-
const sigBuf = Buffer.from(signatureHeader, "utf8");
|
|
2637
|
-
if (sigBuf.length !== expectedBuf.length) return false;
|
|
2638
|
-
return timingSafeEqual3(sigBuf, expectedBuf);
|
|
2639
|
-
}
|
|
2640
2579
|
var slackEventsConnector = {
|
|
2641
2580
|
manifest: {
|
|
2642
2581
|
// NOTE: `slack` is owned by the OAuth bot connector in slack.ts (post_message,
|
|
@@ -2649,23 +2588,17 @@ var slackEventsConnector = {
|
|
|
2649
2588
|
description: "Receive workspace events (messages, reactions, app mentions, \u2026) from Slack's Events API. Outbound bot messaging will land in a follow-up.",
|
|
2650
2589
|
auth: { kind: "hmac" },
|
|
2651
2590
|
category: "comms",
|
|
2652
|
-
// Inbound-only
|
|
2653
|
-
//
|
|
2591
|
+
// Inbound-only. Events are advisory in this incarnation — agents observe
|
|
2592
|
+
// and react, no CAS.
|
|
2654
2593
|
defaultConsistencyModel: "advisory",
|
|
2655
2594
|
capabilities: []
|
|
2656
2595
|
},
|
|
2657
|
-
async executeRead(_inv) {
|
|
2658
|
-
throw new Error("not_implemented: slack outbound read is scaffolded");
|
|
2659
|
-
},
|
|
2660
|
-
async executeMutation(_inv) {
|
|
2661
|
-
throw new Error("not_implemented: slack outbound mutation is scaffolded");
|
|
2662
|
-
},
|
|
2663
2596
|
verifySignature({ rawBody, headers, source }) {
|
|
2664
2597
|
if (source.credentials.kind !== "hmac") return { valid: false, reason: "missing_hmac_secret" };
|
|
2665
|
-
const sig =
|
|
2666
|
-
const ts =
|
|
2598
|
+
const sig = firstHeader(headers, "x-slack-signature");
|
|
2599
|
+
const ts = firstHeader(headers, "x-slack-request-timestamp");
|
|
2667
2600
|
if (!sig || !ts) return { valid: false, reason: "missing_slack_headers" };
|
|
2668
|
-
const ok =
|
|
2601
|
+
const ok = verifySlackSignature(rawBody, sig, ts, source.credentials.secret);
|
|
2669
2602
|
return ok ? { valid: true } : { valid: false, reason: "invalid_signature" };
|
|
2670
2603
|
},
|
|
2671
2604
|
async handleInboundEvent({ rawBody }) {
|
|
@@ -2994,12 +2927,12 @@ function assertScopes(connection, requiredScopes) {
|
|
|
2994
2927
|
if (missing.length > 0) throw new IntegrationError(`Missing integration scopes: ${missing.join(", ")}`, "scope_denied");
|
|
2995
2928
|
}
|
|
2996
2929
|
function hmac(payload, secret) {
|
|
2997
|
-
return
|
|
2930
|
+
return createHmac3("sha256", secret).update(payload).digest("base64url");
|
|
2998
2931
|
}
|
|
2999
2932
|
function constantTimeEqual(a, b) {
|
|
3000
2933
|
const left = Buffer.from(a);
|
|
3001
2934
|
const right = Buffer.from(b);
|
|
3002
|
-
return left.length === right.length &&
|
|
2935
|
+
return left.length === right.length && timingSafeEqual2(left, right);
|
|
3003
2936
|
}
|
|
3004
2937
|
function base64UrlEncode(value) {
|
|
3005
2938
|
return Buffer.from(value, "utf8").toString("base64url");
|