fix(ci): trim slow task and gateway paths

This commit is contained in:
Vincent Koc
2026-04-16 13:34:14 -07:00
parent 56a9fd4b34
commit f835da1667
9 changed files with 191 additions and 120 deletions

View File

@@ -11,6 +11,8 @@ import {
resolveMattermostAccount,
type ResolvedMattermostAccount,
} from "./mattermost/accounts.js";
import type { MattermostSlashCommandConfig } from "./mattermost/slash-commands.js";
import type { MattermostConfig } from "./types.js";
export const mattermostMeta = {
id: "mattermost",
@@ -25,6 +27,8 @@ export const mattermostMeta = {
quickstartAllowFrom: true,
} as const;
const DEFAULT_SLASH_CALLBACK_PATH = "/api/channels/mattermost/command";
export function normalizeMattermostAllowEntry(entry: string): string {
return normalizeLowercaseStringOrEmpty(
entry
@@ -46,6 +50,63 @@ export function formatMattermostAllowEntry(entry: string): string {
return normalizeLowercaseStringOrEmpty(trimmed.replace(/^(mattermost|user):/i, ""));
}
export function collectMattermostSlashCallbackPaths(
raw?: Partial<MattermostSlashCommandConfig>,
): string[] {
const callbackPath = (() => {
const trimmed = raw?.callbackPath?.trim();
if (!trimmed) {
return DEFAULT_SLASH_CALLBACK_PATH;
}
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
})();
const callbackUrl = raw?.callbackUrl?.trim();
const paths = new Set<string>([callbackPath]);
if (callbackUrl) {
try {
const pathname = new URL(callbackUrl).pathname;
if (pathname) {
paths.add(pathname);
}
} catch {
// Keep the normalized callback path when the configured URL is invalid.
}
}
return [...paths];
}
export function resolveMattermostGatewayAuthBypassPaths(cfg: {
channels?: Record<string, unknown>;
}): string[] {
const base = cfg.channels?.mattermost as MattermostConfig | undefined;
const callbackPaths = new Set(
collectMattermostSlashCallbackPaths(
base?.commands as Partial<MattermostSlashCommandConfig> | undefined,
).filter(
(path) =>
path === "/api/channels/mattermost/command" || path.startsWith("/api/channels/mattermost/"),
),
);
const accounts = base?.accounts ?? {};
for (const account of Object.values(accounts)) {
const accountConfig =
account && typeof account === "object" && !Array.isArray(account)
? (account as {
commands?: Parameters<typeof collectMattermostSlashCallbackPaths>[0];
})
: undefined;
for (const path of collectMattermostSlashCallbackPaths(accountConfig?.commands)) {
if (
path === "/api/channels/mattermost/command" ||
path.startsWith("/api/channels/mattermost/")
) {
callbackPaths.add(path);
}
}
}
return [...callbackPaths];
}
export const mattermostConfigAdapter = createScopedChannelConfigAdapter<ResolvedMattermostAccount>({
sectionKey: "mattermost",
listAccountIds: listMattermostAccountIds,

View File

@@ -4,6 +4,7 @@ import {
isMattermostConfigured,
mattermostConfigAdapter,
mattermostMeta,
resolveMattermostGatewayAuthBypassPaths,
} from "./channel-config-shared.js";
import { MattermostChannelConfigSchema } from "./config-surface.js";
import { type ResolvedMattermostAccount } from "./mattermost/accounts.js";
@@ -29,6 +30,9 @@ export const mattermostSetupPlugin: ChannelPlugin<ResolvedMattermostAccount> = {
isConfigured: isMattermostConfigured,
describeAccount: describeMattermostAccount,
},
gateway: {
resolveGatewayAuthBypassPaths: ({ cfg }) => resolveMattermostGatewayAuthBypassPaths(cfg),
},
setup: mattermostSetupAdapter,
setupWizard: mattermostSetupWizard,
};

View File

@@ -30,6 +30,7 @@ import {
mattermostConfigAdapter,
mattermostMeta as meta,
normalizeMattermostAllowEntry as normalizeAllowEntry,
resolveMattermostGatewayAuthBypassPaths,
} from "./channel-config-shared.js";
import { MattermostChannelConfigSchema } from "./config-surface.js";
import { mattermostDoctor } from "./doctor.js";
@@ -41,7 +42,6 @@ import {
resolveMattermostReplyToMode,
type ResolvedMattermostAccount,
} from "./mattermost/accounts.js";
import type { MattermostSlashCommandConfig } from "./mattermost/slash-commands.js";
import { looksLikeMattermostTargetId, normalizeMattermostMessagingTarget } from "./normalize.js";
import { collectRuntimeConfigAssignments, secretTargetRegistryEntries } from "./secret-contract.js";
import { resolveMattermostOutboundSessionRoute } from "./session-route.js";
@@ -51,33 +51,6 @@ import type { MattermostConfig } from "./types.js";
const loadMattermostChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime.js"));
const DEFAULT_SLASH_CALLBACK_PATH = "/api/channels/mattermost/command";
function collectMattermostSlashCallbackPaths(
raw?: Partial<MattermostSlashCommandConfig>,
): string[] {
const callbackPath = (() => {
const trimmed = raw?.callbackPath?.trim();
if (!trimmed) {
return DEFAULT_SLASH_CALLBACK_PATH;
}
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
})();
const callbackUrl = raw?.callbackUrl?.trim();
const paths = new Set<string>([callbackPath]);
if (callbackUrl) {
try {
const pathname = new URL(callbackUrl).pathname;
if (pathname) {
paths.add(pathname);
}
} catch {
// Keep the normalized callback path when the configured URL is invalid.
}
}
return [...paths];
}
const mattermostSecurityAdapter = createRestrictSendersChannelSecurity<ResolvedMattermostAccount>({
channelKey: "mattermost",
resolveDmPolicy: (account) => account.config.dmPolicy,
@@ -375,36 +348,7 @@ export const mattermostPlugin: ChannelPlugin<ResolvedMattermostAccount> = create
}),
}),
gateway: {
resolveGatewayAuthBypassPaths: ({ cfg }) => {
const base = cfg.channels?.mattermost;
const callbackPaths = new Set(
collectMattermostSlashCallbackPaths(
base?.commands as Partial<MattermostSlashCommandConfig> | undefined,
).filter(
(path) =>
path === "/api/channels/mattermost/command" ||
path.startsWith("/api/channels/mattermost/"),
),
);
const accounts = base?.accounts ?? {};
for (const account of Object.values(accounts)) {
const accountConfig =
account && typeof account === "object" && !Array.isArray(account)
? (account as {
commands?: Parameters<typeof collectMattermostSlashCallbackPaths>[0];
})
: undefined;
for (const path of collectMattermostSlashCallbackPaths(accountConfig?.commands)) {
if (
path === "/api/channels/mattermost/command" ||
path.startsWith("/api/channels/mattermost/")
) {
callbackPaths.add(path);
}
}
}
return [...callbackPaths];
},
resolveGatewayAuthBypassPaths: ({ cfg }) => resolveMattermostGatewayAuthBypassPaths(cfg),
startAccount: async (ctx) => {
const account = ctx.account;
const statusSink = createAccountStatusSink({