@helyx/bot 1.3.0 → 1.4.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +92 -28
  2. package/README.md +65 -11
  3. package/dist/cloud-connector.d.ts +11 -4
  4. package/dist/cloud-connector.js +52 -15
  5. package/dist/cloud-control-dispatcher.d.ts +8 -3
  6. package/dist/cloud-control-dispatcher.js +62 -4
  7. package/dist/control-errors.d.ts +4 -0
  8. package/dist/control-errors.js +8 -0
  9. package/dist/control-server-schemas.d.ts +84 -0
  10. package/dist/control-server-schemas.js +101 -0
  11. package/dist/control-server.d.ts +21 -7
  12. package/dist/control-server.js +88 -132
  13. package/dist/core-retention.d.ts +26 -0
  14. package/dist/core-retention.js +49 -0
  15. package/dist/creator-guild-join-service.d.ts +25 -0
  16. package/dist/creator-guild-join-service.js +218 -0
  17. package/dist/creator-invite-service.d.ts +37 -0
  18. package/dist/creator-invite-service.js +686 -0
  19. package/dist/creator-onboarding-control.d.ts +12 -0
  20. package/dist/creator-onboarding-control.js +65 -0
  21. package/dist/creator-onboarding-platform.d.ts +20 -0
  22. package/dist/creator-onboarding-platform.js +58 -0
  23. package/dist/dashboard-action-control.d.ts +2 -2
  24. package/dist/dashboard-action-control.js +2 -3
  25. package/dist/database-bootstrap.d.ts +36 -0
  26. package/dist/database-bootstrap.js +101 -0
  27. package/dist/developer-operations-module.d.ts +1 -0
  28. package/dist/developer-operations-module.js +34 -16
  29. package/dist/discord-owned-message-service.d.ts +1 -0
  30. package/dist/discord-owned-message-service.js +3 -0
  31. package/dist/guild-command-read-service.d.ts +8 -3
  32. package/dist/guild-command-read-service.js +14 -7
  33. package/dist/guild-command-release.d.ts +15 -8
  34. package/dist/guild-command-release.js +10 -3
  35. package/dist/guild-command-worker.d.ts +17 -4
  36. package/dist/guild-command-worker.js +17 -6
  37. package/dist/guilds.d.ts +24 -3
  38. package/dist/guilds.js +185 -64
  39. package/dist/hosted-server-moderation.d.ts +2 -2
  40. package/dist/hosted-server-moderation.js +10 -4
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.js +200 -81
  43. package/dist/interactions.js +16 -3
  44. package/dist/module-configuration.d.ts +1 -1
  45. package/dist/module-configuration.js +5 -2
  46. package/dist/module-logging.d.ts +8 -3
  47. package/dist/module-logging.js +13 -7
  48. package/dist/modules.d.ts +1 -0
  49. package/dist/modules.js +8 -1
  50. package/dist/mysql-runtime-persistence.d.ts +46 -0
  51. package/dist/mysql-runtime-persistence.js +91 -0
  52. package/dist/oauth-module.js +2 -2
  53. package/dist/oauth-service.d.ts +7 -0
  54. package/dist/oauth-service.js +3 -0
  55. package/dist/scheduled-task-runner.d.ts +9 -85
  56. package/dist/scheduled-task-runner.js +1 -1
  57. package/dist/shard-contracts.d.ts +135 -0
  58. package/dist/shard-contracts.js +13 -1
  59. package/dist/shard-router.d.ts +2 -1
  60. package/dist/shard-router.js +7 -0
  61. package/dist/shard-supervisor.js +43 -9
  62. package/dist/shard-worker.d.ts +5 -2
  63. package/dist/shard-worker.js +46 -5
  64. package/dist/supervisor-cloud-directory.d.ts +9 -3
  65. package/dist/supervisor-cloud-directory.js +8 -12
  66. package/dist/trivia-data-provider.d.ts +11 -0
  67. package/dist/trivia-data-provider.js +46 -26
  68. package/dist/verification-service.d.ts +2 -2
  69. package/dist/verification-service.js +6 -3
  70. package/documentation/README.md +5 -3
  71. package/documentation/examples/.env.example +15 -11
  72. package/documentation/guides/getting-started.md +29 -12
  73. package/documentation/guides/privacy-and-support.md +6 -5
  74. package/documentation/guides/self-hosting.md +16 -11
  75. package/documentation/modules/auto-moderation.md +7 -5
  76. package/documentation/modules/building-a-module.md +48 -2
  77. package/documentation/modules/moderation.md +5 -5
  78. package/documentation/modules/publishing-a-module.md +6 -4
  79. package/documentation/modules/testing-a-module.md +39 -4
  80. package/documentation/reference/environment.md +43 -9
  81. package/documentation/runbooks/backup-and-recovery.md +26 -7
  82. package/documentation/runbooks/installation-and-upgrades.md +97 -27
  83. package/package.json +20 -16
