@gakr-gakr/matrix 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/CHANGELOG.md +285 -0
- package/SPEC-SUPPORT.md +116 -0
- package/api.ts +38 -0
- package/auth-presence.ts +56 -0
- package/autobot.plugin.json +28 -0
- package/channel-plugin-api.ts +3 -0
- package/cli-metadata.ts +11 -0
- package/contract-api.ts +17 -0
- package/doctor-contract-api.ts +1 -0
- package/helper-api.ts +3 -0
- package/index.ts +55 -0
- package/package.json +101 -0
- package/plugin-entry.handlers.runtime.ts +1 -0
- package/runtime-api.ts +72 -0
- package/runtime-heavy-api.ts +1 -0
- package/runtime-setter-api.ts +3 -0
- package/secret-contract-api.ts +5 -0
- package/setup-entry.ts +17 -0
- package/setup-plugin-api.ts +3 -0
- package/src/account-selection.ts +223 -0
- package/src/actions.ts +346 -0
- package/src/approval-auth.ts +25 -0
- package/src/approval-handler.runtime.ts +595 -0
- package/src/approval-ids.ts +6 -0
- package/src/approval-native.ts +348 -0
- package/src/approval-reaction-auth.ts +45 -0
- package/src/approval-reactions.ts +313 -0
- package/src/auth-precedence.ts +61 -0
- package/src/channel-account-paths.ts +97 -0
- package/src/channel.runtime.ts +17 -0
- package/src/channel.setup.ts +48 -0
- package/src/channel.ts +667 -0
- package/src/cli-metadata.ts +19 -0
- package/src/cli.ts +2298 -0
- package/src/config-adapter.ts +41 -0
- package/src/config-schema.ts +159 -0
- package/src/config-ui-hints.ts +56 -0
- package/src/directory-live.ts +238 -0
- package/src/doctor-contract.ts +287 -0
- package/src/doctor.ts +262 -0
- package/src/env-vars.ts +92 -0
- package/src/exec-approval-resolver.ts +23 -0
- package/src/exec-approvals.ts +293 -0
- package/src/group-mentions.ts +41 -0
- package/src/legacy-crypto-inspector-availability.ts +60 -0
- package/src/legacy-crypto.ts +531 -0
- package/src/legacy-state.ts +156 -0
- package/src/matrix/account-config.ts +175 -0
- package/src/matrix/accounts.ts +194 -0
- package/src/matrix/actions/client.ts +31 -0
- package/src/matrix/actions/devices.ts +34 -0
- package/src/matrix/actions/limits.ts +6 -0
- package/src/matrix/actions/messages.ts +129 -0
- package/src/matrix/actions/pins.ts +63 -0
- package/src/matrix/actions/polls.ts +109 -0
- package/src/matrix/actions/profile.ts +37 -0
- package/src/matrix/actions/reactions.ts +59 -0
- package/src/matrix/actions/room.ts +71 -0
- package/src/matrix/actions/summary.ts +88 -0
- package/src/matrix/actions/types.ts +63 -0
- package/src/matrix/actions/verification.ts +589 -0
- package/src/matrix/actions.ts +37 -0
- package/src/matrix/active-client.ts +26 -0
- package/src/matrix/async-lock.ts +18 -0
- package/src/matrix/backup-health.ts +124 -0
- package/src/matrix/client/config-runtime-api.ts +9 -0
- package/src/matrix/client/config-secret-input.runtime.ts +1 -0
- package/src/matrix/client/config.ts +853 -0
- package/src/matrix/client/create-client.ts +105 -0
- package/src/matrix/client/env-auth.ts +95 -0
- package/src/matrix/client/file-sync-store.ts +289 -0
- package/src/matrix/client/logging.ts +140 -0
- package/src/matrix/client/migration-snapshot.runtime.ts +1 -0
- package/src/matrix/client/private-network-host.ts +1 -0
- package/src/matrix/client/runtime.ts +4 -0
- package/src/matrix/client/shared.ts +316 -0
- package/src/matrix/client/storage.ts +543 -0
- package/src/matrix/client/types.ts +50 -0
- package/src/matrix/client/url-validation.ts +76 -0
- package/src/matrix/client-bootstrap.ts +173 -0
- package/src/matrix/client.ts +23 -0
- package/src/matrix/config-paths.ts +31 -0
- package/src/matrix/config-update.ts +292 -0
- package/src/matrix/credentials-read.ts +207 -0
- package/src/matrix/credentials-write.runtime.ts +35 -0
- package/src/matrix/credentials.ts +95 -0
- package/src/matrix/deps.ts +309 -0
- package/src/matrix/device-health.ts +31 -0
- package/src/matrix/direct-management.ts +349 -0
- package/src/matrix/direct-room.ts +128 -0
- package/src/matrix/draft-stream.ts +225 -0
- package/src/matrix/encryption-guidance.ts +24 -0
- package/src/matrix/errors.ts +21 -0
- package/src/matrix/format.ts +426 -0
- package/src/matrix/legacy-crypto-inspector.ts +95 -0
- package/src/matrix/media-errors.ts +20 -0
- package/src/matrix/media-text.ts +162 -0
- package/src/matrix/monitor/access-state.ts +145 -0
- package/src/matrix/monitor/ack-config.ts +27 -0
- package/src/matrix/monitor/allowlist.ts +92 -0
- package/src/matrix/monitor/auto-join.ts +86 -0
- package/src/matrix/monitor/config.ts +569 -0
- package/src/matrix/monitor/context-summary.ts +43 -0
- package/src/matrix/monitor/direct.ts +296 -0
- package/src/matrix/monitor/events.ts +397 -0
- package/src/matrix/monitor/handler.ts +2271 -0
- package/src/matrix/monitor/inbound-dedupe.ts +267 -0
- package/src/matrix/monitor/index.ts +540 -0
- package/src/matrix/monitor/legacy-crypto-restore.ts +139 -0
- package/src/matrix/monitor/location.ts +108 -0
- package/src/matrix/monitor/media.ts +119 -0
- package/src/matrix/monitor/mentions.ts +256 -0
- package/src/matrix/monitor/reaction-events.ts +197 -0
- package/src/matrix/monitor/recent-invite.ts +30 -0
- package/src/matrix/monitor/replies.ts +136 -0
- package/src/matrix/monitor/reply-context.ts +92 -0
- package/src/matrix/monitor/room-history.ts +301 -0
- package/src/matrix/monitor/room-info.ts +126 -0
- package/src/matrix/monitor/rooms.ts +52 -0
- package/src/matrix/monitor/route.ts +179 -0
- package/src/matrix/monitor/runtime-api.ts +28 -0
- package/src/matrix/monitor/startup-verification.ts +237 -0
- package/src/matrix/monitor/startup.ts +218 -0
- package/src/matrix/monitor/status.ts +120 -0
- package/src/matrix/monitor/sync-lifecycle.ts +91 -0
- package/src/matrix/monitor/task-runner.ts +38 -0
- package/src/matrix/monitor/test-events.ts +21 -0
- package/src/matrix/monitor/thread-context.ts +108 -0
- package/src/matrix/monitor/threads.ts +85 -0
- package/src/matrix/monitor/types.ts +30 -0
- package/src/matrix/monitor/verification-events.ts +643 -0
- package/src/matrix/monitor/verification-utils.ts +46 -0
- package/src/matrix/outbound-media-runtime.ts +1 -0
- package/src/matrix/poll-summary.ts +110 -0
- package/src/matrix/poll-types.ts +429 -0
- package/src/matrix/probe.runtime.ts +4 -0
- package/src/matrix/probe.ts +97 -0
- package/src/matrix/profile.ts +184 -0
- package/src/matrix/reaction-common.ts +147 -0
- package/src/matrix/sdk/crypto-bootstrap.ts +438 -0
- package/src/matrix/sdk/crypto-facade.ts +242 -0
- package/src/matrix/sdk/crypto-node.runtime.ts +17 -0
- package/src/matrix/sdk/crypto-runtime.ts +14 -0
- package/src/matrix/sdk/decrypt-bridge.ts +410 -0
- package/src/matrix/sdk/event-helpers.ts +83 -0
- package/src/matrix/sdk/http-client.ts +87 -0
- package/src/matrix/sdk/idb-persistence-lock.ts +51 -0
- package/src/matrix/sdk/idb-persistence.ts +286 -0
- package/src/matrix/sdk/logger.ts +108 -0
- package/src/matrix/sdk/read-response-with-limit.ts +19 -0
- package/src/matrix/sdk/recovery-key-store.ts +453 -0
- package/src/matrix/sdk/timeout-abort-signal.ts +1 -0
- package/src/matrix/sdk/transport-runtime-api.ts +18 -0
- package/src/matrix/sdk/transport.ts +352 -0
- package/src/matrix/sdk/types.ts +245 -0
- package/src/matrix/sdk/verification-manager.ts +795 -0
- package/src/matrix/sdk/verification-status.ts +23 -0
- package/src/matrix/sdk.ts +2152 -0
- package/src/matrix/send/client.ts +93 -0
- package/src/matrix/send/formatting.ts +189 -0
- package/src/matrix/send/media.ts +244 -0
- package/src/matrix/send/targets.ts +104 -0
- package/src/matrix/send/types.ts +131 -0
- package/src/matrix/send.ts +660 -0
- package/src/matrix/session-store-metadata.ts +108 -0
- package/src/matrix/startup-abort.ts +44 -0
- package/src/matrix/subagent-hooks.ts +308 -0
- package/src/matrix/sync-state.ts +27 -0
- package/src/matrix/target-ids.ts +79 -0
- package/src/matrix/thread-bindings-shared.ts +206 -0
- package/src/matrix/thread-bindings.ts +580 -0
- package/src/matrix-migration.runtime.ts +9 -0
- package/src/migration-config.ts +243 -0
- package/src/migration-snapshot-backup.ts +116 -0
- package/src/migration-snapshot.ts +53 -0
- package/src/onboarding.ts +775 -0
- package/src/outbound.ts +248 -0
- package/src/plugin-entry.runtime.js +115 -0
- package/src/plugin-entry.runtime.ts +70 -0
- package/src/profile-update.ts +71 -0
- package/src/record-shared.ts +3 -0
- package/src/resolve-targets.ts +175 -0
- package/src/resolver.runtime.ts +5 -0
- package/src/resolver.ts +21 -0
- package/src/runtime-api.ts +106 -0
- package/src/runtime.ts +13 -0
- package/src/secret-contract.ts +174 -0
- package/src/session-route.ts +126 -0
- package/src/setup-bootstrap.ts +102 -0
- package/src/setup-config.ts +222 -0
- package/src/setup-contract.ts +90 -0
- package/src/setup-core.ts +146 -0
- package/src/setup-dm-policy.ts +15 -0
- package/src/setup-surface.ts +4 -0
- package/src/startup-maintenance.ts +114 -0
- package/src/storage-paths.ts +92 -0
- package/src/thread-binding-api.ts +23 -0
- package/src/tool-actions.runtime.ts +1 -0
- package/src/tool-actions.ts +498 -0
- package/src/types.ts +257 -0
- package/subagent-hooks-api.ts +31 -0
- package/test-api.ts +21 -0
- package/thread-binding-api.ts +4 -0
- package/thread-bindings-runtime.ts +4 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
import { isDangerousNameMatchingEnabled } from "autobot/plugin-sdk/dangerous-name-runtime";
|
|
2
|
+
import { resolveMatrixTargets } from "../../resolve-targets.js";
|
|
3
|
+
import type { CoreConfig, MatrixRoomConfig } from "../../types.js";
|
|
4
|
+
import { resolveMatrixAccountConfig } from "../account-config.js";
|
|
5
|
+
import { isMatrixQualifiedUserId } from "../target-ids.js";
|
|
6
|
+
import { normalizeMatrixUserId } from "./allowlist.js";
|
|
7
|
+
import {
|
|
8
|
+
addAllowlistUserEntriesFromConfigEntry,
|
|
9
|
+
buildAllowlistResolutionSummary,
|
|
10
|
+
canonicalizeAllowlistWithResolvedIds,
|
|
11
|
+
patchAllowlistUsersInConfigEntries,
|
|
12
|
+
summarizeMapping,
|
|
13
|
+
type RuntimeEnv,
|
|
14
|
+
} from "./runtime-api.js";
|
|
15
|
+
|
|
16
|
+
type MatrixRoomsConfig = Record<string, MatrixRoomConfig>;
|
|
17
|
+
type ResolveMatrixTargetsFn = typeof resolveMatrixTargets;
|
|
18
|
+
|
|
19
|
+
export type MatrixResolvedAllowlistEntry = {
|
|
20
|
+
input: string;
|
|
21
|
+
id: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type MatrixResolvedUserAllowlist = {
|
|
25
|
+
entries: string[];
|
|
26
|
+
resolvedEntries: MatrixResolvedAllowlistEntry[];
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function normalizeMatrixUserLookupEntry(raw: string): string {
|
|
30
|
+
return raw
|
|
31
|
+
.replace(/^matrix:/i, "")
|
|
32
|
+
.replace(/^user:/i, "")
|
|
33
|
+
.trim();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeMatrixRoomLookupEntry(raw: string): string {
|
|
37
|
+
return raw
|
|
38
|
+
.replace(/^matrix:/i, "")
|
|
39
|
+
.replace(/^(room|channel):/i, "")
|
|
40
|
+
.trim();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function filterResolvedMatrixAllowlistEntries(entries: string[]): string[] {
|
|
44
|
+
return entries.filter((entry) => {
|
|
45
|
+
const trimmed = entry.trim();
|
|
46
|
+
if (!trimmed) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (trimmed === "*") {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return isMatrixQualifiedUserId(normalizeMatrixUserLookupEntry(trimmed));
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function filterFailClosedMatrixAllowlistEntries(entries: string[]): string[] {
|
|
57
|
+
return entries.filter((entry) => entry.trim().length > 0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function listResolvedMatrixAllowlistEntries(params: {
|
|
61
|
+
entries: Array<string | number>;
|
|
62
|
+
resolvedMap: Map<string, { resolved: boolean; id?: string }>;
|
|
63
|
+
}): MatrixResolvedAllowlistEntry[] {
|
|
64
|
+
const resolvedEntries: MatrixResolvedAllowlistEntry[] = [];
|
|
65
|
+
const seen = new Set<string>();
|
|
66
|
+
for (const entry of params.entries) {
|
|
67
|
+
const input = String(entry).trim();
|
|
68
|
+
if (!input || seen.has(input)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
seen.add(input);
|
|
72
|
+
const resolved = params.resolvedMap.get(input);
|
|
73
|
+
if (!resolved?.resolved || !resolved.id) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const id = normalizeMatrixUserId(resolved.id);
|
|
77
|
+
if (isMatrixQualifiedUserId(id)) {
|
|
78
|
+
resolvedEntries.push({ input, id });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return resolvedEntries;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function normalizeConfiguredMatrixAllowlistEntries(
|
|
85
|
+
entries?: ReadonlyArray<string | number>,
|
|
86
|
+
): string[] {
|
|
87
|
+
const normalized: string[] = [];
|
|
88
|
+
for (const entry of entries ?? []) {
|
|
89
|
+
const trimmed = String(entry).trim();
|
|
90
|
+
if (trimmed) {
|
|
91
|
+
normalized.push(trimmed);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return normalized;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isMatrixDangerousNameMatchingEnabled(params: {
|
|
98
|
+
cfg: CoreConfig;
|
|
99
|
+
accountId?: string | null;
|
|
100
|
+
}): boolean {
|
|
101
|
+
return isDangerousNameMatchingEnabled(
|
|
102
|
+
resolveMatrixAccountConfig({
|
|
103
|
+
cfg: params.cfg,
|
|
104
|
+
accountId: params.accountId,
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function addUniqueMatrixAllowlistEntry(params: {
|
|
110
|
+
entries: string[];
|
|
111
|
+
seen: Set<string>;
|
|
112
|
+
entry: string;
|
|
113
|
+
}): void {
|
|
114
|
+
const trimmed = params.entry.trim();
|
|
115
|
+
if (!trimmed) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const key = trimmed.toLowerCase();
|
|
119
|
+
if (params.seen.has(key)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
params.seen.add(key);
|
|
123
|
+
params.entries.push(trimmed);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function resolveStableMatrixMonitorUserEntries(entries: Array<string | number>) {
|
|
127
|
+
const directMatches: Array<{ input: string; resolved: boolean; id?: string }> = [];
|
|
128
|
+
|
|
129
|
+
for (const entry of entries) {
|
|
130
|
+
const input = String(entry).trim();
|
|
131
|
+
if (!input) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const query = normalizeMatrixUserLookupEntry(input);
|
|
135
|
+
if (!query || query === "*") {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
directMatches.push(
|
|
139
|
+
isMatrixQualifiedUserId(query)
|
|
140
|
+
? {
|
|
141
|
+
input,
|
|
142
|
+
resolved: true,
|
|
143
|
+
id: normalizeMatrixUserId(query),
|
|
144
|
+
}
|
|
145
|
+
: {
|
|
146
|
+
input,
|
|
147
|
+
resolved: false,
|
|
148
|
+
},
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return buildAllowlistResolutionSummary(directMatches);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function logStableMatrixAllowlistUnresolved(params: {
|
|
156
|
+
label: string;
|
|
157
|
+
unresolved: string[];
|
|
158
|
+
runtime: RuntimeEnv;
|
|
159
|
+
}): void {
|
|
160
|
+
if (params.unresolved.length === 0) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
summarizeMapping(params.label, [], params.unresolved, params.runtime);
|
|
164
|
+
params.runtime.log?.(
|
|
165
|
+
`${params.label} entries must be full Matrix IDs (example: @user:server). Unresolved entries will not match any sender. To match Matrix display names, set channels.matrix.dangerouslyAllowNameMatching=true.`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function resolveStableMatrixMonitorUserAllowlist(params: {
|
|
170
|
+
allowList: string[];
|
|
171
|
+
failClosedOnUnresolved?: boolean;
|
|
172
|
+
label: string;
|
|
173
|
+
runtime: RuntimeEnv;
|
|
174
|
+
}): MatrixResolvedUserAllowlist {
|
|
175
|
+
const allowList = params.allowList;
|
|
176
|
+
const resolution = resolveStableMatrixMonitorUserEntries(allowList);
|
|
177
|
+
const canonicalized = canonicalizeAllowlistWithResolvedIds({
|
|
178
|
+
existing: allowList,
|
|
179
|
+
resolvedMap: resolution.resolvedMap,
|
|
180
|
+
});
|
|
181
|
+
logStableMatrixAllowlistUnresolved({
|
|
182
|
+
label: params.label,
|
|
183
|
+
unresolved: resolution.unresolved,
|
|
184
|
+
runtime: params.runtime,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
entries: params.failClosedOnUnresolved
|
|
189
|
+
? filterFailClosedMatrixAllowlistEntries(canonicalized)
|
|
190
|
+
: filterResolvedMatrixAllowlistEntries(canonicalized),
|
|
191
|
+
resolvedEntries: listResolvedMatrixAllowlistEntries({
|
|
192
|
+
entries: allowList,
|
|
193
|
+
resolvedMap: resolution.resolvedMap,
|
|
194
|
+
}),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function resolveMatrixMonitorUserEntries(params: {
|
|
199
|
+
cfg: CoreConfig;
|
|
200
|
+
accountId?: string | null;
|
|
201
|
+
entries: Array<string | number>;
|
|
202
|
+
runtime: RuntimeEnv;
|
|
203
|
+
resolveTargets: ResolveMatrixTargetsFn;
|
|
204
|
+
}) {
|
|
205
|
+
const directMatches: Array<{ input: string; resolved: boolean; id?: string }> = [];
|
|
206
|
+
const pending: Array<{ input: string; query: string }> = [];
|
|
207
|
+
|
|
208
|
+
for (const entry of params.entries) {
|
|
209
|
+
const input = String(entry).trim();
|
|
210
|
+
if (!input) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const query = normalizeMatrixUserLookupEntry(input);
|
|
214
|
+
if (!query || query === "*") {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (isMatrixQualifiedUserId(query)) {
|
|
218
|
+
directMatches.push({
|
|
219
|
+
input,
|
|
220
|
+
resolved: true,
|
|
221
|
+
id: normalizeMatrixUserId(query),
|
|
222
|
+
});
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
pending.push({ input, query });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const pendingResolved =
|
|
229
|
+
pending.length === 0
|
|
230
|
+
? []
|
|
231
|
+
: await params.resolveTargets({
|
|
232
|
+
cfg: params.cfg,
|
|
233
|
+
accountId: params.accountId,
|
|
234
|
+
inputs: pending.map((entry) => entry.query),
|
|
235
|
+
kind: "user",
|
|
236
|
+
runtime: params.runtime,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
pendingResolved.forEach((entry, index) => {
|
|
240
|
+
const source = pending[index];
|
|
241
|
+
if (!source) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
directMatches.push({
|
|
245
|
+
input: source.input,
|
|
246
|
+
resolved: entry.resolved,
|
|
247
|
+
id: entry.id ? normalizeMatrixUserId(entry.id) : undefined,
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
return buildAllowlistResolutionSummary(directMatches);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function resolveMatrixMonitorUserAllowlist(params: {
|
|
255
|
+
cfg: CoreConfig;
|
|
256
|
+
accountId?: string | null;
|
|
257
|
+
label: string;
|
|
258
|
+
list?: Array<string | number>;
|
|
259
|
+
failClosedOnUnresolved?: boolean;
|
|
260
|
+
runtime: RuntimeEnv;
|
|
261
|
+
resolveTargets: ResolveMatrixTargetsFn;
|
|
262
|
+
}): Promise<MatrixResolvedUserAllowlist> {
|
|
263
|
+
const allowList = (params.list ?? []).map(String);
|
|
264
|
+
if (allowList.length === 0) {
|
|
265
|
+
return { entries: allowList, resolvedEntries: [] };
|
|
266
|
+
}
|
|
267
|
+
if (
|
|
268
|
+
!isMatrixDangerousNameMatchingEnabled({
|
|
269
|
+
cfg: params.cfg,
|
|
270
|
+
accountId: params.accountId,
|
|
271
|
+
})
|
|
272
|
+
) {
|
|
273
|
+
return resolveStableMatrixMonitorUserAllowlist({
|
|
274
|
+
allowList,
|
|
275
|
+
failClosedOnUnresolved: params.failClosedOnUnresolved,
|
|
276
|
+
label: params.label,
|
|
277
|
+
runtime: params.runtime,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const resolution = await resolveMatrixMonitorUserEntries({
|
|
282
|
+
cfg: params.cfg,
|
|
283
|
+
accountId: params.accountId,
|
|
284
|
+
entries: allowList,
|
|
285
|
+
runtime: params.runtime,
|
|
286
|
+
resolveTargets: params.resolveTargets,
|
|
287
|
+
});
|
|
288
|
+
const canonicalized = canonicalizeAllowlistWithResolvedIds({
|
|
289
|
+
existing: allowList,
|
|
290
|
+
resolvedMap: resolution.resolvedMap,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
summarizeMapping(params.label, resolution.mapping, resolution.unresolved, params.runtime);
|
|
294
|
+
if (resolution.unresolved.length > 0) {
|
|
295
|
+
params.runtime.log?.(
|
|
296
|
+
`${params.label} entries must be full Matrix IDs (example: @user:server). Unresolved entries will not match any sender.`,
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
entries: params.failClosedOnUnresolved
|
|
302
|
+
? filterFailClosedMatrixAllowlistEntries(canonicalized)
|
|
303
|
+
: filterResolvedMatrixAllowlistEntries(canonicalized),
|
|
304
|
+
resolvedEntries: listResolvedMatrixAllowlistEntries({
|
|
305
|
+
entries: allowList,
|
|
306
|
+
resolvedMap: resolution.resolvedMap,
|
|
307
|
+
}),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export async function resolveMatrixMonitorLiveUserAllowlist(params: {
|
|
312
|
+
cfg: CoreConfig;
|
|
313
|
+
accountId?: string | null;
|
|
314
|
+
entries?: ReadonlyArray<string | number>;
|
|
315
|
+
failClosedOnUnresolved?: boolean;
|
|
316
|
+
startupResolvedEntries?: readonly MatrixResolvedAllowlistEntry[];
|
|
317
|
+
runtime: RuntimeEnv;
|
|
318
|
+
resolveTargets?: ResolveMatrixTargetsFn;
|
|
319
|
+
}): Promise<string[]> {
|
|
320
|
+
const liveEntries = normalizeConfiguredMatrixAllowlistEntries(params.entries);
|
|
321
|
+
if (liveEntries.length === 0) {
|
|
322
|
+
return [];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const allowNameMatching = isMatrixDangerousNameMatchingEnabled({
|
|
326
|
+
cfg: params.cfg,
|
|
327
|
+
accountId: params.accountId,
|
|
328
|
+
});
|
|
329
|
+
const effective: string[] = [];
|
|
330
|
+
const seen = new Set<string>();
|
|
331
|
+
const startupByInput = new Map(
|
|
332
|
+
(params.startupResolvedEntries ?? []).map((entry) => [entry.input, entry.id] as const),
|
|
333
|
+
);
|
|
334
|
+
const pending: string[] = [];
|
|
335
|
+
|
|
336
|
+
for (const entry of liveEntries) {
|
|
337
|
+
const query = normalizeMatrixUserLookupEntry(entry);
|
|
338
|
+
if (entry === "*") {
|
|
339
|
+
addUniqueMatrixAllowlistEntry({ entries: effective, seen, entry });
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
if (isMatrixQualifiedUserId(query)) {
|
|
343
|
+
addUniqueMatrixAllowlistEntry({
|
|
344
|
+
entries: effective,
|
|
345
|
+
seen,
|
|
346
|
+
entry: normalizeMatrixUserId(query),
|
|
347
|
+
});
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const startupId = startupByInput.get(entry);
|
|
351
|
+
if (allowNameMatching && startupId) {
|
|
352
|
+
addUniqueMatrixAllowlistEntry({ entries: effective, seen, entry: startupId });
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (allowNameMatching) {
|
|
356
|
+
pending.push(entry);
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
if (params.failClosedOnUnresolved) {
|
|
360
|
+
addUniqueMatrixAllowlistEntry({ entries: effective, seen, entry });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (pending.length === 0) {
|
|
365
|
+
return effective;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const resolution = await resolveMatrixMonitorUserEntries({
|
|
369
|
+
cfg: params.cfg,
|
|
370
|
+
accountId: params.accountId,
|
|
371
|
+
entries: pending,
|
|
372
|
+
runtime: params.runtime,
|
|
373
|
+
resolveTargets: params.resolveTargets ?? resolveMatrixTargets,
|
|
374
|
+
});
|
|
375
|
+
const canonicalized = canonicalizeAllowlistWithResolvedIds({
|
|
376
|
+
existing: pending,
|
|
377
|
+
resolvedMap: resolution.resolvedMap,
|
|
378
|
+
});
|
|
379
|
+
const resolvedEntries = params.failClosedOnUnresolved
|
|
380
|
+
? filterFailClosedMatrixAllowlistEntries(canonicalized)
|
|
381
|
+
: filterResolvedMatrixAllowlistEntries(canonicalized);
|
|
382
|
+
for (const entry of resolvedEntries) {
|
|
383
|
+
addUniqueMatrixAllowlistEntry({ entries: effective, seen, entry });
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return effective;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async function resolveMatrixMonitorRoomsConfig(params: {
|
|
390
|
+
cfg: CoreConfig;
|
|
391
|
+
accountId?: string | null;
|
|
392
|
+
roomsConfig?: MatrixRoomsConfig;
|
|
393
|
+
runtime: RuntimeEnv;
|
|
394
|
+
resolveTargets: ResolveMatrixTargetsFn;
|
|
395
|
+
}): Promise<MatrixRoomsConfig | undefined> {
|
|
396
|
+
const roomsConfig = params.roomsConfig;
|
|
397
|
+
if (!roomsConfig || Object.keys(roomsConfig).length === 0) {
|
|
398
|
+
return roomsConfig;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const mapping: string[] = [];
|
|
402
|
+
const unresolved: string[] = [];
|
|
403
|
+
const nextRooms: MatrixRoomsConfig = {};
|
|
404
|
+
const allowNameMatching = isMatrixDangerousNameMatchingEnabled({
|
|
405
|
+
cfg: params.cfg,
|
|
406
|
+
accountId: params.accountId,
|
|
407
|
+
});
|
|
408
|
+
if (roomsConfig["*"]) {
|
|
409
|
+
nextRooms["*"] = roomsConfig["*"];
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const pending: Array<{ input: string; query: string; config: MatrixRoomConfig }> = [];
|
|
413
|
+
for (const [entry, roomConfig] of Object.entries(roomsConfig)) {
|
|
414
|
+
if (entry === "*") {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
const input = entry.trim();
|
|
418
|
+
if (!input) {
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
const cleaned = normalizeMatrixRoomLookupEntry(input);
|
|
422
|
+
if (!cleaned) {
|
|
423
|
+
unresolved.push(entry);
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
if (cleaned.startsWith("!") && cleaned.includes(":")) {
|
|
427
|
+
if (!nextRooms[cleaned]) {
|
|
428
|
+
nextRooms[cleaned] = roomConfig;
|
|
429
|
+
}
|
|
430
|
+
if (cleaned !== input) {
|
|
431
|
+
mapping.push(`${input}→${cleaned}`);
|
|
432
|
+
}
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
if (!cleaned.startsWith("#") && !allowNameMatching) {
|
|
436
|
+
unresolved.push(input);
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
pending.push({ input, query: cleaned, config: roomConfig });
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (pending.length > 0) {
|
|
443
|
+
const resolved = await params.resolveTargets({
|
|
444
|
+
cfg: params.cfg,
|
|
445
|
+
accountId: params.accountId,
|
|
446
|
+
inputs: pending.map((entry) => entry.query),
|
|
447
|
+
kind: "group",
|
|
448
|
+
runtime: params.runtime,
|
|
449
|
+
});
|
|
450
|
+
resolved.forEach((entry, index) => {
|
|
451
|
+
const source = pending[index];
|
|
452
|
+
if (!source) {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
if (entry.resolved && entry.id) {
|
|
456
|
+
const roomKey = normalizeMatrixRoomLookupEntry(entry.id);
|
|
457
|
+
if (!nextRooms[roomKey]) {
|
|
458
|
+
nextRooms[roomKey] = source.config;
|
|
459
|
+
}
|
|
460
|
+
mapping.push(`${source.input}→${roomKey}`);
|
|
461
|
+
} else {
|
|
462
|
+
unresolved.push(source.input);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
summarizeMapping("matrix rooms", mapping, unresolved, params.runtime);
|
|
468
|
+
if (unresolved.length > 0) {
|
|
469
|
+
params.runtime.log?.(
|
|
470
|
+
"matrix rooms must be room IDs or aliases (example: !room:server or #alias:server). Unresolved entries are ignored.",
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const roomUsers = new Set<string>();
|
|
475
|
+
for (const roomConfig of Object.values(nextRooms)) {
|
|
476
|
+
addAllowlistUserEntriesFromConfigEntry(roomUsers, roomConfig);
|
|
477
|
+
}
|
|
478
|
+
if (roomUsers.size === 0) {
|
|
479
|
+
return nextRooms;
|
|
480
|
+
}
|
|
481
|
+
if (!allowNameMatching) {
|
|
482
|
+
const resolution = resolveStableMatrixMonitorUserEntries(Array.from(roomUsers));
|
|
483
|
+
logStableMatrixAllowlistUnresolved({
|
|
484
|
+
label: "matrix room users",
|
|
485
|
+
unresolved: resolution.unresolved,
|
|
486
|
+
runtime: params.runtime,
|
|
487
|
+
});
|
|
488
|
+
const patched = patchAllowlistUsersInConfigEntries({
|
|
489
|
+
entries: nextRooms,
|
|
490
|
+
resolvedMap: resolution.resolvedMap,
|
|
491
|
+
strategy: "canonicalize",
|
|
492
|
+
});
|
|
493
|
+
return patched;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const resolution = await resolveMatrixMonitorUserEntries({
|
|
497
|
+
cfg: params.cfg,
|
|
498
|
+
accountId: params.accountId,
|
|
499
|
+
entries: Array.from(roomUsers),
|
|
500
|
+
runtime: params.runtime,
|
|
501
|
+
resolveTargets: params.resolveTargets,
|
|
502
|
+
});
|
|
503
|
+
summarizeMapping("matrix room users", resolution.mapping, resolution.unresolved, params.runtime);
|
|
504
|
+
if (resolution.unresolved.length > 0) {
|
|
505
|
+
params.runtime.log?.(
|
|
506
|
+
"matrix room users entries must be full Matrix IDs (example: @user:server). Unresolved entries will not match any sender.",
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const patched = patchAllowlistUsersInConfigEntries({
|
|
511
|
+
entries: nextRooms,
|
|
512
|
+
resolvedMap: resolution.resolvedMap,
|
|
513
|
+
strategy: "canonicalize",
|
|
514
|
+
});
|
|
515
|
+
return patched;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
export async function resolveMatrixMonitorConfig(params: {
|
|
519
|
+
cfg: CoreConfig;
|
|
520
|
+
accountId?: string | null;
|
|
521
|
+
allowFrom?: Array<string | number>;
|
|
522
|
+
groupAllowFrom?: Array<string | number>;
|
|
523
|
+
roomsConfig?: MatrixRoomsConfig;
|
|
524
|
+
runtime: RuntimeEnv;
|
|
525
|
+
resolveTargets?: ResolveMatrixTargetsFn;
|
|
526
|
+
}): Promise<{
|
|
527
|
+
allowFrom: string[];
|
|
528
|
+
allowFromResolvedEntries: MatrixResolvedAllowlistEntry[];
|
|
529
|
+
groupAllowFrom: string[];
|
|
530
|
+
groupAllowFromResolvedEntries: MatrixResolvedAllowlistEntry[];
|
|
531
|
+
roomsConfig?: MatrixRoomsConfig;
|
|
532
|
+
}> {
|
|
533
|
+
const resolveTargets = params.resolveTargets ?? resolveMatrixTargets;
|
|
534
|
+
|
|
535
|
+
const [allowFrom, groupAllowFrom, roomsConfig] = await Promise.all([
|
|
536
|
+
resolveMatrixMonitorUserAllowlist({
|
|
537
|
+
cfg: params.cfg,
|
|
538
|
+
accountId: params.accountId,
|
|
539
|
+
label: "matrix dm allowlist",
|
|
540
|
+
list: params.allowFrom,
|
|
541
|
+
runtime: params.runtime,
|
|
542
|
+
resolveTargets,
|
|
543
|
+
}),
|
|
544
|
+
resolveMatrixMonitorUserAllowlist({
|
|
545
|
+
cfg: params.cfg,
|
|
546
|
+
accountId: params.accountId,
|
|
547
|
+
label: "matrix group allowlist",
|
|
548
|
+
list: params.groupAllowFrom,
|
|
549
|
+
failClosedOnUnresolved: true,
|
|
550
|
+
runtime: params.runtime,
|
|
551
|
+
resolveTargets,
|
|
552
|
+
}),
|
|
553
|
+
resolveMatrixMonitorRoomsConfig({
|
|
554
|
+
cfg: params.cfg,
|
|
555
|
+
accountId: params.accountId,
|
|
556
|
+
roomsConfig: params.roomsConfig,
|
|
557
|
+
runtime: params.runtime,
|
|
558
|
+
resolveTargets,
|
|
559
|
+
}),
|
|
560
|
+
]);
|
|
561
|
+
|
|
562
|
+
return {
|
|
563
|
+
allowFrom: allowFrom.entries,
|
|
564
|
+
allowFromResolvedEntries: allowFrom.resolvedEntries,
|
|
565
|
+
groupAllowFrom: groupAllowFrom.entries,
|
|
566
|
+
groupAllowFromResolvedEntries: groupAllowFrom.resolvedEntries,
|
|
567
|
+
roomsConfig,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatMatrixMessageText,
|
|
3
|
+
resolveMatrixMessageAttachment,
|
|
4
|
+
resolveMatrixMessageBody,
|
|
5
|
+
} from "../media-text.js";
|
|
6
|
+
import {
|
|
7
|
+
formatPollAsText,
|
|
8
|
+
isPollStartType,
|
|
9
|
+
parsePollStartContent,
|
|
10
|
+
type PollStartContent,
|
|
11
|
+
} from "../poll-types.js";
|
|
12
|
+
import type { MatrixRawEvent } from "./types.js";
|
|
13
|
+
|
|
14
|
+
export function trimMatrixMaybeString(value: unknown): string | undefined {
|
|
15
|
+
if (typeof value !== "string") {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const trimmed = value.trim();
|
|
19
|
+
return trimmed || undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function summarizeMatrixMessageContextEvent(event: MatrixRawEvent): string | undefined {
|
|
23
|
+
if (isPollStartType(event.type)) {
|
|
24
|
+
const pollSummary = parsePollStartContent(event.content as PollStartContent);
|
|
25
|
+
if (pollSummary) {
|
|
26
|
+
return formatPollAsText(pollSummary);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const content = event.content as { body?: unknown; filename?: unknown; msgtype?: unknown };
|
|
31
|
+
return formatMatrixMessageText({
|
|
32
|
+
body: resolveMatrixMessageBody({
|
|
33
|
+
body: trimMatrixMaybeString(content.body),
|
|
34
|
+
filename: trimMatrixMaybeString(content.filename),
|
|
35
|
+
msgtype: trimMatrixMaybeString(content.msgtype),
|
|
36
|
+
}),
|
|
37
|
+
attachment: resolveMatrixMessageAttachment({
|
|
38
|
+
body: trimMatrixMaybeString(content.body),
|
|
39
|
+
filename: trimMatrixMaybeString(content.filename),
|
|
40
|
+
msgtype: trimMatrixMaybeString(content.msgtype),
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
}
|