@loomcycle/bridge-discord 0.1.0 → 0.3.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 +43 -2
- package/dist/api.d.ts +11 -0
- package/dist/api.js +5 -0
- package/dist/api.js.map +1 -1
- package/dist/bridge.js +21 -3
- package/dist/bridge.js.map +1 -1
- package/dist/cards.js.map +1 -1
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/events.d.ts +40 -0
- package/dist/events.js +80 -0
- package/dist/events.js.map +1 -0
- package/dist/groups.d.ts +31 -0
- package/dist/groups.js +83 -0
- package/dist/groups.js.map +1 -0
- package/dist/identity.d.ts +15 -1
- package/dist/identity.js +22 -4
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/interactions.d.ts +2 -1
- package/dist/interactions.js +6 -2
- package/dist/interactions.js.map +1 -1
- package/dist/port.d.ts +3 -0
- package/dist/port.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -54,6 +54,12 @@ Run loomcycle with authentication on and a persistent store. Then:
|
|
|
54
54
|
npx @loomcycle/bridge-discord
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
Or run the container image, `denngubsky/loomcycle-bridge-discord` (also `ghcr.io/denn-gubsky/loomcycle-bridge-discord`), tagged with the package version. It takes the same environment variables. Mount a volume at `/data` and set `BRIDGE_STORE=file:/data/discord.json` to keep each conversation's session across restarts:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
docker run --env-file discord-bridge.env -p 8080:8080 -v discord-bridge-data:/data denngubsky/loomcycle-bridge-discord:<version>
|
|
61
|
+
```
|
|
62
|
+
|
|
57
63
|
With `DISCORD_BRIDGE_REGISTER_COMMANDS=1` the bridge registers its four commands when it starts:
|
|
58
64
|
|
|
59
65
|
- **in each allowed server, as that server's commands.** They take effect at once and show only where the bot answers.
|
|
@@ -68,7 +74,7 @@ The shared settings, as every bridge reads them:
|
|
|
68
74
|
| Variable | Meaning | Default |
|
|
69
75
|
|---|---|---|
|
|
70
76
|
| `LOOMCYCLE_BASE_URL` | loomcycle's private URL | required |
|
|
71
|
-
| `LOOMCYCLE_TOKEN` | The bridge's `substrate:tenant` token | required |
|
|
77
|
+
| `LOOMCYCLE_TOKEN` | The bridge's `substrate:tenant` token | required, unless the bridge is a gate (below) |
|
|
72
78
|
| `BRIDGE_AGENT` | The loomcycle agent every conversation runs | required |
|
|
73
79
|
| `BRIDGE_TOKEN_TTL_SECONDS` | Lifetime of a user's token | `43200` |
|
|
74
80
|
| `BRIDGE_RATE_PER_MINUTE`, `BRIDGE_RATE_BURST` | Runs a user may start per minute, and the burst | `6`, `10` |
|
|
@@ -93,6 +99,41 @@ Discord's:
|
|
|
93
99
|
|
|
94
100
|
**The bridge is closed by default.** It refuses to start unless `DISCORD_BRIDGE_ALLOWED_GUILDS` or `DISCORD_BRIDGE_ALLOW_DMS=1` opens something: anyone on the internet can reach a Discord bot, and every message it answers runs on your model keys. `DISCORD_BRIDGE_ALLOW_DMS=1` means exactly that, so pair it with the rate limit and loomcycle's token budgets.
|
|
95
101
|
|
|
102
|
+
## As a loomcycle gate
|
|
103
|
+
|
|
104
|
+
Since 0.3 the bridge can be a loomcycle gate instead of holding a token: it signs who is talking with its own key, and loomcycle provisions the user and issues the token. A stolen bridge can then only speak for Discord users, never act as a tenant operator. Set `BRIDGE_GATE` and the bridge runs this way; without it, it runs with `LOOMCYCLE_TOKEN` as before.
|
|
105
|
+
|
|
106
|
+
1. Make a key pair. The private half goes to the bridge only:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
node -e 'const {privateKey,publicKey}=require("node:crypto").generateKeyPairSync("ed25519");
|
|
110
|
+
console.log("BRIDGE_GATE_KEY=" + JSON.stringify(privateKey.export({format:"jwk"})));
|
|
111
|
+
console.log("public_key: " + JSON.stringify(publicKey.export({format:"jwk"})))'
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
2. Register the gate in loomcycle, in the tenant the bridge used:
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
auth:
|
|
118
|
+
gates:
|
|
119
|
+
discord:
|
|
120
|
+
kind: external
|
|
121
|
+
public_key: { kty: OKP, crv: Ed25519, x: "<the public x>" }
|
|
122
|
+
issued_token: { ttl: 12h, agents: [chat], overrides: [interactive], rate: { per_minute: 6, burst: 10 } }
|
|
123
|
+
identity_map: { tenant: acme, provision: auto, legacy_subject_prefix: discord- }
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`legacy_subject_prefix: discord-` keeps the people and channels the bridge already served: each one's first message through the gate links the user the bridge made (`discord-<user id>`, a channel's `discord-conv-<hash>`), so their history, memory and documents stay theirs. Without it they would start again as new users `discord:<user id>`. New people are `discord:<user id>`, new channels `discord:conv:<hash>`, either way.
|
|
127
|
+
|
|
128
|
+
3. Reconfigure the bridge: set `BRIDGE_GATE=discord`, `BRIDGE_GATE_AUDIENCE` (loomcycle's `LOOMCYCLE_PUBLIC_URL`) and `BRIDGE_GATE_KEY`, and remove `LOOMCYCLE_TOKEN` and `BRIDGE_USER_ACCESS_MODE`, which a gate bridge refuses. Then retire the old operator token. The other `BRIDGE_GATE_*` settings are in `@loomcycle/bridge-core`'s README.
|
|
129
|
+
|
|
130
|
+
Do it in this order: the gate, with its prefix, must be in loomcycle's config before the bridge switches, or the first messages make new, empty users.
|
|
131
|
+
|
|
132
|
+
As a gate the bridge also tells loomcycle about groups and leavers.
|
|
133
|
+
|
|
134
|
+
- **Groups.** A channel is in the loomcycle group `discord:dc-guild-<server id>` of its server. A person (a DM) is in `discord:dc-guild-<server id>` for each server in `DISCORD_BRIDGE_TRUSTED_GUILDS` they are a member of, and `discord:dc-role-<role id>` for each role they hold there, which an operator can bind permissions to; it takes `trusted: true` on the gate and an `identity_map.groups` block. The bridge reads a person's membership with the bot token (Get Guild Member, which needs no privileged intent; the bot must be in the server), once per person per 10 minutes. When a lookup fails, or with more than 20 trusted servers, it asserts no groups for that person, so loomcycle never drops a group on a guess.
|
|
135
|
+
- **Leavers.** A person who removes the app is revoked in loomcycle: disabled at once, then removed by the gate's removal policy. Discord tells the bridge through Webhook Events: in the Developer Portal, on the **Webhooks** page, set the **Endpoint** to `https://<bridge-host>/discord/events`, turn **Events** on and select `APPLICATION_DEAUTHORIZED`. Discord checks the URL with a PING when you save it, so the bridge must already run as a gate. These events are signed like interactions and always verified. The bridge answers an event only once loomcycle has taken the revoke; if it has not, Discord gets a `503` and delivers the event again.
|
|
136
|
+
|
|
96
137
|
## Servers, channels and trust
|
|
97
138
|
|
|
98
139
|
- **A server channel runs as itself, never as one of its members.** It is its own loomcycle user (`discord-conv-<hash>`), with its own memory and history. A thread is its own conversation and shares its parent channel's memory.
|
|
@@ -119,7 +160,7 @@ Discord's:
|
|
|
119
160
|
|
|
120
161
|
- **Inbound:** every request's `X-Signature-Ed25519` is checked over the timestamp and the raw body with the application's public key, before the body is parsed. A timestamp more than five minutes off, and an interaction id already seen, are refused. A failed check is a bare `401`.
|
|
121
162
|
- **Bots are dropped,** the bot itself included, before anything reaches loomcycle.
|
|
122
|
-
- **Least privilege:** the bridge's own token never runs agents. A user's token is limited to one agent, every per-run override except `interactive` is locked, it is rate-limited, and it expires.
|
|
163
|
+
- **Least privilege:** the bridge's own token never runs agents; as a loomcycle gate (above) it holds no loomcycle token at all. A user's token is limited to one agent, every per-run override except `interactive` is locked, it is rate-limited, and it expires.
|
|
123
164
|
- **Credentials stay in memory.** Interaction tokens are never written to the conversation store, so `BRIDGE_STORE=file:` holds no credential; after a restart, replies use the bot token until the next command. The bot token is sent only to Discord's REST API, never to an interaction webhook. Logs carry ids, never a token, message text or agent output.
|
|
124
165
|
- **Output:** agent text can be steered by whoever writes in a channel, so nothing the bridge posts can ping anyone (`allowed_mentions` parses nothing, so `@everyone` and role mentions are inert), shows a link preview (`SUPPRESS_EMBEDS` on every message: Discord would fetch the link to build one, with no click, and hand its query string to whoever runs that server), or hides a link's target (a masked link `[label](url)` is rewritten as `label (<url>)`). Tool inputs and outputs are never sent.
|
|
125
166
|
|
package/dist/api.d.ts
CHANGED
|
@@ -17,6 +17,14 @@ export declare class DiscordApiError extends Error {
|
|
|
17
17
|
/** Discord's JSON error code (10062 "Unknown interaction", say), when sent. */
|
|
18
18
|
code?: number | undefined);
|
|
19
19
|
}
|
|
20
|
+
/** The parts of a guild member object the bridge reads; shape-checked at use. */
|
|
21
|
+
export interface GuildMember {
|
|
22
|
+
roles?: unknown;
|
|
23
|
+
user?: {
|
|
24
|
+
id?: string;
|
|
25
|
+
bot?: boolean;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
20
28
|
/** Discord asks bot clients to identify themselves this way. */
|
|
21
29
|
export declare const USER_AGENT = "DiscordBot (https://github.com/denn-gubsky/loomcycle, 0.1.0)";
|
|
22
30
|
export interface CommandSpec {
|
|
@@ -42,6 +50,9 @@ export declare class DiscordApi {
|
|
|
42
50
|
followUp(interactionToken: string, body: MessageBody): Promise<unknown>;
|
|
43
51
|
createMessage(channelId: string, body: MessageBody): Promise<unknown>;
|
|
44
52
|
typing(channelId: string): Promise<unknown>;
|
|
53
|
+
/** guildMember reads one member of a server (their roles), with the bot
|
|
54
|
+
* token. A person not in the server is a 404. */
|
|
55
|
+
guildMember(guildId: string, userId: string): Promise<GuildMember | undefined>;
|
|
45
56
|
/** putCommands replaces the application's commands: globally, or in one server. */
|
|
46
57
|
putCommands(commands: CommandSpec[], guildId?: string): Promise<unknown>;
|
|
47
58
|
private call;
|
package/dist/api.js
CHANGED
|
@@ -44,6 +44,11 @@ export class DiscordApi {
|
|
|
44
44
|
typing(channelId) {
|
|
45
45
|
return this.call("POST", `/channels/${channelId}/typing`, "POST channels/typing", undefined, true);
|
|
46
46
|
}
|
|
47
|
+
/** guildMember reads one member of a server (their roles), with the bot
|
|
48
|
+
* token. A person not in the server is a 404. */
|
|
49
|
+
guildMember(guildId, userId) {
|
|
50
|
+
return this.call("GET", `/guilds/${guildId}/members/${userId}`, "GET guilds/members", undefined, true);
|
|
51
|
+
}
|
|
47
52
|
/** putCommands replaces the application's commands: globally, or in one server. */
|
|
48
53
|
putCommands(commands, guildId) {
|
|
49
54
|
const path = guildId
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,4EAA4E;AAC5E,2EAA2E;AAC3E,6EAA6E;AAC7E,wEAAwE;AAexE,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAE7B;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/bridge.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// The Discord adapter on the shared core: interactions over HTTP, no Gateway.
|
|
2
2
|
import { consoleLogger, createBridge } from "@loomcycle/bridge-core";
|
|
3
3
|
import { DiscordApi } from "./api.js";
|
|
4
|
-
import { registerCommands } from "./commands.js";
|
|
4
|
+
import { HELP_TEXT, registerCommands } from "./commands.js";
|
|
5
|
+
import { EVENTS_PATH, eventsRoute } from "./events.js";
|
|
6
|
+
import { GroupLookup } from "./groups.js";
|
|
5
7
|
import { interactionRoute } from "./interactions.js";
|
|
6
8
|
import { DiscordPort } from "./port.js";
|
|
7
9
|
import { publicKeyFromHex } from "./verify.js";
|
|
@@ -19,15 +21,30 @@ export function createDiscordBridge(cfg, opts = {}) {
|
|
|
19
21
|
});
|
|
20
22
|
const port = new DiscordPort(api, log, { now });
|
|
21
23
|
const key = publicKeyFromHex(cfg.publicKey);
|
|
24
|
+
const fences = {
|
|
25
|
+
applicationId: cfg.applicationId,
|
|
26
|
+
allowedGuilds: cfg.allowedGuilds,
|
|
27
|
+
allowDms: cfg.allowDms,
|
|
28
|
+
trustedGuilds: cfg.trustedGuilds,
|
|
29
|
+
dev: cfg.dev,
|
|
30
|
+
...(cfg.gate ? { gate: cfg.gate.name } : {}),
|
|
31
|
+
};
|
|
32
|
+
const groups = cfg.gate ? new GroupLookup({ api, gate: cfg.gate.name, trustedGuilds: cfg.trustedGuilds, now }) : undefined;
|
|
22
33
|
const adapter = {
|
|
23
|
-
|
|
34
|
+
// `/ask prompt:/help` reaches the core as "/help": answer with the same
|
|
35
|
+
// list as the /help command, not the core's typed-command one.
|
|
36
|
+
platform: { name: "discord", label: "Discord", helpText: HELP_TEXT },
|
|
24
37
|
// Without the Gateway there is no message to edit as it grows, and each
|
|
25
38
|
// turn is one message per 2,000 characters.
|
|
26
39
|
capabilities: { streaming: "never", maxMessageChars: MAX_MESSAGE_CHARS },
|
|
27
40
|
port,
|
|
28
41
|
async start(ctx) {
|
|
42
|
+
const gate = ctx.gate;
|
|
29
43
|
await ctx.serve({
|
|
30
|
-
"POST /discord/interactions": interactionRoute({ cfg, key, port, api, router: ctx.router, log: ctx.log, now, inlineCardMs: opts.inlineCardMs }),
|
|
44
|
+
"POST /discord/interactions": interactionRoute({ cfg: fences, key, port, api, router: ctx.router, log: ctx.log, now, inlineCardMs: opts.inlineCardMs }),
|
|
45
|
+
// Webhook Events only for a gate, which is what tells loomcycle of a
|
|
46
|
+
// person who removed the app.
|
|
47
|
+
...(gate ? { [`POST ${EVENTS_PATH}`]: eventsRoute({ key, gate, forget: (s) => groups?.forget(s), log: ctx.log, now }) } : {}),
|
|
31
48
|
});
|
|
32
49
|
if (cfg.registerCommands)
|
|
33
50
|
await registerCommands(api, cfg, ctx.log);
|
|
@@ -35,6 +52,7 @@ export function createDiscordBridge(cfg, opts = {}) {
|
|
|
35
52
|
async stop() {
|
|
36
53
|
port.stop();
|
|
37
54
|
},
|
|
55
|
+
...(groups ? { groupsFor: (subject, ref) => groups.groupsFor(subject, ref) } : {}),
|
|
38
56
|
};
|
|
39
57
|
return createBridge(cfg, adapter, { ...opts, logger: log });
|
|
40
58
|
}
|
package/dist/bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAE9E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAuD,MAAM,wBAAwB,CAAC;AAE1H,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAE9E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAuD,MAAM,wBAAwB,CAAC;AAE1H,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE5D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAmB,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAUtC,MAAM,UAAU,mBAAmB,CAAC,GAAkB,EAAE,IAAI,GAAyB,EAAE;IACrF,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACjC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC;QACzB,OAAO,EAAE,GAAG,CAAC,UAAU;QACvB,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,GAAG;QACH,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG;QACb,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC;IACF,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3H,MAAM,OAAO,GAA8B;QACzC,wEAAwE;QACxE,+DAA+D;QAC/D,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE;QACpE,wEAAwE;QACxE,4CAA4C;QAC5C,YAAY,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE;QACxE,IAAI;QACJ,KAAK,CAAC,KAAK,CAAC,GAAG;YACb,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;YACtB,MAAM,GAAG,CAAC,KAAK,CAAC;gBACd,4BAA4B,EAAE,gBAAgB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;gBACvJ,qEAAqE;gBACrE,8BAA8B;gBAC9B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,WAAW,EAAE,CAAC,EAAE,WAAW,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9H,CAAC,CAAC;YACH,IAAI,GAAG,CAAC,gBAAgB;gBAAE,MAAM,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QACtE,CAAC;QACD,KAAK,CAAC,IAAI;YACR,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,OAAe,EAAE,GAAe,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvG,CAAC;IACF,OAAO,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAC9D,CAAC"}
|
package/dist/cards.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cards.js","sourceRoot":"","sources":["../src/cards.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,+EAA+E;AAC/E,8EAA8E;AAC9E,yCAAyC;AACzC,EAAE;AACF,sEAAsE;AACtE,8EAA8E;AAC9E,2EAA2E;AAC3E,8EAA8E;AAC9E,2EAA2E;AAC3E,qEAAqE;AACrE,4EAA4E;AAC5E,iDAAiD;AAEjD,OAAO,EAAE,IAAI,EAAuC,MAAM,wBAAwB,CAAC;AAgBnF,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AACjC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC;AAChC,MAAM,eAAe,GAAG,CAAC,CAAC;AAC1B,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAW,CAAC;AAE3E,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,KAAK,EAAE,EAAc,EAAE,CAAC;AACrD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,CAAC;AAEtC,MAAM,CAAC,MAAM,cAAc,GAAG,iDAAiD,CAAC;AAEhF,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,EAAE,GAAG,GAAG,gBAAgB,GAAG,QAAQ,EAAE,CAAC;IAC5C,IAAI,EAAE,CAAC,MAAM,GAAG,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACjF,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;mCACmC;AACnC,MAAM,UAAU,aAAa,CAAC,QAAiB;IAC7C,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,CAAC,GAAG,4BAA4B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5C,CAAC;AAED,SAAS,IAAI,CAAC,CAAS,EAAE,GAAW;IAClC,OAAO,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;AACzD,CAAC;AAED,SAAS,IAAI,CAAC,OAAiB;IAC7B,MAAM,GAAG,GAA2C,EAAE,CAAC;IACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,eAAe;QAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;IACnI,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,MAAM,CAAC,CAAa,EAAE,KAAa;IAC1C,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,EAAE,SAAS,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACjG,CAAC;AAED,MAAM,WAAW,GAAG,6DAA6D,CAAC;AAElF;;;iFAGiF;AACjF,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,KAAa,EAAE,GAAW,EAAE,EAAE,CAAC,GAAG,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1H,CAAC;AAED;iFACiF;AACjF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,EAAE,gBAAgB,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;AACtH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC5C,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,QAAQ;YACX,wEAAwE;YACxE,OAAO,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;QAC1D,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"cards.js","sourceRoot":"","sources":["../src/cards.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -38,7 +38,9 @@ function guilds(reader, name) {
|
|
|
38
38
|
}
|
|
39
39
|
export function loadConfig(env = process.env) {
|
|
40
40
|
const reader = new EnvReader(env);
|
|
41
|
-
|
|
41
|
+
// A gate only when BRIDGE_GATE names one: a bridge deployed with a
|
|
42
|
+
// loomcycle token keeps running as it was until it is reconfigured.
|
|
43
|
+
const shared = loadSharedConfig(reader, { port: DEFAULT_PORT, gate: reader.get("BRIDGE_GATE") !== undefined });
|
|
42
44
|
const applicationId = reader.required("DISCORD_APPLICATION_ID");
|
|
43
45
|
if (applicationId && !isSnowflake(applicationId))
|
|
44
46
|
reader.problems.push("DISCORD_APPLICATION_ID must be the application's numeric id");
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,6EAA6E;AAC7E,0BAA0B;AAE1B,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAA+B,MAAM,wBAAwB,CAAC;AAoBlG,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AACjC,MAAM,CAAC,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAElE,MAAM,SAAS,GAAG,YAAY,CAAC;AAE/B,MAAM,UAAU,WAAW,CAAC,CAAU;IACpC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;8DAC8D;AAC9D,SAAS,UAAU,CAAC,MAAiB;IACnC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,IAAI,oBAAoB,CAAC;IAC9E,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QAClE,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACzE,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC;QACtE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,MAAM,CAAC,MAAiB,EAAE,IAAY;IAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC;YACrB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,6CAA6C,CAAC,CAAC;YAC3E,MAAM;QACR,CAAC;IACH,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Logger, type Route } from "@loomcycle/bridge-core";
|
|
2
|
+
import type { KeyObject } from "node:crypto";
|
|
3
|
+
export declare const EVENTS_PATH = "/discord/events";
|
|
4
|
+
/** The outer object's type: Discord's probe when the URL is saved, or an event. */
|
|
5
|
+
export declare const WebhookType: {
|
|
6
|
+
readonly PING: 0;
|
|
7
|
+
readonly EVENT: 1;
|
|
8
|
+
};
|
|
9
|
+
export declare const APPLICATION_DEAUTHORIZED = "APPLICATION_DEAUTHORIZED";
|
|
10
|
+
/** The parts of a webhook event the bridge reads; the body is signed by
|
|
11
|
+
* Discord, but its shape is still checked before use. */
|
|
12
|
+
export interface WebhookEvent {
|
|
13
|
+
version?: number;
|
|
14
|
+
application_id?: string;
|
|
15
|
+
type?: number;
|
|
16
|
+
event?: {
|
|
17
|
+
type?: string;
|
|
18
|
+
timestamp?: string;
|
|
19
|
+
data?: {
|
|
20
|
+
user?: {
|
|
21
|
+
id?: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface EventDeps {
|
|
27
|
+
key: KeyObject;
|
|
28
|
+
/** The core's gate: names a platform id's subject, and revokes it. */
|
|
29
|
+
gate: {
|
|
30
|
+
subjectOf(sub: string): string;
|
|
31
|
+
revoke(subject: string): Promise<void>;
|
|
32
|
+
};
|
|
33
|
+
/** Called with the revoked subject, so cached groups go with it. */
|
|
34
|
+
forget(subject: string): void;
|
|
35
|
+
log: Logger;
|
|
36
|
+
now: () => number;
|
|
37
|
+
/** How long the answer waits for loomcycle's revoke (tests). */
|
|
38
|
+
revokeTimeoutMs?: number;
|
|
39
|
+
}
|
|
40
|
+
export declare function eventsRoute(deps: EventDeps): Route;
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// POST /discord/events: Discord's Webhook Events, served only when the bridge
|
|
2
|
+
// is a loomcycle gate. The one event it acts on is APPLICATION_DEAUTHORIZED:
|
|
3
|
+
// a person removed the app, so the gate tells loomcycle they are gone
|
|
4
|
+
// (RFC FA §3.7c) and loomcycle disables them at once and removes them per the
|
|
5
|
+
// gate's policy.
|
|
6
|
+
//
|
|
7
|
+
// Discord signs these exactly as it signs interactions (Ed25519 over the
|
|
8
|
+
// timestamp header then the raw body, with the application's public key). It
|
|
9
|
+
// wants a 204 with no body within 3 seconds, and redelivers an event that got
|
|
10
|
+
// anything else for up to 10 minutes.
|
|
11
|
+
//
|
|
12
|
+
// Revocation must not fail open: the 204 is sent only once loomcycle has
|
|
13
|
+
// taken the revoke. A failed revoke, or one slower than Discord waits, is
|
|
14
|
+
// answered 503 so Discord delivers it again; a repeated revoke changes
|
|
15
|
+
// nothing (loomcycle answers 204 for a person it has already removed, or
|
|
16
|
+
// never knew).
|
|
17
|
+
import { header } from "@loomcycle/bridge-core";
|
|
18
|
+
import { isSnowflake } from "./config.js";
|
|
19
|
+
import { personSub } from "./identity.js";
|
|
20
|
+
import { verifyInteraction } from "./verify.js";
|
|
21
|
+
export const EVENTS_PATH = "/discord/events";
|
|
22
|
+
/** The outer object's type: Discord's probe when the URL is saved, or an event. */
|
|
23
|
+
export const WebhookType = { PING: 0, EVENT: 1 };
|
|
24
|
+
export const APPLICATION_DEAUTHORIZED = "APPLICATION_DEAUTHORIZED";
|
|
25
|
+
// Discord asks for a Content-Type even on the empty answer.
|
|
26
|
+
const NO_CONTENT = { status: 204, headers: { "content-type": "application/json" } };
|
|
27
|
+
const RETRY_LATER = { status: 503, body: "revoke not applied; retry" };
|
|
28
|
+
/** Inside Discord's 3 seconds, with room for the answer to travel. */
|
|
29
|
+
const REVOKE_TIMEOUT_MS = 2500;
|
|
30
|
+
class RevokeTimeout extends Error {
|
|
31
|
+
}
|
|
32
|
+
export function eventsRoute(deps) {
|
|
33
|
+
return async (req) => {
|
|
34
|
+
// Always verified, BRIDGE_DEV or not: what this route does is revoke.
|
|
35
|
+
const ok = verifyInteraction(deps.key, header(req, "x-signature-ed25519"), header(req, "x-signature-timestamp"), req.body, deps.now());
|
|
36
|
+
if (!ok)
|
|
37
|
+
return { status: 401, body: "unauthorized" };
|
|
38
|
+
let wh;
|
|
39
|
+
try {
|
|
40
|
+
wh = JSON.parse(req.body.toString("utf8"));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return { status: 400, body: "bad request" };
|
|
44
|
+
}
|
|
45
|
+
if (!wh || typeof wh !== "object")
|
|
46
|
+
return { status: 400, body: "bad request" };
|
|
47
|
+
if (wh.type !== WebhookType.EVENT || wh.event?.type !== APPLICATION_DEAUTHORIZED)
|
|
48
|
+
return NO_CONTENT;
|
|
49
|
+
const userId = wh.event.data?.user?.id;
|
|
50
|
+
if (!isSnowflake(userId))
|
|
51
|
+
return NO_CONTENT;
|
|
52
|
+
const subject = deps.gate.subjectOf(personSub(userId));
|
|
53
|
+
deps.forget(subject);
|
|
54
|
+
let timer;
|
|
55
|
+
const timeout = new Promise((_, reject) => {
|
|
56
|
+
timer = setTimeout(() => reject(new RevokeTimeout()), deps.revokeTimeoutMs ?? REVOKE_TIMEOUT_MS);
|
|
57
|
+
});
|
|
58
|
+
const revoke = deps.gate.revoke(subject);
|
|
59
|
+
try {
|
|
60
|
+
await Promise.race([revoke, timeout]);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
if (err instanceof RevokeTimeout) {
|
|
64
|
+
// It may still land; the redelivery repeats it either way.
|
|
65
|
+
revoke.catch((late) => deps.log.warn("discord revoke failed", { status: late?.status }));
|
|
66
|
+
deps.log.warn("discord revoke timed out; Discord will redeliver", {});
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
deps.log.warn("discord revoke failed; Discord will redeliver", { status: err?.status });
|
|
70
|
+
}
|
|
71
|
+
return RETRY_LATER;
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
}
|
|
76
|
+
deps.log.info("discord user removed the app; revoked in loomcycle", { user: userId });
|
|
77
|
+
return NO_CONTENT;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
|
package/dist/groups.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type DiscordApi } from "./api.js";
|
|
2
|
+
import type { DiscordRef } from "./port.js";
|
|
3
|
+
/** At most this many trusted servers are asked about a person's membership;
|
|
4
|
+
* past it the bridge asserts no groups for people (a channel's own user
|
|
5
|
+
* still gets its server's). */
|
|
6
|
+
export declare const MAX_GROUP_LOOKUPS = 20;
|
|
7
|
+
/** How long a person's looked-up groups are reused. */
|
|
8
|
+
export declare const GROUP_CACHE_MS: number;
|
|
9
|
+
export interface GroupLookupOptions {
|
|
10
|
+
api: Pick<DiscordApi, "guildMember">;
|
|
11
|
+
/** The gate's name: a person is "<gate>:<user id>", a channel "<gate>:conv:<hash>". */
|
|
12
|
+
gate: string;
|
|
13
|
+
trustedGuilds: ReadonlySet<string>;
|
|
14
|
+
now?: () => number;
|
|
15
|
+
}
|
|
16
|
+
export declare class GroupLookup {
|
|
17
|
+
private readonly opts;
|
|
18
|
+
private readonly cache;
|
|
19
|
+
private readonly now;
|
|
20
|
+
constructor(opts: GroupLookupOptions);
|
|
21
|
+
/** groupsFor: a channel's own user is in its server's group. A person (a
|
|
22
|
+
* DM) is in the group of each trusted server they are a member of, and in
|
|
23
|
+
* a group per role they hold there, looked up with the bot token. A lookup
|
|
24
|
+
* that fails, or more trusted servers than are worth asking about, asserts
|
|
25
|
+
* nothing, so loomcycle never removes a group on a guess. Cached per
|
|
26
|
+
* person for a while: a token is asked for rarely, but a restart asks for
|
|
27
|
+
* all of them at once. */
|
|
28
|
+
groupsFor(subject: string, ref: DiscordRef): Promise<string[] | undefined>;
|
|
29
|
+
/** forget drops a person's cached groups (they were revoked). */
|
|
30
|
+
forget(subject: string): void;
|
|
31
|
+
}
|
package/dist/groups.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// A gate bridge's groups for a run identity (RFC FA §3.7d): what Discord
|
|
2
|
+
// knows, named as platform groups. loomcycle keeps them as "<gate>:<group>"
|
|
3
|
+
// external groups, which an operator maps (group_map) and binds ACLs to.
|
|
4
|
+
import { DiscordApiError } from "./api.js";
|
|
5
|
+
import { isSnowflake } from "./config.js";
|
|
6
|
+
import { guildGroup, roleGroup } from "./identity.js";
|
|
7
|
+
/** At most this many trusted servers are asked about a person's membership;
|
|
8
|
+
* past it the bridge asserts no groups for people (a channel's own user
|
|
9
|
+
* still gets its server's). */
|
|
10
|
+
export const MAX_GROUP_LOOKUPS = 20;
|
|
11
|
+
/** How long a person's looked-up groups are reused. */
|
|
12
|
+
export const GROUP_CACHE_MS = 10 * 60 * 1000;
|
|
13
|
+
const MAX_CACHED = 10_000;
|
|
14
|
+
/** Discord's JSON error code for a server the bot cannot see. */
|
|
15
|
+
const UNKNOWN_GUILD = 10004;
|
|
16
|
+
export class GroupLookup {
|
|
17
|
+
opts;
|
|
18
|
+
cache = new Map();
|
|
19
|
+
now;
|
|
20
|
+
constructor(opts) {
|
|
21
|
+
this.opts = opts;
|
|
22
|
+
this.now = opts.now ?? Date.now;
|
|
23
|
+
}
|
|
24
|
+
/** groupsFor: a channel's own user is in its server's group. A person (a
|
|
25
|
+
* DM) is in the group of each trusted server they are a member of, and in
|
|
26
|
+
* a group per role they hold there, looked up with the bot token. A lookup
|
|
27
|
+
* that fails, or more trusted servers than are worth asking about, asserts
|
|
28
|
+
* nothing, so loomcycle never removes a group on a guess. Cached per
|
|
29
|
+
* person for a while: a token is asked for rarely, but a restart asks for
|
|
30
|
+
* all of them at once. */
|
|
31
|
+
async groupsFor(subject, ref) {
|
|
32
|
+
const prefix = `${this.opts.gate}:`;
|
|
33
|
+
if (!subject.startsWith(prefix))
|
|
34
|
+
return undefined;
|
|
35
|
+
const sub = subject.slice(prefix.length);
|
|
36
|
+
// A ref stored before 0.3 has no server: assert nothing for it.
|
|
37
|
+
if (sub.startsWith("conv:"))
|
|
38
|
+
return ref.guildId ? [guildGroup(ref.guildId)] : undefined;
|
|
39
|
+
if (!isSnowflake(sub))
|
|
40
|
+
return undefined;
|
|
41
|
+
const trusted = this.opts.trustedGuilds;
|
|
42
|
+
if (trusted.size === 0)
|
|
43
|
+
return [];
|
|
44
|
+
if (trusted.size > MAX_GROUP_LOOKUPS)
|
|
45
|
+
return undefined;
|
|
46
|
+
const now = this.now();
|
|
47
|
+
const hit = this.cache.get(subject);
|
|
48
|
+
if (hit && hit.until > now)
|
|
49
|
+
return hit.groups;
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const guild of [...trusted].sort()) {
|
|
52
|
+
let member;
|
|
53
|
+
try {
|
|
54
|
+
member = await this.opts.api.guildMember(guild, sub);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
// Not a member. A server the bot cannot see is also a 404, but says
|
|
58
|
+
// nothing about the person.
|
|
59
|
+
if (err instanceof DiscordApiError && err.status === 404 && err.code !== UNKNOWN_GUILD)
|
|
60
|
+
continue;
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
// A bot is never a person the gate speaks for: no groups for it at all.
|
|
64
|
+
if (member?.user?.bot)
|
|
65
|
+
return undefined;
|
|
66
|
+
out.push(guildGroup(guild));
|
|
67
|
+
const roles = Array.isArray(member?.roles) ? member.roles : [];
|
|
68
|
+
for (const role of roles)
|
|
69
|
+
if (isSnowflake(role))
|
|
70
|
+
out.push(roleGroup(role));
|
|
71
|
+
}
|
|
72
|
+
this.cache.delete(subject);
|
|
73
|
+
this.cache.set(subject, { groups: out, until: now + GROUP_CACHE_MS });
|
|
74
|
+
if (this.cache.size > MAX_CACHED)
|
|
75
|
+
this.cache.delete(this.cache.keys().next().value);
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
/** forget drops a person's cached groups (they were revoked). */
|
|
79
|
+
forget(subject) {
|
|
80
|
+
this.cache.delete(subject);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=groups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups.js","sourceRoot":"","sources":["../src/groups.ts"],"names":[],"mappings":"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"}
|
package/dist/identity.d.ts
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import { type Identified } from "@loomcycle/bridge-core";
|
|
2
2
|
import { type DiscordConfig } from "./config.js";
|
|
3
3
|
import { type Interaction } from "./interaction.js";
|
|
4
|
-
export type Fences = Pick<DiscordConfig, "applicationId" | "allowedGuilds" | "allowDms" | "trustedGuilds"
|
|
4
|
+
export type Fences = Pick<DiscordConfig, "applicationId" | "allowedGuilds" | "allowDms" | "trustedGuilds"> & {
|
|
5
|
+
/** The bridge's gate name in loomcycle (RFC FA §3.7d): a person is
|
|
6
|
+
* "<gate>:<user id>", a channel "<gate>:conv:<hash>". Unset for a bridge
|
|
7
|
+
* with a loomcycle token: "discord-<id>" and "discord-conv-<hash>", the
|
|
8
|
+
* subjects a gate's legacy_subject_prefix links to on a first login. */
|
|
9
|
+
gate?: string;
|
|
10
|
+
};
|
|
5
11
|
/** Where an interaction happened. */
|
|
6
12
|
export interface Place {
|
|
7
13
|
channelId: string;
|
|
8
14
|
/** Absent in a DM. */
|
|
9
15
|
guildId?: string;
|
|
10
16
|
}
|
|
17
|
+
/** personSub is the platform id a person is asserted under: loomcycle makes
|
|
18
|
+
* it the subject "<gate>:<id>". */
|
|
19
|
+
export declare function personSub(userId: string): string;
|
|
20
|
+
/** guildGroup names the platform group of a server's members, and roleGroup
|
|
21
|
+
* that of a role's holders. loomcycle keeps them as "<gate>:dc-guild-<id>"
|
|
22
|
+
* external groups, which an operator maps (group_map) and binds ACLs to. */
|
|
23
|
+
export declare function guildGroup(guildId: string): string;
|
|
24
|
+
export declare function roleGroup(roleId: string): string;
|
|
11
25
|
export declare const NOT_IN_SERVER = "This bot isn't available in this server.";
|
|
12
26
|
export declare const NOT_IN_DMS = "This bot isn't available in direct messages.";
|
|
13
27
|
export declare const NOT_HERE = "This bot isn't available here.";
|
package/dist/identity.js
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
// Who used a command, and where, as the core needs it. The fences (allowed
|
|
2
2
|
// servers, DMs on or off) are applied here, before anything touches loomcycle.
|
|
3
|
-
import { sharedSubject } from "@loomcycle/bridge-core";
|
|
3
|
+
import { gateSharedSubject, sharedSubject } from "@loomcycle/bridge-core";
|
|
4
4
|
import { isSnowflake } from "./config.js";
|
|
5
5
|
import { Context } from "./interaction.js";
|
|
6
6
|
const THREAD_TYPES = new Set([10, 11, 12]);
|
|
7
|
+
/** personSub is the platform id a person is asserted under: loomcycle makes
|
|
8
|
+
* it the subject "<gate>:<id>". */
|
|
9
|
+
export function personSub(userId) {
|
|
10
|
+
return userId;
|
|
11
|
+
}
|
|
12
|
+
/** guildGroup names the platform group of a server's members, and roleGroup
|
|
13
|
+
* that of a role's holders. loomcycle keeps them as "<gate>:dc-guild-<id>"
|
|
14
|
+
* external groups, which an operator maps (group_map) and binds ACLs to. */
|
|
15
|
+
export function guildGroup(guildId) {
|
|
16
|
+
return `dc-guild-${guildId}`;
|
|
17
|
+
}
|
|
18
|
+
export function roleGroup(roleId) {
|
|
19
|
+
return `dc-role-${roleId}`;
|
|
20
|
+
}
|
|
7
21
|
export const NOT_IN_SERVER = "This bot isn't available in this server.";
|
|
8
22
|
export const NOT_IN_DMS = "This bot isn't available in direct messages.";
|
|
9
23
|
export const NOT_HERE = "This bot isn't available here.";
|
|
@@ -35,6 +49,7 @@ export function identify(ix, fences) {
|
|
|
35
49
|
const user = ix.member?.user ?? ix.user;
|
|
36
50
|
if (!user || !isSnowflake(user.id))
|
|
37
51
|
return { ok: false, reason: "no_user" };
|
|
52
|
+
const subject = fences.gate ? `${fences.gate}:${personSub(user.id)}` : `discord-${user.id}`;
|
|
38
53
|
// Bots cannot use slash commands today; this keeps that true if they ever can.
|
|
39
54
|
if (user.bot || user.id === fences.applicationId)
|
|
40
55
|
return { ok: false, reason: "self_or_bot" };
|
|
@@ -49,13 +64,13 @@ export function identify(ix, fences) {
|
|
|
49
64
|
return { ok: false, reason: "private_channel", notice: NOT_HERE, conversationId };
|
|
50
65
|
if (!fences.allowDms)
|
|
51
66
|
return { ok: false, reason: "dms_closed", notice: NOT_IN_DMS, conversationId };
|
|
52
|
-
const speaker = { subject
|
|
67
|
+
const speaker = { subject, name: displayName(ix, user.id), trust: "trusted" };
|
|
53
68
|
return { ok: true, speaker, scope: "personal", conversationId, runAs: { subject: speaker.subject, name: speaker.name } };
|
|
54
69
|
}
|
|
55
70
|
if (!fences.allowedGuilds.has(place.guildId))
|
|
56
71
|
return { ok: false, reason: "guild_not_allowed", notice: NOT_IN_SERVER, conversationId };
|
|
57
72
|
const speaker = {
|
|
58
|
-
subject
|
|
73
|
+
subject,
|
|
59
74
|
name: displayName(ix, user.id),
|
|
60
75
|
trust: fences.trustedGuilds.has(place.guildId) ? "trusted" : "untrusted",
|
|
61
76
|
};
|
|
@@ -68,7 +83,10 @@ export function identify(ix, fences) {
|
|
|
68
83
|
speaker,
|
|
69
84
|
scope: "channel",
|
|
70
85
|
conversationId,
|
|
71
|
-
runAs: {
|
|
86
|
+
runAs: {
|
|
87
|
+
subject: fences.gate ? gateSharedSubject(fences.gate, place.guildId, memoryChannel) : sharedSubject("discord", place.guildId, memoryChannel),
|
|
88
|
+
name: "Discord channel",
|
|
89
|
+
},
|
|
72
90
|
};
|
|
73
91
|
}
|
|
74
92
|
//# sourceMappingURL=identity.js.map
|
package/dist/identity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,+EAA+E;AAE/E,OAAO,EAAE,aAAa,EAAiC,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { DiscordApi, DiscordApiError, retryAfterMs, USER_AGENT } from "./api.js";
|
|
2
|
-
export type { CommandSpec, DiscordApiOptions } from "./api.js";
|
|
2
|
+
export type { CommandSpec, DiscordApiOptions, GuildMember } from "./api.js";
|
|
3
3
|
export { createDiscordBridge, MAX_MESSAGE_CHARS } from "./bridge.js";
|
|
4
4
|
export type { DiscordBridgeOptions } from "./bridge.js";
|
|
5
5
|
export { customIdOf, parseCustomId, renderCard, textMessage } from "./cards.js";
|
|
@@ -7,7 +7,11 @@ export type { MessageBody } from "./cards.js";
|
|
|
7
7
|
export { commandSpecs, HELP_TEXT, registerCommands } from "./commands.js";
|
|
8
8
|
export { DEFAULT_API_BASE_URL, DEFAULT_PORT, loadConfig } from "./config.js";
|
|
9
9
|
export type { DiscordConfig } from "./config.js";
|
|
10
|
-
export {
|
|
10
|
+
export { APPLICATION_DEAUTHORIZED, EVENTS_PATH, eventsRoute, WebhookType } from "./events.js";
|
|
11
|
+
export type { EventDeps, WebhookEvent } from "./events.js";
|
|
12
|
+
export { GROUP_CACHE_MS, GroupLookup, MAX_GROUP_LOOKUPS } from "./groups.js";
|
|
13
|
+
export type { GroupLookupOptions } from "./groups.js";
|
|
14
|
+
export { conversationIdOf, guildGroup, identify, personSub, placeOf, roleGroup } from "./identity.js";
|
|
11
15
|
export type { Fences, Place } from "./identity.js";
|
|
12
16
|
export type { Interaction } from "./interaction.js";
|
|
13
17
|
export { interactionRoute } from "./interactions.js";
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,9 @@ export { createDiscordBridge, MAX_MESSAGE_CHARS } from "./bridge.js";
|
|
|
3
3
|
export { customIdOf, parseCustomId, renderCard, textMessage } from "./cards.js";
|
|
4
4
|
export { commandSpecs, HELP_TEXT, registerCommands } from "./commands.js";
|
|
5
5
|
export { DEFAULT_API_BASE_URL, DEFAULT_PORT, loadConfig } from "./config.js";
|
|
6
|
-
export {
|
|
6
|
+
export { APPLICATION_DEAUTHORIZED, EVENTS_PATH, eventsRoute, WebhookType } from "./events.js";
|
|
7
|
+
export { GROUP_CACHE_MS, GroupLookup, MAX_GROUP_LOOKUPS } from "./groups.js";
|
|
8
|
+
export { conversationIdOf, guildGroup, identify, personSub, placeOf, roleGroup } from "./identity.js";
|
|
7
9
|
export { interactionRoute } from "./interactions.js";
|
|
8
10
|
export { DiscordPort } from "./port.js";
|
|
9
11
|
export { MAX_SKEW_SECONDS, publicKeyFromHex, verifyInteraction } from "./verify.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEjF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEjF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE9F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGtG,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/interactions.d.ts
CHANGED
|
@@ -2,9 +2,10 @@ import { type ConversationRouter, type Logger, type Route } from "@loomcycle/bri
|
|
|
2
2
|
import type { KeyObject } from "node:crypto";
|
|
3
3
|
import type { DiscordApi } from "./api.js";
|
|
4
4
|
import { type DiscordConfig } from "./config.js";
|
|
5
|
+
import { type Fences } from "./identity.js";
|
|
5
6
|
import type { DiscordPort, DiscordRef } from "./port.js";
|
|
6
7
|
export interface InteractionDeps {
|
|
7
|
-
cfg: Pick<DiscordConfig, "
|
|
8
|
+
cfg: Fences & Pick<DiscordConfig, "dev">;
|
|
8
9
|
key: KeyObject;
|
|
9
10
|
port: DiscordPort;
|
|
10
11
|
api: DiscordApi;
|
package/dist/interactions.js
CHANGED
|
@@ -47,6 +47,10 @@ function json(body) {
|
|
|
47
47
|
function ephemeral(text) {
|
|
48
48
|
return json({ type: CallbackType.CHANNEL_MESSAGE_WITH_SOURCE, data: { ...textMessage(text), flags: EPHEMERAL | SUPPRESS_EMBEDS } });
|
|
49
49
|
}
|
|
50
|
+
/** refOf is where replies go, as the conversation store keeps it. */
|
|
51
|
+
function refOf(place) {
|
|
52
|
+
return place.guildId ? { channelId: place.channelId, guildId: place.guildId } : { channelId: place.channelId };
|
|
53
|
+
}
|
|
50
54
|
function promptOf(ix) {
|
|
51
55
|
const v = ix.data?.options?.find((o) => o.name === "prompt")?.value;
|
|
52
56
|
return typeof v === "string" ? v.trim().slice(0, MAX_PROMPT_CHARS) : "";
|
|
@@ -70,7 +74,7 @@ export function interactionRoute(deps) {
|
|
|
70
74
|
if (!text)
|
|
71
75
|
return ephemeral("Write something after /ask.");
|
|
72
76
|
const place = placeOf(ix);
|
|
73
|
-
const ref =
|
|
77
|
+
const ref = refOf(place);
|
|
74
78
|
port.track(ix.id, ix.token, place.channelId, FALLBACK[name]);
|
|
75
79
|
// After this response is written: the core's first reply edits the
|
|
76
80
|
// deferred message, which must exist by then.
|
|
@@ -98,7 +102,7 @@ export function interactionRoute(deps) {
|
|
|
98
102
|
return ephemeral(id.notice ?? NOT_HERE);
|
|
99
103
|
}
|
|
100
104
|
const place = placeOf(ix);
|
|
101
|
-
const ref =
|
|
105
|
+
const ref = refOf(place);
|
|
102
106
|
// Its token also carries the agent's next messages in this channel.
|
|
103
107
|
port.track(ix.id, ix.token, place.channelId);
|
|
104
108
|
const work = deps.router.onCardAction(id, ref, input).catch((err) => {
|
package/dist/interactions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactions.js","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,oBAAoB;AAEpB,OAAO,EAAE,MAAM,EAAuF,MAAM,wBAAwB,CAAC;AAIrI,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"interactions.js","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"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"}
|
package/dist/port.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ import { type DiscordApi } from "./api.js";
|
|
|
5
5
|
* interaction the port holds for it (see deliver), else the bot token. */
|
|
6
6
|
export interface DiscordRef {
|
|
7
7
|
channelId: string;
|
|
8
|
+
/** The server the channel is in; absent in a DM, and in a ref stored by a
|
|
9
|
+
* bridge before 0.3. Only a gate bridge reads it (its channel's groups). */
|
|
10
|
+
guildId?: string;
|
|
8
11
|
}
|
|
9
12
|
export declare const TOKEN_LIFETIME_MS: number;
|
|
10
13
|
export declare const CONTINUED = "Continued below.";
|
package/dist/port.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port.js","sourceRoot":"","sources":["../src/port.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6BAA6B;AAC7B,EAAE;AACF,8EAA8E;AAC9E,2EAA2E;AAC3E,gDAAgD;AAChD,4EAA4E;AAC5E,oEAAoE;AACpE,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,4DAA4D;AAE5D,OAAO,EAAE,YAAY,EAAuD,MAAM,wBAAwB,CAAC;AAE3G,OAAO,EAAE,eAAe,EAAmB,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"port.js","sourceRoot":"","sources":["../src/port.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomcycle/bridge-discord",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Discord bridge for loomcycle interactive agents (RFC EQ): people talk to a loomcycle agent with slash commands, each as their own loomcycle user, with question and review cards as buttons. Interactions over HTTP; no Gateway.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"test:watch": "vitest"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@loomcycle/bridge-core": "^0.1
|
|
35
|
+
"@loomcycle/bridge-core": "^0.3.1"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@types/node": "^
|
|
39
|
-
"typescript": "^
|
|
40
|
-
"vitest": "^
|
|
38
|
+
"@types/node": "^26.6.5",
|
|
39
|
+
"typescript": "^7.0.2",
|
|
40
|
+
"vitest": "^5.0.5"
|
|
41
41
|
}
|
|
42
42
|
}
|