package/dist/modules.d.ts CHANGED
@@ -10,6 +10,7 @@ interface LoadedDefinition {
10
10
  export interface ConfiguredModulePackage extends LoadedDefinition {
11
11
  packageRoot: string;
12
12
  }
13
+ export declare function assertConfiguredModuleDatabaseCompatibility(modules: readonly ConfiguredModulePackage[], engine: BotEnvironment["DATABASE_ENGINE"]): void;
13
14
  export declare const secureRandomSelectionWorkerKeyName = "HELYX_INTERNAL_SECURE_RANDOM_SELECTION_KEY";
14
15
  interface PlatformServiceEnvironment extends Pick<BotEnvironment, "HELYX_DATA_ENCRYPTION_KEY"> {
15
16
  HELYX_RUNTIME_PROFILE?: BotEnvironment["HELYX_RUNTIME_PROFILE"];
package/dist/modules.js CHANGED
@@ -1,10 +1,17 @@
1
- import { orderModuleManifests, parseModuleManifest, } from "@helyx/module-manifest";
1
+ import { getModuleDatabaseEngines, orderModuleManifests, parseModuleManifest, } from "@helyx/module-manifest";
2
2
  import { NEXUS_COMMAND_SPECS, NEXUS_ROOT_MODULE_ID, sharedCommandFamilySpec, sharedCommandPathSpec, } from "@helyx/sdk";
3
3
  import { createHmac } from "node:crypto";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import { createRequire } from "node:module";
6
6
  import { dirname } from "node:path";
7
7
  import { assertCommandPathContract } from "./command-path-contract.js";
8
+ export function assertConfiguredModuleDatabaseCompatibility(modules, engine) {
9
+ for (const { definition } of modules) {
10
+ if (!getModuleDatabaseEngines(definition.manifest).includes(engine)) {
11
+ throw new Error(`Module ${definition.manifest.id} does not support DATABASE_ENGINE=${engine}`);
12
+ }
13
+ }
14
+ }
8
15
  const officialModulePackage = /^@helyx\/module-[a-z0-9][a-z0-9-]*$/u;
9
16
  const giveawaysModuleId = "helyx.giveaways";
10
17
  const inviteTrackingModuleId = "helyx.invite-tracking";
@@ -0,0 +1,46 @@
1
+ import type { BotEnvironment } from "@helyx/config";
2
+ import type { GuildCommandRepository as MysqlGuildCommandRepository, InstallationRepository as MysqlInstallationRepository, MysqlPool, RuntimeStateRepository as MysqlRuntimeStateRepository } from "@helyx/database-mysql";
3
+ import type { MysqlMemberRoleGrantOwnershipStore, createMysqlPlatformServices } from "@helyx/platform";
4
+ import type { ModuleDefinition } from "@helyx/sdk";
5
+ import { type BotDatabaseHandle } from "./database-bootstrap.js";
6
+ import type { CloudConnectorStore } from "./cloud-control-dispatcher.js";
7
+ import { type BotControlPersistence } from "./control-server.js";
8
+ import { type CoreRetentionRepositories } from "./core-retention.js";
9
+ import type { GuildCommandReadRepositories } from "./guild-command-read-service.js";
10
+ import type { GuildCommandWorkerRepositories } from "./guild-command-worker.js";
11
+ import { type GuildTrackingPersistence } from "./guilds.js";
12
+ import type { ModuleLoggingRepositories } from "./module-logging.js";
13
+ import type { ConfiguredModulePackage } from "./modules.js";
14
+ import type { ScheduledTaskRepositoryContract } from "./scheduled-task-runner.js";
15
+ type MysqlRuntimeEnvironment = Pick<BotEnvironment, "DATABASE_ENGINE" | "DATABASE_URL" | "DATABASE_SSL" | "HELYX_RUNTIME_PROFILE" | "HELYX_SHARD_MODE" | "HELYX_HOSTED_MODERATION_ENABLED" | "HELYX_VERIFICATION_ENABLED" | "HELYX_PRIVACY_ENABLED" | "HELYX_PRIVACY_EXECUTOR_DATABASE_URL" | "HELYX_OAUTH_ENABLED" | "HELYX_ECKO_TRANSPORT_SECRET" | "HELYX_SUPPORT_STAFF_CHANNEL_ID" | "STRIPE_ENVIRONMENT">;
16
+ export interface MysqlBotRuntimePersistence {
17
+ /** The adapter owns this single pool and closes it via database.close(). */
18
+ readonly database: BotDatabaseHandle<{
19
+ pool: MysqlPool;
20
+ }>;
21
+ readonly pool: MysqlPool;
22
+ readonly cloudConnector: CloudConnectorStore;
23
+ readonly guildTracking: GuildTrackingPersistence;
24
+ readonly control: BotControlPersistence;
25
+ readonly coreRetention: CoreRetentionRepositories;
26
+ readonly scheduledTasks: ScheduledTaskRepositoryContract;
27
+ readonly commandWorker: GuildCommandWorkerRepositories;
28
+ readonly commandRead: GuildCommandReadRepositories;
29
+ readonly commandRelease: {
30
+ installations: Pick<MysqlInstallationRepository, "listActiveGuilds">;
31
+ commands: Pick<MysqlGuildCommandRepository, "getState" | "schedule">;
32
+ runtime: Pick<MysqlRuntimeStateRepository, "get" | "compareAndSet">;
33
+ };
34
+ readonly logging: ModuleLoggingRepositories;
35
+ readonly memberRoleOwnership: MysqlMemberRoleGrantOwnershipStore;
36
+ readonly createPlatformServices: (modules: readonly ModuleDefinition[], options?: Parameters<typeof createMysqlPlatformServices>[2]) => ReturnType<typeof createMysqlPlatformServices>;
37
+ }
38
+ export interface OpenMysqlBotRuntimePersistenceInput {
39
+ readonly environment: MysqlRuntimeEnvironment;
40
+ readonly modulePackages: readonly ConfiguredModulePackage[];
41
+ readonly applicationName?: string;
42
+ }
43
+ /** Connect, migrate, and compose ordinary self-host persistence from one pool. */
44
+ export declare function openMysqlBotRuntimePersistence(input: OpenMysqlBotRuntimePersistenceInput): Promise<MysqlBotRuntimePersistence>;
45
+ export {};
46
+ //# sourceMappingURL=mysql-runtime-persistence.d.ts.map
@@ -0,0 +1,91 @@
1
+ import { openBotDatabaseWithAdapter, } from "./database-bootstrap.js";
2
+ import { createMysqlBotControlPersistence, } from "./control-server.js";
3
+ import { createMysqlCoreRetentionRepositories, } from "./core-retention.js";
4
+ import { createMysqlGuildTrackingPersistence, } from "./guilds.js";
5
+ /** Connect, migrate, and compose ordinary self-host persistence from one pool. */
6
+ export async function openMysqlBotRuntimePersistence(input) {
7
+ assertMysqlRuntimeOptions(input.environment);
8
+ const mysql = await import("@helyx/database-mysql");
9
+ const adapter = mysql.createMysqlDatabaseAdapter({
10
+ repositories: (_executor, pool) => ({ pool }),
11
+ });
12
+ const database = await openBotDatabaseWithAdapter(input, adapter);
13
+ try {
14
+ const pool = database.session.repositories.pool;
15
+ const installations = new mysql.InstallationRepository(pool);
16
+ const commands = new mysql.GuildCommandRepository(pool);
17
+ const availability = new mysql.ModuleAvailabilityRepository(pool);
18
+ const runtime = new mysql.RuntimeStateRepository(pool);
19
+ const [guildTracking, control, coreRetention, platform] = await Promise.all([
20
+ createMysqlGuildTrackingPersistence(pool),
21
+ createMysqlBotControlPersistence(pool),
22
+ createMysqlCoreRetentionRepositories(pool),
23
+ import("@helyx/platform"),
24
+ ]);
25
+ return {
26
+ database,
27
+ pool,
28
+ cloudConnector: new mysql.CloudConnectorRepository(pool),
29
+ guildTracking,
30
+ control,
31
+ coreRetention,
32
+ scheduledTasks: new mysql.ScheduledTaskRepository(pool),
33
+ commandWorker: {
34
+ commands,
35
+ installations,
36
+ availability,
37
+ },
38
+ commandRead: { commands, installations },
39
+ commandRelease: { commands, installations, runtime },
40
+ logging: {
41
+ installations,
42
+ configuration: new mysql.ModuleConfigurationRepository(pool),
43
+ policies: new mysql.ModuleLoggingPolicyRepository(pool),
44
+ },
45
+ memberRoleOwnership: new platform.MysqlMemberRoleGrantOwnershipStore(pool),
46
+ createPlatformServices: (modules, options) => platform.createMysqlPlatformServices(pool, modules, {
47
+ ...options,
48
+ runtimeProfile: "self-hosted",
49
+ }),
50
+ };
51
+ }
52
+ catch (error) {
53
+ await database.close().catch(() => undefined);
54
+ throw error;
55
+ }
56
+ }
57
+ function assertMysqlRuntimeOptions(environment) {
58
+ if (environment.DATABASE_ENGINE !== "mysql") {
59
+ throw new Error("MySQL bot runtime requires DATABASE_ENGINE=mysql");
60
+ }
61
+ if (environment.HELYX_RUNTIME_PROFILE !== "self-hosted") {
62
+ throw new Error("MySQL bot runtime requires HELYX_RUNTIME_PROFILE=self-hosted");
63
+ }
64
+ if (environment.HELYX_SHARD_MODE !== "off") {
65
+ throw new Error("MySQL bot runtime does not support shard mode");
66
+ }
67
+ const unsupported = [
68
+ [
69
+ "HELYX_HOSTED_MODERATION_ENABLED",
70
+ environment.HELYX_HOSTED_MODERATION_ENABLED,
71
+ ],
72
+ ["HELYX_VERIFICATION_ENABLED", environment.HELYX_VERIFICATION_ENABLED],
73
+ ["HELYX_PRIVACY_ENABLED", environment.HELYX_PRIVACY_ENABLED],
74
+ [
75
+ "HELYX_PRIVACY_EXECUTOR_DATABASE_URL",
76
+ environment.HELYX_PRIVACY_EXECUTOR_DATABASE_URL,
77
+ ],
78
+ ["HELYX_OAUTH_ENABLED", environment.HELYX_OAUTH_ENABLED],
79
+ ["HELYX_ECKO_TRANSPORT_SECRET", environment.HELYX_ECKO_TRANSPORT_SECRET],
80
+ [
81
+ "HELYX_SUPPORT_STAFF_CHANNEL_ID",
82
+ environment.HELYX_SUPPORT_STAFF_CHANNEL_ID,
83
+ ],
84
+ ["STRIPE_ENVIRONMENT", environment.STRIPE_ENVIRONMENT],
85
+ ];
86
+ for (const [name, value] of unsupported) {
87
+ if (value)
88
+ throw new Error(`MySQL bot runtime does not support ${name}`);
89
+ }
90
+ }
91
+ //# sourceMappingURL=mysql-runtime-persistence.js.map
@@ -204,7 +204,7 @@ export function createOAuthModule() {
204
204
  text: [
205
205
  {
206
206
  content: result.outcome === "processing"
207
- ? `${providerName(result.provider)} access removal is already in progress. Helyx will finish it automatically.`
207
+ ? `${providerName(result.provider)} access removal is in progress. Helyx is handling local cleanup automatically. Provider-side revocation is not confirmed yet, so you can also remove Helyx from your ${providerName(result.provider)} connected-app settings. Run \`/helyx connections\` to check whether local access remains.`
208
208
  : result.outcome === "cleanup_pending"
209
209
  ? `${providerName(result.provider)} credentials were deleted. Helyx is still removing related roles and connection records.`
210
210
  : result.providerRevocation === "completed"
@@ -235,7 +235,7 @@ function unavailable() {
235
235
  componentsV2: {
236
236
  text: [
237
237
  {
238
- content: "OAuth access could not be updated right now. Nothing new was retained; please try again.",
238
+ content: "Helyx could not confirm the final result. The removal may still be finishing automatically. Run /helyx connections to check before trying again.",
239
239
  },
240
240
  ],
241
241
  },
@@ -2,6 +2,13 @@ import type { OAuthConnectionSummary, OAuthConnectionIdentity, OAuthEligibilityR
2
2
  export declare class HttpOAuthService implements OAuthService {
3
3
  #private;
4
4
  private readonly internalSecret;
5
+ resolveCreatorIdentity(input: {
6
+ provider: "twitch";
7
+ login: string;
8
+ }): Promise<{
9
+ userId: string;
10
+ login: string;
11
+ }>;
5
12
  constructor(baseUrl: string, internalSecret: string);
6
13
  listConnections(input: {
7
14
  discordUserId: string;
@@ -1,5 +1,8 @@
1
1
  export class HttpOAuthService {
2
2
  internalSecret;
3
+ resolveCreatorIdentity(input) {
4
+ return this.#request("/v1/internal/oauth/creator-identity", input);
5
+ }
3
6
  #baseUrl;
4
7
  constructor(baseUrl, internalSecret) {
5
8
  this.internalSecret = internalSecret;
@@ -1,91 +1,10 @@
1
- import { type CoalescedTaskRecord, type ScheduledTaskRecord, type ScheduledTaskDefinition, type SchedulerHealth } from "@helyx/database";
1
+ import { ScheduledTaskRepository, type ScheduledTaskDefinition, type SchedulerHealth } from "@helyx/database";
2
2
  import { type Logger, type ModuleDefinition, type ModuleScheduledTaskExecution, type ScheduledTaskExecutionResult, type ServiceAccess } from "@helyx/sdk";
3
3
  import type { Pool } from "pg";
4
4
  export interface ScheduledTaskRoute {
5
5
  (task: ModuleScheduledTaskExecution, signal: AbortSignal): Promise<ScheduledTaskExecutionResult>;
6
6
  }
7
- interface ScheduledTaskRepositoryContract {
8
- claimDue(input: {
9
- workerId: string;
10
- leaseMs: number;
11
- limit?: number;
12
- eligible?: readonly ScheduledTaskDefinition[];
13
- }): Promise<ScheduledTaskRecord[]>;
14
- claimCoalesced(input: {
15
- workerId: string;
16
- leaseMs: number;
17
- limit?: number;
18
- eligible?: readonly ScheduledTaskDefinition[];
19
- }): Promise<CoalescedTaskRecord[]>;
20
- heartbeat(input: {
21
- taskId: string;
22
- workerId: string;
23
- leaseGeneration: number;
24
- leaseMs: number;
25
- }): Promise<boolean>;
26
- heartbeatCoalesced(input: {
27
- laneId: string;
28
- workerId: string;
29
- leaseGeneration: number;
30
- claimedGeneration: number;
31
- leaseMs: number;
32
- }): Promise<boolean>;
33
- complete(input: {
34
- taskId: string;
35
- workerId: string;
36
- leaseGeneration: number;
37
- }): Promise<boolean>;
38
- completeCoalesced(input: {
39
- laneId: string;
40
- workerId: string;
41
- leaseGeneration: number;
42
- claimedGeneration: number;
43
- }): Promise<boolean>;
44
- defer(input: {
45
- taskId: string;
46
- workerId: string;
47
- leaseGeneration: number;
48
- delayMs: number;
49
- safeCode: string;
50
- }): Promise<boolean>;
51
- deferCoalesced(input: {
52
- laneId: string;
53
- workerId: string;
54
- leaseGeneration: number;
55
- claimedGeneration: number;
56
- delayMs: number;
57
- safeCode: string;
58
- }): Promise<boolean>;
59
- retry(input: {
60
- taskId: string;
61
- workerId: string;
62
- leaseGeneration: number;
63
- delayMs: number;
64
- safeCode: string;
65
- }): Promise<boolean>;
66
- retryCoalesced(input: {
67
- laneId: string;
68
- workerId: string;
69
- leaseGeneration: number;
70
- claimedGeneration: number;
71
- delayMs: number;
72
- safeCode: string;
73
- }): Promise<boolean>;
74
- markRequiresReview(input: {
75
- taskId: string;
76
- workerId: string;
77
- leaseGeneration: number;
78
- safeCode: string;
79
- }): Promise<boolean>;
80
- markCoalescedRequiresReview(input: {
81
- laneId: string;
82
- workerId: string;
83
- leaseGeneration: number;
84
- claimedGeneration: number;
85
- safeCode: string;
86
- }): Promise<boolean>;
87
- getHealth(sampleLimit?: number): Promise<SchedulerHealth>;
88
- }
7
+ export type ScheduledTaskRepositoryContract = Pick<ScheduledTaskRepository, "claimDue" | "claimCoalesced" | "heartbeat" | "heartbeatCoalesced" | "complete" | "completeCoalesced" | "defer" | "deferCoalesced" | "retry" | "retryCoalesced" | "markRequiresReview" | "markCoalescedRequiresReview" | "getHealth">;
89
8
  export declare class ScheduledTaskRunner {
90
9
  #private;
91
10
  constructor(input: {
@@ -107,12 +26,17 @@ export declare class ScheduledTaskRunner {
107
26
  getHealth(): Promise<SchedulerHealth>;
108
27
  }
109
28
  export declare function createScheduledTaskRunner(input: {
110
- database: Pool;
111
29
  modules: readonly ModuleDefinition[];
112
30
  route: ScheduledTaskRoute;
113
31
  logger: Logger;
114
32
  workerId?: string;
115
- }): ScheduledTaskRunner;
33
+ } & ({
34
+ database: Pool;
35
+ repository?: never;
36
+ } | {
37
+ repository: ScheduledTaskRepositoryContract;
38
+ database?: never;
39
+ })): ScheduledTaskRunner;
116
40
  export declare function schedulerOperationalHealth(health: SchedulerHealth): {
117
41
  status: "available";
118
42
  oneShot: ReturnType<typeof mapSchedulerWorkHealth>;
@@ -271,7 +271,7 @@ export class ScheduledTaskRunner {
271
271
  }
272
272
  export function createScheduledTaskRunner(input) {
273
273
  return new ScheduledTaskRunner({
274
- repository: new ScheduledTaskRepository(input.database),
274
+ repository: input.repository ?? new ScheduledTaskRepository(input.database),
275
275
  route: input.route,
276
276
  logger: input.logger,
277
277
  eligibleTasks: [
@@ -167,6 +167,51 @@ export declare const shardHealthSnapshotSchema: z.ZodObject<{
167
167
  }, z.core.$strict>;
168
168
  export type ShardHealthSnapshot = z.infer<typeof shardHealthSnapshotSchema>;
169
169
  export declare const shardControlOperationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
170
+ kind: z.ZodLiteral<"creator.onboarding">;
171
+ guildId: z.ZodString;
172
+ input: z.ZodDiscriminatedUnion<[z.ZodObject<{
173
+ action: z.ZodLiteral<"page">;
174
+ guildId: z.ZodString;
175
+ reference: z.ZodUUID;
176
+ }, z.core.$strict>, z.ZodObject<{
177
+ action: z.ZodLiteral<"consumer">;
178
+ guildId: z.ZodString;
179
+ overviewId: z.ZodUUID;
180
+ reference: z.ZodOptional<z.ZodUUID>;
181
+ configurationRevision: z.ZodOptional<z.ZodNumber>;
182
+ }, z.core.$strict>, z.ZodObject<{
183
+ guildId: z.ZodString;
184
+ reference: z.ZodUUID;
185
+ configurationRevision: z.ZodNumber;
186
+ memberUserId: z.ZodString;
187
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
188
+ action: z.ZodLiteral<"inspect">;
189
+ }, z.core.$strict>, z.ZodObject<{
190
+ guildId: z.ZodString;
191
+ reference: z.ZodUUID;
192
+ configurationRevision: z.ZodNumber;
193
+ memberUserId: z.ZodString;
194
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
195
+ action: z.ZodLiteral<"check">;
196
+ }, z.core.$strict>, z.ZodObject<{
197
+ guildId: z.ZodString;
198
+ reference: z.ZodUUID;
199
+ configurationRevision: z.ZodNumber;
200
+ memberUserId: z.ZodString;
201
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
202
+ action: z.ZodLiteral<"deliver">;
203
+ }, z.core.$strict>, z.ZodObject<{
204
+ sessionId: z.ZodUUID;
205
+ authorisationReference: z.ZodString;
206
+ withTwitch: z.ZodBoolean;
207
+ guildId: z.ZodString;
208
+ reference: z.ZodUUID;
209
+ configurationRevision: z.ZodNumber;
210
+ memberUserId: z.ZodString;
211
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
212
+ action: z.ZodLiteral<"join">;
213
+ }, z.core.$strict>], "action">;
214
+ }, z.core.$strict>, z.ZodObject<{
170
215
  kind: z.ZodLiteral<"automod.enhanced.configuration.page">;
171
216
  cursor: z.ZodOptional<z.ZodString>;
172
217
  limit: z.ZodNumber;
@@ -578,6 +623,51 @@ export declare const shardControlRequestSchema: z.ZodObject<{
578
623
  fencingToken: z.ZodNumber;
579
624
  deadlineAt: z.ZodISODateTime;
580
625
  operation: z.ZodDiscriminatedUnion<[z.ZodObject<{
626
+ kind: z.ZodLiteral<"creator.onboarding">;
627
+ guildId: z.ZodString;
628
+ input: z.ZodDiscriminatedUnion<[z.ZodObject<{
629
+ action: z.ZodLiteral<"page">;
630
+ guildId: z.ZodString;
631
+ reference: z.ZodUUID;
632
+ }, z.core.$strict>, z.ZodObject<{
633
+ action: z.ZodLiteral<"consumer">;
634
+ guildId: z.ZodString;
635
+ overviewId: z.ZodUUID;
636
+ reference: z.ZodOptional<z.ZodUUID>;
637
+ configurationRevision: z.ZodOptional<z.ZodNumber>;
638
+ }, z.core.$strict>, z.ZodObject<{
639
+ guildId: z.ZodString;
640
+ reference: z.ZodUUID;
641
+ configurationRevision: z.ZodNumber;
642
+ memberUserId: z.ZodString;
643
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
644
+ action: z.ZodLiteral<"inspect">;
645
+ }, z.core.$strict>, z.ZodObject<{
646
+ guildId: z.ZodString;
647
+ reference: z.ZodUUID;
648
+ configurationRevision: z.ZodNumber;
649
+ memberUserId: z.ZodString;
650
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
651
+ action: z.ZodLiteral<"check">;
652
+ }, z.core.$strict>, z.ZodObject<{
653
+ guildId: z.ZodString;
654
+ reference: z.ZodUUID;
655
+ configurationRevision: z.ZodNumber;
656
+ memberUserId: z.ZodString;
657
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
658
+ action: z.ZodLiteral<"deliver">;
659
+ }, z.core.$strict>, z.ZodObject<{
660
+ sessionId: z.ZodUUID;
661
+ authorisationReference: z.ZodString;
662
+ withTwitch: z.ZodBoolean;
663
+ guildId: z.ZodString;
664
+ reference: z.ZodUUID;
665
+ configurationRevision: z.ZodNumber;
666
+ memberUserId: z.ZodString;
667
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
668
+ action: z.ZodLiteral<"join">;
669
+ }, z.core.$strict>], "action">;
670
+ }, z.core.$strict>, z.ZodObject<{
581
671
  kind: z.ZodLiteral<"automod.enhanced.configuration.page">;
582
672
  cursor: z.ZodOptional<z.ZodString>;
583
673
  limit: z.ZodNumber;
@@ -1494,6 +1584,51 @@ export declare const supervisorMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObje
1494
1584
  fencingToken: z.ZodNumber;
1495
1585
  deadlineAt: z.ZodISODateTime;
1496
1586
  operation: z.ZodDiscriminatedUnion<[z.ZodObject<{
1587
+ kind: z.ZodLiteral<"creator.onboarding">;
1588
+ guildId: z.ZodString;
1589
+ input: z.ZodDiscriminatedUnion<[z.ZodObject<{
1590
+ action: z.ZodLiteral<"page">;
1591
+ guildId: z.ZodString;
1592
+ reference: z.ZodUUID;
1593
+ }, z.core.$strict>, z.ZodObject<{
1594
+ action: z.ZodLiteral<"consumer">;
1595
+ guildId: z.ZodString;
1596
+ overviewId: z.ZodUUID;
1597
+ reference: z.ZodOptional<z.ZodUUID>;
1598
+ configurationRevision: z.ZodOptional<z.ZodNumber>;
1599
+ }, z.core.$strict>, z.ZodObject<{
1600
+ guildId: z.ZodString;
1601
+ reference: z.ZodUUID;
1602
+ configurationRevision: z.ZodNumber;
1603
+ memberUserId: z.ZodString;
1604
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
1605
+ action: z.ZodLiteral<"inspect">;
1606
+ }, z.core.$strict>, z.ZodObject<{
1607
+ guildId: z.ZodString;
1608
+ reference: z.ZodUUID;
1609
+ configurationRevision: z.ZodNumber;
1610
+ memberUserId: z.ZodString;
1611
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
1612
+ action: z.ZodLiteral<"check">;
1613
+ }, z.core.$strict>, z.ZodObject<{
1614
+ guildId: z.ZodString;
1615
+ reference: z.ZodUUID;
1616
+ configurationRevision: z.ZodNumber;
1617
+ memberUserId: z.ZodString;
1618
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
1619
+ action: z.ZodLiteral<"deliver">;
1620
+ }, z.core.$strict>, z.ZodObject<{
1621
+ sessionId: z.ZodUUID;
1622
+ authorisationReference: z.ZodString;
1623
+ withTwitch: z.ZodBoolean;
1624
+ guildId: z.ZodString;
1625
+ reference: z.ZodUUID;
1626
+ configurationRevision: z.ZodNumber;
1627
+ memberUserId: z.ZodString;
1628
+ accountSlot: z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
1629
+ action: z.ZodLiteral<"join">;
1630
+ }, z.core.$strict>], "action">;
1631
+ }, z.core.$strict>, z.ZodObject<{
1497
1632
  kind: z.ZodLiteral<"automod.enhanced.configuration.page">;
1498
1633
  cursor: z.ZodOptional<z.ZodString>;
1499
1634
  limit: z.ZodNumber;
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { CLOUD_MAX_RESOURCE_IMPORT_BYTES } from "@helyx/control-protocol";
2
+ import { CLOUD_MAX_RESOURCE_IMPORT_BYTES, creatorOnboardingRequestSchema, } from "@helyx/control-protocol";
3
3
  import { AUTOMOD_SCANNER_LIMITS } from "@helyx/sdk";
4
4
  import { signedAssessmentEnvelopeSchema } from "@helyx/verification-contracts";
5
5
  export const SHARD_CONTRACT_VERSION = 1;
@@ -254,6 +254,14 @@ export const shardHealthSnapshotSchema = z
254
254
  });
255
255
  });
256
256
  export const shardControlOperationSchema = z.discriminatedUnion("kind", [
257
+ z
258
+ .object({
259
+ kind: z.literal("creator.onboarding"),
260
+ guildId: snowflake,
261
+ input: creatorOnboardingRequestSchema,
262
+ })
263
+ .strict()
264
+ .refine((value) => value.guildId === value.input.guildId),
257
265
  z
258
266
  .object({
259
267
  kind: z.literal("automod.enhanced.configuration.page"),
@@ -1273,6 +1281,10 @@ export async function executeShardControlOperation(handler, operation) {
1273
1281
  ? { actorAuthenticatedAt: operation.actorAuthenticatedAt }
1274
1282
  : {}),
1275
1283
  });
1284
+ case "creator.onboarding":
1285
+ if (!handler.creatorOnboarding)
1286
+ throw new Error("Creator onboarding is unavailable");
1287
+ return handler.creatorOnboarding(operation.input);
1276
1288
  case "oauth.consumer.cleanup":
1277
1289
  return handler.cleanupOAuthConsumer({
1278
1290
  consumerBindingId: operation.consumerBindingId,
@@ -1,4 +1,4 @@
1
- import { type AutoModerationEnhancedResultOutcome } from "@helyx/sdk";
1
+ import { type AutoModerationEnhancedResultOutcome, type CreatorOnboardingRequest, type CreatorOnboardingResponse } from "@helyx/sdk";
2
2
  import { type BotControlHandler } from "./control-server.js";
3
3
  import { type ShardControlRequest, type ShardControlResponse } from "./shard-contracts.js";
4
4
  import type { ShardCoordinator, ShardLeaderLease, ShardLease } from "./shard-coordinator.js";
@@ -8,6 +8,7 @@ type LocalDispatcher = (shardId: number, request: ShardControlRequest) => Promis
8
8
  export declare class ShardControlRouter implements BotControlHandler {
9
9
  #private;
10
10
  private readonly input;
11
+ creatorOnboarding(input: CreatorOnboardingRequest): Promise<CreatorOnboardingResponse>;
11
12
  constructor(input: {
12
13
  generation: string;
13
14
  shardCount: number;
@@ -11,6 +11,13 @@ const LEASE_VALIDATION_TIMEOUT_MS = 3_000;
11
11
  const ECKO_RESULT_TIMEOUT_MS = AUTOMOD_SCANNER_LIMITS.resultAcknowledgementSeconds * 1_000;
12
12
  export class ShardControlRouter {
13
13
  input;
14
+ creatorOnboarding(input) {
15
+ return this.#route({
16
+ kind: "creator.onboarding",
17
+ guildId: input.guildId,
18
+ input,
19
+ });
20
+ }
14
21
  constructor(input) {
15
22
  this.input = input;
16
23
  }