@cogenta/channels 0.1.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/dist/adapter.d.ts +111 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +2 -0
- package/dist/adapter.js.map +1 -0
- package/dist/approvals/commands.d.ts +28 -0
- package/dist/approvals/commands.d.ts.map +1 -0
- package/dist/approvals/commands.js +66 -0
- package/dist/approvals/commands.js.map +1 -0
- package/dist/approvals/dispatch.d.ts +22 -0
- package/dist/approvals/dispatch.d.ts.map +1 -0
- package/dist/approvals/dispatch.js +22 -0
- package/dist/approvals/dispatch.js.map +1 -0
- package/dist/approvals/message.d.ts +18 -0
- package/dist/approvals/message.d.ts.map +1 -0
- package/dist/approvals/message.js +40 -0
- package/dist/approvals/message.js.map +1 -0
- package/dist/approvals/signed-link.d.ts +19 -0
- package/dist/approvals/signed-link.d.ts.map +1 -0
- package/dist/approvals/signed-link.js +42 -0
- package/dist/approvals/signed-link.js.map +1 -0
- package/dist/approvals/store.d.ts +41 -0
- package/dist/approvals/store.d.ts.map +1 -0
- package/dist/approvals/store.js +41 -0
- package/dist/approvals/store.js.map +1 -0
- package/dist/approvals/token.d.ts +7 -0
- package/dist/approvals/token.d.ts.map +1 -0
- package/dist/approvals/token.js +40 -0
- package/dist/approvals/token.js.map +1 -0
- package/dist/formats/alert.d.ts +18 -0
- package/dist/formats/alert.d.ts.map +1 -0
- package/dist/formats/alert.js +49 -0
- package/dist/formats/alert.js.map +1 -0
- package/dist/formats/budget.d.ts +14 -0
- package/dist/formats/budget.d.ts.map +1 -0
- package/dist/formats/budget.js +13 -0
- package/dist/formats/budget.js.map +1 -0
- package/dist/formats/notification.d.ts +8 -0
- package/dist/formats/notification.d.ts.map +1 -0
- package/dist/formats/notification.js +26 -0
- package/dist/formats/notification.js.map +1 -0
- package/dist/formats/report.d.ts +18 -0
- package/dist/formats/report.d.ts.map +1 -0
- package/dist/formats/report.js +44 -0
- package/dist/formats/report.js.map +1 -0
- package/dist/inbound/authorize.d.ts +57 -0
- package/dist/inbound/authorize.d.ts.map +1 -0
- package/dist/inbound/authorize.js +32 -0
- package/dist/inbound/authorize.js.map +1 -0
- package/dist/inbound/router.d.ts +67 -0
- package/dist/inbound/router.d.ts.map +1 -0
- package/dist/inbound/router.js +69 -0
- package/dist/inbound/router.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/linking/codes.d.ts +6 -0
- package/dist/linking/codes.d.ts.map +1 -0
- package/dist/linking/codes.js +37 -0
- package/dist/linking/codes.js.map +1 -0
- package/dist/linking/store.d.ts +39 -0
- package/dist/linking/store.d.ts.map +1 -0
- package/dist/linking/store.js +77 -0
- package/dist/linking/store.js.map +1 -0
- package/dist/linking/tables.d.ts +14 -0
- package/dist/linking/tables.d.ts.map +1 -0
- package/dist/linking/tables.js +52 -0
- package/dist/linking/tables.js.map +1 -0
- package/dist/preferences/dispatcher.d.ts +37 -0
- package/dist/preferences/dispatcher.d.ts.map +1 -0
- package/dist/preferences/dispatcher.js +103 -0
- package/dist/preferences/dispatcher.js.map +1 -0
- package/dist/preferences/quiet-hours.d.ts +12 -0
- package/dist/preferences/quiet-hours.d.ts.map +1 -0
- package/dist/preferences/quiet-hours.js +22 -0
- package/dist/preferences/quiet-hours.js.map +1 -0
- package/dist/preferences/store.d.ts +8 -0
- package/dist/preferences/store.d.ts.map +1 -0
- package/dist/preferences/store.js +60 -0
- package/dist/preferences/store.js.map +1 -0
- package/dist/preferences/tables.d.ts +12 -0
- package/dist/preferences/tables.d.ts.map +1 -0
- package/dist/preferences/tables.js +55 -0
- package/dist/preferences/tables.js.map +1 -0
- package/dist/preferences/types.d.ts +37 -0
- package/dist/preferences/types.d.ts.map +1 -0
- package/dist/preferences/types.js +31 -0
- package/dist/preferences/types.js.map +1 -0
- package/dist/providers/discord/adapter.d.ts +38 -0
- package/dist/providers/discord/adapter.d.ts.map +1 -0
- package/dist/providers/discord/adapter.js +97 -0
- package/dist/providers/discord/adapter.js.map +1 -0
- package/dist/providers/discord/client.d.ts +67 -0
- package/dist/providers/discord/client.d.ts.map +1 -0
- package/dist/providers/discord/client.js +65 -0
- package/dist/providers/discord/client.js.map +1 -0
- package/dist/providers/discord/gateway.d.ts +55 -0
- package/dist/providers/discord/gateway.d.ts.map +1 -0
- package/dist/providers/discord/gateway.js +114 -0
- package/dist/providers/discord/gateway.js.map +1 -0
- package/dist/providers/discord/inbound.d.ts +22 -0
- package/dist/providers/discord/inbound.d.ts.map +1 -0
- package/dist/providers/discord/inbound.js +75 -0
- package/dist/providers/discord/inbound.js.map +1 -0
- package/dist/providers/discord/render.d.ts +9 -0
- package/dist/providers/discord/render.d.ts.map +1 -0
- package/dist/providers/discord/render.js +73 -0
- package/dist/providers/discord/render.js.map +1 -0
- package/dist/providers/email/adapter.d.ts +18 -0
- package/dist/providers/email/adapter.d.ts.map +1 -0
- package/dist/providers/email/adapter.js +41 -0
- package/dist/providers/email/adapter.js.map +1 -0
- package/dist/providers/email/file-transport.d.ts +14 -0
- package/dist/providers/email/file-transport.d.ts.map +1 -0
- package/dist/providers/email/file-transport.js +33 -0
- package/dist/providers/email/file-transport.js.map +1 -0
- package/dist/providers/email/render.d.ts +20 -0
- package/dist/providers/email/render.d.ts.map +1 -0
- package/dist/providers/email/render.js +89 -0
- package/dist/providers/email/render.js.map +1 -0
- package/dist/providers/email/transport.d.ts +25 -0
- package/dist/providers/email/transport.d.ts.map +1 -0
- package/dist/providers/email/transport.js +2 -0
- package/dist/providers/email/transport.js.map +1 -0
- package/dist/providers/slack/adapter.d.ts +35 -0
- package/dist/providers/slack/adapter.d.ts.map +1 -0
- package/dist/providers/slack/adapter.js +91 -0
- package/dist/providers/slack/adapter.js.map +1 -0
- package/dist/providers/slack/client.d.ts +45 -0
- package/dist/providers/slack/client.d.ts.map +1 -0
- package/dist/providers/slack/client.js +54 -0
- package/dist/providers/slack/client.js.map +1 -0
- package/dist/providers/slack/inbound.d.ts +23 -0
- package/dist/providers/slack/inbound.d.ts.map +1 -0
- package/dist/providers/slack/inbound.js +76 -0
- package/dist/providers/slack/inbound.js.map +1 -0
- package/dist/providers/slack/render.d.ts +8 -0
- package/dist/providers/slack/render.d.ts.map +1 -0
- package/dist/providers/slack/render.js +72 -0
- package/dist/providers/slack/render.js.map +1 -0
- package/dist/providers/slack/socket.d.ts +34 -0
- package/dist/providers/slack/socket.d.ts.map +1 -0
- package/dist/providers/slack/socket.js +70 -0
- package/dist/providers/slack/socket.js.map +1 -0
- package/dist/providers/telegram/adapter.d.ts +35 -0
- package/dist/providers/telegram/adapter.d.ts.map +1 -0
- package/dist/providers/telegram/adapter.js +109 -0
- package/dist/providers/telegram/adapter.js.map +1 -0
- package/dist/providers/telegram/client.d.ts +78 -0
- package/dist/providers/telegram/client.d.ts.map +1 -0
- package/dist/providers/telegram/client.js +53 -0
- package/dist/providers/telegram/client.js.map +1 -0
- package/dist/providers/telegram/inbound.d.ts +21 -0
- package/dist/providers/telegram/inbound.d.ts.map +1 -0
- package/dist/providers/telegram/inbound.js +72 -0
- package/dist/providers/telegram/inbound.js.map +1 -0
- package/dist/providers/telegram/render.d.ts +15 -0
- package/dist/providers/telegram/render.d.ts.map +1 -0
- package/dist/providers/telegram/render.js +87 -0
- package/dist/providers/telegram/render.js.map +1 -0
- package/dist/providers/webhook/adapter.d.ts +40 -0
- package/dist/providers/webhook/adapter.d.ts.map +1 -0
- package/dist/providers/webhook/adapter.js +71 -0
- package/dist/providers/webhook/adapter.js.map +1 -0
- package/dist/providers/webhook/render.d.ts +26 -0
- package/dist/providers/webhook/render.d.ts.map +1 -0
- package/dist/providers/webhook/render.js +41 -0
- package/dist/providers/webhook/render.js.map +1 -0
- package/dist/providers/webhook/signing.d.ts +59 -0
- package/dist/providers/webhook/signing.d.ts.map +1 -0
- package/dist/providers/webhook/signing.js +108 -0
- package/dist/providers/webhook/signing.js.map +1 -0
- package/dist/registry.d.ts +16 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +39 -0
- package/dist/registry.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
function requireNonEmpty(field, value) {
|
|
3
|
+
if (value.trim().length > 0)
|
|
4
|
+
return;
|
|
5
|
+
throw new CogentaError({
|
|
6
|
+
code: 'CHANNEL_MESSAGE_INVALID',
|
|
7
|
+
message: `An alert message's "${field}" cannot be empty.`,
|
|
8
|
+
hint: '"Titre, gravité, une phrase de contexte, l\'action attendue, un lien vers l\'admin" are all required — fill in every field before dispatching.',
|
|
9
|
+
details: { field },
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function requireUrl(field, value) {
|
|
13
|
+
try {
|
|
14
|
+
const parsed = new URL(value);
|
|
15
|
+
void parsed;
|
|
16
|
+
}
|
|
17
|
+
catch (cause) {
|
|
18
|
+
throw new CogentaError({
|
|
19
|
+
code: 'CHANNEL_MESSAGE_INVALID',
|
|
20
|
+
message: `An alert message's "${field}" is not a valid URL: "${value}".`,
|
|
21
|
+
hint: "Pass an absolute URL, e.g. the entry's real admin edit link.",
|
|
22
|
+
details: { field, value },
|
|
23
|
+
cause,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* "Alerte — quelque chose demande une action. Titre, gravité, une phrase de
|
|
29
|
+
* contexte, l'action attendue, un lien vers l'admin." The one required
|
|
30
|
+
* constructor for every alert this package (or an agent) dispatches — never
|
|
31
|
+
* hand-assemble the discriminated union literal, so this validation cannot
|
|
32
|
+
* be skipped by a new call site.
|
|
33
|
+
*/
|
|
34
|
+
export function buildAlert(input) {
|
|
35
|
+
requireNonEmpty('title', input.title);
|
|
36
|
+
requireNonEmpty('context', input.context);
|
|
37
|
+
requireNonEmpty('expectedAction', input.expectedAction);
|
|
38
|
+
requireUrl('adminUrl', input.adminUrl);
|
|
39
|
+
return {
|
|
40
|
+
level: 'alert',
|
|
41
|
+
title: input.title,
|
|
42
|
+
severity: input.severity,
|
|
43
|
+
context: input.context,
|
|
44
|
+
expectedAction: input.expectedAction,
|
|
45
|
+
adminUrl: input.adminUrl,
|
|
46
|
+
...(input.actions === undefined ? {} : { actions: input.actions }),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=alert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alert.js","sourceRoot":"","sources":["../../src/formats/alert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAY5C,SAAS,eAAe,CAAC,KAAa,EAAE,KAAa;IACnD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QAAE,OAAM;IACnC,MAAM,IAAI,YAAY,CAAC;QACrB,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,uBAAuB,KAAK,oBAAoB;QACzD,IAAI,EAAE,gJAAgJ;QACtJ,OAAO,EAAE,EAAE,KAAK,EAAE;KACnB,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAAa,EAAE,KAAa;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;QAC7B,KAAK,MAAM,CAAA;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,uBAAuB,KAAK,0BAA0B,KAAK,IAAI;YACxE,IAAI,EAAE,8DAA8D;YACpE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;YACzB,KAAK;SACN,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IACrC,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IACzC,eAAe,CAAC,gBAAgB,EAAE,KAAK,CAAC,cAAc,CAAC,CAAA;IACvD,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;IAEtC,OAAO;QACL,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;KACnE,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Un message qui ne rentre pas dans un écran de téléphone est un message
|
|
3
|
+
* qui ne sera pas lu." An abstract, channel-agnostic screen budget — not
|
|
4
|
+
* Telegram's real 4096-character API limit (that's a *harder*, later,
|
|
5
|
+
* channel-specific ceiling enforced in `providers/telegram/render.ts`; this
|
|
6
|
+
* one is the point past which `## Formats de message`'s own rule says the
|
|
7
|
+
* detail belongs in the admin, not in the message).
|
|
8
|
+
*/
|
|
9
|
+
export declare const REPORT_SCREEN_BUDGET_CHARS = 480;
|
|
10
|
+
export declare function reportBodyLength(sections: readonly {
|
|
11
|
+
readonly heading?: string;
|
|
12
|
+
readonly body: string;
|
|
13
|
+
}[]): number;
|
|
14
|
+
//# sourceMappingURL=budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/formats/budget.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,MAAM,CAAA;AAE7C,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GACxE,MAAM,CAKR"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Un message qui ne rentre pas dans un écran de téléphone est un message
|
|
3
|
+
* qui ne sera pas lu." An abstract, channel-agnostic screen budget — not
|
|
4
|
+
* Telegram's real 4096-character API limit (that's a *harder*, later,
|
|
5
|
+
* channel-specific ceiling enforced in `providers/telegram/render.ts`; this
|
|
6
|
+
* one is the point past which `## Formats de message`'s own rule says the
|
|
7
|
+
* detail belongs in the admin, not in the message).
|
|
8
|
+
*/
|
|
9
|
+
export const REPORT_SCREEN_BUDGET_CHARS = 480;
|
|
10
|
+
export function reportBodyLength(sections) {
|
|
11
|
+
return sections.reduce((total, section) => total + (section.heading?.length ?? 0) + section.body.length, 0);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/formats/budget.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAA;AAE7C,MAAM,UAAU,gBAAgB,CAC9B,QAAyE;IAEzE,OAAO,QAAQ,CAAC,MAAM,CACpB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAChF,CAAC,CACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NotificationChannelMessage } from '../adapter.js';
|
|
2
|
+
/**
|
|
3
|
+
* "Notification — information sans action. Une ligne." The type already
|
|
4
|
+
* has nowhere to put a title or an action; this constructor is what refuses
|
|
5
|
+
* text that isn't actually one line, which the type alone cannot enforce.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildNotification(text: string): NotificationChannelMessage;
|
|
8
|
+
//# sourceMappingURL=notification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/formats/notification.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAA;AAE/D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,0BAA0B,CAmB1E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* "Notification — information sans action. Une ligne." The type already
|
|
4
|
+
* has nowhere to put a title or an action; this constructor is what refuses
|
|
5
|
+
* text that isn't actually one line, which the type alone cannot enforce.
|
|
6
|
+
*/
|
|
7
|
+
export function buildNotification(text) {
|
|
8
|
+
const trimmed = text.trim();
|
|
9
|
+
if (trimmed.length === 0) {
|
|
10
|
+
throw new CogentaError({
|
|
11
|
+
code: 'CHANNEL_MESSAGE_INVALID',
|
|
12
|
+
message: 'A notification message cannot be empty.',
|
|
13
|
+
hint: 'Pass a single line of real information, or send nothing at all.',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
if (trimmed.includes('\n')) {
|
|
17
|
+
throw new CogentaError({
|
|
18
|
+
code: 'CHANNEL_MESSAGE_INVALID',
|
|
19
|
+
message: 'A notification message must be a single line.',
|
|
20
|
+
hint: '"Une ligne" is the whole point of this level — split multi-line detail into a Report instead, or trim it to one sentence.',
|
|
21
|
+
details: { lineCount: trimmed.split('\n').length },
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return { level: 'notification', text: trimmed };
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=notification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification.js","sourceRoot":"","sources":["../../src/formats/notification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAG5C;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,yCAAyC;YAClD,IAAI,EAAE,iEAAiE;SACxE,CAAC,CAAA;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,+CAA+C;YACxD,IAAI,EAAE,2HAA2H;YACjI,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE;SACnD,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;AACjD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ChannelKeyFigure, ChannelMessageSection, ReportChannelMessage } from '../adapter.js';
|
|
2
|
+
export interface BuildReportInput {
|
|
3
|
+
readonly title: string;
|
|
4
|
+
readonly keyFigures: readonly ChannelKeyFigure[];
|
|
5
|
+
readonly sections: readonly ChannelMessageSection[];
|
|
6
|
+
readonly moreUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* "Rapport — synthèse périodique. Structure fixe, chiffres clés en tête,
|
|
10
|
+
* détail ensuite, jamais plus d'un écran sans repli." A report with no key
|
|
11
|
+
* figure isn't a synthesis, it's a dump; a report over the screen budget
|
|
12
|
+
* with nowhere to send the reader for detail is exactly the failure mode
|
|
13
|
+
* the lot's own words warn against ("un message qui ne rentre pas dans un
|
|
14
|
+
* écran de téléphone est un message qui ne sera pas lu") — both are refused
|
|
15
|
+
* here rather than left to whichever channel adapter happens to render it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildReport(input: BuildReportInput): ReportChannelMessage;
|
|
18
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/formats/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAGlG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAChD,QAAQ,CAAC,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAA;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,oBAAoB,CAgCzE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
import { REPORT_SCREEN_BUDGET_CHARS, reportBodyLength } from './budget.js';
|
|
3
|
+
/**
|
|
4
|
+
* "Rapport — synthèse périodique. Structure fixe, chiffres clés en tête,
|
|
5
|
+
* détail ensuite, jamais plus d'un écran sans repli." A report with no key
|
|
6
|
+
* figure isn't a synthesis, it's a dump; a report over the screen budget
|
|
7
|
+
* with nowhere to send the reader for detail is exactly the failure mode
|
|
8
|
+
* the lot's own words warn against ("un message qui ne rentre pas dans un
|
|
9
|
+
* écran de téléphone est un message qui ne sera pas lu") — both are refused
|
|
10
|
+
* here rather than left to whichever channel adapter happens to render it.
|
|
11
|
+
*/
|
|
12
|
+
export function buildReport(input) {
|
|
13
|
+
if (input.title.trim().length === 0) {
|
|
14
|
+
throw new CogentaError({
|
|
15
|
+
code: 'CHANNEL_MESSAGE_INVALID',
|
|
16
|
+
message: 'A report message must have a non-empty title.',
|
|
17
|
+
hint: 'Give the report a real title before dispatching it.',
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
if (input.keyFigures.length === 0) {
|
|
21
|
+
throw new CogentaError({
|
|
22
|
+
code: 'CHANNEL_MESSAGE_INVALID',
|
|
23
|
+
message: 'A report message must carry at least one key figure.',
|
|
24
|
+
hint: '"Chiffres clés en tête" is not optional — summarise the period with at least one number before the detail sections.',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const bodyLength = reportBodyLength(input.sections);
|
|
28
|
+
if (bodyLength > REPORT_SCREEN_BUDGET_CHARS && input.moreUrl === undefined) {
|
|
29
|
+
throw new CogentaError({
|
|
30
|
+
code: 'CHANNEL_MESSAGE_INVALID',
|
|
31
|
+
message: `This report's detail is ${bodyLength} characters, over the ${REPORT_SCREEN_BUDGET_CHARS}-character screen budget, with no "moreUrl" fallback.`,
|
|
32
|
+
hint: 'Either shorten the sections, or pass moreUrl pointing at the full detail in the admin — "jamais plus d\'un écran sans repli".',
|
|
33
|
+
details: { bodyLength, budget: REPORT_SCREEN_BUDGET_CHARS },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
level: 'report',
|
|
38
|
+
title: input.title,
|
|
39
|
+
keyFigures: input.keyFigures,
|
|
40
|
+
sections: input.sections,
|
|
41
|
+
...(input.moreUrl === undefined ? {} : { moreUrl: input.moreUrl }),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/formats/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAS1E;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,+CAA+C;YACxD,IAAI,EAAE,qDAAqD;SAC5D,CAAC,CAAA;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,sDAAsD;YAC/D,IAAI,EAAE,qHAAqH;SAC5H,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IACnD,IAAI,UAAU,GAAG,0BAA0B,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC3E,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,2BAA2B,UAAU,yBAAyB,0BAA0B,uDAAuD;YACxJ,IAAI,EAAE,+HAA+H;YACrI,OAAO,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,0BAA0B,EAAE;SAC5D,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,QAAQ;QACf,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;KACnE,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ChannelIdentity } from '../adapter.js';
|
|
2
|
+
/**
|
|
3
|
+
* "Une identité de canal non liée à un compte est ignorée, sans réponse —
|
|
4
|
+
* répondre confirmerait l'existence du bot à un inconnu." An unlinked
|
|
5
|
+
* identity is a fundamentally different posture than a linked-but-forbidden
|
|
6
|
+
* one: the caller must be able to do nothing at all without effort, so
|
|
7
|
+
* `shouldReply` is `false` here and `true` below — a channel adapter that
|
|
8
|
+
* simply checks this flag before sending anything gets the security
|
|
9
|
+
* property for free, instead of having to remember "unlinked = silent" as
|
|
10
|
+
* a rule to not forget.
|
|
11
|
+
*/
|
|
12
|
+
export interface UnlinkedResult {
|
|
13
|
+
readonly ok: false;
|
|
14
|
+
readonly reason: 'unlinked';
|
|
15
|
+
readonly shouldReply: false;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* "Un utilisateur sans `content.publish` ne peut pas approuver une
|
|
19
|
+
* publication depuis Telegram, même s'il voit le message." A linked user
|
|
20
|
+
* who lacks the required role(s) is refused the action but is a known
|
|
21
|
+
* person — they may be told so.
|
|
22
|
+
*/
|
|
23
|
+
export interface ForbiddenResult {
|
|
24
|
+
readonly ok: false;
|
|
25
|
+
readonly reason: 'forbidden';
|
|
26
|
+
readonly shouldReply: true;
|
|
27
|
+
readonly userId: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The only shape that carries a `userId` a command may act as. It is
|
|
31
|
+
* always the identified human's real id — never the agent's, never
|
|
32
|
+
* anything read off the inbound payload itself, which an attacker fully
|
|
33
|
+
* controls.
|
|
34
|
+
*/
|
|
35
|
+
export interface AuthorizedResult {
|
|
36
|
+
readonly ok: true;
|
|
37
|
+
readonly userId: string;
|
|
38
|
+
}
|
|
39
|
+
export type AuthorizationResult = UnlinkedResult | ForbiddenResult | AuthorizedResult;
|
|
40
|
+
/**
|
|
41
|
+
* "Une commande entrante s'exécute avec les permissions de l'humain
|
|
42
|
+
* identifié, jamais avec celles de l'agent." — the one function every
|
|
43
|
+
* inbound command handler must pass through before doing anything. It
|
|
44
|
+
* derives the acting user exclusively from `identity.linkedUserId` (set
|
|
45
|
+
* only by the real, verified linking flow, L6 task 2) and from real roles
|
|
46
|
+
* fetched for that id — never from `identity.channelUserId` or any other
|
|
47
|
+
* field an inbound message controls. Bypassing this check requires a
|
|
48
|
+
* caller to deliberately not call it; there is no path through it that
|
|
49
|
+
* hands out a permission the identified user does not really hold.
|
|
50
|
+
*
|
|
51
|
+
* `requiredRoles` mirrors contract A's own open role-name-array convention
|
|
52
|
+
* (`CollectionDefinition.permissions`, `@cogenta/api`'s `PermissionLayer`)
|
|
53
|
+
* rather than inventing a parallel "permission string" system for
|
|
54
|
+
* channels — an empty list means "any linked user may run this command".
|
|
55
|
+
*/
|
|
56
|
+
export declare function authorizeInboundCommand(identity: ChannelIdentity, requiredRoles: readonly string[], getUserRoles: (userId: string) => Promise<readonly string[]>): Promise<AuthorizationResult>;
|
|
57
|
+
//# sourceMappingURL=authorize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/inbound/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAA;IAClB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAA;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAA;IAClB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,eAAe,GAAG,gBAAgB,CAAA;AAErF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,GAC3D,OAAO,CAAC,mBAAmB,CAAC,CAgB9B"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Une commande entrante s'exécute avec les permissions de l'humain
|
|
3
|
+
* identifié, jamais avec celles de l'agent." — the one function every
|
|
4
|
+
* inbound command handler must pass through before doing anything. It
|
|
5
|
+
* derives the acting user exclusively from `identity.linkedUserId` (set
|
|
6
|
+
* only by the real, verified linking flow, L6 task 2) and from real roles
|
|
7
|
+
* fetched for that id — never from `identity.channelUserId` or any other
|
|
8
|
+
* field an inbound message controls. Bypassing this check requires a
|
|
9
|
+
* caller to deliberately not call it; there is no path through it that
|
|
10
|
+
* hands out a permission the identified user does not really hold.
|
|
11
|
+
*
|
|
12
|
+
* `requiredRoles` mirrors contract A's own open role-name-array convention
|
|
13
|
+
* (`CollectionDefinition.permissions`, `@cogenta/api`'s `PermissionLayer`)
|
|
14
|
+
* rather than inventing a parallel "permission string" system for
|
|
15
|
+
* channels — an empty list means "any linked user may run this command".
|
|
16
|
+
*/
|
|
17
|
+
export async function authorizeInboundCommand(identity, requiredRoles, getUserRoles) {
|
|
18
|
+
const userId = identity.linkedUserId;
|
|
19
|
+
if (userId === null) {
|
|
20
|
+
return { ok: false, reason: 'unlinked', shouldReply: false };
|
|
21
|
+
}
|
|
22
|
+
if (requiredRoles.length === 0) {
|
|
23
|
+
return { ok: true, userId };
|
|
24
|
+
}
|
|
25
|
+
const heldRoles = new Set(await getUserRoles(userId));
|
|
26
|
+
for (const role of requiredRoles) {
|
|
27
|
+
if (heldRoles.has(role))
|
|
28
|
+
return { ok: true, userId };
|
|
29
|
+
}
|
|
30
|
+
return { ok: false, reason: 'forbidden', shouldReply: true, userId };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=authorize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/inbound/authorize.ts"],"names":[],"mappings":"AA4CA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,QAAyB,EACzB,aAAgC,EAChC,YAA4D;IAE5D,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAA;IACpC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;IAC9D,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IAC7B,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CAAA;IACrD,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IACtD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACtE,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ChannelIdentity } from '../adapter.js';
|
|
2
|
+
/**
|
|
3
|
+
* A structured inbound command, never free text handed to an agent —
|
|
4
|
+
* "conversation libre avec un agent depuis le canal" is explicitly hors
|
|
5
|
+
* périmètre (`## Hors périmètre`). `/approve 3f2c` parses to
|
|
6
|
+
* `{name: 'approve', args: ['3f2c']}`.
|
|
7
|
+
*/
|
|
8
|
+
export interface ParsedCommand {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly args: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
/** Whitespace-separated; a leading `/` is optional and stripped if present. */
|
|
13
|
+
export declare function parseCommand(text: string): ParsedCommand | null;
|
|
14
|
+
export interface CommandHandlerInput {
|
|
15
|
+
readonly args: readonly string[];
|
|
16
|
+
/** The identified human this command runs as — never the agent's identity. */
|
|
17
|
+
readonly userId: string;
|
|
18
|
+
readonly identity: ChannelIdentity;
|
|
19
|
+
}
|
|
20
|
+
export type CommandHandler = (input: CommandHandlerInput) => Promise<void> | void;
|
|
21
|
+
export interface RegisteredCommand {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
/** Open role-name list, same convention as `CollectionDefinition.permissions` — empty means "any linked user". */
|
|
24
|
+
readonly requiredRoles: readonly string[];
|
|
25
|
+
readonly handler: CommandHandler;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* What `route()` did with an inbound command, so a channel adapter knows
|
|
29
|
+
* exactly whether — and what — to reply. `shouldReply: false` on an
|
|
30
|
+
* unlinked identity is the one case a caller must be able to implement by
|
|
31
|
+
* doing nothing; every other case is safe to surface to the sender.
|
|
32
|
+
*/
|
|
33
|
+
export type RouteResult = {
|
|
34
|
+
readonly kind: 'unlinked';
|
|
35
|
+
readonly shouldReply: false;
|
|
36
|
+
} | {
|
|
37
|
+
readonly kind: 'forbidden';
|
|
38
|
+
readonly shouldReply: true;
|
|
39
|
+
readonly userId: string;
|
|
40
|
+
} | {
|
|
41
|
+
readonly kind: 'unrecognized';
|
|
42
|
+
readonly shouldReply: true;
|
|
43
|
+
readonly commandName: string;
|
|
44
|
+
} | {
|
|
45
|
+
readonly kind: 'invalid';
|
|
46
|
+
readonly shouldReply: false;
|
|
47
|
+
} | {
|
|
48
|
+
readonly kind: 'handled';
|
|
49
|
+
readonly shouldReply: false;
|
|
50
|
+
readonly userId: string;
|
|
51
|
+
};
|
|
52
|
+
export interface CommandRouter {
|
|
53
|
+
register(command: RegisteredCommand): void;
|
|
54
|
+
route(text: string, identity: ChannelIdentity): Promise<RouteResult>;
|
|
55
|
+
}
|
|
56
|
+
export interface CommandRouterOptions {
|
|
57
|
+
readonly getUserRoles: (userId: string) => Promise<readonly string[]>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The routing mechanism task 3 exists to build: parse → look up → the
|
|
61
|
+
* security gate (`authorizeInboundCommand`) → invoke, with no path from a
|
|
62
|
+
* raw inbound string to a handler call that skips authorization. The full
|
|
63
|
+
* command vocabulary (an approval queue's `/approve`, `/deny`, ...) is a
|
|
64
|
+
* later task's job — this is the mechanism they will register into.
|
|
65
|
+
*/
|
|
66
|
+
export declare function createCommandRouter(options: CommandRouterOptions): CommandRouter;
|
|
67
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/inbound/router.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CACjC;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAQ/D;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;CACnC;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAEjF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,kHAAkH;IAClH,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAA;IACzC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;CACjC;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnF;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC3F;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAC1C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CACrE;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAA;CACtE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAsDhF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
import { authorizeInboundCommand } from './authorize.js';
|
|
3
|
+
/** Whitespace-separated; a leading `/` is optional and stripped if present. */
|
|
4
|
+
export function parseCommand(text) {
|
|
5
|
+
const trimmed = text.trim();
|
|
6
|
+
if (trimmed.length === 0)
|
|
7
|
+
return null;
|
|
8
|
+
const [rawName, ...args] = trimmed.split(/\s+/);
|
|
9
|
+
if (rawName === undefined)
|
|
10
|
+
return null;
|
|
11
|
+
const name = rawName.startsWith('/') ? rawName.slice(1) : rawName;
|
|
12
|
+
if (name.length === 0)
|
|
13
|
+
return null;
|
|
14
|
+
return { name, args };
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The routing mechanism task 3 exists to build: parse → look up → the
|
|
18
|
+
* security gate (`authorizeInboundCommand`) → invoke, with no path from a
|
|
19
|
+
* raw inbound string to a handler call that skips authorization. The full
|
|
20
|
+
* command vocabulary (an approval queue's `/approve`, `/deny`, ...) is a
|
|
21
|
+
* later task's job — this is the mechanism they will register into.
|
|
22
|
+
*/
|
|
23
|
+
export function createCommandRouter(options) {
|
|
24
|
+
const commands = new Map();
|
|
25
|
+
return {
|
|
26
|
+
register(command) {
|
|
27
|
+
if (commands.has(command.name)) {
|
|
28
|
+
throw new CogentaError({
|
|
29
|
+
code: 'CHANNEL_COMMAND_DUPLICATE',
|
|
30
|
+
message: `A command named "${command.name}" is already registered.`,
|
|
31
|
+
hint: 'Command names must be unique across everything registered on this router.',
|
|
32
|
+
details: { name: command.name },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
commands.set(command.name, command);
|
|
36
|
+
},
|
|
37
|
+
async route(text, identity) {
|
|
38
|
+
// Checked before anything else, including whether the command even
|
|
39
|
+
// exists: an unlinked identity gets silence no matter what it sends,
|
|
40
|
+
// never even an "unknown command" reply — any reply at all would
|
|
41
|
+
// confirm the bot's existence to a stranger.
|
|
42
|
+
if (identity.linkedUserId === null) {
|
|
43
|
+
return { kind: 'unlinked', shouldReply: false };
|
|
44
|
+
}
|
|
45
|
+
const parsed = parseCommand(text);
|
|
46
|
+
if (parsed === null)
|
|
47
|
+
return { kind: 'invalid', shouldReply: false };
|
|
48
|
+
const command = commands.get(parsed.name);
|
|
49
|
+
if (command === undefined) {
|
|
50
|
+
return { kind: 'unrecognized', shouldReply: true, commandName: parsed.name };
|
|
51
|
+
}
|
|
52
|
+
const decision = await authorizeInboundCommand(identity, command.requiredRoles, options.getUserRoles);
|
|
53
|
+
if (!decision.ok) {
|
|
54
|
+
// decision.reason is always 'forbidden' here — the unlinked case was
|
|
55
|
+
// already returned above, before authorizeInboundCommand was even
|
|
56
|
+
// called — but the type doesn't know that, so narrow explicitly
|
|
57
|
+
// rather than asserting it.
|
|
58
|
+
if (decision.reason === 'unlinked')
|
|
59
|
+
return { kind: 'unlinked', shouldReply: false };
|
|
60
|
+
return { kind: 'forbidden', shouldReply: true, userId: decision.userId };
|
|
61
|
+
}
|
|
62
|
+
// The handler receives exactly the identified human's userId — never
|
|
63
|
+
// `identity.channelUserId`, never anything parsed from `text`.
|
|
64
|
+
await command.handler({ args: parsed.args, userId: decision.userId, identity });
|
|
65
|
+
return { kind: 'handled', shouldReply: false, userId: decision.userId };
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/inbound/router.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export type { AlertChannelMessage, ChannelAction, ChannelAdapter, ChannelIdentity, ChannelKeyFigure, ChannelMessage, ChannelMessageSection, ChannelSeverity, ChannelTarget, InboundCommand, InboundHandler, MessageId, NotificationChannelMessage, ReportChannelMessage, } from './adapter.js';
|
|
2
|
+
export type { ApprovalCommandsOptions } from './approvals/commands.js';
|
|
3
|
+
export { createApprovalCommands } from './approvals/commands.js';
|
|
4
|
+
export type { DispatchApprovalOptions } from './approvals/dispatch.js';
|
|
5
|
+
export { dispatchApproval } from './approvals/dispatch.js';
|
|
6
|
+
export type { RenderApprovalMessageOptions } from './approvals/message.js';
|
|
7
|
+
export { renderApprovalMessage } from './approvals/message.js';
|
|
8
|
+
export { buildSignedApprovalLink, signApprovalLink, verifyApprovalLinkSignature, } from './approvals/signed-link.js';
|
|
9
|
+
export type { ApprovalTokenOutcome, ApprovalTokenStore, ApprovalTokenStoreOptions, GeneratedApprovalToken, } from './approvals/store.js';
|
|
10
|
+
export { createApprovalTokenStore } from './approvals/store.js';
|
|
11
|
+
export { APPROVAL_TOKEN_TTL_MS, generateApprovalToken, hashApprovalToken, normalizeApprovalToken, } from './approvals/token.js';
|
|
12
|
+
export type { BuildAlertInput } from './formats/alert.js';
|
|
13
|
+
export { buildAlert } from './formats/alert.js';
|
|
14
|
+
export { REPORT_SCREEN_BUDGET_CHARS } from './formats/budget.js';
|
|
15
|
+
export { buildNotification } from './formats/notification.js';
|
|
16
|
+
export type { BuildReportInput } from './formats/report.js';
|
|
17
|
+
export { buildReport } from './formats/report.js';
|
|
18
|
+
export type { AuthorizationResult, AuthorizedResult, ForbiddenResult, UnlinkedResult, } from './inbound/authorize.js';
|
|
19
|
+
export { authorizeInboundCommand } from './inbound/authorize.js';
|
|
20
|
+
export type { CommandHandler, CommandHandlerInput, CommandRouter, CommandRouterOptions, ParsedCommand, RegisteredCommand, RouteResult, } from './inbound/router.js';
|
|
21
|
+
export { createCommandRouter, parseCommand } from './inbound/router.js';
|
|
22
|
+
export { generateLinkCode, hashLinkCode, normalizeCode } from './linking/codes.js';
|
|
23
|
+
export type { ChannelLinkStore, GeneratedLinkCode, LinkedChannel } from './linking/store.js';
|
|
24
|
+
export { createChannelLinkStore } from './linking/store.js';
|
|
25
|
+
export { ensureChannelTables, LINKING_TABLES } from './linking/tables.js';
|
|
26
|
+
export type { CreateNotificationDispatcherOptions, NotificationDispatcher, NotifyInput, NotifyOutcome, } from './preferences/dispatcher.js';
|
|
27
|
+
export { createNotificationDispatcher } from './preferences/dispatcher.js';
|
|
28
|
+
export { isWithinQuietHours, minuteOfDayUtc } from './preferences/quiet-hours.js';
|
|
29
|
+
export type { PreferenceStore } from './preferences/store.js';
|
|
30
|
+
export { createPreferenceStore } from './preferences/store.js';
|
|
31
|
+
export { ensurePreferenceTables, PREFERENCE_TABLES } from './preferences/tables.js';
|
|
32
|
+
export type { ChannelEventType, ChannelPreferences, GroupingMode, QuietHours, } from './preferences/types.js';
|
|
33
|
+
export { CHANNEL_EVENT_TYPES, DEFAULT_CHANNEL_PREFERENCES, SEVERITY_RANK, } from './preferences/types.js';
|
|
34
|
+
export type { DiscordAdapter, DiscordAdapterOptions, DiscordLinkProof, } from './providers/discord/adapter.js';
|
|
35
|
+
export { createDiscordAdapter } from './providers/discord/adapter.js';
|
|
36
|
+
export type { DiscordActionRow, DiscordButtonComponent, DiscordClient, DiscordClientConfig, DiscordEmbed, DiscordEmbedField, DiscordMessageResult, DiscordSendMessageParams, DiscordUpdateMessageParams, } from './providers/discord/client.js';
|
|
37
|
+
export { createDiscordClient } from './providers/discord/client.js';
|
|
38
|
+
export type { DiscordDispatchEvent, DiscordGatewayClient, DiscordGatewayClientConfig, DiscordGatewayPayload, } from './providers/discord/gateway.js';
|
|
39
|
+
export { createDiscordGatewayClient } from './providers/discord/gateway.js';
|
|
40
|
+
export type { DiscordInboundDeps } from './providers/discord/inbound.js';
|
|
41
|
+
export { createDiscordInboundHandler } from './providers/discord/inbound.js';
|
|
42
|
+
export type { RenderedDiscordMessage } from './providers/discord/render.js';
|
|
43
|
+
export { renderDiscordMessage } from './providers/discord/render.js';
|
|
44
|
+
export type { EmailAdapterOptions } from './providers/email/adapter.js';
|
|
45
|
+
export { createEmailAdapter } from './providers/email/adapter.js';
|
|
46
|
+
export type { FileEmailTransportOptions } from './providers/email/file-transport.js';
|
|
47
|
+
export { createFileEmailTransport } from './providers/email/file-transport.js';
|
|
48
|
+
export type { EmailActionLinkOptions, RenderedEmailMessage } from './providers/email/render.js';
|
|
49
|
+
export { renderEmailMessage } from './providers/email/render.js';
|
|
50
|
+
export type { EmailTransport, OutgoingEmail, SentEmail } from './providers/email/transport.js';
|
|
51
|
+
export type { SlackAdapter, SlackAdapterOptions, SlackLinkProof, } from './providers/slack/adapter.js';
|
|
52
|
+
export { createSlackAdapter } from './providers/slack/adapter.js';
|
|
53
|
+
export type { SlackBlock, SlackClient, SlackClientConfig, SlackMessageResult, SlackPostMessageParams, SlackUpdateMessageParams, } from './providers/slack/client.js';
|
|
54
|
+
export { createSlackClient } from './providers/slack/client.js';
|
|
55
|
+
export type { SlackInboundDeps } from './providers/slack/inbound.js';
|
|
56
|
+
export { createSlackInboundHandler } from './providers/slack/inbound.js';
|
|
57
|
+
export type { RenderedSlackMessage } from './providers/slack/render.js';
|
|
58
|
+
export { renderSlackMessage } from './providers/slack/render.js';
|
|
59
|
+
export type { SlackSocketClient, SlackSocketClientConfig, SlackSocketEnvelope, } from './providers/slack/socket.js';
|
|
60
|
+
export { createSlackSocketClient } from './providers/slack/socket.js';
|
|
61
|
+
export type { TelegramAdapter, TelegramAdapterOptions, TelegramLinkProof, } from './providers/telegram/adapter.js';
|
|
62
|
+
export { createTelegramAdapter } from './providers/telegram/adapter.js';
|
|
63
|
+
export type { TelegramCallbackQuery, TelegramClient, TelegramClientConfig, TelegramEditMessageParams, TelegramIncomingMessage, TelegramInlineButton, TelegramMessage, TelegramReplyMarkup, TelegramSendMessageParams, TelegramUpdate, TelegramUser, } from './providers/telegram/client.js';
|
|
64
|
+
export { createTelegramClient } from './providers/telegram/client.js';
|
|
65
|
+
export type { TelegramInboundDeps } from './providers/telegram/inbound.js';
|
|
66
|
+
export { createTelegramInboundHandler } from './providers/telegram/inbound.js';
|
|
67
|
+
export type { RenderedTelegramMessage } from './providers/telegram/render.js';
|
|
68
|
+
export { escapeMarkdownV2, renderTelegramMessage } from './providers/telegram/render.js';
|
|
69
|
+
export type { WebhookAdapterOptions, WebhookFetch } from './providers/webhook/adapter.js';
|
|
70
|
+
export { createWebhookAdapter } from './providers/webhook/adapter.js';
|
|
71
|
+
export type { WebhookActionLinkOptions, WebhookPayload } from './providers/webhook/render.js';
|
|
72
|
+
export { renderWebhookPayload } from './providers/webhook/render.js';
|
|
73
|
+
export type { SignedWebhookRequest, VerifyIncomingWebhookInput, WebhookVerificationResult, } from './providers/webhook/signing.js';
|
|
74
|
+
export { assertValidIncomingWebhook, signOutgoingWebhook, verifyIncomingWebhook, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, WebhookReplayGuard, } from './providers/webhook/signing.js';
|
|
75
|
+
export type { ChannelRegistry } from './registry.js';
|
|
76
|
+
export { createChannelRegistry } from './registry.js';
|
|
77
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export { createApprovalCommands } from './approvals/commands.js';
|
|
2
|
+
export { dispatchApproval } from './approvals/dispatch.js';
|
|
3
|
+
export { renderApprovalMessage } from './approvals/message.js';
|
|
4
|
+
export { buildSignedApprovalLink, signApprovalLink, verifyApprovalLinkSignature, } from './approvals/signed-link.js';
|
|
5
|
+
export { createApprovalTokenStore } from './approvals/store.js';
|
|
6
|
+
export { APPROVAL_TOKEN_TTL_MS, generateApprovalToken, hashApprovalToken, normalizeApprovalToken, } from './approvals/token.js';
|
|
7
|
+
export { buildAlert } from './formats/alert.js';
|
|
8
|
+
export { REPORT_SCREEN_BUDGET_CHARS } from './formats/budget.js';
|
|
9
|
+
export { buildNotification } from './formats/notification.js';
|
|
10
|
+
export { buildReport } from './formats/report.js';
|
|
11
|
+
export { authorizeInboundCommand } from './inbound/authorize.js';
|
|
12
|
+
export { createCommandRouter, parseCommand } from './inbound/router.js';
|
|
13
|
+
export { generateLinkCode, hashLinkCode, normalizeCode } from './linking/codes.js';
|
|
14
|
+
export { createChannelLinkStore } from './linking/store.js';
|
|
15
|
+
export { ensureChannelTables, LINKING_TABLES } from './linking/tables.js';
|
|
16
|
+
export { createNotificationDispatcher } from './preferences/dispatcher.js';
|
|
17
|
+
export { isWithinQuietHours, minuteOfDayUtc } from './preferences/quiet-hours.js';
|
|
18
|
+
export { createPreferenceStore } from './preferences/store.js';
|
|
19
|
+
export { ensurePreferenceTables, PREFERENCE_TABLES } from './preferences/tables.js';
|
|
20
|
+
export { CHANNEL_EVENT_TYPES, DEFAULT_CHANNEL_PREFERENCES, SEVERITY_RANK, } from './preferences/types.js';
|
|
21
|
+
export { createDiscordAdapter } from './providers/discord/adapter.js';
|
|
22
|
+
export { createDiscordClient } from './providers/discord/client.js';
|
|
23
|
+
export { createDiscordGatewayClient } from './providers/discord/gateway.js';
|
|
24
|
+
export { createDiscordInboundHandler } from './providers/discord/inbound.js';
|
|
25
|
+
export { renderDiscordMessage } from './providers/discord/render.js';
|
|
26
|
+
export { createEmailAdapter } from './providers/email/adapter.js';
|
|
27
|
+
export { createFileEmailTransport } from './providers/email/file-transport.js';
|
|
28
|
+
export { renderEmailMessage } from './providers/email/render.js';
|
|
29
|
+
export { createSlackAdapter } from './providers/slack/adapter.js';
|
|
30
|
+
export { createSlackClient } from './providers/slack/client.js';
|
|
31
|
+
export { createSlackInboundHandler } from './providers/slack/inbound.js';
|
|
32
|
+
export { renderSlackMessage } from './providers/slack/render.js';
|
|
33
|
+
export { createSlackSocketClient } from './providers/slack/socket.js';
|
|
34
|
+
export { createTelegramAdapter } from './providers/telegram/adapter.js';
|
|
35
|
+
export { createTelegramClient } from './providers/telegram/client.js';
|
|
36
|
+
export { createTelegramInboundHandler } from './providers/telegram/inbound.js';
|
|
37
|
+
export { escapeMarkdownV2, renderTelegramMessage } from './providers/telegram/render.js';
|
|
38
|
+
export { createWebhookAdapter } from './providers/webhook/adapter.js';
|
|
39
|
+
export { renderWebhookPayload } from './providers/webhook/render.js';
|
|
40
|
+
export { assertValidIncomingWebhook, signOutgoingWebhook, verifyIncomingWebhook, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, WebhookReplayGuard, } from './providers/webhook/signing.js';
|
|
41
|
+
export { createChannelRegistry } from './registry.js';
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function generateLinkCode(): string;
|
|
2
|
+
/** Stored hashed, exactly like a session token (`@cogenta/auth/sessions.ts`) — a leaked table hands out nothing usable. */
|
|
3
|
+
export declare function hashLinkCode(code: string): string;
|
|
4
|
+
/** Case-insensitive, whitespace-tolerant — a code typed by hand into a chat app should not fail on a stray space or lowercase letter. */
|
|
5
|
+
export declare function normalizeCode(code: string): string;
|
|
6
|
+
//# sourceMappingURL=codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codes.d.ts","sourceRoot":"","sources":["../../src/linking/codes.ts"],"names":[],"mappings":"AAsBA,wBAAgB,gBAAgB,IAAI,MAAM,CAQzC;AAED,2HAA2H;AAC3H,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,yIAAyI;AACzI,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD"}
|