@chatcops/server 0.6.0 → 1.0.0-rc.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/README.md +15 -19
- package/dist/adapters/ai-sdk.js +1 -1
- package/dist/adapters/ai-sdk.js.map +1 -1
- package/dist/adapters/cloudflare.js +1 -1
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/express.d.ts.map +1 -1
- package/dist/adapters/express.js +6 -5
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/vercel.js +1 -1
- package/dist/adapters/vercel.js.map +1 -1
- package/dist/client-ip.d.ts +5 -4
- package/dist/client-ip.d.ts.map +1 -1
- package/dist/client-ip.js +9 -14
- package/dist/client-ip.js.map +1 -1
- package/dist/config.d.ts +33 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -1
- package/dist/examples/cloudflare-worker.d.ts.map +1 -1
- package/dist/examples/cloudflare-worker.js +4 -2
- package/dist/examples/cloudflare-worker.js.map +1 -1
- package/dist/examples/express-server.js +3 -1
- package/dist/examples/express-server.js.map +1 -1
- package/dist/examples/vercel-api.d.ts.map +1 -1
- package/dist/examples/vercel-api.js +3 -1
- package/dist/examples/vercel-api.js.map +1 -1
- package/dist/handler.d.ts +2 -0
- package/dist/handler.d.ts.map +1 -1
- package/dist/handler.js +64 -37
- package/dist/handler.js.map +1 -1
- package/dist/http.d.ts +4 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +6 -6
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/knowledge.d.ts +18 -0
- package/dist/knowledge.d.ts.map +1 -0
- package/dist/knowledge.js +32 -0
- package/dist/knowledge.js.map +1 -0
- package/dist/removed-options.d.ts +7 -0
- package/dist/removed-options.d.ts.map +1 -0
- package/dist/removed-options.js +21 -0
- package/dist/removed-options.js.map +1 -0
- package/dist/security/origin-policy.d.ts +3 -5
- package/dist/security/origin-policy.d.ts.map +1 -1
- package/dist/security/origin-policy.js +6 -17
- package/dist/security/origin-policy.js.map +1 -1
- package/dist/security/sessions.d.ts +26 -3
- package/dist/security/sessions.d.ts.map +1 -1
- package/dist/security/sessions.js +69 -11
- package/dist/security/sessions.js.map +1 -1
- package/dist/security/startup-checks.d.ts +2 -1
- package/dist/security/startup-checks.d.ts.map +1 -1
- package/dist/security/startup-checks.js +6 -16
- package/dist/security/startup-checks.js.map +1 -1
- package/dist/visitor-context.d.ts.map +1 -1
- package/dist/visitor-context.js +6 -0
- package/dist/visitor-context.js.map +1 -1
- package/dist/webhook.d.ts +4 -10
- package/dist/webhook.d.ts.map +1 -1
- package/dist/webhook.js +6 -6
- package/dist/webhook.js.map +1 -1
- package/package.json +2 -2
- package/dist/rate-limit.d.ts +0 -20
- package/dist/rate-limit.d.ts.map +0 -1
- package/dist/rate-limit.js +0 -45
- package/dist/rate-limit.js.map +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const UPGRADE_GUIDE = 'https://chat.codercops.com/getting-started/upgrading-to-1/';
|
|
2
|
+
/** Options 1.0 removed, and what to use instead. */
|
|
3
|
+
const REMOVED = {
|
|
4
|
+
cors: "`cors` was removed in 1.0. Use `allowedOrigins: ['https://your.site']`, which also takes several sites and wildcards.",
|
|
5
|
+
conversationStore: '`conversationStore` was removed in 1.0. Use `storage: { conversations: yourStore }`, or a store package.',
|
|
6
|
+
requireSession: '`requireSession` was removed in 1.0: session tokens are required by default. To accept chat requests without one (what `requireSession: false` did), set `allowAnonymous: true`.',
|
|
7
|
+
i18n: "`i18n` was removed in 1.0. It did nothing since 0.6: set the chat's text with the widget's `strings` option.",
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Throws for a config that still sets an option 1.0 removed, so an upgrade
|
|
11
|
+
* fails at startup with what to change instead of quietly behaving
|
|
12
|
+
* differently (an open `cors` site, say, or conversations in memory).
|
|
13
|
+
*/
|
|
14
|
+
export function rejectRemovedOptions(config) {
|
|
15
|
+
for (const [option, message] of Object.entries(REMOVED)) {
|
|
16
|
+
if (option in config && config[option] !== undefined) {
|
|
17
|
+
throw new Error(`${message} See ${UPGRADE_GUIDE}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=removed-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"removed-options.js","sourceRoot":"","sources":["../src/removed-options.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,4DAA4D,CAAC;AAEnF,oDAAoD;AACpD,MAAM,OAAO,GAA2B;IACtC,IAAI,EAAE,uHAAuH;IAC7H,iBAAiB,EAAE,0GAA0G;IAC7H,cAAc,EACZ,kLAAkL;IACpL,IAAI,EAAE,8GAA8G;CACrH,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,IAAI,MAAM,IAAI,MAAM,IAAK,MAAkC,CAAC,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;YAClF,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,QAAQ,aAAa,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChatCopsServerConfig } from '../config.js';
|
|
2
|
-
/** `allowedOrigins`, or
|
|
3
|
-
export declare function allowedOriginsOf(config: Pick<ChatCopsServerConfig, 'allowedOrigins'
|
|
2
|
+
/** `allowedOrigins`, or any origin. */
|
|
3
|
+
export declare function allowedOriginsOf(config: Pick<ChatCopsServerConfig, 'allowedOrigins'>): string[];
|
|
4
4
|
export interface OriginPolicy {
|
|
5
5
|
/** False for a browser request from a page whose origin isn't allowed. Requests without `Origin` pass. */
|
|
6
6
|
allows(origin: string | null): boolean;
|
|
@@ -13,7 +13,5 @@ export interface OriginPolicy {
|
|
|
13
13
|
* Which sites can use the chat. This stops other sites embedding your bot in
|
|
14
14
|
* their pages; it doesn't stop scripts, which can send any `Origin`.
|
|
15
15
|
*/
|
|
16
|
-
export declare function originPolicy(config: Pick<ChatCopsServerConfig, 'allowedOrigins' | '
|
|
17
|
-
/** For tests. */
|
|
18
|
-
export declare function resetCorsWarning(): void;
|
|
16
|
+
export declare function originPolicy(config: Pick<ChatCopsServerConfig, 'allowedOrigins' | 'logger'>): OriginPolicy;
|
|
19
17
|
//# sourceMappingURL=origin-policy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origin-policy.d.ts","sourceRoot":"","sources":["../../src/security/origin-policy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"origin-policy.d.ts","sourceRoot":"","sources":["../../src/security/origin-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAMzD,uCAAuC;AACvC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,GAAG,MAAM,EAAE,CAS/F;AAED,MAAM,WAAW,YAAY;IAC3B,0GAA0G;IAC1G,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC;IACvC,sEAAsE;IACtE,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,wCAAwC;IACxC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,GAAG,QAAQ,CAAC,GAAG,YAAY,CA4B1G"}
|
|
@@ -1,24 +1,16 @@
|
|
|
1
|
+
import { consoleLogger } from '@chatcops/core';
|
|
1
2
|
import { corsHeaders, matchOrigin } from './origin.js';
|
|
2
|
-
|
|
3
|
+
import { rejectRemovedOptions } from '../removed-options.js';
|
|
3
4
|
const MAX_REFUSAL_LOGS = 20;
|
|
4
|
-
/** `allowedOrigins`, or
|
|
5
|
+
/** `allowedOrigins`, or any origin. */
|
|
5
6
|
export function allowedOriginsOf(config) {
|
|
6
|
-
|
|
7
|
-
throw new Error('Set `allowedOrigins` or `cors`, not both. `allowedOrigins` replaces `cors`.');
|
|
8
|
-
}
|
|
7
|
+
rejectRemovedOptions(config);
|
|
9
8
|
if (config.allowedOrigins !== undefined) {
|
|
10
9
|
if (config.allowedOrigins.length === 0) {
|
|
11
10
|
throw new Error("`allowedOrigins` is empty, so no site could use the chat. List your sites, or use ['*'] for any site.");
|
|
12
11
|
}
|
|
13
12
|
return config.allowedOrigins;
|
|
14
13
|
}
|
|
15
|
-
if (config.cors !== undefined) {
|
|
16
|
-
if (!warnedCors) {
|
|
17
|
-
warnedCors = true;
|
|
18
|
-
console.warn(`[chatcops] \`cors\` is deprecated. Use \`allowedOrigins: ['${config.cors}']\`, which also takes several sites and wildcards like 'https://*.acme.com'.`);
|
|
19
|
-
}
|
|
20
|
-
return [config.cors];
|
|
21
|
-
}
|
|
22
14
|
return ['*'];
|
|
23
15
|
}
|
|
24
16
|
/**
|
|
@@ -28,6 +20,7 @@ export function allowedOriginsOf(config) {
|
|
|
28
20
|
export function originPolicy(config) {
|
|
29
21
|
const allowed = allowedOriginsOf(config);
|
|
30
22
|
const logged = new Set();
|
|
23
|
+
const logger = config.logger ?? consoleLogger();
|
|
31
24
|
const allows = (origin) => !origin || matchOrigin(origin, allowed) !== null;
|
|
32
25
|
const headers = (origin) => {
|
|
33
26
|
if (allows(origin))
|
|
@@ -36,7 +29,7 @@ export function originPolicy(config) {
|
|
|
36
29
|
// the 403 and say why in the console.
|
|
37
30
|
if (logged.size < MAX_REFUSAL_LOGS && origin && !logged.has(origin)) {
|
|
38
31
|
logged.add(origin);
|
|
39
|
-
|
|
32
|
+
logger.warn('origin_refused', `Refused a request from ${origin}, which isn't in allowedOrigins.`, { origin });
|
|
40
33
|
}
|
|
41
34
|
return { 'Access-Control-Allow-Origin': origin ?? '', Vary: 'Origin' };
|
|
42
35
|
};
|
|
@@ -51,8 +44,4 @@ export function originPolicy(config) {
|
|
|
51
44
|
}),
|
|
52
45
|
};
|
|
53
46
|
}
|
|
54
|
-
/** For tests. */
|
|
55
|
-
export function resetCorsWarning() {
|
|
56
|
-
warnedCors = false;
|
|
57
|
-
}
|
|
58
47
|
//# sourceMappingURL=origin-policy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origin-policy.js","sourceRoot":"","sources":["../../src/security/origin-policy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"origin-policy.js","sourceRoot":"","sources":["../../src/security/origin-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B,uCAAuC;AACvC,MAAM,UAAU,gBAAgB,CAAC,MAAoD;IACnF,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACxC,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,uGAAuG,CAAC,CAAC;QAC3H,CAAC;QACD,OAAO,MAAM,CAAC,cAAc,CAAC;IAC/B,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAWD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAA+D;IAC1F,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;IAEhD,MAAM,MAAM,GAAG,CAAC,MAAqB,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAE3F,MAAM,OAAO,GAAG,CAAC,MAAqB,EAA0B,EAAE;QAChE,IAAI,MAAM,CAAC,MAAM,CAAC;YAAE,OAAO,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACxD,wEAAwE;QACxE,sCAAsC;QACtC,IAAI,MAAM,CAAC,IAAI,GAAG,gBAAgB,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,0BAA0B,MAAM,kCAAkC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAChH,CAAC;QACD,OAAO,EAAE,6BAA6B,EAAE,MAAM,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACzE,CAAC,CAAC;IAEF,OAAO;QACL,MAAM;QACN,OAAO;QACP,gBAAgB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC7B,GAAG,OAAO,CAAC,MAAM,CAAC;YAClB,8BAA8B,EAAE,eAAe;YAC/C,8BAA8B,EAAE,kDAAkD;YAClF,wBAAwB,EAAE,OAAO;SAClC,CAAC;KACH,CAAC;AACJ,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Logger } from '@chatcops/core';
|
|
1
2
|
import { type WireErrorBody, type WireErrorCode } from '@chatcops/core';
|
|
2
3
|
import { type SessionClaims } from './session-token.js';
|
|
3
4
|
import { type TurnstileConfig } from './turnstile.js';
|
|
@@ -12,10 +13,21 @@ export declare const DEFAULT_SESSION_TTL_SEC = 900;
|
|
|
12
13
|
/** An expired token still resumes its conversation for this long after it expires. */
|
|
13
14
|
export declare const SESSION_RESUME_GRACE_SEC: number;
|
|
14
15
|
export interface SessionConfig {
|
|
16
|
+
logger?: Logger;
|
|
15
17
|
sessionSecrets?: string[];
|
|
16
18
|
sessionTtlSec?: number;
|
|
17
|
-
|
|
19
|
+
allowAnonymous?: boolean;
|
|
18
20
|
turnstile?: TurnstileConfig;
|
|
21
|
+
identity?: {
|
|
22
|
+
secret: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** What `/session` needs to know about a conversation id. */
|
|
26
|
+
export interface ConversationInfo {
|
|
27
|
+
/** Nothing is stored under it yet. */
|
|
28
|
+
unused: boolean;
|
|
29
|
+
/** The signed-in user it belongs to, from a `userToken`. */
|
|
30
|
+
uid?: string;
|
|
19
31
|
}
|
|
20
32
|
export type SessionCheck = {
|
|
21
33
|
ok: true;
|
|
@@ -43,7 +55,18 @@ export interface Sessions {
|
|
|
43
55
|
}
|
|
44
56
|
/**
|
|
45
57
|
* `undefined` when `sessionSecrets` isn't set. Throws at startup on a bad
|
|
46
|
-
* config. `
|
|
58
|
+
* config. `lookup` says what's stored under a conversation id.
|
|
59
|
+
*/
|
|
60
|
+
export declare function createSessions(config: SessionConfig, lookup?: (conversationId: string) => Promise<ConversationInfo>, now?: () => number): Sessions | undefined;
|
|
61
|
+
interface UserClaims {
|
|
62
|
+
sub: string;
|
|
63
|
+
tier?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A host site's `userToken`: an HS256 JWT signed with `identity.secret`, with
|
|
67
|
+
* `sub` (the user id, up to 128 characters), `exp` in seconds and an optional
|
|
68
|
+
* `tier`. `undefined` when it doesn't verify or has expired.
|
|
47
69
|
*/
|
|
48
|
-
export declare function
|
|
70
|
+
export declare function verifyUserToken(token: string, key: CryptoKey, nowSec: number): Promise<UserClaims | undefined>;
|
|
71
|
+
export {};
|
|
49
72
|
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/security/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/security/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAa,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAyF,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC/I,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEvE;;;;;;GAMG;AAEH,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,sFAAsF;AACtF,eAAO,MAAM,wBAAwB,QAAoB,CAAC;AAI1D,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC;CACpF;AAED,MAAM,WAAW,QAAQ;IACvB,yDAAyD;IACzD,QAAQ,EAAE,OAAO,CAAC;IAClB,+BAA+B;IAC/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACrF,iFAAiF;IACjF,KAAK,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACvH;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,MAAM,GAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAmC,EAC/F,GAAG,GAAE,MAAM,MAAiB,GAC3B,QAAQ,GAAG,SAAS,CAgItB;AA8CD,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAapH"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { consoleLogger } from '@chatcops/core';
|
|
1
2
|
import { errorBody } from '@chatcops/core';
|
|
2
|
-
import { importSessionKey, signSession, verifySession } from './session-token.js';
|
|
3
|
+
import { base64UrlDecode, importSessionKey, signSession, verifySession, verifySessionSignature } from './session-token.js';
|
|
3
4
|
import { verifyTurnstile } from './turnstile.js';
|
|
4
5
|
/**
|
|
5
6
|
* Session tokens for the chat endpoint. `POST /session` gives the widget a
|
|
@@ -15,17 +16,24 @@ const MIN_SECRET_BYTES = 32;
|
|
|
15
16
|
const MAX_ID_LENGTH = 128;
|
|
16
17
|
/**
|
|
17
18
|
* `undefined` when `sessionSecrets` isn't set. Throws at startup on a bad
|
|
18
|
-
* config. `
|
|
19
|
+
* config. `lookup` says what's stored under a conversation id.
|
|
19
20
|
*/
|
|
20
|
-
export function createSessions(config,
|
|
21
|
+
export function createSessions(config, lookup = async () => ({ unused: false }), now = Date.now) {
|
|
21
22
|
const secrets = config.sessionSecrets;
|
|
22
23
|
if (secrets === undefined) {
|
|
23
|
-
if (config.
|
|
24
|
-
throw new Error('`
|
|
24
|
+
if (!config.allowAnonymous) {
|
|
25
|
+
throw new Error('Chat requests need a session token unless `allowAnonymous: true` is set. Set `sessionSecrets` (generate one with `openssl rand -base64 32`, and keep it on the server); the widget fetches tokens by itself. Or set `allowAnonymous: true` to accept chat without them. See https://chat.codercops.com/server/setup/#session-tokens');
|
|
26
|
+
}
|
|
25
27
|
if (config.turnstile)
|
|
26
28
|
throw new Error('`turnstile` is checked when a session token is issued, so it needs `sessionSecrets`.');
|
|
29
|
+
if (config.identity)
|
|
30
|
+
throw new Error('`identity` goes into session tokens, so it needs `sessionSecrets`.');
|
|
27
31
|
return undefined;
|
|
28
32
|
}
|
|
33
|
+
const identitySecret = config.identity?.secret;
|
|
34
|
+
if (config.identity && (typeof identitySecret !== 'string' || new TextEncoder().encode(identitySecret).byteLength < MIN_SECRET_BYTES)) {
|
|
35
|
+
throw new Error(`\`identity.secret\` needs at least ${MIN_SECRET_BYTES} bytes, like \`sessionSecrets\`.`);
|
|
36
|
+
}
|
|
29
37
|
const turnstile = config.turnstile;
|
|
30
38
|
if (turnstile && !turnstile.secretKey)
|
|
31
39
|
throw new Error('`turnstile` needs its `secretKey`.');
|
|
@@ -43,8 +51,10 @@ export function createSessions(config, isUnused = async () => false, now = Date.
|
|
|
43
51
|
// Imported on first use: Workers don't allow crypto.subtle at global scope.
|
|
44
52
|
let keys;
|
|
45
53
|
const getKeys = () => (keys ??= Promise.all(secrets.map((secret) => importSessionKey(secret))));
|
|
54
|
+
let identityKey;
|
|
55
|
+
const getIdentityKey = () => (identityKey ??= importSessionKey(identitySecret));
|
|
46
56
|
const nowSec = () => Math.floor(now() / 1000);
|
|
47
|
-
const required = config.
|
|
57
|
+
const required = !config.allowAnonymous;
|
|
48
58
|
return {
|
|
49
59
|
required,
|
|
50
60
|
async mint(body, origin, clientIp) {
|
|
@@ -56,7 +66,8 @@ export function createSessions(config, isUnused = async () => false, now = Date.
|
|
|
56
66
|
// Resuming a conversation needs a token that was issued for it, from
|
|
57
67
|
// this origin. Expired is fine within the grace window. An id with
|
|
58
68
|
// nothing stored yet (the widget makes its own) is given out as is,
|
|
59
|
-
// since there's nothing in it to read
|
|
69
|
+
// since there's nothing in it to read, and so is a signed-in user's own
|
|
70
|
+
// conversation (with a \`userToken\` for them). Anything else gets a new
|
|
60
71
|
// conversation, so a guessed or leaked id is useless.
|
|
61
72
|
let resumed;
|
|
62
73
|
let cid;
|
|
@@ -70,6 +81,19 @@ export function createSessions(config, isUnused = async () => false, now = Date.
|
|
|
70
81
|
if (result.ok)
|
|
71
82
|
resumed = result.claims;
|
|
72
83
|
}
|
|
84
|
+
// A visitor the host site signed in. A token that doesn't verify is an
|
|
85
|
+
// error, not an anonymous session, so a bug on the host site shows.
|
|
86
|
+
let user;
|
|
87
|
+
if (request.userToken !== undefined) {
|
|
88
|
+
if (!identitySecret)
|
|
89
|
+
return { status: 400, body: errorBody('invalid_request', { message: '`userToken` needs `identity` on the server.' }) };
|
|
90
|
+
user = await verifyUserToken(request.userToken, await getIdentityKey(), time);
|
|
91
|
+
if (!user)
|
|
92
|
+
return { status: 401, body: errorBody('session_required', { message: 'The userToken is invalid or has expired.' }) };
|
|
93
|
+
}
|
|
94
|
+
// A token for another user doesn't carry over.
|
|
95
|
+
if (resumed?.uid && resumed.uid !== user?.sub)
|
|
96
|
+
resumed = undefined;
|
|
73
97
|
// A refresh was checked when its first token was issued; a new session
|
|
74
98
|
// has to pass Turnstile first.
|
|
75
99
|
if (turnstile && !resumed) {
|
|
@@ -79,7 +103,7 @@ export function createSessions(config, isUnused = async () => false, now = Date.
|
|
|
79
103
|
});
|
|
80
104
|
if (!result.ok) {
|
|
81
105
|
if (result.code === 'unavailable') {
|
|
82
|
-
|
|
106
|
+
(config.logger ?? consoleLogger()).warn('turnstile_unavailable', 'Turnstile could not be reached, so no session token was issued.');
|
|
83
107
|
return { status: 503, body: errorBody('turnstile_failed', { message: 'Turnstile could not be reached. Try again.' }) };
|
|
84
108
|
}
|
|
85
109
|
return { status: 401, body: errorBody('turnstile_failed', { message: 'The Turnstile check failed.' }) };
|
|
@@ -87,8 +111,12 @@ export function createSessions(config, isUnused = async () => false, now = Date.
|
|
|
87
111
|
}
|
|
88
112
|
if (resumed)
|
|
89
113
|
cid = resumed.cid;
|
|
90
|
-
else if (request.conversationId
|
|
91
|
-
|
|
114
|
+
else if (request.conversationId) {
|
|
115
|
+
const info = await lookup(request.conversationId);
|
|
116
|
+
// Nothing stored yet, or this signed-in user's own conversation.
|
|
117
|
+
if (info.unused || (user && info.uid === user.sub))
|
|
118
|
+
cid = request.conversationId;
|
|
119
|
+
}
|
|
92
120
|
const claims = {
|
|
93
121
|
v: 1,
|
|
94
122
|
sid: resumed?.sid ?? crypto.randomUUID(),
|
|
@@ -96,6 +124,7 @@ export function createSessions(config, isUnused = async () => false, now = Date.
|
|
|
96
124
|
org,
|
|
97
125
|
iat: time,
|
|
98
126
|
exp: time + ttlSec,
|
|
127
|
+
...(user ? { uid: user.sub, ...(user.tier ? { tier: user.tier } : {}) } : {}),
|
|
99
128
|
};
|
|
100
129
|
const token = await signSession(claims, await getKeys());
|
|
101
130
|
return { status: 200, body: { token, expiresAt: claims.exp * 1000, conversationId: claims.cid } };
|
|
@@ -132,8 +161,13 @@ function readMintRequest(body) {
|
|
|
132
161
|
return {};
|
|
133
162
|
if (typeof body !== 'object' || Array.isArray(body))
|
|
134
163
|
return undefined;
|
|
135
|
-
const { conversationId, previousToken, turnstileToken, idempotencyKey } = body;
|
|
164
|
+
const { conversationId, previousToken, turnstileToken, idempotencyKey, userToken } = body;
|
|
136
165
|
const request = {};
|
|
166
|
+
if (userToken !== undefined) {
|
|
167
|
+
if (typeof userToken !== 'string' || userToken.length > 4096)
|
|
168
|
+
return undefined;
|
|
169
|
+
request.userToken = userToken;
|
|
170
|
+
}
|
|
137
171
|
if (turnstileToken !== undefined) {
|
|
138
172
|
if (typeof turnstileToken !== 'string' || turnstileToken.length > 4096)
|
|
139
173
|
return undefined;
|
|
@@ -156,4 +190,28 @@ function readMintRequest(body) {
|
|
|
156
190
|
}
|
|
157
191
|
return request;
|
|
158
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* A host site's `userToken`: an HS256 JWT signed with `identity.secret`, with
|
|
195
|
+
* `sub` (the user id, up to 128 characters), `exp` in seconds and an optional
|
|
196
|
+
* `tier`. `undefined` when it doesn't verify or has expired.
|
|
197
|
+
*/
|
|
198
|
+
export async function verifyUserToken(token, key, nowSec) {
|
|
199
|
+
if (!(await verifySessionSignature(token, [key])))
|
|
200
|
+
return undefined;
|
|
201
|
+
let payload;
|
|
202
|
+
try {
|
|
203
|
+
payload = JSON.parse(new TextDecoder().decode(base64UrlDecode(token.split('.')[1] ?? '')));
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
const { sub, exp, tier } = payload ?? {};
|
|
209
|
+
if (typeof sub !== 'string' || sub.length === 0 || sub.length > 128)
|
|
210
|
+
return undefined;
|
|
211
|
+
if (typeof exp !== 'number' || !Number.isFinite(exp) || exp + 60 < nowSec)
|
|
212
|
+
return undefined;
|
|
213
|
+
if (tier !== undefined && (typeof tier !== 'string' || tier.length > 64))
|
|
214
|
+
return undefined;
|
|
215
|
+
return { sub, ...(typeof tier === 'string' ? { tier } : {}) };
|
|
216
|
+
}
|
|
159
217
|
//# sourceMappingURL=sessions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/security/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA0C,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAsB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/security/sessions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Logger } from '@chatcops/core';
|
|
1
2
|
/**
|
|
2
3
|
* Startup checks for the security settings the server is about to add: the
|
|
3
4
|
* allowed origins and the secrets that sign session tokens.
|
|
@@ -40,5 +41,5 @@ export interface SecuritySummary {
|
|
|
40
41
|
/** The one line the server logs at startup about its security settings. */
|
|
41
42
|
export declare function describeSecurity(summary: SecuritySummary): string;
|
|
42
43
|
/** Logs the problems `checkSecuritySettings` finds, errors first, then the summary line. */
|
|
43
|
-
export declare function logSecurityAtStartup(settings: SecuritySettings & Omit<SecuritySummary, 'allowedOrigins'
|
|
44
|
+
export declare function logSecurityAtStartup(settings: SecuritySettings & Omit<SecuritySummary, 'allowedOrigins'>, logger?: Logger): void;
|
|
44
45
|
//# sourceMappingURL=startup-checks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startup-checks.d.ts","sourceRoot":"","sources":["../../src/security/startup-checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,0DAA0D;AAC1D,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;CACjB;AAwBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACvC,eAAe,EAAE,CAkFnB;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CASjE;AAED,4FAA4F;AAC5F,wBAAgB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"startup-checks.d.ts","sourceRoot":"","sources":["../../src/security/startup-checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC5D;;;;;;;;;;GAUG;AAEH,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,0DAA0D;AAC1D,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;CACjB;AAwBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACvC,eAAe,EAAE,CAkFnB;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CASjE;AAED,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,gBAAgB,CAAC,EACpE,MAAM,GAAE,MAAwB,GAC/B,IAAI,CAMN"}
|
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Startup checks for the security settings the server is about to add: the
|
|
3
|
-
* allowed origins and the secrets that sign session tokens.
|
|
4
|
-
*
|
|
5
|
-
* These are the mistakes that fail silently. A secret that is ten characters
|
|
6
|
-
* long works, and so does a secret that is also a `NEXT_PUBLIC_` variable, so
|
|
7
|
-
* nothing breaks until the day it does. A function that finds them before the
|
|
8
|
-
* server starts is worth more than one that finds them during a request.
|
|
9
|
-
*
|
|
10
|
-
* Nothing here logs or throws. The caller decides what to do with a problem.
|
|
11
|
-
*/
|
|
1
|
+
import { consoleLogger } from '@chatcops/core';
|
|
12
2
|
/** How many bytes a session secret needs to be worth signing with. */
|
|
13
3
|
const MIN_SECRET_BYTES = 32;
|
|
14
4
|
/**
|
|
@@ -119,16 +109,16 @@ export function describeSecurity(summary) {
|
|
|
119
109
|
const sessions = summary.sessionTtlSec === undefined
|
|
120
110
|
? 'session tokens off'
|
|
121
111
|
: `session tokens on (${summary.sessionTtlSec}s${summary.requireSession === false ? ', not required' : ''})`;
|
|
122
|
-
return `
|
|
112
|
+
return `Security: chat allowed from ${origins}; ${sessions}; Turnstile ${summary.turnstile ? 'on' : 'off'}.`;
|
|
123
113
|
}
|
|
124
114
|
/** Logs the problems `checkSecuritySettings` finds, errors first, then the summary line. */
|
|
125
|
-
export function logSecurityAtStartup(settings) {
|
|
115
|
+
export function logSecurityAtStartup(settings, logger = consoleLogger()) {
|
|
126
116
|
const allowedOrigins = settings.allowedOrigins ?? ['*'];
|
|
127
117
|
const problems = checkSecuritySettings({ ...settings, allowedOrigins });
|
|
128
118
|
for (const problem of problems.filter((p) => p.level === 'error'))
|
|
129
|
-
|
|
119
|
+
logger.error('insecure_config', `ERROR: ${problem.message}`);
|
|
130
120
|
for (const problem of problems.filter((p) => p.level === 'warning'))
|
|
131
|
-
|
|
132
|
-
|
|
121
|
+
logger.warn('insecure_config', problem.message);
|
|
122
|
+
logger.info('security', describeSecurity({ ...settings, allowedOrigins }));
|
|
133
123
|
}
|
|
134
124
|
//# sourceMappingURL=startup-checks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startup-checks.js","sourceRoot":"","sources":["../../src/security/startup-checks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"startup-checks.js","sourceRoot":"","sources":["../../src/security/startup-checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visitor-context.d.ts","sourceRoot":"","sources":["../src/visitor-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,kSACyP,CAAC;AAElS,yFAAyF;AACzF,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAc9C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,oBAAoB,EAAE,aAAa,GAAG,UAAU,CAAC,GAAG,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"visitor-context.d.ts","sourceRoot":"","sources":["../src/visitor-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,kSACyP,CAAC;AAElS,yFAAyF;AACzF,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAc9C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,oBAAoB,EAAE,aAAa,GAAG,UAAU,CAAC,GAAG,MAAM,GAAG,IAAI,CA0B9G;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,EAAE,CAOjG;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD"}
|
package/dist/visitor-context.js
CHANGED
|
@@ -27,6 +27,12 @@ export function buildVisitorContext(req) {
|
|
|
27
27
|
lines.push(`Page title: ${clean(req.pageContext.title)}`);
|
|
28
28
|
if (req.pageContext.description)
|
|
29
29
|
lines.push(`Page description: ${clean(req.pageContext.description)}`);
|
|
30
|
+
const added = Object.entries(req.pageContext.data ?? {}).filter(([, value]) => clean(value));
|
|
31
|
+
if (added.length > 0) {
|
|
32
|
+
lines.push('Details the page added (not verified):');
|
|
33
|
+
for (const [key, value] of added)
|
|
34
|
+
lines.push(`- ${clean(key)}: ${clean(value)}`);
|
|
35
|
+
}
|
|
30
36
|
}
|
|
31
37
|
const entries = Object.entries(req.userData ?? {}).filter(([, value]) => clean(value));
|
|
32
38
|
if (entries.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visitor-context.js","sourceRoot":"","sources":["../src/visitor-context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GACtC,+RAA+R,CAAC;AAElS,yFAAyF;AACzF,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C,MAAM,GAAG,GAAG,iBAAiB,CAAC;AAE9B,yGAAyG;AACzG,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,KAAK;QACV,uFAAuF;SACtF,OAAO,CAAC,yBAAyB,EAAE,GAAG,CAAC;SACvC,OAAO,CAAC,IAAI,MAAM,CAAC,cAAc,GAAG,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;SACxD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAA2D;IAC7F,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,+FAA+F;QAC/F,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC;QAChF,IAAI,GAAG,CAAC,WAAW,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,IAAI,GAAG,CAAC,WAAW,CAAC,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"visitor-context.js","sourceRoot":"","sources":["../src/visitor-context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GACtC,+RAA+R,CAAC;AAElS,yFAAyF;AACzF,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C,MAAM,GAAG,GAAG,iBAAiB,CAAC;AAE9B,yGAAyG;AACzG,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,KAAK;QACV,uFAAuF;SACtF,OAAO,CAAC,yBAAyB,EAAE,GAAG,CAAC;SACvC,OAAO,CAAC,IAAI,MAAM,CAAC,cAAc,GAAG,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;SACxD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAA2D;IAC7F,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,+FAA+F;QAC/F,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC;QAChF,IAAI,GAAG,CAAC,WAAW,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,IAAI,GAAG,CAAC,WAAW,CAAC,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACvG,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7F,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;YACrD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACvF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAC/E,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,IAAI,CAAC,MAAM,GAAG,yBAAyB;QAAE,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,yBAAyB,CAAC,KAAK,CAAC;IACrG,OAAO,IAAI,GAAG,MAAM,IAAI,OAAO,GAAG,GAAG,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAuB,EAAE,OAAsB;IAChF,IAAI,CAAC,OAAO;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,QAAQ,CAAC;IAClC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CACjC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CACpF,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,kCAAkC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACzD,CAAC"}
|
package/dist/webhook.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
/**
|
|
3
|
-
* The JSON body of every delivery. `event` and `timestamp` repeat `type` and
|
|
4
|
-
* `created` for receivers written against the old format.
|
|
5
|
-
*/
|
|
1
|
+
import { type Logger, type WebhookConfig } from '@chatcops/core';
|
|
2
|
+
/** The JSON body of every delivery. */
|
|
6
3
|
export interface WebhookEvent<T = unknown> {
|
|
7
4
|
/** Unique per event, and the same on every retry, so receivers can drop duplicates. */
|
|
8
5
|
id: string;
|
|
@@ -10,10 +7,6 @@ export interface WebhookEvent<T = unknown> {
|
|
|
10
7
|
/** Milliseconds since the epoch. */
|
|
11
8
|
created: number;
|
|
12
9
|
data: T;
|
|
13
|
-
/** @deprecated Same as `type`. */
|
|
14
|
-
event: string;
|
|
15
|
-
/** @deprecated Same as `created`. */
|
|
16
|
-
timestamp: number;
|
|
17
10
|
}
|
|
18
11
|
export declare const DEFAULT_WEBHOOK_TIMEOUT_MS = 5000;
|
|
19
12
|
export declare const SIGNATURE_HEADER = "X-ChatCops-Signature";
|
|
@@ -34,7 +27,8 @@ export declare function assertSafeWebhookUrl(rawUrl: string, allowPrivateNetwork
|
|
|
34
27
|
export declare class WebhookDispatcher {
|
|
35
28
|
private configs;
|
|
36
29
|
private timeoutMs;
|
|
37
|
-
|
|
30
|
+
private logger;
|
|
31
|
+
constructor(configs: WebhookConfig[], timeoutMs?: number, logger?: Logger);
|
|
38
32
|
dispatch(event: string, data: unknown): Promise<void>;
|
|
39
33
|
private send;
|
|
40
34
|
}
|
package/dist/webhook.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEhF,uCAAuC;AACvC,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,uFAAuF;IACvF,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,CAAC,CAAC;CACT;AAED,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAC/C,eAAO,MAAM,gBAAgB,yBAAyB,CAAC;AACvD,6EAA6E;AAC7E,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAKnD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,mBAAmB,UAAQ,GAAG,GAAG,CAiBrF;AAqCD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,aAAa,EAAE,EAAE,SAAS,GAAE,MAAmC,EAAE,MAAM,GAAE,MAAwB;IAShH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;YAe7C,IAAI;CA8CnB;AAoBD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,SAAgC,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7H;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBnB"}
|
package/dist/webhook.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { consoleLogger } from '@chatcops/core';
|
|
1
2
|
export const DEFAULT_WEBHOOK_TIMEOUT_MS = 5000;
|
|
2
3
|
export const SIGNATURE_HEADER = 'X-ChatCops-Signature';
|
|
3
4
|
/** Signatures older than this are rejected by `verifyWebhook` by default. */
|
|
@@ -66,7 +67,9 @@ function isPrivateHost(hostname) {
|
|
|
66
67
|
export class WebhookDispatcher {
|
|
67
68
|
configs;
|
|
68
69
|
timeoutMs;
|
|
69
|
-
|
|
70
|
+
logger;
|
|
71
|
+
constructor(configs, timeoutMs = DEFAULT_WEBHOOK_TIMEOUT_MS, logger = consoleLogger()) {
|
|
72
|
+
this.logger = logger;
|
|
70
73
|
for (const config of configs) {
|
|
71
74
|
assertSafeWebhookUrl(config.url, config.allowPrivateNetwork);
|
|
72
75
|
}
|
|
@@ -77,14 +80,11 @@ export class WebhookDispatcher {
|
|
|
77
80
|
const matching = this.configs.filter((c) => c.events.includes(event) || c.events.includes('*'));
|
|
78
81
|
if (matching.length === 0)
|
|
79
82
|
return;
|
|
80
|
-
const created = Date.now();
|
|
81
83
|
const envelope = {
|
|
82
84
|
id: `evt_${crypto.randomUUID()}`,
|
|
83
85
|
type: event,
|
|
84
|
-
created,
|
|
86
|
+
created: Date.now(),
|
|
85
87
|
data,
|
|
86
|
-
event,
|
|
87
|
-
timestamp: created,
|
|
88
88
|
};
|
|
89
89
|
const body = JSON.stringify(envelope);
|
|
90
90
|
await Promise.allSettled(matching.map((config) => this.send(config, envelope, body)));
|
|
@@ -126,7 +126,7 @@ export class WebhookDispatcher {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
// Never log the body or the secret; they can hold lead details.
|
|
129
|
-
|
|
129
|
+
this.logger.error('webhook_failed', `Webhook delivery failed: ${envelope.type} (${envelope.id}) to ${new URL(config.url).origin}: ${lastProblem}`, { webhookEvent: envelope.type, deliveryId: envelope.id });
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
function parseRetryAfter(value) {
|
package/dist/webhook.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"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"}
|