@firela/billclaw-openclaw 0.1.4 → 0.2.0
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/LICENSE +21 -0
- package/dist/oauth/gmail.d.ts +21 -9
- package/dist/oauth/gmail.d.ts.map +1 -1
- package/dist/oauth/gmail.js +88 -145
- package/dist/oauth/gmail.js.map +1 -1
- package/dist/oauth/plaid.d.ts +10 -8
- package/dist/oauth/plaid.d.ts.map +1 -1
- package/dist/oauth/plaid.js +55 -60
- package/dist/oauth/plaid.js.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +3 -0
- package/dist/plugin.js.map +1 -1
- package/dist/services/webhook-handler.d.ts +15 -8
- package/dist/services/webhook-handler.d.ts.map +1 -1
- package/dist/services/webhook-handler.js +255 -75
- package/dist/services/webhook-handler.js.map +1 -1
- package/package.json +14 -14
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 fire-la
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/oauth/gmail.d.ts
CHANGED
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Gmail OAuth handler -
|
|
2
|
+
* Gmail OAuth handler - OpenClaw adapter
|
|
3
3
|
*
|
|
4
|
-
* This
|
|
4
|
+
* This is an adapter layer that calls the framework-agnostic OAuth implementation
|
|
5
|
+
* from @firela/billclaw-core and adds OpenClaw-specific functionality (config management).
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
* 1. Generate authorization URL (with PKCE) - Returns { url, state }
|
|
8
|
-
* 2. Handle callback - Receives authorization code
|
|
9
|
-
* 3. Exchange code for access token - Returns { accessToken, refreshToken }
|
|
7
|
+
* @packageDocumentation
|
|
10
8
|
*/
|
|
11
9
|
import type { OpenClawPluginApi } from "../types/openclaw-plugin.js";
|
|
12
10
|
/**
|
|
13
11
|
* Handle Gmail OAuth flow
|
|
14
12
|
*
|
|
15
|
-
* This
|
|
13
|
+
* This is an OpenClaw adapter that calls the framework-agnostic OAuth handler
|
|
14
|
+
* from @firela/billclaw-core and adds OpenClaw-specific functionality.
|
|
16
15
|
*
|
|
17
16
|
* Flow:
|
|
18
17
|
* 1. Initialize OAuth (no params) - Returns { url, state }
|
|
19
|
-
* 2. Handle callback (code + state) - Returns { accessToken, refreshToken }
|
|
18
|
+
* 2. Handle callback (code + state + accountId) - Returns { accessToken, refreshToken }
|
|
19
|
+
* - Tokens are automatically saved to account config if accountId is provided
|
|
20
20
|
*
|
|
21
21
|
* @param api - OpenClaw plugin API
|
|
22
|
-
* @param context - OAuth context with optional code
|
|
22
|
+
* @param context - OAuth context with optional code, state, redirectUri, and accountId
|
|
23
23
|
* @returns OAuthResult with URL and/or token
|
|
24
24
|
*/
|
|
25
25
|
export declare function gmailOAuthHandler(api: OpenClawPluginApi, context?: {
|
|
26
26
|
code?: string;
|
|
27
27
|
state?: string;
|
|
28
28
|
redirectUri?: string;
|
|
29
|
+
accountId?: string;
|
|
29
30
|
}): Promise<{
|
|
30
31
|
url: string;
|
|
31
32
|
state?: string;
|
|
@@ -33,4 +34,15 @@ export declare function gmailOAuthHandler(api: OpenClawPluginApi, context?: {
|
|
|
33
34
|
refreshToken?: string;
|
|
34
35
|
expiresIn?: number;
|
|
35
36
|
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Refresh Gmail access token using refresh token
|
|
39
|
+
*
|
|
40
|
+
* @param api - OpenClaw plugin API
|
|
41
|
+
* @param accountId - Account ID to refresh token for
|
|
42
|
+
* @returns New access token and expiry info, or null if refresh failed
|
|
43
|
+
*/
|
|
44
|
+
export declare function refreshGmailToken(api: OpenClawPluginApi, accountId: string): Promise<{
|
|
45
|
+
accessToken: string;
|
|
46
|
+
expiresIn: number;
|
|
47
|
+
} | null>;
|
|
36
48
|
//# sourceMappingURL=gmail.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gmail.d.ts","sourceRoot":"","sources":["../../src/oauth/gmail.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gmail.d.ts","sourceRoot":"","sources":["../../src/oauth/gmail.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AA8FpE;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,iBAAiB,EACtB,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GACA,OAAO,CAAC;IACT,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAC,CA4BD;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,iBAAiB,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA4C5D"}
|
package/dist/oauth/gmail.js
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Gmail OAuth handler -
|
|
2
|
+
* Gmail OAuth handler - OpenClaw adapter
|
|
3
3
|
*
|
|
4
|
-
* This
|
|
4
|
+
* This is an adapter layer that calls the framework-agnostic OAuth implementation
|
|
5
|
+
* from @firela/billclaw-core and adds OpenClaw-specific functionality (config management).
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import { gmailOAuthHandler as coreGmailOAuthHandler, refreshGmailToken as coreRefreshGmailToken, } from "@firela/billclaw-core";
|
|
10
|
+
/**
|
|
11
|
+
* Get a logger from OpenClaw API, or provide a no-op logger
|
|
10
12
|
*/
|
|
13
|
+
function getLogger(api) {
|
|
14
|
+
return {
|
|
15
|
+
info: api.logger?.info || (() => { }),
|
|
16
|
+
error: api.logger?.error || (() => { }),
|
|
17
|
+
warn: api.logger?.warn || (() => { }),
|
|
18
|
+
debug: api.logger?.debug || (() => { }),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
11
21
|
/**
|
|
12
22
|
* Get Gmail configuration from OpenClaw config
|
|
13
23
|
*/
|
|
@@ -25,166 +35,99 @@ function getGmailConfig(api) {
|
|
|
25
35
|
};
|
|
26
36
|
}
|
|
27
37
|
/**
|
|
28
|
-
*
|
|
29
|
-
*/
|
|
30
|
-
function generateCodeVerifier() {
|
|
31
|
-
const array = new Uint8Array(32);
|
|
32
|
-
crypto.getRandomValues(array);
|
|
33
|
-
return base64UrlEncode(array);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Generate code challenge from verifier for PKCE
|
|
37
|
-
*/
|
|
38
|
-
async function generateCodeChallenge(verifier) {
|
|
39
|
-
const encoder = new TextEncoder();
|
|
40
|
-
const data = encoder.encode(verifier);
|
|
41
|
-
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
42
|
-
return base64UrlEncode(new Uint8Array(hash));
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Base64URL encode a byte array
|
|
46
|
-
*/
|
|
47
|
-
function base64UrlEncode(bytes) {
|
|
48
|
-
const binString = Array.from(bytes, (byte) => String.fromCharCode(byte));
|
|
49
|
-
const base64 = btoa(binString.join(""));
|
|
50
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* State parameter storage (in-memory for security)
|
|
54
|
-
* In production, this should be stored in a secure session
|
|
55
|
-
*/
|
|
56
|
-
const oauthStateStore = new Map();
|
|
57
|
-
/**
|
|
58
|
-
* Clean up expired states (older than 10 minutes)
|
|
59
|
-
*/
|
|
60
|
-
function cleanupExpiredStates() {
|
|
61
|
-
const now = Date.now();
|
|
62
|
-
const maxAge = 10 * 60 * 1000; // 10 minutes
|
|
63
|
-
for (const [key, value] of oauthStateStore.entries()) {
|
|
64
|
-
if (now - value.timestamp > maxAge) {
|
|
65
|
-
oauthStateStore.delete(key);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Generate Gmail OAuth authorization URL
|
|
71
|
-
*
|
|
72
|
-
* Uses PKCE for security without requiring client secret.
|
|
73
|
-
*/
|
|
74
|
-
async function generateAuthorizationUrl(api, redirectUri = "http://localhost:3000/callback") {
|
|
75
|
-
cleanupExpiredStates();
|
|
76
|
-
const gmailConfig = getGmailConfig(api);
|
|
77
|
-
// Generate PKCE verifier and challenge
|
|
78
|
-
const codeVerifier = generateCodeVerifier();
|
|
79
|
-
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
80
|
-
// Generate state parameter for CSRF protection
|
|
81
|
-
const state = Array.from(crypto.getRandomValues(new Uint8Array(16)))
|
|
82
|
-
.map((b) => b.toString(16).padStart(2, "0"))
|
|
83
|
-
.join("");
|
|
84
|
-
// Store state and verifier
|
|
85
|
-
oauthStateStore.set(state, {
|
|
86
|
-
codeVerifier,
|
|
87
|
-
timestamp: Date.now(),
|
|
88
|
-
});
|
|
89
|
-
// Build authorization URL
|
|
90
|
-
const params = new URLSearchParams();
|
|
91
|
-
params.set("client_id", gmailConfig.clientId);
|
|
92
|
-
params.set("redirect_uri", redirectUri);
|
|
93
|
-
params.set("response_type", "code");
|
|
94
|
-
params.set("scope", "https://www.googleapis.com/auth/gmail.readonly");
|
|
95
|
-
params.set("state", state);
|
|
96
|
-
params.set("code_challenge", codeChallenge);
|
|
97
|
-
params.set("code_challenge_method", "S256");
|
|
98
|
-
params.set("access_type", "offline"); // Allow refresh token
|
|
99
|
-
params.set("prompt", "consent"); // Force consent to get refresh token
|
|
100
|
-
const url = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
|
|
101
|
-
api.logger.info?.("Gmail authorization URL generated");
|
|
102
|
-
return { url, state };
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Exchange authorization code for access token
|
|
38
|
+
* Save Gmail OAuth tokens to account configuration
|
|
106
39
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
40
|
+
* NOTE: This requires the OpenClaw runtime to support config updates.
|
|
41
|
+
* The actual persistence depends on the OpenClawConfigProvider implementation.
|
|
109
42
|
*/
|
|
110
|
-
async function
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
params.set("client_id", gmailConfig.clientId);
|
|
124
|
-
if (gmailConfig.clientSecret) {
|
|
125
|
-
params.set("client_secret", gmailConfig.clientSecret);
|
|
43
|
+
async function saveGmailTokensToAccount(api, accountId, accessToken, refreshToken, expiresIn) {
|
|
44
|
+
const logger = getLogger(api);
|
|
45
|
+
// Calculate token expiry timestamp
|
|
46
|
+
const expiresAt = expiresIn
|
|
47
|
+
? new Date(Date.now() + expiresIn * 1000).toISOString()
|
|
48
|
+
: undefined;
|
|
49
|
+
// Get config from OpenClaw
|
|
50
|
+
const config = api.pluginConfig;
|
|
51
|
+
// Find and update the account
|
|
52
|
+
const accountIndex = config.accounts?.findIndex((a) => a.id === accountId && a.type === "gmail");
|
|
53
|
+
if (accountIndex === -1 || accountIndex === undefined) {
|
|
54
|
+
logger.warn(`Gmail account ${accountId} not found in config. Tokens not saved.`);
|
|
55
|
+
return;
|
|
126
56
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
},
|
|
135
|
-
body: params.toString(),
|
|
136
|
-
});
|
|
137
|
-
if (!response.ok) {
|
|
138
|
-
const errorText = await response.text();
|
|
139
|
-
throw new Error(`Failed to exchange token: ${response.status} ${errorText}`);
|
|
140
|
-
}
|
|
141
|
-
const data = (await response.json());
|
|
142
|
-
api.logger.info?.("Gmail access token obtained successfully");
|
|
143
|
-
return {
|
|
144
|
-
accessToken: data.access_token,
|
|
145
|
-
refreshToken: data.refresh_token,
|
|
146
|
-
expiresIn: data.expires_in,
|
|
57
|
+
// Update account with tokens
|
|
58
|
+
config.accounts[accountIndex] = {
|
|
59
|
+
...config.accounts[accountIndex],
|
|
60
|
+
gmailAccessToken: accessToken,
|
|
61
|
+
gmailRefreshToken: refreshToken,
|
|
62
|
+
gmailTokenExpiry: expiresAt,
|
|
63
|
+
enabled: true, // Auto-enable account after successful OAuth
|
|
147
64
|
};
|
|
65
|
+
// Note: The actual persistence to disk depends on OpenClaw's config management
|
|
66
|
+
// The updated config is in memory but OpenClaw needs to handle persistence
|
|
67
|
+
logger.info(`Gmail tokens updated in memory for account ${accountId}. Persistence depends on OpenClaw config management.`);
|
|
148
68
|
}
|
|
149
69
|
/**
|
|
150
70
|
* Handle Gmail OAuth flow
|
|
151
71
|
*
|
|
152
|
-
* This
|
|
72
|
+
* This is an OpenClaw adapter that calls the framework-agnostic OAuth handler
|
|
73
|
+
* from @firela/billclaw-core and adds OpenClaw-specific functionality.
|
|
153
74
|
*
|
|
154
75
|
* Flow:
|
|
155
76
|
* 1. Initialize OAuth (no params) - Returns { url, state }
|
|
156
|
-
* 2. Handle callback (code + state) - Returns { accessToken, refreshToken }
|
|
77
|
+
* 2. Handle callback (code + state + accountId) - Returns { accessToken, refreshToken }
|
|
78
|
+
* - Tokens are automatically saved to account config if accountId is provided
|
|
157
79
|
*
|
|
158
80
|
* @param api - OpenClaw plugin API
|
|
159
|
-
* @param context - OAuth context with optional code
|
|
81
|
+
* @param context - OAuth context with optional code, state, redirectUri, and accountId
|
|
160
82
|
* @returns OAuthResult with URL and/or token
|
|
161
83
|
*/
|
|
162
84
|
export async function gmailOAuthHandler(api, context) {
|
|
163
85
|
try {
|
|
164
|
-
const { code, state, redirectUri } = context || {};
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
86
|
+
const { code, state, redirectUri, accountId } = context || {};
|
|
87
|
+
const config = getGmailConfig(api);
|
|
88
|
+
const logger = getLogger(api);
|
|
89
|
+
// Call the framework-agnostic OAuth handler from core
|
|
90
|
+
const result = await coreGmailOAuthHandler(config, { code, state, redirectUri }, logger);
|
|
91
|
+
// Save tokens to account config if accountId is provided and we have accessToken
|
|
92
|
+
if (accountId && result.accessToken && code) {
|
|
93
|
+
await saveGmailTokensToAccount(api, accountId, result.accessToken, result.refreshToken, result.expiresIn);
|
|
94
|
+
logger.info(`Gmail tokens saved for account ${accountId} (expires in ${result.expiresIn}s)`);
|
|
172
95
|
}
|
|
173
|
-
|
|
174
|
-
if (!state) {
|
|
175
|
-
throw new Error("State parameter is required for code exchange");
|
|
176
|
-
}
|
|
177
|
-
const { accessToken, refreshToken, expiresIn } = await exchangeCodeForToken(api, code, state, redirectUri);
|
|
178
|
-
return {
|
|
179
|
-
url: "",
|
|
180
|
-
accessToken,
|
|
181
|
-
refreshToken,
|
|
182
|
-
expiresIn,
|
|
183
|
-
};
|
|
96
|
+
return result;
|
|
184
97
|
}
|
|
185
98
|
catch (error) {
|
|
186
|
-
api.
|
|
99
|
+
getLogger(api).error("Gmail OAuth error:", error);
|
|
187
100
|
throw error;
|
|
188
101
|
}
|
|
189
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Refresh Gmail access token using refresh token
|
|
105
|
+
*
|
|
106
|
+
* @param api - OpenClaw plugin API
|
|
107
|
+
* @param accountId - Account ID to refresh token for
|
|
108
|
+
* @returns New access token and expiry info, or null if refresh failed
|
|
109
|
+
*/
|
|
110
|
+
export async function refreshGmailToken(api, accountId) {
|
|
111
|
+
const config = api.pluginConfig;
|
|
112
|
+
const logger = getLogger(api);
|
|
113
|
+
// Find the account
|
|
114
|
+
const account = config.accounts?.find((a) => a.id === accountId && a.type === "gmail");
|
|
115
|
+
if (!account) {
|
|
116
|
+
logger.error(`Gmail account ${accountId} not found`);
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const gmailConfig = getGmailConfig(api);
|
|
120
|
+
if (!account.gmailRefreshToken) {
|
|
121
|
+
logger.error(`No refresh token available for Gmail account ${accountId}. User must re-authenticate.`);
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
// Call the framework-agnostic refresh handler from core
|
|
125
|
+
const result = await coreRefreshGmailToken(gmailConfig, account.gmailRefreshToken, logger);
|
|
126
|
+
if (!result) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
// Save new tokens to account config
|
|
130
|
+
await saveGmailTokensToAccount(api, accountId, result.accessToken, account.gmailRefreshToken, result.expiresIn);
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
190
133
|
//# sourceMappingURL=gmail.js.map
|
package/dist/oauth/gmail.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gmail.js","sourceRoot":"","sources":["../../src/oauth/gmail.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gmail.js","sourceRoot":"","sources":["../../src/oauth/gmail.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth/plaid.d.ts
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Plaid OAuth handler -
|
|
2
|
+
* Plaid OAuth handler - OpenClaw adapter
|
|
3
3
|
*
|
|
4
|
-
* This
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* This is an adapter layer that calls the framework-agnostic OAuth implementation
|
|
5
|
+
* from @firela/billclaw-core and adds OpenClaw-specific functionality (config management).
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
import type { OpenClawPluginApi } from "../types/openclaw-plugin.js";
|
|
10
10
|
/**
|
|
11
11
|
* Handle Plaid Link OAuth flow
|
|
12
12
|
*
|
|
13
|
-
* This
|
|
14
|
-
*
|
|
13
|
+
* This is an OpenClaw adapter that calls the framework-agnostic OAuth handler
|
|
14
|
+
* from @firela/billclaw-core and adds OpenClaw-specific functionality.
|
|
15
15
|
*
|
|
16
16
|
* Flow:
|
|
17
17
|
* 1. Create Link token (no params) - Returns { url, token: linkToken }
|
|
18
18
|
* 2. Handle Link success callback - Receives publicToken
|
|
19
19
|
* 3. Exchange public_token for access_token - Returns { url: "", token: accessToken, itemId }
|
|
20
|
+
* - If accountId is provided, tokens are automatically saved to account config
|
|
20
21
|
*
|
|
21
22
|
* @param api - OpenClaw plugin API
|
|
22
23
|
* @param publicToken - Optional public token from Plaid Link callback
|
|
24
|
+
* @param accountId - Optional account ID to save tokens to
|
|
23
25
|
* @returns OAuthResult with URL and token
|
|
24
26
|
*/
|
|
25
|
-
export declare function plaidOAuthHandler(api: OpenClawPluginApi, publicToken?: string): Promise<{
|
|
27
|
+
export declare function plaidOAuthHandler(api: OpenClawPluginApi, publicToken?: string, accountId?: string): Promise<{
|
|
26
28
|
url: string;
|
|
27
29
|
token?: string;
|
|
28
30
|
itemId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plaid.d.ts","sourceRoot":"","sources":["../../src/oauth/plaid.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"plaid.d.ts","sourceRoot":"","sources":["../../src/oauth/plaid.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAyFpE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,iBAAiB,EACtB,WAAW,CAAC,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IACT,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAC,CA6BD"}
|
package/dist/oauth/plaid.js
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Plaid OAuth handler -
|
|
2
|
+
* Plaid OAuth handler - OpenClaw adapter
|
|
3
3
|
*
|
|
4
|
-
* This
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* This is an adapter layer that calls the framework-agnostic OAuth implementation
|
|
5
|
+
* from @firela/billclaw-core and adds OpenClaw-specific functionality (config management).
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { plaidOAuthHandler as corePlaidOAuthHandler, } from "@firela/billclaw-core";
|
|
10
|
+
/**
|
|
11
|
+
* Get a logger from OpenClaw API, or provide a no-op logger
|
|
12
|
+
*/
|
|
13
|
+
function getLogger(api) {
|
|
14
|
+
return {
|
|
15
|
+
info: api.logger?.info || (() => { }),
|
|
16
|
+
error: api.logger?.error || (() => { }),
|
|
17
|
+
warn: api.logger?.warn || (() => { }),
|
|
18
|
+
debug: api.logger?.debug || (() => { }),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
10
21
|
/**
|
|
11
22
|
* Get Plaid configuration from OpenClaw config
|
|
12
23
|
*
|
|
@@ -28,80 +39,64 @@ function getPlaidConfig(api) {
|
|
|
28
39
|
};
|
|
29
40
|
}
|
|
30
41
|
/**
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const plaidClient = createPlaidClient(plaidConfig);
|
|
36
|
-
const request = {
|
|
37
|
-
user: {
|
|
38
|
-
client_user_id: accountId || `user_${Date.now()}`,
|
|
39
|
-
},
|
|
40
|
-
client_name: "BillClaw",
|
|
41
|
-
products: ["transactions"],
|
|
42
|
-
country_codes: ["US"],
|
|
43
|
-
language: "en",
|
|
44
|
-
};
|
|
45
|
-
const axiosResponse = await plaidClient.linkTokenCreate(request);
|
|
46
|
-
const response = axiosResponse.data;
|
|
47
|
-
api.logger.info?.("Plaid Link token created successfully");
|
|
48
|
-
return { linkToken: response.link_token };
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Exchange Plaid public token for access token
|
|
42
|
+
* Save Plaid OAuth tokens to account configuration
|
|
43
|
+
*
|
|
44
|
+
* NOTE: This requires the OpenClaw runtime to support config updates.
|
|
45
|
+
* The actual persistence depends on the OpenClawConfigProvider implementation.
|
|
52
46
|
*/
|
|
53
|
-
async function
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
47
|
+
async function savePlaidTokensToAccount(api, accountId, accessToken, itemId) {
|
|
48
|
+
const logger = getLogger(api);
|
|
49
|
+
// Get config from OpenClaw
|
|
50
|
+
const config = api.pluginConfig;
|
|
51
|
+
// Find and update the account
|
|
52
|
+
const accountIndex = config.accounts?.findIndex((a) => a.id === accountId && a.type === "plaid");
|
|
53
|
+
if (accountIndex === -1 || accountIndex === undefined) {
|
|
54
|
+
logger.warn(`Plaid account ${accountId} not found in config. Tokens not saved.`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// Update account with tokens
|
|
58
|
+
config.accounts[accountIndex] = {
|
|
59
|
+
...config.accounts[accountIndex],
|
|
60
|
+
plaidAccessToken: accessToken,
|
|
61
|
+
plaidItemId: itemId,
|
|
62
|
+
enabled: true, // Auto-enable account after successful OAuth
|
|
65
63
|
};
|
|
64
|
+
// Note: The actual persistence to disk depends on OpenClaw's config management
|
|
65
|
+
// The updated config is in memory but OpenClaw needs to handle persistence
|
|
66
|
+
logger.info(`Plaid tokens updated in memory for account ${accountId}. Persistence depends on OpenClaw config management.`);
|
|
66
67
|
}
|
|
67
68
|
/**
|
|
68
69
|
* Handle Plaid Link OAuth flow
|
|
69
70
|
*
|
|
70
|
-
* This
|
|
71
|
-
*
|
|
71
|
+
* This is an OpenClaw adapter that calls the framework-agnostic OAuth handler
|
|
72
|
+
* from @firela/billclaw-core and adds OpenClaw-specific functionality.
|
|
72
73
|
*
|
|
73
74
|
* Flow:
|
|
74
75
|
* 1. Create Link token (no params) - Returns { url, token: linkToken }
|
|
75
76
|
* 2. Handle Link success callback - Receives publicToken
|
|
76
77
|
* 3. Exchange public_token for access_token - Returns { url: "", token: accessToken, itemId }
|
|
78
|
+
* - If accountId is provided, tokens are automatically saved to account config
|
|
77
79
|
*
|
|
78
80
|
* @param api - OpenClaw plugin API
|
|
79
81
|
* @param publicToken - Optional public token from Plaid Link callback
|
|
82
|
+
* @param accountId - Optional account ID to save tokens to
|
|
80
83
|
* @returns OAuthResult with URL and token
|
|
81
84
|
*/
|
|
82
|
-
export async function plaidOAuthHandler(api, publicToken) {
|
|
85
|
+
export async function plaidOAuthHandler(api, publicToken, accountId) {
|
|
83
86
|
try {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
};
|
|
87
|
+
const config = getPlaidConfig(api);
|
|
88
|
+
const logger = getLogger(api);
|
|
89
|
+
// Call the framework-agnostic OAuth handler from core
|
|
90
|
+
const result = await corePlaidOAuthHandler(config, publicToken, accountId, logger);
|
|
91
|
+
// Save tokens to account config if accountId is provided and we have accessToken
|
|
92
|
+
if (accountId && result.accessToken && publicToken) {
|
|
93
|
+
await savePlaidTokensToAccount(api, accountId, result.accessToken, result.itemId || "");
|
|
94
|
+
logger.info(`Plaid tokens saved for account ${accountId}`);
|
|
92
95
|
}
|
|
93
|
-
|
|
94
|
-
const { accessToken, itemId } = await exchangePublicToken(api, publicToken);
|
|
95
|
-
// Return the access token and item ID for storage
|
|
96
|
-
return {
|
|
97
|
-
url: "",
|
|
98
|
-
token: accessToken,
|
|
99
|
-
itemId,
|
|
100
|
-
accessToken,
|
|
101
|
-
};
|
|
96
|
+
return result;
|
|
102
97
|
}
|
|
103
98
|
catch (error) {
|
|
104
|
-
api.
|
|
99
|
+
getLogger(api).error("Plaid OAuth error:", error);
|
|
105
100
|
throw error;
|
|
106
101
|
}
|
|
107
102
|
}
|
package/dist/oauth/plaid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plaid.js","sourceRoot":"","sources":["../../src/oauth/plaid.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"plaid.js","sourceRoot":"","sources":["../../src/oauth/plaid.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAYnE;;GAEG;;;;;;kBAQa,iBAAiB;;AAPjC,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAYnE;;GAEG;;;;;;kBAQa,iBAAiB;;AAPjC,wBA6NC"}
|
package/dist/plugin.js
CHANGED
|
@@ -176,9 +176,12 @@ export default {
|
|
|
176
176
|
// ========================================================================
|
|
177
177
|
const cfg = api.pluginConfig;
|
|
178
178
|
const plaidSecret = cfg.plaid?.webhookSecret || process.env.PLAID_WEBHOOK_SECRET;
|
|
179
|
+
// Webhook registration is now async (initializes Core components)
|
|
179
180
|
registerWebhookHandlers({
|
|
180
181
|
api,
|
|
181
182
|
plaidWebhookSecret: plaidSecret,
|
|
183
|
+
}).catch((error) => {
|
|
184
|
+
api.logger.error?.("Failed to register webhook handlers:", error);
|
|
182
185
|
});
|
|
183
186
|
// ========================================================================
|
|
184
187
|
// Background Services
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,aAAa,EACb,cAAc,EACd,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD;;GAEG;AACH,eAAe;IACb,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,UAAU;IAChB,WAAW,EACT,oEAAoE;IACtE,IAAI,EAAE,cAAuB;IAE7B,QAAQ,CAAC,GAAsB;QAC7B,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,6BAA6B,CAAC,CAAA;QAEhD,2EAA2E;QAC3E,QAAQ;QACR,2EAA2E;QAE3E,GAAG,CAAC,YAAY,CAAC;YACf,IAAI,EAAE,aAAa,CAAC,IAAI;YACxB,KAAK,EAAE,aAAa,CAAC,KAAK;YAC1B,WAAW,EAAE,aAAa,CAAC,WAAW;YACtC,UAAU,EAAE,aAAa,CAAC,UAAU;YACpC,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;gBACrC,OAAO,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,MAAe,CAAC,CAAA;YACpD,CAAC;SACF,CAAC,CAAA;QAEF,GAAG,CAAC,YAAY,CAAC;YACf,IAAI,EAAE,cAAc,CAAC,IAAI;YACzB,KAAK,EAAE,cAAc,CAAC,KAAK;YAC3B,WAAW,EAAE,cAAc,CAAC,WAAW;YACvC,UAAU,EAAE,cAAc,CAAC,UAAU;YACrC,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;gBACrC,OAAO,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,MAAe,CAAC,CAAA;YACrD,CAAC;SACF,CAAC,CAAA;QAEF,GAAG,CAAC,YAAY,CAAC;YACf,IAAI,EAAE,aAAa,CAAC,IAAI;YACxB,KAAK,EAAE,aAAa,CAAC,KAAK;YAC1B,WAAW,EAAE,aAAa,CAAC,WAAW;YACtC,UAAU,EAAE,aAAa,CAAC,UAAU;YACpC,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;gBACrC,OAAO,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,MAAe,CAAC,CAAA;YACpD,CAAC;SACF,CAAC,CAAA;QAEF,GAAG,CAAC,YAAY,CAAC;YACf,IAAI,EAAE,sBAAsB,CAAC,IAAI;YACjC,KAAK,EAAE,sBAAsB,CAAC,KAAK;YACnC,WAAW,EAAE,sBAAsB,CAAC,WAAW;YAC/C,UAAU,EAAE,sBAAsB,CAAC,UAAU;YAC7C,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;gBACrC,OAAO,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,MAAe,CAAC,CAAA;YAC7D,CAAC;SACF,CAAC,CAAA;QAEF,GAAG,CAAC,YAAY,CAAC;YACf,IAAI,EAAE,wBAAwB,CAAC,IAAI;YACnC,KAAK,EAAE,wBAAwB,CAAC,KAAK;YACrC,WAAW,EAAE,wBAAwB,CAAC,WAAW;YACjD,UAAU,EAAE,wBAAwB,CAAC,UAAU;YAC/C,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;gBACrC,OAAO,wBAAwB,CAAC,OAAO,CAAC,GAAG,EAAE,MAAe,CAAC,CAAA;YAC/D,CAAC;SACF,CAAC,CAAA;QAEF,GAAG,CAAC,YAAY,CAAC;YACf,IAAI,EAAE,sBAAsB,CAAC,IAAI;YACjC,KAAK,EAAE,sBAAsB,CAAC,KAAK;YACnC,WAAW,EAAE,sBAAsB,CAAC,WAAW;YAC/C,UAAU,EAAE,sBAAsB,CAAC,UAAU;YAC7C,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;gBACrC,OAAO,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,MAAe,CAAC,CAAA;YAC7D,CAAC;SACF,CAAC,CAAA;QAEF,2EAA2E;QAC3E,eAAe;QACf,2EAA2E;QAE3E,GAAG,CAAC,WAAW,CAAC;YACd,QAAQ,EAAE;gBACR,OAAO;gBACP,aAAa;gBACb,YAAY;gBACZ,cAAc;gBACd,cAAc;aACf;YACD,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;gBACvB,MAAM,KAAK,GAAG,OAAO;qBAClB,OAAO,CAAC,OAAO,CAAC;qBAChB,WAAW,CAAC,wDAAwD,CAAC,CAAA;gBAExE,KAAK;qBACF,OAAO,CAAC,OAAO,CAAC;qBAChB,WAAW,CAAC,kDAAkD,CAAC;qBAC/D,QAAQ,CAAC,YAAY,EAAE,8CAA8C,CAAC;qBACtE,MAAM,CAAC,kBAAkB,EAAE,eAAe,CAAC;qBAC3C,MAAM,CAAC,mBAAmB,EAAE,YAAY,CAAC;qBACzC,MAAM,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;qBAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,EAAE,OAAiC,EAAE,EAAE;oBACxE,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,yBAAyB,CAAC,CAAA;oBAC5C,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;oBAC3D,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;wBACrB,OAAO;4BACL,OAAO,EAAE,MAAM,CAAC,OAAO;4BACvB,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;yBACvC,CAAA;oBACH,CAAC;oBACD,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAA;gBACpC,CAAC,CAAC,CAAA;gBAEJ,KAAK;qBACF,OAAO,CAAC,MAAM,CAAC;qBACf,WAAW,CAAC,mCAAmC,CAAC;qBAChD,QAAQ,CAAC,aAAa,EAAE,6BAA6B,CAAC;qBACtD,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,EAAE;oBACtC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CACf,UACE,SAAS,CAAC,CAAC,CAAC,YAAY,SAAS,EAAE,CAAC,CAAC,CAAC,eACxC,KAAK,CACN,CAAA;oBACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;oBAC9D,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAA;oBAC3C,OAAO,MAAM,CAAA;gBACf,CAAC,CAAC,CAAA;gBAEJ,KAAK;qBACF,OAAO,CAAC,QAAQ,CAAC;qBACjB,WAAW,CAAC,gDAAgD,CAAC;qBAC7D,MAAM,CAAC,KAAK,IAAI,EAAE;oBACjB,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;oBAC9D,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;oBACpC,OAAO,MAAM,CAAA;gBACf,CAAC,CAAC,CAAA;gBAEJ,KAAK;qBACF,OAAO,CAAC,QAAQ,CAAC;qBACjB,WAAW,CAAC,6BAA6B,CAAC;qBAC1C,QAAQ,CAAC,OAAO,EAAE,wBAAwB,CAAC;qBAC3C,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC;qBAC1C,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG,SAAS,EAAE,KAAK,GAAG,SAAS,EAAE,EAAE;oBACnD,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;wBACjB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,mBAAmB,GAAG,MAAM,KAAK,EAAE,CAAC,CAAA;wBACtD,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE,CAAA;oBAC7C,CAAC;yBAAM,IAAI,GAAG,EAAE,CAAC;wBACf,MAAM,MAAM,GAAG,GAAG,CAAC,YAAuC,CAAA;wBAC1D,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAA;oBAC/B,CAAC;yBAAM,CAAC;wBACN,OAAO,GAAG,CAAC,YAAY,CAAA;oBACzB,CAAC;gBACH,CAAC,CAAC,CAAA;YACN,CAAC;SACF,CAAC,CAAA;QAEF,2EAA2E;QAC3E,kBAAkB;QAClB,2EAA2E;QAE3E,GAAG,CAAC,aAAa,CAAC;YAChB,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,oDAAoD;YACjE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBACzB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,uBAAuB,CAAC,CAAA;gBAC1C,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAA;gBAC9D,MAAM,WAAW,GAAG,OAAO,EAAE,WAAiC,CAAA;gBAC9D,OAAO,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;YAC5C,CAAC;SACF,CAAC,CAAA;QAEF,GAAG,CAAC,aAAa,CAAC;YAChB,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,gDAAgD;YAC7D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBACzB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,uBAAuB,CAAC,CAAA;gBAC1C,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAA;gBAC9D,MAAM,IAAI,GAAG,OAAO,EAAE,IAA0B,CAAA;gBAChD,MAAM,KAAK,GAAG,OAAO,EAAE,KAA2B,CAAA;gBAClD,MAAM,WAAW,GAAG,OAAO,EAAE,WAAiC,CAAA;gBAC9D,OAAO,iBAAiB,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;YAC7D,CAAC;SACF,CAAC,CAAA;QAEF,2EAA2E;QAC3E,mBAAmB;QACnB,2EAA2E;QAE3E,MAAM,GAAG,GAAG,GAAG,CAAC,YAAmB,CAAA;QACnC,MAAM,WAAW,GACf,GAAG,CAAC,KAAK,EAAE,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAA;QAE9D,kEAAkE;QAClE,uBAAuB,CAAC;YACtB,GAAG;YACH,kBAAkB,EAAE,WAAW;SAChC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACjB,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAA;QACnE,CAAC,CAAC,CAAA;QAEF,2EAA2E;QAC3E,sBAAsB;QACtB,2EAA2E;QAE3E,GAAG,CAAC,eAAe,CAAC;YAClB,EAAE,EAAE,eAAe;YACnB,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,gCAAgC,CAAC,CAAA;YACrD,CAAC;YACD,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,gCAAgC,CAAC,CAAA;YACrD,CAAC;SACF,CAAC,CAAA;QAEF,GAAG,CAAC,eAAe,CAAC;YAClB,EAAE,EAAE,kBAAkB;YACtB,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,mCAAmC,CAAC,CAAA;YACxD,CAAC;YACD,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,mCAAmC,CAAC,CAAA;YACxD,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
|
|
@@ -2,8 +2,16 @@
|
|
|
2
2
|
* Webhook handlers for BillClaw OpenClaw plugin
|
|
3
3
|
*
|
|
4
4
|
* This module provides HTTP route handlers for receiving webhooks from
|
|
5
|
-
* external services (Plaid, GoCardless, etc.)
|
|
6
|
-
*
|
|
5
|
+
* external services (Plaid, GoCardless, etc.) using the Core webhook layer.
|
|
6
|
+
*
|
|
7
|
+
* P0 Security Features:
|
|
8
|
+
* - Replay attack protection (timestamp + nonce validation)
|
|
9
|
+
* - Rate limiting (per-IP fixed-window)
|
|
10
|
+
* - Signature verification
|
|
11
|
+
*
|
|
12
|
+
* P1 Error Handling:
|
|
13
|
+
* - Sync failures emit sync.failed event
|
|
14
|
+
* - Retry logic with exponential backoff (3 retries)
|
|
7
15
|
*/
|
|
8
16
|
import type { OpenClawPluginApi } from "../types/openclaw-plugin.js";
|
|
9
17
|
/**
|
|
@@ -15,12 +23,11 @@ interface WebhookHandlerDependencies {
|
|
|
15
23
|
}
|
|
16
24
|
/**
|
|
17
25
|
* Register webhook handlers with OpenClaw HTTP routes
|
|
18
|
-
*
|
|
19
|
-
* This function registers HTTP routes for:
|
|
20
|
-
* - /webhook/plaid - Plaid webhook handler
|
|
21
|
-
* - /webhook/gocardless - GoCardless webhook handler
|
|
22
|
-
* - /webhook/test - Test webhook endpoint
|
|
23
26
|
*/
|
|
24
|
-
export declare function registerWebhookHandlers(dependencies: WebhookHandlerDependencies): void
|
|
27
|
+
export declare function registerWebhookHandlers(dependencies: WebhookHandlerDependencies): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Cleanup rate limit entries (call periodically)
|
|
30
|
+
*/
|
|
31
|
+
export declare function cleanupRateLimits(): void;
|
|
25
32
|
export {};
|
|
26
33
|
//# sourceMappingURL=webhook-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-handler.d.ts","sourceRoot":"","sources":["../../src/services/webhook-handler.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"webhook-handler.d.ts","sourceRoot":"","sources":["../../src/services/webhook-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAYpE;;GAEG;AACH,UAAU,0BAA0B;IAClC,GAAG,EAAE,iBAAiB,CAAA;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAG5B;AAiFD;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,0BAA0B,GACvC,OAAO,CAAC,IAAI,CAAC,CA8Hf;AAkND;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAOxC"}
|
|
@@ -2,19 +2,39 @@
|
|
|
2
2
|
* Webhook handlers for BillClaw OpenClaw plugin
|
|
3
3
|
*
|
|
4
4
|
* This module provides HTTP route handlers for receiving webhooks from
|
|
5
|
-
* external services (Plaid, GoCardless, etc.)
|
|
6
|
-
*
|
|
5
|
+
* external services (Plaid, GoCardless, etc.) using the Core webhook layer.
|
|
6
|
+
*
|
|
7
|
+
* P0 Security Features:
|
|
8
|
+
* - Replay attack protection (timestamp + nonce validation)
|
|
9
|
+
* - Rate limiting (per-IP fixed-window)
|
|
10
|
+
* - Signature verification
|
|
11
|
+
*
|
|
12
|
+
* P1 Error Handling:
|
|
13
|
+
* - Sync failures emit sync.failed event
|
|
14
|
+
* - Retry logic with exponential backoff (3 retries)
|
|
7
15
|
*/
|
|
8
|
-
import {
|
|
9
|
-
|
|
16
|
+
import { WebhookProcessor, createWebhookSecurity, createWebhookDeduplication, createSyncRateLimiter, PlaidWebhookHandler, GoCardlessWebhookHandler, } from "@firela/billclaw-core";
|
|
17
|
+
import { emitEvent, emitSyncFailed } from "@firela/billclaw-core";
|
|
18
|
+
// Global state
|
|
10
19
|
let api = null;
|
|
11
20
|
let configWebhooks = [];
|
|
12
21
|
let plaidWebhookSecret;
|
|
22
|
+
// gocardlessWebhookSecret reserved for future use
|
|
23
|
+
// let gocardlessWebhookSecret: string | undefined
|
|
24
|
+
// Core components
|
|
25
|
+
let processor = null;
|
|
26
|
+
let rateLimiter = null;
|
|
27
|
+
const rateLimitMap = new Map();
|
|
28
|
+
// Rate limit configuration
|
|
29
|
+
const RATE_LIMITS = {
|
|
30
|
+
plaid: { requests: 100, window: 60_000 }, // 100/min
|
|
31
|
+
gocardless: { requests: 50, window: 60_000 }, // 50/min
|
|
32
|
+
test: { requests: 30, window: 60_000 }, // 30/min
|
|
33
|
+
};
|
|
13
34
|
/**
|
|
14
35
|
* Convert OpenClaw logger to BillClaw Logger interface
|
|
15
36
|
*/
|
|
16
37
|
function toLogger(logger) {
|
|
17
|
-
// Ensure all methods are defined and callable
|
|
18
38
|
const log = logger?.info || (() => { });
|
|
19
39
|
const logError = logger?.error || (() => { });
|
|
20
40
|
const logWarn = logger?.warn || (() => console.warn);
|
|
@@ -26,22 +46,112 @@ function toLogger(logger) {
|
|
|
26
46
|
debug: logDebug,
|
|
27
47
|
};
|
|
28
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Check rate limit for a source and IP
|
|
51
|
+
*/
|
|
52
|
+
function checkRateLimit(source, ip) {
|
|
53
|
+
const now = Date.now();
|
|
54
|
+
const key = `${source}:${ip}`;
|
|
55
|
+
const limit = RATE_LIMITS[source];
|
|
56
|
+
let entry = rateLimitMap.get(key);
|
|
57
|
+
// Reset if window expired
|
|
58
|
+
if (!entry || now > entry.resetTime) {
|
|
59
|
+
entry = { count: 0, resetTime: now + limit.window };
|
|
60
|
+
rateLimitMap.set(key, entry);
|
|
61
|
+
}
|
|
62
|
+
// Check if exceeded
|
|
63
|
+
if (entry.count >= limit.requests) {
|
|
64
|
+
const retryAfter = Math.ceil((entry.resetTime - now) / 1000);
|
|
65
|
+
return { allowed: false, retryAfter };
|
|
66
|
+
}
|
|
67
|
+
// Increment counter
|
|
68
|
+
entry.count++;
|
|
69
|
+
return { allowed: true };
|
|
70
|
+
}
|
|
29
71
|
/**
|
|
30
72
|
* Register webhook handlers with OpenClaw HTTP routes
|
|
31
|
-
*
|
|
32
|
-
* This function registers HTTP routes for:
|
|
33
|
-
* - /webhook/plaid - Plaid webhook handler
|
|
34
|
-
* - /webhook/gocardless - GoCardless webhook handler
|
|
35
|
-
* - /webhook/test - Test webhook endpoint
|
|
36
73
|
*/
|
|
37
|
-
export function registerWebhookHandlers(dependencies) {
|
|
74
|
+
export async function registerWebhookHandlers(dependencies) {
|
|
38
75
|
api = dependencies.api;
|
|
39
76
|
plaidWebhookSecret = dependencies.plaidWebhookSecret;
|
|
77
|
+
// gocardlessWebhookSecret reserved for future use
|
|
78
|
+
// gocardlessWebhookSecret = dependencies.gocardlessWebhookSecret
|
|
40
79
|
// Get webhooks from config
|
|
41
80
|
const pluginConfig = api.pluginConfig;
|
|
42
81
|
configWebhooks = pluginConfig?.webhooks || [];
|
|
43
|
-
api.logger
|
|
82
|
+
const logger = toLogger(api.logger);
|
|
83
|
+
// Initialize Core components
|
|
84
|
+
const storageBase = pluginConfig?.storage?.path || "~/.billclaw";
|
|
85
|
+
const basePath = storageBase.startsWith("~")
|
|
86
|
+
? storageBase.replace("~", process.env.HOME || "")
|
|
87
|
+
: storageBase;
|
|
88
|
+
// Create deduplication cache
|
|
89
|
+
const deduplication = await createWebhookDeduplication({
|
|
90
|
+
basePath,
|
|
91
|
+
logger,
|
|
92
|
+
});
|
|
93
|
+
// Create security layer
|
|
94
|
+
const security = createWebhookSecurity(deduplication, logger);
|
|
95
|
+
// Create rate limiter
|
|
96
|
+
rateLimiter = createSyncRateLimiter(logger);
|
|
97
|
+
// Create processor
|
|
98
|
+
processor = new WebhookProcessor({
|
|
99
|
+
logger,
|
|
100
|
+
webhookSecret: plaidWebhookSecret,
|
|
101
|
+
security,
|
|
102
|
+
});
|
|
103
|
+
// Register handlers
|
|
104
|
+
processor.registerHandler("plaid", new PlaidWebhookHandler({
|
|
105
|
+
logger,
|
|
106
|
+
findAccountByItemId: async (itemId) => {
|
|
107
|
+
const accounts = pluginConfig?.accounts || [];
|
|
108
|
+
return accounts.find((acc) => acc.type === "plaid" && acc.plaidItemId === itemId && acc.enabled);
|
|
109
|
+
},
|
|
110
|
+
triggerSync: async (accountId) => {
|
|
111
|
+
const { plaidSyncTool } = await import("../tools/index.js");
|
|
112
|
+
// P1: Retry logic with exponential backoff
|
|
113
|
+
let lastError = null;
|
|
114
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
115
|
+
try {
|
|
116
|
+
await plaidSyncTool.execute(api, { accountId });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
lastError = error;
|
|
121
|
+
if (attempt < 2) {
|
|
122
|
+
// Exponential backoff: 1s, 2s, 4s
|
|
123
|
+
const delay = 2 ** attempt * 1000;
|
|
124
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// All retries failed - emit sync.failed event (P1)
|
|
129
|
+
logger.error?.(`Webhook-triggered sync failed for ${accountId}:`, lastError);
|
|
130
|
+
await emitSyncFailed(logger, configWebhooks, accountId, `webhook_${Date.now()}`, lastError?.message || "Unknown error").catch((err) => logger.debug?.(`Event emission failed:`, err));
|
|
131
|
+
throw lastError;
|
|
132
|
+
},
|
|
133
|
+
emitEvent: async (eventType, data) => {
|
|
134
|
+
await emitEvent(logger, configWebhooks, eventType, data);
|
|
135
|
+
},
|
|
136
|
+
webhooks: configWebhooks,
|
|
137
|
+
rateLimiter: {
|
|
138
|
+
isWebhookSyncAllowed: (accountId) => {
|
|
139
|
+
if (!rateLimiter)
|
|
140
|
+
return true;
|
|
141
|
+
return rateLimiter.isWebhookSyncAllowed(accountId);
|
|
142
|
+
},
|
|
143
|
+
recordWebhookSync: (accountId) => {
|
|
144
|
+
if (!rateLimiter)
|
|
145
|
+
return;
|
|
146
|
+
rateLimiter.recordWebhookSync(accountId);
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
}));
|
|
150
|
+
processor.registerHandler("gocardless", new GoCardlessWebhookHandler({
|
|
151
|
+
logger,
|
|
152
|
+
}));
|
|
44
153
|
// Register HTTP routes
|
|
154
|
+
api.logger.info?.("billclaw webhook handler registered with Core layer");
|
|
45
155
|
api.http?.register({
|
|
46
156
|
path: "/webhook/plaid",
|
|
47
157
|
method: "POST",
|
|
@@ -61,67 +171,75 @@ export function registerWebhookHandlers(dependencies) {
|
|
|
61
171
|
handler: handleTestWebhook,
|
|
62
172
|
});
|
|
63
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Get client IP from request
|
|
176
|
+
*/
|
|
177
|
+
function getClientIp(request) {
|
|
178
|
+
// Check for forwarded IP (proxy/load balancer)
|
|
179
|
+
const forwarded = request.headers["x-forwarded-for"];
|
|
180
|
+
if (forwarded) {
|
|
181
|
+
return forwarded.split(",")[0].trim();
|
|
182
|
+
}
|
|
183
|
+
// Check for real IP header
|
|
184
|
+
const realIp = request.headers["x-real-ip"];
|
|
185
|
+
if (realIp) {
|
|
186
|
+
return realIp;
|
|
187
|
+
}
|
|
188
|
+
// Fallback to query param or default
|
|
189
|
+
return request.query.ip || "unknown";
|
|
190
|
+
}
|
|
64
191
|
/**
|
|
65
192
|
* Handle Plaid webhook
|
|
66
193
|
*
|
|
67
|
-
*
|
|
68
|
-
* - TRANSACTIONS/SYNC_UPDATES_AVAILABLE: Trigger sync for the item
|
|
69
|
-
* - ITEM/ERROR: Emit account.error event
|
|
70
|
-
* - ITEM/LOGIN_REQUIRED: Notify user to re-authenticate
|
|
194
|
+
* Applies rate limiting and delegates to Core processor.
|
|
71
195
|
*/
|
|
72
196
|
async function handlePlaidWebhook(request) {
|
|
73
197
|
try {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
status: 401,
|
|
87
|
-
body: { received: false, error: "Invalid signature" },
|
|
88
|
-
};
|
|
89
|
-
}
|
|
198
|
+
const ip = getClientIp(request);
|
|
199
|
+
// P0: Rate limiting check
|
|
200
|
+
const rateLimit = checkRateLimit("plaid", ip);
|
|
201
|
+
if (!rateLimit.allowed) {
|
|
202
|
+
api?.logger.warn?.(`Rate limit exceeded for Plaid webhook from ${ip}`);
|
|
203
|
+
return {
|
|
204
|
+
status: 429,
|
|
205
|
+
body: {
|
|
206
|
+
received: false,
|
|
207
|
+
error: `Rate limit exceeded. Retry after ${rateLimit.retryAfter} seconds`,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
90
210
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const pluginConfig = api?.pluginConfig;
|
|
97
|
-
const account = pluginConfig?.accounts?.find((acc) => acc.type === "plaid" && acc.plaidItemId === itemId && acc.enabled);
|
|
98
|
-
if (account && api) {
|
|
99
|
-
// Trigger async sync (don't wait for completion)
|
|
100
|
-
const { plaidSyncTool } = await import("../tools/index.js");
|
|
101
|
-
plaidSyncTool
|
|
102
|
-
.execute(api, { accountId: account.id })
|
|
103
|
-
.catch((error) => {
|
|
104
|
-
api?.logger.error?.(`Webhook-triggered sync failed:`, error);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
break;
|
|
109
|
-
case "ITEM":
|
|
110
|
-
if (webhookCode === "ERROR" || webhookCode === "LOGIN_REQUIRED") {
|
|
111
|
-
const error = body.error ?? {
|
|
112
|
-
error_code: webhookCode,
|
|
113
|
-
error_message: "Item login required",
|
|
114
|
-
};
|
|
115
|
-
// Emit account error event
|
|
116
|
-
await emitEvent(toLogger(api.logger), configWebhooks, "account.error", {
|
|
117
|
-
accountId: itemId,
|
|
118
|
-
accountType: "plaid",
|
|
119
|
-
error: JSON.stringify(error),
|
|
120
|
-
}).catch((err) => api?.logger.debug?.(`Event emission failed:`, err));
|
|
121
|
-
}
|
|
122
|
-
break;
|
|
211
|
+
if (!processor) {
|
|
212
|
+
return {
|
|
213
|
+
status: 500,
|
|
214
|
+
body: { received: false, error: "Webhook processor not initialized" },
|
|
215
|
+
};
|
|
123
216
|
}
|
|
124
|
-
|
|
217
|
+
// Normalize request to Core format
|
|
218
|
+
const webhookRequest = {
|
|
219
|
+
body: request.body,
|
|
220
|
+
headers: request.headers,
|
|
221
|
+
query: request.query,
|
|
222
|
+
source: "plaid",
|
|
223
|
+
timestamp: request.headers["plaid-timestamp"]
|
|
224
|
+
? parseInt(request.headers["plaid-timestamp"], 10)
|
|
225
|
+
: undefined,
|
|
226
|
+
nonce: request.body.webhook_id
|
|
227
|
+
? `${request.body.webhook_id}_${request.body.webhook_code}`
|
|
228
|
+
: undefined,
|
|
229
|
+
signature: request.headers["plaid-verification"],
|
|
230
|
+
};
|
|
231
|
+
// Process with Core
|
|
232
|
+
const response = await processor.process(webhookRequest);
|
|
233
|
+
// Convert Core response to OpenClaw format
|
|
234
|
+
return {
|
|
235
|
+
status: response.status,
|
|
236
|
+
body: {
|
|
237
|
+
received: response.body.received,
|
|
238
|
+
error: typeof response.body.error === "string"
|
|
239
|
+
? response.body.error
|
|
240
|
+
: response.body.error?.message || response.body.error?.code,
|
|
241
|
+
},
|
|
242
|
+
};
|
|
125
243
|
}
|
|
126
244
|
catch (error) {
|
|
127
245
|
api?.logger.error?.(`Error handling Plaid webhook:`, error);
|
|
@@ -134,29 +252,80 @@ async function handlePlaidWebhook(request) {
|
|
|
134
252
|
/**
|
|
135
253
|
* Handle GoCardless webhook
|
|
136
254
|
*
|
|
137
|
-
*
|
|
255
|
+
* Applies rate limiting and delegates to Core processor.
|
|
138
256
|
*/
|
|
139
|
-
async function handleGoCardlessWebhook(
|
|
257
|
+
async function handleGoCardlessWebhook(request) {
|
|
140
258
|
try {
|
|
141
|
-
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
259
|
+
const ip = getClientIp(request);
|
|
260
|
+
// P0: Rate limiting check
|
|
261
|
+
const rateLimit = checkRateLimit("gocardless", ip);
|
|
262
|
+
if (!rateLimit.allowed) {
|
|
263
|
+
api?.logger.warn?.(`Rate limit exceeded for GoCardless webhook from ${ip}`);
|
|
264
|
+
return {
|
|
265
|
+
status: 429,
|
|
266
|
+
body: {
|
|
267
|
+
received: false,
|
|
268
|
+
error: `Rate limit exceeded. Retry after ${rateLimit.retryAfter} seconds`,
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
if (!processor) {
|
|
273
|
+
return {
|
|
274
|
+
status: 500,
|
|
275
|
+
body: { received: false, error: "Webhook processor not initialized" },
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
// Normalize request to Core format
|
|
279
|
+
const webhookRequest = {
|
|
280
|
+
body: request.body,
|
|
281
|
+
headers: request.headers,
|
|
282
|
+
query: request.query,
|
|
283
|
+
source: "gocardless",
|
|
284
|
+
// GoCardless doesn't provide timestamp/nonce in standard format
|
|
285
|
+
// Signature is in body.signature
|
|
286
|
+
signature: request.body?.signature,
|
|
287
|
+
};
|
|
288
|
+
// Process with Core
|
|
289
|
+
const response = await processor.process(webhookRequest);
|
|
290
|
+
// Convert Core response to OpenClaw format
|
|
291
|
+
return {
|
|
292
|
+
status: response.status,
|
|
293
|
+
body: {
|
|
294
|
+
received: response.body.received,
|
|
295
|
+
error: typeof response.body.error === "string"
|
|
296
|
+
? response.body.error
|
|
297
|
+
: response.body.error?.message || response.body.error?.code,
|
|
298
|
+
},
|
|
299
|
+
};
|
|
147
300
|
}
|
|
148
301
|
catch (error) {
|
|
149
302
|
api?.logger.error?.(`Error handling GoCardless webhook:`, error);
|
|
150
|
-
return {
|
|
303
|
+
return {
|
|
304
|
+
status: 500,
|
|
305
|
+
body: { received: false, error: "Internal server error" },
|
|
306
|
+
};
|
|
151
307
|
}
|
|
152
308
|
}
|
|
153
309
|
/**
|
|
154
310
|
* Handle test webhook
|
|
155
311
|
*
|
|
156
|
-
* Sends a test event to all configured webhooks
|
|
312
|
+
* Sends a test event to all configured webhooks.
|
|
157
313
|
*/
|
|
158
314
|
async function handleTestWebhook(_request) {
|
|
159
315
|
try {
|
|
316
|
+
const ip = getClientIp(_request);
|
|
317
|
+
// P0: Rate limiting check
|
|
318
|
+
const rateLimit = checkRateLimit("test", ip);
|
|
319
|
+
if (!rateLimit.allowed) {
|
|
320
|
+
api?.logger.warn?.(`Rate limit exceeded for test webhook from ${ip}`);
|
|
321
|
+
return {
|
|
322
|
+
status: 429,
|
|
323
|
+
body: {
|
|
324
|
+
sent: false,
|
|
325
|
+
error: `Rate limit exceeded. Retry after ${rateLimit.retryAfter} seconds`,
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
160
329
|
api?.logger.info?.("Received test webhook request");
|
|
161
330
|
// Emit test event to all configured webhooks
|
|
162
331
|
await emitEvent(toLogger(api.logger), configWebhooks, "webhook.test", {
|
|
@@ -173,4 +342,15 @@ async function handleTestWebhook(_request) {
|
|
|
173
342
|
};
|
|
174
343
|
}
|
|
175
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Cleanup rate limit entries (call periodically)
|
|
347
|
+
*/
|
|
348
|
+
export function cleanupRateLimits() {
|
|
349
|
+
const now = Date.now();
|
|
350
|
+
for (const [key, entry] of rateLimitMap.entries()) {
|
|
351
|
+
if (now > entry.resetTime) {
|
|
352
|
+
rateLimitMap.delete(key);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
176
356
|
//# sourceMappingURL=webhook-handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-handler.js","sourceRoot":"","sources":["../../src/services/webhook-handler.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"webhook-handler.js","sourceRoot":"","sources":["../../src/services/webhook-handler.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firela/billclaw-openclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "BillClaw OpenClaw Plugin - Adapter for OpenClaw AI framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,16 +20,6 @@
|
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|
|
22
22
|
},
|
|
23
|
-
"scripts": {
|
|
24
|
-
"build": "tsc",
|
|
25
|
-
"dev": "tsc --watch",
|
|
26
|
-
"test": "vitest",
|
|
27
|
-
"test:coverage": "vitest --coverage",
|
|
28
|
-
"lint": "oxlint",
|
|
29
|
-
"format": "oxfmt src/",
|
|
30
|
-
"format:write": "oxfmt -w src/",
|
|
31
|
-
"clean": "rm -rf dist"
|
|
32
|
-
},
|
|
33
23
|
"keywords": [
|
|
34
24
|
"openclaw",
|
|
35
25
|
"plugin",
|
|
@@ -58,9 +48,9 @@
|
|
|
58
48
|
"vitest": "^3.0.0"
|
|
59
49
|
},
|
|
60
50
|
"dependencies": {
|
|
61
|
-
"@firela/billclaw-core": "workspace:*",
|
|
62
51
|
"plaid": "^32.0.0",
|
|
63
|
-
"zod": "^3.25.0"
|
|
52
|
+
"zod": "^3.25.0",
|
|
53
|
+
"@firela/billclaw-core": "0.2.0"
|
|
64
54
|
},
|
|
65
55
|
"peerDependencies": {
|
|
66
56
|
"openclaw": "^0.0.1"
|
|
@@ -72,5 +62,15 @@
|
|
|
72
62
|
},
|
|
73
63
|
"engines": {
|
|
74
64
|
"node": ">=20.0.0"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsc",
|
|
68
|
+
"dev": "tsc --watch",
|
|
69
|
+
"test": "vitest",
|
|
70
|
+
"test:coverage": "vitest --coverage",
|
|
71
|
+
"lint": "oxlint",
|
|
72
|
+
"format": "oxfmt src/",
|
|
73
|
+
"format:write": "oxfmt -w src/",
|
|
74
|
+
"clean": "rm -rf dist"
|
|
75
75
|
}
|
|
76
|
-
}
|
|
76
|
+
}
|