@refrainai/cli 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ai-model-FM6GWCID.js → ai-model-DP5PKGM6.js} +2 -2
- package/dist/{chunk-2BVDAJZT.js → chunk-65CTEK2K.js} +9 -6
- package/dist/chunk-65CTEK2K.js.map +1 -0
- package/dist/chunk-BGC75OVR.js +30 -0
- package/dist/chunk-BGC75OVR.js.map +1 -0
- package/dist/{chunk-H47NWH7N.js → chunk-CJM3IU5Q.js} +611 -73
- package/dist/chunk-CJM3IU5Q.js.map +1 -0
- package/dist/{chunk-CLYJHKPY.js → chunk-CMWLFQXD.js} +43 -42
- package/dist/chunk-CMWLFQXD.js.map +1 -0
- package/dist/{chunk-IGFCYKHC.js → chunk-CNJ5KCDN.js} +252 -295
- package/dist/chunk-CNJ5KCDN.js.map +1 -0
- package/dist/{chunk-DJVUITRB.js → chunk-ELQ23L4Z.js} +898 -1135
- package/dist/chunk-ELQ23L4Z.js.map +1 -0
- package/dist/chunk-EMAYENG4.js +1146 -0
- package/dist/chunk-EMAYENG4.js.map +1 -0
- package/dist/{chunk-7UCVPKD4.js → chunk-F7WTOQIQ.js} +12 -72
- package/dist/chunk-F7WTOQIQ.js.map +1 -0
- package/dist/{chunk-WEYR56ZN.js → chunk-HHRHHFSK.js} +4 -4
- package/dist/{chunk-UGPXCQY3.js → chunk-KFNW4XR2.js} +13 -4
- package/dist/chunk-KFNW4XR2.js.map +1 -0
- package/dist/{chunk-RT664YIO.js → chunk-LZDZGI4M.js} +3 -1
- package/dist/chunk-LZDZGI4M.js.map +1 -0
- package/dist/chunk-RBZK7T76.js +349 -0
- package/dist/chunk-RBZK7T76.js.map +1 -0
- package/dist/{chunk-HQDXLWAY.js → chunk-SDV3X5UN.js} +2 -2
- package/dist/{chunk-Z33FCOTZ.js → chunk-VVXNFUPL.js} +4 -2
- package/dist/chunk-VVXNFUPL.js.map +1 -0
- package/dist/chunk-XIVS7N3V.js +74 -0
- package/dist/chunk-XIVS7N3V.js.map +1 -0
- package/dist/chunk-YTVEYQGA.js +64 -0
- package/dist/chunk-YTVEYQGA.js.map +1 -0
- package/dist/{chunk-RYIJPYM3.js → chunk-YW46VP57.js} +25 -8
- package/dist/chunk-YW46VP57.js.map +1 -0
- package/dist/cli.js +5 -5
- package/dist/{compose-MTSIJY5D.js → compose-B2IAO7YW.js} +9 -7
- package/dist/{compose-MTSIJY5D.js.map → compose-B2IAO7YW.js.map} +1 -1
- package/dist/extraction-prompt-VDCKIFLB.js +17 -0
- package/dist/extraction-prompt-VDCKIFLB.js.map +1 -0
- package/dist/{fix-runbook-ZSBOTLC2.js → fix-runbook-JJN4HVIP.js} +12 -10
- package/dist/{fix-runbook-ZSBOTLC2.js.map → fix-runbook-JJN4HVIP.js.map} +1 -1
- package/dist/prompts-XMJXIITW.js +13 -0
- package/dist/runbook-builder-2ZLE2AEO.js +11 -0
- package/dist/{runbook-data-helpers-KRR2SH76.js → runbook-data-helpers-5UAO65TZ.js} +3 -3
- package/dist/{runbook-executor-K7T6RJWJ.js → runbook-executor-TVV5EG6Q.js} +41 -444
- package/dist/runbook-executor-TVV5EG6Q.js.map +1 -0
- package/dist/{runbook-generator-MPXJBQ5N.js → runbook-generator-4XKNV2B7.js} +61 -136
- package/dist/runbook-generator-4XKNV2B7.js.map +1 -0
- package/dist/{runbook-schema-3T6TP3JJ.js → runbook-schema-X7DW725O.js} +2 -2
- package/dist/runbook-store-S24PXIHD.js +11 -0
- package/dist/{schema-5G6UQSPT.js → schema-XFSD5EWN.js} +2 -2
- package/dist/{server-AG3LXQBI.js → server-5XARL5N7.js} +1176 -128
- package/dist/server-5XARL5N7.js.map +1 -0
- package/dist/{tenant-ai-config-QPFEJUVJ.js → tenant-ai-config-4NHKRW7O.js} +4 -4
- package/dist/tenant-ai-config-4NHKRW7O.js.map +1 -0
- package/dist/yaml-patcher-32QBPXT2.js +18 -0
- package/dist/yaml-patcher-32QBPXT2.js.map +1 -0
- package/package.json +3 -2
- package/dist/chunk-2BVDAJZT.js.map +0 -1
- package/dist/chunk-7UCVPKD4.js.map +0 -1
- package/dist/chunk-CLYJHKPY.js.map +0 -1
- package/dist/chunk-DJVUITRB.js.map +0 -1
- package/dist/chunk-H47NWH7N.js.map +0 -1
- package/dist/chunk-IGFCYKHC.js.map +0 -1
- package/dist/chunk-RT664YIO.js.map +0 -1
- package/dist/chunk-RYIJPYM3.js.map +0 -1
- package/dist/chunk-UGPXCQY3.js.map +0 -1
- package/dist/chunk-VPK2MQAZ.js +0 -589
- package/dist/chunk-VPK2MQAZ.js.map +0 -1
- package/dist/chunk-Z33FCOTZ.js.map +0 -1
- package/dist/runbook-executor-K7T6RJWJ.js.map +0 -1
- package/dist/runbook-generator-MPXJBQ5N.js.map +0 -1
- package/dist/runbook-store-G5GUOWRR.js +0 -11
- package/dist/server-AG3LXQBI.js.map +0 -1
- package/dist/yaml-patcher-VGUS2JGH.js +0 -15
- /package/dist/{ai-model-FM6GWCID.js.map → ai-model-DP5PKGM6.js.map} +0 -0
- /package/dist/{chunk-WEYR56ZN.js.map → chunk-HHRHHFSK.js.map} +0 -0
- /package/dist/{chunk-HQDXLWAY.js.map → chunk-SDV3X5UN.js.map} +0 -0
- /package/dist/{runbook-data-helpers-KRR2SH76.js.map → prompts-XMJXIITW.js.map} +0 -0
- /package/dist/{runbook-schema-3T6TP3JJ.js.map → runbook-builder-2ZLE2AEO.js.map} +0 -0
- /package/dist/{runbook-store-G5GUOWRR.js.map → runbook-data-helpers-5UAO65TZ.js.map} +0 -0
- /package/dist/{schema-5G6UQSPT.js.map → runbook-schema-X7DW725O.js.map} +0 -0
- /package/dist/{tenant-ai-config-QPFEJUVJ.js.map → runbook-store-S24PXIHD.js.map} +0 -0
- /package/dist/{yaml-patcher-VGUS2JGH.js.map → schema-XFSD5EWN.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/index.ts","../../../src/server/app.ts","../../../src/server/auth/index.ts","../../../src/server/auth/email.ts","../../../src/server/auth/hooks.ts","../../../src/server/inngest/client.ts","../../../src/server/inngest/functions/health.ts","../../../src/server/inngest/functions/execute-job.ts","../../../src/server/db/client.ts","../../../src/server/store/job-store.ts","../../../src/server/store/artifact-store.ts","../../../src/server/inngest/helpers/runbook-loader.ts","../../../src/server/inngest/helpers/progress-emitter.ts","../../../src/server/inngest/helpers/server-logger.ts","../../../src/server/redis.ts","../../../src/harness/ai-service.ts","../../../src/server/inngest/helpers/screenshot-streamer.ts","../../../src/server/inngest/helpers/remote-confirmation.ts","../../../src/server/inngest/helpers/chat-bot-factory.ts","../../../src/server/routes/settings-defaults.ts","../../../src/storage/gcs-store.ts","../../../src/storage/local-store.ts","../../../src/server/store/telemetry-store.ts","../../../src/server/telemetry/collector.ts","../../../src/server/inngest/functions/generate-job.ts","../../../src/server/inngest/helpers/remote-intervention.ts","../../../src/server/inngest/functions/schedule-poller.ts","../../../src/server/store/schedule-store.ts","../../../src/server/utils/cron.ts","../../../src/server/helpers/execution-config-builder.ts","../../../src/server/inngest/index.ts","../../../src/server/middleware/auth.ts","../../../src/server/handlers/runbooks.ts","../../../src/server/middleware/rbac.ts","../../../src/server/middleware/plan-gate.ts","../../../src/server/handlers/jobs.ts","../../../src/server/sse/job-stream.ts","../../../src/server/sse/types.ts","../../../src/server/store/metering-store.ts","../../../src/server/handlers/artifacts.ts","../../../src/server/handlers/schedules.ts","../../../src/server/handlers/api-keys.ts","../../../src/plan/keygen.ts","../../../src/server/handlers/validate-key.ts","../../../src/server/handlers/tenants.ts","../../../src/server/handlers/users.ts","../../../src/server/routes/settings.ts","../../../src/server/telemetry/debug-report-generator.ts","../../../src/server/routes/settings-schema.ts","../../../src/server/handlers/usage.ts","../../../src/server/handlers/telemetry.ts","../../../src/server/webhooks/slack.ts","../../../src/server/webhooks/approval-parser.ts","../../../src/server/webhooks/credential-resolver.ts","../../../src/server/webhooks/teams.ts","../../../src/server/webhooks/discord.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\nimport { serve } from \"@hono/node-server\";\nimport { loadServerConfig } from \"./config.js\";\nimport { createApp } from \"./app.js\";\nimport { getDb, getPool, closeDb } from \"./db/client.js\";\nimport { closeRedisPublisher } from \"./redis.js\";\n\nasync function main() {\n const config = loadServerConfig();\n\n let db: ReturnType<typeof getDb>;\n try {\n db = getDb(config.databaseUrl);\n } catch (e) {\n console.error(\"Failed to initialize database:\", e);\n process.exit(1);\n }\n\n const pool = getPool();\n const app = createApp(config, pool, db);\n\n // serve() は非同期(listen 完了前にリターン)\n const server = serve({\n fetch: app.fetch,\n port: config.port,\n });\n\n let retries = 0;\n const maxRetries = 3;\n\n server.on(\"listening\", () => {\n console.log(`API server listening on port ${config.port}`);\n console.log(`[Inngest] Event key: ${config.inngestEventKey ? \"set\" : \"NOT SET\"}`);\n console.log(`[Inngest] Signing key: ${config.inngestSigningKey ? \"set\" : \"NOT SET\"}`);\n console.log(`[Inngest] Dev server: ${process.env.INNGEST_DEV ?? \"auto-detect\"}`);\n console.log(`[Inngest] Serve endpoint: /api/inngest`);\n });\n\n server.on(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\" && retries < maxRetries) {\n retries++;\n console.warn(\n `Port ${config.port} is in use (attempt ${retries}/${maxRetries}). Killing old process...`\n );\n try {\n execSync(`lsof -ti :${config.port} | xargs kill -9`, {\n stdio: \"ignore\",\n });\n } catch {}\n setTimeout(() => server.listen(config.port), 1000);\n } else {\n console.error(`Failed to start on port ${config.port}: ${err.message}`);\n process.exit(1);\n }\n });\n\n let shuttingDown = false;\n const shutdown = async () => {\n if (shuttingDown) return;\n shuttingDown = true;\n console.log(\"Shutting down...\");\n\n // クリーンアップがハングしても確実に終了する\n const forceExit = setTimeout(() => process.exit(1), 3000);\n forceExit.unref();\n\n try {\n (server as import(\"node:http\").Server).closeAllConnections?.();\n server.close();\n await closeRedisPublisher();\n await closeDb();\n } catch {\n // クリーンアップ失敗でも終了する\n }\n process.exit(0);\n };\n\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n}\n\nmain();\n","import { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { logger } from \"hono/logger\";\nimport { serve as serveInngest } from \"inngest/hono\";\nimport type pg from \"pg\";\nimport type { ServerConfig } from \"./config.js\";\nimport type { getDb } from \"./db/client.js\";\nimport { createAuth } from \"./auth/index.js\";\nimport { inngest, inngestFunctions } from \"./inngest/index.js\";\nimport { createAuthMiddleware, requireAuth, requireVerifiedEmail } from \"./middleware/auth.js\";\nimport type { AppVariables } from \"./middleware/types.js\";\nimport { RunbookStore } from \"./store/runbook-store.js\";\nimport { JobStore } from \"./store/job-store.js\";\nimport { ScheduleStore } from \"./store/schedule-store.js\";\nimport { createRunbookHandlers } from \"./handlers/runbooks.js\";\nimport { createJobHandlers } from \"./handlers/jobs.js\";\nimport { createScheduleHandlers } from \"./handlers/schedules.js\";\nimport { apiKeysRoutes } from \"./handlers/api-keys.js\";\nimport { validateKeyRoute } from \"./handlers/validate-key.js\";\nimport { tenantsRoutes, resolveInvitationByToken } from \"./handlers/tenants.js\";\nimport { usersRoutes } from \"./handlers/users.js\";\nimport { createSettingsRoutes } from \"./routes/settings.js\";\nimport { createUsageHandlers } from \"./handlers/usage.js\";\nimport { createTelemetryHandlers } from \"./handlers/telemetry.js\";\nimport { createSlackWebhookRoute } from \"./webhooks/slack.js\";\nimport { createTeamsWebhookRoute } from \"./webhooks/teams.js\";\nimport { createDiscordWebhookRoute } from \"./webhooks/discord.js\";\nimport type { WebhookDeps } from \"./webhooks/credential-resolver.js\";\n\nexport function createApp(\n config: ServerConfig,\n pool: pg.Pool,\n db: ReturnType<typeof getDb>,\n) {\n const auth = createAuth(config, pool, db);\n\n const app = new Hono<{ Variables: AppVariables }>();\n\n if (config.nodeEnv !== \"test\") {\n app.use(\"*\", logger());\n }\n\n app.use(\n \"*\",\n cors({\n origin: config.corsOrigin,\n credentials: true,\n }),\n );\n\n // 二重認証ミドルウェア(Cookie セッション + Bearer API Key)\n app.use(\"*\", createAuthMiddleware(auth, db));\n\n // Better Auth ルート\n app.on([\"POST\", \"GET\"], \"/api/auth/**\", (c) => {\n return auth.handler(c.req.raw);\n });\n\n app.get(\"/health\", (c) =>\n c.json({ status: \"ok\", timestamp: new Date().toISOString() }),\n );\n\n // 公開エンドポイント(認証不要)\n app.get(\"/api/public/invitations/by-token\", async (c) => {\n const token = c.req.query(\"token\");\n if (!token) return c.json({ error: \"token is required\" }, 400);\n\n const row = await resolveInvitationByToken(db, token);\n if (!row || row.status !== \"pending\" || row.expiresAt < new Date()) {\n return c.json({ error: \"Invitation not found or expired\" }, 410);\n }\n\n return c.json({\n id: row.id,\n role: row.role,\n tenantId: row.tenantId,\n tenantName: row.tenantName,\n inviterName: row.inviterName,\n createdAt: row.createdAt.toISOString(),\n expiresAt: row.expiresAt.toISOString(),\n });\n });\n\n // opaque キーバリデーション(認証不要、キー自体がクレデンシャル)\n app.route(\"/api/public/validate-key\", validateKeyRoute(db));\n\n // 有効な OAuth プロバイダー一覧(認証不要)\n app.get(\"/api/public/auth-providers\", (c) => {\n const providers: string[] = [];\n if (config.githubClientId && config.githubClientSecret) providers.push(\"github\");\n if (config.googleClientId && config.googleClientSecret) providers.push(\"google\");\n if (config.microsoftClientId && config.microsoftClientSecret) providers.push(\"microsoft\");\n return c.json({ providers });\n });\n\n // 認証必須ルート\n app.use(\"/api/v1/*\", requireAuth);\n app.use(\"/api/v1/*\", requireVerifiedEmail);\n\n // ── v1 API ルート ──\n const runbookStore = new RunbookStore(db);\n const jobStore = new JobStore(db);\n const scheduleStore = new ScheduleStore(db);\n\n const v1 = new Hono<{ Variables: AppVariables }>();\n v1.route(\"/runbooks\", createRunbookHandlers(runbookStore, jobStore, inngest, config.encryptionKey, scheduleStore, db, config));\n v1.route(\"/jobs\", createJobHandlers(jobStore, runbookStore, inngest, config.redisUrl, db, config));\n v1.route(\"/schedules\", createScheduleHandlers(scheduleStore, jobStore, db));\n v1.route(\"/settings\", createSettingsRoutes(db, config));\n v1.route(\"/usage\", createUsageHandlers(db));\n v1.route(\"/telemetry\", createTelemetryHandlers(db));\n\n app.route(\"/api/v1\", v1);\n app.route(\"/api/v1/api-keys\", apiKeysRoutes(db));\n app.route(\"/api/v1/tenants\", tenantsRoutes(db, config));\n app.route(\"/api/v1/users\", usersRoutes(db));\n\n // Inngest serve ハンドラ(認証不要 — Inngest Server が署名キーで検証)\n app.on(\n [\"GET\", \"POST\", \"PUT\"],\n \"/api/inngest\",\n serveInngest({\n client: inngest,\n functions: inngestFunctions,\n signingKey: config.inngestSigningKey,\n }),\n );\n\n // Webhook ハンドラ(認証不要 — 各プラットフォーム独自の署名検証で保護)\n // マルチテナント: テナント別クレデンシャルを DB から解決するため常時ルート登録\n const webhookDeps: WebhookDeps = { db, encryptionKey: config.encryptionKey, redisUrl: config.redisUrl };\n app.route(\"/api/webhooks/slack\", createSlackWebhookRoute(webhookDeps));\n app.route(\"/api/webhooks/teams\", createTeamsWebhookRoute(webhookDeps));\n app.route(\"/api/webhooks/discord\", createDiscordWebhookRoute(webhookDeps));\n\n return app;\n}\n","/**\n * Better Auth インスタンス — ファクトリ関数\n */\n\nimport { betterAuth } from \"better-auth\";\nimport { drizzleAdapter } from \"better-auth/adapters/drizzle\";\nimport { eq } from \"drizzle-orm\";\nimport type pg from \"pg\";\nimport type { ServerConfig } from \"../config.js\";\nimport type { getDb } from \"../db/client.js\";\nimport * as schema from \"../db/schema.js\";\nimport {\n createEmailSender,\n buildVerificationEmailHtml,\n buildPasswordResetEmailHtml,\n emailString,\n type EmailLocale,\n} from \"./email.js\";\nimport { createUserHooks } from \"./hooks.js\";\n\n/** ユーザーの最初のテナントの locale を取得 */\nasync function getUserPrimaryLocale(\n db: ReturnType<typeof getDb>,\n userId: string,\n): Promise<EmailLocale> {\n const [row] = await db\n .select({ locale: schema.tenants.locale })\n .from(schema.tenantMembers)\n .innerJoin(schema.tenants, eq(schema.tenantMembers.tenantId, schema.tenants.id))\n .where(eq(schema.tenantMembers.userId, userId))\n .orderBy(schema.tenantMembers.createdAt)\n .limit(1);\n return (row?.locale as EmailLocale) ?? \"en\";\n}\n\nexport function createAuth(\n config: ServerConfig,\n _pool: pg.Pool,\n db: ReturnType<typeof getDb>,\n) {\n const socialProviders: Record<string, { clientId: string; clientSecret: string }> = {};\n\n if (config.githubClientId && config.githubClientSecret) {\n socialProviders.github = {\n clientId: config.githubClientId,\n clientSecret: config.githubClientSecret,\n };\n }\n if (config.googleClientId && config.googleClientSecret) {\n socialProviders.google = {\n clientId: config.googleClientId,\n clientSecret: config.googleClientSecret,\n };\n }\n if (config.microsoftClientId && config.microsoftClientSecret) {\n socialProviders.microsoft = {\n clientId: config.microsoftClientId,\n clientSecret: config.microsoftClientSecret,\n };\n }\n\n const sendEmail = createEmailSender(config);\n\n return betterAuth({\n basePath: \"/api/auth\",\n baseURL: config.betterAuthUrl,\n secret: config.betterAuthSecret,\n database: drizzleAdapter(db, {\n provider: \"pg\",\n schema,\n }),\n emailAndPassword: {\n enabled: true,\n requireEmailVerification: true,\n sendResetPassword: async ({ user, url }) => {\n const locale = await getUserPrimaryLocale(db, user.id);\n void sendEmail({\n to: user.email,\n subject: emailString(\"resetSubject\", locale),\n html: buildPasswordResetEmailHtml(url, locale),\n });\n },\n onPasswordReset: async ({ user }) => {\n // パスワードリセットリンクのクリック=メール所有権の証明\n await db\n .update(schema.user)\n .set({ emailVerified: true })\n .where(eq(schema.user.id, user.id));\n },\n },\n emailVerification: {\n sendVerificationEmail: async ({ user, url }) => {\n const locale = await getUserPrimaryLocale(db, user.id);\n const verifyUrl = url.replace(\n /callbackURL=[^&]*/,\n `callbackURL=${encodeURIComponent(\"/?email_verified=true\")}`,\n );\n void sendEmail({\n to: user.email,\n subject: emailString(\"verifySubject\", locale),\n html: buildVerificationEmailHtml(verifyUrl, locale),\n });\n },\n sendOnSignUp: true,\n autoSignInAfterVerification: true,\n expiresIn: 3600,\n },\n accountLinking: {\n enabled: true,\n trustedProviders: [\"github\", \"google\", \"microsoft\"],\n },\n socialProviders,\n trustedOrigins: [config.corsOrigin],\n databaseHooks: createUserHooks(db),\n });\n}\n\nexport type Auth = ReturnType<typeof createAuth>;\n","/**\n * メール送信抽象化(SendGrid / Resend 切り替え対応)\n */\n\nimport type { ServerConfig } from \"../config.js\";\n\nexport type EmailLocale = \"en\" | \"ja\";\n\nconst emailStrings = {\n en: {\n verifySubject: \"Welcome to Refrain — Verify your email\",\n verifyTitle: \"Welcome to Refrain\",\n verifyBody: \"Thanks for signing up! Refrain generates reproducible runbooks from your browser workflows — no brittle selectors to maintain. Reruns execute with zero AI tokens, and when UIs change, self-healing agents auto-patch your automation. Verify your email to get started.\",\n verifyButton: \"Verify my email\",\n verifyFooter: \"If you didn't create an account, you can safely ignore this email.\",\n resetSubject: \"Reset your password\",\n resetTitle: \"Reset your password\",\n resetBody: \"We received a request to reset your Refrain account password. Click below to set a new password. This link expires in 1 hour.\",\n resetButton: \"Reset password\",\n resetFooter: \"If you didn't request a password reset, you can safely ignore this email.\",\n invitationSubject: \"You've been invited to {tenantName} on Refrain\",\n invitationTitle: \"You've been invited to {tenantName}\",\n invitationBody: '{inviterName} has invited you to join <strong style=\"color:#f5f5f5;\">{tenantName}</strong> as a <strong style=\"color:#f5f5f5;\">{role}</strong> on Refrain — browser automation with AI-generated self-healing runbooks. No brittle selectors, zero rerun cost, and built-in approval workflows. Sign up to start collaborating.',\n invitationButton: \"Accept Invitation\",\n invitationFooter: \"This invitation expires in 7 days. If you didn't expect this invitation, you can safely ignore this email.\",\n invitationExistingBody: '{inviterName} has invited you to join <strong style=\"color:#f5f5f5;\">{tenantName}</strong> as a <strong style=\"color:#f5f5f5;\">{role}</strong>. Click below to accept and start collaborating.',\n invitationExistingButton: \"View Invitation\",\n brandFooter: \"Refrain by BaseMachina — Self-healing browser automation\",\n },\n ja: {\n verifySubject: \"Refrain へようこそ — メールアドレスの確認\",\n verifyTitle: \"Refrain へようこそ\",\n verifyBody: \"ご登録ありがとうございます!Refrain はやりたいことを伝えるだけで、AI がブラウザ操作の手順書を自動作成。従来の RPA のような高額ライセンスやエンジニアへの修正依頼は不要です。繰り返し実行の AI コストはゼロで、画面が変わっても AI が自動で修正を提案してくれます。メールアドレスを確認して始めましょう。\",\n verifyButton: \"メールアドレスを確認する\",\n verifyFooter: \"アカウントを作成した覚えがない場合は、このメールを無視してください。\",\n resetSubject: \"パスワードのリセット\",\n resetTitle: \"パスワードをリセット\",\n resetBody: \"Refrain アカウントのパスワードリセットのリクエストを受け付けました。下のボタンから新しいパスワードを設定してください。このリンクは 1 時間で期限切れになります。\",\n resetButton: \"パスワードをリセット\",\n resetFooter: \"パスワードリセットをリクエストした覚えがない場合は、このメールを無視してください。\",\n invitationSubject: \"{tenantName} への招待 — Refrain\",\n invitationTitle: \"{tenantName} への招待\",\n invitationBody: '{inviterName} さんから <strong style=\"color:#f5f5f5;\">{tenantName}</strong> に <strong style=\"color:#f5f5f5;\">{role}</strong> として招待されました。Refrain はやりたいことを伝えるだけで AI が業務手順を自動作成。高額な RPA ライセンスやエンジニアへの修正依頼は不要で、繰り返し実行の AI コストもゼロです。登録してチームに参加しましょう。',\n invitationButton: \"招待を受ける\",\n invitationFooter: \"この招待は7日間有効です。心当たりがない場合は、このメールを無視してください。\",\n invitationExistingBody: '{inviterName} さんから <strong style=\"color:#f5f5f5;\">{tenantName}</strong> に <strong style=\"color:#f5f5f5;\">{role}</strong> として招待されました。下のボタンからチームに参加できます。',\n invitationExistingButton: \"招待を確認\",\n brandFooter: \"Refrain by BaseMachina — AI ブラウザ自動化\",\n },\n} as const;\n\ntype EmailStringKey = keyof (typeof emailStrings)[\"en\"];\n\n/** 文言取得ヘルパー({key} 形式のプレースホルダ対応) */\nexport function emailString(\n key: EmailStringKey,\n locale: EmailLocale = \"en\",\n params?: Record<string, string>,\n): string {\n let text = emailStrings[locale][key];\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n text = text.replaceAll(`{${k}}`, v) as typeof text;\n }\n }\n return text;\n}\n\ninterface SendEmailParams {\n to: string;\n subject: string;\n html: string;\n}\n\ntype EmailSender = (params: SendEmailParams) => Promise<void>;\n\nconst noopSender: EmailSender = async ({ to, subject }) => {\n console.warn(`[auth] Skipping email to=${to} subject=\"${subject}\"`);\n};\n\nfunction createResendSender(config: ServerConfig): EmailSender {\n if (!config.resendApiKey) {\n console.warn(\n \"[auth] RESEND_API_KEY is not set — emails will not be sent\",\n );\n return noopSender;\n }\n\n const from = config.emailFrom;\n let resend: import(\"resend\").Resend | undefined;\n\n return async ({ to, subject, html }) => {\n if (!resend) {\n const { Resend } = await import(\"resend\");\n resend = new Resend(config.resendApiKey);\n }\n const { error } = await resend.emails.send({ from, to, subject, html });\n if (error) {\n console.error(\"[auth] Failed to send email via Resend:\", error);\n }\n };\n}\n\nfunction createSendGridSender(config: ServerConfig): EmailSender {\n if (!config.sendgridApiKey) {\n console.warn(\n \"[auth] SENDGRID_API_KEY is not set — emails will not be sent\",\n );\n return noopSender;\n }\n\n const from = config.emailFrom;\n let sgMail: import(\"@sendgrid/mail\").MailService | undefined;\n\n return async ({ to, subject, html }) => {\n try {\n if (!sgMail) {\n const mod = await import(\"@sendgrid/mail\");\n sgMail = mod.default as import(\"@sendgrid/mail\").MailService;\n sgMail.setApiKey(config.sendgridApiKey!);\n }\n const [response] = await sgMail.send({ to, from, subject, html });\n console.log(\n `[auth] Email sent via SendGrid to=${to} statusCode=${response.statusCode}`,\n );\n } catch (err) {\n console.error(\"[auth] Failed to send email via SendGrid:\", err);\n }\n };\n}\n\nexport function createEmailSender(config: ServerConfig): EmailSender {\n if (config.emailProvider === \"resend\") {\n return createResendSender(config);\n }\n return createSendGridSender(config);\n}\n\nexport function buildVerificationEmailHtml(url: string, locale: EmailLocale = \"en\"): string {\n const s = emailStrings[locale];\n return `<!DOCTYPE html>\n<html lang=\"${locale}\">\n<head><meta charset=\"UTF-8\"></head>\n<body style=\"margin:0;padding:0;background:#0a0a0a;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;\">\n <div style=\"max-width:480px;margin:0 auto;padding:40px 24px;\">\n <h2 style=\"color:#f5f5f5;font-size:20px;margin:0 0 16px;\">\n ${s.verifyTitle}\n </h2>\n <p style=\"color:#a3a3a3;font-size:14px;line-height:1.7;margin:0 0 24px;\">\n ${s.verifyBody}\n </p>\n <a href=\"${url}\" style=\"display:inline-block;background:#f5f5f5;color:#0a0a0a;text-decoration:none;font-size:14px;font-weight:600;padding:12px 24px;border-radius:6px;\">\n ${s.verifyButton}\n </a>\n <p style=\"color:#525252;font-size:12px;line-height:1.7;margin:24px 0 0;\">\n ${s.verifyFooter}\n </p>\n <hr style=\"border:none;border-top:1px solid #262626;margin:24px 0;\">\n <p style=\"color:#525252;font-size:12px;margin:0;\">\n ${s.brandFooter}\n </p>\n </div>\n</body>\n</html>`;\n}\n\nexport function buildInvitationEmailHtml({\n inviteUrl,\n tenantName,\n inviterName,\n role,\n locale = \"en\",\n variant = \"new\",\n}: {\n inviteUrl: string;\n tenantName: string;\n inviterName: string;\n role: string;\n locale?: EmailLocale;\n variant?: \"new\" | \"existing\";\n}): string {\n const params = { tenantName, inviterName, role };\n const title = emailString(\"invitationTitle\", locale, params);\n const body = variant === \"existing\"\n ? emailString(\"invitationExistingBody\", locale, params)\n : emailString(\"invitationBody\", locale, params);\n const button = variant === \"existing\"\n ? emailString(\"invitationExistingButton\", locale)\n : emailString(\"invitationButton\", locale);\n const s = emailStrings[locale];\n return `<!DOCTYPE html>\n<html lang=\"${locale}\">\n<head><meta charset=\"UTF-8\"></head>\n<body style=\"margin:0;padding:0;background:#0a0a0a;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;\">\n <div style=\"max-width:480px;margin:0 auto;padding:40px 24px;\">\n <h2 style=\"color:#f5f5f5;font-size:20px;margin:0 0 16px;\">\n ${title}\n </h2>\n <p style=\"color:#a3a3a3;font-size:14px;line-height:1.7;margin:0 0 24px;\">\n ${body}\n </p>\n <a href=\"${inviteUrl}\" style=\"display:inline-block;background:#f5f5f5;color:#0a0a0a;text-decoration:none;font-size:14px;font-weight:600;padding:12px 24px;border-radius:6px;\">\n ${button}\n </a>\n <p style=\"color:#525252;font-size:12px;line-height:1.7;margin:24px 0 0;\">\n ${s.invitationFooter}\n </p>\n <hr style=\"border:none;border-top:1px solid #262626;margin:24px 0;\">\n <p style=\"color:#525252;font-size:12px;margin:0;\">\n ${s.brandFooter}\n </p>\n </div>\n</body>\n</html>`;\n}\n\nexport function buildPasswordResetEmailHtml(url: string, locale: EmailLocale = \"en\"): string {\n const s = emailStrings[locale];\n return `<!DOCTYPE html>\n<html lang=\"${locale}\">\n<head><meta charset=\"UTF-8\"></head>\n<body style=\"margin:0;padding:0;background:#0a0a0a;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;\">\n <div style=\"max-width:480px;margin:0 auto;padding:40px 24px;\">\n <h2 style=\"color:#f5f5f5;font-size:20px;margin:0 0 16px;\">\n ${s.resetTitle}\n </h2>\n <p style=\"color:#a3a3a3;font-size:14px;line-height:1.7;margin:0 0 24px;\">\n ${s.resetBody}\n </p>\n <a href=\"${url}\" style=\"display:inline-block;background:#f5f5f5;color:#0a0a0a;text-decoration:none;font-size:14px;font-weight:600;padding:12px 24px;border-radius:6px;\">\n ${s.resetButton}\n </a>\n <p style=\"color:#525252;font-size:12px;line-height:1.7;margin:24px 0 0;\">\n ${s.resetFooter}\n </p>\n <hr style=\"border:none;border-top:1px solid #262626;margin:24px 0;\">\n <p style=\"color:#525252;font-size:12px;margin:0;\">\n ${s.brandFooter}\n </p>\n </div>\n</body>\n</html>`;\n}\n","/**\n * Better Auth databaseHooks — ユーザー作成後にデフォルトテナントを自動作成\n */\n\nimport type { BetterAuthOptions } from \"better-auth\";\nimport type { getDb } from \"../db/client.js\";\nimport { tenants, tenantMembers } from \"../db/schema.js\";\n\n/**\n * user.create.after フック:\n * 1. tenants にデフォルトテナントを INSERT\n * 2. tenant_members に owner ロールで INSERT\n */\nexport function createUserHooks(\n db: ReturnType<typeof getDb>,\n): BetterAuthOptions[\"databaseHooks\"] {\n return {\n user: {\n create: {\n after: async (user) => {\n const slug = `u-${user.id.toLowerCase().replace(/[^a-z0-9]/g, \"\")}`;\n const teamName = user.name ? `${user.name}'s Team` : \"My Team\";\n\n const [tenant] = await db\n .insert(tenants)\n .values({ name: teamName, slug })\n .returning();\n\n await db\n .insert(tenantMembers)\n .values({ tenantId: tenant.id, userId: user.id, role: \"owner\" });\n },\n },\n },\n };\n}\n","import { Inngest, EventSchemas } from \"inngest\";\nimport type { InngestEvents } from \"./types.js\";\n\nexport const inngest = new Inngest({\n id: \"refrain\",\n eventKey: process.env.INNGEST_EVENT_KEY,\n schemas: new EventSchemas().fromRecord<InngestEvents>(),\n});\n","import { inngest } from \"../client.js\";\n\nexport const healthCheck = inngest.createFunction(\n { id: \"health-check\" },\n { event: \"health/check\" },\n async ({ step }) => {\n const result = await step.run(\"check\", () => ({\n ok: true as const,\n timestamp: new Date().toISOString(),\n }));\n return result;\n },\n);\n","import { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\nimport { eq } from \"drizzle-orm\";\nimport { inngest } from \"../client.js\";\nimport { getDb } from \"../../db/client.js\";\nimport { tenants, tenantExecutionSettings } from \"../../db/schema.js\";\nimport { JobStore } from \"../../store/job-store.js\";\nimport { ArtifactDBStore } from \"../../store/artifact-store.js\";\nimport { loadRunbookForExecution } from \"../helpers/runbook-loader.js\";\nimport { resolveTenantAIConfig, buildModelFactory } from \"../helpers/tenant-ai-config.js\";\nimport { ProgressEmitter } from \"../helpers/progress-emitter.js\";\nimport { ServerLogger, ServerSpinner } from \"../helpers/server-logger.js\";\nimport { getRedisPublisher, createRedisSubscriber } from \"../../redis.js\";\nimport { loadServerConfig } from \"../../config.js\";\nimport { ConfiguredAIModelProvider } from \"../../../harness/ai-service.js\";\nimport { AIMetricsCollector, runWithMetricsCollector } from \"../../../harness/ai-metrics.js\";\nimport { resolvePlanFromTier, enforceFeatureGates } from \"../../../plan/index.js\";\nimport type { PlanTier } from \"../../../plan/index.js\";\nimport { AgentBrowser } from \"../../../browser/browser-client.js\";\nimport { RuntimeStore } from \"../../../context/runtime-store.js\";\nimport { resolveVariablesCore, mergeVariablesAndSecrets } from \"../../../runbook-executor/execution-planner.js\";\nimport { scanStepsForTemplates } from \"../../../context/template-resolver.js\";\nimport {\n serializeSecrets,\n deserializeSecrets,\n} from \"../../../cli/secrets-loader.js\";\nimport type { SecretsData } from \"../../../cli/secrets-loader.js\";\nimport { InMemoryDataStore } from \"../../../context/data-store.js\";\nimport { DownloadManager } from \"../../../context/download-manager.js\";\nimport { execute } from \"../../../runbook-executor/executor.js\";\nimport { analyzeDebugResult } from \"../../../runbook-executor/self-heal-analyzer.js\";\nimport { buildNotificationCard, buildDebugNotificationCard } from \"../../../messaging/cards.js\";\nimport { ScreenshotStreamer } from \"../helpers/screenshot-streamer.js\";\nimport { ServerConfirmationProvider } from \"../helpers/remote-confirmation.js\";\nimport { createTenantChatBot } from \"../helpers/chat-bot-factory.js\";\nimport { GCSArtifactStore } from \"../../../storage/gcs-store.js\";\nimport { LocalArtifactStore } from \"../../../storage/local-store.js\";\nimport type { ArtifactStore } from \"../../../storage/types.js\";\nimport type { SharedChatBot } from \"../../../messaging/chat-bot.js\";\nimport type { ChatPlatform } from \"../../../messaging/config.js\";\nimport { getUserFriendlyAIErrorFromMessage } from \"../../../harness/ai-error.js\";\nimport type { ExecutorConfig, ExecutionReport } from \"../../../runbook-executor/types.js\";\nimport { applyExecutorDefaults, SELF_HEAL_DEFAULTS } from \"../../../runbook-executor/types.js\";\nimport type { DebugReport } from \"../../../runbook-executor/types.js\";\nimport { TelemetryStore } from \"../../store/telemetry-store.js\";\nimport {\n computeJobSummary,\n extractFailureEvents,\n extractResolutionOutcomes,\n deriveFailurePatterns,\n computeRunbookHash,\n} from \"../../telemetry/collector.js\";\n\n/** MIME タイプ推定 */\nfunction guessMimeType(filename: string): string {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n const map: Record<string, string> = {\n csv: \"text/csv\",\n json: \"application/json\",\n xlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n pdf: \"application/pdf\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n webm: \"video/webm\",\n mp4: \"video/mp4\",\n txt: \"text/plain\",\n };\n return map[ext ?? \"\"] ?? \"application/octet-stream\";\n}\n\n/**\n * ジョブ実行 Inngest 関数\n *\n * event: \"job/execute\" { jobId, tenantId }\n * mode=\"execute\" と mode=\"self_heal\" の両方を処理する。\n */\nexport const executeJob = inngest.createFunction(\n {\n id: \"execute-job\",\n timeouts: { finish: \"30m\" },\n retries: 0,\n concurrency: [{ scope: \"account\", key: \"event.data.tenantId\", limit: 3 }],\n onFailure: async ({ event }) => {\n try {\n const originalEvent = event.data.event;\n const { jobId } = originalEvent.data;\n const rawErrorMsg = event.data.error?.message ?? \"Unknown error\";\n const errorMsg = getUserFriendlyAIErrorFromMessage(rawErrorMsg);\n\n const config = loadServerConfig();\n const db = getDb(config.databaseUrl);\n const jobStore = new JobStore(db);\n const redis = getRedisPublisher(config.redisUrl);\n const emitter = new ProgressEmitter(redis, jobId);\n\n console.error(`[execute-job] Function failed for job ${jobId}: ${errorMsg}`);\n await jobStore.updateStatus(jobId, \"failed\", {\n completedAt: new Date(),\n errorMessage: errorMsg,\n });\n await emitter.emitFailed(errorMsg);\n } catch (err) {\n console.error(`[execute-job] onFailure handler itself failed:`, err);\n }\n },\n },\n { event: \"job/execute\" },\n async ({ event, step }) => {\n const { jobId, tenantId } = event.data;\n const serverConfig = loadServerConfig();\n const db = getDb(serverConfig.databaseUrl);\n const jobStore = new JobStore(db);\n const redis = getRedisPublisher(serverConfig.redisUrl);\n const emitter = new ProgressEmitter(redis, jobId);\n const logger = new ServerLogger(jobId, emitter);\n\n // 1. ジョブ + Runbook ロード\n const jobInfo = await step.run(\"load-job\", async () => {\n console.log(`[execute-job] Loading job ${jobId} for tenant ${tenantId}`);\n const job = await jobStore.findById(tenantId, jobId);\n if (!job) throw new Error(`Job ${jobId} not found`);\n if (!job.runbookId) throw new Error(`Job ${jobId} has no runbook`);\n\n // runbookVersionId が記録されている場合はそのバージョンを使用(実行中のバージョン切替に安全)\n const { runbook, secrets } = await loadRunbookForExecution(\n db, tenantId, job.runbookId, serverConfig.encryptionKey,\n job.runbookVersionId ?? undefined,\n );\n\n if (runbook.steps.length === 0) {\n throw new Error(`Runbook for job ${jobId} has 0 steps (runbookId: ${job.runbookId}). Check that runbook steps are saved in the database.`);\n }\n\n console.log(`[execute-job] Job loaded: mode=${job.mode}, runbook steps=${runbook.steps.length}, secrets=${Object.keys(secrets.values).length}`);\n\n return {\n mode: job.mode as \"execute\" | \"self_heal\",\n purpose: job.purpose as string | undefined,\n runbookId: job.runbookId,\n executionConfig: job.executionConfig,\n variables: job.variables,\n runbook,\n secrets: serializeSecrets(secrets),\n };\n });\n\n // 2. AI 設定解決 + Plan ゲート + テナント実行設定\n const resolvedConfig = await step.run(\"resolve-config\", async () => {\n console.log(`[execute-job] Resolving config for tenant ${tenantId}`);\n const [tenant] = await db\n .select({ tier: tenants.tier })\n .from(tenants)\n .where(eq(tenants.id, tenantId))\n .limit(1);\n const tier = (tenant?.tier ?? \"community\") as PlanTier;\n const plan = resolvePlanFromTier(tier, tenantId);\n\n const aiConfig = await resolveTenantAIConfig(db, tenantId, serverConfig.encryptionKey);\n\n // テナント実行設定(approvalMode / notifyMode / artifact settings)\n const execSettings = await db.query.tenantExecutionSettings.findFirst({\n where: eq(tenantExecutionSettings.tenantId, tenantId),\n columns: {\n approvalMode: true,\n notifyMode: true,\n enableScreenshots: true,\n enableVideoRecording: true,\n skills: true,\n },\n });\n\n console.log(`[execute-job] Config resolved: provider=${aiConfig.provider}, model=${aiConfig.modelId}, plan=${plan.tier}`);\n\n return {\n plan,\n aiConfig,\n approvalMode: (execSettings?.approvalMode ?? \"web\") as string,\n notifyMode: (execSettings?.notifyMode ?? null) as string | null,\n enableScreenshots: execSettings?.enableScreenshots ?? false,\n enableVideoRecording: execSettings?.enableVideoRecording ?? false,\n skills: execSettings?.skills ?? [],\n };\n });\n\n // 承認モード判定: isSelfHeal のみスキップ\n const approvalMode = resolvedConfig.approvalMode;\n const isSelfHeal = jobInfo.mode === \"self_heal\";\n const skipConfirmation = isSelfHeal;\n const notifyMode = resolvedConfig.notifyMode;\n\n // チャットプラットフォーム: 承認 or 通知で使うプラットフォームを特定\n // \"web\" の場合は chatBot 不要(ServerConfirmationProvider のみ)\n const approvalPlatform = (!skipConfirmation && approvalMode !== \"web\" ? approvalMode : null) as ChatPlatform | null;\n const chatPlatform: ChatPlatform | null =\n approvalPlatform ?? (notifyMode as ChatPlatform | null);\n\n // ChatBot 生成(step.run の外: SharedChatBot は非シリアライズ)\n let chatBot: SharedChatBot | null = null;\n if (chatPlatform) {\n try {\n chatBot = await createTenantChatBot(\n db, tenantId, serverConfig.encryptionKey, chatPlatform,\n );\n if (!chatBot) {\n console.warn(`[execute-job] ChatBot creation returned null for platform=${chatPlatform}, tenantId=${tenantId}. Check notification credentials.`);\n }\n } catch (err) {\n console.error(`[execute-job] ChatBot creation failed for platform=${chatPlatform}, tenantId=${tenantId}:`, err);\n }\n }\n\n // ConfirmationProvider 生成(step.run の外)\n // \"web\" モードでは chatBot なしで ServerConfirmationProvider を使う(SSE/Redis で Web UI 承認)\n const confirmationProvider = skipConfirmation\n ? undefined\n : new ServerConfirmationProvider(\n db, jobStore, emitter, jobId, serverConfig.redisUrl,\n // 承認プラットフォームとして使う場合のみ chatBot を渡す\n approvalPlatform ? chatBot ?? undefined : undefined,\n );\n\n // 3. ステータス更新: running\n await step.run(\"mark-running\", async () => {\n console.log(`[execute-job] Marking job ${jobId} as running`);\n await jobStore.updateStatus(jobId, \"running\", { startedAt: new Date() });\n await emitter.emitStatusChange(\"running\");\n });\n\n // 4. ブラウザ実行\n let report: ExecutionReport;\n let debugReport: DebugReport | undefined;\n\n // AbortController + Redis cancel 検知(step.run の外で生成)\n const abortController = new AbortController();\n const cancelRedis = createRedisSubscriber(serverConfig.redisUrl);\n const cancelChannel = `job:${jobId}:intervention`;\n await cancelRedis.subscribe(cancelChannel);\n cancelRedis.on(\"message\", (_ch: string, message: string) => {\n try {\n const msg = JSON.parse(message);\n if (msg.type === \"cancel\") abortController.abort();\n } catch { /* ignore */ }\n });\n\n // ConfiguredAIModelProvider(step.run の外で生成)\n const modelFactory = await buildModelFactory(resolvedConfig.aiConfig);\n const aiProvider = new ConfiguredAIModelProvider(resolvedConfig.aiConfig, modelFactory);\n\n // スキルインスタンス初期化(step.run の外: 非シリアライズ)\n let skillInstances: import(\"../../../skills/types.js\").Skill[] | undefined;\n const skillNames = resolvedConfig.skills;\n if (skillNames && skillNames.length > 0) {\n const { initBuiltinSkills, createSkills } = await import(\"../../../skills/registry.js\");\n await initBuiltinSkills();\n skillInstances = createSkills(skillNames);\n console.log(`[execute-job] Skills: ${skillNames.join(\", \")}`);\n }\n\n try {\n report = await step.run(\"execute\", async (): Promise<ExecutionReport> => {\n console.log(`[execute-job] Starting execution for job ${jobId} (mode: ${jobInfo.mode})`);\n const isSelfHeal = jobInfo.mode === \"self_heal\";\n const ec = jobInfo.executionConfig;\n const tmpOutputDir = `/tmp/downloads-${jobId}`;\n\n const executorConfig: ExecutorConfig = {\n runbookPath: \"\",\n headless: true,\n skipConfirmation,\n forceReport: false,\n enableSelectorCache: ec?.enableSelectorCache ?? true,\n enableAgentFallback: ec?.enableAgentFallback ?? true,\n enableVisionFallback: ec?.enableVisionFallback ?? false,\n stepDelay: ec?.stepDelay ?? undefined,\n selfHeal: isSelfHeal,\n aiModelConfig: resolvedConfig.aiConfig,\n contextMarkdown: jobInfo.runbook.context,\n outputDir: tmpOutputDir,\n };\n\n // self-heal デフォルト適用 + Plan ゲート\n applyExecutorDefaults(executorConfig);\n enforceFeatureGates(executorConfig, resolvedConfig.plan);\n\n const collector = new AIMetricsCollector();\n\n // ArtifactStore 初期化\n const artifactStore: ArtifactStore = serverConfig.gcsBucket\n ? new GCSArtifactStore(serverConfig.gcsBucket)\n : new LocalArtifactStore(\"/tmp/artifacts\");\n const artifactDb = new ArtifactDBStore(db);\n\n const result = await runWithMetricsCollector(collector, async () => {\n const browser = new AgentBrowser();\n const screenshotStreamer = new ScreenshotStreamer(browser, emitter);\n\n // スクリーンショット保存有効化(設定で有効、または動作確認時に自動有効化)\n const isVerification = jobInfo.purpose === \"verification\";\n const shouldSaveScreenshots = resolvedConfig.plan.features.screenshotSave\n && (resolvedConfig.enableScreenshots || isVerification);\n if (shouldSaveScreenshots) {\n screenshotStreamer.enableArtifactSaving(\n artifactStore, artifactDb, tenantId, jobId,\n resolvedConfig.plan.limits.maxScreenshots,\n );\n }\n\n // ダウンロードマネージャ(/tmp に一時保存 → 完了後 GCS へ)\n const downloadManager = new DownloadManager(tmpOutputDir);\n\n try {\n const startUrl = jobInfo.runbook.metadata.startUrl;\n if (!startUrl) {\n throw new Error(`Runbook has no startUrl (runbookId: ${jobInfo.runbookId})`);\n }\n await browser.open(startUrl, { headless: true });\n await browser.waitForDOMStability(3000);\n\n screenshotStreamer.start();\n\n // 動画録画開始(Business+ かつ設定で有効 or 動作確認時)\n let videoRecordingEnabled = false;\n const shouldRecordVideo = resolvedConfig.plan.features.videoRecording\n && (resolvedConfig.enableVideoRecording || isVerification);\n if (shouldRecordVideo) {\n try {\n await browser.startRecording(`/tmp/video-${jobId}`);\n videoRecordingEnabled = true;\n } catch { /* ffmpeg not available = skip */ }\n }\n\n // secrets 復元(Inngest step.run シリアライズ後)\n const secretsData: SecretsData | undefined = jobInfo.secrets\n ? deserializeSecrets(jobInfo.secrets as { values: Record<string, string>; keys: string[] })\n : undefined;\n\n // job.variables を secrets にマージ(API body の値が最優先)\n let mergedSecrets = secretsData;\n if (jobInfo.variables?.length) {\n const jobVarValues: Record<string, string> = {};\n for (const v of jobInfo.variables) jobVarValues[v.key] = v.value;\n const { mergedValues, sensitiveKeys } = mergeVariablesAndSecrets(\n jobVarValues,\n mergedSecrets,\n );\n mergedSecrets = {\n values: mergedValues,\n keys: sensitiveKeys,\n };\n }\n\n // resolveVariablesCore で全変数を解決(fixed, expression, context 含む)\n const resolved = await resolveVariablesCore(jobInfo.runbook, {\n secrets: mergedSecrets,\n contextMarkdown: executorConfig.contextMarkdown,\n skipEnv: true,\n aiProvider,\n });\n\n // 未解決の必須変数を検出 → 早期エラーで分かりやすいメッセージ\n const runbookVars = jobInfo.runbook.variables ?? {};\n const captureVarNames = new Set(resolved.captureVars);\n const unresolvedRequired = Object.entries(runbookVars).filter(\n ([name, def]) =>\n !resolved.values.has(name) &&\n !resolved.unresolvedDataVars.includes(name) &&\n !captureVarNames.has(name) &&\n def.required !== false,\n );\n\n if (unresolvedRequired.length > 0) {\n const names = unresolvedRequired.map(([n]) => n).join(\", \");\n throw new Error(\n `Unresolved required variables: ${names}. ` +\n `Configure default values in the runbook settings or provide them via the API.`,\n );\n }\n\n // ステップ内のテンプレート参照もチェック(警告のみ)\n const allTemplateRefs = scanStepsForTemplates(jobInfo.runbook.steps);\n const unresolvedRefs = allTemplateRefs.filter(\n (name) =>\n !resolved.values.has(name) &&\n !resolved.unresolvedDataVars.includes(name) &&\n !captureVarNames.has(name),\n );\n if (unresolvedRefs.length > 0) {\n console.warn(\n `[execute-job] Unresolved template references: ${unresolvedRefs.join(\", \")}. ` +\n `These may cause failures if not resolved at runtime via captures.`,\n );\n }\n\n const store = new RuntimeStore();\n store.seed(resolved.values, resolved.sensitiveKeys);\n\n const dataStore = new InMemoryDataStore();\n\n const execResult = await execute(executorConfig, jobInfo.runbook, {\n store,\n browser,\n logger,\n createSpinner: () => new ServerSpinner(logger),\n dataStore,\n confirmationProvider,\n downloadManager,\n aiProvider,\n skills: skillInstances,\n abortSignal: abortController.signal,\n onStepStart: async (ordinal, description, actionType) => {\n await emitter.emitStepStart(ordinal, description, actionType);\n },\n onStepComplete: async (ordinal, status, durationMs, description, actionType) => {\n await emitter.emitStepComplete(ordinal, status, durationMs);\n await screenshotStreamer.saveStepScreenshot(ordinal);\n // 逐次 DB 保存\n await jobStore.upsertStepResult(jobId, {\n ordinal, description, status, durationMs, actionType,\n }).catch((err) => {\n console.error(`[execute-job] upsertStepResult failed for step ${ordinal}:`, err);\n });\n },\n onStepFailed: async (ordinal, error) => {\n await emitter.emitStepFailed(ordinal, error);\n },\n });\n\n // 動画保存\n if (videoRecordingEnabled) {\n try {\n const { paths } = await browser.stopRecording();\n for (const p of paths) {\n const data = await readFile(p);\n const meta = await artifactStore.save(\n tenantId, jobId, \"video\", basename(p), data, guessMimeType(basename(p)),\n );\n await artifactDb.insert(meta);\n }\n } catch { /* non-fatal */ }\n }\n\n // ダウンロードファイル保存\n for (const dl of downloadManager.getDownloads()) {\n try {\n const data = await readFile(dl.path);\n const meta = await artifactStore.save(\n tenantId, jobId, \"download\", dl.filename, data,\n guessMimeType(dl.filename), dl.stepOrdinal,\n );\n await artifactDb.insert(meta);\n } catch { /* non-fatal */ }\n }\n\n console.log(`[execute-job] Execution result: steps=${execResult.steps?.length ?? 0}, succeeded=${execResult.succeeded}, failed=${execResult.failed}, totalSteps=${execResult.totalSteps}`);\n\n return {\n ...execResult,\n aiMetrics: collector.getSummary(),\n _purgedCount: screenshotStreamer.purgedCount,\n } as ExecutionReport & { _purgedCount: number };\n } finally {\n screenshotStreamer.stop();\n try { await browser.close(); } catch { /* ignore */ }\n }\n });\n\n return result;\n });\n\n // 5. 結果保存\n await step.run(\"save-results\", async () => {\n await jobStore.saveResults(jobId, report);\n });\n\n // 5b. テレメトリ記録\n await step.run(\"save-telemetry\", async () => {\n try {\n const telemetryStore = new TelemetryStore(db);\n\n // 全ジョブでサマリーを記録\n const summary = computeJobSummary(report, {\n tenantId,\n jobId,\n runbookId: jobInfo.runbookId,\n runbookContentHash: computeRunbookHash(jobInfo.runbook),\n mode: jobInfo.mode,\n modelId: resolvedConfig.aiConfig.modelId,\n modelProvider: resolvedConfig.aiConfig.provider,\n });\n await telemetryStore.saveJobSummary(summary);\n\n // 全ステップの解決結果を記録\n const outcomes = extractResolutionOutcomes(report, {\n tenantId,\n jobId,\n runbookId: jobInfo.runbookId,\n });\n if (outcomes.length > 0) {\n await telemetryStore.saveResolutionOutcomes(outcomes);\n }\n\n // 失敗ステップがあればイベント + パターンを記録\n const failedSteps = report.steps.filter((s) => s.status === \"failed\");\n if (failedSteps.length > 0) {\n const events = extractFailureEvents(report, {\n tenantId,\n jobId,\n runbookId: jobInfo.runbookId,\n });\n await telemetryStore.saveFailureEvents(events);\n\n const patterns = deriveFailurePatterns(events);\n await telemetryStore.upsertFailurePatterns(\n tenantId,\n jobInfo.runbookId ?? null,\n patterns,\n );\n }\n\n // 提案検証(過去の適用済み未検証提案を検証)\n await telemetryStore.verifySuggestionOutcomes(\n tenantId,\n jobInfo.runbookId ?? null,\n jobId,\n report,\n );\n } catch (err) {\n console.error(`[execute-job] Telemetry save failed:`, err);\n }\n });\n\n // 6. self_heal モード: 修正提案生成\n if (jobInfo.mode === \"self_heal\") {\n await step.run(\"analyze\", async () => {\n try {\n const result = await analyzeDebugResult(\n report, jobInfo.runbook, 3, jobInfo.runbook.context ?? \"\", aiProvider,\n );\n\n if (result) {\n debugReport = result;\n await jobStore.saveDebugReport(\n jobId,\n result.warningSteps.map((w: { ordinal: number; description?: string; retryCount?: number; threshold?: number }) => ({\n ordinal: w.ordinal,\n description: w.description,\n retryCount: w.retryCount,\n threshold: w.threshold,\n })),\n result.suggestions.map((s: { stepOrdinal?: number; stepDescription?: string; error?: string; runbookFix?: string; contextFix?: string; severity?: string; failureCategory?: string; suggestedStrategy?: string }) => ({\n stepOrdinal: s.stepOrdinal,\n stepDescription: s.stepDescription,\n error: s.error,\n runbookFix: s.runbookFix,\n contextFix: s.contextFix,\n severity: s.severity,\n failureCategory: s.failureCategory,\n suggestedStrategy: s.suggestedStrategy,\n })),\n );\n }\n } catch (err) {\n logger.warn(`Self-heal analysis failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n });\n\n // 6b. self-heal 提案をテレメトリに記録\n if (debugReport?.suggestions?.length && jobInfo.runbookId) {\n await step.run(\"save-suggestion-telemetry\", async () => {\n try {\n const telemetryStore = new TelemetryStore(db);\n await telemetryStore.saveSuggestionOutcomes(\n tenantId,\n jobInfo.runbookId!,\n jobId,\n debugReport!.suggestions,\n );\n } catch (err) {\n console.error(`[execute-job] Suggestion telemetry save failed:`, err);\n }\n });\n }\n }\n\n // 7. 完了(cancel 済みなら上書きしない)\n await step.run(\"mark-terminal-status\", async () => {\n const currentJob = await jobStore.findBasicById(tenantId, jobId);\n if (currentJob?.status === \"cancelled\") {\n await emitter.emitStatusChange(\"cancelled\");\n return;\n }\n\n const hasFailed = report.failed > 0 || report.aborted;\n const jobStatus = hasFailed ? \"failed\" : \"completed\";\n console.log(`[execute-job] Marking job ${jobId} as ${jobStatus}`);\n await jobStore.updateStatus(jobId, jobStatus, { completedAt: new Date() });\n const purgedCount = (report as ExecutionReport & { _purgedCount?: number })._purgedCount ?? 0;\n await emitter.emitCompleted({\n steps: report.steps.length,\n failed: report.steps.filter((s) => s.status === \"failed\").length,\n ...(purgedCount > 0 ? { artifactsPurged: purgedCount } : {}),\n });\n });\n\n // 8. 通知\n if (chatBot && notifyMode) {\n await step.run(\"notify\", async () => {\n try {\n await chatBot!.ensureInitialized();\n const card = (jobInfo.mode === \"self_heal\" && debugReport)\n ? buildDebugNotificationCard(debugReport)\n : buildNotificationCard(report);\n await chatBot!.getChannel().post(card);\n } catch {\n // 通知失敗は無視\n }\n });\n }\n\n return { jobId, status: \"completed\" };\n } finally {\n // クリーンアップ\n cancelRedis.unsubscribe(cancelChannel).catch(() => {});\n cancelRedis.quit().catch(() => {});\n if (chatBot) {\n try { await chatBot.dispose(); } catch { /* ignore */ }\n }\n }\n },\n);\n","import { drizzle } from \"drizzle-orm/node-postgres\";\nimport pg from \"pg\";\nimport * as schema from \"./schema.js\";\n\nlet _db: ReturnType<typeof drizzle<typeof schema>> | null = null;\nlet _pool: pg.Pool | null = null;\n\nexport function getDb(databaseUrl?: string) {\n if (!_db) {\n const url = databaseUrl ?? process.env.DATABASE_URL;\n if (!url) {\n throw new Error(\"DATABASE_URL is required\");\n }\n _pool = new pg.Pool({ connectionString: url });\n _db = drizzle(_pool, { schema });\n }\n return _db;\n}\n\nexport function getPool(): pg.Pool {\n if (!_pool) {\n throw new Error(\"Database not initialized. Call getDb() first.\");\n }\n return _pool;\n}\n\nexport async function closeDb(): Promise<void> {\n if (_pool) {\n await _pool.end();\n _pool = null;\n _db = null;\n }\n}\n","import { eq, and, desc, count, sql } from \"drizzle-orm\";\nimport type { getDb } from \"../db/client.js\";\nimport {\n jobs,\n jobExecutionConfigs,\n jobVariables,\n jobResults,\n jobResultDiagnostics,\n jobAiMetrics,\n jobGenerateConfigs,\n jobRecordedSteps,\n jobReviewResults,\n jobReviewedSteps,\n jobDebugWarnings,\n jobDebugSuggestions,\n} from \"../db/schema.js\";\nimport type {\n ExecutionReport,\n} from \"../../runbook-executor/types.js\";\nimport type { JobStatus, JobMode } from \"../types/job-types.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\nexport type JobPurpose = \"verification\" | \"scheduled\" | \"manual\" | \"api\" | \"generation\";\n\nexport interface JobExecutionConfig {\n defaultTimeout: number;\n pauseBetweenSteps: number;\n stopOnError: boolean;\n stepDelay?: number;\n enableSelectorCache: boolean;\n enableAgentFallback: boolean;\n enableVisionFallback: boolean;\n modelId?: string;\n modelProvider?: string;\n}\n\nexport interface JobGenerateConfig {\n maxIterations?: number;\n stepDelay?: number;\n headless?: boolean;\n snapshotFilter?: boolean;\n stallCheckInterval?: number;\n historyWindow?: number;\n maxConsecutiveFailures?: number;\n screenshotDir?: string;\n videoDir?: string;\n stealth?: boolean;\n proxy?: string;\n modelId?: string;\n modelProvider?: string;\n skills?: string[];\n}\n\nexport interface JobInsertData {\n tenantId: string;\n mode?: JobMode;\n status?: JobStatus;\n runbookId?: string;\n runbookVersionId?: string;\n totalSteps?: number;\n createdBy?: string;\n purpose?: JobPurpose;\n variables?: { key: string; value: string; sensitive: boolean }[];\n executionConfig?: JobExecutionConfig;\n // 予約実行用\n scheduledAt?: Date;\n scheduleId?: string;\n // generate モード用\n startUrl?: string;\n goal?: string;\n context?: string;\n generateConfig?: JobGenerateConfig;\n}\n\nexport class JobStore {\n constructor(private db: Db) {}\n\n async insert(data: JobInsertData) {\n return await this.db.transaction(async (tx) => {\n const [row] = await tx\n .insert(jobs)\n .values({\n tenantId: data.tenantId,\n mode: data.mode ?? \"execute\",\n status: data.status ?? \"queued\",\n runbookId: data.runbookId ?? null,\n runbookVersionId: data.runbookVersionId ?? null,\n totalSteps: data.totalSteps ?? 0,\n purpose: data.purpose ?? \"manual\",\n createdBy: data.createdBy ?? null,\n scheduledAt: data.scheduledAt ?? null,\n scheduleId: data.scheduleId ?? null,\n startUrl: data.startUrl ?? null,\n goal: data.goal ?? null,\n context: data.context ?? null,\n })\n .returning();\n\n if (data.executionConfig) {\n await tx.insert(jobExecutionConfigs).values({\n jobId: row.id,\n ...data.executionConfig,\n });\n }\n\n if (data.generateConfig) {\n const gc = data.generateConfig;\n await tx.insert(jobGenerateConfigs).values({\n jobId: row.id,\n ...(gc.maxIterations !== undefined && { maxIterations: gc.maxIterations }),\n ...(gc.stepDelay !== undefined && { stepDelay: gc.stepDelay }),\n ...(gc.headless !== undefined && { headless: gc.headless }),\n ...(gc.snapshotFilter !== undefined && { snapshotFilter: gc.snapshotFilter }),\n ...(gc.stallCheckInterval !== undefined && { stallCheckInterval: gc.stallCheckInterval }),\n ...(gc.historyWindow !== undefined && { historyWindow: gc.historyWindow }),\n ...(gc.maxConsecutiveFailures !== undefined && { maxConsecutiveFailures: gc.maxConsecutiveFailures }),\n ...(gc.screenshotDir !== undefined && { screenshotDir: gc.screenshotDir }),\n ...(gc.videoDir !== undefined && { videoDir: gc.videoDir }),\n ...(gc.stealth !== undefined && { stealth: gc.stealth }),\n ...(gc.proxy !== undefined && { proxy: gc.proxy }),\n ...(gc.modelId !== undefined && { modelId: gc.modelId }),\n ...(gc.modelProvider !== undefined && { modelProvider: gc.modelProvider }),\n ...(gc.skills !== undefined && { skills: gc.skills }),\n });\n }\n\n if (data.variables && data.variables.length > 0) {\n await tx.insert(jobVariables).values(\n data.variables.map((v) => ({\n jobId: row.id,\n key: v.key,\n value: v.value,\n sensitive: v.sensitive,\n })),\n );\n }\n\n return row;\n });\n }\n\n /** control 操作用の軽量クエリ(mode + status のみ) */\n async findBasicById(tenantId: string, id: string) {\n const row = await this.db.query.jobs.findFirst({\n where: and(eq(jobs.id, id), eq(jobs.tenantId, tenantId)),\n columns: { id: true, mode: true, status: true },\n });\n return row ?? null;\n }\n\n async findById(tenantId: string, id: string) {\n const row = await this.db.query.jobs.findFirst({\n where: and(eq(jobs.id, id), eq(jobs.tenantId, tenantId)),\n });\n if (!row) return null;\n\n const [execConfig, vars, results, aiMetrics] = await Promise.all([\n this.db.query.jobExecutionConfigs.findFirst({\n where: eq(jobExecutionConfigs.jobId, id),\n }),\n this.db.query.jobVariables.findMany({\n where: eq(jobVariables.jobId, id),\n }),\n this.db.query.jobResults.findMany({\n where: eq(jobResults.jobId, id),\n orderBy: [jobResults.ordinal],\n }),\n this.db.query.jobAiMetrics.findFirst({\n where: eq(jobAiMetrics.jobId, id),\n }),\n ]);\n\n // diagnostics を結果に付帯\n const resultIds = results.map((r) => r.id);\n let diagnosticsMap = new Map<string, typeof jobResultDiagnostics.$inferSelect>();\n if (resultIds.length > 0) {\n const allDiag = await Promise.all(\n resultIds.map((rid) =>\n this.db.query.jobResultDiagnostics.findFirst({\n where: eq(jobResultDiagnostics.jobResultId, rid),\n }),\n ),\n );\n for (const d of allDiag) {\n if (d) diagnosticsMap.set(d.jobResultId, d);\n }\n }\n\n // generate モード用データ\n let generateConfig = null;\n let recordedSteps = null;\n let reviewResult = null;\n if (row.mode === \"generate\") {\n [generateConfig, recordedSteps, reviewResult] = await Promise.all([\n this.db.query.jobGenerateConfigs.findFirst({\n where: eq(jobGenerateConfigs.jobId, id),\n }),\n this.db.query.jobRecordedSteps.findMany({\n where: eq(jobRecordedSteps.jobId, id),\n orderBy: [jobRecordedSteps.ordinal],\n }),\n this.db.query.jobReviewResults.findFirst({\n where: eq(jobReviewResults.jobId, id),\n }),\n ]);\n }\n\n // self_heal モード用データ\n let debugWarnings = null;\n let debugSuggestions = null;\n if (row.mode === \"self_heal\") {\n [debugWarnings, debugSuggestions] = await Promise.all([\n this.db.query.jobDebugWarnings.findMany({\n where: eq(jobDebugWarnings.jobId, id),\n orderBy: [jobDebugWarnings.ordinal],\n }),\n this.db.query.jobDebugSuggestions.findMany({\n where: eq(jobDebugSuggestions.jobId, id),\n }),\n ]);\n }\n\n return {\n ...row,\n executionConfig: execConfig ?? null,\n variables: vars,\n results: results.map((r) => ({\n ...r,\n diagnostics: diagnosticsMap.get(r.id) ?? null,\n })),\n aiMetrics: aiMetrics ?? null,\n generateConfig: generateConfig ?? null,\n recordedSteps: recordedSteps ?? null,\n reviewResult: reviewResult ?? null,\n debugWarnings: debugWarnings ?? null,\n debugSuggestions: debugSuggestions ?? null,\n };\n }\n\n async list(\n tenantId: string,\n opts: {\n runbookId?: string;\n status?: JobStatus;\n mode?: JobMode;\n limit?: number;\n offset?: number;\n } = {},\n ) {\n const { runbookId, status, mode, limit = 50, offset = 0 } = opts;\n\n const conditions = [eq(jobs.tenantId, tenantId)];\n if (runbookId) conditions.push(eq(jobs.runbookId, runbookId));\n if (status) conditions.push(eq(jobs.status, status));\n if (mode) conditions.push(eq(jobs.mode, mode));\n\n const where = and(...conditions);\n\n const rows = await this.db\n .select()\n .from(jobs)\n .where(where)\n .orderBy(desc(jobs.createdAt))\n .limit(limit)\n .offset(offset);\n\n const [totalResult] = await this.db\n .select({ count: count() })\n .from(jobs)\n .where(where);\n\n return { items: rows, total: totalResult.count };\n }\n\n async updateStatus(\n id: string,\n status: JobStatus,\n extras?: {\n currentStep?: number;\n errorMessage?: string;\n startedAt?: Date;\n completedAt?: Date;\n },\n ) {\n await this.db\n .update(jobs)\n .set({\n status,\n ...(extras?.currentStep !== undefined && {\n currentStep: extras.currentStep,\n }),\n ...(extras?.errorMessage !== undefined && {\n errorMessage: extras.errorMessage,\n }),\n ...(extras?.startedAt && { startedAt: extras.startedAt }),\n ...(extras?.completedAt && { completedAt: extras.completedAt }),\n })\n .where(eq(jobs.id, id));\n }\n\n async setAdoptedRunbook(id: string, runbookId: string) {\n await this.db\n .update(jobs)\n .set({ adoptedRunbookId: runbookId })\n .where(eq(jobs.id, id));\n }\n\n /** scheduleId に紐づく scheduled ステータスのジョブを検索 */\n async findScheduledByScheduleId(scheduleId: string) {\n const row = await this.db.query.jobs.findFirst({\n where: and(eq(jobs.scheduleId, scheduleId), eq(jobs.status, \"scheduled\")),\n columns: { id: true },\n });\n return row ?? null;\n }\n\n async delete(id: string) {\n const result = await this.db\n .delete(jobs)\n .where(eq(jobs.id, id))\n .returning({ id: jobs.id });\n return result.length > 0;\n }\n\n /** 実行中のステップ結果を逐次保存(upsert) */\n async upsertStepResult(jobId: string, result: {\n ordinal: number;\n description: string;\n status: string;\n durationMs: number;\n actionType?: string;\n error?: string;\n retryCount?: number;\n failureCategory?: string;\n }) {\n await this.db.insert(jobResults).values({\n jobId,\n ordinal: result.ordinal,\n description: result.description,\n status: result.status as \"success\" | \"failed\" | \"skipped\",\n durationMs: result.durationMs,\n actionType: result.actionType ?? null,\n error: result.error ?? null,\n retryCount: result.retryCount ?? 0,\n failureCategory: result.failureCategory ?? null,\n }).onConflictDoUpdate({\n target: [jobResults.jobId, jobResults.ordinal],\n set: {\n description: sql`excluded.description`,\n status: sql`excluded.status`,\n durationMs: sql`excluded.duration_ms`,\n actionType: sql`excluded.action_type`,\n error: sql`excluded.error`,\n retryCount: sql`excluded.retry_count`,\n failureCategory: sql`excluded.failure_category`,\n },\n });\n }\n\n async saveResults(jobId: string, report: ExecutionReport) {\n await this.db.transaction(async (tx) => {\n for (const step of report.steps) {\n const [resultRow] = await tx\n .insert(jobResults)\n .values({\n jobId,\n ordinal: step.ordinal,\n description: step.description,\n status: step.status,\n durationMs: step.durationMs,\n error: step.error ?? null,\n actionType: step.actionType ?? null,\n retryCount: step.retryCount ?? 0,\n failureCategory: step.failureCategory ?? null,\n capturedValues: step.capturedValues ?? null,\n conditionSkipped: step.conditionSkipped ?? false,\n loopIterations: step.loopIterations ?? null,\n branchMatch: step.branchMatch ?? null,\n forEachItemCount: step.forEachItemCount ?? null,\n extractedData: step.extractedData ?? null,\n downloadedFile: step.downloadedFile ?? null,\n exportedFile: step.exportedFile ?? null,\n })\n .onConflictDoUpdate({\n target: [jobResults.jobId, jobResults.ordinal],\n set: {\n description: sql`excluded.description`,\n status: sql`excluded.status`,\n durationMs: sql`excluded.duration_ms`,\n error: sql`excluded.error`,\n actionType: sql`excluded.action_type`,\n retryCount: sql`excluded.retry_count`,\n failureCategory: sql`excluded.failure_category`,\n capturedValues: sql`excluded.captured_values`,\n conditionSkipped: sql`excluded.condition_skipped`,\n loopIterations: sql`excluded.loop_iterations`,\n branchMatch: sql`excluded.branch_match`,\n forEachItemCount: sql`excluded.for_each_item_count`,\n extractedData: sql`excluded.extracted_data`,\n downloadedFile: sql`excluded.downloaded_file`,\n exportedFile: sql`excluded.exported_file`,\n },\n })\n .returning();\n\n if (step.diagnostics) {\n const d = step.diagnostics;\n await tx.insert(jobResultDiagnostics).values({\n jobResultId: resultRow.id,\n lastSnapshotPreview: d.lastSnapshotPreview ?? null,\n failureHistory: d.failureHistory ?? null,\n lastAiResponseText: d.lastAiResponseText ?? null,\n recoveryHint: d.recoveryHint ?? null,\n deterministicResolveResult: d.deterministicResolveResult ?? null,\n visionFallbackResult: d.visionFallbackResult ?? null,\n agentFallbackResult: d.agentFallbackResult ?? null,\n validationWarnings: d.validationWarnings ?? null,\n validationErrors: d.validationErrors ?? null,\n stepUrl: d.stepUrl ?? null,\n });\n }\n }\n\n if (report.aiMetrics) {\n const m = report.aiMetrics;\n await tx.insert(jobAiMetrics).values({\n jobId,\n totalCalls: m.totalCalls,\n totalInputTokens: m.totalInputTokens,\n totalOutputTokens: m.totalOutputTokens,\n totalCachedInputTokens: m.totalCachedInputTokens,\n totalCacheCreationTokens: m.totalCacheCreationTokens,\n cacheHitRate: m.cacheHitRate,\n estimatedCostUsd: m.estimatedCostUsd,\n totalDurationMs: m.totalDurationMs,\n });\n }\n });\n }\n\n /** generate モード: 探索結果の RecordedStep を保存 */\n async saveRecordedSteps(\n jobId: string,\n steps: {\n ordinal: number;\n actionType: string;\n selector?: string;\n value?: string;\n description?: string;\n inputCategory?: string;\n variableName?: string;\n url?: string;\n success?: boolean;\n error?: string;\n screenshotPath?: string;\n failureCategory?: string;\n durationMs?: number;\n snapshotBefore?: string;\n suggestedCaptures?: unknown;\n script?: string;\n extractPrompt?: string;\n memoryCollection?: string;\n aggregation?: unknown;\n downloadPath?: string;\n exportCollection?: string;\n exportFormat?: string;\n exportPath?: string;\n keys?: string;\n }[],\n ) {\n if (steps.length === 0) return;\n await this.db.insert(jobRecordedSteps).values(\n steps.map((s) => ({\n jobId,\n ordinal: s.ordinal,\n actionType: s.actionType,\n selector: s.selector ?? null,\n value: s.value ?? null,\n description: s.description ?? null,\n inputCategory: s.inputCategory ?? null,\n variableName: s.variableName ?? null,\n url: s.url ?? null,\n success: s.success ?? null,\n error: s.error ?? null,\n screenshotPath: s.screenshotPath ?? null,\n failureCategory: s.failureCategory ?? null,\n durationMs: s.durationMs ?? null,\n snapshotBefore: s.snapshotBefore ?? null,\n suggestedCaptures: s.suggestedCaptures ?? null,\n script: s.script ?? null,\n extractPrompt: s.extractPrompt ?? null,\n memoryCollection: s.memoryCollection ?? null,\n aggregation: s.aggregation ?? null,\n downloadPath: s.downloadPath ?? null,\n exportCollection: s.exportCollection ?? null,\n exportFormat: s.exportFormat ?? null,\n exportPath: s.exportPath ?? null,\n keys: s.keys ?? null,\n })),\n ).onConflictDoUpdate({\n target: [jobRecordedSteps.jobId, jobRecordedSteps.ordinal],\n set: {\n actionType: sql`excluded.action_type`,\n selector: sql`excluded.selector`,\n value: sql`excluded.value`,\n description: sql`excluded.description`,\n inputCategory: sql`excluded.input_category`,\n variableName: sql`excluded.variable_name`,\n url: sql`excluded.url`,\n success: sql`excluded.success`,\n error: sql`excluded.error`,\n screenshotPath: sql`excluded.screenshot_path`,\n failureCategory: sql`excluded.failure_category`,\n durationMs: sql`excluded.duration_ms`,\n snapshotBefore: sql`excluded.snapshot_before`,\n suggestedCaptures: sql`excluded.suggested_captures`,\n script: sql`excluded.script`,\n extractPrompt: sql`excluded.extract_prompt`,\n memoryCollection: sql`excluded.memory_collection`,\n aggregation: sql`excluded.aggregation`,\n downloadPath: sql`excluded.download_path`,\n exportCollection: sql`excluded.export_collection`,\n exportFormat: sql`excluded.export_format`,\n exportPath: sql`excluded.export_path`,\n keys: sql`excluded.keys`,\n },\n });\n }\n\n /** generate モード: レビュー結果を保存 */\n async saveReviewResult(\n jobId: string,\n review: {\n summary?: string;\n yamlContent?: string;\n goalAchieved?: boolean;\n reviewedSteps?: {\n originalOrdinal: number;\n keep: boolean;\n removalReason?: string;\n riskLevel?: string;\n requiresConfirmation?: boolean;\n confirmationReason?: string;\n }[];\n },\n ) {\n await this.db.transaction(async (tx) => {\n const [reviewRow] = await tx\n .insert(jobReviewResults)\n .values({\n jobId,\n summary: review.summary ?? null,\n yamlContent: review.yamlContent ?? null,\n goalAchieved: review.goalAchieved ?? null,\n })\n .returning();\n\n if (review.reviewedSteps && review.reviewedSteps.length > 0) {\n await tx.insert(jobReviewedSteps).values(\n review.reviewedSteps.map((s) => ({\n reviewResultId: reviewRow.id,\n originalOrdinal: s.originalOrdinal,\n keep: s.keep,\n removalReason: s.removalReason ?? null,\n riskLevel: s.riskLevel ?? null,\n requiresConfirmation: s.requiresConfirmation ?? null,\n confirmationReason: s.confirmationReason ?? null,\n })),\n );\n }\n });\n }\n\n /** self_heal モード: デバッグレポートを保存 */\n async saveDebugReport(\n jobId: string,\n warningSteps: {\n ordinal: number;\n description?: string;\n retryCount?: number;\n threshold?: number;\n }[],\n suggestions: {\n stepOrdinal?: number;\n stepDescription?: string;\n error?: string;\n runbookFix?: string;\n contextFix?: string;\n severity?: string;\n failureCategory?: string;\n suggestedStrategy?: string;\n }[],\n ) {\n await this.db.transaction(async (tx) => {\n if (warningSteps.length > 0) {\n await tx.insert(jobDebugWarnings).values(\n warningSteps.map((w) => ({\n jobId,\n ordinal: w.ordinal,\n description: w.description ?? null,\n retryCount: w.retryCount ?? null,\n threshold: w.threshold ?? null,\n })),\n );\n }\n\n if (suggestions.length > 0) {\n await tx.insert(jobDebugSuggestions).values(\n suggestions.map((s) => ({\n jobId,\n stepOrdinal: s.stepOrdinal ?? null,\n stepDescription: s.stepDescription ?? null,\n error: s.error ?? null,\n runbookFix: s.runbookFix ?? null,\n contextFix: s.contextFix ?? null,\n severity: s.severity ?? null,\n failureCategory: s.failureCategory ?? null,\n suggestedStrategy: s.suggestedStrategy ?? null,\n })),\n );\n }\n });\n }\n}\n","/**\n * store/artifact-store --- アーティファクト DB ストア\n *\n * job_artifacts テーブルの CRUD 操作。\n */\n\nimport { eq, and, asc, inArray } from \"drizzle-orm\";\nimport { jobArtifacts } from \"../db/schema.js\";\nimport type { ArtifactType, ArtifactMetadata } from \"../../storage/types.js\";\nimport type { getDb } from \"../db/client.js\";\n\nexport type JobArtifact = typeof jobArtifacts.$inferSelect;\n\nexport class ArtifactDBStore {\n constructor(private db: ReturnType<typeof getDb>) {}\n\n async insert(metadata: ArtifactMetadata): Promise<void> {\n await this.db.insert(jobArtifacts).values({\n jobId: metadata.jobId,\n tenantId: metadata.tenantId,\n type: metadata.type,\n filename: metadata.filename,\n storagePath: metadata.storagePath,\n contentType: metadata.contentType,\n sizeBytes: metadata.sizeBytes,\n stepOrdinal: metadata.stepOrdinal,\n });\n }\n\n async insertBatch(list: ArtifactMetadata[]): Promise<void> {\n if (list.length === 0) return;\n await this.db.insert(jobArtifacts).values(\n list.map((m) => ({\n jobId: m.jobId,\n tenantId: m.tenantId,\n type: m.type,\n filename: m.filename,\n storagePath: m.storagePath,\n contentType: m.contentType,\n sizeBytes: m.sizeBytes,\n stepOrdinal: m.stepOrdinal,\n })),\n );\n }\n\n async listByJob(\n tenantId: string,\n jobId: string,\n type?: ArtifactType,\n ): Promise<JobArtifact[]> {\n const conditions = [\n eq(jobArtifacts.tenantId, tenantId),\n eq(jobArtifacts.jobId, jobId),\n ];\n if (type) {\n conditions.push(eq(jobArtifacts.type, type));\n }\n return this.db\n .select()\n .from(jobArtifacts)\n .where(and(...conditions))\n .orderBy(jobArtifacts.createdAt);\n }\n\n async findById(\n tenantId: string,\n id: string,\n ): Promise<JobArtifact | undefined> {\n const [row] = await this.db\n .select()\n .from(jobArtifacts)\n .where(and(eq(jobArtifacts.tenantId, tenantId), eq(jobArtifacts.id, id)))\n .limit(1);\n return row;\n }\n\n /**\n * 指定ジョブ ID 群のうち、アーティファクトが存在するジョブ ID のセットを返す。\n */\n async hasArtifactsByJobIds(\n tenantId: string,\n jobIds: string[],\n ): Promise<Set<string>> {\n if (jobIds.length === 0) return new Set();\n const rows = await this.db\n .selectDistinct({ jobId: jobArtifacts.jobId })\n .from(jobArtifacts)\n .where(\n and(\n eq(jobArtifacts.tenantId, tenantId),\n inArray(jobArtifacts.jobId, jobIds),\n ),\n );\n return new Set(rows.map((r) => r.jobId));\n }\n\n async deleteByJob(jobId: string): Promise<void> {\n await this.db\n .delete(jobArtifacts)\n .where(eq(jobArtifacts.jobId, jobId));\n }\n\n /**\n * テナントの指定タイプのアーティファクト数をカウントし、\n * 上限を超える分の古いレコードを削除して storagePath を返す。\n * 呼び出し元で GCS からも削除する。\n */\n async rotateOldest(\n tenantId: string,\n type: ArtifactType,\n maxCount: number,\n ): Promise<{ purgedCount: number; purgedPaths: string[] }> {\n if (maxCount === Infinity || maxCount <= 0) {\n return { purgedCount: 0, purgedPaths: [] };\n }\n\n // 古い順に全レコード取得\n const all = await this.db\n .select({ id: jobArtifacts.id, storagePath: jobArtifacts.storagePath })\n .from(jobArtifacts)\n .where(and(eq(jobArtifacts.tenantId, tenantId), eq(jobArtifacts.type, type)))\n .orderBy(asc(jobArtifacts.createdAt));\n\n const excess = all.length - maxCount;\n if (excess <= 0) {\n return { purgedCount: 0, purgedPaths: [] };\n }\n\n const toDelete = all.slice(0, excess);\n const ids = toDelete.map((r) => r.id);\n const paths = toDelete.map((r) => r.storagePath);\n\n // バッチ削除\n await this.db\n .delete(jobArtifacts)\n .where(inArray(jobArtifacts.id, ids));\n\n return { purgedCount: ids.length, purgedPaths: paths };\n }\n}\n","/**\n * DB runbook → ParsedRunbook 変換\n *\n * runbooks + runbook_versions + runbookSteps + runbookVariables + runbookSecrets テーブルから\n * ParsedRunbook を構築する。\n *\n * バージョン対応: versionId が指定された場合はそのバージョンを使用。\n * 未指定時は activeVersionId を使用。\n */\n\nimport { eq } from \"drizzle-orm\";\nimport type { getDb } from \"../../db/client.js\";\nimport {\n runbooks,\n runbookVersions,\n runbookSteps,\n runbookVariables,\n runbookSecrets,\n runbookSettings,\n} from \"../../db/schema.js\";\nimport { decrypt } from \"../../crypto.js\";\nimport type { ParsedRunbook } from \"../../../runbook-executor/types.js\";\nimport type { SecretsData } from \"../../../cli/secrets-loader.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\n/**\n * DB から runbook を読み込み、executor 互換の ParsedRunbook + secrets を返す。\n * versionId が指定された場合はそのバージョンを使用。未指定時は activeVersionId を使用。\n */\nexport async function loadRunbookForExecution(\n db: Db,\n tenantId: string,\n runbookId: string,\n encryptionKey: string,\n versionId?: string,\n): Promise<{ runbook: ParsedRunbook; secrets: SecretsData; versionId: string }> {\n const [rb] = await db\n .select()\n .from(runbooks)\n .where(eq(runbooks.id, runbookId))\n .limit(1);\n\n if (!rb || rb.tenantId !== tenantId) {\n throw new Error(`Runbook ${runbookId} not found for tenant ${tenantId}`);\n }\n\n // バージョン解決: 明示指定 > activeVersionId\n const resolvedVersionId = versionId ?? rb.activeVersionId;\n if (!resolvedVersionId) {\n throw new Error(`Runbook ${runbookId} has no active version`);\n }\n\n const [ver] = await db\n .select()\n .from(runbookVersions)\n .where(eq(runbookVersions.id, resolvedVersionId))\n .limit(1);\n\n if (!ver) {\n throw new Error(`Version ${resolvedVersionId} not found for runbook ${runbookId}`);\n }\n\n const [steps, variables, secretsRows, settings] = await Promise.all([\n db\n .select()\n .from(runbookSteps)\n .where(eq(runbookSteps.versionId, resolvedVersionId))\n .orderBy(runbookSteps.ordinal),\n db\n .select()\n .from(runbookVariables)\n .where(eq(runbookVariables.versionId, resolvedVersionId)),\n db\n .select()\n .from(runbookSecrets)\n .where(eq(runbookSecrets.versionId, resolvedVersionId)),\n db.query.runbookSettings.findFirst({\n where: eq(runbookSettings.versionId, resolvedVersionId),\n }),\n ]);\n\n // secrets の復号\n const secretValues: Record<string, string> = {};\n const secretKeys = new Set<string>();\n let decryptFailed = 0;\n for (const s of secretsRows) {\n try {\n secretValues[s.key] = decrypt(s.encryptedValue, encryptionKey);\n secretKeys.add(s.key);\n } catch (e) {\n decryptFailed++;\n console.warn(`[runbook-loader] Failed to decrypt secret \"${s.key}\": ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n if (decryptFailed > 0) {\n console.warn(`[runbook-loader] ${decryptFailed}/${secretsRows.length} secrets failed to decrypt`);\n }\n const secretsData: SecretsData = { values: secretValues, keys: secretKeys };\n\n // steps をツリー構造に変換\n const topLevelSteps = steps.filter((s) => !s.parentStepId);\n const childMap = new Map<string, typeof steps>();\n for (const s of steps) {\n if (s.parentStepId) {\n const children = childMap.get(s.parentStepId) ?? [];\n children.push(s);\n childMap.set(s.parentStepId, children);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function convertStep(dbStep: (typeof steps)[0]): any {\n const children = childMap.get(dbStep.id) ?? [];\n\n const action: Record<string, unknown> = {\n type: dbStep.actionType,\n };\n if (dbStep.url) action.url = dbStep.url;\n if (dbStep.value) action.value = dbStep.value;\n if (dbStep.optionText) action.optionText = dbStep.optionText;\n if (dbStep.script) action.script = dbStep.script;\n if (dbStep.keys) action.keys = dbStep.keys;\n if (dbStep.downloadPath) action.downloadPath = dbStep.downloadPath;\n if (dbStep.exportCollection) action.exportCollection = dbStep.exportCollection;\n if (dbStep.exportFormat) action.exportFormat = dbStep.exportFormat;\n if (dbStep.exportPath) action.exportPath = dbStep.exportPath;\n if (dbStep.selector) action.selector = dbStep.selector;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const step: any = {\n ordinal: dbStep.ordinal,\n description: dbStep.description,\n action,\n url: dbStep.url ?? \"\",\n riskLevel: dbStep.riskLevel ?? \"low\",\n requiresConfirmation: dbStep.requiresConfirmation,\n };\n\n if (dbStep.condition) step.condition = dbStep.condition;\n if (dbStep.captures) step.captures = dbStep.captures;\n if (dbStep.memoryOperations) step.memoryOperations = dbStep.memoryOperations;\n\n if (dbStep.loopCondition || dbStep.loopForEach) {\n step.loop = {\n ...(dbStep.loopCondition && { condition: dbStep.loopCondition }),\n ...(dbStep.loopForEach && { forEach: dbStep.loopForEach }),\n ...(dbStep.loopItemVariable && { itemVariable: dbStep.loopItemVariable }),\n ...(dbStep.loopIndexVariable && { indexVariable: dbStep.loopIndexVariable }),\n ...(dbStep.loopMaxIterations && { maxIterations: dbStep.loopMaxIterations }),\n ...(dbStep.loopCounterVariable && { counterVariable: dbStep.loopCounterVariable }),\n steps: children.map(convertStep),\n };\n }\n\n if (dbStep.branchValue) {\n step.branches = {\n value: dbStep.branchValue,\n cases: children\n .filter((c) => !c.branchIsDefault)\n .map((c) => ({\n match: c.branchCaseMatch ?? \"\",\n steps: (childMap.get(c.id) ?? []).map(convertStep),\n })),\n };\n const defaultChild = children.find((c) => c.branchIsDefault);\n if (defaultChild) {\n step.branches.default = {\n steps: (childMap.get(defaultChild.id) ?? []).map(convertStep),\n };\n }\n }\n\n return step;\n }\n\n const parsedSteps = topLevelSteps.map(convertStep);\n\n console.log(`[runbook-loader] Loaded runbook ${runbookId} (version ${resolvedVersionId}): ${steps.length} steps (${topLevelSteps.length} top-level), ${variables.length} variables, ${secretsRows.length} secrets`);\n\n // variables を Record<string, VariableDefinition> に変換\n const varsRecord: Record<string, { source: string; description?: string; required?: boolean; sensitive?: boolean; value?: string }> = {};\n for (const v of variables) {\n varsRecord[v.name] = {\n source: v.source,\n ...(v.description && { description: v.description }),\n ...(v.required && { required: v.required }),\n ...(v.sensitive && { sensitive: v.sensitive }),\n ...(v.value != null && { value: v.value }),\n };\n }\n\n const parsedRunbook = {\n title: rb.title,\n settings: {\n baseUrl: ver.startUrl ?? \"\",\n defaultTimeout: settings?.defaultTimeout ?? 10000,\n pauseBetweenSteps: settings?.pauseBetweenSteps ?? 500,\n stopOnError: settings?.stopOnError ?? true,\n },\n metadata: {\n startUrl: ver.startUrl ?? \"\",\n goal: ver.goal,\n goalAchieved: true,\n totalSteps: parsedSteps.length,\n generatedAt: ver.generatedAt ?? new Date().toISOString(),\n },\n steps: parsedSteps,\n ...(Object.keys(varsRecord).length > 0 && { variables: varsRecord }),\n ...(ver.context && { context: ver.context }),\n } as ParsedRunbook;\n\n return { runbook: parsedRunbook, secrets: secretsData, versionId: resolvedVersionId };\n}\n","/**\n * Redis Pub/Sub 進捗イベント発行\n *\n * Inngest 関数内でステップ進捗・ステータス変更をリアルタイムに配信する。\n * SSE エンドポイント(PR10)が `job:{jobId}:events` チャネルを subscribe し、\n * クライアントにストリーミングする。\n */\n\nimport type Redis from \"ioredis\";\nimport type { SSEEvent } from \"../../sse/types.js\";\n\nexport class ProgressEmitter {\n private channel: string;\n\n constructor(\n private redis: Redis,\n jobId: string,\n ) {\n this.channel = `job:${jobId}:events`;\n }\n\n /** SSE イベントを Redis チャネルに publish */\n async emit(event: Omit<SSEEvent, \"timestamp\"> & { timestamp?: string }): Promise<void> {\n const fullEvent: SSEEvent = {\n ...event,\n timestamp: event.timestamp ?? new Date().toISOString(),\n };\n try {\n await this.redis.publish(this.channel, JSON.stringify(fullEvent));\n } catch (err) {\n console.warn(`[ProgressEmitter] Redis publish failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n /** ステータス変更イベント */\n async emitStatusChange(status: string, extras?: Record<string, unknown>): Promise<void> {\n await this.emit({\n type: \"status_change\",\n data: { status, ...extras },\n });\n }\n\n /** ステップ開始イベント */\n async emitStepStart(stepOrdinal: number, description: string, actionType?: string): Promise<void> {\n await this.emit({\n type: \"step_start\",\n data: { stepOrdinal, description, ...(actionType && { actionType }) },\n });\n }\n\n /** ステップ完了イベント */\n async emitStepComplete(stepOrdinal: number, status: string, durationMs: number, description?: string): Promise<void> {\n await this.emit({\n type: \"step_complete\",\n data: { stepOrdinal, status, durationMs, ...(description && { description }) },\n });\n }\n\n /** ステップ失敗イベント */\n async emitStepFailed(stepOrdinal: number, error: string): Promise<void> {\n await this.emit({\n type: \"step_failed\",\n data: { stepOrdinal, error },\n });\n }\n\n /** 完了イベント */\n async emitCompleted(summary?: Record<string, unknown>): Promise<void> {\n await this.emit({\n type: \"completed\",\n data: summary ?? {},\n });\n }\n\n /** 失敗イベント */\n async emitFailed(error: string): Promise<void> {\n await this.emit({\n type: \"failed\",\n data: { error },\n });\n }\n}\n","/**\n * サーバー用 Logger 実装\n *\n * @clack/prompts に依存せず、構造化 JSON ログ + Redis 進捗イベント発行を行う。\n * Logger / SpinnerLike インターフェースに準拠し、executor / explorer に注入可能。\n */\n\nimport type { Logger, SpinnerLike } from \"../../../logger.js\";\nimport type { ProgressEmitter } from \"./progress-emitter.js\";\n\nexport class ServerLogger implements Logger {\n constructor(\n private jobId: string,\n private emitter?: ProgressEmitter,\n ) {}\n\n step(message: string): void {\n this.log(\"step\", message);\n }\n\n success(message: string): void {\n this.log(\"success\", message);\n }\n\n error(message: string): void {\n this.log(\"error\", message);\n }\n\n warn(message: string): void {\n this.log(\"warn\", message);\n }\n\n info(message: string): void {\n this.log(\"info\", message);\n }\n\n debug(message: string): void {\n this.log(\"debug\", message);\n }\n\n private log(level: string, message: string): void {\n // 構造化 JSON ログ(stdout)\n const entry = {\n ts: new Date().toISOString(),\n level,\n jobId: this.jobId,\n message,\n };\n // eslint-disable-next-line no-console\n console.log(JSON.stringify(entry));\n\n // Redis 進捗イベント(fire-and-forget)\n this.emitter?.emit({\n type: \"progress\",\n data: { level, message },\n }).catch(() => {});\n }\n}\n\nexport class ServerSpinner implements SpinnerLike {\n constructor(\n private logger: ServerLogger,\n ) {}\n\n start(message: string): void {\n this.logger.info(message);\n }\n\n stop(message: string): void {\n this.logger.info(message);\n }\n}\n","/**\n * ioredis クライアントシングルトン\n *\n * SSE 進捗イベント配信・スクリーンショットストリーミング・途中指示シグナルに使用。\n * Inngest 用 Redis を再利用する。\n */\n\nimport Redis from \"ioredis\";\n\nlet publisherInstance: Redis | null = null;\n\n/**\n * Publisher 用 Redis クライアントを取得(遅延初期化シングルトン)。\n * Pub/Sub では subscriber と publisher を分離する必要があるため、\n * subscribe が必要な箇所では createSubscriber() で専用インスタンスを生成する。\n */\nexport function getRedisPublisher(redisUrl: string): Redis {\n if (!publisherInstance) {\n publisherInstance = new Redis(redisUrl, {\n maxRetriesPerRequest: 3,\n lazyConnect: true,\n });\n publisherInstance.connect().catch((err) => {\n console.warn(`[Redis] Publisher connection failed: ${err instanceof Error ? err.message : String(err)}`);\n });\n }\n return publisherInstance;\n}\n\n/**\n * Subscriber 用 Redis クライアントを新規作成。\n * Pub/Sub の subscriber は他のコマンドを発行できないため、\n * 各 SSE 接続・各 intervention controller で専用インスタンスが必要。\n */\nexport function createRedisSubscriber(redisUrl: string): Redis {\n return new Redis(redisUrl, {\n maxRetriesPerRequest: 3,\n });\n}\n\n/** テスト・シャットダウン用: publisher インスタンスを閉じる */\nexport async function closeRedisPublisher(): Promise<void> {\n if (publisherInstance) {\n await publisherInstance.quit().catch(() => {});\n publisherInstance = null;\n }\n}\n","/**\n * ai-service --- AI モデル提供の DI インターフェース\n *\n * harness モジュール(selector-resolver, goal-agent, vision-resolver)や\n * executor / generator が AI モデルを取得するための抽象レイヤー。\n *\n * - DefaultAIModelProvider: 既存の getModel() にフォールバック(CLI/SDK 後方互換)\n * - ConfiguredAIModelProvider: AIModelConfig + factory から直接モデルを解決(サーバー用)\n */\n\nimport type { LanguageModel } from \"ai\";\nimport type { ModelPurpose, ModelProvider, AIModelConfig } from \"./ai-model.js\";\nimport { DEFAULT_MODEL_ID, PROVIDER_DEFAULT_MODELS, getModel, getModelId } from \"./ai-model.js\";\n\n/** AI モデル提供インターフェース */\nexport interface AIModelProvider {\n getModel(purpose?: ModelPurpose): LanguageModel;\n getModelId(purpose?: ModelPurpose): string;\n}\n\n/**\n * デフォルト実装: 既存の getModel() にフォールバック(CLI/SDK 後方互換)\n */\nexport class DefaultAIModelProvider implements AIModelProvider {\n getModel(purpose?: ModelPurpose): LanguageModel {\n return getModel(purpose);\n }\n getModelId(purpose?: ModelPurpose): string {\n return getModelId(purpose);\n }\n}\n\n/**\n * 設定済み実装: AIModelConfig + factory から直接モデルを解決(サーバー用)\n * ALS に依存しない。テナント設定を明示的に保持。\n */\nexport class ConfiguredAIModelProvider implements AIModelProvider {\n private cache = new Map<string, LanguageModel>();\n constructor(\n private config: AIModelConfig,\n private factory: (modelId: string) => LanguageModel,\n ) {}\n\n getModel(purpose?: ModelPurpose): LanguageModel {\n const overrideId = purpose\n ? this.config.modelOverrides?.[purpose]\n : undefined;\n const modelId = overrideId\n ?? this.config.modelId\n ?? PROVIDER_DEFAULT_MODELS[this.config.provider as ModelProvider]\n ?? DEFAULT_MODEL_ID;\n const cacheKey = `${purpose ?? \"default\"}:${modelId}`;\n let model = this.cache.get(cacheKey);\n if (!model) {\n model = this.factory(modelId);\n this.cache.set(cacheKey, model);\n }\n return model;\n }\n\n getModelId(purpose?: ModelPurpose): string {\n const overrideId = purpose\n ? this.config.modelOverrides?.[purpose]\n : undefined;\n return overrideId\n ?? this.config.modelId\n ?? PROVIDER_DEFAULT_MODELS[this.config.provider as ModelProvider]\n ?? DEFAULT_MODEL_ID;\n }\n}\n","/**\n * スクリーンショット定期配信クラス\n *\n * AgentBrowser の page から定期的にスクリーンショットを撮影し、\n * ProgressEmitter 経由で SSE に配信する。\n *\n * enableArtifactSaving() を呼ぶと、ステップ完了時に高品質 PNG を\n * ArtifactStore + ArtifactDBStore に永続化する。\n */\n\nimport type { AgentBrowser } from \"../../../browser/browser-client.js\";\nimport type { ProgressEmitter } from \"./progress-emitter.js\";\nimport type { ArtifactStore, ArtifactMetadata } from \"../../../storage/types.js\";\nimport type { ArtifactDBStore } from \"../../store/artifact-store.js\";\n\nexport class ScreenshotStreamer {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private capturing = false;\n\n // アーティファクト保存用(enableArtifactSaving() で設定)\n private artifactStore?: ArtifactStore;\n private artifactDb?: ArtifactDBStore;\n private tenantId?: string;\n private jobId?: string;\n private screenshotCount = 0;\n private maxScreenshots = Infinity;\n /** ローテーションで削除されたアーティファクト数 */\n purgedCount = 0;\n\n constructor(\n private browser: AgentBrowser,\n private emitter: ProgressEmitter,\n private intervalMs: number = 1500,\n private quality: number = 50,\n ) {}\n\n /** アーティファクト保存を有効化 */\n enableArtifactSaving(\n store: ArtifactStore,\n db: ArtifactDBStore,\n tenantId: string,\n jobId: string,\n max: number,\n ): void {\n this.artifactStore = store;\n this.artifactDb = db;\n this.tenantId = tenantId;\n this.jobId = jobId;\n this.maxScreenshots = max;\n }\n\n /** 定期スクリーンショット配信を開始 */\n start(): void {\n if (this.intervalId) return;\n\n this.intervalId = setInterval(async () => {\n if (this.capturing) return; // 前回の撮影が完了していない場合はスキップ\n this.capturing = true;\n try {\n await this.captureAndEmit();\n } catch {\n // スクリーンショット撮影失敗は無視\n } finally {\n this.capturing = false;\n }\n }, this.intervalMs);\n }\n\n /** 即座に1枚撮影して配信(ステップ完了時用) */\n async captureNow(): Promise<void> {\n try {\n await this.captureAndEmit();\n } catch {\n // 撮影失敗は無視\n }\n }\n\n /** 定期スクリーンショット配信を停止 */\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n }\n\n /** ステップ完了時に高品質 PNG を GCS + DB に保存(上限到達時は古いものを削除) */\n async saveStepScreenshot(stepOrdinal: number): Promise<ArtifactMetadata | null> {\n if (!this.artifactStore || !this.artifactDb || !this.tenantId || !this.jobId) {\n return null;\n }\n\n // 上限到達時: 古いスクリーンショットをローテーション削除\n if (this.screenshotCount >= this.maxScreenshots && this.maxScreenshots !== Infinity) {\n try {\n const { purgedCount, purgedPaths } = await this.artifactDb.rotateOldest(\n this.tenantId, \"screenshot\", this.maxScreenshots - 1, // 1 枠空ける\n );\n if (purgedCount > 0) {\n this.purgedCount += purgedCount;\n this.screenshotCount -= purgedCount;\n // GCS からも削除\n for (const path of purgedPaths) {\n await this.artifactStore!.delete(path).catch(() => {});\n }\n }\n } catch {\n // ローテーション失敗時は保存をスキップ\n return null;\n }\n }\n\n const page = this.browser.getPage();\n if (!page) return null;\n\n try {\n const buf = await page.screenshot({ type: \"png\" });\n const filename = `step-${String(stepOrdinal).padStart(3, \"0\")}.png`;\n\n const meta = await this.artifactStore.save(\n this.tenantId,\n this.jobId,\n \"screenshot\",\n filename,\n buf,\n \"image/png\",\n stepOrdinal,\n );\n await this.artifactDb.insert(meta);\n\n this.screenshotCount++;\n return meta;\n } catch {\n return null;\n }\n }\n\n private async captureAndEmit(): Promise<void> {\n const page = this.browser.getPage();\n if (!page) return;\n\n const buf = await page.screenshot({\n type: \"jpeg\",\n quality: this.quality,\n });\n\n await this.emitter.emit({\n type: \"screenshot\",\n data: {\n image: buf.toString(\"base64\"),\n format: \"jpeg\",\n },\n });\n }\n}\n","/**\n * ServerConfirmationProvider — Redis Pub/Sub ベースのブロッキング承認\n *\n * 承認が必要なステップに到達すると:\n * 1. DB に approval_request を INSERT (pending)\n * 2. ステータスを waiting_approval に更新\n * 3. SSE \"waiting_approval\" イベントを発行 → Web UI に表示\n * 4. チャット設定あり → 承認カードを投稿(Button value に jobId:stepOrdinal)\n * 5. Redis subscribe で待機(UI / チャット どちらからでも先着解決)\n * 6. resolve 後: DB ステータス更新 + SSE approval_result イベント発行\n */\n\nimport type { ConfirmationProvider, ConfirmationResult, ConfirmationContext } from \"../../../harness/confirmation.js\";\nimport type { ParsedStep } from \"../../../runbook-executor/types.js\";\nimport type { ProgressEmitter } from \"./progress-emitter.js\";\nimport { DEFAULT_APPROVAL_TIMEOUT_MS } from \"../../../messaging/config.js\";\nimport type { JobStore } from \"../../store/job-store.js\";\nimport type { getDb } from \"../../db/client.js\";\nimport { jobApprovalRequests } from \"../../db/schema.js\";\nimport { eq, and } from \"drizzle-orm\";\nimport { createRedisSubscriber } from \"../../redis.js\";\nimport type { SharedChatBot } from \"../../../messaging/chat-bot.js\";\nimport { buildApprovalCard, buildApprovalResultCard } from \"../../../messaging/cards.js\";\nimport { t } from \"../../../i18n/index.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\nexport class ServerConfirmationProvider implements ConfirmationProvider {\n constructor(\n private db: Db,\n private jobStore: JobStore,\n private emitter: ProgressEmitter,\n private jobId: string,\n private redisUrl: string,\n private chatBot?: SharedChatBot,\n private timeoutMs = DEFAULT_APPROVAL_TIMEOUT_MS,\n ) {}\n\n async confirm(\n step: ParsedStep,\n stepIndex: number,\n context?: ConfirmationContext,\n ): Promise<ConfirmationResult> {\n const description = step.description;\n const riskLevel = step.riskLevel ?? \"low\";\n\n // 1. DB に承認リクエストを保存\n await this.db.insert(jobApprovalRequests).values({\n jobId: this.jobId,\n stepOrdinal: stepIndex,\n stepDescription: description,\n riskLevel: riskLevel as \"low\" | \"medium\" | \"high\",\n status: \"pending\",\n });\n\n // 2. ステータス更新: waiting_approval\n await this.jobStore.updateStatus(this.jobId, \"waiting_approval\");\n\n // 3. SSE イベント発行\n await this.emitter.emit({\n type: \"waiting_approval\",\n data: {\n stepOrdinal: stepIndex,\n description,\n riskLevel,\n },\n });\n await this.emitter.emitStatusChange(\"waiting_approval\");\n\n // 4. チャット承認カード投稿\n if (this.chatBot) {\n try {\n await this.chatBot.ensureInitialized();\n const card = buildApprovalCard(step, context, {\n jobId: this.jobId,\n stepOrdinal: stepIndex,\n });\n await this.chatBot.getChannel().post(card);\n } catch (err) {\n console.warn(`[ServerConfirmationProvider] Approval card posting failed for job=${this.jobId}, step=${stepIndex}:`, err);\n }\n }\n\n // 5. Redis subscribe で待機\n const channel = `job:${this.jobId}:approval:${stepIndex}`;\n const subscriber = createRedisSubscriber(this.redisUrl);\n\n try {\n const result = await new Promise<{ action: ConfirmationResult; respondedBy?: string }>(\n (resolve, reject) => {\n const timer = setTimeout(() => {\n resolve({ action: \"abort\" as ConfirmationResult });\n }, this.timeoutMs);\n\n subscriber.subscribe(channel, (err) => {\n if (err) {\n clearTimeout(timer);\n reject(err);\n }\n });\n\n subscriber.on(\"message\", (_ch: string, message: string) => {\n clearTimeout(timer);\n try {\n const parsed = JSON.parse(message) as { action: string; respondedBy?: string };\n const action = ([\"approve\", \"skip\", \"abort\"].includes(parsed.action)\n ? parsed.action\n : \"abort\") as ConfirmationResult;\n resolve({ action, respondedBy: parsed.respondedBy });\n } catch {\n resolve({ action: \"abort\" as ConfirmationResult });\n }\n });\n },\n );\n\n // 6. DB ステータス更新\n const dbStatus = result.action === \"approve\"\n ? \"approved\"\n : result.action === \"skip\"\n ? \"skipped\"\n : \"aborted\";\n\n await this.db\n .update(jobApprovalRequests)\n .set({\n status: dbStatus as \"approved\" | \"skipped\" | \"aborted\" | \"timeout\",\n respondedBy: result.respondedBy ?? null,\n respondedAt: new Date(),\n })\n .where(\n and(\n eq(jobApprovalRequests.jobId, this.jobId),\n eq(jobApprovalRequests.stepOrdinal, stepIndex),\n ),\n );\n\n // ステータスを running に戻す\n await this.jobStore.updateStatus(this.jobId, \"running\");\n await this.emitter.emitStatusChange(\"running\");\n\n // SSE approval_result イベント\n await this.emitter.emit({\n type: \"approval_result\",\n data: {\n stepOrdinal: stepIndex,\n action: result.action,\n respondedBy: result.respondedBy,\n },\n });\n\n // チャットに結果カードを投稿\n if (this.chatBot) {\n try {\n const resultText =\n result.action === \"approve\"\n ? t(\"chat.approved\")\n : result.action === \"skip\"\n ? t(\"chat.chatSkipped\")\n : t(\"chat.chatAborted\");\n const resultCard = buildApprovalResultCard(step, resultText);\n await this.chatBot.getChannel().post(resultCard);\n } catch (err) {\n console.warn(`[ServerConfirmationProvider] Approval result card posting failed for job=${this.jobId}, step=${stepIndex}:`, err);\n }\n }\n\n return result.action;\n } finally {\n try {\n await subscriber.unsubscribe(channel);\n await subscriber.quit();\n } catch {\n // クリーンアップ失敗は無視\n }\n }\n }\n\n async dispose(): Promise<void> {\n // chatBot の dispose は execute-job.ts 側で管理\n }\n}\n","/**\n * chat-bot-factory --- テナントの DB クレデンシャルから SharedChatBot を生成\n *\n * マルチテナントサーバーでは credentials を SharedChatBot に直接渡し、\n * アダプター生成時に process.env ではなくクレデンシャルを使用する。\n */\n\nimport { eq } from \"drizzle-orm\";\nimport { SharedChatBot } from \"../../../messaging/chat-bot.js\";\nimport { decrypt } from \"../../crypto.js\";\nimport { tenantExecutionSettings } from \"../../db/schema.js\";\nimport type { getDb } from \"../../db/client.js\";\nimport { DEFAULT_APPROVAL_TIMEOUT_MS, DEFAULT_CALLBACK_PORT, type ChatPlatform } from \"../../../messaging/config.js\";\nimport {\n NOTIFICATION_SENSITIVE_FIELDS,\n NOTIFICATION_CREDENTIAL_FIELDS,\n} from \"../../routes/settings-defaults.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\ntype NotificationCredentials = Record<\n string,\n Record<string, string> | undefined\n>;\n\n/**\n * テナント設定の notificationCredentials + approvalMode/notifyMode から\n * SharedChatBot を生成する。\n *\n * クレデンシャルが存在しない or 必須フィールドが不足 → null を返す。\n */\nexport async function createTenantChatBot(\n db: Db,\n tenantId: string,\n encryptionKey: string,\n platform: ChatPlatform,\n): Promise<SharedChatBot | null> {\n const row = await db.query.tenantExecutionSettings.findFirst({\n where: eq(tenantExecutionSettings.tenantId, tenantId),\n columns: { notificationCredentials: true },\n });\n\n const allCreds = row?.notificationCredentials as\n | NotificationCredentials\n | null\n | undefined;\n const creds = allCreds?.[platform];\n if (!creds) {\n console.warn(`[chat-bot-factory] No credentials found for platform=${platform}, tenantId=${tenantId}`);\n return null;\n }\n\n // 必須フィールドの存在チェック\n const requiredFields = NOTIFICATION_CREDENTIAL_FIELDS[platform]\n ?.filter((f) => f.required)\n .map((f) => f.key);\n if (requiredFields?.some((k) => !creds[k])) {\n console.warn(`[chat-bot-factory] Missing required fields for platform=${platform}: ${requiredFields?.filter((k) => !creds[k]).join(\", \")}`);\n return null;\n }\n\n // sensitive フィールドを復号\n const sensitiveKeys = new Set(\n NOTIFICATION_SENSITIVE_FIELDS[platform] ?? [],\n );\n const decrypted: Record<string, string> = {};\n for (const [key, val] of Object.entries(creds)) {\n if (!val) continue;\n decrypted[key] = sensitiveKeys.has(key)\n ? decrypt(val, encryptionKey)\n : val;\n }\n\n // チャンネル ID をクレデンシャルから取得\n const channelIdKey =\n platform === \"slack\"\n ? \"SLACK_CHANNEL_ID\"\n : platform === \"teams\"\n ? \"TEAMS_CHANNEL_ID\"\n : \"DISCORD_CHANNEL_ID\";\n const channelId = decrypted[channelIdKey];\n if (!channelId) {\n console.warn(`[chat-bot-factory] Missing channel ID (${channelIdKey}) for platform=${platform}, tenantId=${tenantId}`);\n return null;\n }\n\n return new SharedChatBot({\n platform,\n channelId,\n callbackPort: DEFAULT_CALLBACK_PORT, // サーバーでは使われない\n approvalTimeoutMs: DEFAULT_APPROVAL_TIMEOUT_MS,\n skipWebhookServer: true,\n credentials: decrypted,\n });\n}\n","/**\n * デフォルトプロバイダー・モデルオーバーライド定義(サーバー側)\n */\n\nimport { PROVIDER_DEFAULT_MODELS } from \"../../harness/ai-model.js\";\n\nexport interface ProviderConfigField {\n key: string;\n label: string;\n value?: string;\n sensitive?: boolean;\n required?: boolean;\n placeholder?: string;\n type?: \"text\" | \"file\";\n}\n\nexport interface DashboardProvider {\n id:\n | \"anthropic\"\n | \"openai\"\n | \"openai-compatible\"\n | \"google\"\n | \"azure\"\n | \"bedrock\"\n | \"vertex\";\n connected: boolean | \"pending\";\n modelId: string;\n configFields: ProviderConfigField[];\n}\n\nexport interface DashboardModelOverride {\n purpose:\n | \"selector\"\n | \"extraction\"\n | \"exploration\"\n | \"exploration-light\"\n | \"review\"\n | \"fallback\"\n | \"vision\";\n description: string;\n modelId: string;\n}\n\nexport const DEFAULT_PROVIDERS: DashboardProvider[] = [\n {\n id: \"anthropic\",\n connected: false,\n modelId: PROVIDER_DEFAULT_MODELS.anthropic,\n configFields: [\n {\n key: \"ANTHROPIC_API_KEY\",\n label: \"API Key\",\n sensitive: true,\n required: true,\n placeholder: \"sk-ant-...\",\n },\n ],\n },\n {\n id: \"openai\",\n connected: false,\n modelId: PROVIDER_DEFAULT_MODELS.openai,\n configFields: [\n {\n key: \"OPENAI_API_KEY\",\n label: \"API Key\",\n sensitive: true,\n required: true,\n placeholder: \"sk-proj-...\",\n },\n ],\n },\n {\n id: \"openai-compatible\",\n connected: false,\n modelId: PROVIDER_DEFAULT_MODELS[\"openai-compatible\"],\n configFields: [\n {\n key: \"OPENAI_COMPATIBLE_BASE_URL\",\n label: \"Base URL\",\n required: true,\n placeholder: \"https://api.example.com/v1\",\n },\n {\n key: \"OPENAI_COMPATIBLE_API_KEY\",\n label: \"API Key\",\n sensitive: true,\n placeholder: \"sk-...\",\n },\n ],\n },\n {\n id: \"google\",\n connected: false,\n modelId: PROVIDER_DEFAULT_MODELS.google,\n configFields: [\n {\n key: \"GOOGLE_GENERATIVE_AI_API_KEY\",\n label: \"API Key\",\n sensitive: true,\n required: true,\n placeholder: \"AIzaSy...\",\n },\n ],\n },\n {\n id: \"azure\",\n connected: false,\n modelId: PROVIDER_DEFAULT_MODELS.azure,\n configFields: [\n {\n key: \"AZURE_RESOURCE_NAME\",\n label: \"Resource Name\",\n required: true,\n placeholder: \"my-azure-resource\",\n },\n {\n key: \"AZURE_API_KEY\",\n label: \"API Key\",\n sensitive: true,\n placeholder: \"xxxxxxxx\",\n },\n {\n key: \"AZURE_API_VERSION\",\n label: \"API Version\",\n placeholder: \"2024-02-15-preview\",\n },\n ],\n },\n {\n id: \"bedrock\",\n connected: false,\n modelId: PROVIDER_DEFAULT_MODELS.bedrock,\n configFields: [\n {\n key: \"AWS_REGION\",\n label: \"AWS Region\",\n required: true,\n placeholder: \"us-east-1\",\n },\n {\n key: \"AWS_ACCESS_KEY_ID\",\n label: \"Access Key ID\",\n sensitive: true,\n placeholder: \"AKIA...\",\n },\n {\n key: \"AWS_SECRET_ACCESS_KEY\",\n label: \"Secret Access Key\",\n sensitive: true,\n placeholder: \"wJalrXU...\",\n },\n ],\n },\n {\n id: \"vertex\",\n connected: false,\n modelId: PROVIDER_DEFAULT_MODELS.vertex,\n configFields: [\n {\n key: \"GOOGLE_VERTEX_PROJECT\",\n label: \"GCP Project\",\n required: true,\n placeholder: \"my-gcp-project\",\n },\n {\n key: \"GOOGLE_VERTEX_LOCATION\",\n label: \"Location\",\n required: true,\n placeholder: \"us-east5\",\n },\n {\n key: \"GOOGLE_APPLICATION_CREDENTIALS\",\n label: \"Service Account Key\",\n sensitive: true,\n type: \"file\",\n placeholder: \"Upload JSON key file\",\n },\n ],\n },\n];\n\n/** プロバイダーごとの sensitive フィールドキー */\nexport const SENSITIVE_FIELDS: Record<string, string[]> = {\n anthropic: [\"ANTHROPIC_API_KEY\"],\n openai: [\"OPENAI_API_KEY\"],\n \"openai-compatible\": [\"OPENAI_COMPATIBLE_API_KEY\"],\n google: [\"GOOGLE_GENERATIVE_AI_API_KEY\"],\n azure: [\"AZURE_API_KEY\"],\n bedrock: [\"AWS_ACCESS_KEY_ID\", \"AWS_SECRET_ACCESS_KEY\"],\n vertex: [\"GOOGLE_APPLICATION_CREDENTIALS\"],\n};\n\nexport interface NotificationCredentialField {\n key: string;\n label: string;\n sensitive?: boolean;\n required?: boolean;\n placeholder?: string;\n}\n\nexport type NotificationPlatform = \"slack\" | \"teams\" | \"discord\";\n\nexport const NOTIFICATION_CREDENTIAL_FIELDS: Record<NotificationPlatform, NotificationCredentialField[]> = {\n slack: [\n { key: \"SLACK_BOT_TOKEN\", label: \"Bot Token\", sensitive: true, required: true, placeholder: \"xoxb-...\" },\n { key: \"SLACK_SIGNING_SECRET\", label: \"Signing Secret\", sensitive: true, required: true, placeholder: \"xxxxxxxx\" },\n { key: \"SLACK_CHANNEL_ID\", label: \"Channel ID\", required: true, placeholder: \"C01XXXXXXXX\" },\n ],\n teams: [\n { key: \"TEAMS_APP_ID\", label: \"App ID\", required: true, placeholder: \"xxxxxxxx-xxxx-...\" },\n { key: \"TEAMS_APP_PASSWORD\", label: \"App Password\", sensitive: true, required: true, placeholder: \"xxxxxxxx\" },\n { key: \"TEAMS_APP_TENANT_ID\", label: \"Tenant ID\", placeholder: \"xxxxxxxx-xxxx-...\" },\n { key: \"TEAMS_CHANNEL_ID\", label: \"Channel ID\", required: true, placeholder: \"19:xxxxxxxx...\" },\n ],\n discord: [\n { key: \"DISCORD_BOT_TOKEN\", label: \"Bot Token\", sensitive: true, required: true, placeholder: \"MTIx...\" },\n { key: \"DISCORD_PUBLIC_KEY\", label: \"Public Key\", sensitive: true, required: true, placeholder: \"xxxxxxxx\" },\n { key: \"DISCORD_APPLICATION_ID\", label: \"Application ID\", required: true, placeholder: \"123456789...\" },\n { key: \"DISCORD_CHANNEL_ID\", label: \"Channel ID\", required: true, placeholder: \"123456789...\" },\n ],\n};\n\nexport const NOTIFICATION_SENSITIVE_FIELDS: Record<NotificationPlatform, string[]> = {\n slack: [\"SLACK_BOT_TOKEN\", \"SLACK_SIGNING_SECRET\"],\n teams: [\"TEAMS_APP_PASSWORD\"],\n discord: [\"DISCORD_BOT_TOKEN\", \"DISCORD_PUBLIC_KEY\"],\n};\n\nexport const DEFAULT_MODEL_OVERRIDES: DashboardModelOverride[] = [\n {\n purpose: \"selector\",\n description: \"Element resolution (high frequency)\",\n modelId: \"\",\n },\n {\n purpose: \"extraction\",\n description: \"Data extraction (high frequency)\",\n modelId: \"\",\n },\n {\n purpose: \"exploration\",\n description: \"Exploration loop (tool-calling)\",\n modelId: \"\",\n },\n {\n purpose: \"exploration-light\",\n description: \"Routine exploration steps (cheaper model)\",\n modelId: \"\",\n },\n {\n purpose: \"review\",\n description: \"Review, fix suggestions, YAML patches\",\n modelId: \"\",\n },\n {\n purpose: \"fallback\",\n description: \"Agent Fallback (last resort)\",\n modelId: \"\",\n },\n {\n purpose: \"vision\",\n description: \"Vision Fallback (screenshot-based)\",\n modelId: \"\",\n },\n];\n","/**\n * storage/gcs-store --- Google Cloud Storage アーティファクトストア\n *\n * ADC 認証(Cloud Run SA で自動)。\n * オブジェクトレイアウト: {tenantId}/{jobId}/{type}/{filename}\n */\n\nimport { Storage } from \"@google-cloud/storage\";\nimport type { ArtifactStore, ArtifactType, ArtifactMetadata } from \"./types.js\";\n\nexport class GCSArtifactStore implements ArtifactStore {\n private storage: Storage;\n private bucketName: string;\n\n constructor(bucketName: string) {\n this.storage = new Storage();\n this.bucketName = bucketName;\n }\n\n async save(\n tenantId: string,\n jobId: string,\n type: ArtifactType,\n filename: string,\n data: Buffer,\n contentType: string,\n stepOrdinal?: number,\n ): Promise<ArtifactMetadata> {\n const storagePath = `${tenantId}/${jobId}/${type}/${filename}`;\n const bucket = this.storage.bucket(this.bucketName);\n const file = bucket.file(storagePath);\n\n await file.save(data, {\n contentType,\n metadata: {\n tenantId,\n jobId,\n type,\n ...(stepOrdinal !== undefined ? { stepOrdinal: String(stepOrdinal) } : {}),\n },\n });\n\n return {\n jobId,\n tenantId,\n type,\n filename,\n storagePath,\n contentType,\n sizeBytes: data.length,\n stepOrdinal,\n createdAt: new Date(),\n };\n }\n\n async getSignedUrl(storagePath: string, expiresInSeconds = 3600): Promise<string> {\n const bucket = this.storage.bucket(this.bucketName);\n const file = bucket.file(storagePath);\n\n const [url] = await file.getSignedUrl({\n version: \"v4\",\n action: \"read\",\n expires: Date.now() + expiresInSeconds * 1000,\n });\n\n return url;\n }\n\n async getContent(storagePath: string): Promise<Buffer> {\n const bucket = this.storage.bucket(this.bucketName);\n const [data] = await bucket.file(storagePath).download();\n return data;\n }\n\n async delete(storagePath: string): Promise<void> {\n const bucket = this.storage.bucket(this.bucketName);\n const file = bucket.file(storagePath);\n await file.delete({ ignoreNotFound: true });\n }\n\n async deleteByJob(tenantId: string, jobId: string): Promise<void> {\n const bucket = this.storage.bucket(this.bucketName);\n const prefix = `${tenantId}/${jobId}/`;\n const [files] = await bucket.getFiles({ prefix });\n if (files.length > 0) {\n await Promise.all(files.map((f) => f.delete({ ignoreNotFound: true })));\n }\n }\n}\n","/**\n * storage/local-store --- ローカルファイルシステム アーティファクトストア\n *\n * 開発・テスト用フォールバック。getSignedUrl() は file:// URL を返す。\n */\n\nimport { readFile, writeFile, mkdir, rm, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ArtifactStore, ArtifactType, ArtifactMetadata } from \"./types.js\";\n\nexport class LocalArtifactStore implements ArtifactStore {\n constructor(private baseDir: string) {}\n\n async save(\n tenantId: string,\n jobId: string,\n type: ArtifactType,\n filename: string,\n data: Buffer,\n contentType: string,\n stepOrdinal?: number,\n ): Promise<ArtifactMetadata> {\n const dir = join(this.baseDir, tenantId, jobId, type);\n await mkdir(dir, { recursive: true });\n\n const storagePath = join(tenantId, jobId, type, filename);\n const fullPath = join(this.baseDir, storagePath);\n await writeFile(fullPath, data);\n\n return {\n jobId,\n tenantId,\n type,\n filename,\n storagePath,\n contentType,\n sizeBytes: data.length,\n stepOrdinal,\n createdAt: new Date(),\n };\n }\n\n async getSignedUrl(storagePath: string): Promise<string> {\n const fullPath = join(this.baseDir, storagePath);\n // 開発用: ファイルが存在するか確認してから URL を返す\n try {\n await readFile(fullPath);\n } catch {\n throw new Error(`File not found: ${fullPath}`);\n }\n return `file://${fullPath}`;\n }\n\n async getContent(storagePath: string): Promise<Buffer> {\n return readFile(join(this.baseDir, storagePath));\n }\n\n async delete(storagePath: string): Promise<void> {\n const fullPath = join(this.baseDir, storagePath);\n try {\n await rm(fullPath, { force: true });\n } catch {\n // ファイルが存在しない場合は無視\n }\n }\n\n async deleteByJob(tenantId: string, jobId: string): Promise<void> {\n const dir = join(this.baseDir, tenantId, jobId);\n try {\n await rm(dir, { recursive: true, force: true });\n } catch {\n // ディレクトリが存在しない場合は無視\n }\n }\n}\n","/**\n * TelemetryStore — テレメトリ永続化ストア\n *\n * 5 テーブルの書き込み・読み取り。\n */\n\nimport { eq, and, desc, sql, count, avg, sum } from \"drizzle-orm\";\nimport type { getDb } from \"../db/client.js\";\nimport {\n telemetryFailureEvents,\n telemetryResolutionOutcomes,\n telemetryFailurePatterns,\n telemetryJobSummaries,\n telemetrySuggestionOutcomes,\n tenants,\n jobResults,\n jobResultDiagnostics,\n jobAiMetrics,\n} from \"../db/schema.js\";\nimport type {\n TelemetryJobSummaryInput,\n TelemetryFailureEventInput,\n TelemetryResolutionOutcomeInput,\n FailurePatternInput,\n TelemetrySuggestionOutcomeInput,\n AggregateStats,\n} from \"../telemetry/types.js\";\nimport type { ExecutionReport } from \"../../runbook-executor/types.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\nexport class TelemetryStore {\n constructor(private db: Db) {}\n\n // ── 書き込み ──\n\n async saveJobSummary(input: TelemetryJobSummaryInput): Promise<void> {\n await this.db.insert(telemetryJobSummaries).values({\n tenantId: input.tenantId,\n jobId: input.jobId,\n runbookId: input.runbookId,\n runbookContentHash: input.runbookContentHash,\n mode: input.mode,\n totalSteps: input.totalSteps,\n succeededSteps: input.succeededSteps,\n failedSteps: input.failedSteps,\n skippedSteps: input.skippedSteps,\n aborted: input.aborted,\n totalDurationMs: input.totalDurationMs,\n failureCategoryCounts: input.failureCategoryCounts,\n retryDistribution: input.retryDistribution,\n resolveMethodCounts: input.resolveMethodCounts,\n stepsWithRetries: input.stepsWithRetries,\n totalRetryCount: input.totalRetryCount,\n visionFallbackAttempts: input.visionFallbackAttempts,\n visionFallbackSuccesses: input.visionFallbackSuccesses,\n agentFallbackAttempts: input.agentFallbackAttempts,\n agentFallbackSuccesses: input.agentFallbackSuccesses,\n slowStepsCount: input.slowStepsCount,\n maxStepDurationMs: input.maxStepDurationMs,\n aiTotalCalls: input.aiTotalCalls,\n aiTotalInputTokens: input.aiTotalInputTokens,\n aiTotalOutputTokens: input.aiTotalOutputTokens,\n aiCacheHitRate: input.aiCacheHitRate,\n aiEstimatedCostUsd: input.aiEstimatedCostUsd,\n aiTotalDurationMs: input.aiTotalDurationMs,\n modelId: input.modelId,\n modelProvider: input.modelProvider,\n }).onConflictDoUpdate({\n target: [telemetryJobSummaries.jobId],\n set: {\n totalSteps: input.totalSteps,\n succeededSteps: input.succeededSteps,\n failedSteps: input.failedSteps,\n skippedSteps: input.skippedSteps,\n aborted: input.aborted,\n totalDurationMs: input.totalDurationMs,\n failureCategoryCounts: input.failureCategoryCounts,\n retryDistribution: input.retryDistribution,\n resolveMethodCounts: input.resolveMethodCounts,\n stepsWithRetries: input.stepsWithRetries,\n totalRetryCount: input.totalRetryCount,\n },\n });\n }\n\n async saveFailureEvents(events: TelemetryFailureEventInput[]): Promise<void> {\n if (events.length === 0) return;\n await this.db.insert(telemetryFailureEvents).values(events);\n }\n\n async saveResolutionOutcomes(outcomes: TelemetryResolutionOutcomeInput[]): Promise<void> {\n if (outcomes.length === 0) return;\n await this.db.insert(telemetryResolutionOutcomes).values(outcomes);\n }\n\n async upsertFailurePatterns(\n tenantId: string,\n runbookId: string | null,\n patterns: FailurePatternInput[],\n ): Promise<void> {\n for (const p of patterns) {\n await this.db\n .insert(telemetryFailurePatterns)\n .values({\n tenantId,\n runbookId,\n urlPattern: p.urlPattern,\n selectorHint: p.selectorHint,\n failureCategory: p.failureCategory,\n occurrenceCount: 1,\n lastErrorMessage: p.lastErrorMessage,\n lastSnapshotExcerpt: p.lastSnapshotExcerpt,\n successfulRecoveries: p.resolveMethod ? { [p.resolveMethod]: 1 } : {},\n lastRecoveryMethod: p.resolveMethod,\n lastJobId: p.jobId,\n lastStepOrdinal: p.stepOrdinal,\n })\n .onConflictDoUpdate({\n target: [\n telemetryFailurePatterns.tenantId,\n telemetryFailurePatterns.urlPattern,\n telemetryFailurePatterns.selectorHint,\n telemetryFailurePatterns.failureCategory,\n ],\n set: {\n occurrenceCount: sql`${telemetryFailurePatterns.occurrenceCount} + 1`,\n lastErrorMessage: p.lastErrorMessage,\n lastSnapshotExcerpt: p.lastSnapshotExcerpt,\n lastRecoveryMethod: p.resolveMethod,\n lastJobId: p.jobId,\n lastStepOrdinal: p.stepOrdinal,\n lastSeenAt: new Date(),\n // successfulRecoveries JSONB マージ: 既存値に新メソッドのカウントを加算\n ...(p.resolveMethod ? {\n successfulRecoveries: sql`COALESCE(${telemetryFailurePatterns.successfulRecoveries}, '{}'::jsonb) || jsonb_build_object(${p.resolveMethod}, COALESCE((${telemetryFailurePatterns.successfulRecoveries}->>${ p.resolveMethod})::int, 0) + 1)`,\n } : {}),\n },\n });\n }\n }\n\n async saveSuggestionOutcomes(\n tenantId: string,\n runbookId: string,\n jobId: string,\n suggestions: Array<{\n stepOrdinal?: number;\n stepDescription?: string;\n failureCategory?: string;\n suggestedStrategy?: string;\n runbookFix?: string;\n contextFix?: string;\n severity?: string;\n }>,\n ): Promise<void> {\n if (suggestions.length === 0) return;\n await this.db.insert(telemetrySuggestionOutcomes).values(\n suggestions.map((s) => ({\n tenantId,\n runbookId,\n suggestionJobId: jobId,\n stepOrdinal: s.stepOrdinal ?? null,\n stepDescription: s.stepDescription ?? null,\n failureCategory: s.failureCategory ?? null,\n suggestedStrategy: s.suggestedStrategy ?? null,\n runbookFix: s.runbookFix ?? null,\n contextFix: s.contextFix ?? null,\n severity: s.severity ?? null,\n })),\n );\n }\n\n /** 後続実行で未検証の提案を検証 */\n async verifySuggestionOutcomes(\n tenantId: string,\n runbookId: string | null,\n jobId: string,\n report: ExecutionReport,\n ): Promise<void> {\n if (!runbookId) return;\n\n // applied=true かつ未検証の提案を検索\n const unverified = await this.db\n .select()\n .from(telemetrySuggestionOutcomes)\n .where(\n and(\n eq(telemetrySuggestionOutcomes.tenantId, tenantId),\n eq(telemetrySuggestionOutcomes.runbookId, runbookId),\n eq(telemetrySuggestionOutcomes.applied, true),\n sql`${telemetrySuggestionOutcomes.verificationJobId} IS NULL`,\n ),\n );\n\n if (unverified.length === 0) return;\n\n // レポートのステップ結果を ordinal → status でマッピング\n const stepResults = new Map<number, { status: string; error?: string }>();\n for (const step of report.steps) {\n stepResults.set(step.ordinal, { status: step.status, error: step.error });\n }\n\n for (const suggestion of unverified) {\n if (suggestion.stepOrdinal == null) continue;\n const result = stepResults.get(suggestion.stepOrdinal);\n if (!result) continue;\n\n await this.db\n .update(telemetrySuggestionOutcomes)\n .set({\n verificationJobId: jobId,\n verificationSuccess: result.status === \"success\",\n verificationError: result.status === \"failed\" ? result.error ?? null : null,\n verifiedAt: new Date(),\n })\n .where(eq(telemetrySuggestionOutcomes.id, suggestion.id));\n }\n }\n\n // ── 読み取り(API 用) ──\n\n async getRecentSummaries(\n tenantId: string,\n opts: { runbookId?: string; limit?: number; days?: number } = {},\n ) {\n const limit = opts.limit ?? 50;\n const conditions = [eq(telemetryJobSummaries.tenantId, tenantId)];\n if (opts.runbookId) {\n conditions.push(eq(telemetryJobSummaries.runbookId, opts.runbookId));\n }\n if (opts.days) {\n const since = new Date(Date.now() - opts.days * 86400000);\n conditions.push(sql`${telemetryJobSummaries.createdAt} >= ${since}`);\n }\n\n return this.db\n .select()\n .from(telemetryJobSummaries)\n .where(and(...conditions))\n .orderBy(desc(telemetryJobSummaries.createdAt))\n .limit(limit);\n }\n\n async getFailureEvents(\n tenantId: string,\n opts: { runbookId?: string; category?: string; urlPattern?: string; limit?: number } = {},\n ) {\n const limit = opts.limit ?? 20;\n const conditions = [eq(telemetryFailureEvents.tenantId, tenantId)];\n if (opts.runbookId) {\n conditions.push(eq(telemetryFailureEvents.runbookId, opts.runbookId));\n }\n if (opts.category) {\n conditions.push(eq(telemetryFailureEvents.failureCategory, opts.category));\n }\n if (opts.urlPattern) {\n conditions.push(eq(telemetryFailureEvents.urlPattern, opts.urlPattern));\n }\n\n return this.db\n .select()\n .from(telemetryFailureEvents)\n .where(and(...conditions))\n .orderBy(desc(telemetryFailureEvents.createdAt))\n .limit(limit);\n }\n\n async getResolutionOutcomes(\n tenantId: string,\n opts: { runbookId?: string; resolveMethod?: string; matchType?: string; limit?: number } = {},\n ) {\n const limit = opts.limit ?? 50;\n const conditions = [eq(telemetryResolutionOutcomes.tenantId, tenantId)];\n if (opts.runbookId) {\n conditions.push(eq(telemetryResolutionOutcomes.runbookId, opts.runbookId));\n }\n if (opts.resolveMethod) {\n conditions.push(eq(telemetryResolutionOutcomes.resolveMethod, opts.resolveMethod));\n }\n if (opts.matchType) {\n conditions.push(eq(telemetryResolutionOutcomes.deterministicMatchType, opts.matchType));\n }\n\n return this.db\n .select()\n .from(telemetryResolutionOutcomes)\n .where(and(...conditions))\n .orderBy(desc(telemetryResolutionOutcomes.createdAt))\n .limit(limit);\n }\n\n async getTopFailurePatterns(\n tenantId: string,\n opts: { runbookId?: string; category?: string; limit?: number } = {},\n ) {\n const limit = opts.limit ?? 20;\n const conditions = [eq(telemetryFailurePatterns.tenantId, tenantId)];\n if (opts.runbookId) {\n conditions.push(eq(telemetryFailurePatterns.runbookId, opts.runbookId));\n }\n if (opts.category) {\n conditions.push(eq(telemetryFailurePatterns.failureCategory, opts.category));\n }\n\n return this.db\n .select()\n .from(telemetryFailurePatterns)\n .where(and(...conditions))\n .orderBy(desc(telemetryFailurePatterns.occurrenceCount))\n .limit(limit);\n }\n\n async getSuggestionOutcomes(\n tenantId: string,\n opts: { runbookId?: string; applied?: boolean; limit?: number } = {},\n ) {\n const limit = opts.limit ?? 20;\n const conditions = [eq(telemetrySuggestionOutcomes.tenantId, tenantId)];\n if (opts.runbookId) {\n conditions.push(eq(telemetrySuggestionOutcomes.runbookId, opts.runbookId));\n }\n if (opts.applied !== undefined) {\n conditions.push(eq(telemetrySuggestionOutcomes.applied, opts.applied));\n }\n\n return this.db\n .select()\n .from(telemetrySuggestionOutcomes)\n .where(and(...conditions))\n .orderBy(desc(telemetrySuggestionOutcomes.createdAt))\n .limit(limit);\n }\n\n async getAggregateStats(\n tenantId: string,\n opts: { runbookId?: string; fromDate?: Date; toDate?: Date } = {},\n ): Promise<AggregateStats> {\n const conditions = [eq(telemetryJobSummaries.tenantId, tenantId)];\n if (opts.runbookId) {\n conditions.push(eq(telemetryJobSummaries.runbookId, opts.runbookId));\n }\n if (opts.fromDate) {\n conditions.push(sql`${telemetryJobSummaries.createdAt} >= ${opts.fromDate}`);\n }\n if (opts.toDate) {\n conditions.push(sql`${telemetryJobSummaries.createdAt} <= ${opts.toDate}`);\n }\n\n const where = and(...conditions);\n\n const [result] = await this.db\n .select({\n totalJobs: count(),\n totalSteps: sum(telemetryJobSummaries.totalSteps),\n totalSucceeded: sum(telemetryJobSummaries.succeededSteps),\n totalFailed: sum(telemetryJobSummaries.failedSteps),\n avgRetryCount: avg(telemetryJobSummaries.totalRetryCount),\n totalVisionAttempts: sum(telemetryJobSummaries.visionFallbackAttempts),\n totalVisionSuccesses: sum(telemetryJobSummaries.visionFallbackSuccesses),\n totalAgentAttempts: sum(telemetryJobSummaries.agentFallbackAttempts),\n totalAgentSuccesses: sum(telemetryJobSummaries.agentFallbackSuccesses),\n aiTotalCost: sum(telemetryJobSummaries.aiEstimatedCostUsd),\n })\n .from(telemetryJobSummaries)\n .where(where);\n\n const totalSteps = Number(result.totalSteps ?? 0);\n const totalSucceeded = Number(result.totalSucceeded ?? 0);\n const totalVisionAttempts = Number(result.totalVisionAttempts ?? 0);\n const totalVisionSuccesses = Number(result.totalVisionSuccesses ?? 0);\n const totalAgentAttempts = Number(result.totalAgentAttempts ?? 0);\n const totalAgentSuccesses = Number(result.totalAgentSuccesses ?? 0);\n\n // 失敗カテゴリ別集計(日付フィルタ対応のため failure_events を使用)\n const failureConditions = [eq(telemetryFailureEvents.tenantId, tenantId)];\n if (opts.runbookId) {\n failureConditions.push(eq(telemetryFailureEvents.runbookId, opts.runbookId));\n }\n if (opts.fromDate) {\n failureConditions.push(sql`${telemetryFailureEvents.createdAt} >= ${opts.fromDate}`);\n }\n if (opts.toDate) {\n failureConditions.push(sql`${telemetryFailureEvents.createdAt} <= ${opts.toDate}`);\n }\n const failureRows = await this.db\n .select({\n category: telemetryFailureEvents.failureCategory,\n total: count(),\n })\n .from(telemetryFailureEvents)\n .where(and(...failureConditions))\n .groupBy(telemetryFailureEvents.failureCategory);\n\n const failureCategoryCounts: Record<string, number> = {};\n for (const r of failureRows) {\n failureCategoryCounts[r.category] = r.total;\n }\n\n // 解決メソッド別集計\n const outcomeConditions = [eq(telemetryResolutionOutcomes.tenantId, tenantId)];\n if (opts.runbookId) {\n outcomeConditions.push(eq(telemetryResolutionOutcomes.runbookId, opts.runbookId));\n }\n if (opts.fromDate) {\n outcomeConditions.push(sql`${telemetryResolutionOutcomes.createdAt} >= ${opts.fromDate}`);\n }\n if (opts.toDate) {\n outcomeConditions.push(sql`${telemetryResolutionOutcomes.createdAt} <= ${opts.toDate}`);\n }\n const methodRows = await this.db\n .select({\n method: telemetryResolutionOutcomes.resolveMethod,\n total: count(),\n })\n .from(telemetryResolutionOutcomes)\n .where(and(...outcomeConditions))\n .groupBy(telemetryResolutionOutcomes.resolveMethod);\n\n const resolveMethodCounts: Record<string, number> = {};\n for (const r of methodRows) {\n if (r.method) resolveMethodCounts[r.method] = r.total;\n }\n\n return {\n totalJobs: result.totalJobs,\n totalSteps,\n overallSuccessRate: totalSteps > 0 ? totalSucceeded / totalSteps : 0,\n failureCategoryCounts,\n resolveMethodCounts,\n avgRetryCount: Number(result.avgRetryCount ?? 0),\n visionFallbackSuccessRate: totalVisionAttempts > 0 ? totalVisionSuccesses / totalVisionAttempts : 0,\n agentFallbackSuccessRate: totalAgentAttempts > 0 ? totalAgentSuccesses / totalAgentAttempts : 0,\n aiTotalCostUsd: Number(result.aiTotalCost ?? 0),\n };\n }\n\n // ── テナント横断読み取り(デバッグ用) ──\n\n async getCrossTenantSummaries(\n opts: { tenantId?: string; runbookId?: string; days?: number; limit?: number; offset?: number } = {},\n ) {\n const limit = opts.limit ?? 50;\n const offset = opts.offset ?? 0;\n const conditions: ReturnType<typeof eq>[] = [];\n if (opts.tenantId) {\n conditions.push(eq(telemetryJobSummaries.tenantId, opts.tenantId));\n }\n if (opts.runbookId) {\n conditions.push(eq(telemetryJobSummaries.runbookId, opts.runbookId));\n }\n if (opts.days) {\n const since = new Date(Date.now() - opts.days * 86400000);\n conditions.push(sql`${telemetryJobSummaries.createdAt} >= ${since}` as unknown as ReturnType<typeof eq>);\n }\n const where = conditions.length > 0 ? and(...conditions) : undefined;\n\n const [items, [{ total }]] = await Promise.all([\n this.db\n .select({\n summary: telemetryJobSummaries,\n tenantName: tenants.name,\n tenantSlug: tenants.slug,\n })\n .from(telemetryJobSummaries)\n .leftJoin(tenants, eq(telemetryJobSummaries.tenantId, tenants.id))\n .where(where)\n .orderBy(desc(telemetryJobSummaries.createdAt))\n .limit(limit)\n .offset(offset),\n this.db.select({ total: count() }).from(telemetryJobSummaries).where(where),\n ]);\n return { items, total };\n }\n\n async getCrossTenantFailureEvents(\n opts: { tenantId?: string; runbookId?: string; category?: string; urlPattern?: string; days?: number; limit?: number; offset?: number } = {},\n ) {\n const limit = opts.limit ?? 50;\n const offset = opts.offset ?? 0;\n const conditions: ReturnType<typeof eq>[] = [];\n if (opts.tenantId) {\n conditions.push(eq(telemetryFailureEvents.tenantId, opts.tenantId));\n }\n if (opts.runbookId) {\n conditions.push(eq(telemetryFailureEvents.runbookId, opts.runbookId));\n }\n if (opts.category) {\n conditions.push(eq(telemetryFailureEvents.failureCategory, opts.category));\n }\n if (opts.urlPattern) {\n conditions.push(eq(telemetryFailureEvents.urlPattern, opts.urlPattern));\n }\n if (opts.days) {\n const since = new Date(Date.now() - opts.days * 86400000);\n conditions.push(sql`${telemetryFailureEvents.createdAt} >= ${since}` as unknown as ReturnType<typeof eq>);\n }\n const where = conditions.length > 0 ? and(...conditions) : undefined;\n\n const [items, [{ total }]] = await Promise.all([\n this.db\n .select({\n event: telemetryFailureEvents,\n tenantName: tenants.name,\n tenantSlug: tenants.slug,\n })\n .from(telemetryFailureEvents)\n .leftJoin(tenants, eq(telemetryFailureEvents.tenantId, tenants.id))\n .where(where)\n .orderBy(desc(telemetryFailureEvents.createdAt))\n .limit(limit)\n .offset(offset),\n this.db.select({ total: count() }).from(telemetryFailureEvents).where(where),\n ]);\n return { items, total };\n }\n\n async getCrossTenantResolutionOutcomes(\n opts: { tenantId?: string; runbookId?: string; resolveMethod?: string; matchType?: string; days?: number; limit?: number; offset?: number } = {},\n ) {\n const limit = opts.limit ?? 50;\n const offset = opts.offset ?? 0;\n const conditions: ReturnType<typeof eq>[] = [];\n if (opts.tenantId) {\n conditions.push(eq(telemetryResolutionOutcomes.tenantId, opts.tenantId));\n }\n if (opts.runbookId) {\n conditions.push(eq(telemetryResolutionOutcomes.runbookId, opts.runbookId));\n }\n if (opts.resolveMethod) {\n conditions.push(eq(telemetryResolutionOutcomes.resolveMethod, opts.resolveMethod));\n }\n if (opts.matchType) {\n conditions.push(eq(telemetryResolutionOutcomes.deterministicMatchType, opts.matchType));\n }\n if (opts.days) {\n const since = new Date(Date.now() - opts.days * 86400000);\n conditions.push(sql`${telemetryResolutionOutcomes.createdAt} >= ${since}` as unknown as ReturnType<typeof eq>);\n }\n const where = conditions.length > 0 ? and(...conditions) : undefined;\n\n const [items, [{ total }]] = await Promise.all([\n this.db\n .select({\n outcome: telemetryResolutionOutcomes,\n tenantName: tenants.name,\n tenantSlug: tenants.slug,\n })\n .from(telemetryResolutionOutcomes)\n .leftJoin(tenants, eq(telemetryResolutionOutcomes.tenantId, tenants.id))\n .where(where)\n .orderBy(desc(telemetryResolutionOutcomes.createdAt))\n .limit(limit)\n .offset(offset),\n this.db.select({ total: count() }).from(telemetryResolutionOutcomes).where(where),\n ]);\n return { items, total };\n }\n\n async getCrossTenantFailurePatterns(\n opts: { tenantId?: string; runbookId?: string; category?: string; limit?: number; offset?: number } = {},\n ) {\n const limit = opts.limit ?? 50;\n const offset = opts.offset ?? 0;\n const conditions: ReturnType<typeof eq>[] = [];\n if (opts.tenantId) {\n conditions.push(eq(telemetryFailurePatterns.tenantId, opts.tenantId));\n }\n if (opts.runbookId) {\n conditions.push(eq(telemetryFailurePatterns.runbookId, opts.runbookId));\n }\n if (opts.category) {\n conditions.push(eq(telemetryFailurePatterns.failureCategory, opts.category));\n }\n const where = conditions.length > 0 ? and(...conditions) : undefined;\n\n const [items, [{ total }]] = await Promise.all([\n this.db\n .select({\n pattern: telemetryFailurePatterns,\n tenantName: tenants.name,\n tenantSlug: tenants.slug,\n })\n .from(telemetryFailurePatterns)\n .leftJoin(tenants, eq(telemetryFailurePatterns.tenantId, tenants.id))\n .where(where)\n .orderBy(desc(telemetryFailurePatterns.occurrenceCount))\n .limit(limit)\n .offset(offset),\n this.db.select({ total: count() }).from(telemetryFailurePatterns).where(where),\n ]);\n return { items, total };\n }\n\n async getCrossTenantSuggestionOutcomes(\n opts: { tenantId?: string; runbookId?: string; applied?: boolean; limit?: number; offset?: number } = {},\n ) {\n const limit = opts.limit ?? 50;\n const offset = opts.offset ?? 0;\n const conditions: ReturnType<typeof eq>[] = [];\n if (opts.tenantId) {\n conditions.push(eq(telemetrySuggestionOutcomes.tenantId, opts.tenantId));\n }\n if (opts.runbookId) {\n conditions.push(eq(telemetrySuggestionOutcomes.runbookId, opts.runbookId));\n }\n if (opts.applied !== undefined) {\n conditions.push(eq(telemetrySuggestionOutcomes.applied, opts.applied));\n }\n const where = conditions.length > 0 ? and(...conditions) : undefined;\n\n const [items, [{ total }]] = await Promise.all([\n this.db\n .select({\n suggestion: telemetrySuggestionOutcomes,\n tenantName: tenants.name,\n tenantSlug: tenants.slug,\n })\n .from(telemetrySuggestionOutcomes)\n .leftJoin(tenants, eq(telemetrySuggestionOutcomes.tenantId, tenants.id))\n .where(where)\n .orderBy(desc(telemetrySuggestionOutcomes.createdAt))\n .limit(limit)\n .offset(offset),\n this.db.select({ total: count() }).from(telemetrySuggestionOutcomes).where(where),\n ]);\n return { items, total };\n }\n\n async getCrossTenantAggregateStats(\n opts: { tenantId?: string; days?: number } = {},\n ): Promise<AggregateStats & { perTenantBreakdown: Array<{ tenantId: string; tenantName: string | null; totalJobs: number; successRate: number; aiCostUsd: number }> }> {\n const conditions: ReturnType<typeof eq>[] = [];\n if (opts.tenantId) {\n conditions.push(eq(telemetryJobSummaries.tenantId, opts.tenantId));\n }\n if (opts.days) {\n const since = new Date(Date.now() - opts.days * 86400000);\n conditions.push(sql`${telemetryJobSummaries.createdAt} >= ${since}` as unknown as ReturnType<typeof eq>);\n }\n const where = conditions.length > 0 ? and(...conditions) : undefined;\n\n const [result] = await this.db\n .select({\n totalJobs: count(),\n totalSteps: sum(telemetryJobSummaries.totalSteps),\n totalSucceeded: sum(telemetryJobSummaries.succeededSteps),\n totalFailed: sum(telemetryJobSummaries.failedSteps),\n avgRetryCount: avg(telemetryJobSummaries.totalRetryCount),\n totalVisionAttempts: sum(telemetryJobSummaries.visionFallbackAttempts),\n totalVisionSuccesses: sum(telemetryJobSummaries.visionFallbackSuccesses),\n totalAgentAttempts: sum(telemetryJobSummaries.agentFallbackAttempts),\n totalAgentSuccesses: sum(telemetryJobSummaries.agentFallbackSuccesses),\n aiTotalCost: sum(telemetryJobSummaries.aiEstimatedCostUsd),\n })\n .from(telemetryJobSummaries)\n .where(where);\n\n const totalSteps = Number(result.totalSteps ?? 0);\n const totalSucceeded = Number(result.totalSucceeded ?? 0);\n const totalVisionAttempts = Number(result.totalVisionAttempts ?? 0);\n const totalVisionSuccesses = Number(result.totalVisionSuccesses ?? 0);\n const totalAgentAttempts = Number(result.totalAgentAttempts ?? 0);\n const totalAgentSuccesses = Number(result.totalAgentSuccesses ?? 0);\n\n // 失敗カテゴリ別集計\n const failureConditions: ReturnType<typeof eq>[] = [];\n if (opts.tenantId) {\n failureConditions.push(eq(telemetryFailureEvents.tenantId, opts.tenantId));\n }\n if (opts.days) {\n const since = new Date(Date.now() - opts.days * 86400000);\n failureConditions.push(sql`${telemetryFailureEvents.createdAt} >= ${since}` as unknown as ReturnType<typeof eq>);\n }\n const failureRows = await this.db\n .select({\n category: telemetryFailureEvents.failureCategory,\n total: count(),\n })\n .from(telemetryFailureEvents)\n .where(failureConditions.length > 0 ? and(...failureConditions) : undefined)\n .groupBy(telemetryFailureEvents.failureCategory);\n\n const failureCategoryCounts: Record<string, number> = {};\n for (const r of failureRows) {\n failureCategoryCounts[r.category] = r.total;\n }\n\n // 解決メソッド別集計\n const outcomeConditions: ReturnType<typeof eq>[] = [];\n if (opts.tenantId) {\n outcomeConditions.push(eq(telemetryResolutionOutcomes.tenantId, opts.tenantId));\n }\n if (opts.days) {\n const since = new Date(Date.now() - opts.days * 86400000);\n outcomeConditions.push(sql`${telemetryResolutionOutcomes.createdAt} >= ${since}` as unknown as ReturnType<typeof eq>);\n }\n const methodRows = await this.db\n .select({\n method: telemetryResolutionOutcomes.resolveMethod,\n total: count(),\n })\n .from(telemetryResolutionOutcomes)\n .where(outcomeConditions.length > 0 ? and(...outcomeConditions) : undefined)\n .groupBy(telemetryResolutionOutcomes.resolveMethod);\n\n const resolveMethodCounts: Record<string, number> = {};\n for (const r of methodRows) {\n if (r.method) resolveMethodCounts[r.method] = r.total;\n }\n\n // テナント別ブレークダウン\n const perTenantRows = await this.db\n .select({\n tenantId: telemetryJobSummaries.tenantId,\n tenantName: tenants.name,\n totalJobs: count(),\n totalSteps: sum(telemetryJobSummaries.totalSteps),\n totalSucceeded: sum(telemetryJobSummaries.succeededSteps),\n aiCost: sum(telemetryJobSummaries.aiEstimatedCostUsd),\n })\n .from(telemetryJobSummaries)\n .leftJoin(tenants, eq(telemetryJobSummaries.tenantId, tenants.id))\n .where(where)\n .groupBy(telemetryJobSummaries.tenantId, tenants.name);\n\n const perTenantBreakdown = perTenantRows.map((r) => {\n const steps = Number(r.totalSteps ?? 0);\n const succeeded = Number(r.totalSucceeded ?? 0);\n return {\n tenantId: r.tenantId,\n tenantName: r.tenantName,\n totalJobs: r.totalJobs,\n successRate: steps > 0 ? succeeded / steps : 0,\n aiCostUsd: Number(r.aiCost ?? 0),\n };\n });\n\n return {\n totalJobs: result.totalJobs,\n totalSteps,\n overallSuccessRate: totalSteps > 0 ? totalSucceeded / totalSteps : 0,\n failureCategoryCounts,\n resolveMethodCounts,\n avgRetryCount: Number(result.avgRetryCount ?? 0),\n visionFallbackSuccessRate: totalVisionAttempts > 0 ? totalVisionSuccesses / totalVisionAttempts : 0,\n agentFallbackSuccessRate: totalAgentAttempts > 0 ? totalAgentSuccesses / totalAgentAttempts : 0,\n aiTotalCostUsd: Number(result.aiTotalCost ?? 0),\n perTenantBreakdown,\n };\n }\n\n async getJobTelemetryDetail(jobId: string) {\n const [summary] = await this.db\n .select({\n summary: telemetryJobSummaries,\n tenantName: tenants.name,\n tenantSlug: tenants.slug,\n })\n .from(telemetryJobSummaries)\n .leftJoin(tenants, eq(telemetryJobSummaries.tenantId, tenants.id))\n .where(eq(telemetryJobSummaries.jobId, jobId))\n .limit(1);\n\n const failureEvents = await this.db\n .select()\n .from(telemetryFailureEvents)\n .where(eq(telemetryFailureEvents.jobId, jobId))\n .orderBy(telemetryFailureEvents.stepOrdinal);\n\n const resolutionOutcomes = await this.db\n .select()\n .from(telemetryResolutionOutcomes)\n .where(eq(telemetryResolutionOutcomes.jobId, jobId))\n .orderBy(telemetryResolutionOutcomes.stepOrdinal);\n\n const suggestionOutcomes = await this.db\n .select()\n .from(telemetrySuggestionOutcomes)\n .where(eq(telemetrySuggestionOutcomes.suggestionJobId, jobId))\n .orderBy(telemetrySuggestionOutcomes.createdAt);\n\n return {\n summary: summary ?? null,\n failureEvents,\n resolutionOutcomes,\n suggestionOutcomes,\n };\n }\n\n /** ジョブ実行詳細(jobResults + diagnostics + aiMetrics)を取得 */\n async getJobExecutionDetails(jobId: string) {\n const results = await this.db\n .select()\n .from(jobResults)\n .where(eq(jobResults.jobId, jobId))\n .orderBy(jobResults.ordinal);\n\n const resultIds = results.map((r) => r.id);\n const diagnosticsMap = new Map<string, typeof jobResultDiagnostics.$inferSelect>();\n if (resultIds.length > 0) {\n const allDiag = await Promise.all(\n resultIds.map((rid) =>\n this.db\n .select()\n .from(jobResultDiagnostics)\n .where(eq(jobResultDiagnostics.jobResultId, rid))\n .limit(1),\n ),\n );\n for (const rows of allDiag) {\n if (rows[0]) diagnosticsMap.set(rows[0].jobResultId, rows[0]);\n }\n }\n\n const [aiMetricsRow] = await this.db\n .select()\n .from(jobAiMetrics)\n .where(eq(jobAiMetrics.jobId, jobId))\n .limit(1);\n\n return {\n stepResults: results.map((r) => ({\n ...r,\n diagnostics: diagnosticsMap.get(r.id) ?? null,\n })),\n aiMetrics: aiMetricsRow ?? null,\n };\n }\n}\n","/**\n * テレメトリコレクター — ExecutionReport → テレメトリデータ変換\n *\n * executor の ExecutionReport からテレメトリ 5 テーブル分のデータを抽出する。\n */\n\nimport { normalizeUrlPattern, buildSelectorHint } from \"../../harness/failure-registry.js\";\nimport type { ExecutionReport, StepExecutionResult, Selector } from \"../../runbook-executor/types.js\";\nimport type {\n TelemetryJobSummaryInput,\n TelemetryFailureEventInput,\n TelemetryResolutionOutcomeInput,\n FailurePatternInput,\n} from \"./types.js\";\n\n/** ジョブサマリー計算(全ジョブで実行) */\nexport function computeJobSummary(\n report: ExecutionReport,\n meta: {\n tenantId: string;\n jobId: string;\n runbookId?: string | null;\n runbookContentHash?: string | null;\n mode: string;\n modelId?: string | null;\n modelProvider?: string | null;\n },\n): TelemetryJobSummaryInput {\n const failureCategoryCounts: Record<string, number> = {};\n const retryDistribution: Record<string, number> = {};\n const resolveMethodCounts: Record<string, number> = {};\n let stepsWithRetries = 0;\n let totalRetryCount = 0;\n let visionFallbackAttempts = 0;\n let visionFallbackSuccesses = 0;\n let agentFallbackAttempts = 0;\n let agentFallbackSuccesses = 0;\n let slowStepsCount = 0;\n let maxStepDurationMs = 0;\n\n const SLOW_THRESHOLD_MS = 30_000;\n\n for (const step of report.steps) {\n // 失敗カテゴリ分布\n if (step.failureCategory) {\n failureCategoryCounts[step.failureCategory] =\n (failureCategoryCounts[step.failureCategory] ?? 0) + 1;\n }\n\n // リトライ分布\n const rc = step.retryCount ?? 0;\n const rcKey = String(rc);\n retryDistribution[rcKey] = (retryDistribution[rcKey] ?? 0) + 1;\n if (rc > 0) {\n stepsWithRetries++;\n totalRetryCount += rc;\n }\n\n // 解決メソッド\n if (step.resolveMethod) {\n resolveMethodCounts[step.resolveMethod] =\n (resolveMethodCounts[step.resolveMethod] ?? 0) + 1;\n }\n\n // Vision/Agent fallback\n if (step.diagnostics?.visionFallbackResult) {\n visionFallbackAttempts++;\n if (step.diagnostics.visionFallbackResult.success) visionFallbackSuccesses++;\n } else if (step.resolveMethod === \"vision\") {\n // 成功時は diagnostics がない場合があるため resolveMethod でフォールバック\n visionFallbackAttempts++;\n visionFallbackSuccesses++;\n }\n if (step.diagnostics?.agentFallbackResult) {\n agentFallbackAttempts++;\n if (step.diagnostics.agentFallbackResult.success) agentFallbackSuccesses++;\n } else if (step.resolveMethod === \"agent\") {\n agentFallbackAttempts++;\n agentFallbackSuccesses++;\n }\n\n // パフォーマンス\n if (step.durationMs > SLOW_THRESHOLD_MS) slowStepsCount++;\n if (step.durationMs > maxStepDurationMs) maxStepDurationMs = step.durationMs;\n }\n\n const ai = report.aiMetrics;\n\n return {\n tenantId: meta.tenantId,\n jobId: meta.jobId,\n runbookId: meta.runbookId ?? null,\n runbookContentHash: meta.runbookContentHash ?? null,\n mode: meta.mode,\n totalSteps: report.totalSteps,\n succeededSteps: report.succeeded,\n failedSteps: report.failed,\n skippedSteps: report.skipped,\n aborted: report.aborted,\n totalDurationMs: report.totalDurationMs,\n failureCategoryCounts,\n retryDistribution,\n resolveMethodCounts,\n stepsWithRetries,\n totalRetryCount,\n visionFallbackAttempts,\n visionFallbackSuccesses,\n agentFallbackAttempts,\n agentFallbackSuccesses,\n slowStepsCount,\n maxStepDurationMs,\n aiTotalCalls: ai?.totalCalls ?? 0,\n aiTotalInputTokens: ai?.totalInputTokens ?? 0,\n aiTotalOutputTokens: ai?.totalOutputTokens ?? 0,\n aiCacheHitRate: ai?.cacheHitRate ?? 0,\n aiEstimatedCostUsd: ai?.estimatedCostUsd ?? 0,\n aiTotalDurationMs: ai?.totalDurationMs ?? 0,\n modelId: meta.modelId ?? null,\n modelProvider: meta.modelProvider ?? null,\n };\n}\n\n/** 失敗イベント抽出(失敗ステップがある場合のみ) */\nexport function extractFailureEvents(\n report: ExecutionReport,\n meta: { tenantId: string; jobId: string; runbookId?: string | null },\n): TelemetryFailureEventInput[] {\n const events: TelemetryFailureEventInput[] = [];\n\n for (const step of report.steps) {\n if (step.status !== \"failed\") continue;\n\n const diag = step.diagnostics;\n const stepAction = diag?.stepAction ?? null;\n const selector = stepAction?.selector as Record<string, unknown> | undefined;\n\n const urlPattern = diag?.stepUrl\n ? normalizeUrlPattern(diag.stepUrl)\n : \"unknown\";\n const selectorHint = selector\n ? buildSelectorHint(selector as unknown as Selector)\n : \"unknown\";\n\n events.push({\n tenantId: meta.tenantId,\n jobId: meta.jobId,\n runbookId: meta.runbookId ?? null,\n stepOrdinal: step.ordinal,\n urlPattern,\n selectorHint,\n failureCategory: step.failureCategory ?? \"unknown\",\n actionType: step.actionType ?? null,\n stepDescription: step.description ?? null,\n stepAction: stepAction as Record<string, unknown> | null,\n errorMessage: step.error ?? null,\n failureHistory: diag?.failureHistory ?? null,\n retryCount: step.retryCount ?? 0,\n retryDetails: step.retryDetails ?? null,\n snapshotPreview: diag?.lastSnapshotPreview?.slice(0, 2000) ?? null,\n stepUrl: diag?.stepUrl ?? null,\n deterministicResult: diag?.deterministicResolveResult ?? null,\n visionFallback: diag?.visionFallbackResult as Record<string, unknown> | null ?? null,\n agentFallback: diag?.agentFallbackResult as Record<string, unknown> | null ?? null,\n resolveMethod: step.resolveMethod ?? null,\n contextChunksUsed: step.contextChunksUsed ?? null,\n failureHintsInjected: step.failureHintsProvided ? \"yes\" : null,\n validationWarnings: diag?.validationWarnings ?? null,\n validationErrors: diag?.validationErrors ?? null,\n executionStrategy: diag?.executionStrategy as Record<string, unknown> | null ?? null,\n durationMs: step.durationMs,\n recoveryHint: diag?.recoveryHint ?? null,\n });\n }\n\n return events;\n}\n\n/** 全ステップの解決結果抽出(成功含む全ステップ) */\nexport function extractResolutionOutcomes(\n report: ExecutionReport,\n meta: { tenantId: string; jobId: string; runbookId?: string | null },\n): TelemetryResolutionOutcomeInput[] {\n const outcomes: TelemetryResolutionOutcomeInput[] = [];\n\n for (const step of report.steps) {\n const diag = step.diagnostics;\n const stepAction = diag?.stepAction ?? null;\n const selector = stepAction?.selector as Record<string, unknown> | undefined;\n\n const urlPattern = diag?.stepUrl\n ? normalizeUrlPattern(diag.stepUrl)\n : null;\n const selectorHint = selector\n ? buildSelectorHint(selector as unknown as Selector)\n : null;\n\n // 成功時の AI 推論(最後のリトライの推論)\n let aiReasoning: string | null = null;\n if (step.retryDetails && step.retryDetails.length > 0) {\n const lastRetry = step.retryDetails[step.retryDetails.length - 1];\n aiReasoning = lastRetry.aiReasoning ?? null;\n }\n\n outcomes.push({\n tenantId: meta.tenantId,\n jobId: meta.jobId,\n runbookId: meta.runbookId ?? null,\n stepOrdinal: step.ordinal,\n status: step.status,\n resolveMethod: step.resolveMethod ?? null,\n retryCount: step.retryCount ?? 0,\n durationMs: step.durationMs,\n deterministicMatchType: step.deterministicMatchType ?? null,\n deterministicConfidence: step.deterministicConfidence ?? null,\n urlPattern,\n selectorHint,\n actionType: step.actionType ?? null,\n aiReasoning,\n contextChunksUsed: step.contextChunksUsed ?? 0,\n workingMemoryTokens: step.workingMemoryTokens ?? 0,\n failureHintsProvided: step.failureHintsProvided ?? false,\n snapshotElementCount: step.snapshotElementCount ?? 0,\n });\n }\n\n return outcomes;\n}\n\n/** 失敗パターン集計用データ */\nexport function deriveFailurePatterns(\n events: TelemetryFailureEventInput[],\n): FailurePatternInput[] {\n const map = new Map<string, FailurePatternInput>();\n\n for (const ev of events) {\n const key = `${ev.urlPattern}||${ev.selectorHint}||${ev.failureCategory}`;\n if (!map.has(key)) {\n map.set(key, {\n urlPattern: ev.urlPattern,\n selectorHint: ev.selectorHint,\n failureCategory: ev.failureCategory,\n lastErrorMessage: ev.errorMessage,\n lastSnapshotExcerpt: ev.snapshotPreview?.slice(0, 500) ?? null,\n resolveMethod: ev.resolveMethod,\n jobId: ev.jobId,\n stepOrdinal: ev.stepOrdinal,\n });\n } else {\n const existing = map.get(key)!;\n existing.lastErrorMessage = ev.errorMessage;\n existing.lastSnapshotExcerpt = ev.snapshotPreview?.slice(0, 500) ?? null;\n existing.resolveMethod = ev.resolveMethod;\n existing.jobId = ev.jobId;\n existing.stepOrdinal = ev.stepOrdinal;\n }\n }\n\n return [...map.values()];\n}\n\n/** ランブックのコンテンツハッシュを計算 */\nexport function computeRunbookHash(\n runbook: { steps: unknown[]; context?: string; metadata?: { startUrl?: string } },\n): string {\n const content = JSON.stringify({\n steps: runbook.steps,\n context: runbook.context ?? \"\",\n startUrl: runbook.metadata?.startUrl ?? \"\",\n });\n // 簡易ハッシュ(FNV-1a)\n let hash = 0x811c9dc5;\n for (let i = 0; i < content.length; i++) {\n hash ^= content.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { eq } from \"drizzle-orm\";\nimport { inngest } from \"../client.js\";\nimport { getDb } from \"../../db/client.js\";\nimport { tenants, tenantExecutionSettings } from \"../../db/schema.js\";\nimport { JobStore } from \"../../store/job-store.js\";\nimport { resolveTenantAIConfig, buildModelFactory } from \"../helpers/tenant-ai-config.js\";\nimport { ProgressEmitter } from \"../helpers/progress-emitter.js\";\nimport { ServerLogger, ServerSpinner } from \"../helpers/server-logger.js\";\nimport { getRedisPublisher, createRedisSubscriber } from \"../../redis.js\";\nimport { loadServerConfig } from \"../../config.js\";\nimport { trackedGenerateObject } from \"../../../harness/ai-model.js\";\nimport { ConfiguredAIModelProvider } from \"../../../harness/ai-service.js\";\nimport { AIMetricsCollector, runWithMetricsCollector } from \"../../../harness/ai-metrics.js\";\nimport { resolvePlanFromTier } from \"../../../plan/index.js\";\nimport type { PlanTier } from \"../../../plan/index.js\";\nimport { AgentBrowser } from \"../../../browser/browser-client.js\";\nimport { ScreenshotStreamer } from \"../helpers/screenshot-streamer.js\";\nimport { RemoteInterventionController } from \"../helpers/remote-intervention.js\";\nimport { ArtifactDBStore } from \"../../store/artifact-store.js\";\nimport { GCSArtifactStore } from \"../../../storage/gcs-store.js\";\nimport { LocalArtifactStore } from \"../../../storage/local-store.js\";\nimport type { ArtifactStore } from \"../../../storage/types.js\";\nimport { DownloadManager } from \"../../../context/download-manager.js\";\nimport { explore } from \"../../../runbook-generator/explorer.js\";\nimport { createReviewPrompt, reviewResponseSchema } from \"../../../runbook-generator/prompts.js\";\nimport { buildRunbookYaml } from \"../../../runbook-generator/runbook-builder.js\";\nimport { buildGenerateNotificationCard } from \"../../../messaging/cards.js\";\nimport { createTenantChatBot } from \"../helpers/chat-bot-factory.js\";\nimport { loadRunbookForExecution } from \"../helpers/runbook-loader.js\";\nimport type { AIModelConfig } from \"../../../harness/ai-model.js\";\nimport type { SharedChatBot } from \"../../../messaging/chat-bot.js\";\nimport type { ChatPlatform } from \"../../../messaging/config.js\";\nimport { getUserFriendlyAIErrorFromMessage } from \"../../../harness/ai-error.js\";\nimport type { GeneratorConfig, InterventionRecord, RecordedStep, ReviewResult } from \"../../../runbook-generator/types.js\";\nimport type { Locale } from \"../../../i18n/index.js\";\nimport {\n mergeVariablesIntoSecrets,\n serializeSecrets,\n deserializeSecrets,\n} from \"../../../cli/secrets-loader.js\";\nimport type { SecretsData } from \"../../../cli/secrets-loader.js\";\n\nfunction applyGenerateAIOverrides(\n baseConfig: AIModelConfig,\n generateConfig?: { modelId?: string; modelProvider?: string | null },\n): AIModelConfig {\n return {\n ...baseConfig,\n ...(generateConfig?.modelId ? { modelId: generateConfig.modelId } : {}),\n ...(generateConfig?.modelProvider\n ? { provider: generateConfig.modelProvider as AIModelConfig[\"provider\"] }\n : {}),\n };\n}\n\n/** MIME タイプ推定 */\nfunction guessMimeType(filename: string): string {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n const map: Record<string, string> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n webm: \"video/webm\",\n mp4: \"video/mp4\",\n csv: \"text/csv\",\n json: \"application/json\",\n txt: \"text/plain\",\n xlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n pdf: \"application/pdf\",\n };\n return map[ext ?? \"\"] ?? \"application/octet-stream\";\n}\n\n/**\n * 手順書生成 Inngest 関数\n *\n * event: \"job/generate\" { jobId, tenantId }\n * ライフサイクル: queued → exploring → reviewing → completed | failed\n */\nexport const generateJob = inngest.createFunction(\n {\n id: \"generate-job\",\n timeouts: { finish: \"30m\" },\n retries: 0,\n concurrency: [{ scope: \"account\", key: \"event.data.tenantId\", limit: 2 }],\n onFailure: async ({ event }) => {\n try {\n const originalEvent = event.data.event;\n const { jobId } = originalEvent.data;\n const rawErrorMsg = event.data.error?.message ?? \"Unknown error\";\n const errorMsg = getUserFriendlyAIErrorFromMessage(rawErrorMsg);\n\n const config = loadServerConfig();\n const db = getDb(config.databaseUrl);\n const jobStore = new JobStore(db);\n const redis = getRedisPublisher(config.redisUrl);\n const emitter = new ProgressEmitter(redis, jobId);\n\n console.error(`[generate-job] Function failed for job ${jobId}: ${errorMsg}`);\n await jobStore.updateStatus(jobId, \"failed\", {\n completedAt: new Date(),\n errorMessage: errorMsg,\n });\n await emitter.emitFailed(errorMsg);\n } catch (err) {\n console.error(`[generate-job] onFailure handler itself failed:`, err);\n }\n },\n },\n { event: \"job/generate\" },\n async ({ event, step }) => {\n const { jobId, tenantId } = event.data;\n const serverConfig = loadServerConfig();\n const db = getDb(serverConfig.databaseUrl);\n const jobStore = new JobStore(db);\n const redis = getRedisPublisher(serverConfig.redisUrl);\n const emitter = new ProgressEmitter(redis, jobId);\n const logger = new ServerLogger(jobId, emitter);\n\n // 1. ジョブ情報ロード(runbookId があれば secrets/変数/コンテキストも取得)\n const jobInfo = await step.run(\"load-job\", async () => {\n const job = await jobStore.findById(tenantId, jobId);\n if (!job) throw new Error(`Job ${jobId} not found`);\n\n const gc = job.generateConfig;\n\n console.log(`[generate-job] Job loaded: url=${job.startUrl}, goal=${job.goal?.slice(0, 50)}`);\n\n let secrets: SecretsData | undefined;\n let enrichedContext = job.context;\n\n if (job.runbookId) {\n try {\n const { runbook: rbData, secrets: rbSecrets } = await loadRunbookForExecution(\n db, tenantId, job.runbookId, serverConfig.encryptionKey,\n job.runbookVersionId ?? undefined,\n );\n\n console.log(`[generate-job] Secrets loaded: db=${Object.keys(rbSecrets.values).length}, vars=${Object.keys(rbData.variables ?? {}).length}`);\n\n // secrets + 変数の値を統合(AI が「フォーム入力で使用」と認識する)\n secrets = mergeVariablesIntoSecrets(\n Object.keys(rbSecrets.values).length > 0 ? rbSecrets : undefined,\n rbData.variables,\n );\n\n // runbook の context を使う(ジョブ側の context が未設定なら)\n if (!enrichedContext && rbData.context) {\n enrichedContext = rbData.context;\n }\n } catch (e) {\n console.warn(`[generate-job] Failed to load runbook secrets/variables: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n // job.variables (jobVariables テーブル) は runbookId の有無に関わらず最優先でマージ\n if (job.variables?.length) {\n const base = secrets ?? { values: {}, keys: new Set<string>() };\n const jobVarValues: Record<string, string> = {};\n for (const v of job.variables) jobVarValues[v.key] = v.value;\n secrets = {\n values: { ...base.values, ...jobVarValues },\n keys: new Set([...base.keys, ...Object.keys(jobVarValues)]),\n };\n }\n\n console.log(`[generate-job] Merged secrets: ${secrets ? Object.keys(secrets.values).length : 0} keys`);\n\n return {\n startUrl: job.startUrl!,\n goal: job.goal!,\n context: enrichedContext,\n runbookId: job.runbookId ?? null,\n runbookVersionId: job.runbookVersionId ?? null,\n purpose: job.purpose ?? null,\n secrets: secrets ? serializeSecrets(secrets) : undefined,\n generateConfig: gc ? {\n maxIterations: gc.maxIterations ?? 20,\n stepDelay: gc.stepDelay ?? 500,\n headless: gc.headless ?? true,\n snapshotFilter: gc.snapshotFilter ?? true,\n stallCheckInterval: gc.stallCheckInterval ?? 3,\n historyWindow: gc.historyWindow ?? 10,\n maxConsecutiveFailures: gc.maxConsecutiveFailures ?? 3,\n screenshotDir: gc.screenshotDir ?? undefined,\n videoDir: gc.videoDir ?? undefined,\n stealth: gc.stealth ?? false,\n proxy: gc.proxy ?? undefined,\n modelId: gc.modelId ?? undefined,\n modelProvider: gc.modelProvider ?? undefined,\n skills: gc.skills ?? undefined,\n } : undefined,\n };\n });\n\n // 2. AI 設定解決 + テナント通知設定\n const resolvedConfig = await step.run(\"resolve-config\", async () => {\n const [tenant] = await db\n .select({ tier: tenants.tier, locale: tenants.locale })\n .from(tenants)\n .where(eq(tenants.id, tenantId))\n .limit(1);\n const tier = (tenant?.tier ?? \"community\") as PlanTier;\n const plan = resolvePlanFromTier(tier, tenantId);\n const baseAiConfig = await resolveTenantAIConfig(db, tenantId, serverConfig.encryptionKey);\n const aiConfig = applyGenerateAIOverrides(baseAiConfig, jobInfo.generateConfig);\n\n // テナント通知設定 + アーティファクト設定\n const execSettings = await db.query.tenantExecutionSettings.findFirst({\n where: eq(tenantExecutionSettings.tenantId, tenantId),\n columns: { notifyMode: true, enableScreenshots: true, enableVideoRecording: true, skills: true },\n });\n\n return {\n plan, aiConfig,\n locale: (tenant?.locale ?? \"en\") as Locale,\n notifyMode: execSettings?.notifyMode ?? null,\n enableScreenshots: execSettings?.enableScreenshots ?? false,\n enableVideoRecording: execSettings?.enableVideoRecording ?? false,\n skills: execSettings?.skills ?? [],\n };\n });\n\n const notifyMode = resolvedConfig.notifyMode;\n\n // ChatBot 生成(step.run の外: SharedChatBot は非シリアライズ)\n let chatBot: SharedChatBot | null = null;\n if (notifyMode) {\n try {\n chatBot = await createTenantChatBot(\n db, tenantId, serverConfig.encryptionKey, notifyMode as ChatPlatform,\n );\n } catch {\n // 通知生成失敗は無視\n }\n }\n\n try {\n // 3. ステータス: exploring\n await step.run(\"mark-exploring\", async () => {\n await jobStore.updateStatus(jobId, \"exploring\", { startedAt: new Date() });\n await emitter.emitStatusChange(\"exploring\");\n });\n\n // 4. ブラウザ探索\n // RemoteInterventionController + AI provider を step.run の外で生成(非シリアライズ)\n const interventionRedis = createRedisSubscriber(serverConfig.redisUrl);\n const interventionController = new RemoteInterventionController(interventionRedis, emitter, jobId);\n await interventionController.startListening();\n\n const modelFactory = await buildModelFactory(resolvedConfig.aiConfig);\n const aiProvider = new ConfiguredAIModelProvider(resolvedConfig.aiConfig, modelFactory);\n\n let exploreResult: {\n recordedSteps: RecordedStep[];\n goalAchieved: boolean;\n cancelled: boolean;\n interventions: InterventionRecord[];\n error?: string;\n };\n try {\n exploreResult = await step.run(\"explore\", async () => {\n const gc = jobInfo.generateConfig;\n const collector = new AIMetricsCollector();\n\n // SecretsData の復元(Inngest step.run シリアライズ後)\n const secretsData: SecretsData | undefined = jobInfo.secrets\n ? deserializeSecrets(jobInfo.secrets as { values: Record<string, string>; keys: string[] })\n : undefined;\n\n const result = await runWithMetricsCollector(collector, async () => {\n const generatorConfig: GeneratorConfig = {\n url: jobInfo.startUrl,\n goal: jobInfo.goal,\n locale: resolvedConfig.locale,\n output: \"\", // サーバーでは直接出力しない\n maxIterations: gc?.maxIterations ?? 20,\n stepDelay: gc?.stepDelay ?? 500,\n headless: gc?.headless ?? true,\n snapshotFilter: gc?.snapshotFilter ?? true,\n stallCheckInterval: gc?.stallCheckInterval ?? 3,\n historyWindow: gc?.historyWindow ?? 10,\n maxConsecutiveFailures: gc?.maxConsecutiveFailures ?? 3,\n contextMarkdown: jobInfo.context ?? \"\",\n secrets: secretsData,\n stealth: gc?.stealth,\n proxy: gc?.proxy,\n skills: gc?.skills ?? resolvedConfig.skills,\n aiModelConfig: resolvedConfig.aiConfig,\n };\n\n // ブラウザとスクリーンショットストリーマーを生成ジョブ用に初期化\n const browser = new AgentBrowser();\n const screenshotStreamer = new ScreenshotStreamer(browser, emitter);\n\n // ArtifactStore 初期化(スクリーンショット・動画共通)\n const artifactStore: ArtifactStore = serverConfig.gcsBucket\n ? new GCSArtifactStore(serverConfig.gcsBucket)\n : new LocalArtifactStore(\"/tmp/artifacts\");\n const artifactDb = new ArtifactDBStore(db);\n\n // スクリーンショット保存有効化(設定で有効、または動作確認時に自動有効化)\n const isVerification = jobInfo.purpose === \"verification\";\n if (resolvedConfig.plan.features.screenshotSave\n && (resolvedConfig.enableScreenshots || isVerification)) {\n screenshotStreamer.enableArtifactSaving(\n artifactStore, artifactDb, tenantId, jobId,\n resolvedConfig.plan.limits.maxScreenshots,\n );\n }\n\n // 動画録画ディレクトリ(Plan ゲート + テナント設定で有効時)\n const videoDir = (resolvedConfig.plan.features.videoRecording\n && (resolvedConfig.enableVideoRecording || isVerification))\n ? `/tmp/video-${jobId}` : undefined;\n\n // DownloadManager(探索中の download/export ファイル追跡)\n const downloadManager = new DownloadManager(`/tmp/downloads-${jobId}`);\n\n screenshotStreamer.start();\n try {\n const exploreResult = await explore({\n ...generatorConfig,\n videoDir,\n }, {\n logger, browser, interventionController, aiProvider,\n downloadManager,\n onExplorerStep: async (stepNumber, description, recordedStep) => {\n await emitter.emit({\n type: \"explorer_step\",\n data: { stepNumber, description, actionType: recordedStep.action.action },\n });\n await jobStore.updateStatus(jobId, \"exploring\", { currentStep: stepNumber });\n // ステップを DB にインクリメンタル保存(リロード耐性)\n await jobStore.saveRecordedSteps(jobId, [{\n ordinal: recordedStep.ordinal,\n actionType: recordedStep.action.action,\n selector: recordedStep.action.selector,\n value: recordedStep.action.value,\n description: recordedStep.action.description,\n inputCategory: recordedStep.action.inputCategory,\n variableName: recordedStep.action.variableName,\n url: recordedStep.url,\n success: recordedStep.success,\n error: recordedStep.error,\n screenshotPath: recordedStep.screenshotPath,\n failureCategory: recordedStep.failureCategory,\n durationMs: recordedStep.durationMs,\n snapshotBefore: recordedStep.snapshotBefore,\n suggestedCaptures: recordedStep.action.suggestedCaptures,\n script: recordedStep.action.script,\n extractPrompt: recordedStep.action.extractPrompt,\n memoryCollection: recordedStep.action.memoryCollection,\n aggregation: recordedStep.action.aggregation,\n downloadPath: recordedStep.action.downloadPath,\n exportCollection: recordedStep.action.exportCollection,\n exportFormat: recordedStep.action.exportFormat,\n exportPath: recordedStep.action.exportPath,\n keys: recordedStep.action.keys,\n }]);\n // ステップスクリーンショットを保存\n await screenshotStreamer.saveStepScreenshot(recordedStep.ordinal);\n },\n });\n return exploreResult;\n } finally {\n screenshotStreamer.stop();\n\n // 動画ファイルを ArtifactStore に保存\n if (videoDir) {\n try {\n const files = await readdir(videoDir);\n for (const file of files) {\n if (file.endsWith(\".webm\") || file.endsWith(\".mp4\")) {\n const data = await readFile(join(videoDir, file));\n const meta = await artifactStore.save(\n tenantId, jobId, \"video\", file, data, guessMimeType(file),\n );\n await artifactDb.insert(meta);\n }\n }\n } catch { /* non-fatal */ }\n }\n\n // ダウンロード/エクスポートファイルを ArtifactStore に保存\n for (const dl of downloadManager.getDownloads()) {\n try {\n const data = await readFile(dl.path);\n const meta = await artifactStore.save(\n tenantId, jobId, \"download\", dl.filename, data,\n guessMimeType(dl.filename), dl.stepOrdinal,\n );\n await artifactDb.insert(meta);\n } catch { /* non-fatal */ }\n }\n\n try { await browser.close(); } catch { /* ignore */ }\n }\n });\n\n console.log(`[generate-job] Explore result: steps=${result.recordedSteps.length}, goalAchieved=${result.goalAchieved}, cancelled=${result.cancelled}`);\n\n return {\n recordedSteps: result.recordedSteps,\n goalAchieved: result.goalAchieved,\n cancelled: result.cancelled,\n interventions: result.interventions,\n error: result.error?.message,\n };\n });\n } finally {\n interventionController.dispose();\n interventionRedis.quit().catch(() => {});\n }\n\n if (exploreResult.cancelled) {\n // ステップは探索中に既にインクリメンタル保存済み\n await step.run(\"mark-cancelled\", async () => {\n await jobStore.updateStatus(jobId, \"cancelled\", { completedAt: new Date() });\n await emitter.emitStatusChange(\"cancelled\");\n });\n return { jobId, status: \"cancelled\" };\n }\n\n // 5. ステータス: reviewing\n await step.run(\"mark-reviewing\", async () => {\n await jobStore.updateStatus(jobId, \"reviewing\");\n await emitter.emitStatusChange(\"reviewing\");\n });\n\n // 6. AI レビュー\n const reviewResult = await step.run(\"review\", async () => {\n const { system, userPrompt } = createReviewPrompt(\n jobInfo.goal,\n exploreResult.recordedSteps,\n exploreResult.goalAchieved,\n exploreResult.interventions,\n resolvedConfig.locale,\n );\n\n const { object } = await trackedGenerateObject(\"review\", {\n model: aiProvider.getModel(\"review\"),\n system,\n prompt: userPrompt,\n schema: reviewResponseSchema,\n });\n\n return object as ReviewResult;\n });\n\n // 7. YAML 生成 + 結果保存\n // ステップは探索中に既にインクリメンタル保存済み\n let yamlGenerated = false;\n await step.run(\"save-output\", async () => {\n // YAML 生成\n let yamlContent: string | undefined;\n try {\n yamlContent = buildRunbookYaml({\n goal: jobInfo.goal,\n startUrl: jobInfo.startUrl,\n recordedSteps: exploreResult.recordedSteps,\n goalAchieved: exploreResult.goalAchieved,\n stepDelay: jobInfo.generateConfig?.stepDelay ?? 500,\n contextMarkdown: jobInfo.context ?? \"\",\n reviewResult,\n humanGuidance: exploreResult.interventions.map((iv) => iv.userInstruction),\n interventions: exploreResult.interventions,\n });\n yamlGenerated = !!yamlContent;\n } catch {\n // YAML 生成失敗は許容\n }\n\n // レビュー結果保存\n await jobStore.saveReviewResult(jobId, {\n summary: reviewResult.summary,\n yamlContent,\n goalAchieved: exploreResult.goalAchieved,\n reviewedSteps: reviewResult.reviewedSteps.map((s) => ({\n originalOrdinal: s.originalOrdinal,\n keep: s.keep,\n removalReason: s.removalReason,\n riskLevel: s.riskLevel,\n requiresConfirmation: s.requiresConfirmation,\n confirmationReason: s.confirmationReason,\n })),\n });\n\n // runbook にステップを書き戻す(verification generate の場合)\n if (jobInfo.runbookId && yamlContent) {\n const { parse: yamlParse } = await import(\"yaml\");\n const { ParsedRunbookSchema } = await import(\"../../../schemas/runbook-schema.js\");\n const { RunbookStore } = await import(\"../../store/runbook-store.js\");\n const parsed = ParsedRunbookSchema.safeParse(yamlParse(yamlContent));\n if (parsed.success) {\n const runbookStore = new RunbookStore(db);\n\n if (jobInfo.runbookVersionId) {\n // バージョン指定あり → 当該バージョンに書き戻し(active version を変更しない)\n await runbookStore.versions.updateVersion(tenantId, jobInfo.runbookId, jobInfo.runbookVersionId, {\n goal: parsed.data.metadata.goal,\n startUrl: parsed.data.metadata.startUrl,\n context: jobInfo.context ?? undefined,\n steps: parsed.data.steps,\n skipVerificationJobClear: true,\n });\n } else {\n // バージョン指定なし → 従来通り active version に書き戻し\n const existing = await runbookStore.findById(tenantId, jobInfo.runbookId);\n const existingVariables = existing\n ? Object.fromEntries(\n existing.variables.map((v) => [v.name, {\n source: v.source as \"prompt\" | \"fixed\" | \"context\" | \"env\" | \"expression\" | \"data\",\n description: v.description ?? undefined,\n required: v.required,\n sensitive: v.sensitive,\n value: v.value ?? undefined,\n }]),\n )\n : undefined;\n parsed.data.title = existing?.title ?? parsed.data.title;\n await runbookStore.update(tenantId, jobInfo.runbookId, {\n runbook: parsed.data,\n context: jobInfo.context ?? \"\",\n variables: existingVariables,\n skipStatusReset: true,\n });\n }\n }\n }\n });\n\n // 8. 完了(cancel 済みなら上書きしない)\n await step.run(\"mark-completed\", async () => {\n const currentJob = await jobStore.findBasicById(tenantId, jobId);\n if (currentJob?.status === \"cancelled\") {\n await emitter.emitStatusChange(\"cancelled\");\n return;\n }\n\n await jobStore.updateStatus(jobId, \"completed\", { completedAt: new Date() });\n await emitter.emitCompleted({\n goalAchieved: exploreResult.goalAchieved,\n steps: exploreResult.recordedSteps.length,\n });\n });\n\n // 9. 通知\n if (chatBot && notifyMode) {\n await step.run(\"notify\", async () => {\n try {\n await chatBot!.ensureInitialized();\n const card = buildGenerateNotificationCard({\n goal: jobInfo.goal,\n goalAchieved: exploreResult.goalAchieved,\n stepsCount: exploreResult.recordedSteps.length,\n yamlGenerated,\n });\n await chatBot!.getChannel().post(card);\n } catch {\n // 通知失敗は無視\n }\n });\n }\n\n return { jobId, status: \"completed\" };\n } finally {\n if (chatBot) {\n try { await chatBot.dispose(); } catch { /* ignore */ }\n }\n }\n },\n);\n","/**\n * RemoteInterventionController — Redis ベースの InterventionController(サーバー用)\n *\n * CLI の InterventionController と同じ API を公開する。\n * Web UI → API → Redis publish → この controller が受信。\n */\n\nimport type Redis from \"ioredis\";\nimport type { ProgressEmitter } from \"./progress-emitter.js\";\nimport type {\n InterventionRecord,\n} from \"../../../runbook-generator/types.js\";\nimport type {\n IInterventionController,\n InterventionResult,\n InterventionControllerOptions,\n} from \"../../../runbook-generator/intervention-controller.js\";\n\nexport class RemoteInterventionController implements IInterventionController {\n private _pauseRequested = false;\n private _cancelRequested = false;\n private pendingResolve: ((result: InterventionResult) => void) | null = null;\n private options: InterventionControllerOptions = {};\n readonly interventions: InterventionRecord[] = [];\n\n constructor(\n private redis: Redis,\n private emitter: ProgressEmitter,\n private jobId: string,\n ) {}\n\n setCallbacks(options: InterventionControllerOptions): void {\n this.options = options;\n }\n\n /** Redis チャネル `job:{jobId}:intervention` を subscribe */\n async startListening(): Promise<void> {\n const channel = `job:${this.jobId}:intervention`;\n await this.redis.subscribe(channel);\n\n this.redis.on(\"message\", (_ch: string, message: string) => {\n try {\n const msg = JSON.parse(message) as {\n type: \"pause\" | \"resume\" | \"cancel\";\n guidance?: string;\n stepIndex?: number;\n url?: string;\n };\n\n switch (msg.type) {\n case \"pause\":\n this._pauseRequested = true;\n break;\n\n case \"resume\":\n if (this.pendingResolve) {\n const result: InterventionResult = msg.guidance\n ? { action: \"guidance\", guidanceText: msg.guidance }\n : { action: \"guidance\", guidanceText: \"\" };\n\n this.interventions.push({\n stepIndex: msg.stepIndex ?? 0,\n userInstruction: msg.guidance ?? \"\",\n url: msg.url ?? \"\",\n timestamp: new Date().toISOString(),\n });\n\n this.pendingResolve(result);\n this.pendingResolve = null;\n this._pauseRequested = false;\n\n this.emitter.emit({\n type: \"resumed\",\n data: { guidance: msg.guidance },\n }).catch(() => {});\n\n this.options.onResume?.();\n }\n break;\n\n case \"cancel\":\n this._cancelRequested = true;\n if (this.pendingResolve) {\n this.pendingResolve({ action: \"abort\" });\n this.pendingResolve = null;\n }\n this.options.onCancel?.();\n break;\n }\n } catch {\n // JSON パースエラーは無視\n }\n });\n }\n\n isPauseRequested(): boolean {\n return this._pauseRequested;\n }\n\n isCancelRequested(): boolean {\n return this._cancelRequested;\n }\n\n /**\n * 一時停止 → resume/cancel を待機\n * CLI の InterventionController.collectIntervention() に相当\n */\n async collectIntervention(\n currentStepIndex: number,\n currentUrl: string,\n ): Promise<InterventionResult> {\n this.options.onPause?.();\n\n await this.emitter.emit({\n type: \"paused\",\n data: { stepIndex: currentStepIndex, url: currentUrl },\n });\n\n return new Promise((resolve) => {\n this.pendingResolve = resolve;\n });\n }\n\n dispose(): void {\n const channel = `job:${this.jobId}:intervention`;\n this.redis.unsubscribe(channel).catch(() => {});\n }\n}\n","/**\n * schedule-poller — 毎分ポーリングして期限到来スケジュールのジョブを発火\n */\n\nimport { eq, and } from \"drizzle-orm\";\nimport { inngest } from \"../client.js\";\nimport { getDb } from \"../../db/client.js\";\nimport { tenants, runbooks, runbookVersions, runbookSettings, runbookVariables } from \"../../db/schema.js\";\nimport { ScheduleStore } from \"../../store/schedule-store.js\";\nimport { JobStore } from \"../../store/job-store.js\";\nimport { loadServerConfig } from \"../../config.js\";\nimport { resolvePlanFromTier } from \"../../../plan/index.js\";\nimport type { PlanTier } from \"../../../plan/index.js\";\nimport { computeNextRun } from \"../../utils/cron.js\";\nimport { buildExecutionConfig } from \"../../helpers/execution-config-builder.js\";\n\nexport const schedulePoller = inngest.createFunction(\n { id: \"schedule-poller\", retries: 0 },\n { cron: \"*/1 * * * *\" },\n async ({ step }) => {\n await step.run(\"poll-and-dispatch\", async () => {\n const serverConfig = loadServerConfig();\n const db = getDb(serverConfig.databaseUrl);\n const scheduleStore = new ScheduleStore(db);\n const jobStore = new JobStore(db);\n\n const now = new Date();\n const dueSchedules = await scheduleStore.findDue(now);\n\n for (const schedule of dueSchedules) {\n try {\n // テナント tier チェック (scheduling feature gate)\n const [tenant] = await db\n .select({ tier: tenants.tier })\n .from(tenants)\n .where(eq(tenants.id, schedule.tenantId))\n .limit(1);\n if (!tenant) continue;\n\n const plan = resolvePlanFromTier(\n (tenant.tier ?? \"community\") as PlanTier,\n schedule.tenantId,\n );\n if (!plan.features.scheduling) continue;\n\n // self_heal の場合は selfHealMode feature gate もチェック\n if (schedule.purpose === \"self_heal\" && !plan.features.selfHealMode) continue;\n\n // Runbook が有効かつ activeVersionId があるか確認\n const [rb] = await db\n .select({ id: runbooks.id, disabled: runbooks.disabled, activeVersionId: runbooks.activeVersionId })\n .from(runbooks)\n .where(eq(runbooks.id, schedule.runbookId))\n .limit(1);\n if (!rb || rb.disabled || !rb.activeVersionId) continue;\n\n // アクティブバージョンから startUrl を取得\n const [ver] = await db\n .select({ startUrl: runbookVersions.startUrl })\n .from(runbookVersions)\n .where(eq(runbookVersions.id, rb.activeVersionId))\n .limit(1);\n if (!ver?.startUrl) {\n console.warn(`[schedule-poller] Skipping schedule ${schedule.id}: runbook ${schedule.runbookId} has no startUrl`);\n continue;\n }\n\n const activeVersionId = rb.activeVersionId;\n\n // トップレベルステップ数を取得(versionId ベース)\n const { runbookSteps } = await import(\"../../db/schema.js\");\n const { count, isNull } = await import(\"drizzle-orm\");\n const [stepCountResult] = await db\n .select({ cnt: count() })\n .from(runbookSteps)\n .where(\n and(\n eq(runbookSteps.versionId, activeVersionId),\n isNull(runbookSteps.parentStepId),\n ),\n );\n const totalSteps = stepCountResult?.cnt ?? 0;\n\n // ジョブモード決定\n const isSelfHeal = schedule.purpose === \"self_heal\";\n const mode = isSelfHeal ? \"self_heal\" : \"execute\";\n\n // Runbook 個別設定を取得(versionId ベース)\n const rbSettings = await db.query.runbookSettings.findFirst({\n where: eq(runbookSettings.versionId, activeVersionId),\n });\n\n // stored value を持つ変数をジョブ変数として渡す(versionId ベース)\n const rbVars = await db\n .select({\n name: runbookVariables.name,\n value: runbookVariables.value,\n sensitive: runbookVariables.sensitive,\n })\n .from(runbookVariables)\n .where(eq(runbookVariables.versionId, activeVersionId));\n\n const storedVars = rbVars\n .filter((v) => v.value != null)\n .map((v) => ({\n key: v.name,\n value: v.value!,\n sensitive: v.sensitive,\n }));\n\n // 既存の scheduled ジョブを検索(once スケジュール作成時に作成済みの場合)\n const existingJob = await jobStore.findScheduledByScheduleId(schedule.id);\n\n let jobId: string;\n if (existingJob) {\n // 既存ジョブを queued に遷移\n await jobStore.updateStatus(existingJob.id, \"queued\");\n jobId = existingJob.id;\n } else {\n // 新規ジョブ作成(recurring スケジュールまたはキャンセル済み等)\n const job = await jobStore.insert({\n tenantId: schedule.tenantId,\n mode,\n runbookId: schedule.runbookId,\n runbookVersionId: activeVersionId,\n totalSteps,\n purpose: \"scheduled\",\n scheduleId: schedule.id,\n variables: storedVars.length > 0 ? storedVars : undefined,\n executionConfig: buildExecutionConfig(rbSettings, { isSelfHeal }),\n });\n jobId = job.id;\n }\n\n // Inngest にジョブ実行イベントを送信\n await inngest.send({\n name: \"job/execute\",\n data: { jobId, tenantId: schedule.tenantId },\n });\n\n // スケジュールを進める\n if (schedule.type === \"once\") {\n // 一回限り → 無効化\n await scheduleStore.advanceSchedule(schedule.id, now, null, true);\n } else if (schedule.type === \"recurring\" && schedule.cron) {\n // 定期 → 次回実行時刻を計算\n const nextRunAt = computeNextRun(schedule.cron, schedule.timezone);\n await scheduleStore.advanceSchedule(schedule.id, now, nextRunAt);\n }\n } catch {\n // 個別スケジュールの失敗はスキップ\n }\n }\n });\n },\n);\n","import { eq, and, desc, count, lte } from \"drizzle-orm\";\nimport type { getDb } from \"../db/client.js\";\nimport { schedules } from \"../db/schema.js\";\nimport { computeNextRun } from \"../utils/cron.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\nexport type ScheduleType = \"recurring\" | \"once\";\nexport type SchedulePurpose = \"execute\" | \"self_heal\";\n\nexport interface ScheduleInsertData {\n tenantId: string;\n runbookId: string;\n type?: ScheduleType;\n cron?: string;\n timezone?: string;\n scheduledAt?: Date;\n purpose?: SchedulePurpose;\n enabled?: boolean;\n createdBy?: string;\n}\n\nexport interface ScheduleUpdateData {\n cron?: string;\n timezone?: string;\n scheduledAt?: Date;\n enabled?: boolean;\n}\n\nexport class ScheduleStore {\n constructor(private db: Db) {}\n\n async insert(data: ScheduleInsertData) {\n const type = data.type ?? \"recurring\";\n const timezone = data.timezone ?? \"UTC\";\n\n // nextRunAt を自動計算\n let nextRunAt: Date | null = null;\n if (type === \"recurring\" && data.cron) {\n nextRunAt = computeNextRun(data.cron, timezone);\n } else if (type === \"once\" && data.scheduledAt) {\n nextRunAt = data.scheduledAt;\n }\n\n const [row] = await this.db\n .insert(schedules)\n .values({\n tenantId: data.tenantId,\n runbookId: data.runbookId,\n type,\n cron: data.cron ?? null,\n timezone,\n scheduledAt: data.scheduledAt ?? null,\n purpose: data.purpose ?? \"execute\",\n enabled: data.enabled ?? true,\n nextRunAt,\n createdBy: data.createdBy ?? null,\n })\n .returning();\n return row;\n }\n\n async findById(tenantId: string, id: string) {\n const row = await this.db.query.schedules.findFirst({\n where: and(eq(schedules.id, id), eq(schedules.tenantId, tenantId)),\n });\n return row ?? null;\n }\n\n async findByRunbookAndPurpose(tenantId: string, runbookId: string, purpose: SchedulePurpose) {\n const row = await this.db.query.schedules.findFirst({\n where: and(\n eq(schedules.tenantId, tenantId),\n eq(schedules.runbookId, runbookId),\n eq(schedules.purpose, purpose),\n ),\n });\n return row ?? null;\n }\n\n async list(\n tenantId: string,\n opts: {\n runbookId?: string;\n enabled?: boolean;\n purpose?: SchedulePurpose;\n limit?: number;\n offset?: number;\n } = {},\n ) {\n const { runbookId, enabled, purpose, limit = 50, offset = 0 } = opts;\n\n const conditions = [eq(schedules.tenantId, tenantId)];\n if (runbookId) conditions.push(eq(schedules.runbookId, runbookId));\n if (enabled !== undefined) conditions.push(eq(schedules.enabled, enabled));\n if (purpose) conditions.push(eq(schedules.purpose, purpose));\n\n const where = and(...conditions);\n\n const rows = await this.db\n .select()\n .from(schedules)\n .where(where)\n .orderBy(desc(schedules.createdAt))\n .limit(limit)\n .offset(offset);\n\n const [totalResult] = await this.db\n .select({ count: count() })\n .from(schedules)\n .where(where);\n\n return { items: rows, total: totalResult.count };\n }\n\n async update(tenantId: string, id: string, data: ScheduleUpdateData) {\n const existing = await this.db.query.schedules.findFirst({\n where: and(eq(schedules.id, id), eq(schedules.tenantId, tenantId)),\n });\n if (!existing) return null;\n\n // nextRunAt を再計算\n const updates: Record<string, unknown> = { ...data };\n if (data.cron !== undefined || data.timezone !== undefined) {\n const cron = data.cron ?? existing.cron;\n const timezone = data.timezone ?? existing.timezone;\n if (cron && existing.type === \"recurring\") {\n updates.nextRunAt = computeNextRun(cron, timezone);\n }\n }\n if (data.scheduledAt !== undefined && existing.type === \"once\") {\n updates.nextRunAt = data.scheduledAt;\n }\n\n const [row] = await this.db\n .update(schedules)\n .set(updates)\n .where(eq(schedules.id, id))\n .returning();\n return row;\n }\n\n async delete(tenantId: string, id: string): Promise<boolean> {\n const result = await this.db\n .delete(schedules)\n .where(and(eq(schedules.id, id), eq(schedules.tenantId, tenantId)))\n .returning({ id: schedules.id });\n return result.length > 0;\n }\n\n async deleteByRunbookAndPurpose(tenantId: string, runbookId: string, purpose: SchedulePurpose): Promise<boolean> {\n const result = await this.db\n .delete(schedules)\n .where(and(\n eq(schedules.tenantId, tenantId),\n eq(schedules.runbookId, runbookId),\n eq(schedules.purpose, purpose),\n ))\n .returning({ id: schedules.id });\n return result.length > 0;\n }\n\n async findDue(now: Date) {\n return await this.db\n .select()\n .from(schedules)\n .where(and(eq(schedules.enabled, true), lte(schedules.nextRunAt, now)));\n }\n\n async advanceSchedule(id: string, lastRunAt: Date, nextRunAt: Date | null, disableIfOnce = false) {\n const updates: Record<string, unknown> = { lastRunAt, nextRunAt };\n if (disableIfOnce) {\n updates.enabled = false;\n }\n await this.db\n .update(schedules)\n .set(updates)\n .where(eq(schedules.id, id));\n }\n}\n","/**\n * cron ユーティリティ — cron 式の次回実行時刻計算とバリデーション\n */\n\nimport { CronExpressionParser } from \"cron-parser\";\n\n/**\n * cron 式とタイムゾーンから次回実行時刻を計算する。\n */\nexport function computeNextRun(cron: string, timezone: string): Date {\n const interval = CronExpressionParser.parse(cron, {\n tz: timezone,\n currentDate: new Date(),\n });\n return interval.next().toDate();\n}\n\n/**\n * cron 式が有効か検証する。\n */\nexport function isValidCron(cron: string): boolean {\n try {\n CronExpressionParser.parse(cron);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * executionConfig ビルダー — DB の runbookSettings からジョブ用 executionConfig を構築\n */\n\nimport { SELF_HEAL_DEFAULTS } from \"../../runbook-executor/types.js\";\n\nexport interface RunbookSettingsInput {\n defaultTimeout?: number | null;\n pauseBetweenSteps?: number | null;\n stopOnError?: boolean | null;\n enableSelectorCache?: boolean | null;\n enableAgentFallback?: boolean | null;\n enableVisionFallback?: boolean | null;\n}\n\nexport interface ExecutionConfigOutput {\n defaultTimeout: number;\n pauseBetweenSteps: number;\n stopOnError: boolean;\n enableSelectorCache: boolean;\n enableAgentFallback: boolean;\n enableVisionFallback: boolean;\n}\n\n/** DB の runbookSettings から executionConfig を構築する */\nexport function buildExecutionConfig(\n settings: RunbookSettingsInput | null | undefined,\n opts?: { isSelfHeal?: boolean },\n): ExecutionConfigOutput {\n const isSelfHeal = opts?.isSelfHeal ?? false;\n return {\n defaultTimeout: settings?.defaultTimeout ?? 30000,\n pauseBetweenSteps: settings?.pauseBetweenSteps ?? 500,\n stopOnError: settings?.stopOnError ?? true,\n enableSelectorCache: isSelfHeal\n ? SELF_HEAL_DEFAULTS.enableSelectorCache\n : (settings?.enableSelectorCache ?? true),\n enableAgentFallback: isSelfHeal\n ? SELF_HEAL_DEFAULTS.enableAgentFallback\n : (settings?.enableAgentFallback ?? true),\n enableVisionFallback: isSelfHeal\n ? SELF_HEAL_DEFAULTS.enableVisionFallback\n : (settings?.enableVisionFallback ?? false),\n };\n}\n","export { inngest } from \"./client.js\";\nexport { healthCheck } from \"./functions/health.js\";\nexport { executeJob } from \"./functions/execute-job.js\";\nexport { generateJob } from \"./functions/generate-job.js\";\nexport { schedulePoller } from \"./functions/schedule-poller.js\";\n\nimport { healthCheck } from \"./functions/health.js\";\nimport { executeJob } from \"./functions/execute-job.js\";\nimport { generateJob } from \"./functions/generate-job.js\";\nimport { schedulePoller } from \"./functions/schedule-poller.js\";\nexport const inngestFunctions = [healthCheck, executeJob, generateJob, schedulePoller];\n","/**\n * 二重認証ミドルウェア — Cookie セッション + Bearer API Key\n *\n * 1. Authorization: Bearer rfn_... → opaque キー認証(DB lookup)\n * Authorization: Bearer rfnd-... → デバッグトークン → 拒否(CLI/SDK 専用)\n * 2. Cookie セッション → Better Auth セッション認証\n * 3. どちらも失敗 → 未認証(user=null, plan=COMMUNITY_PLAN)\n */\n\nimport { createMiddleware } from \"hono/factory\";\nimport { getCookie } from \"hono/cookie\";\nimport { createHash } from \"node:crypto\";\nimport { eq, and } from \"drizzle-orm\";\nimport type { Auth } from \"../auth/index.js\";\nimport type { getDb } from \"../db/client.js\";\nimport { tenantMembers, apiKeys, tenants } from \"../db/schema.js\";\nimport { detectKeyKind } from \"../../plan/key-kind.js\";\nimport { resolvePlanFromTier, COMMUNITY_PLAN } from \"../../plan/index.js\";\nimport type { PlanTier } from \"../../plan/index.js\";\nimport type { AppVariables } from \"./types.js\";\nimport { tWithLocale, resolveAcceptLanguage } from \"../../i18n/index.js\";\n\n// ── authMiddleware ──\n\nexport function createAuthMiddleware(\n auth: Auth,\n db: ReturnType<typeof getDb>,\n) {\n return createMiddleware<{ Variables: AppVariables }>(async (c, next) => {\n // デフォルト値\n c.set(\"user\", null);\n c.set(\"session\", null);\n c.set(\"tenantId\", null);\n c.set(\"memberRole\", null);\n c.set(\"plan\", COMMUNITY_PLAN);\n\n // Webhook パスは独自の署名検証を行うためスキップ\n if (c.req.path.startsWith(\"/api/webhooks/\")) {\n await next();\n return;\n }\n\n // 1. Bearer API Key 認証\n const authHeader = c.req.header(\"Authorization\");\n if (authHeader?.startsWith(\"Bearer rfn\")) {\n const apiKey = authHeader.slice(\"Bearer \".length);\n const kind = detectKeyKind(apiKey);\n\n // デバッグトークン(rfnd-xxx)はサーバーでは拒否(CLI/SDK 専用)\n if (kind === \"debug\") {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: \"Debug tokens are not accepted by the server\" }, 401);\n }\n\n if (kind === \"opaque\") {\n // DB に登録済みキーか確認(失効チェック)\n const keyHash = createHash(\"sha256\").update(apiKey).digest(\"hex\");\n const [dbKey] = await db\n .select({ id: apiKeys.id, tenantId: apiKeys.tenantId, revokedAt: apiKeys.revokedAt })\n .from(apiKeys)\n .where(eq(apiKeys.keyHash, keyHash))\n .limit(1);\n\n if (dbKey) {\n if (dbKey.revokedAt) {\n // 失効済み → 401\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.apiKeyRevoked\", locale) }, 401);\n }\n // lastUsedAt 更新(fire-and-forget)\n db.update(apiKeys)\n .set({ lastUsedAt: new Date() })\n .where(eq(apiKeys.id, dbKey.id))\n .then(() => {})\n .catch(() => {});\n\n // tenants.tier から Plan を解決\n const [tenant] = await db\n .select({ tier: tenants.tier })\n .from(tenants)\n .where(eq(tenants.id, dbKey.tenantId))\n .limit(1);\n\n c.set(\"tenantId\", dbKey.tenantId);\n if (tenant?.tier) {\n c.set(\"plan\", resolvePlanFromTier(tenant.tier as PlanTier, dbKey.tenantId));\n }\n await next();\n return;\n }\n // DB 未登録の opaque キーは不正 → フォールスルー\n }\n // 不正な形式 → フォールスルーせずデフォルトのまま進む\n }\n\n // 2. Cookie セッション認証(Better Auth)\n const session = await auth.api.getSession({\n headers: c.req.raw.headers,\n });\n\n if (session) {\n c.set(\"user\", session.user);\n c.set(\"session\", session.session);\n\n // Cookie からアクティブテナントを読み取り、メンバーシップ検証\n const activeTenantId = getCookie(c, \"active-tenant-id\");\n\n if (activeTenantId) {\n const [verified] = await db\n .select({ tenantId: tenantMembers.tenantId, role: tenantMembers.role })\n .from(tenantMembers)\n .where(\n and(\n eq(tenantMembers.tenantId, activeTenantId),\n eq(tenantMembers.userId, session.user.id),\n ),\n )\n .limit(1);\n\n if (verified) {\n c.set(\"tenantId\", verified.tenantId);\n c.set(\"memberRole\", verified.role as import(\"./types.js\").MemberRole);\n } else {\n // 不正 Cookie → フォールバック(最初のテナント)\n const [fallback] = await db\n .select({ tenantId: tenantMembers.tenantId, role: tenantMembers.role })\n .from(tenantMembers)\n .where(eq(tenantMembers.userId, session.user.id))\n .limit(1);\n if (fallback) {\n c.set(\"tenantId\", fallback.tenantId);\n c.set(\"memberRole\", fallback.role as import(\"./types.js\").MemberRole);\n }\n }\n } else {\n // Cookie なし → 従来通り最初のテナント\n const [membership] = await db\n .select({ tenantId: tenantMembers.tenantId, role: tenantMembers.role })\n .from(tenantMembers)\n .where(eq(tenantMembers.userId, session.user.id))\n .limit(1);\n if (membership) {\n c.set(\"tenantId\", membership.tenantId);\n c.set(\"memberRole\", membership.role as import(\"./types.js\").MemberRole);\n }\n }\n\n // tenants.tier から Plan を解決\n const resolvedTenantId = c.get(\"tenantId\");\n if (resolvedTenantId) {\n const [tenant] = await db\n .select({ tier: tenants.tier })\n .from(tenants)\n .where(eq(tenants.id, resolvedTenantId))\n .limit(1);\n if (tenant?.tier) {\n c.set(\"plan\", resolvePlanFromTier(tenant.tier as PlanTier, resolvedTenantId));\n }\n }\n }\n\n await next();\n });\n}\n\n// ── requireAuth ──\n\nexport const requireAuth = createMiddleware<{ Variables: AppVariables }>(\n async (c, next) => {\n const user = c.get(\"user\");\n const tenantId = c.get(\"tenantId\");\n\n // セッション認証(user あり)または API Key 認証(tenantId あり)のいずれかが必要\n if (!user && !tenantId) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n await next();\n },\n);\n\n// ── requireVerifiedEmail ──\n\n/** メール未確認ユーザーの書き込み系 API をブロック(403) */\nexport const requireVerifiedEmail = createMiddleware<{ Variables: AppVariables }>(\n async (c, next) => {\n const user = c.get(\"user\");\n // API Key 認証(user=null)はスキップ\n if (!user) { await next(); return; }\n\n // 読み取り系はスキップ\n const method = c.req.method.toUpperCase();\n if (method === \"GET\" || method === \"HEAD\" || method === \"OPTIONS\") {\n await next(); return;\n }\n\n // テナント切替・招待受諾/辞退は未確認でも許可\n const path = c.req.path;\n if (\n path === \"/api/v1/tenants/switch\" ||\n /^\\/api\\/v1\\/tenants\\/my-invitations\\/[^/]+\\/(accept|decline)$/.test(path)\n ) {\n await next(); return;\n }\n\n if (!user.emailVerified) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json(\n { error: tWithLocale(\"serverErrors.emailVerificationRequired\", locale), code: \"EMAIL_NOT_VERIFIED\" },\n 403,\n );\n }\n\n await next();\n },\n);\n","import { Hono } from \"hono\";\nimport { stringify as yamlStringify } from \"yaml\";\nimport type { Inngest } from \"inngest\";\nimport { ParsedRunbookSchema } from \"../../schemas/runbook-schema.js\";\nimport type { RunbookStore } from \"../store/runbook-store.js\";\nimport { isEditable, isVerifiable } from \"../store/version-lifecycle.js\";\nimport type { VersionStatus } from \"../store/version-lifecycle.js\";\nimport type { JobStore } from \"../store/job-store.js\";\nimport type { ScheduleStore } from \"../store/schedule-store.js\";\nimport type { AppVariables } from \"../middleware/types.js\";\nimport { requireRole } from \"../middleware/rbac.js\";\nimport { requirePlanFeature } from \"../middleware/plan-gate.js\";\nimport { encrypt, decrypt, isMaskedValue } from \"../crypto.js\";\nimport type { getDb } from \"../db/client.js\";\nimport { runbookSettings, runbookSteps, runbookVersions } from \"../db/schema.js\";\nimport { desc } from \"drizzle-orm\";\nimport { eq } from \"drizzle-orm\";\nimport type { ServerConfig } from \"../config.js\";\nimport { buildExecutionConfig } from \"../helpers/execution-config-builder.js\";\nimport { ArtifactDBStore } from \"../store/artifact-store.js\";\nimport { GCSArtifactStore } from \"../../storage/gcs-store.js\";\nimport { LocalArtifactStore } from \"../../storage/local-store.js\";\nimport type { ArtifactStore } from \"../../storage/types.js\";\n\nexport function createRunbookHandlers(\n store: RunbookStore,\n jobStore: JobStore,\n inngest: Inngest,\n encryptionKey?: string,\n scheduleStore?: ScheduleStore,\n db?: ReturnType<typeof getDb>,\n config?: ServerConfig,\n) {\n const app = new Hono<{ Variables: AppVariables }>();\n\n // POST /api/v1/runbooks(developer 以上)\n app.post(\"/\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const body = await c.req.json();\n\n // draft モード: title のみ必須、ParsedRunbookSchema バリデーションをスキップ\n if (body.draft) {\n if (!body.title || typeof body.title !== \"string\" || !body.title.trim()) {\n return c.json({ error: \"Title is required for draft\" }, 400);\n }\n const row = await store.insertDraft({\n tenantId,\n createdBy: userId,\n title: body.title.trim(),\n goal: body.goal,\n startUrl: body.startUrl,\n context: body.context,\n secrets: encryptSecrets(body.secrets, encryptionKey),\n variables: body.variables,\n });\n return c.json({ id: row.id }, 201);\n }\n\n const parsed = ParsedRunbookSchema.safeParse(body.runbook);\n if (!parsed.success) {\n return c.json(\n { error: \"Invalid runbook\", details: parsed.error.issues },\n 400,\n );\n }\n\n // ステップ数のプランゲートチェック\n const plan = c.get(\"plan\");\n const stepCount = parsed.data.steps.length;\n if (stepCount > plan.limits.maxStepsPerRunbook) {\n return c.json({\n error: `Runbook has ${stepCount} steps, but your plan allows up to ${plan.limits.maxStepsPerRunbook}`,\n }, 403);\n }\n\n const row = await store.insert({\n tenantId,\n createdBy: userId,\n runbook: parsed.data,\n secrets: encryptSecrets(body.secrets, encryptionKey),\n context: body.context,\n settings: body.settings,\n });\n\n return c.json({ id: row.id }, 201);\n });\n\n // GET /api/v1/runbooks\n app.get(\"/\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const limit = Number(c.req.query(\"limit\") ?? \"50\");\n const offset = Number(c.req.query(\"offset\") ?? \"0\");\n const statusParam = c.req.query(\"status\") as\n | \"draft\"\n | \"pending_verification\"\n | \"active\"\n | \"disabled\"\n | undefined;\n const includeDisabled = c.req.query(\"includeDisabled\") === \"true\";\n\n const result = await store.list(tenantId, {\n limit,\n offset,\n status: statusParam,\n includeDisabled,\n });\n return c.json(result);\n });\n\n // GET /api/v1/runbooks/:id\n app.get(\"/:id\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n // secrets: ?secrets=plain で復号値を返す(編集画面用)\n const wantPlain = c.req.query(\"secrets\") === \"plain\" && encryptionKey;\n const secrets = row.secrets.map((s) => ({\n key: s.key,\n value: wantPlain ? decryptSafe(s.encryptedValue, encryptionKey!) : \"***\",\n }));\n\n return c.json({ ...row, secrets });\n });\n\n // GET /api/v1/runbooks/:id/yaml\n app.get(\"/:id/yaml\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n const parsedRunbook = rebuildParsedRunbook(row);\n const yaml = yamlStringify(parsedRunbook);\n\n c.header(\"Content-Type\", \"text/yaml; charset=utf-8\");\n return c.body(yaml);\n });\n\n // PUT /api/v1/runbooks/:id(developer 以上)\n app.put(\"/:id\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const body = await c.req.json();\n\n const currentStatus = await store.getStatus(tenantId, id);\n if (!currentStatus) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n // draft / pending_verification ステータスはバリデーションなしで部分保存\n if (currentStatus === \"draft\" || currentStatus === \"pending_verification\") {\n let processedSecrets = body.secrets;\n if (body.secrets && encryptionKey) {\n const existing = await store.findById(tenantId, id);\n processedSecrets = encryptSecrets(body.secrets, encryptionKey, existing?.secrets);\n }\n const updated = await store.updateDraft(tenantId, id, {\n title: body.title,\n goal: body.goal,\n startUrl: body.startUrl,\n context: body.context,\n settings: body.settings,\n secrets: processedSecrets,\n variables: body.variables,\n });\n if (!updated) {\n return c.json({ error: \"Not found\" }, 404);\n }\n return c.json(updated);\n }\n\n let parsedRunbook: ReturnType<typeof ParsedRunbookSchema.parse> | undefined;\n if (body.runbook) {\n const parsed = ParsedRunbookSchema.safeParse(body.runbook);\n if (!parsed.success) {\n return c.json(\n { error: \"Invalid runbook\", details: parsed.error.issues },\n 400,\n );\n }\n parsedRunbook = parsed.data;\n\n // ステップ数のプランゲートチェック\n const plan = c.get(\"plan\");\n const stepCount = parsedRunbook.steps.length;\n if (stepCount > plan.limits.maxStepsPerRunbook) {\n return c.json({\n error: `Runbook has ${stepCount} steps, but your plan allows up to ${plan.limits.maxStepsPerRunbook}`,\n }, 403);\n }\n }\n\n // 自動バージョン作成(Business+ で maxRunbookVersions > 1 の場合)\n const plan = c.get(\"plan\");\n if (plan.limits.maxRunbookVersions > 1 && db) {\n const userId = c.get(\"user\")?.id;\n const result = await store.versions.createVersionFromActive(tenantId, id, userId, \"Auto-versioned on edit\");\n if (result && \"error\" in result && result.error === \"DRAFT_EXISTS\") {\n const draftVersionId = result.draftVersionId;\n let processedSecrets = body.secrets;\n if (body.secrets && encryptionKey) {\n const existing = await store.findById(tenantId, id);\n processedSecrets = encryptSecrets(body.secrets, encryptionKey, existing?.secrets);\n }\n await store.versions.updateVersion(tenantId, id, draftVersionId, {\n goal: parsedRunbook?.metadata.goal ?? body.goal,\n startUrl: parsedRunbook?.metadata.startUrl ?? body.startUrl,\n context: body.context,\n settings: body.settings,\n secrets: processedSecrets,\n variables: body.variables ?? (parsedRunbook ? parsedRunbook.variables : undefined),\n // steps は除外: フロントの DashboardStepSelector は情報が不足しており上書きすると selector が消失する\n title: parsedRunbook?.title ?? body.title,\n });\n // completeDraft: ステータスを pending_verification に遷移\n if (body.completeDraft) {\n await db.update(runbookVersions).set({\n status: \"pending_verification\",\n verificationJobId: null,\n }).where(eq(runbookVersions.id, draftVersionId));\n }\n // reverify: ステータスを pending_verification に + steps をクリア\n if (body.reverify) {\n await db.update(runbookVersions).set({\n status: \"pending_verification\",\n verificationJobId: null,\n }).where(eq(runbookVersions.id, draftVersionId));\n await db.delete(runbookSteps).where(eq(runbookSteps.versionId, draftVersionId));\n }\n const updated = await store.versions.findById(tenantId, id, draftVersionId);\n return c.json({ ...updated, versionCreated: false });\n }\n if (result && \"version\" in result) {\n const newVersionId = result.version.id;\n let processedSecrets = body.secrets;\n if (body.secrets && encryptionKey) {\n const existing = await store.findById(tenantId, id);\n processedSecrets = encryptSecrets(body.secrets, encryptionKey, existing?.secrets);\n }\n await store.versions.updateVersion(tenantId, id, newVersionId, {\n goal: parsedRunbook?.metadata.goal ?? body.goal,\n startUrl: parsedRunbook?.metadata.startUrl ?? body.startUrl,\n context: body.context,\n settings: body.settings,\n secrets: processedSecrets,\n variables: body.variables ?? (parsedRunbook ? parsedRunbook.variables : undefined),\n // steps は除外: createVersionFromActive が full selector 付きでコピー済み\n title: parsedRunbook?.title ?? body.title,\n });\n // completeDraft: ステータスを pending_verification に遷移\n if (body.completeDraft) {\n await db.update(runbookVersions).set({\n status: \"pending_verification\",\n verificationJobId: null,\n }).where(eq(runbookVersions.id, newVersionId));\n }\n // reverify: ステータスを pending_verification に + steps をクリア\n if (body.reverify) {\n await db.update(runbookVersions).set({\n status: \"pending_verification\",\n verificationJobId: null,\n }).where(eq(runbookVersions.id, newVersionId));\n await db.delete(runbookSteps).where(eq(runbookSteps.versionId, newVersionId));\n }\n const updated = await store.versions.findById(tenantId, id, newVersionId);\n return c.json({ ...updated, versionCreated: true });\n }\n }\n\n let processedSecrets = body.secrets;\n if (body.secrets && encryptionKey) {\n const existing = await store.findById(tenantId, id);\n processedSecrets = encryptSecrets(body.secrets, encryptionKey, existing?.secrets);\n }\n const updated = await store.update(tenantId, id, {\n runbook: parsedRunbook,\n secrets: processedSecrets,\n context: body.context,\n settings: body.settings,\n variables: body.variables,\n skipStatusReset: body.skipStatusReset === true,\n });\n\n if (!updated) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n return c.json(updated);\n });\n\n // DELETE /api/v1/runbooks/:id(admin 以上)\n // draft, pending_verification, disabled のみ物理削除可。active は 400。\n app.delete(\"/:id\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const currentStatus = await store.getStatus(tenantId, id);\n if (!currentStatus) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (currentStatus === \"active\") {\n return c.json(\n { error: \"Cannot delete an active runbook. Disable it first.\" },\n 400,\n );\n }\n\n const deleted = await store.delete(tenantId, id);\n if (!deleted) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n return c.body(null, 204);\n });\n\n // POST /api/v1/runbooks/:id/complete-draft — 下書き完了(developer 以上)\n app.post(\"/:id/complete-draft\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const body = await c.req.json();\n\n const currentStatus = await store.getStatus(tenantId, id);\n if (!currentStatus) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (currentStatus !== \"draft\") {\n return c.json(\n { error: \"Only draft runbooks can be completed\" },\n 400,\n );\n }\n\n // draft 完了に必要なのはメタデータのみ(steps は不要)\n const { z } = await import(\"zod\");\n const draftCompleteSchema = z.object({\n title: z.string().min(1, \"Title is required\"),\n goal: z.string().min(1, \"Goal is required\"),\n startUrl: z.string().min(1, \"Start URL is required\"),\n });\n const parsed = draftCompleteSchema.safeParse(body);\n if (!parsed.success) {\n return c.json(\n { error: \"Runbook is not complete\", details: parsed.error.issues },\n 400,\n );\n }\n\n let processedSecrets = body.secrets;\n if (body.secrets && encryptionKey) {\n const existing = await store.findById(tenantId, id);\n processedSecrets = encryptSecrets(body.secrets, encryptionKey, existing?.secrets);\n }\n const updated = await store.completeDraft(tenantId, id, {\n title: body.title,\n goal: body.goal,\n startUrl: body.startUrl,\n context: body.context,\n settings: body.settings,\n secrets: processedSecrets,\n variables: body.variables,\n });\n\n if (!updated) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n return c.json(updated);\n });\n\n // POST /api/v1/runbooks/:id/verify — 実行確認ジョブ作成(developer 以上)\n app.post(\"/:id/verify\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const id = c.req.param(\"id\");\n\n const currentStatus = await store.getStatus(tenantId, id);\n if (!currentStatus) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (currentStatus !== \"pending_verification\") {\n return c.json(\n { error: \"Only pending_verification runbooks can be verified\" },\n 400,\n );\n }\n\n const rb = await store.findById(tenantId, id);\n if (!rb) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n const totalSteps = rb.steps.filter((s) => !s.parentStepId).length;\n\n if (totalSteps === 0) {\n // steps がない → generate ジョブで AI 探索\n if (!rb.startUrl || !rb.goal) {\n return c.json({ error: \"startUrl and goal are required for generation\" }, 400);\n }\n const job = await jobStore.insert({\n tenantId,\n mode: \"generate\",\n runbookId: id,\n runbookVersionId: rb.currentVersionId ?? undefined,\n purpose: \"verification\",\n createdBy: userId,\n startUrl: rb.startUrl,\n goal: rb.goal,\n context: rb.context ?? \"\",\n });\n await store.setVerificationJob(tenantId, id, job.id);\n await inngest.send({\n name: \"job/generate\",\n data: { jobId: job.id, tenantId },\n });\n return c.json({ jobId: job.id }, 201);\n }\n\n // steps がある → execute ジョブで実行確認\n const job = await jobStore.insert({\n tenantId,\n runbookId: id,\n runbookVersionId: rb.currentVersionId ?? undefined,\n totalSteps,\n purpose: \"verification\",\n createdBy: userId,\n executionConfig: buildExecutionConfig(rb.settings),\n });\n\n await store.setVerificationJob(tenantId, id, job.id);\n\n await inngest.send({\n name: \"job/execute\",\n data: { jobId: job.id, tenantId },\n });\n\n return c.json({ jobId: job.id }, 201);\n });\n\n // POST /api/v1/runbooks/:id/regenerate — 再生成(developer 以上)\n // 既存ステップ + ジョブ関連データを削除し、AI 再生成ジョブを作成\n app.post(\"/:id/regenerate\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const id = c.req.param(\"id\");\n\n const currentStatus = await store.getStatus(tenantId, id);\n if (!currentStatus) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (currentStatus !== \"pending_verification\") {\n return c.json(\n { error: \"Only pending_verification runbooks can be regenerated\" },\n 400,\n );\n }\n\n const rb = await store.findById(tenantId, id);\n if (!rb) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (!rb.startUrl || !rb.goal) {\n return c.json({ error: \"startUrl and goal are required for regeneration\" }, 400);\n }\n\n // 1. 既存の検証ジョブが実行中なら cancelled に更新\n if (rb.verificationJobId) {\n const existingJob = await jobStore.findById(tenantId, rb.verificationJobId);\n if (existingJob && ![\"completed\", \"failed\", \"cancelled\"].includes(existingJob.status)) {\n await jobStore.updateStatus(rb.verificationJobId, \"cancelled\", {\n completedAt: new Date(),\n errorMessage: \"Regeneration requested\",\n });\n }\n\n // 2. アーティファクトファイル削除(GCS/ローカル)\n if (db) {\n const aStore: ArtifactStore = config?.gcsBucket\n ? new GCSArtifactStore(config.gcsBucket)\n : new LocalArtifactStore(\"/tmp/artifacts\");\n try {\n await aStore.deleteByJob(tenantId, rb.verificationJobId);\n } catch { /* ストレージ削除失敗は許容 */ }\n }\n\n // 3. ジョブ行削除(CASCADE で job_results, job_result_diagnostics, job_ai_metrics, job_artifacts 等も削除)\n await jobStore.delete(rb.verificationJobId);\n }\n\n // 4. runbook_steps 削除(現在のバージョンから)\n if (db && rb.currentVersionId) {\n await db.delete(runbookSteps).where(eq(runbookSteps.versionId, rb.currentVersionId));\n }\n\n // 5. generate ジョブ作成\n const job = await jobStore.insert({\n tenantId,\n mode: \"generate\",\n runbookId: id,\n runbookVersionId: rb.currentVersionId ?? undefined,\n purpose: \"verification\",\n createdBy: userId,\n startUrl: rb.startUrl,\n goal: rb.goal,\n context: rb.context ?? undefined,\n });\n await store.setVerificationJob(tenantId, id, job.id);\n await inngest.send({\n name: \"job/generate\",\n data: { jobId: job.id, tenantId },\n });\n\n return c.json({ jobId: job.id }, 201);\n });\n\n // POST /api/v1/runbooks/:id/activate — 有効化(admin 以上)\n app.post(\"/:id/activate\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const rb = await store.findById(tenantId, id);\n if (!rb) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (rb.status !== \"pending_verification\") {\n return c.json(\n { error: \"Only pending_verification runbooks can be activated\" },\n 400,\n );\n }\n\n // 実行確認ジョブが完了しているか確認\n if (rb.verificationJobId) {\n const job = await jobStore.findById(tenantId, rb.verificationJobId);\n if (job && job.status !== \"completed\") {\n return c.json(\n { error: \"Verification job has not completed yet\" },\n 400,\n );\n }\n }\n\n const body = await c.req.json().catch(() => ({}));\n // stepConfirmations や notes は将来的に保存可能(現時点はステータス更新のみ)\n void body;\n\n await store.updateStatus(tenantId, id, \"active\");\n return c.json({ status: \"active\" });\n });\n\n // POST /api/v1/runbooks/:id/disable — 無効化(admin 以上)\n app.post(\"/:id/disable\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const currentStatus = await store.getStatus(tenantId, id);\n if (!currentStatus) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (currentStatus !== \"active\") {\n return c.json(\n { error: \"Only active runbooks can be disabled\" },\n 400,\n );\n }\n\n await store.updateStatus(tenantId, id, \"disabled\");\n return c.json({ status: \"disabled\" });\n });\n\n // POST /api/v1/runbooks/:id/enable — 有効化(admin 以上)\n app.post(\"/:id/enable\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const currentStatus = await store.getStatus(tenantId, id);\n if (!currentStatus) return c.json({ error: \"Not found\" }, 404);\n if (currentStatus !== \"disabled\") {\n return c.json({ error: \"Only disabled runbooks can be enabled\" }, 400);\n }\n await store.updateStatus(tenantId, id, \"active\");\n return c.json({ status: \"active\" });\n });\n\n // POST /api/v1/runbooks/:id/duplicate — 手順書の複製(developer 以上)\n app.post(\"/:id/duplicate\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const id = c.req.param(\"id\");\n\n const result = await store.duplicate(tenantId, id, userId);\n if (!result) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n return c.json({ id: result.id }, 201);\n });\n\n // PATCH /api/v1/runbooks/:id/steps — ステップ部分更新(developer 以上)\n app.patch(\"/:id/steps\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const currentStatus = await store.getStatus(tenantId, id);\n if (!currentStatus) {\n return c.json({ error: \"Not found\" }, 404);\n }\n const body = await c.req.json();\n if (!Array.isArray(body.steps) || body.steps.length === 0) {\n return c.json({ error: \"steps array is required\" }, 400);\n }\n\n const validRiskLevels = [\"low\", \"medium\", \"high\"];\n const patches: Array<{ id: string; description?: string; riskLevel?: string; requiresConfirmation?: boolean }> = [];\n for (const s of body.steps) {\n if (!s.id || typeof s.id !== \"string\") {\n return c.json({ error: \"Each step must have a string id\" }, 400);\n }\n if (s.riskLevel !== undefined && !validRiskLevels.includes(s.riskLevel)) {\n return c.json({ error: `Invalid riskLevel: ${s.riskLevel}` }, 400);\n }\n patches.push({\n id: s.id,\n description: s.description,\n riskLevel: s.riskLevel,\n requiresConfirmation: s.requiresConfirmation,\n });\n }\n\n const ok = await store.patchSteps(tenantId, id, patches);\n if (!ok) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n return c.json({ ok: true });\n });\n\n // GET /api/v1/runbooks/:id/context — context ダウンロード\n app.get(\"/:id/context\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (!row.context) {\n return c.json({ error: \"No context set\" }, 404);\n }\n\n c.header(\"Content-Type\", \"text/markdown; charset=utf-8\");\n c.header(\"Content-Disposition\", `attachment; filename=\"${id}-context.md\"`);\n return c.body(row.context);\n });\n\n // POST /api/v1/runbooks/:id/self-heal — Self-Heal 有効/無効切替(developer 以上、Team+)\n app.post(\"/:id/self-heal\", requireRole(\"developer\"), requirePlanFeature(\"selfHealMode\", \"Team\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const body = await c.req.json<{ enabled: boolean }>();\n if (typeof body.enabled !== \"boolean\") {\n return c.json({ error: \"enabled (boolean) is required\" }, 400);\n }\n\n const rb = await store.findById(tenantId, id);\n if (!rb) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (db && rb.currentVersionId) {\n // runbookSettings の selfHealEnabled を更新(upsert)\n const existingSettings = await db.query.runbookSettings.findFirst({\n where: eq(runbookSettings.versionId, rb.currentVersionId),\n });\n if (existingSettings) {\n await db.update(runbookSettings)\n .set({ selfHealEnabled: body.enabled })\n .where(eq(runbookSettings.versionId, rb.currentVersionId));\n } else {\n await db.insert(runbookSettings).values({\n versionId: rb.currentVersionId,\n selfHealEnabled: body.enabled,\n });\n }\n }\n\n if (scheduleStore) {\n if (body.enabled) {\n // self-heal 用定期スケジュールを作成(既存がなければ)\n const existing = await scheduleStore.findByRunbookAndPurpose(tenantId, id, \"self_heal\");\n if (!existing) {\n await scheduleStore.insert({\n tenantId,\n runbookId: id,\n type: \"recurring\",\n cron: \"0 3 * * *\", // 毎日 AM 3:00\n timezone: \"UTC\",\n purpose: \"self_heal\",\n enabled: true,\n createdBy: c.get(\"user\")?.id,\n });\n } else if (!existing.enabled) {\n await scheduleStore.update(tenantId, existing.id, { enabled: true });\n }\n } else {\n // self-heal スケジュールを無効化\n await scheduleStore.deleteByRunbookAndPurpose(tenantId, id, \"self_heal\");\n }\n }\n\n return c.json({ enabled: body.enabled });\n });\n\n // GET /api/v1/runbooks/:id/self-heal — Self-Heal ステータス取得\n app.get(\"/:id/self-heal\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const rb = await store.findById(tenantId, id);\n if (!rb) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n const selfHealEnabled = rb.settings?.selfHealEnabled ?? false;\n\n // self-heal スケジュール取得\n let schedule: { id: string; cron: string | null; nextRunAt: Date | string | null; lastRunAt: Date | string | null } | null = null;\n if (scheduleStore) {\n const s = await scheduleStore.findByRunbookAndPurpose(tenantId, id, \"self_heal\");\n if (s) {\n schedule = {\n id: s.id,\n cron: s.cron,\n nextRunAt: s.nextRunAt,\n lastRunAt: s.lastRunAt,\n };\n }\n }\n\n // 最新の self-heal ジョブを取得\n let latestJob: { id: string; status: string; createdAt: Date; hasSuggestions: boolean; goalAchieved: boolean } | null = null;\n const jobResult = await jobStore.list(tenantId, {\n runbookId: id,\n mode: \"self_heal\",\n limit: 1,\n });\n if (jobResult.items.length > 0) {\n const job = jobResult.items[0];\n const fullJob = await jobStore.findById(tenantId, job.id);\n const hasSuggestions = (fullJob?.debugSuggestions ?? []).length > 0;\n // goalAchieved: 全ステップ成功 = true, それ以外 = false\n const goalAchieved = job.status === \"completed\" && !hasSuggestions;\n latestJob = {\n id: job.id,\n status: job.status,\n createdAt: job.createdAt,\n hasSuggestions,\n goalAchieved,\n };\n }\n\n return c.json({ enabled: selfHealEnabled, schedule, latestJob });\n });\n\n // ── バージョン API ──\n\n // POST /api/v1/runbooks/:id/versions — 新バージョン作成(developer 以上)\n app.post(\"/:id/versions\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const id = c.req.param(\"id\");\n const body = await c.req.json().catch(() => ({}));\n\n const result = await store.versions.createVersionFromActive(tenantId, id, userId, body.changeDescription);\n if (!result) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (\"error\" in result) {\n return c.json({ error: \"A draft version already exists\", draftVersionId: result.draftVersionId }, 409);\n }\n return c.json(result.version, 201);\n });\n\n // GET /api/v1/runbooks/:id/versions — バージョン一覧\n app.get(\"/:id/versions\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const versions = await store.versions.list(tenantId, id);\n if (!versions) {\n return c.json({ error: \"Not found\" }, 404);\n }\n return c.json(versions);\n });\n\n // GET /api/v1/runbooks/:id/versions/:vid — バージョン詳細\n app.get(\"/:id/versions/:vid\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n\n const version = await store.versions.findById(tenantId, id, vid);\n if (!version) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n // secrets: ?secrets=plain で復号値を返す(編集画面用)\n const wantPlain = c.req.query(\"secrets\") === \"plain\" && encryptionKey;\n const secrets = version.secrets.map((s) => ({\n key: s.key,\n value: wantPlain ? decryptSafe(s.encryptedValue, encryptionKey!) : \"***\",\n }));\n\n return c.json({ ...version, secrets });\n });\n\n // PUT /api/v1/runbooks/:id/versions/:vid — バージョン編集(draft/pending_verification のみ)\n app.put(\"/:id/versions/:vid\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n const body = await c.req.json();\n\n let processedSecrets = body.secrets;\n if (body.secrets && encryptionKey) {\n const existing = await store.versions.findById(tenantId, id, vid);\n processedSecrets = encryptSecrets(body.secrets, encryptionKey, existing?.secrets);\n }\n\n const result = await store.versions.updateVersion(tenantId, id, vid, {\n goal: body.goal,\n startUrl: body.startUrl,\n context: body.context,\n settings: body.settings,\n secrets: processedSecrets,\n variables: body.variables,\n changeDescription: body.changeDescription,\n });\n if (!result) {\n return c.json({ error: \"Not found or not editable\" }, 404);\n }\n return c.json(result);\n });\n\n // DELETE /api/v1/runbooks/:id/versions/:vid — in-progress バージョン削除(draft / pending_verification)\n app.delete(\"/:id/versions/:vid\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n\n const deleted = await store.versions.deleteVersion(tenantId, id, vid);\n if (!deleted) {\n return c.json({ error: \"Not found or not deletable\" }, 404);\n }\n return c.body(null, 204);\n });\n\n // POST /api/v1/runbooks/:id/versions/:vid/complete-draft — draft → pending_verification\n app.post(\"/:id/versions/:vid/complete-draft\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n const body = await c.req.json().catch(() => ({}));\n // steps は除外: フロントの DashboardStep は selector 情報が不足しており\n // 上書きすると copyVersionData でコピー済みの full selector が消失する。\n // steps の編集は別 API (PATCH /steps) で行う。\n delete body.steps;\n\n // 安全網: マスク値 (***) で secrets が上書きされないようにする\n if (body.secrets && encryptionKey) {\n const existing = await store.versions.findById(tenantId, id, vid);\n body.secrets = encryptSecrets(body.secrets, encryptionKey, existing?.secrets);\n }\n\n const result = await store.versions.completeVersion(tenantId, id, vid, body);\n if (!result) {\n return c.json({ error: \"Not found or not a draft\" }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/v1/runbooks/:id/versions/:vid/verify — 検証ジョブ作成\n app.post(\"/:id/versions/:vid/verify\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n\n const version = await store.versions.findById(tenantId, id, vid);\n if (!version) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (!isVerifiable(version.status as VersionStatus)) {\n return c.json({ error: `Cannot verify: version is ${version.status}` }, 400);\n }\n\n const totalSteps = version.steps.filter((s) => !s.parentStepId).length;\n\n if (totalSteps === 0) {\n // steps なし → generate ジョブ\n if (!version.startUrl || !version.goal) {\n return c.json({ error: \"startUrl and goal are required for generation\" }, 400);\n }\n const job = await jobStore.insert({\n tenantId,\n mode: \"generate\",\n runbookId: id,\n runbookVersionId: vid,\n purpose: \"verification\",\n createdBy: userId,\n startUrl: version.startUrl,\n goal: version.goal,\n context: version.context ?? \"\",\n });\n await store.versions.setVerificationJob(vid, job.id);\n await inngest.send({\n name: \"job/generate\",\n data: { jobId: job.id, tenantId },\n });\n return c.json({ jobId: job.id }, 201);\n }\n\n // steps あり → execute ジョブ\n const job = await jobStore.insert({\n tenantId,\n runbookId: id,\n runbookVersionId: vid,\n totalSteps,\n purpose: \"verification\",\n createdBy: userId,\n executionConfig: buildExecutionConfig(version.settings),\n });\n await store.versions.setVerificationJob(vid, job.id);\n await inngest.send({\n name: \"job/execute\",\n data: { jobId: job.id, tenantId },\n });\n return c.json({ jobId: job.id }, 201);\n });\n\n // POST /api/v1/runbooks/:id/versions/:vid/regenerate — 再生成\n app.post(\"/:id/versions/:vid/regenerate\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n\n const version = await store.versions.findById(tenantId, id, vid);\n if (!version) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (!isVerifiable(version.status as VersionStatus)) {\n return c.json({ error: `Cannot regenerate: version is ${version.status}` }, 400);\n }\n if (!version.startUrl || !version.goal) {\n return c.json({ error: \"startUrl and goal are required for regeneration\" }, 400);\n }\n\n // 既存の検証ジョブをキャンセル\n if (version.verificationJobId) {\n const existingJob = await jobStore.findById(tenantId, version.verificationJobId);\n if (existingJob && ![\"completed\", \"failed\", \"cancelled\"].includes(existingJob.status)) {\n await jobStore.updateStatus(version.verificationJobId, \"cancelled\", {\n completedAt: new Date(),\n errorMessage: \"Regeneration requested\",\n });\n }\n await jobStore.delete(version.verificationJobId);\n }\n\n // steps 削除\n if (db) {\n await db.delete(runbookSteps).where(eq(runbookSteps.versionId, vid));\n }\n\n // generate ジョブ作成\n const job = await jobStore.insert({\n tenantId,\n mode: \"generate\",\n runbookId: id,\n runbookVersionId: vid,\n purpose: \"verification\",\n createdBy: userId,\n startUrl: version.startUrl,\n goal: version.goal,\n context: version.context ?? undefined,\n });\n await store.versions.setVerificationJob(vid, job.id);\n await inngest.send({\n name: \"job/generate\",\n data: { jobId: job.id, tenantId },\n });\n return c.json({ jobId: job.id }, 201);\n });\n\n // POST /api/v1/runbooks/:id/versions/:vid/request-review — レビューリクエスト(developer 以上、Business+)\n app.post(\"/:id/versions/:vid/request-review\", requireRole(\"developer\"), requirePlanFeature(\"runbookApprovalWorkflow\", \"Business\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n\n const version = await store.versions.findById(tenantId, id, vid);\n if (!version) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (!isVerifiable(version.status as VersionStatus)) {\n return c.json({ error: `Cannot request review: version is ${version.status}` }, 400);\n }\n\n // 検証ジョブが完了していることを確認\n if (!version.verificationJobId) {\n return c.json({ error: \"Version must be verified before requesting review\" }, 400);\n }\n const verificationJob = await jobStore.findBasicById(tenantId, version.verificationJobId);\n if (!verificationJob || verificationJob.status !== \"completed\") {\n return c.json({ error: \"Verification must be completed before requesting review\" }, 400);\n }\n\n // pending_approval に遷移\n await store.versions.updateStatus(vid, \"pending_approval\");\n const review = await store.versions.requestReview(vid, userId!);\n return c.json(review, 201);\n });\n\n // POST /api/v1/runbooks/:id/versions/:vid/review — レビュー応答(developer 以上、Business+)\n app.post(\"/:id/versions/:vid/review\", requireRole(\"developer\"), requirePlanFeature(\"runbookApprovalWorkflow\", \"Business\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n\n const vid = c.req.param(\"vid\");\n const body = await c.req.json<{ status: \"approved\" | \"rejected\"; comment?: string }>();\n if (![\"approved\", \"rejected\"].includes(body.status)) {\n return c.json({ error: \"status must be 'approved' or 'rejected'\" }, 400);\n }\n\n // 最新の pending レビューを取得\n const reviews = await store.versions.getReviews(vid);\n const pendingReview = reviews.find((r) => r.status === \"pending\");\n if (!pendingReview) {\n return c.json({ error: \"No pending review found\" }, 404);\n }\n\n // 自己承認チェック(allowSelfApproval 設定に基づく)\n if (body.status === \"approved\" && userId === pendingReview.requestedBy && db) {\n const { tenantDevelopmentSettings } = await import(\"../db/schema.js\");\n const devSettings = await db.query.tenantDevelopmentSettings.findFirst({\n where: eq(tenantDevelopmentSettings.tenantId, tenantId),\n });\n if (!(devSettings?.allowSelfApproval ?? false)) {\n return c.json({ error: \"Self-approval is not allowed\" }, 400);\n }\n }\n\n await store.versions.submitReview(pendingReview.id, userId!, body.status, body.comment);\n\n // rejected → pending_verification に戻す\n if (body.status === \"rejected\") {\n await store.versions.updateStatus(vid, \"pending_verification\");\n }\n\n return c.json({ status: body.status });\n });\n\n // POST /api/v1/runbooks/:id/versions/:vid/publish — バージョンを公開(active 化)\n app.post(\"/:id/versions/:vid/publish\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const plan = c.get(\"plan\");\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n\n // requireApprovalBeforePublish チェック(Business+)\n if (plan.features.runbookApprovalWorkflow && db) {\n const { tenantDevelopmentSettings } = await import(\"../db/schema.js\");\n const devSettings = await db.query.tenantDevelopmentSettings.findFirst({\n where: eq(tenantDevelopmentSettings.tenantId, tenantId),\n });\n if (devSettings?.requireApprovalBeforePublish) {\n const version = await store.versions.findById(tenantId, id, vid);\n if (version?.status !== \"pending_approval\") {\n // pending_approval ステータスかつ承認済みレビューがあるか確認\n const reviews = await store.versions.getReviews(vid);\n const hasApproval = reviews.some((r) => r.status === \"approved\");\n if (!hasApproval) {\n return c.json({ error: \"Approval is required before publishing\" }, 400);\n }\n }\n }\n }\n\n const result = await store.versions.publishVersion(tenantId, id, vid, userId, plan.limits.maxRunbookVersions);\n if (!result) {\n return c.json({ error: \"Not found or not publishable\" }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/v1/runbooks/:id/versions/:vid/rollback — ロールバック(admin 以上、Business+)\n app.post(\"/:id/versions/:vid/rollback\", requireRole(\"admin\"), requirePlanFeature(\"runbookRollback\", \"Business\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const plan = c.get(\"plan\");\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n\n const result = await store.versions.rollbackVersion(tenantId, id, vid, userId, plan.limits.maxRunbookVersions);\n if (!result) {\n return c.json({ error: \"Not found or not an archived version\" }, 404);\n }\n return c.json(result);\n });\n\n // PATCH /api/v1/runbooks/:id/versions/:vid/steps — バージョンのステップ部分編集\n app.patch(\"/:id/versions/:vid/steps\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const vid = c.req.param(\"vid\");\n\n const version = await store.versions.findById(tenantId, id, vid);\n if (!version) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (!isEditable(version.status as VersionStatus)) {\n return c.json({ error: `Cannot edit: version is ${version.status}` }, 400);\n }\n\n const body = await c.req.json();\n if (!Array.isArray(body.steps) || body.steps.length === 0) {\n return c.json({ error: \"steps array is required\" }, 400);\n }\n\n const validRiskLevels = [\"low\", \"medium\", \"high\"];\n const patches: Array<{ id: string; description?: string; riskLevel?: string; requiresConfirmation?: boolean }> = [];\n for (const s of body.steps) {\n if (!s.id || typeof s.id !== \"string\") {\n return c.json({ error: \"Each step must have a string id\" }, 400);\n }\n if (s.riskLevel !== undefined && !validRiskLevels.includes(s.riskLevel)) {\n return c.json({ error: `Invalid riskLevel: ${s.riskLevel}` }, 400);\n }\n patches.push({\n id: s.id,\n description: s.description,\n riskLevel: s.riskLevel,\n requiresConfirmation: s.requiresConfirmation,\n });\n }\n\n const ok = await store.versions.patchSteps(tenantId, id, vid, patches);\n if (!ok) {\n return c.json({ error: \"Not found\" }, 404);\n }\n return c.json({ ok: true });\n });\n\n // GET /api/v1/runbooks/:id/versions/:vid/reviews — バージョンのレビュー一覧\n app.get(\"/:id/versions/:vid/reviews\", async (c) => {\n const vid = c.req.param(\"vid\");\n const reviews = await store.versions.getReviews(vid);\n return c.json(reviews);\n });\n\n // GET /api/v1/runbooks/:id/secrets — secrets ダウンロード(admin 以上)\n app.get(\"/:id/secrets\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n if (!encryptionKey) {\n return c.json({ error: \"Encryption key not configured\" }, 500);\n }\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n if (!row.secrets || row.secrets.length === 0) {\n return c.json({ error: \"No secrets set\" }, 404);\n }\n\n const decrypted: Record<string, string> = {};\n for (const s of row.secrets) {\n try {\n decrypted[s.key] = decrypt(s.encryptedValue, encryptionKey);\n } catch {\n // 復号失敗はスキップ\n }\n }\n\n c.header(\"Content-Type\", \"application/json; charset=utf-8\");\n c.header(\"Content-Disposition\", `attachment; filename=\"${id}-secrets.json\"`);\n return c.json(decrypted);\n });\n\n return app;\n}\n\n/**\n * secrets を暗号化する。マスク値(`••••`)は暗号化せず、既存の暗号化値を保持する。\n */\nfunction encryptSecrets(\n secrets: Record<string, string> | undefined,\n encryptionKey: string | undefined,\n existingSecrets?: { key: string; encryptedValue: string }[],\n): Record<string, string> | undefined {\n if (!secrets) return secrets;\n if (!encryptionKey) return secrets;\n const existingMap = new Map(existingSecrets?.map((s) => [s.key, s.encryptedValue]) ?? []);\n return Object.fromEntries(\n Object.entries(secrets).map(([key, val]) => [\n key,\n isMaskedValue(val) ? (existingMap.get(key) ?? val) : encrypt(val, encryptionKey),\n ]),\n );\n}\n\n/** 復号ヘルパー(失敗時はマスク値にフォールバック) */\nfunction decryptSafe(encryptedValue: string, key: string): string {\n try { return decrypt(encryptedValue, key); } catch { return \"***\"; }\n}\n\n/**\n * DB の正規化データから ParsedRunbook 相当のオブジェクトを再構築する。\n * secrets は除外(YAML にはセンシティブ値を含めない)。\n */\nexport function rebuildParsedRunbook(row: NonNullable<Awaited<ReturnType<RunbookStore[\"findById\"]>>>) {\n const variables: Record<string, Record<string, unknown>> = {};\n for (const v of row.variables) {\n variables[v.name] = {\n source: v.source,\n ...(v.description && { description: v.description }),\n required: v.required,\n sensitive: v.sensitive,\n ...(v.value && { value: v.value }),\n };\n }\n\n const steps = rebuildSteps(row.steps, null);\n\n return {\n title: row.title,\n settings: {\n baseUrl: row.startUrl ?? \"\",\n defaultTimeout:\n row.settings?.defaultTimeout ?? 10000,\n pauseBetweenSteps:\n row.settings?.pauseBetweenSteps ?? 500,\n stopOnError: row.settings?.stopOnError ?? true,\n },\n metadata: {\n startUrl: row.startUrl ?? \"\",\n goal: row.goal,\n goalAchieved: true,\n totalSteps: steps.length,\n generatedAt: row.generatedAt,\n },\n steps,\n ...(Object.keys(variables).length > 0 && { variables }),\n ...(row.context && { context: row.context }),\n };\n}\n\ntype StepRow = NonNullable<Awaited<ReturnType<RunbookStore[\"findById\"]>>>[\"steps\"][number];\n\nfunction rebuildSteps(allSteps: StepRow[], parentId: string | null): Record<string, unknown>[] {\n const children = allSteps.filter((s) => s.parentStepId === parentId && !s.branchCaseMatch && !s.branchIsDefault);\n\n return children.map((s) => {\n const action: Record<string, unknown> = { type: s.actionType };\n if (s.selector) action.selector = s.selector;\n if (s.value) action.value = s.value;\n if (s.optionText) action.optionText = s.optionText;\n if (s.url) action.url = s.url;\n if (s.script) action.script = s.script;\n if (s.keys) action.keys = s.keys;\n if (s.downloadPath) action.downloadPath = s.downloadPath;\n if (s.exportCollection) action.exportCollection = s.exportCollection;\n if (s.exportFormat) action.exportFormat = s.exportFormat;\n if (s.exportPath) action.exportPath = s.exportPath;\n\n const step: Record<string, unknown> = {\n ordinal: s.ordinal,\n description: s.description,\n action,\n url: s.url ?? \"\",\n riskLevel: s.riskLevel,\n requiresConfirmation: s.requiresConfirmation,\n };\n\n if (s.captures) step.captures = s.captures;\n if (s.condition) step.condition = s.condition;\n if (s.memoryOperations) step.memoryOperations = s.memoryOperations;\n\n // loop\n if (s.loopCondition || s.loopForEach) {\n const loop: Record<string, unknown> = {};\n if (s.loopCondition) loop.condition = s.loopCondition;\n if (s.loopForEach) loop.forEach = s.loopForEach;\n if (s.loopItemVariable) loop.itemVariable = s.loopItemVariable;\n if (s.loopIndexVariable) loop.indexVariable = s.loopIndexVariable;\n if (s.loopMaxIterations) loop.maxIterations = s.loopMaxIterations;\n if (s.loopCounterVariable) loop.counterVariable = s.loopCounterVariable;\n step.loop = loop;\n\n // substeps\n const substeps = rebuildSteps(allSteps, s.id);\n if (substeps.length > 0) step.steps = substeps;\n }\n\n // branches\n if (s.branchValue) {\n const branchChildren = allSteps.filter((c) => c.parentStepId === s.id);\n const caseMatches = new Set(\n branchChildren.filter((c) => c.branchCaseMatch).map((c) => c.branchCaseMatch!),\n );\n const cases = [...caseMatches].map((match) => ({\n match,\n steps: rebuildSteps(\n branchChildren.filter((c) => c.branchCaseMatch === match),\n // Pass parentId=null to treat these as top-level within their branch\n null,\n ).length > 0\n ? branchChildren\n .filter((c) => c.branchCaseMatch === match)\n .map((c) => rebuildStepFromRow(c, allSteps))\n : [],\n }));\n\n const defaultChildren = branchChildren.filter((c) => c.branchIsDefault);\n const branches: Record<string, unknown> = {\n value: s.branchValue,\n cases,\n };\n if (defaultChildren.length > 0) {\n branches.default = {\n steps: defaultChildren.map((c) => rebuildStepFromRow(c, allSteps)),\n };\n }\n step.branches = branches;\n }\n\n return step;\n });\n}\n\nfunction rebuildStepFromRow(s: StepRow, _allSteps: StepRow[]): Record<string, unknown> {\n const action: Record<string, unknown> = { type: s.actionType };\n if (s.selector) action.selector = s.selector;\n if (s.value) action.value = s.value;\n if (s.optionText) action.optionText = s.optionText;\n if (s.url) action.url = s.url;\n if (s.script) action.script = s.script;\n if (s.keys) action.keys = s.keys;\n\n const result: Record<string, unknown> = {\n ordinal: s.ordinal,\n description: s.description,\n action,\n url: s.url ?? \"\",\n riskLevel: s.riskLevel,\n requiresConfirmation: s.requiresConfirmation,\n };\n if (s.captures) result.captures = s.captures;\n if (s.condition) result.condition = s.condition;\n if (s.memoryOperations) result.memoryOperations = s.memoryOperations;\n return result;\n}\n","/**\n * ロールベースアクセス制御ミドルウェア\n *\n * ロール階層: owner (3) > admin (2) > developer (1) > member (0)\n */\n\nimport { createMiddleware } from \"hono/factory\";\nimport type { AppVariables, MemberRole } from \"./types.js\";\nimport { tWithLocale, tfWithLocale, resolveAcceptLanguage } from \"../../i18n/index.js\";\n\nconst ROLE_LEVELS: Record<MemberRole, number> = {\n member: 0,\n developer: 1,\n admin: 2,\n owner: 3,\n};\n\n/**\n * 指定ロール以上を要求するミドルウェア。\n * API Key 認証(memberRole=null)はデフォルトで通過(rejectApiKey: true で拒否)。\n */\nexport function requireRole(\n minRole: MemberRole,\n opts?: { rejectApiKey?: boolean },\n) {\n return createMiddleware<{ Variables: AppVariables }>(async (c, next) => {\n const user = c.get(\"user\");\n const memberRole = c.get(\"memberRole\");\n\n if (!user) {\n // API Key 認証(user=null)\n if (opts?.rejectApiKey) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.sessionRequired\", locale) }, 401);\n }\n await next();\n return;\n }\n\n if (!memberRole || ROLE_LEVELS[memberRole] < ROLE_LEVELS[minRole]) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json(\n { error: tfWithLocale(\"serverErrors.roleForbidden\", locale, { role: minRole }) },\n 403,\n );\n }\n\n await next();\n });\n}\n\nexport function isAdminOrOwner(role: MemberRole | null): boolean {\n return role === \"owner\" || role === \"admin\";\n}\n\n/** ロール階層チェック(ミドルウェア外から使用するヘルパー) */\nexport function checkRole(role: MemberRole | null, minRole: MemberRole): boolean {\n if (!role) return false;\n return ROLE_LEVELS[role] >= ROLE_LEVELS[minRole];\n}\n","/**\n * プラン機能ゲートミドルウェア\n *\n * requireRole() と同パターンで、プラン機能フラグをチェックする。\n */\n\nimport { createMiddleware } from \"hono/factory\";\nimport type { AppVariables } from \"./types.js\";\nimport type { PlanFeatures } from \"../../plan/index.js\";\nimport { tfWithLocale, resolveAcceptLanguage } from \"../../i18n/index.js\";\n\n/**\n * 指定プラン機能が有効であることを要求するミドルウェア。\n * 無効な場合は 403 + i18n エラーメッセージを返す。\n */\nexport function requirePlanFeature(\n feature: keyof PlanFeatures,\n tierLabel: string,\n) {\n return createMiddleware<{ Variables: AppVariables }>(async (c, next) => {\n const plan = c.get(\"plan\");\n if (!plan.features[feature]) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json(\n { error: tfWithLocale(\"serverErrors.planFeatureRequired\", locale, { tier: tierLabel }) },\n 403,\n );\n }\n await next();\n });\n}\n","import { Hono } from \"hono\";\nimport type { Inngest } from \"inngest\";\nimport type { JobStore } from \"../store/job-store.js\";\nimport type { RunbookStore } from \"../store/runbook-store.js\";\nimport type { AppVariables, MemberRole } from \"../middleware/types.js\";\nimport { requireRole, checkRole } from \"../middleware/rbac.js\";\nimport type { JobStatus, JobMode } from \"../types/job-types.js\";\nimport { handleJobStream } from \"../sse/job-stream.js\";\nimport { TERMINAL_STATUSES } from \"../sse/types.js\";\nimport { getRedisPublisher } from \"../redis.js\";\nimport { MeteringStore } from \"../store/metering-store.js\";\nimport { ArtifactDBStore } from \"../store/artifact-store.js\";\nimport { createArtifactHandlers } from \"./artifacts.js\";\nimport { GCSArtifactStore } from \"../../storage/gcs-store.js\";\nimport { LocalArtifactStore } from \"../../storage/local-store.js\";\nimport type { ArtifactStore } from \"../../storage/types.js\";\nimport type { ServerConfig } from \"../config.js\";\nimport { and, eq, inArray } from \"drizzle-orm\";\nimport { runbooks, runbookVersions, jobApprovalRequests } from \"../db/schema.js\";\nimport { rebuildParsedRunbook } from \"./runbooks.js\";\nimport { buildExecutionConfig } from \"../helpers/execution-config-builder.js\";\nimport { tfWithLocale, resolveAcceptLanguage } from \"../../i18n/index.js\";\n\nconst validStatuses = new Set<JobStatus>([\n \"scheduled\",\n \"queued\",\n \"running\",\n \"waiting_approval\",\n \"paused\",\n \"completed\",\n \"failed\",\n \"cancelled\",\n \"exploring\",\n \"reviewing\",\n]);\n\nconst validModes = new Set<JobMode>([\"execute\", \"self_heal\", \"generate\"]);\n\nexport function createJobHandlers(\n store: JobStore,\n runbookStore: RunbookStore,\n inngest: Inngest,\n redisUrl?: string,\n db?: ReturnType<typeof import(\"../db/client.js\").getDb>,\n config?: ServerConfig,\n) {\n const meteringStore = db ? new MeteringStore(db) : null;\n const app = new Hono<{ Variables: AppVariables }>();\n\n // アーティファクトルートをマウント\n if (db) {\n const artifactDb = new ArtifactDBStore(db);\n const artifactStore: ArtifactStore = config?.gcsBucket\n ? new GCSArtifactStore(config.gcsBucket)\n : new LocalArtifactStore(\"/tmp/artifacts\");\n app.route(\"/:jobId/artifacts\", createArtifactHandlers(artifactDb, artifactStore));\n }\n\n // POST /api/v1/jobs — ジョブ作成(mode で分岐、generate は developer 以上)\n app.post(\"/\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const plan = c.get(\"plan\");\n const body = await c.req.json();\n\n // クォータチェック(月間ジョブ数)\n if (meteringStore && plan.limits.maxMonthlyJobs !== Number.POSITIVE_INFINITY) {\n try {\n const usage = await meteringStore.getCurrentUsage(tenantId);\n if (usage.jobCount >= plan.limits.maxMonthlyJobs) {\n return c.json({\n error: \"Monthly job quota exceeded\",\n usage: usage.jobCount,\n limit: plan.limits.maxMonthlyJobs,\n tier: plan.tier,\n }, 429);\n }\n } catch {\n // メータリングエラーはジョブ作成をブロックしない\n }\n }\n\n const mode: JobMode = body.mode ?? \"execute\";\n if (!validModes.has(mode)) {\n return c.json({ error: `Invalid mode: ${mode}` }, 400);\n }\n\n // generate モードは developer 以上を要求\n if (mode === \"generate\") {\n const memberRole = c.get(\"memberRole\") as MemberRole | null;\n if (c.get(\"user\") && !checkRole(memberRole, \"developer\")) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tfWithLocale(\"serverErrors.roleForbidden\", locale, { role: \"developer\" }) }, 403);\n }\n return await createGenerateJob(c, store, runbookStore, inngest, tenantId, userId, body);\n }\n\n // self_heal モードのプランゲート\n if (mode === \"self_heal\" && !plan.features.selfHealMode) {\n return c.json({ error: \"Self-heal mode requires Team plan or higher\" }, 403);\n }\n\n return await createExecuteJob(c, store, runbookStore, inngest, tenantId, userId, body, mode);\n });\n\n // GET /api/v1/jobs\n app.get(\"/\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const runbookId = c.req.query(\"runbookId\");\n const statusParam = c.req.query(\"status\");\n const modeParam = c.req.query(\"mode\");\n const limit = Number(c.req.query(\"limit\") ?? \"50\");\n const offset = Number(c.req.query(\"offset\") ?? \"0\");\n\n let status: JobStatus | undefined;\n if (statusParam) {\n if (!validStatuses.has(statusParam as JobStatus)) {\n return c.json({ error: `Invalid status: ${statusParam}` }, 400);\n }\n status = statusParam as JobStatus;\n }\n\n let mode: JobMode | undefined;\n if (modeParam) {\n if (!validModes.has(modeParam as JobMode)) {\n return c.json({ error: `Invalid mode: ${modeParam}` }, 400);\n }\n mode = modeParam as JobMode;\n }\n\n const result = await store.list(tenantId, {\n runbookId,\n status,\n mode,\n limit,\n offset,\n });\n\n // runbookTitle をバッチ取得して付与\n const runbookIds = [...new Set(result.items.filter((r) => r.runbookId).map((r) => r.runbookId!))];\n let titleMap = new Map<string, string>();\n if (runbookIds.length > 0 && db) {\n const rbRows = await db\n .select({ id: runbooks.id, title: runbooks.title })\n .from(runbooks)\n .where(inArray(runbooks.id, runbookIds));\n titleMap = new Map(rbRows.map((r) => [r.id, r.title]));\n }\n\n // versionNumber をバッチ取得\n const versionIds = [...new Set(result.items.filter((r) => r.runbookVersionId).map((r) => r.runbookVersionId!))];\n let versionMap = new Map<string, number>();\n if (versionIds.length > 0 && db) {\n const vRows = await db\n .select({ id: runbookVersions.id, versionNumber: runbookVersions.versionNumber })\n .from(runbookVersions)\n .where(inArray(runbookVersions.id, versionIds));\n versionMap = new Map(vRows.map((r) => [r.id, r.versionNumber]));\n }\n\n // アーティファクト有無をバッチチェック\n const jobIds = result.items.map((r) => r.id);\n let artifactJobIds = new Set<string>();\n if (jobIds.length > 0 && db) {\n const artifactDb = new ArtifactDBStore(db);\n artifactJobIds = await artifactDb.hasArtifactsByJobIds(tenantId, jobIds);\n }\n\n const items = result.items.map((item) => ({\n ...item,\n runbookTitle: item.runbookId ? titleMap.get(item.runbookId) ?? null : null,\n versionNumber: item.runbookVersionId ? versionMap.get(item.runbookVersionId) ?? null : null,\n hasArtifacts: artifactJobIds.has(item.id),\n }));\n\n return c.json({ items, total: result.total });\n });\n\n // GET /api/v1/jobs/:id\n app.get(\"/:id\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n // sensitive 変数をマスク\n const maskedVariables = row.variables.map((v) => ({\n key: v.key,\n value: v.sensitive ? \"***\" : v.value,\n sensitive: v.sensitive,\n }));\n\n // runbookTitle を付与\n let runbookTitle: string | null = null;\n if (row.runbookId && db) {\n const rbRow = await db\n .select({ title: runbooks.title })\n .from(runbooks)\n .where(eq(runbooks.id, row.runbookId))\n .limit(1);\n runbookTitle = rbRow[0]?.title ?? null;\n }\n\n // versionNumber を付与\n let versionNumber: number | null = null;\n if (row.runbookVersionId && db) {\n const vRow = await db\n .select({ versionNumber: runbookVersions.versionNumber })\n .from(runbookVersions)\n .where(eq(runbookVersions.id, row.runbookVersionId))\n .limit(1);\n versionNumber = vRow[0]?.versionNumber ?? null;\n }\n\n // pendingApproval 情報を取得(waiting_approval 状態のみ)\n let pendingApproval: { stepOrdinal: number; description: string; riskLevel: string } | null = null;\n if (row.status === \"waiting_approval\" && db) {\n try {\n const req = await db.query.jobApprovalRequests.findFirst({\n where: and(\n eq(jobApprovalRequests.jobId, id),\n eq(jobApprovalRequests.status, \"pending\"),\n ),\n });\n if (req) {\n pendingApproval = {\n stepOrdinal: req.stepOrdinal,\n description: req.stepDescription ?? \"\",\n riskLevel: req.riskLevel ?? \"low\",\n };\n }\n } catch { /* DB エラーは無視 */ }\n }\n\n return c.json({ ...row, variables: maskedVariables, runbookTitle, versionNumber, pendingApproval });\n });\n\n // POST /api/v1/jobs/:id/cancel — キャンセル(全モード共通)\n app.post(\"/:id/cancel\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findBasicById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n const cancellableStatuses = new Set<JobStatus>([\n \"scheduled\",\n \"queued\",\n \"running\",\n \"waiting_approval\",\n \"paused\",\n \"exploring\",\n \"reviewing\",\n ]);\n if (!cancellableStatuses.has(row.status)) {\n return c.json(\n { error: `Cannot cancel job in status: ${row.status}` },\n 400,\n );\n }\n\n await store.updateStatus(id, \"cancelled\", {\n completedAt: new Date(),\n });\n\n // Redis publish で Inngest 内のプロセスに cancel を伝える\n const cancelRedisUrl = redisUrl ?? process.env.REDIS_URL ?? \"redis://localhost:6379\";\n const redis = getRedisPublisher(cancelRedisUrl);\n await redis.publish(\n `job:${id}:intervention`,\n JSON.stringify({ type: \"cancel\" }),\n );\n\n // SSE イベントも発行(UI 即時反映用)\n await redis.publish(\n `job:${id}:events`,\n JSON.stringify({\n type: \"status_change\",\n timestamp: new Date().toISOString(),\n data: { status: \"cancelled\" },\n }),\n );\n\n return c.json({ status: \"cancelled\" });\n });\n\n // GET /api/v1/jobs/:id/live — SSE ストリーム\n app.get(\"/:id/live\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n const url = redisUrl ?? process.env.REDIS_URL ?? \"redis://localhost:6379\";\n return handleJobStream(c, store, tenantId, id, url, db);\n });\n\n // POST /api/v1/jobs/:id/approve/:step — ステップ承認(execute / self_heal 専用)\n app.post(\"/:id/approve/:step\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const stepOrdinal = Number(c.req.param(\"step\"));\n\n const row = await store.findBasicById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (row.mode === \"generate\") {\n return c.json({ error: \"Cannot approve steps on generate jobs\" }, 400);\n }\n\n if (row.status !== \"waiting_approval\") {\n return c.json({ error: \"Job is not waiting for approval\" }, 400);\n }\n\n const body = await c.req.json().catch(() => ({}));\n const action = (body as { action?: string }).action ?? \"approve\";\n if (![\"approve\", \"skip\", \"abort\"].includes(action)) {\n return c.json({ error: `Invalid action: ${action}` }, 400);\n }\n\n // Redis publish で ServerConfirmationProvider を再開\n const approvalRedisUrl = redisUrl ?? process.env.REDIS_URL ?? \"redis://localhost:6379\";\n const approvalRedis = getRedisPublisher(approvalRedisUrl);\n await approvalRedis.publish(\n `job:${id}:approval:${stepOrdinal}`,\n JSON.stringify({\n action: action as \"approve\" | \"skip\" | \"abort\",\n respondedBy: c.get(\"user\")?.id,\n }),\n );\n\n return c.json({ status: action });\n });\n\n // POST /api/v1/jobs/:id/pause — 一時停止(generate モード専用)\n app.post(\"/:id/pause\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findBasicById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (row.mode !== \"generate\") {\n return c.json({ error: \"Pause is only available for generate jobs\" }, 400);\n }\n\n if (row.status !== \"exploring\") {\n return c.json({ error: \"Job must be in exploring state to pause\" }, 400);\n }\n\n const url = redisUrl ?? process.env.REDIS_URL ?? \"redis://localhost:6379\";\n const redis = getRedisPublisher(url);\n await redis.publish(\n `job:${id}:intervention`,\n JSON.stringify({ type: \"pause\" }),\n );\n\n return c.json({ status: \"pause_requested\" });\n });\n\n // POST /api/v1/jobs/:id/resume — 再開(generate モード専用)\n app.post(\"/:id/resume\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findBasicById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (row.mode !== \"generate\") {\n return c.json({ error: \"Resume is only available for generate jobs\" }, 400);\n }\n\n const body = await c.req.json().catch(() => ({}));\n const guidance = (body as { guidance?: string }).guidance;\n\n const url = redisUrl ?? process.env.REDIS_URL ?? \"redis://localhost:6379\";\n const redis = getRedisPublisher(url);\n await redis.publish(\n `job:${id}:intervention`,\n JSON.stringify({ type: \"resume\", guidance }),\n );\n\n return c.json({ status: \"resumed\" });\n });\n\n // GET /api/v1/jobs/:id/suggestions — 修正提案取得(self_heal 専用)\n app.get(\"/:id/suggestions\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (row.mode !== \"self_heal\") {\n return c.json({ error: \"Suggestions are only available for self_heal jobs\" }, 400);\n }\n\n return c.json({\n debugReport: {\n warningSteps: row.debugWarnings ?? [],\n suggestions: row.debugSuggestions ?? [],\n },\n });\n });\n\n // POST /api/v1/jobs/:id/apply-fix — 修正適用(developer 以上、self_heal 専用)\n app.post(\"/:id/apply-fix\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (row.mode !== \"self_heal\") {\n return c.json({ error: \"apply-fix is only available for self_heal jobs\" }, 400);\n }\n\n if (row.status !== \"completed\" && row.status !== \"failed\") {\n return c.json({ error: \"Job must be completed or failed to apply fix\" }, 400);\n }\n\n const body = await c.req.json<{ suggestionIndex: number }>();\n if (typeof body.suggestionIndex !== \"number\") {\n return c.json({ error: \"suggestionIndex (number) is required\" }, 400);\n }\n\n const suggestions = row.debugSuggestions ?? [];\n if (body.suggestionIndex < 0 || body.suggestionIndex >= suggestions.length) {\n return c.json({ error: \"Invalid suggestionIndex\" }, 400);\n }\n\n const suggestion = suggestions[body.suggestionIndex];\n\n if (!row.runbookId) {\n return c.json({ error: \"Job has no associated runbook\" }, 400);\n }\n\n // Runbook の YAML を取得\n const rb = await runbookStore.findById(tenantId, row.runbookId);\n if (!rb) {\n return c.json({ error: \"Associated runbook not found\" }, 404);\n }\n\n try {\n // rebuildParsedRunbook → YAML 化\n const { stringify: yamlStringify } = await import(\"yaml\");\n const { generatePatchCore } = await import(\"../../fix-runbook/yaml-patcher.js\");\n const { runWithModelContext } = await import(\"../../harness/ai-model.js\");\n const { resolveTenantAIConfig, buildModelFactory } = await import(\"../inngest/helpers/tenant-ai-config.js\");\n const { loadServerConfig } = await import(\"../config.js\");\n\n const serverConfig = loadServerConfig();\n\n // ParsedRunbook 的なオブジェクトを再構築\n const parsedRb = rebuildParsedRunbook(rb);\n const originalYaml = yamlStringify(parsedRb);\n\n // AI config 解決\n const aiConfig = await resolveTenantAIConfig(db!, tenantId, serverConfig.encryptionKey);\n const modelFactory = await buildModelFactory(aiConfig);\n\n // パッチ生成(AI 呼び出し)\n const patchResult = await runWithModelContext(aiConfig, modelFactory, () =>\n generatePatchCore(originalYaml, {\n stepOrdinal: suggestion.stepOrdinal ?? 0,\n description: suggestion.stepDescription ?? \"\",\n error: suggestion.error ?? \"\",\n yamlFix: suggestion.runbookFix ?? undefined,\n category: suggestion.failureCategory ?? undefined,\n }),\n );\n\n if (!patchResult.success) {\n return c.json({ error: `Patch generation failed: ${patchResult.error}` }, 500);\n }\n\n // パッチ済み YAML をパースして runbook を更新\n const { parse: yamlParse } = await import(\"yaml\");\n const { ParsedRunbookSchema } = await import(\"../../schemas/runbook-schema.js\");\n const patchedDoc = yamlParse(patchResult.patchedYaml);\n const validated = ParsedRunbookSchema.parse(patchedDoc);\n\n // 既存の variables を保持(パッチ結果で上書きしない)\n const existingVariables = Object.fromEntries(\n rb.variables.map((v) => [v.name, {\n source: v.source as \"prompt\" | \"fixed\" | \"context\" | \"env\" | \"expression\" | \"data\",\n description: v.description ?? undefined,\n required: v.required,\n sensitive: v.sensitive,\n value: v.value ?? undefined,\n }]),\n );\n\n await runbookStore.update(tenantId, row.runbookId, {\n runbook: validated,\n variables: existingVariables,\n });\n\n return c.json({ success: true, runbookId: row.runbookId });\n } catch (error) {\n return c.json({\n error: `Failed to apply fix: ${error instanceof Error ? error.message : String(error)}`,\n }, 500);\n }\n });\n\n // POST /api/v1/jobs/:id/adopt — 生成結果を採用(developer 以上)\n app.post(\"/:id/adopt\", requireRole(\"developer\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (row.mode !== \"generate\") {\n return c.json({ error: \"Adopt is only available for generate jobs\" }, 400);\n }\n\n if (row.status !== \"completed\") {\n return c.json({ error: \"Job must be completed to adopt\" }, 400);\n }\n\n if (row.adoptedRunbookId) {\n return c.json({ error: \"Job has already been adopted\" }, 400);\n }\n\n if (!row.reviewResult?.yamlContent) {\n return c.json({ error: \"No generated content available\" }, 400);\n }\n\n // TODO: buildRunbookYaml() の結果を runbookStore に保存\n // 現時点ではスタブ — Inngest Function で yamlContent を reviewResult に保存済みの前提\n const runbook = await runbookStore.insertDraft({\n tenantId,\n createdBy: userId,\n title: row.reviewResult.summary ?? row.goal ?? \"Generated Runbook\",\n goal: row.goal ?? undefined,\n startUrl: row.startUrl ?? undefined,\n context: row.context ?? undefined,\n });\n\n await store.setAdoptedRunbook(id, runbook.id);\n\n return c.json({ runbookId: runbook.id }, 201);\n });\n\n // POST /api/v1/jobs/:id/retry — リトライ(generate 専用)\n app.post(\"/:id/retry\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (row.mode !== \"generate\") {\n return c.json({ error: \"Retry is only available for generate jobs\" }, 400);\n }\n\n if (!TERMINAL_STATUSES.has(row.status)) {\n return c.json({ error: \"Job must be in a terminal state to retry\" }, 400);\n }\n\n const body = await c.req.json().catch(() => ({}));\n\n // 元の generateConfig を引き継ぎ\n const gc = row.generateConfig;\n const generateConfig = gc ? {\n maxIterations: gc.maxIterations,\n stepDelay: gc.stepDelay,\n headless: gc.headless,\n snapshotFilter: gc.snapshotFilter,\n stallCheckInterval: gc.stallCheckInterval,\n historyWindow: gc.historyWindow,\n maxConsecutiveFailures: gc.maxConsecutiveFailures,\n screenshotDir: gc.screenshotDir ?? undefined,\n videoDir: gc.videoDir ?? undefined,\n stealth: gc.stealth,\n proxy: gc.proxy ?? undefined,\n modelId: gc.modelId ?? undefined,\n modelProvider: gc.modelProvider ?? undefined,\n skills: gc.skills ?? undefined,\n } : undefined;\n\n // 新しいジョブを作成(元のパラメータを引き継ぎ、context は上書き可)\n const newJob = await store.insert({\n tenantId,\n mode: \"generate\",\n runbookId: row.runbookId ?? undefined,\n purpose: row.purpose,\n createdBy: userId,\n startUrl: row.startUrl ?? undefined,\n goal: row.goal ?? undefined,\n context: body.context ?? row.context ?? undefined,\n variables: row.variables.map((v) => ({\n key: v.key,\n value: v.value,\n sensitive: v.sensitive,\n })),\n generateConfig,\n });\n\n try {\n await inngest.send({\n name: \"job/generate\",\n data: { jobId: newJob.id, tenantId },\n });\n } catch (err) {\n console.error(`[Inngest] Failed to send job/generate event for job ${newJob.id}:`, err);\n throw err;\n }\n\n return c.json({ id: newJob.id }, 201);\n });\n\n // DELETE /api/v1/jobs/:id — 破棄(admin 以上)\n app.delete(\"/:id\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n if (row.mode !== \"generate\" && row.mode !== \"self_heal\") {\n return c.json({ error: \"Delete is only available for generate or self_heal jobs\" }, 400);\n }\n\n if (!TERMINAL_STATUSES.has(row.status)) {\n return c.json({ error: \"Job must be in a terminal state to delete\" }, 400);\n }\n\n // アーティファクト削除(GCS + DB CASCADE)\n if (db) {\n const aDb = new ArtifactDBStore(db);\n const aStore: ArtifactStore = config?.gcsBucket\n ? new GCSArtifactStore(config.gcsBucket)\n : new LocalArtifactStore(\"/tmp/artifacts\");\n try {\n await aStore.deleteByJob(row.tenantId, id);\n } catch { /* GCS 削除失敗は許容 */ }\n }\n // jobs テーブルの CASCADE で関連テーブルも削除される\n await store.delete(id);\n\n return c.body(null, 204);\n });\n\n return app;\n}\n\n// ── ヘルパー関数 ──\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype HonoContext = any;\n\nfunction buildGenerateJobVariables(\n variables?: Record<string, string>,\n secrets?: Record<string, string>,\n): { key: string; value: string; sensitive: boolean }[] | undefined {\n const merged = new Map<string, { value: string; sensitive: boolean }>();\n\n for (const [key, value] of Object.entries(variables ?? {})) {\n merged.set(key, { value, sensitive: false });\n }\n\n for (const [key, value] of Object.entries(secrets ?? {})) {\n merged.set(key, { value, sensitive: true });\n }\n\n if (merged.size === 0) return undefined;\n\n return [...merged.entries()].map(([key, entry]) => ({\n key,\n value: entry.value,\n sensitive: entry.sensitive,\n }));\n}\n\nasync function createExecuteJob(\n c: HonoContext,\n store: JobStore,\n runbookStore: RunbookStore,\n inngest: Inngest,\n tenantId: string,\n userId: string | undefined,\n body: Record<string, unknown>,\n mode: \"execute\" | \"self_heal\",\n) {\n const { runbookId, variables, purpose } = body as {\n runbookId: string;\n variables?: Record<string, string>;\n purpose?: string;\n };\n\n if (!runbookId) {\n return c.json({ error: \"runbookId is required\" }, 400);\n }\n\n const rb = await runbookStore.findById(tenantId, runbookId);\n if (!rb) {\n return c.json({ error: \"Runbook not found\" }, 404);\n }\n if (rb.status !== \"active\") {\n return c.json(\n { error: \"Only active runbooks can create jobs\" },\n 400,\n );\n }\n\n // activeVersionId を解決して記録(実行中にバージョンが切り替わっても開始時点のバージョンで実行)\n const activeVersionId = rb.activeVersionId ?? rb.currentVersionId;\n\n const totalSteps = rb.steps.filter((s) => !s.parentStepId).length;\n\n const varsArray = variables\n ? Object.entries(variables).map(([key, value]) => {\n const varDef = rb.variables.find((v) => v.name === key);\n return { key, value, sensitive: varDef?.sensitive ?? false };\n })\n : undefined;\n\n // self_heal モードのデフォルト設定オーバーライド\n const isSelfHeal = mode === \"self_heal\";\n\n const job = await store.insert({\n tenantId,\n mode,\n runbookId,\n runbookVersionId: activeVersionId ?? undefined,\n totalSteps,\n purpose: (purpose as \"manual\" | \"api\") ?? \"manual\",\n createdBy: userId,\n variables: varsArray,\n executionConfig: buildExecutionConfig(rb.settings, { isSelfHeal }),\n });\n\n try {\n await inngest.send({\n name: \"job/execute\",\n data: { jobId: job.id, tenantId },\n });\n } catch (err) {\n console.error(`[Inngest] Failed to send job/execute event for job ${job.id}:`, err);\n throw err;\n }\n\n return c.json({ id: job.id }, 201);\n}\n\nasync function createGenerateJob(\n c: HonoContext,\n store: JobStore,\n runbookStore: RunbookStore,\n inngest: Inngest,\n tenantId: string,\n userId: string | undefined,\n body: Record<string, unknown>,\n) {\n const { runbookId, startUrl, goal, context, generateConfig, variables, secrets } = body as {\n runbookId?: string;\n startUrl?: string;\n goal?: string;\n context?: string;\n generateConfig?: Record<string, unknown>;\n variables?: Record<string, string>;\n secrets?: Record<string, string>;\n };\n\n const runbook = runbookId\n ? await runbookStore.findById(tenantId, runbookId)\n : null;\n\n if (runbookId && !runbook) {\n return c.json({ error: \"Runbook not found\" }, 404);\n }\n\n const resolvedStartUrl = startUrl ?? runbook?.startUrl ?? undefined;\n const resolvedGoal = goal ?? runbook?.goal ?? undefined;\n const resolvedContext = context ?? runbook?.context ?? undefined;\n\n if (!resolvedStartUrl) {\n return c.json({ error: \"startUrl is required for generate mode\" }, 400);\n }\n if (!resolvedGoal) {\n return c.json({ error: \"goal is required for generate mode\" }, 400);\n }\n if (!resolvedContext) {\n return c.json({ error: \"context is required for generate mode\" }, 400);\n }\n\n const job = await store.insert({\n tenantId,\n mode: \"generate\",\n runbookId,\n purpose: \"generation\",\n createdBy: userId,\n startUrl: resolvedStartUrl,\n goal: resolvedGoal,\n context: resolvedContext,\n variables: buildGenerateJobVariables(variables, secrets),\n generateConfig: generateConfig as import(\"../store/job-store.js\").JobGenerateConfig | undefined,\n });\n\n try {\n await inngest.send({\n name: \"job/generate\",\n data: { jobId: job.id, tenantId },\n });\n } catch (err) {\n console.error(`[Inngest] Failed to send job/generate event for job ${job.id}:`, err);\n throw err;\n }\n\n return c.json({ id: job.id }, 201);\n}\n","/**\n * SSE ストリームハンドラ\n *\n * Redis `job:{jobId}:events` を subscribe し、SSE レスポンスに変換する。\n * 初回接続時に DB から現在状態のスナップショットを送信する。\n */\n\nimport type { Context } from \"hono\";\nimport { and, eq } from \"drizzle-orm\";\nimport { createRedisSubscriber } from \"../redis.js\";\nimport { TERMINAL_STATUSES, TERMINAL_EVENT_TYPES } from \"./types.js\";\nimport type { SSEEvent } from \"./types.js\";\nimport type { JobStore } from \"../store/job-store.js\";\nimport { jobApprovalRequests } from \"../db/schema.js\";\nimport type { getDb } from \"../db/client.js\";\n\nconst KEEPALIVE_INTERVAL_MS = 30_000;\n\n/**\n * SSE ストリームを開始し、Redis Pub/Sub からイベントを配信する。\n *\n * @param c - Hono コンテキスト\n * @param jobStore - ジョブストア\n * @param tenantId - テナントID\n * @param jobId - ジョブID\n * @param redisUrl - Redis URL\n */\nexport function handleJobStream(\n c: Context,\n jobStore: JobStore,\n tenantId: string,\n jobId: string,\n redisUrl: string,\n db?: ReturnType<typeof getDb>,\n): Response {\n const channel = `job:${jobId}:events`;\n\n const stream = new ReadableStream({\n async start(controller) {\n const encoder = new TextEncoder();\n\n function send(event: SSEEvent): void {\n try {\n const data = JSON.stringify(event);\n controller.enqueue(encoder.encode(`data: ${data}\\n\\n`));\n } catch {\n // ストリーム閉鎖済みの場合は無視\n }\n }\n\n // 初回: DB から現在状態のスナップショットを送信\n try {\n const job = await jobStore.findById(tenantId, jobId);\n if (job) {\n // pendingApproval 情報を取得(waiting_approval 状態のみ)\n let pendingApproval: { stepOrdinal: number; description: string; riskLevel: string } | null = null;\n if (db && job.status === \"waiting_approval\") {\n try {\n const req = await db.query.jobApprovalRequests.findFirst({\n where: and(\n eq(jobApprovalRequests.jobId, jobId),\n eq(jobApprovalRequests.status, \"pending\"),\n ),\n });\n if (req) {\n pendingApproval = {\n stepOrdinal: req.stepOrdinal,\n description: req.stepDescription ?? \"\",\n riskLevel: req.riskLevel ?? \"low\",\n };\n }\n } catch { /* DB エラーは無視 */ }\n }\n\n send({\n type: \"snapshot\",\n timestamp: new Date().toISOString(),\n data: {\n status: job.status,\n mode: job.mode,\n currentStep: job.currentStep,\n totalSteps: job.totalSteps,\n startedAt: job.startedAt?.toISOString() ?? null,\n completedAt: job.completedAt?.toISOString() ?? null,\n errorMessage: job.errorMessage ?? null,\n results: job.results.map((r) => ({\n ordinal: r.ordinal,\n description: r.description,\n status: r.status,\n durationMs: r.durationMs,\n actionType: r.actionType ?? null,\n })),\n ...(pendingApproval ? { pendingApproval } : {}),\n },\n });\n\n // 既に終端ステータスなら snapshot のみ送って close\n if (TERMINAL_STATUSES.has(job.status)) {\n controller.close();\n return;\n }\n }\n } catch {\n // DB エラーは snapshot 欠落として許容\n }\n\n // Redis subscribe\n let subscriber: ReturnType<typeof createRedisSubscriber> | null = null;\n let keepaliveTimer: ReturnType<typeof setInterval> | null = null;\n let closed = false;\n\n const cleanup = () => {\n if (closed) return;\n closed = true;\n if (keepaliveTimer) clearInterval(keepaliveTimer);\n if (subscriber) {\n subscriber.unsubscribe(channel).catch(() => {});\n subscriber.quit().catch(() => {});\n subscriber = null;\n }\n try { controller.close(); } catch { /* already closed */ }\n };\n\n try {\n subscriber = createRedisSubscriber(redisUrl);\n await subscriber.subscribe(channel);\n\n subscriber.on(\"message\", (_ch: string, message: string) => {\n if (closed) return;\n try {\n const event = JSON.parse(message) as SSEEvent;\n send(event);\n\n // 終端イベントでストリームを閉じる\n if (TERMINAL_EVENT_TYPES.has(event.type)) {\n cleanup();\n }\n } catch {\n // JSON パースエラーは無視\n }\n });\n\n subscriber.on(\"error\", () => {\n cleanup();\n });\n\n // Keepalive\n keepaliveTimer = setInterval(() => {\n if (closed) return;\n try {\n controller.enqueue(encoder.encode(\": keepalive\\n\\n\"));\n } catch {\n cleanup();\n }\n }, KEEPALIVE_INTERVAL_MS);\n } catch {\n cleanup();\n }\n },\n });\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"X-Accel-Buffering\": \"no\",\n },\n });\n}\n","/**\n * SSE イベント型定義\n *\n * Redis Pub/Sub → SSE 変換で使用する共通型。\n */\n\nexport type SSEEventType =\n | \"snapshot\"\n | \"status_change\"\n | \"step_start\"\n | \"step_complete\"\n | \"step_failed\"\n | \"waiting_approval\"\n | \"approval_result\"\n | \"screenshot\"\n | \"paused\"\n | \"resumed\"\n | \"guidance_received\"\n | \"progress\"\n | \"explorer_step\"\n | \"review_start\"\n | \"metrics_update\"\n | \"completed\"\n | \"failed\"\n | \"error\";\n\nexport interface SSEEvent {\n type: SSEEventType;\n timestamp: string;\n data: Record<string, unknown>;\n}\n\n/** ジョブの終端ステータス */\nexport const TERMINAL_STATUSES = new Set([\n \"completed\",\n \"failed\",\n \"cancelled\",\n]);\n\n/** 承認待ちイベントのペイロード */\nexport interface PendingApproval {\n stepOrdinal: number;\n description: string;\n riskLevel: string;\n}\n\n/** SSE イベントタイプのうち、ストリーム終了を意味するもの */\nexport const TERMINAL_EVENT_TYPES = new Set<SSEEventType>([\n \"completed\",\n \"failed\",\n]);\n","/**\n * PgMeteringCollector — PostgreSQL ベースのメータリング永続化\n *\n * UPSERT ベースの月間使用量追跡。\n */\n\nimport { eq, and, sql } from \"drizzle-orm\";\nimport type { getDb } from \"../db/client.js\";\nimport { tenantUsage } from \"../db/schema.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\n/** 現在の月文字列を取得(\"2026-03\" 形式) */\nfunction getCurrentMonth(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, \"0\");\n return `${year}-${month}`;\n}\n\nexport class MeteringStore {\n constructor(private db: Db) {}\n\n /**\n * ジョブ実行を記録(ジョブ数 +1、ステップ数 +N)\n */\n async recordJobExecution(\n tenantId: string,\n stepCount: number,\n ): Promise<void> {\n const month = getCurrentMonth();\n\n await this.db\n .insert(tenantUsage)\n .values({\n tenantId,\n month,\n jobCount: 1,\n stepCount,\n })\n .onConflictDoUpdate({\n target: [tenantUsage.tenantId, tenantUsage.month],\n set: {\n jobCount: sql`${tenantUsage.jobCount} + 1`,\n stepCount: sql`${tenantUsage.stepCount} + ${stepCount}`,\n updatedAt: new Date(),\n },\n });\n }\n\n /**\n * ステップ実行を記録(ステップ数のみ +N)\n */\n async recordStepExecution(\n tenantId: string,\n stepCount: number,\n ): Promise<void> {\n const month = getCurrentMonth();\n\n await this.db\n .insert(tenantUsage)\n .values({\n tenantId,\n month,\n jobCount: 0,\n stepCount,\n })\n .onConflictDoUpdate({\n target: [tenantUsage.tenantId, tenantUsage.month],\n set: {\n stepCount: sql`${tenantUsage.stepCount} + ${stepCount}`,\n updatedAt: new Date(),\n },\n });\n }\n\n /**\n * 当月の使用量を取得\n */\n async getCurrentUsage(\n tenantId: string,\n ): Promise<{ jobCount: number; stepCount: number; month: string }> {\n const month = getCurrentMonth();\n\n const [row] = await this.db\n .select({\n jobCount: tenantUsage.jobCount,\n stepCount: tenantUsage.stepCount,\n })\n .from(tenantUsage)\n .where(\n and(\n eq(tenantUsage.tenantId, tenantId),\n eq(tenantUsage.month, month),\n ),\n )\n .limit(1);\n\n return {\n jobCount: row?.jobCount ?? 0,\n stepCount: row?.stepCount ?? 0,\n month,\n };\n }\n}\n","/**\n * handlers/artifacts --- アーティファクト API ハンドラ\n *\n * GET /api/v1/jobs/:jobId/artifacts — 一覧取得\n * GET /api/v1/jobs/:jobId/artifacts/:id/url — Signed URL 取得\n */\n\nimport { Hono } from \"hono\";\nimport type { AppVariables } from \"../middleware/types.js\";\nimport type { ArtifactDBStore } from \"../store/artifact-store.js\";\nimport type { ArtifactStore, ArtifactType } from \"../../storage/types.js\";\n\nconst validTypes = new Set<ArtifactType>([\"screenshot\", \"video\", \"download\", \"export\"]);\n\nexport function createArtifactHandlers(\n artifactDb: ArtifactDBStore,\n artifactStore: ArtifactStore,\n) {\n const app = new Hono<{ Variables: AppVariables }>();\n\n // GET /api/v1/jobs/:jobId/artifacts?type=screenshot\n app.get(\"/\", async (c) => {\n const tenantId = c.get(\"tenantId\") as string;\n const jobId = c.req.param(\"jobId\") as string;\n const typeParam = c.req.query(\"type\");\n\n let type: ArtifactType | undefined;\n if (typeParam) {\n if (!validTypes.has(typeParam as ArtifactType)) {\n return c.json({ error: `Invalid type: ${typeParam}` }, 400);\n }\n type = typeParam as ArtifactType;\n }\n\n const items = await artifactDb.listByJob(tenantId, jobId, type);\n return c.json({\n items: items.map((item) => ({\n id: item.id,\n type: item.type,\n filename: item.filename,\n contentType: item.contentType,\n sizeBytes: item.sizeBytes,\n stepOrdinal: item.stepOrdinal,\n createdAt: item.createdAt.toISOString(),\n })),\n });\n });\n\n // GET /api/v1/jobs/:jobId/artifacts/:artifactId/url\n app.get(\"/:artifactId/url\", async (c) => {\n const tenantId = c.get(\"tenantId\") as string;\n const jobId = c.req.param(\"jobId\") as string;\n const artifactId = c.req.param(\"artifactId\") as string;\n\n const artifact = await artifactDb.findById(tenantId, artifactId);\n if (!artifact) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n const url = await artifactStore.getSignedUrl(artifact.storagePath, 3600);\n // ローカル開発では file:// URL をブラウザが読めないため API 経由で配信\n if (url.startsWith(\"file://\")) {\n return c.json({\n url: `/api/v1/jobs/${jobId}/artifacts/${artifactId}/content`,\n expiresIn: 3600,\n });\n }\n return c.json({ url, expiresIn: 3600 });\n });\n\n // GET /api/v1/jobs/:jobId/artifacts/:artifactId/content\n app.get(\"/:artifactId/content\", async (c) => {\n const tenantId = c.get(\"tenantId\") as string;\n const artifactId = c.req.param(\"artifactId\") as string;\n\n const artifact = await artifactDb.findById(tenantId, artifactId);\n if (!artifact) {\n return c.notFound();\n }\n\n const data = await artifactStore.getContent(artifact.storagePath);\n return new Response(new Uint8Array(data), {\n headers: {\n \"Content-Type\": artifact.contentType,\n \"Cache-Control\": \"private, max-age=3600\",\n },\n });\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport { eq, and, isNull, count } from \"drizzle-orm\";\nimport type { ScheduleStore, ScheduleType, SchedulePurpose } from \"../store/schedule-store.js\";\nimport type { JobStore } from \"../store/job-store.js\";\nimport type { AppVariables } from \"../middleware/types.js\";\nimport { requireRole } from \"../middleware/rbac.js\";\nimport { requirePlanFeature } from \"../middleware/plan-gate.js\";\nimport { tfWithLocale, resolveAcceptLanguage, type Locale } from \"../../i18n/index.js\";\nimport { isValidCron } from \"../utils/cron.js\";\nimport { buildExecutionConfig } from \"../helpers/execution-config-builder.js\";\nimport { runbooks, runbookVersions, runbookSettings, runbookVariables, runbookSteps } from \"../db/schema.js\";\nimport type { getDb } from \"../db/client.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\nexport function createScheduleHandlers(store: ScheduleStore, jobStore: JobStore, db: Db) {\n const app = new Hono<{ Variables: AppVariables }>();\n\n function reqLocale(c: { req: { header: (name: string) => string | undefined } }): Locale {\n return resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n }\n\n // POST /api/v1/schedules(admin 以上、Team+)\n app.post(\"/\", requireRole(\"admin\"), requirePlanFeature(\"scheduling\", \"Team\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const userId = c.get(\"user\")?.id;\n const body = await c.req.json<{\n runbookId: string;\n type?: ScheduleType;\n cron?: string;\n timezone?: string;\n scheduledAt?: string;\n purpose?: SchedulePurpose;\n enabled?: boolean;\n }>();\n\n if (!body.runbookId) {\n return c.json({ error: \"runbookId is required\" }, 400);\n }\n\n const type = body.type ?? \"recurring\";\n\n // recurring は cron 必須\n if (type === \"recurring\") {\n if (!body.cron) {\n return c.json({ error: \"cron is required for recurring schedules\" }, 400);\n }\n if (!isValidCron(body.cron)) {\n return c.json({ error: \"Invalid cron expression\" }, 400);\n }\n }\n\n // once は scheduledAt 必須(未来の日時のみ)\n if (type === \"once\") {\n if (!body.scheduledAt) {\n return c.json({ error: \"scheduledAt is required for one-time schedules\" }, 400);\n }\n const scheduledDate = new Date(body.scheduledAt);\n if (isNaN(scheduledDate.getTime())) {\n return c.json({ error: \"Invalid scheduledAt date\" }, 400);\n }\n if (scheduledDate <= new Date()) {\n return c.json({ error: tfWithLocale(\"serverErrors.scheduledAtMustBeFuture\", reqLocale(c), {}) }, 400);\n }\n }\n\n const row = await store.insert({\n tenantId,\n runbookId: body.runbookId,\n type,\n cron: body.cron,\n timezone: body.timezone,\n scheduledAt: body.scheduledAt ? new Date(body.scheduledAt) : undefined,\n purpose: body.purpose,\n enabled: body.enabled,\n createdBy: userId,\n });\n\n // once スケジュール作成時にジョブレコードも同時作成(scheduled ステータス)\n let jobId: string | undefined;\n if (type === \"once\") {\n const isSelfHeal = (body.purpose ?? \"execute\") === \"self_heal\";\n const mode = isSelfHeal ? \"self_heal\" : \"execute\";\n\n // activeVersionId を解決\n const [rb] = await db\n .select({ activeVersionId: runbooks.activeVersionId })\n .from(runbooks)\n .where(eq(runbooks.id, body.runbookId))\n .limit(1);\n const activeVersionId = rb?.activeVersionId;\n if (!activeVersionId) {\n return c.json({ error: \"Runbook has no active version\" }, 400);\n }\n\n // runbookSettings + totalSteps + storedVars を並列ロード(versionId ベース)\n const [rbSettings, stepCountResult, rbVars] = await Promise.all([\n db.query.runbookSettings.findFirst({\n where: eq(runbookSettings.versionId, activeVersionId),\n }),\n db.select({ cnt: count() })\n .from(runbookSteps)\n .where(and(eq(runbookSteps.versionId, activeVersionId), isNull(runbookSteps.parentStepId))),\n db.select({ name: runbookVariables.name, value: runbookVariables.value, sensitive: runbookVariables.sensitive })\n .from(runbookVariables)\n .where(eq(runbookVariables.versionId, activeVersionId)),\n ]);\n\n const totalSteps = stepCountResult[0]?.cnt ?? 0;\n const storedVars = rbVars\n .filter((v) => v.value != null)\n .map((v) => ({ key: v.name, value: v.value!, sensitive: v.sensitive }));\n\n const job = await jobStore.insert({\n tenantId,\n mode,\n status: \"scheduled\",\n runbookId: body.runbookId,\n runbookVersionId: activeVersionId,\n totalSteps,\n purpose: \"scheduled\",\n createdBy: userId,\n scheduledAt: new Date(body.scheduledAt!),\n scheduleId: row.id,\n variables: storedVars.length > 0 ? storedVars : undefined,\n executionConfig: buildExecutionConfig(rbSettings, { isSelfHeal }),\n });\n jobId = job.id;\n }\n\n return c.json({ ...row, jobId }, 201);\n });\n\n // GET /api/v1/schedules\n app.get(\"/\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const runbookId = c.req.query(\"runbookId\");\n const enabledParam = c.req.query(\"enabled\");\n const purposeParam = c.req.query(\"purpose\") as SchedulePurpose | undefined;\n const limit = Number(c.req.query(\"limit\") ?? \"50\");\n const offset = Number(c.req.query(\"offset\") ?? \"0\");\n\n let enabled: boolean | undefined;\n if (enabledParam === \"true\") enabled = true;\n else if (enabledParam === \"false\") enabled = false;\n\n const result = await store.list(tenantId, {\n runbookId,\n enabled,\n purpose: purposeParam,\n limit,\n offset,\n });\n return c.json(result);\n });\n\n // GET /api/v1/schedules/:id\n app.get(\"/:id\", async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n const row = await store.findById(tenantId, id);\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n return c.json(row);\n });\n\n // PUT /api/v1/schedules/:id(admin 以上、Team+)\n app.put(\"/:id\", requireRole(\"admin\"), requirePlanFeature(\"scheduling\", \"Team\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n const body = await c.req.json<{\n cron?: string;\n timezone?: string;\n scheduledAt?: string;\n enabled?: boolean;\n }>();\n\n if (body.cron !== undefined && !isValidCron(body.cron)) {\n return c.json({ error: \"Invalid cron expression\" }, 400);\n }\n\n const row = await store.update(tenantId, id, {\n cron: body.cron,\n timezone: body.timezone,\n scheduledAt: body.scheduledAt ? new Date(body.scheduledAt) : undefined,\n enabled: body.enabled,\n });\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n return c.json(row);\n });\n\n // DELETE /api/v1/schedules/:id(admin 以上)\n app.delete(\"/:id\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\")!;\n const id = c.req.param(\"id\");\n\n // 関連する scheduled ジョブをキャンセル\n const scheduledJob = await jobStore.findScheduledByScheduleId(id);\n if (scheduledJob) {\n await jobStore.updateStatus(scheduledJob.id, \"cancelled\", {\n completedAt: new Date(),\n });\n }\n\n const deleted = await store.delete(tenantId, id);\n if (!deleted) {\n return c.json({ error: \"Not found\" }, 404);\n }\n return c.json({ ok: true });\n });\n\n return app;\n}\n","/**\n * API キー管理ハンドラー\n *\n * POST /api/v1/api-keys — キー生成(セッション認証のみ)\n * GET /api/v1/api-keys — キー一覧\n * DELETE /api/v1/api-keys/:id — キー失効(soft delete)\n */\n\nimport { Hono } from \"hono\";\nimport { createHash } from \"node:crypto\";\nimport { eq, and, isNull } from \"drizzle-orm\";\nimport type { getDb } from \"../db/client.js\";\nimport { apiKeys, tenants } from \"../db/schema.js\";\nimport { generateOpaqueApiKey } from \"../../plan/keygen.js\";\nimport type { AppVariables } from \"../middleware/types.js\";\nimport { requireRole } from \"../middleware/rbac.js\";\nimport { tWithLocale, resolveAcceptLanguage } from \"../../i18n/index.js\";\n\n/** SHA-256 ハッシュ */\nexport function hashApiKey(key: string): string {\n return createHash(\"sha256\").update(key).digest(\"hex\");\n}\n\nexport function apiKeysRoutes(db: ReturnType<typeof getDb>) {\n const app = new Hono<{ Variables: AppVariables }>();\n\n // POST / — キー生成(admin 以上 + セッション認証必須)\n app.post(\"/\", requireRole(\"admin\", { rejectApiKey: true }), async (c) => {\n const user = c.get(\"user\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!user) {\n return c.json({ error: tWithLocale(\"serverErrors.sessionRequired\", locale) }, 401);\n }\n\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 400);\n }\n\n const body = await c.req.json<{ name?: string }>();\n const name = body.name?.trim();\n if (!name) {\n return c.json({ error: tWithLocale(\"serverErrors.nameRequired\", locale) }, 400);\n }\n\n // テナントの tier を DB から取得\n const [tenant] = await db\n .select({ tier: tenants.tier })\n .from(tenants)\n .where(eq(tenants.id, tenantId))\n .limit(1);\n\n if (!tenant) {\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 404);\n }\n\n const tier = tenant.tier;\n if (tier === \"community\") {\n return c.json(\n { error: tWithLocale(\"serverErrors.communityNoApiKey\", locale) },\n 400,\n );\n }\n\n const generated = generateOpaqueApiKey({ tenantId });\n\n const [inserted] = await db\n .insert(apiKeys)\n .values({\n tenantId,\n createdBy: user.id,\n name,\n keyHash: generated.keyHash,\n keyPrefix: generated.keyPrefix,\n })\n .returning();\n\n return c.json(\n {\n id: inserted.id,\n name: inserted.name,\n tier,\n keyPrefix: inserted.keyPrefix,\n createdAt: inserted.createdAt.toISOString(),\n // フルキーは作成時のみ返却\n key: generated.key,\n },\n 201,\n );\n });\n\n // GET / — キー一覧(admin 以上)\n app.get(\"/\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 400);\n }\n\n const includeRevoked = c.req.query(\"include_revoked\") === \"true\";\n\n const conditions = includeRevoked\n ? [eq(apiKeys.tenantId, tenantId)]\n : [eq(apiKeys.tenantId, tenantId), isNull(apiKeys.revokedAt)];\n\n const keys = await db\n .select({\n id: apiKeys.id,\n name: apiKeys.name,\n tier: tenants.tier,\n keyPrefix: apiKeys.keyPrefix,\n createdAt: apiKeys.createdAt,\n revokedAt: apiKeys.revokedAt,\n lastUsedAt: apiKeys.lastUsedAt,\n createdBy: apiKeys.createdBy,\n })\n .from(apiKeys)\n .innerJoin(tenants, eq(apiKeys.tenantId, tenants.id))\n .where(and(...conditions));\n\n return c.json(\n keys.map((k) => ({\n ...k,\n createdAt: k.createdAt.toISOString(),\n revokedAt: k.revokedAt?.toISOString() ?? null,\n lastUsedAt: k.lastUsedAt?.toISOString() ?? null,\n })),\n );\n });\n\n // DELETE /:id — キー失効(admin 以上)\n app.delete(\"/:id\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 400);\n }\n\n const id = c.req.param(\"id\");\n\n const [updated] = await db\n .update(apiKeys)\n .set({ revokedAt: new Date() })\n .where(\n and(\n eq(apiKeys.id, id),\n eq(apiKeys.tenantId, tenantId),\n isNull(apiKeys.revokedAt),\n ),\n )\n .returning({ id: apiKeys.id });\n\n if (!updated) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.apiKeyNotFoundOrRevoked\", locale) }, 404);\n }\n\n return c.body(null, 204);\n });\n\n return app;\n}\n","/**\n * plan/keygen --- API キー生成(opaque トークン)\n *\n * API キー形式: rfn_<random32chars>(crypto.randomBytes(24).toString('base64url')、192bit)\n * メタ情報は全て DB サーバー側に保持し、キーに一切含まない。\n */\n\nimport { randomBytes, createHash } from \"node:crypto\";\n\n// ── 定数 ──\n\n/** Opaque API キーのプレフィックス */\nconst KEY_PREFIX = \"rfn_\";\n\n/** ランダム部分のバイト数(192bit = 24 bytes → base64url で 32 chars) */\nconst RANDOM_BYTES = 24;\n\n// ── 型定義 ──\n\nexport interface GenerateKeyOptions {\n /** テナント ID(必須) */\n tenantId: string;\n}\n\nexport interface GeneratedKey {\n /** 生成された API キー文字列(rfn_xxx 形式) */\n key: string;\n /** テナント ID */\n tenantId: string;\n /** 生成日時(ISO 8601) */\n createdAt: string;\n /** SHA-256 ハッシュ(DB 保存用) */\n keyHash: string;\n /** プレフィックス(表示用、先頭 12 文字: \"rfn_xxxxxxxx\") */\n keyPrefix: string;\n}\n\n// ── 生成 ──\n\n/**\n * opaque API キーを生成する。\n *\n * @param options - 生成オプション(tenantId 必須)\n * @returns 生成結果(フルキー + ハッシュ + プレフィックス)\n */\nexport function generateOpaqueApiKey(options: GenerateKeyOptions): GeneratedKey {\n if (!options.tenantId) {\n throw new Error(\"tenantId is required\");\n }\n\n const random = randomBytes(RANDOM_BYTES).toString(\"base64url\");\n const key = `${KEY_PREFIX}${random}`;\n const keyHash = createHash(\"sha256\").update(key).digest(\"hex\");\n const keyPrefix = key.slice(0, 12); // \"rfn_xxxxxxxx\"\n\n return {\n key,\n tenantId: options.tenantId,\n createdAt: new Date().toISOString(),\n keyHash,\n keyPrefix,\n };\n}\n","/**\n * GET /api/public/validate-key — opaque キーバリデーション\n *\n * 認証不要(キー自体がクレデンシャル)。\n * Authorization: Bearer rfn_xxx → 200: { valid, tier, tenantId, limits, features, expiresAt }\n * デバッグトークン(rfnd-xxx)は拒否。\n */\n\nimport { Hono } from \"hono\";\nimport { createHash } from \"node:crypto\";\nimport { eq, isNull } from \"drizzle-orm\";\nimport type { getDb } from \"../db/client.js\";\nimport { apiKeys, tenants } from \"../db/schema.js\";\nimport { detectKeyKind } from \"../../plan/key-kind.js\";\nimport { resolvePlanFromTier, type PlanTier } from \"../../plan/index.js\";\n\n/** デフォルト TTL: 24 時間 */\nconst DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;\n\nexport function validateKeyRoute(db: ReturnType<typeof getDb>) {\n const app = new Hono();\n\n app.get(\"/\", async (c) => {\n const authHeader = c.req.header(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n return c.json({ valid: false, error: \"Missing Authorization header\" }, 401);\n }\n\n const apiKey = authHeader.slice(\"Bearer \".length);\n const kind = detectKeyKind(apiKey);\n\n // デバッグトークンはサーバーで拒否\n if (kind === \"debug\") {\n return c.json({ valid: false, error: \"Debug tokens are not accepted by the server\" }, 401);\n }\n\n if (kind !== \"opaque\") {\n return c.json({ valid: false, error: \"Invalid API key format\" }, 401);\n }\n\n // SHA-256 ハッシュで DB lookup\n const keyHash = createHash(\"sha256\").update(apiKey).digest(\"hex\");\n const [dbKey] = await db\n .select({\n id: apiKeys.id,\n tenantId: apiKeys.tenantId,\n revokedAt: apiKeys.revokedAt,\n })\n .from(apiKeys)\n .where(eq(apiKeys.keyHash, keyHash))\n .limit(1);\n\n if (!dbKey) {\n return c.json({ valid: false, error: \"API key not found\" }, 401);\n }\n\n if (dbKey.revokedAt) {\n return c.json({ valid: false, error: \"API key has been revoked\" }, 401);\n }\n\n // テナントの tier を取得\n const [tenant] = await db\n .select({ tier: tenants.tier })\n .from(tenants)\n .where(eq(tenants.id, dbKey.tenantId))\n .limit(1);\n\n if (!tenant) {\n return c.json({ valid: false, error: \"Tenant not found\" }, 401);\n }\n\n const plan = resolvePlanFromTier(tenant.tier as PlanTier, dbKey.tenantId);\n\n // lastUsedAt 更新(fire-and-forget)\n db.update(apiKeys)\n .set({ lastUsedAt: new Date() })\n .where(eq(apiKeys.id, dbKey.id))\n .then(() => {})\n .catch(() => {});\n\n return c.json({\n valid: true,\n tier: plan.tier,\n tenantId: plan.tenantId,\n limits: plan.limits,\n features: plan.features,\n expiresAt: new Date(Date.now() + DEFAULT_TTL_MS).toISOString(),\n });\n });\n\n return app;\n}\n","/**\n * テナント管理ハンドラー\n *\n * GET /api/v1/tenants — 所属テナント一覧\n * POST /api/v1/tenants/switch — アクティブテナント切替\n * GET /api/v1/tenants/me — テナント情報\n * PATCH /api/v1/tenants/me — テナント名/slug 更新\n * GET /api/v1/tenants/me/members — メンバー一覧\n * POST /api/v1/tenants/me/members — メンバー招待(既存/新規共通)\n * PATCH /api/v1/tenants/me/members/:id — ロール変更\n * DELETE /api/v1/tenants/me/members/:id — メンバー削除\n * GET /api/v1/tenants/me/invitations — 招待一覧\n * DELETE /api/v1/tenants/me/invitations/:id — 招待キャンセル\n * POST /api/v1/tenants/me/invitations/:id/resend — 招待再送信\n * GET /api/v1/tenants/my-invitations — ユーザーの pending 招待一覧\n * POST /api/v1/tenants/my-invitations/:id/accept — 招待受諾\n * POST /api/v1/tenants/my-invitations/:id/decline — 招待辞退\n */\n\nimport { Hono } from \"hono\";\nimport { setCookie } from \"hono/cookie\";\nimport { eq, and, ne, gt } from \"drizzle-orm\";\nimport { randomUUID } from \"node:crypto\";\nimport type { getDb } from \"../db/client.js\";\nimport { tenants, tenantMembers, user, invitations } from \"../db/schema.js\";\nimport type { ServerConfig } from \"../config.js\";\nimport { createEmailSender, buildInvitationEmailHtml, emailString, type EmailLocale } from \"../auth/email.js\";\nimport type { AppVariables, MemberRole } from \"../middleware/types.js\";\nimport { isAdminOrOwner } from \"../middleware/rbac.js\";\nimport { tWithLocale, tfWithLocale, resolveAcceptLanguage } from \"../../i18n/index.js\";\n\nconst VALID_ROLES = new Set<string>([\"owner\", \"admin\", \"developer\", \"member\"]);\n\n/** slug バリデーション: 小文字英数字+ハイフン、3〜48文字、user- プレフィックス禁止 */\nconst SLUG_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;\n\nfunction validateSlug(slug: string, locale: import(\"../../i18n/types.js\").Locale): { valid: false; reason: string } | { valid: true } {\n if (slug.length < 3 || slug.length > 48) {\n return { valid: false, reason: tWithLocale(\"tenant.slugLength\", locale) };\n }\n if (!SLUG_PATTERN.test(slug)) {\n return { valid: false, reason: tWithLocale(\"tenant.slugPattern\", locale) };\n }\n if (slug.startsWith(\"u-\")) {\n return { valid: false, reason: tWithLocale(\"tenant.slugReserved\", locale) };\n }\n return { valid: true };\n}\n\n/** 招待有効期限: 7日 */\nconst INVITATION_EXPIRY_DAYS = 7;\n\nfunction createInvitationToken(): string {\n return randomUUID();\n}\n\nexport function tenantsRoutes(db: ReturnType<typeof getDb>, config: ServerConfig) {\n const sendEmail = createEmailSender(config);\n const app = new Hono<{ Variables: AppVariables }>();\n\n // GET / — 所属テナント一覧\n app.get(\"/\", async (c) => {\n const currentUser = c.get(\"user\");\n if (!currentUser) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const rows = await db\n .select({\n id: tenants.id,\n name: tenants.name,\n slug: tenants.slug,\n tier: tenants.tier,\n locale: tenants.locale,\n role: tenantMembers.role,\n createdAt: tenants.createdAt,\n })\n .from(tenantMembers)\n .innerJoin(tenants, eq(tenantMembers.tenantId, tenants.id))\n .where(eq(tenantMembers.userId, currentUser.id));\n\n return c.json(\n rows.map((r) => ({\n id: r.id,\n name: r.name,\n slug: r.slug,\n tier: r.tier,\n locale: r.locale,\n role: r.role,\n createdAt: r.createdAt.toISOString(),\n })),\n );\n });\n\n // POST /switch — アクティブテナント切替\n app.post(\"/switch\", async (c) => {\n const currentUser = c.get(\"user\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser) return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n\n const { tenantId } = await c.req.json<{ tenantId: string }>();\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantIdRequired\", locale) }, 400);\n\n // メンバーシップ検証\n const [membership] = await db\n .select({ tenantId: tenantMembers.tenantId })\n .from(tenantMembers)\n .where(\n and(\n eq(tenantMembers.tenantId, tenantId),\n eq(tenantMembers.userId, currentUser.id),\n ),\n )\n .limit(1);\n\n if (!membership) return c.json({ error: tWithLocale(\"serverErrors.notMember\", locale) }, 403);\n\n setCookie(c, \"active-tenant-id\", tenantId, {\n path: \"/\",\n httpOnly: true,\n sameSite: \"Lax\",\n secure: config.nodeEnv === \"production\",\n maxAge: 60 * 60 * 24 * 365,\n });\n\n return c.json({ ok: true, tenantId });\n });\n\n // GET /me — テナント情報\n app.get(\"/me\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 404);\n }\n\n const [tenant] = await db\n .select()\n .from(tenants)\n .where(eq(tenants.id, tenantId))\n .limit(1);\n\n if (!tenant) {\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 404);\n }\n\n return c.json({\n id: tenant.id,\n name: tenant.name,\n slug: tenant.slug,\n tier: tenant.tier,\n locale: tenant.locale,\n createdAt: tenant.createdAt.toISOString(),\n updatedAt: tenant.updatedAt.toISOString(),\n onboardingCompletedAt: tenant.onboardingCompletedAt?.toISOString() ?? null,\n });\n });\n\n // PATCH /me — テナント名/slug/locale 更新\n app.patch(\"/me\", async (c) => {\n const currentUser = c.get(\"user\");\n const tenantId = c.get(\"tenantId\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser || !tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const role = c.get(\"memberRole\");\n if (!isAdminOrOwner(role)) {\n return c.json({ error: tWithLocale(\"serverErrors.adminRequired\", locale) }, 403);\n }\n\n const body = await c.req.json<{ name?: string; slug?: string; locale?: string; completeOnboarding?: boolean }>();\n const updates: Partial<typeof tenants.$inferInsert> = {};\n if (body.completeOnboarding) {\n updates.onboardingCompletedAt = new Date();\n }\n if (body.name?.trim()) updates.name = body.name.trim();\n if (body.locale) {\n if (body.locale !== \"en\" && body.locale !== \"ja\") {\n return c.json({ error: tWithLocale(\"serverErrors.invalidLocale\", locale) }, 400);\n }\n updates.locale = body.locale;\n }\n if (body.slug?.trim()) {\n const slug = body.slug.trim();\n const validation = validateSlug(slug, locale);\n if (!validation.valid) {\n return c.json({ error: validation.reason }, 400);\n }\n // 一意性チェック(自テナント以外)\n const [existing] = await db\n .select({ id: tenants.id })\n .from(tenants)\n .where(and(eq(tenants.slug, slug), ne(tenants.id, tenantId)))\n .limit(1);\n if (existing) {\n return c.json({ error: tWithLocale(\"tenant.slugTaken\", locale) }, 409);\n }\n updates.slug = slug;\n }\n\n if (Object.keys(updates).length === 0) {\n return c.json({ error: tWithLocale(\"serverErrors.noFieldsToUpdate\", locale) }, 400);\n }\n\n const [updated] = await db\n .update(tenants)\n .set(updates)\n .where(eq(tenants.id, tenantId))\n .returning();\n\n return c.json({\n id: updated.id,\n name: updated.name,\n slug: updated.slug,\n tier: updated.tier,\n locale: updated.locale,\n createdAt: updated.createdAt.toISOString(),\n updatedAt: updated.updatedAt.toISOString(),\n onboardingCompletedAt: updated.onboardingCompletedAt?.toISOString() ?? null,\n });\n });\n\n // GET /me/slug-available — slug の一意性チェック\n app.get(\"/me/slug-available\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 404);\n }\n\n const slug = c.req.query(\"slug\");\n if (!slug) {\n return c.json({ error: \"slug query parameter is required\" }, 400);\n }\n\n const validation = validateSlug(slug, locale);\n if (!validation.valid) {\n return c.json({ available: false, reason: validation.reason });\n }\n\n const [existing] = await db\n .select({ id: tenants.id })\n .from(tenants)\n .where(and(eq(tenants.slug, slug), ne(tenants.id, tenantId)))\n .limit(1);\n\n if (existing) {\n return c.json({ available: false, reason: tWithLocale(\"tenant.slugTaken\", locale) });\n }\n\n return c.json({ available: true });\n });\n\n // GET /me/members — メンバー一覧\n app.get(\"/me/members\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 404);\n }\n\n const members = await db\n .select({\n id: tenantMembers.id,\n userId: tenantMembers.userId,\n role: tenantMembers.role,\n createdAt: tenantMembers.createdAt,\n userName: user.name,\n userEmail: user.email,\n userImage: user.image,\n })\n .from(tenantMembers)\n .innerJoin(user, eq(tenantMembers.userId, user.id))\n .where(eq(tenantMembers.tenantId, tenantId));\n\n return c.json(\n members.map((m) => ({\n id: m.id,\n userId: m.userId,\n role: m.role,\n createdAt: m.createdAt.toISOString(),\n name: m.userName,\n email: m.userEmail,\n image: m.userImage,\n })),\n );\n });\n\n // POST /me/members — メンバー追加 or 招待\n app.post(\"/me/members\", async (c) => {\n const currentUser = c.get(\"user\");\n const tenantId = c.get(\"tenantId\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser || !tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const role = c.get(\"memberRole\");\n if (!isAdminOrOwner(role)) {\n return c.json({ error: tWithLocale(\"serverErrors.adminRequired\", locale) }, 403);\n }\n\n const body = await c.req.json<{ email?: string; role?: string }>();\n const email = body.email?.trim();\n if (!email) {\n return c.json({ error: tWithLocale(\"serverErrors.emailRequired\", locale) }, 400);\n }\n\n const memberRole = body.role ?? \"member\";\n if (!VALID_ROLES.has(memberRole)) {\n return c.json(\n { error: tfWithLocale(\"serverErrors.invalidRole\", locale, { roles: [...VALID_ROLES].join(\", \") }) },\n 400,\n );\n }\n\n // owner ロールの付与は owner のみ\n if (memberRole === \"owner\" && role !== \"owner\") {\n return c.json({ error: tWithLocale(\"serverErrors.ownerOnlyAssign\", locale) }, 403);\n }\n\n // ユーザーを検索\n const [targetUser] = await db\n .select({ id: user.id, name: user.name, email: user.email, image: user.image })\n .from(user)\n .where(eq(user.email, email))\n .limit(1);\n\n if (targetUser) {\n // 既存ユーザー → 既にメンバーか確認\n const [existing] = await db\n .select({ id: tenantMembers.id })\n .from(tenantMembers)\n .where(\n and(\n eq(tenantMembers.tenantId, tenantId),\n eq(tenantMembers.userId, targetUser.id),\n ),\n )\n .limit(1);\n\n if (existing) {\n return c.json({ error: tWithLocale(\"serverErrors.alreadyMember\", locale) }, 409);\n }\n // 既存ユーザーも招待フローに統一(以下の共通パスで処理)\n }\n\n // 共通: 同一テナント+メールで pending 招待がある場合は 409\n const [existingInvite] = await db\n .select({ id: invitations.id })\n .from(invitations)\n .where(\n and(\n eq(invitations.tenantId, tenantId),\n eq(invitations.email, email),\n eq(invitations.status, \"pending\"),\n gt(invitations.expiresAt, new Date()),\n ),\n )\n .limit(1);\n\n if (existingInvite) {\n return c.json({ error: tWithLocale(\"serverErrors.invitationPending\", locale) }, 409);\n }\n\n // テナント名・locale を取得\n const [tenant] = await db\n .select({ name: tenants.name, locale: tenants.locale })\n .from(tenants)\n .where(eq(tenants.id, tenantId))\n .limit(1);\n\n const token = createInvitationToken();\n const expiresAt = new Date();\n expiresAt.setDate(expiresAt.getDate() + INVITATION_EXPIRY_DAYS);\n\n const [invitation] = await db\n .insert(invitations)\n .values({\n tenantId,\n email,\n role: memberRole as MemberRole,\n token,\n invitedBy: currentUser.id,\n expiresAt,\n })\n .returning();\n\n // 招待メール送信\n const inviteLocale = (tenant?.locale as EmailLocale) ?? \"en\";\n const inviteTenantName = tenant?.name ?? \"a team\";\n const variant = targetUser ? \"existing\" as const : \"new\" as const;\n const inviteUrl = targetUser\n ? `${config.corsOrigin}/invitations/accept?token=${token}`\n : `${config.corsOrigin}/register?invitation=${token}`;\n await sendEmail({\n to: email,\n subject: emailString(\"invitationSubject\", inviteLocale, { tenantName: inviteTenantName }),\n html: buildInvitationEmailHtml({\n inviteUrl,\n tenantName: inviteTenantName,\n inviterName: currentUser.name,\n role: memberRole,\n locale: inviteLocale,\n variant,\n }),\n });\n\n return c.json(\n {\n id: invitation.id,\n email: invitation.email,\n role: invitation.role,\n status: invitation.status,\n createdAt: invitation.createdAt.toISOString(),\n expiresAt: invitation.expiresAt.toISOString(),\n type: \"invitation\" as const,\n },\n 201,\n );\n });\n\n // PATCH /me/members/:id — ロール変更\n app.patch(\"/me/members/:id\", async (c) => {\n const currentUser = c.get(\"user\");\n const tenantId = c.get(\"tenantId\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser || !tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const currentRole = c.get(\"memberRole\");\n if (currentRole !== \"owner\") {\n return c.json({ error: tWithLocale(\"serverErrors.ownerOnly\", locale) }, 403);\n }\n\n const memberId = c.req.param(\"id\");\n const body = await c.req.json<{ role?: string }>();\n const newRole = body.role;\n\n if (!newRole || !VALID_ROLES.has(newRole)) {\n return c.json(\n { error: tfWithLocale(\"serverErrors.invalidRole\", locale, { roles: [...VALID_ROLES].join(\", \") }) },\n 400,\n );\n }\n\n const [updated] = await db\n .update(tenantMembers)\n .set({ role: newRole as MemberRole })\n .where(\n and(\n eq(tenantMembers.id, memberId),\n eq(tenantMembers.tenantId, tenantId),\n ),\n )\n .returning({ id: tenantMembers.id });\n\n if (!updated) {\n return c.json({ error: tWithLocale(\"serverErrors.memberNotFound\", locale) }, 404);\n }\n\n return c.body(null, 204);\n });\n\n // DELETE /me/members/:id — メンバー削除\n app.delete(\"/me/members/:id\", async (c) => {\n const currentUser = c.get(\"user\");\n const tenantId = c.get(\"tenantId\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser || !tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const currentRole = c.get(\"memberRole\");\n if (!isAdminOrOwner(currentRole)) {\n return c.json({ error: tWithLocale(\"serverErrors.adminRequired\", locale) }, 403);\n }\n\n const memberId = c.req.param(\"id\");\n\n // 対象メンバーを確認\n const [target] = await db\n .select({ id: tenantMembers.id, role: tenantMembers.role, userId: tenantMembers.userId })\n .from(tenantMembers)\n .where(\n and(\n eq(tenantMembers.id, memberId),\n eq(tenantMembers.tenantId, tenantId),\n ),\n )\n .limit(1);\n\n if (!target) {\n return c.json({ error: tWithLocale(\"serverErrors.memberNotFound\", locale) }, 404);\n }\n\n // owner は削除不可(自分自身含む)\n if (target.role === \"owner\") {\n return c.json({ error: tWithLocale(\"serverErrors.cannotRemoveOwner\", locale) }, 403);\n }\n\n // admin が admin を削除するのは不可\n if (target.role === \"admin\" && currentRole !== \"owner\") {\n return c.json({ error: tWithLocale(\"serverErrors.ownerOnlyRemoveAdmin\", locale) }, 403);\n }\n\n await db\n .delete(tenantMembers)\n .where(eq(tenantMembers.id, memberId));\n\n return c.body(null, 204);\n });\n\n // GET /me/invitations — 招待一覧(pending のみ、期限切れ除外)\n app.get(\"/me/invitations\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", locale) }, 404);\n }\n\n const rows = await db\n .select()\n .from(invitations)\n .where(\n and(\n eq(invitations.tenantId, tenantId),\n eq(invitations.status, \"pending\"),\n gt(invitations.expiresAt, new Date()),\n ),\n );\n\n return c.json(\n rows.map((inv) => ({\n id: inv.id,\n email: inv.email,\n role: inv.role,\n status: inv.status,\n createdAt: inv.createdAt.toISOString(),\n expiresAt: inv.expiresAt.toISOString(),\n })),\n );\n });\n\n // DELETE /me/invitations/:id — 招待キャンセル\n app.delete(\"/me/invitations/:id\", async (c) => {\n const currentUser = c.get(\"user\");\n const tenantId = c.get(\"tenantId\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser || !tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const currentRole = c.get(\"memberRole\");\n if (!isAdminOrOwner(currentRole)) {\n return c.json({ error: tWithLocale(\"serverErrors.adminRequired\", locale) }, 403);\n }\n\n const invitationId = c.req.param(\"id\");\n const [updated] = await db\n .update(invitations)\n .set({ status: \"cancelled\" })\n .where(\n and(\n eq(invitations.id, invitationId),\n eq(invitations.tenantId, tenantId),\n eq(invitations.status, \"pending\"),\n ),\n )\n .returning({ id: invitations.id });\n\n if (!updated) {\n return c.json({ error: tWithLocale(\"serverErrors.invitationNotFound\", locale) }, 404);\n }\n\n return c.body(null, 204);\n });\n\n // POST /me/invitations/:id/resend — 招待再送信\n app.post(\"/me/invitations/:id/resend\", async (c) => {\n const currentUser = c.get(\"user\");\n const tenantId = c.get(\"tenantId\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser || !tenantId) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const currentRole = c.get(\"memberRole\");\n if (!isAdminOrOwner(currentRole)) {\n return c.json({ error: tWithLocale(\"serverErrors.adminRequired\", locale) }, 403);\n }\n\n const invitationId = c.req.param(\"id\");\n const [existing] = await db\n .select()\n .from(invitations)\n .where(\n and(\n eq(invitations.id, invitationId),\n eq(invitations.tenantId, tenantId),\n eq(invitations.status, \"pending\"),\n ),\n )\n .limit(1);\n\n if (!existing) {\n return c.json({ error: tWithLocale(\"serverErrors.invitationNotFound\", locale) }, 404);\n }\n\n // 新トークン + expiresAt リセット\n const newToken = createInvitationToken();\n const newExpires = new Date();\n newExpires.setDate(newExpires.getDate() + INVITATION_EXPIRY_DAYS);\n\n await db\n .update(invitations)\n .set({ token: newToken, expiresAt: newExpires })\n .where(eq(invitations.id, invitationId));\n\n // テナント名・locale を取得\n const [tenant] = await db\n .select({ name: tenants.name, locale: tenants.locale })\n .from(tenants)\n .where(eq(tenants.id, tenantId))\n .limit(1);\n\n // 既存ユーザーか判定して URL と variant を分岐\n const [targetUser] = await db\n .select({ id: user.id })\n .from(user)\n .where(eq(user.email, existing.email))\n .limit(1);\n\n const resendLocale = (tenant?.locale as EmailLocale) ?? \"en\";\n const resendTenantName = tenant?.name ?? \"a team\";\n const variant = targetUser ? \"existing\" as const : \"new\" as const;\n const inviteUrl = targetUser\n ? `${config.corsOrigin}/invitations/accept?token=${newToken}`\n : `${config.corsOrigin}/register?invitation=${newToken}`;\n await sendEmail({\n to: existing.email,\n subject: emailString(\"invitationSubject\", resendLocale, { tenantName: resendTenantName }),\n html: buildInvitationEmailHtml({\n inviteUrl,\n tenantName: resendTenantName,\n inviterName: currentUser.name,\n role: existing.role,\n locale: resendLocale,\n variant,\n }),\n });\n\n return c.json({ ok: true });\n });\n\n // GET /my-invitations — 現在ユーザーの pending 招待一覧\n app.get(\"/my-invitations\", async (c) => {\n const currentUser = c.get(\"user\");\n if (!currentUser) {\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const rows = await db\n .select({\n id: invitations.id,\n role: invitations.role,\n tenantId: invitations.tenantId,\n tenantName: tenants.name,\n inviterName: user.name,\n createdAt: invitations.createdAt,\n expiresAt: invitations.expiresAt,\n })\n .from(invitations)\n .innerJoin(tenants, eq(invitations.tenantId, tenants.id))\n .innerJoin(user, eq(invitations.invitedBy, user.id))\n .where(\n and(\n eq(invitations.email, currentUser.email),\n eq(invitations.status, \"pending\"),\n gt(invitations.expiresAt, new Date()),\n ),\n );\n\n return c.json(\n rows.map((r) => ({\n id: r.id,\n role: r.role,\n tenantId: r.tenantId,\n tenantName: r.tenantName,\n inviterName: r.inviterName,\n createdAt: r.createdAt.toISOString(),\n expiresAt: r.expiresAt.toISOString(),\n })),\n );\n });\n\n // POST /my-invitations/:id/accept — 招待受諾\n app.post(\"/my-invitations/:id/accept\", async (c) => {\n const currentUser = c.get(\"user\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser) return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n\n const invitationId = c.req.param(\"id\");\n const [inv] = await db\n .select()\n .from(invitations)\n .where(\n and(\n eq(invitations.id, invitationId),\n eq(invitations.email, currentUser.email),\n eq(invitations.status, \"pending\"),\n ),\n )\n .limit(1);\n\n if (!inv) return c.json({ error: tWithLocale(\"serverErrors.invitationNotFound\", locale) }, 404);\n\n if (inv.expiresAt < new Date()) {\n return c.json({ error: tWithLocale(\"serverErrors.invitationExpired\", locale) }, 410);\n }\n\n // 招待ステータス更新 + メンバー追加をトランザクションで実行\n await db.transaction(async (tx) => {\n await tx\n .update(invitations)\n .set({ status: \"accepted\", acceptedAt: new Date() })\n .where(eq(invitations.id, invitationId));\n\n const [existingMember] = await tx\n .select({ id: tenantMembers.id })\n .from(tenantMembers)\n .where(\n and(\n eq(tenantMembers.tenantId, inv.tenantId),\n eq(tenantMembers.userId, currentUser.id),\n ),\n )\n .limit(1);\n\n if (!existingMember) {\n await tx\n .insert(tenantMembers)\n .values({\n tenantId: inv.tenantId,\n userId: currentUser.id,\n role: inv.role as MemberRole,\n });\n }\n });\n\n return c.json({ ok: true, tenantId: inv.tenantId });\n });\n\n // POST /my-invitations/:id/decline — 招待辞退\n app.post(\"/my-invitations/:id/decline\", async (c) => {\n const currentUser = c.get(\"user\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser) return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n\n const invitationId = c.req.param(\"id\");\n const [updated] = await db\n .update(invitations)\n .set({ status: \"declined\" })\n .where(\n and(\n eq(invitations.id, invitationId),\n eq(invitations.email, currentUser.email),\n eq(invitations.status, \"pending\"),\n ),\n )\n .returning({ id: invitations.id });\n\n if (!updated) {\n return c.json({ error: tWithLocale(\"serverErrors.invitationNotFound\", locale) }, 404);\n }\n\n return c.body(null, 204);\n });\n\n return app;\n}\n\n/** トークンで招待を解決(公開エンドポイント用) */\nexport async function resolveInvitationByToken(\n db: ReturnType<typeof getDb>,\n token: string,\n) {\n const [row] = await db\n .select({\n id: invitations.id,\n role: invitations.role,\n tenantId: invitations.tenantId,\n tenantName: tenants.name,\n inviterName: user.name,\n status: invitations.status,\n expiresAt: invitations.expiresAt,\n createdAt: invitations.createdAt,\n })\n .from(invitations)\n .innerJoin(tenants, eq(invitations.tenantId, tenants.id))\n .innerJoin(user, eq(invitations.invitedBy, user.id))\n .where(eq(invitations.token, token))\n .limit(1);\n\n return row ?? null;\n}\n","/**\n * ユーザーハンドラー\n *\n * GET /api/v1/users/me — ユーザー情報\n * POST /api/v1/users/me/complete-onboarding — ユーザーオンボーディング完了\n */\n\nimport { Hono } from \"hono\";\nimport { eq } from \"drizzle-orm\";\nimport type { getDb } from \"../db/client.js\";\nimport { user } from \"../db/schema.js\";\nimport type { AppVariables } from \"../middleware/types.js\";\nimport { resolveAcceptLanguage, tWithLocale } from \"../../i18n/index.js\";\n\nexport function usersRoutes(db: ReturnType<typeof getDb>) {\n const app = new Hono<{ Variables: AppVariables }>();\n\n // GET /me — ユーザー情報\n app.get(\"/me\", async (c) => {\n const currentUser = c.get(\"user\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n const [row] = await db\n .select()\n .from(user)\n .where(eq(user.id, currentUser.id))\n .limit(1);\n\n if (!row) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n return c.json({\n id: row.id,\n name: row.name,\n email: row.email,\n image: row.image,\n createdAt: row.createdAt.toISOString(),\n onboardingCompletedAt: row.onboardingCompletedAt?.toISOString() ?? null,\n });\n });\n\n // POST /me/complete-onboarding — ユーザーオンボーディング完了(冪等)\n app.post(\"/me/complete-onboarding\", async (c) => {\n const currentUser = c.get(\"user\");\n const locale = resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n if (!currentUser) {\n return c.json({ error: tWithLocale(\"serverErrors.unauthorized\", locale) }, 401);\n }\n\n // 既に完了済みなら何もしない(冪等)\n const [existing] = await db\n .select({ onboardingCompletedAt: user.onboardingCompletedAt })\n .from(user)\n .where(eq(user.id, currentUser.id))\n .limit(1);\n\n if (existing?.onboardingCompletedAt) {\n return c.json({ ok: true });\n }\n\n await db\n .update(user)\n .set({ onboardingCompletedAt: new Date() })\n .where(eq(user.id, currentUser.id));\n\n return c.json({ ok: true });\n });\n\n return app;\n}\n","/**\n * 設定 API ハンドラ\n */\n\nimport { Hono } from \"hono\";\nimport { eq, and } from \"drizzle-orm\";\nimport type { getDb } from \"../db/client.js\";\nimport type { ServerConfig } from \"../config.js\";\nimport type { AppVariables } from \"../middleware/types.js\";\nimport { requireRole } from \"../middleware/rbac.js\";\nimport { requirePlanFeature } from \"../middleware/plan-gate.js\";\nimport {\n tenantExecutionSettings,\n tenantModelProviders,\n tenantModelOverrides,\n tenants,\n tenantMembers,\n user,\n schedules,\n} from \"../db/schema.js\";\nimport { TelemetryStore } from \"../store/telemetry-store.js\";\nimport { generateDebugTelemetryReport, generateJobTelemetryReport } from \"../telemetry/debug-report-generator.js\";\nimport {\n encrypt,\n decrypt,\n maskSensitiveValue,\n isMaskedValue,\n} from \"../crypto.js\";\nimport { TIER_TO_PLAN, PLAN_PRICING, type PlanTier } from \"../../plan/index.js\";\nimport { generateDebugToken, getDebugSigningKey, getDebugPublicKey } from \"../../plan/debug-token.js\";\nimport { z } from \"zod\";\nimport {\n executionConfigSchema,\n modelsConfigSchema,\n providerSchema,\n overridesConfigSchema,\n teamPatchSchema,\n} from \"./settings-schema.js\";\nimport type { ProviderConfigField, DashboardProvider, DashboardModelOverride, NotificationPlatform } from \"./settings-defaults.js\";\nimport {\n DEFAULT_PROVIDERS,\n DEFAULT_MODEL_OVERRIDES,\n SENSITIVE_FIELDS,\n NOTIFICATION_SENSITIVE_FIELDS,\n NOTIFICATION_CREDENTIAL_FIELDS,\n} from \"./settings-defaults.js\";\nimport { tWithLocale, tfWithLocale, resolveAcceptLanguage, type Locale } from \"../../i18n/index.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\ntype NotificationCredentials = Record<string, Record<string, string> | undefined>;\n\n/** Decrypt & mask sensitive notification credential fields for API response */\nfunction maskNotificationCredentials(\n stored: NotificationCredentials | null | undefined,\n encryptionKey: string,\n): NotificationCredentials | null {\n if (!stored) return null;\n const result: NotificationCredentials = {};\n for (const platform of [\"slack\", \"teams\", \"discord\"] as NotificationPlatform[]) {\n const creds = stored[platform];\n if (!creds) continue;\n const sensitiveKeys = new Set(NOTIFICATION_SENSITIVE_FIELDS[platform] ?? []);\n const masked: Record<string, string> = {};\n for (const [key, val] of Object.entries(creds)) {\n if (!val) continue;\n if (sensitiveKeys.has(key)) {\n try {\n masked[key] = maskSensitiveValue(decrypt(val, encryptionKey));\n } catch {\n masked[key] = \"••••••••\";\n }\n } else {\n masked[key] = val;\n }\n }\n result[platform] = masked;\n }\n return Object.keys(result).length > 0 ? result : null;\n}\n\n/** Process incoming notification credentials: encrypt new values, preserve masked values */\nfunction processNotificationCredentials(\n incoming: NotificationCredentials | null | undefined,\n existing: NotificationCredentials | null | undefined,\n encryptionKey: string,\n): NotificationCredentials | null {\n if (!incoming) return null;\n const result: NotificationCredentials = {};\n for (const platform of [\"slack\", \"teams\", \"discord\"] as NotificationPlatform[]) {\n const creds = incoming[platform];\n if (!creds) {\n // preserve existing if not provided\n if (existing?.[platform]) {\n result[platform] = existing[platform];\n }\n continue;\n }\n const sensitiveKeys = new Set(NOTIFICATION_SENSITIVE_FIELDS[platform] ?? []);\n const processed: Record<string, string> = {};\n const existingCreds = existing?.[platform] ?? {};\n for (const [key, val] of Object.entries(creds)) {\n if (!val) continue;\n if (sensitiveKeys.has(key) && isMaskedValue(val)) {\n // preserve existing encrypted value\n if (existingCreds[key]) {\n processed[key] = existingCreds[key];\n }\n } else if (sensitiveKeys.has(key)) {\n processed[key] = encrypt(val, encryptionKey);\n } else {\n processed[key] = val;\n }\n }\n result[platform] = processed;\n }\n return Object.keys(result).length > 0 ? result : null;\n}\n\nexport function createSettingsRoutes(db: Db, config: ServerConfig) {\n const app = new Hono<{ Variables: AppVariables }>();\n\n /** Resolve locale from request */\n function reqLocale(c: { req: { header: (name: string) => string | undefined } }): Locale {\n return resolveAcceptLanguage(c.req.header(\"Accept-Language\"));\n }\n\n // ── GET /execution ──\n app.get(\"/execution\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n const row = await db.query.tenantExecutionSettings.findFirst({\n where: eq(tenantExecutionSettings.tenantId, tenantId),\n });\n\n if (!row) {\n return c.json({\n stealth: false,\n proxy: null,\n approvalMode: \"web\",\n notifyMode: null,\n enableSelectorCache: true,\n enableAgentFallback: true,\n enableVisionFallback: false,\n enableScreenshots: false,\n enableVideoRecording: false,\n skills: [],\n apiKey: null,\n notificationCredentials: null,\n });\n }\n\n return c.json({\n stealth: row.stealth,\n proxy: row.proxy,\n approvalMode: row.approvalMode,\n notifyMode: row.notifyMode,\n enableSelectorCache: row.enableSelectorCache,\n enableAgentFallback: row.enableAgentFallback,\n enableVisionFallback: row.enableVisionFallback,\n enableScreenshots: row.enableScreenshots,\n enableVideoRecording: row.enableVideoRecording,\n skills: row.skills,\n apiKey: row.apiKey\n ? maskSensitiveValue(decrypt(row.apiKey, config.encryptionKey))\n : null,\n notificationCredentials: maskNotificationCredentials(\n row.notificationCredentials as NotificationCredentials | null,\n config.encryptionKey,\n ),\n });\n });\n\n // ── PUT /execution ──(admin 以上)\n app.put(\"/execution\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n const userId = c.get(\"user\")?.id ?? null;\n const body = await c.req.json();\n const parsed = executionConfigSchema.safeParse(body);\n if (!parsed.success) {\n return c.json({ error: parsed.error.flatten() }, 400);\n }\n\n const data = parsed.data;\n\n // プランゲートチェック\n const plan = c.get(\"plan\");\n if (data.stealth && !plan.features.stealthMode) {\n return c.json({ error: tfWithLocale(\"serverErrors.planFeatureRequired\", reqLocale(c), { tier: \"Pro\" }) }, 403);\n }\n if (data.proxy && !plan.features.stealthMode) {\n return c.json({ error: tfWithLocale(\"serverErrors.planFeatureRequired\", reqLocale(c), { tier: \"Pro\" }) }, 403);\n }\n if (data.skills.length > 0 && !plan.features.skills) {\n return c.json({ error: tfWithLocale(\"serverErrors.planFeatureRequired\", reqLocale(c), { tier: \"Pro\" }) }, 403);\n }\n if (data.enableVideoRecording && !plan.features.videoRecording) {\n return c.json({ error: tfWithLocale(\"serverErrors.planFeatureRequired\", reqLocale(c), { tier: \"Business\" }) }, 403);\n }\n if (data.enableScreenshots && !plan.features.screenshotSave) {\n return c.json({ error: tfWithLocale(\"serverErrors.planFeatureRequired\", reqLocale(c), { tier: \"Team\" }) }, 403);\n }\n if (!plan.features.hitl && data.notifyMode) {\n return c.json({ error: tfWithLocale(\"serverErrors.planFeatureRequired\", reqLocale(c), { tier: \"Business\" }) }, 403);\n }\n\n // 既存値を取得(apiKey + notificationCredentials のマスク値保持用)\n const existingRow = await db.query.tenantExecutionSettings.findFirst({\n where: eq(tenantExecutionSettings.tenantId, tenantId),\n columns: { apiKey: true, notificationCredentials: true },\n });\n\n // apiKey: マスク値なら既存値を保持\n let encryptedApiKey: string | null = null;\n if (data.apiKey && !isMaskedValue(data.apiKey)) {\n encryptedApiKey = encrypt(data.apiKey, config.encryptionKey);\n } else if (data.apiKey && isMaskedValue(data.apiKey)) {\n encryptedApiKey = existingRow?.apiKey ?? null;\n }\n\n // notificationCredentials: encrypt new values, preserve masked values\n const processedCredentials = processNotificationCredentials(\n data.notificationCredentials as NotificationCredentials | null | undefined,\n existingRow?.notificationCredentials as NotificationCredentials | null | undefined,\n config.encryptionKey,\n );\n\n // 必須認証情報のバリデーション\n const requiredPlatforms = new Set<NotificationPlatform>();\n if (data.approvalMode !== \"web\") requiredPlatforms.add(data.approvalMode as NotificationPlatform);\n if (data.notifyMode) requiredPlatforms.add(data.notifyMode as NotificationPlatform);\n\n for (const platform of requiredPlatforms) {\n const fields = NOTIFICATION_CREDENTIAL_FIELDS[platform];\n if (!fields) continue;\n const creds = processedCredentials?.[platform] ?? {};\n const missing = fields\n .filter((f) => f.required && !creds[f.key])\n .map((f) => f.key);\n if (missing.length > 0) {\n return c.json(\n { error: tfWithLocale(\"serverErrors.missingCredentials\", reqLocale(c), { platform, fields: missing.join(\", \") }) },\n 400,\n );\n }\n }\n\n const values = {\n tenantId,\n stealth: data.stealth,\n proxy: data.proxy ?? null,\n approvalMode: data.approvalMode,\n notifyMode: data.notifyMode ?? null,\n enableSelectorCache: data.enableSelectorCache,\n enableAgentFallback: data.enableAgentFallback,\n enableVisionFallback: data.enableVisionFallback,\n enableScreenshots: data.enableScreenshots,\n enableVideoRecording: data.enableVideoRecording,\n skills: data.skills,\n apiKey: encryptedApiKey,\n notificationCredentials: processedCredentials,\n updatedAt: new Date(),\n updatedBy: userId,\n };\n\n await db\n .insert(tenantExecutionSettings)\n .values(values)\n .onConflictDoUpdate({\n target: tenantExecutionSettings.tenantId,\n set: {\n ...values,\n tenantId: undefined,\n },\n });\n\n return c.json({ ok: true });\n });\n\n // ── GET /models ──\n app.get(\"/models\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n\n const [providerRows, overrideRows] = await Promise.all([\n db.query.tenantModelProviders.findMany({\n where: eq(tenantModelProviders.tenantId, tenantId),\n }),\n db.query.tenantModelOverrides.findMany({\n where: eq(tenantModelOverrides.tenantId, tenantId),\n }),\n ]);\n\n // プロバイダー: DB に保存済みのものはそれを使い、未保存のものはデフォルト\n const providerMap = new Map(providerRows.map((r) => [r.providerId, r]));\n const providers: DashboardProvider[] = DEFAULT_PROVIDERS.map((def) => {\n const row = providerMap.get(def.id);\n if (!row) return def;\n\n const configObj = (row.config ?? {}) as Record<string, string>;\n const configFields: ProviderConfigField[] = def.configFields.map((field) => {\n const storedVal = configObj[field.key];\n let displayVal: string | undefined;\n if (storedVal) {\n if (field.sensitive) {\n try {\n displayVal = maskSensitiveValue(\n decrypt(storedVal, config.encryptionKey),\n );\n } catch {\n displayVal = \"••••••••\";\n }\n } else {\n displayVal = storedVal;\n }\n }\n return { ...field, value: displayVal };\n });\n\n // connected 3段階: true(テスト成功)/ \"pending\"(保存済み・未テスト)/ false(未設定)\n const hasRequiredConfig = def.configFields\n .filter((f) => f.required)\n .every((f) => !!configObj[f.key]);\n const connected: boolean | \"pending\" = row.connected\n ? true\n : hasRequiredConfig\n ? \"pending\"\n : false;\n\n return {\n id: def.id,\n connected,\n modelId: row.modelId,\n configFields,\n };\n });\n\n // オーバーライド: DB に保存済みのものはそれを使い、未保存のものはデフォルト\n const overrideMap = new Map(overrideRows.map((r) => [r.purpose, r]));\n const overrides: DashboardModelOverride[] = DEFAULT_MODEL_OVERRIDES.map(\n (def) => {\n const row = overrideMap.get(def.purpose);\n if (!row) return def;\n return {\n purpose: row.purpose as DashboardModelOverride[\"purpose\"],\n description: row.description,\n modelId: row.modelId,\n };\n },\n );\n\n return c.json({ providers, overrides });\n });\n\n // ── PUT /models ──(admin 以上)\n app.put(\"/models\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n const body = await c.req.json();\n const parsed = modelsConfigSchema.safeParse(body);\n if (!parsed.success) {\n return c.json({ error: parsed.error.flatten() }, 400);\n }\n\n const { providers, overrides } = parsed.data;\n\n // 既存プロバイダーの暗号化値を取得(マスク値保持用)\n const existingProviders = await db.query.tenantModelProviders.findMany({\n where: eq(tenantModelProviders.tenantId, tenantId),\n });\n const existingMap = new Map(\n existingProviders.map((r) => [r.providerId, r]),\n );\n\n // プロバイダー upsert\n for (const provider of providers) {\n const configObj: Record<string, string> = {};\n const existingRow = existingMap.get(provider.id);\n const existingConfig = (existingRow?.config ?? {}) as Record<string, string>;\n const sensitiveKeys = new Set(SENSITIVE_FIELDS[provider.id] ?? []);\n\n let configChanged = false;\n for (const field of provider.configFields) {\n if (!field.value) continue;\n if (sensitiveKeys.has(field.key) && isMaskedValue(field.value)) {\n // マスク値 → 既存の暗号化値を保持\n if (existingConfig[field.key]) {\n configObj[field.key] = existingConfig[field.key];\n }\n } else if (sensitiveKeys.has(field.key)) {\n // 新しい値 → 暗号化\n configObj[field.key] = encrypt(field.value, config.encryptionKey);\n configChanged = true;\n } else {\n if (existingConfig[field.key] !== field.value) {\n configChanged = true;\n }\n // 非 sensitive → そのまま保存\n configObj[field.key] = field.value;\n }\n }\n\n // config が変わったら connected をリセット\n const connected = existingRow?.connected && !configChanged ? true : false;\n\n await db\n .insert(tenantModelProviders)\n .values({\n tenantId,\n providerId: provider.id,\n modelId: provider.modelId,\n connected,\n config: configObj,\n updatedAt: new Date(),\n })\n .onConflictDoUpdate({\n target: [\n tenantModelProviders.tenantId,\n tenantModelProviders.providerId,\n ],\n set: {\n modelId: provider.modelId,\n connected,\n config: configObj,\n updatedAt: new Date(),\n },\n });\n }\n\n // オーバーライド upsert(modelOverrides が許可されていない場合はスキップ)\n const plan = c.get(\"plan\");\n const filteredOverrides = plan.features.modelOverrides\n ? overrides\n : overrides.filter((o) => !o.modelId);\n for (const override of filteredOverrides) {\n await db\n .insert(tenantModelOverrides)\n .values({\n tenantId,\n purpose: override.purpose,\n description: override.description,\n modelId: override.modelId,\n updatedAt: new Date(),\n })\n .onConflictDoUpdate({\n target: [\n tenantModelOverrides.tenantId,\n tenantModelOverrides.purpose,\n ],\n set: {\n description: override.description,\n modelId: override.modelId,\n updatedAt: new Date(),\n },\n });\n }\n\n return c.json({ ok: true });\n });\n\n // ── PUT /models/providers/:providerId ──(admin 以上)\n app.put(\"/models/providers/:providerId\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n const { providerId } = c.req.param();\n const body = await c.req.json();\n const parsed = providerSchema.safeParse(body);\n if (!parsed.success) {\n return c.json({ error: parsed.error.flatten() }, 400);\n }\n const provider = parsed.data;\n if (provider.id !== providerId) {\n return c.json({ error: tWithLocale(\"serverErrors.providerIdMismatch\", reqLocale(c)) }, 400);\n }\n\n // 既存の暗号化値を取得(マスク値保持用 + config変更検出)\n const existingRow = await db.query.tenantModelProviders.findFirst({\n where: and(\n eq(tenantModelProviders.tenantId, tenantId),\n eq(tenantModelProviders.providerId, providerId),\n ),\n columns: { config: true, connected: true },\n });\n const existingConfig = (existingRow?.config ?? {}) as Record<string, string>;\n const sensitiveKeys = new Set(SENSITIVE_FIELDS[provider.id] ?? []);\n\n const configObj: Record<string, string> = {};\n for (const field of provider.configFields) {\n if (!field.value) continue;\n if (sensitiveKeys.has(field.key) && isMaskedValue(field.value)) {\n if (existingConfig[field.key]) {\n configObj[field.key] = existingConfig[field.key];\n }\n } else if (sensitiveKeys.has(field.key)) {\n configObj[field.key] = encrypt(field.value, config.encryptionKey);\n } else {\n configObj[field.key] = field.value;\n }\n }\n\n // 常に接続テストを実行(テスト用 config 構築: 新しい平文値 + 既存の復号値をマージ)\n const testConfig: Record<string, string> = {};\n for (const field of provider.configFields) {\n if (!field.value) continue;\n if (sensitiveKeys.has(field.key) && isMaskedValue(field.value)) {\n if (existingConfig[field.key]) {\n try {\n testConfig[field.key] = decrypt(existingConfig[field.key], config.encryptionKey);\n } catch { /* skip */ }\n }\n } else if (sensitiveKeys.has(field.key)) {\n testConfig[field.key] = field.value;\n } else {\n testConfig[field.key] = field.value;\n }\n }\n\n // required フィールドが揃っていれば接続テスト\n const providerDef = DEFAULT_PROVIDERS.find(p => p.id === providerId);\n const hasRequiredFields = providerDef?.configFields\n .filter(f => f.required)\n .every(f => !!testConfig[f.key]) ?? false;\n\n let connected: boolean;\n if (hasRequiredFields) {\n try {\n const model = await createTestModel(providerId, provider.modelId, testConfig);\n const { generateText } = await import(\"ai\");\n await generateText({ model, prompt: \"Respond with OK.\" });\n connected = true;\n } catch (error) {\n return c.json({\n error: \"Connection test failed\",\n message: error instanceof Error ? error.message : \"Connection failed\",\n }, 400);\n }\n } else {\n connected = false;\n }\n\n await db\n .insert(tenantModelProviders)\n .values({\n tenantId,\n providerId: provider.id,\n modelId: provider.modelId,\n connected,\n config: configObj,\n updatedAt: new Date(),\n })\n .onConflictDoUpdate({\n target: [\n tenantModelProviders.tenantId,\n tenantModelProviders.providerId,\n ],\n set: {\n modelId: provider.modelId,\n connected,\n config: configObj,\n updatedAt: new Date(),\n },\n });\n\n return c.json({ ok: true, connected });\n });\n\n // ── POST /models/providers/:providerId/test ──(admin 以上)\n app.post(\"/models/providers/:providerId/test\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n const { providerId } = c.req.param();\n const providerIdTyped = providerId as typeof tenantModelProviders.providerId.enumValues[number];\n\n const row = await db.query.tenantModelProviders.findFirst({\n where: and(\n eq(tenantModelProviders.tenantId, tenantId),\n eq(tenantModelProviders.providerId, providerIdTyped),\n ),\n });\n if (!row) return c.json({ error: tWithLocale(\"serverErrors.providerNotConfigured\", reqLocale(c)) }, 404);\n\n const configObj = (row.config ?? {}) as Record<string, string>;\n const sensitiveKeys = new Set(SENSITIVE_FIELDS[providerId] ?? []);\n const decrypted: Record<string, string> = {};\n for (const [key, val] of Object.entries(configObj)) {\n decrypted[key] = sensitiveKeys.has(key)\n ? decrypt(val, config.encryptionKey)\n : val;\n }\n\n try {\n const model = await createTestModel(providerId, row.modelId, decrypted);\n const start = Date.now();\n const { generateText } = await import(\"ai\");\n await generateText({\n model,\n prompt: \"Respond with OK.\",\n });\n const latencyMs = Date.now() - start;\n\n // 成功 → connected = true に更新\n await db\n .update(tenantModelProviders)\n .set({ connected: true, updatedAt: new Date() })\n .where(\n and(\n eq(tenantModelProviders.tenantId, tenantId),\n eq(tenantModelProviders.providerId, providerIdTyped),\n ),\n );\n\n return c.json({ success: true, message: \"Connection successful\", latencyMs });\n } catch (error) {\n return c.json({\n success: false,\n message: error instanceof Error ? error.message : \"Connection failed\",\n });\n }\n });\n\n // ── PUT /models/overrides ──(admin 以上、Business+)\n app.put(\"/models/overrides\", requireRole(\"admin\"), requirePlanFeature(\"modelOverrides\", \"Business\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n const body = await c.req.json();\n const parsed = overridesConfigSchema.safeParse(body);\n if (!parsed.success) {\n return c.json({ error: parsed.error.flatten() }, 400);\n }\n\n const { overrides } = parsed.data;\n for (const override of overrides) {\n await db\n .insert(tenantModelOverrides)\n .values({\n tenantId,\n purpose: override.purpose,\n description: override.description,\n modelId: override.modelId,\n updatedAt: new Date(),\n })\n .onConflictDoUpdate({\n target: [\n tenantModelOverrides.tenantId,\n tenantModelOverrides.purpose,\n ],\n set: {\n description: override.description,\n modelId: override.modelId,\n updatedAt: new Date(),\n },\n });\n }\n\n return c.json({ ok: true });\n });\n\n // ── GET /development ──\n app.get(\"/development\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n\n const { tenantDevelopmentSettings } = await import(\"../db/schema.js\");\n const row = await db.query.tenantDevelopmentSettings.findFirst({\n where: eq(tenantDevelopmentSettings.tenantId, tenantId),\n });\n\n return c.json({\n requireApprovalBeforePublish: row?.requireApprovalBeforePublish ?? false,\n allowSelfApproval: row?.allowSelfApproval ?? false,\n });\n });\n\n // ── PUT /development ──(admin 以上、Business+)\n app.put(\"/development\", requireRole(\"admin\"), requirePlanFeature(\"runbookApprovalWorkflow\", \"Business\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n const userId = c.get(\"user\")?.id ?? null;\n\n const body = await c.req.json();\n const schema = z.object({\n requireApprovalBeforePublish: z.boolean(),\n allowSelfApproval: z.boolean().optional(),\n });\n const parsed = schema.safeParse(body);\n if (!parsed.success) {\n return c.json({ error: parsed.error.flatten() }, 400);\n }\n\n const { tenantDevelopmentSettings } = await import(\"../db/schema.js\");\n await db\n .insert(tenantDevelopmentSettings)\n .values({\n tenantId,\n requireApprovalBeforePublish: parsed.data.requireApprovalBeforePublish,\n ...(parsed.data.allowSelfApproval !== undefined && { allowSelfApproval: parsed.data.allowSelfApproval }),\n updatedBy: userId,\n })\n .onConflictDoUpdate({\n target: tenantDevelopmentSettings.tenantId,\n set: {\n requireApprovalBeforePublish: parsed.data.requireApprovalBeforePublish,\n ...(parsed.data.allowSelfApproval !== undefined && { allowSelfApproval: parsed.data.allowSelfApproval }),\n updatedBy: userId,\n },\n });\n\n return c.json({ ok: true });\n });\n\n // ── GET /plan ──\n app.get(\"/plan\", async (c) => {\n const plan = c.get(\"plan\");\n return c.json({\n tier: plan.tier,\n features: plan.features,\n limits: {\n maxStepsPerRunbook: plan.limits.maxStepsPerRunbook,\n maxBatchRows: plan.limits.maxBatchRows,\n maxMonthlySteps: plan.limits.maxMonthlySteps,\n maxScreenshots: plan.limits.maxScreenshots,\n maxVideoRecordings: plan.limits.maxVideoRecordings,\n maxRunbookVersions: plan.limits.maxRunbookVersions,\n },\n });\n });\n\n // ── GET /plans ──\n app.get(\"/plans\", (c) => {\n const currentTier = c.get(\"plan\").tier;\n const tiers: PlanTier[] = [\"community\", \"pro\", \"team\", \"business\", \"enterprise\"];\n const finiteOrNull = (v: number) => (v === Number.POSITIVE_INFINITY ? null : v);\n const plans = tiers.map((tier) => {\n const plan = TIER_TO_PLAN[tier];\n return {\n tier,\n priceMonthly: PLAN_PRICING[tier],\n isCurrent: tier === currentTier,\n features: plan.features,\n limits: {\n maxStepsPerRunbook: finiteOrNull(plan.limits.maxStepsPerRunbook),\n maxMonthlySteps: finiteOrNull(plan.limits.maxMonthlySteps),\n maxBatchRows: finiteOrNull(plan.limits.maxBatchRows),\n maxScreenshots: finiteOrNull(plan.limits.maxScreenshots),\n maxVideoRecordings: finiteOrNull(plan.limits.maxVideoRecordings),\n },\n };\n });\n return c.json({ plans, currentTier });\n });\n\n // ── GET /team ──\n app.get(\"/team\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n\n const tenant = await db.query.tenants.findFirst({\n where: eq(tenants.id, tenantId),\n });\n if (!tenant) {\n return c.json({ error: tWithLocale(\"serverErrors.tenantNotFound\", reqLocale(c)) }, 404);\n }\n\n const members = await db\n .select({\n id: user.id,\n name: user.name,\n email: user.email,\n role: tenantMembers.role,\n joinedAt: tenantMembers.createdAt,\n })\n .from(tenantMembers)\n .innerJoin(user, eq(tenantMembers.userId, user.id))\n .where(eq(tenantMembers.tenantId, tenantId));\n\n return c.json({\n tenant: {\n id: tenant.id,\n name: tenant.name,\n slug: tenant.slug,\n locale: tenant.locale,\n },\n members: members.map((m) => ({\n id: m.id,\n name: m.name,\n email: m.email,\n role: m.role,\n joinedAt: m.joinedAt.toISOString(),\n })),\n });\n });\n\n // ── PATCH /team ──(admin 以上)\n app.patch(\"/team\", requireRole(\"admin\"), async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n const body = await c.req.json();\n const parsed = teamPatchSchema.safeParse(body);\n if (!parsed.success) {\n return c.json({ error: parsed.error.flatten() }, 400);\n }\n\n const updates: Record<string, unknown> = {};\n if (parsed.data.name !== undefined) updates.name = parsed.data.name;\n if (parsed.data.locale !== undefined) updates.locale = parsed.data.locale;\n\n if (Object.keys(updates).length > 0) {\n await db\n .update(tenants)\n .set(updates)\n .where(eq(tenants.id, tenantId));\n }\n\n return c.json({ ok: true });\n });\n\n // ── PUT /debug/tier ──(dev 環境限定、owner ロール限定)\n app.put(\"/debug/tier\", requireRole(\"owner\"), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n\n const body = await c.req.json();\n const schema = z.object({\n tier: z.enum([\"community\", \"pro\", \"team\", \"business\", \"enterprise\"]),\n });\n const parsed = schema.safeParse(body);\n if (!parsed.success) {\n return c.json({ error: parsed.error.flatten() }, 400);\n }\n\n await db\n .update(tenants)\n .set({ tier: parsed.data.tier })\n .where(eq(tenants.id, tenantId));\n\n return c.json({ ok: true, tier: parsed.data.tier });\n });\n\n // ── POST /debug/trigger-schedule ──(dev 環境限定、owner ロール限定)\n app.post(\"/debug/trigger-schedule\", requireRole(\"owner\"), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n\n const body = await c.req.json();\n const schema = z.object({ scheduleId: z.string().uuid() });\n const parsed = schema.safeParse(body);\n if (!parsed.success) {\n return c.json({ error: parsed.error.flatten() }, 400);\n }\n\n const schedule = await db.query.schedules.findFirst({\n where: and(\n eq(schedules.id, parsed.data.scheduleId),\n eq(schedules.tenantId, tenantId),\n ),\n });\n if (!schedule) {\n return c.json({ error: \"Schedule not found\" }, 404);\n }\n\n await db\n .update(schedules)\n .set({ nextRunAt: new Date(0), enabled: true })\n .where(eq(schedules.id, parsed.data.scheduleId));\n\n return c.json({ ok: true, scheduleId: parsed.data.scheduleId });\n });\n\n // ── POST /debug/generate-debug-token ──(dev 環境限定、owner ロール限定)\n app.post(\"/debug/generate-debug-token\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: tWithLocale(\"serverErrors.tenantRequired\", reqLocale(c)) }, 403);\n\n const signingKey = getDebugSigningKey();\n if (!signingKey) {\n return c.json({ error: \"REFRAIN_DEBUG_SIGNING_KEY is not configured\" }, 400);\n }\n\n const token = generateDebugToken(tenantId, signingKey, getDebugPublicKey());\n return c.json({ ok: true, token });\n });\n\n // ── デバッグテレメトリ(dev 環境限定、owner + セッション認証限定) ──\n\n const telemetryStore = new TelemetryStore(db);\n\n /** 安全な正の整数パース(NaN → undefined) */\n function safeInt(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? Math.floor(n) : undefined;\n }\n\n // GET /debug/telemetry/summaries — テナント横断ジョブサマリー\n app.get(\"/debug/telemetry/summaries\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const tenantId = c.req.query(\"tenantId\") || undefined;\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const days = safeInt(c.req.query(\"days\"));\n const limit = safeInt(c.req.query(\"limit\"));\n const offset = safeInt(c.req.query(\"offset\"));\n\n const result = await telemetryStore.getCrossTenantSummaries({ tenantId, runbookId, days, limit, offset });\n return c.json(result);\n });\n\n // GET /debug/telemetry/failure-events — テナント横断失敗イベント\n app.get(\"/debug/telemetry/failure-events\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const tenantId = c.req.query(\"tenantId\") || undefined;\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const category = c.req.query(\"category\") || undefined;\n const urlPattern = c.req.query(\"urlPattern\") || undefined;\n const days = safeInt(c.req.query(\"days\"));\n const limit = safeInt(c.req.query(\"limit\"));\n const offset = safeInt(c.req.query(\"offset\"));\n\n const result = await telemetryStore.getCrossTenantFailureEvents({ tenantId, runbookId, category, urlPattern, days, limit, offset });\n return c.json(result);\n });\n\n // GET /debug/telemetry/resolution-outcomes — テナント横断解決結果\n app.get(\"/debug/telemetry/resolution-outcomes\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const tenantId = c.req.query(\"tenantId\") || undefined;\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const resolveMethod = c.req.query(\"resolveMethod\") || undefined;\n const matchType = c.req.query(\"matchType\") || undefined;\n const days = safeInt(c.req.query(\"days\"));\n const limit = safeInt(c.req.query(\"limit\"));\n const offset = safeInt(c.req.query(\"offset\"));\n\n const result = await telemetryStore.getCrossTenantResolutionOutcomes({ tenantId, runbookId, resolveMethod, matchType, days, limit, offset });\n return c.json(result);\n });\n\n // GET /debug/telemetry/failure-patterns — テナント横断失敗パターン\n app.get(\"/debug/telemetry/failure-patterns\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const tenantId = c.req.query(\"tenantId\") || undefined;\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const category = c.req.query(\"category\") || undefined;\n const limit = safeInt(c.req.query(\"limit\"));\n const offset = safeInt(c.req.query(\"offset\"));\n\n const result = await telemetryStore.getCrossTenantFailurePatterns({ tenantId, runbookId, category, limit, offset });\n return c.json(result);\n });\n\n // GET /debug/telemetry/suggestion-outcomes — テナント横断提案結果\n app.get(\"/debug/telemetry/suggestion-outcomes\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const tenantId = c.req.query(\"tenantId\") || undefined;\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const appliedParam = c.req.query(\"applied\");\n const applied = appliedParam !== undefined ? appliedParam === \"true\" : undefined;\n const limit = safeInt(c.req.query(\"limit\"));\n const offset = safeInt(c.req.query(\"offset\"));\n\n const result = await telemetryStore.getCrossTenantSuggestionOutcomes({ tenantId, runbookId, applied, limit, offset });\n return c.json(result);\n });\n\n // GET /debug/telemetry/stats — テナント横断集計統計\n app.get(\"/debug/telemetry/stats\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const tenantId = c.req.query(\"tenantId\") || undefined;\n const days = safeInt(c.req.query(\"days\"));\n\n const stats = await telemetryStore.getCrossTenantAggregateStats({ tenantId, days });\n return c.json(stats);\n });\n\n // GET /debug/telemetry/jobs/:jobId — ジョブ詳細(全テレメトリ)\n app.get(\"/debug/telemetry/jobs/:jobId\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const jobId = c.req.param(\"jobId\");\n const detail = await telemetryStore.getJobTelemetryDetail(jobId);\n if (!detail.summary) {\n return c.json({ error: \"Job telemetry not found\" }, 404);\n }\n return c.json(detail);\n });\n\n // GET /debug/telemetry/jobs/:jobId/report — ジョブ単体レポート(Markdown)\n app.get(\"/debug/telemetry/jobs/:jobId/report\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const jobId = c.req.param(\"jobId\");\n const [detail, executionDetails] = await Promise.all([\n telemetryStore.getJobTelemetryDetail(jobId),\n telemetryStore.getJobExecutionDetails(jobId),\n ]);\n if (!detail.summary) {\n return c.json({ error: \"Job telemetry not found\" }, 404);\n }\n const md = generateJobTelemetryReport({\n ...detail,\n stepResults: executionDetails.stepResults,\n aiMetrics: executionDetails.aiMetrics,\n });\n return new Response(md, {\n headers: { \"Content-Type\": \"text/markdown; charset=utf-8\" },\n });\n });\n\n // GET /debug/telemetry/report — フルレポート出力(JSON/Markdown)\n app.get(\"/debug/telemetry/report\", requireRole(\"owner\", { rejectApiKey: true }), async (c) => {\n if (config.nodeEnv !== \"development\") {\n return c.json({ error: \"Debug endpoints are only available in development\" }, 403);\n }\n const format = c.req.query(\"format\") ?? \"json\";\n const days = safeInt(c.req.query(\"days\")) ?? 30;\n const tenantId = c.req.query(\"tenantId\") || undefined;\n const opts = { tenantId, days, limit: 1000 };\n\n const data = {\n summaries: (await telemetryStore.getCrossTenantSummaries(opts)).items,\n failurePatterns: (await telemetryStore.getCrossTenantFailurePatterns(opts)).items,\n stats: await telemetryStore.getCrossTenantAggregateStats({ tenantId, days }),\n resolutionOutcomes: (await telemetryStore.getCrossTenantResolutionOutcomes(opts)).items,\n suggestionOutcomes: (await telemetryStore.getCrossTenantSuggestionOutcomes(opts)).items,\n };\n\n if (format === \"md\") {\n const md = generateDebugTelemetryReport({ ...data, days });\n return new Response(md, {\n headers: { \"Content-Type\": \"text/markdown; charset=utf-8\" },\n });\n }\n return c.json(data);\n });\n\n return app;\n}\n\n/** プロバイダー固有の LanguageModel を生成(接続テスト用) */\nasync function createTestModel(\n providerId: string,\n modelId: string,\n config: Record<string, string>,\n) {\n switch (providerId) {\n case \"anthropic\": {\n const { createAnthropic } = await import(\"@ai-sdk/anthropic\");\n return createAnthropic({ apiKey: config.ANTHROPIC_API_KEY })(modelId);\n }\n case \"openai\": {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({ apiKey: config.OPENAI_API_KEY })(modelId);\n }\n case \"openai-compatible\": {\n const { createOpenAICompatible } = await import(\"@ai-sdk/openai-compatible\");\n return createOpenAICompatible({\n name: \"openai-compatible\",\n baseURL: config.OPENAI_COMPATIBLE_BASE_URL,\n apiKey: config.OPENAI_COMPATIBLE_API_KEY,\n })(modelId);\n }\n case \"google\": {\n const { createGoogleGenerativeAI } = await import(\"@ai-sdk/google\");\n return createGoogleGenerativeAI({ apiKey: config.GOOGLE_GENERATIVE_AI_API_KEY })(modelId);\n }\n case \"azure\": {\n const { createAzure } = await import(\"@ai-sdk/azure\");\n return createAzure({\n resourceName: config.AZURE_RESOURCE_NAME,\n apiKey: config.AZURE_API_KEY,\n apiVersion: config.AZURE_API_VERSION,\n })(modelId);\n }\n case \"bedrock\": {\n const { createAmazonBedrock } = await import(\"@ai-sdk/amazon-bedrock\");\n return createAmazonBedrock({\n region: config.AWS_REGION,\n accessKeyId: config.AWS_ACCESS_KEY_ID,\n secretAccessKey: config.AWS_SECRET_ACCESS_KEY,\n })(modelId);\n }\n case \"vertex\": {\n const { createVertex } = await import(\"@ai-sdk/google-vertex\");\n return createVertex({\n project: config.GOOGLE_VERTEX_PROJECT,\n location: config.GOOGLE_VERTEX_LOCATION,\n })(modelId);\n }\n default:\n throw new Error(`Unsupported provider: ${providerId}`);\n }\n}\n","/**\n * デバッグテレメトリレポート生成\n *\n * テナント横断のテレメトリデータから改善分析用 Markdown レポートを生成。\n */\n\nimport type { AggregateStats } from \"./types.js\";\n\n/** getCrossTenantSummaries の返り値の要素型 */\ninterface CrossTenantSummary {\n summary: {\n id: string;\n tenantId: string;\n jobId: string;\n runbookId: string | null;\n mode: string | null;\n totalSteps: number | null;\n succeededSteps: number | null;\n failedSteps: number | null;\n totalDurationMs: number | null;\n aiEstimatedCostUsd: number | null;\n modelId: string | null;\n createdAt: Date | null;\n [key: string]: unknown;\n };\n tenantName: string | null;\n tenantSlug: string | null;\n}\n\ninterface CrossTenantFailurePattern {\n pattern: {\n urlPattern: string;\n selectorHint: string;\n failureCategory: string;\n occurrenceCount: number | null;\n lastErrorMessage: string | null;\n successfulRecoveries: unknown;\n lastRecoveryMethod: string | null;\n [key: string]: unknown;\n };\n tenantName: string | null;\n tenantSlug: string | null;\n}\n\ninterface CrossTenantResolutionOutcome {\n outcome: {\n resolveMethod: string | null;\n status: string | null;\n retryCount: number | null;\n durationMs: number | null;\n deterministicMatchType: string | null;\n deterministicConfidence: number | null;\n contextChunksUsed: number | null;\n failureHintsProvided: boolean | null;\n [key: string]: unknown;\n };\n tenantName: string | null;\n tenantSlug: string | null;\n}\n\ninterface CrossTenantSuggestionOutcome {\n suggestion: {\n failureCategory: string | null;\n suggestedStrategy: string | null;\n applied: boolean | null;\n verificationSuccess: boolean | null;\n [key: string]: unknown;\n };\n tenantName: string | null;\n tenantSlug: string | null;\n}\n\ninterface PerTenantBreakdown {\n tenantId: string;\n tenantName: string | null;\n totalJobs: number;\n successRate: number;\n aiCostUsd: number;\n}\n\nexport interface DebugReportData {\n summaries: CrossTenantSummary[];\n failurePatterns: CrossTenantFailurePattern[];\n stats: AggregateStats & { perTenantBreakdown: PerTenantBreakdown[] };\n resolutionOutcomes: CrossTenantResolutionOutcome[];\n suggestionOutcomes: CrossTenantSuggestionOutcome[];\n days: number;\n}\n\n/** テナント横断テレメトリの Markdown レポートを生成 */\nexport function generateDebugTelemetryReport(data: DebugReportData): string {\n const lines: string[] = [];\n\n lines.push(\"# テレメトリ分析レポート\");\n lines.push(\"\");\n lines.push(`期間: 直近 ${data.days} 日間`);\n lines.push(`生成日時: ${new Date().toISOString()}`);\n lines.push(\"\");\n\n // 概要\n appendOverview(lines, data.stats);\n\n // テナント別サマリー\n appendTenantBreakdown(lines, data.stats.perTenantBreakdown);\n\n // 頻出失敗パターン\n appendFailurePatterns(lines, data.failurePatterns);\n\n // 解決戦略の有効性\n appendResolutionAnalysis(lines, data.resolutionOutcomes);\n\n // 決定論的リゾルバ分析\n appendDeterministicAnalysis(lines, data.resolutionOutcomes);\n\n // Fallback 分析\n appendFallbackAnalysis(lines, data.stats);\n\n // Self-heal 提案効果\n appendSuggestionAnalysis(lines, data.suggestionOutcomes);\n\n // コンテキストチャンク効果\n appendContextAnalysis(lines, data.resolutionOutcomes);\n\n // 改善提案\n appendRecommendations(lines, data);\n\n return lines.join(\"\\n\");\n}\n\nfunction appendOverview(lines: string[], stats: AggregateStats): void {\n lines.push(\"## 概要\");\n lines.push(\"\");\n lines.push(`| 指標 | 値 |`);\n lines.push(`|------|-----|`);\n lines.push(`| 総ジョブ数 | ${stats.totalJobs} |`);\n lines.push(`| 総ステップ数 | ${stats.totalSteps} |`);\n lines.push(`| 全体成功率 | ${pct(stats.overallSuccessRate)} |`);\n lines.push(`| 平均リトライ数 | ${stats.avgRetryCount.toFixed(1)} |`);\n lines.push(`| AI コスト合計 | $${stats.aiTotalCostUsd.toFixed(4)} |`);\n lines.push(`| Vision Fallback 成功率 | ${pct(stats.visionFallbackSuccessRate)} |`);\n lines.push(`| Agent Fallback 成功率 | ${pct(stats.agentFallbackSuccessRate)} |`);\n lines.push(\"\");\n}\n\nfunction appendTenantBreakdown(lines: string[], breakdown: PerTenantBreakdown[]): void {\n if (breakdown.length === 0) return;\n lines.push(\"## テナント別サマリー\");\n lines.push(\"\");\n lines.push(\"| テナント | ジョブ数 | 成功率 | AI コスト |\");\n lines.push(\"|----------|---------|--------|----------|\");\n for (const t of breakdown) {\n lines.push(`| ${t.tenantName ?? t.tenantId} | ${t.totalJobs} | ${pct(t.successRate)} | $${t.aiCostUsd.toFixed(4)} |`);\n }\n lines.push(\"\");\n}\n\nfunction appendFailurePatterns(lines: string[], patterns: CrossTenantFailurePattern[]): void {\n if (patterns.length === 0) return;\n lines.push(\"## 頻出失敗パターン Top 20\");\n lines.push(\"\");\n lines.push(\"| # | テナント | URL パターン | セレクタ | カテゴリ | 出現数 | 最終回復 |\");\n lines.push(\"|---|----------|-------------|---------|---------|--------|---------|\");\n const top = patterns.slice(0, 20);\n for (let i = 0; i < top.length; i++) {\n const p = top[i];\n const occ = p.pattern.occurrenceCount ?? 0;\n lines.push(`| ${i + 1} | ${p.tenantName ?? \"-\"} | \\`${truncate(p.pattern.urlPattern, 30)}\\` | \\`${truncate(p.pattern.selectorHint, 25)}\\` | ${p.pattern.failureCategory} | ${occ} | ${p.pattern.lastRecoveryMethod ?? \"-\"} |`);\n }\n lines.push(\"\");\n}\n\nfunction appendResolutionAnalysis(lines: string[], outcomes: CrossTenantResolutionOutcome[]): void {\n if (outcomes.length === 0) return;\n lines.push(\"## 解決戦略の有効性\");\n lines.push(\"\");\n\n const methodStats = new Map<string, { total: number; success: number; retrySum: number; durationSum: number }>();\n for (const o of outcomes) {\n const method = o.outcome.resolveMethod ?? \"(none)\";\n const existing = methodStats.get(method) ?? { total: 0, success: 0, retrySum: 0, durationSum: 0 };\n existing.total++;\n if (o.outcome.status === \"success\") existing.success++;\n existing.retrySum += o.outcome.retryCount ?? 0;\n existing.durationSum += o.outcome.durationMs ?? 0;\n methodStats.set(method, existing);\n }\n\n lines.push(\"| 解決方法 | 使用数 | 成功率 | 平均リトライ | 平均所要時間 |\");\n lines.push(\"|---------|--------|--------|------------|------------|\");\n const sorted = [...methodStats.entries()].sort((a, b) => b[1].total - a[1].total);\n for (const [method, s] of sorted) {\n lines.push(`| ${method} | ${s.total} | ${pct(s.total > 0 ? s.success / s.total : 0)} | ${(s.retrySum / s.total).toFixed(1)} | ${Math.round(s.durationSum / s.total)}ms |`);\n }\n lines.push(\"\");\n}\n\nfunction appendDeterministicAnalysis(lines: string[], outcomes: CrossTenantResolutionOutcome[]): void {\n const withMatch = outcomes.filter((o) => o.outcome.deterministicMatchType);\n if (withMatch.length === 0) return;\n\n lines.push(\"## 決定論的リゾルバ分析\");\n lines.push(\"\");\n\n const matchStats = new Map<string, { total: number; success: number; confidenceSum: number }>();\n for (const o of withMatch) {\n const mt = o.outcome.deterministicMatchType!;\n const existing = matchStats.get(mt) ?? { total: 0, success: 0, confidenceSum: 0 };\n existing.total++;\n if (o.outcome.status === \"success\") existing.success++;\n existing.confidenceSum += o.outcome.deterministicConfidence ?? 0;\n matchStats.set(mt, existing);\n }\n\n lines.push(\"| マッチタイプ | 使用数 | 成功率 | 平均 Confidence |\");\n lines.push(\"|------------|--------|--------|----------------|\");\n const sorted = [...matchStats.entries()].sort((a, b) => b[1].total - a[1].total);\n for (const [mt, s] of sorted) {\n lines.push(`| ${mt} | ${s.total} | ${pct(s.total > 0 ? s.success / s.total : 0)} | ${(s.confidenceSum / s.total).toFixed(2)} |`);\n }\n lines.push(\"\");\n}\n\nfunction appendFallbackAnalysis(lines: string[], stats: AggregateStats): void {\n lines.push(\"## Fallback 分析\");\n lines.push(\"\");\n lines.push(\"| Fallback | 成功率 |\");\n lines.push(\"|----------|--------|\");\n lines.push(`| Vision | ${pct(stats.visionFallbackSuccessRate)} |`);\n lines.push(`| Agent | ${pct(stats.agentFallbackSuccessRate)} |`);\n lines.push(\"\");\n}\n\nfunction appendSuggestionAnalysis(lines: string[], suggestions: CrossTenantSuggestionOutcome[]): void {\n if (suggestions.length === 0) return;\n lines.push(\"## Self-heal 提案効果\");\n lines.push(\"\");\n\n const catStats = new Map<string, { total: number; applied: number; verifiedSuccess: number; verifiedFail: number }>();\n for (const s of suggestions) {\n const cat = s.suggestion.failureCategory ?? \"(unknown)\";\n const existing = catStats.get(cat) ?? { total: 0, applied: 0, verifiedSuccess: 0, verifiedFail: 0 };\n existing.total++;\n if (s.suggestion.applied) existing.applied++;\n if (s.suggestion.verificationSuccess === true) existing.verifiedSuccess++;\n if (s.suggestion.verificationSuccess === false) existing.verifiedFail++;\n catStats.set(cat, existing);\n }\n\n lines.push(\"| カテゴリ | 提案数 | 適用数 | 検証成功 | 検証失敗 |\");\n lines.push(\"|---------|--------|--------|---------|---------|\");\n for (const [cat, s] of catStats) {\n lines.push(`| ${cat} | ${s.total} | ${s.applied} | ${s.verifiedSuccess} | ${s.verifiedFail} |`);\n }\n lines.push(\"\");\n}\n\nfunction appendContextAnalysis(lines: string[], outcomes: CrossTenantResolutionOutcome[]): void {\n if (outcomes.length === 0) return;\n lines.push(\"## コンテキストチャンク効果\");\n lines.push(\"\");\n\n const chunkStats = new Map<number, { total: number; success: number }>();\n for (const o of outcomes) {\n const chunks = o.outcome.contextChunksUsed ?? 0;\n const existing = chunkStats.get(chunks) ?? { total: 0, success: 0 };\n existing.total++;\n if (o.outcome.status === \"success\") existing.success++;\n chunkStats.set(chunks, existing);\n }\n\n lines.push(\"| チャンク数 | ステップ数 | 成功率 |\");\n lines.push(\"|-----------|-----------|--------|\");\n const sorted = [...chunkStats.entries()].sort((a, b) => a[0] - b[0]);\n for (const [chunks, s] of sorted) {\n lines.push(`| ${chunks} | ${s.total} | ${pct(s.total > 0 ? s.success / s.total : 0)} |`);\n }\n lines.push(\"\");\n\n // FailureRegistry ヒント効果\n const hintYes = outcomes.filter((o) => o.outcome.failureHintsProvided);\n const hintNo = outcomes.filter((o) => !o.outcome.failureHintsProvided);\n const hintYesSuccess = hintYes.filter((o) => o.outcome.status === \"success\").length;\n const hintNoSuccess = hintNo.filter((o) => o.outcome.status === \"success\").length;\n\n if (hintYes.length > 0) {\n lines.push(\"**FailureRegistry ヒント注入効果:**\");\n lines.push(`- ヒントあり: ${hintYes.length} ステップ, 成功率 ${pct(hintYes.length > 0 ? hintYesSuccess / hintYes.length : 0)}`);\n lines.push(`- ヒントなし: ${hintNo.length} ステップ, 成功率 ${pct(hintNo.length > 0 ? hintNoSuccess / hintNo.length : 0)}`);\n lines.push(\"\");\n }\n}\n\nfunction appendRecommendations(lines: string[], data: DebugReportData): void {\n const recommendations: string[] = [];\n\n // 高頻度失敗パターンの警告\n for (const p of data.failurePatterns.slice(0, 5)) {\n const occ = p.pattern.occurrenceCount ?? 0;\n if (occ >= 3) {\n recommendations.push(\n `- **${p.pattern.failureCategory}** が \\`${truncate(p.pattern.urlPattern, 40)}\\` + \\`${truncate(p.pattern.selectorHint, 30)}\\` で ${occ} 回発生 → ランブック修正推奨`,\n );\n }\n }\n\n // 低成功率の解決メソッド\n const methodStats = new Map<string, { total: number; success: number }>();\n for (const o of data.resolutionOutcomes) {\n const method = o.outcome.resolveMethod ?? \"(none)\";\n const existing = methodStats.get(method) ?? { total: 0, success: 0 };\n existing.total++;\n if (o.outcome.status === \"success\") existing.success++;\n methodStats.set(method, existing);\n }\n for (const [method, s] of methodStats) {\n if (s.total >= 5 && s.success / s.total < 0.5) {\n recommendations.push(\n `- 解決メソッド **${method}** の成功率が ${pct(s.success / s.total)} と低い(${s.total} 件中 ${s.success} 件成功)→ 戦略見直し推奨`,\n );\n }\n }\n\n // 全体成功率が低い場合\n if (data.stats.totalSteps > 10 && data.stats.overallSuccessRate < 0.8) {\n recommendations.push(\n `- 全体成功率 ${pct(data.stats.overallSuccessRate)} — 失敗カテゴリ分布を確認し、主要な原因に対処推奨`,\n );\n }\n\n if (recommendations.length === 0) return;\n lines.push(\"## 改善提案\");\n lines.push(\"\");\n for (const r of recommendations) {\n lines.push(r);\n }\n lines.push(\"\");\n}\n\n// ── ジョブ単体レポート ──\n\nexport interface JobReportStepResult {\n ordinal: number;\n description: string;\n status: string;\n durationMs: number;\n error: string | null;\n actionType: string | null;\n retryCount: number | null;\n failureCategory: string | null;\n capturedValues: unknown;\n conditionSkipped: boolean | null;\n loopIterations: number | null;\n branchMatch: string | null;\n forEachItemCount: number | null;\n extractedData: string | null;\n downloadedFile: string | null;\n exportedFile: string | null;\n diagnostics: {\n lastSnapshotPreview: string | null;\n failureHistory: unknown;\n lastAiResponseText: string | null;\n recoveryHint: string | null;\n deterministicResolveResult: string | null;\n visionFallbackResult: unknown;\n agentFallbackResult: unknown;\n validationWarnings: unknown;\n validationErrors: unknown;\n stepUrl: string | null;\n } | null;\n}\n\nexport interface JobReportAiMetrics {\n totalCalls: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCachedInputTokens: number;\n totalCacheCreationTokens: number;\n cacheHitRate: number;\n estimatedCostUsd: number;\n totalDurationMs: number;\n}\n\nexport interface JobReportData {\n summary: {\n summary: {\n jobId: string;\n mode: string | null;\n totalSteps: number | null;\n succeededSteps: number | null;\n failedSteps: number | null;\n skippedSteps: number | null;\n aborted: boolean | null;\n totalDurationMs: number | null;\n aiEstimatedCostUsd: number | null;\n modelId: string | null;\n modelProvider: string | null;\n runbookId: string | null;\n createdAt: Date | null;\n [key: string]: unknown;\n };\n tenantName: string | null;\n tenantSlug: string | null;\n } | null;\n failureEvents: Array<Record<string, unknown>>;\n resolutionOutcomes: Array<Record<string, unknown>>;\n suggestionOutcomes: Array<Record<string, unknown>>;\n stepResults?: JobReportStepResult[];\n aiMetrics?: JobReportAiMetrics | null;\n}\n\n/** ジョブ単体テレメトリの Markdown レポートを生成 */\nexport function generateJobTelemetryReport(data: JobReportData): string {\n const lines: string[] = [];\n const s = data.summary?.summary;\n if (!s) return \"# ジョブテレメトリレポート\\n\\nデータなし\\n\";\n\n lines.push(`# ジョブテレメトリレポート — ${s.jobId}`);\n lines.push(\"\");\n lines.push(`生成日時: ${new Date().toISOString()}`);\n lines.push(\"\");\n\n // 概要\n lines.push(\"## 概要\");\n lines.push(\"\");\n lines.push(\"| 項目 | 値 |\");\n lines.push(\"|------|-----|\");\n lines.push(`| テナント | ${data.summary?.tenantName ?? \"-\"} |`);\n lines.push(`| モード | ${s.mode ?? \"-\"} |`);\n lines.push(`| モデル | ${s.modelId ?? \"-\"} (${s.modelProvider ?? \"-\"}) |`);\n lines.push(`| 総ステップ | ${s.totalSteps ?? 0} |`);\n lines.push(`| 成功 | ${s.succeededSteps ?? 0} |`);\n lines.push(`| 失敗 | ${s.failedSteps ?? 0} |`);\n lines.push(`| スキップ | ${s.skippedSteps ?? 0} |`);\n lines.push(`| 中断 | ${s.aborted ? \"Yes\" : \"No\"} |`);\n lines.push(`| 所要時間 | ${s.totalDurationMs != null ? `${(s.totalDurationMs / 1000).toFixed(1)}s` : \"-\"} |`);\n lines.push(`| AI コスト | ${s.aiEstimatedCostUsd != null ? `$${s.aiEstimatedCostUsd.toFixed(4)}` : \"-\"} |`);\n lines.push(`| ランブック ID | ${s.runbookId ?? \"-\"} |`);\n lines.push(`| 作成日時 | ${s.createdAt ? new Date(s.createdAt).toISOString() : \"-\"} |`);\n lines.push(\"\");\n\n // 全ステップ結果\n appendStepResults(lines, data.stepResults);\n\n // リトライ詳細\n appendRetryDetails(lines, data.stepResults);\n\n // 失敗イベント\n if (data.failureEvents.length > 0) {\n lines.push(\"## 失敗イベント\");\n lines.push(\"\");\n lines.push(\"| Step | カテゴリ | セレクタ | URL | エラーメッセージ | 解決方法 | リトライ数 |\");\n lines.push(\"|------|---------|---------|-----|----------------|---------|-----------|\");\n for (const e of data.failureEvents) {\n const step = e.step_ordinal ?? e.stepOrdinal ?? \"-\";\n const cat = e.failure_category ?? e.failureCategory ?? \"-\";\n const sel = truncate(String(e.selector_hint ?? e.selectorHint ?? \"-\"), 25);\n const url = truncate(String(e.url_pattern ?? e.urlPattern ?? \"-\"), 30);\n const msg = truncate(String(e.error_message ?? e.errorMessage ?? \"-\"), 40);\n const resolve = e.resolve_method ?? e.resolveMethod ?? \"-\";\n const retries = e.retry_count ?? e.retryCount ?? 0;\n lines.push(`| ${step} | ${cat} | \\`${sel}\\` | \\`${url}\\` | ${msg} | ${resolve} | ${retries} |`);\n }\n lines.push(\"\");\n }\n\n // 解決結果\n if (data.resolutionOutcomes.length > 0) {\n lines.push(\"## 解決結果\");\n lines.push(\"\");\n lines.push(\"| Step | メソッド | マッチタイプ | ステータス | リトライ | 所要時間 |\");\n lines.push(\"|------|---------|------------|----------|---------|---------|\");\n for (const o of data.resolutionOutcomes) {\n const step = o.step_ordinal ?? o.stepOrdinal ?? \"-\";\n const method = o.resolve_method ?? o.resolveMethod ?? \"-\";\n const matchType = o.deterministic_match_type ?? o.deterministicMatchType ?? \"-\";\n const status = o.status ?? \"-\";\n const retries = o.retry_count ?? o.retryCount ?? 0;\n const dur = o.duration_ms ?? o.durationMs;\n lines.push(`| ${step} | ${method} | ${matchType} | ${status} | ${retries} | ${dur != null ? `${dur}ms` : \"-\"} |`);\n }\n lines.push(\"\");\n }\n\n // AI メトリクス詳細\n appendAiMetrics(lines, data.aiMetrics);\n\n // 提案\n if (data.suggestionOutcomes.length > 0) {\n lines.push(\"## 提案\");\n lines.push(\"\");\n lines.push(\"| カテゴリ | 戦略 | 適用 | 検証結果 | ランブック修正 |\");\n lines.push(\"|---------|------|------|---------|--------------|\");\n for (const sg of data.suggestionOutcomes) {\n const cat = sg.failure_category ?? sg.failureCategory ?? \"-\";\n const strategy = sg.suggested_strategy ?? sg.suggestedStrategy ?? \"-\";\n const applied = (sg.applied ?? false) ? \"Yes\" : \"No\";\n const verified = sg.verification_success ?? sg.verificationSuccess;\n const verifiedStr = verified === true ? \"Pass\" : verified === false ? \"Fail\" : \"-\";\n const fix = truncate(String(sg.runbook_fix ?? sg.runbookFix ?? \"-\"), 40);\n lines.push(`| ${cat} | ${strategy} | ${applied} | ${verifiedStr} | ${fix} |`);\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n// ── ジョブ単体レポート追加セクション ──\n\nfunction appendStepResults(lines: string[], stepResults?: JobReportStepResult[]): void {\n if (!stepResults || stepResults.length === 0) return;\n\n lines.push(\"## 全ステップ結果\");\n lines.push(\"\");\n lines.push(\"| # | 説明 | ステータス | アクション | 所要時間 | リトライ | 失敗カテゴリ | 備考 |\");\n lines.push(\"|---|------|----------|----------|---------|---------|------------|------|\");\n for (const r of stepResults) {\n const notes = buildStepNotes(r);\n const statusIcon = r.status === \"success\" ? \"✅\" : r.status === \"failed\" ? \"❌\" : \"⏭️\";\n lines.push(\n `| ${r.ordinal} | ${truncate(r.description, 40)} | ${statusIcon} ${r.status} | ${r.actionType ?? \"-\"} | ${formatMs(r.durationMs)} | ${r.retryCount ?? 0} | ${r.failureCategory ?? \"-\"} | ${notes} |`,\n );\n }\n lines.push(\"\");\n}\n\nfunction buildStepNotes(r: JobReportStepResult): string {\n const parts: string[] = [];\n if (r.conditionSkipped) parts.push(\"condition-skipped\");\n if (r.branchMatch) parts.push(`branch: ${r.branchMatch}`);\n if (r.loopIterations != null) parts.push(`loop: ${r.loopIterations}回`);\n if (r.forEachItemCount != null) parts.push(`forEach: ${r.forEachItemCount}件`);\n if (r.capturedValues) parts.push(\"captured\");\n if (r.extractedData) parts.push(\"extracted\");\n if (r.downloadedFile) parts.push(\"downloaded\");\n if (r.exportedFile) parts.push(\"exported\");\n return parts.length > 0 ? parts.join(\", \") : \"-\";\n}\n\nfunction appendRetryDetails(lines: string[], stepResults?: JobReportStepResult[]): void {\n if (!stepResults) return;\n const failedWithDiag = stepResults.filter((r) => r.status === \"failed\" && r.diagnostics);\n if (failedWithDiag.length === 0) return;\n\n lines.push(\"## リトライ詳細(失敗ステップ)\");\n lines.push(\"\");\n\n for (const r of failedWithDiag) {\n const d = r.diagnostics!;\n lines.push(`### Step ${r.ordinal}: ${r.description}`);\n lines.push(\"\");\n if (r.error) lines.push(`- **エラー**: ${truncate(r.error, 120)}`);\n if (d.stepUrl) lines.push(`- **URL**: ${d.stepUrl}`);\n if (d.recoveryHint) lines.push(`- **Recovery Hint**: ${d.recoveryHint}`);\n lines.push(\"\");\n\n // Failure History\n if (d.failureHistory && Array.isArray(d.failureHistory) && d.failureHistory.length > 0) {\n lines.push(\"**Failure History:**\");\n for (let i = 0; i < d.failureHistory.length; i++) {\n const reason = typeof d.failureHistory[i] === \"string\"\n ? d.failureHistory[i]\n : JSON.stringify(d.failureHistory[i]);\n lines.push(`${i + 1}. ${truncate(String(reason), 120)}`);\n }\n lines.push(\"\");\n }\n\n // Last AI Response\n if (d.lastAiResponseText) {\n lines.push(\"**Last AI Response** (truncated):\");\n lines.push(`> ${truncate(d.lastAiResponseText.replace(/\\n/g, \" \"), 300)}`);\n lines.push(\"\");\n }\n\n // Snapshot Preview\n if (d.lastSnapshotPreview) {\n lines.push(\"**Snapshot Preview** (truncated):\");\n lines.push(\"```\");\n lines.push(truncate(d.lastSnapshotPreview, 500));\n lines.push(\"```\");\n lines.push(\"\");\n }\n\n // Deterministic Resolve\n if (d.deterministicResolveResult) {\n lines.push(`- **Deterministic Resolve**: ${truncate(d.deterministicResolveResult, 100)}`);\n }\n\n // Vision Fallback\n if (d.visionFallbackResult && typeof d.visionFallbackResult === \"object\") {\n const v = d.visionFallbackResult as Record<string, unknown>;\n lines.push(`- **Vision Fallback**: success=${v.success ?? \"-\"}, annotations=${v.annotationCount ?? \"-\"}`);\n if (v.reasoning) lines.push(` > ${truncate(String(v.reasoning), 200)}`);\n }\n\n // Agent Fallback\n if (d.agentFallbackResult && typeof d.agentFallbackResult === \"object\") {\n const a = d.agentFallbackResult as Record<string, unknown>;\n lines.push(`- **Agent Fallback**: strategy=${a.strategy ?? \"-\"}, success=${a.success ?? \"-\"}`);\n if (a.reasoning) lines.push(` > ${truncate(String(a.reasoning), 200)}`);\n }\n\n // Validation\n if (d.validationWarnings && Array.isArray(d.validationWarnings) && d.validationWarnings.length > 0) {\n lines.push(`- **Validation Warnings**: ${d.validationWarnings.map(String).join(\", \")}`);\n }\n if (d.validationErrors && Array.isArray(d.validationErrors) && d.validationErrors.length > 0) {\n lines.push(`- **Validation Errors**: ${d.validationErrors.map(String).join(\", \")}`);\n }\n\n lines.push(\"\");\n }\n}\n\nfunction appendAiMetrics(lines: string[], aiMetrics?: JobReportAiMetrics | null): void {\n if (!aiMetrics) return;\n\n lines.push(\"## AI メトリクス詳細\");\n lines.push(\"\");\n lines.push(\"| 指標 | 値 |\");\n lines.push(\"|------|-----|\");\n lines.push(`| API コール数 | ${aiMetrics.totalCalls.toLocaleString()} |`);\n lines.push(`| Input トークン | ${aiMetrics.totalInputTokens.toLocaleString()} |`);\n lines.push(`| Output トークン | ${aiMetrics.totalOutputTokens.toLocaleString()} |`);\n lines.push(`| Cached Input トークン | ${aiMetrics.totalCachedInputTokens.toLocaleString()} |`);\n lines.push(`| Cache Creation トークン | ${aiMetrics.totalCacheCreationTokens.toLocaleString()} |`);\n lines.push(`| キャッシュヒット率 | ${pct(aiMetrics.cacheHitRate)} |`);\n lines.push(`| 推定コスト | $${aiMetrics.estimatedCostUsd.toFixed(4)} |`);\n lines.push(`| 総 AI 所要時間 | ${formatMs(aiMetrics.totalDurationMs)} |`);\n if (aiMetrics.totalCalls > 0) {\n lines.push(`| 平均レイテンシ/コール | ${formatMs(Math.round(aiMetrics.totalDurationMs / aiMetrics.totalCalls))} |`);\n }\n lines.push(\"\");\n}\n\nfunction formatMs(ms: number): string {\n if (ms >= 60000) return `${(ms / 60000).toFixed(1)}m`;\n if (ms >= 1000) return `${(ms / 1000).toFixed(1)}s`;\n return `${ms}ms`;\n}\n\n// ── ヘルパー ──\n\nfunction pct(rate: number): string {\n return `${(rate * 100).toFixed(1)}%`;\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max)}...` : s;\n}\n","/**\n * 設定 API Zod バリデーション\n */\n\nimport { z } from \"zod\";\n\nconst platformCredentialsSchema = z.record(z.string(), z.string().optional()).optional();\n\nconst notificationCredentialsSchema = z.object({\n slack: platformCredentialsSchema,\n teams: platformCredentialsSchema,\n discord: platformCredentialsSchema,\n}).nullable().optional();\n\nexport const executionConfigSchema = z.object({\n stealth: z.boolean(),\n proxy: z.string().nullable().optional(),\n approvalMode: z.enum([\"web\", \"slack\", \"teams\", \"discord\"]),\n notifyMode: z.enum([\"slack\", \"teams\", \"discord\"]).nullable().optional(),\n enableSelectorCache: z.boolean(),\n enableAgentFallback: z.boolean(),\n enableVisionFallback: z.boolean(),\n enableScreenshots: z.boolean(),\n enableVideoRecording: z.boolean(),\n skills: z.array(z.string()),\n apiKey: z.string().nullable().optional(),\n notificationCredentials: notificationCredentialsSchema,\n});\n\nexport type ExecutionConfigInput = z.infer<typeof executionConfigSchema>;\n\nexport const providerSchema = z.object({\n id: z.enum([\n \"anthropic\",\n \"openai\",\n \"openai-compatible\",\n \"google\",\n \"azure\",\n \"bedrock\",\n \"vertex\",\n ]),\n connected: z.union([z.boolean(), z.literal(\"pending\")]),\n modelId: z.string(),\n configFields: z.array(\n z.object({\n key: z.string(),\n label: z.string(),\n value: z.string().optional(),\n sensitive: z.boolean().optional(),\n required: z.boolean().optional(),\n placeholder: z.string().optional(),\n type: z.enum([\"text\", \"file\"]).optional(),\n }),\n ),\n});\n\nexport const modelOverrideSchema = z.object({\n purpose: z.enum([\n \"selector\",\n \"extraction\",\n \"exploration\",\n \"exploration-light\",\n \"review\",\n \"fallback\",\n \"vision\",\n ]),\n description: z.string(),\n modelId: z.string(),\n});\n\nexport const modelsConfigSchema = z.object({\n providers: z.array(providerSchema),\n overrides: z.array(modelOverrideSchema),\n});\n\nexport type ModelsConfigInput = z.infer<typeof modelsConfigSchema>;\n\nexport const overridesConfigSchema = z.object({\n overrides: z.array(modelOverrideSchema),\n});\n\nexport const teamPatchSchema = z.object({\n name: z.string().min(1).optional(),\n locale: z.enum([\"en\", \"ja\"]).optional(),\n});\n\nexport type TeamPatchInput = z.infer<typeof teamPatchSchema>;\n","/**\n * Usage API ハンドラ\n *\n * 当月使用量 + プラン上限を返す。\n */\n\nimport { Hono } from \"hono\";\nimport type { AppVariables } from \"../middleware/types.js\";\nimport { MeteringStore } from \"../store/metering-store.js\";\nimport type { getDb } from \"../db/client.js\";\n\nexport function createUsageHandlers(db: ReturnType<typeof getDb>) {\n const app = new Hono<{ Variables: AppVariables }>();\n const meteringStore = new MeteringStore(db);\n\n // GET /api/v1/usage — 当月使用量\n app.get(\"/\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) {\n return c.json({ error: \"Tenant required\" }, 400);\n }\n\n const plan = c.get(\"plan\");\n const usage = await meteringStore.getCurrentUsage(tenantId);\n\n return c.json({\n month: usage.month,\n usage: {\n jobCount: usage.jobCount,\n stepCount: usage.stepCount,\n },\n limits: {\n maxMonthlyJobs: plan.limits.maxMonthlyJobs,\n maxMonthlySteps: plan.limits.maxMonthlySteps,\n },\n tier: plan.tier,\n });\n });\n\n return app;\n}\n","/**\n * テレメトリ API ハンドラ\n *\n * テレメトリデータの読み取りエンドポイント。\n */\n\nimport { Hono } from \"hono\";\nimport type { AppVariables } from \"../middleware/types.js\";\nimport { requireRole } from \"../middleware/rbac.js\";\nimport { TelemetryStore } from \"../store/telemetry-store.js\";\nimport type { getDb } from \"../db/client.js\";\n\n/** 安全な正の整数パース(NaN → undefined) */\nfunction safeInt(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? Math.floor(n) : undefined;\n}\n\n/** 安全な日付パース(Invalid Date → undefined) */\nfunction safeDate(value: string | undefined): Date | undefined {\n if (!value) return undefined;\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? undefined : d;\n}\n\nexport function createTelemetryHandlers(db: ReturnType<typeof getDb>) {\n const app = new Hono<{ Variables: AppVariables }>();\n const store = new TelemetryStore(db);\n\n // admin 以上のみアクセス可(一般ユーザーにはテレメトリを非公開)\n app.use(\"*\", requireRole(\"admin\"));\n\n // GET /api/v1/telemetry/summaries\n app.get(\"/summaries\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: \"Tenant required\" }, 400);\n\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const days = safeInt(c.req.query(\"days\"));\n const limit = safeInt(c.req.query(\"limit\"));\n\n const items = await store.getRecentSummaries(tenantId, { runbookId, days, limit });\n return c.json({ items });\n });\n\n // GET /api/v1/telemetry/failure-events\n app.get(\"/failure-events\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: \"Tenant required\" }, 400);\n\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const category = c.req.query(\"category\") || undefined;\n const urlPattern = c.req.query(\"urlPattern\") || undefined;\n const limit = safeInt(c.req.query(\"limit\"));\n\n const items = await store.getFailureEvents(tenantId, { runbookId, category, urlPattern, limit });\n return c.json({ items });\n });\n\n // GET /api/v1/telemetry/resolution-outcomes\n app.get(\"/resolution-outcomes\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: \"Tenant required\" }, 400);\n\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const resolveMethod = c.req.query(\"resolveMethod\") || undefined;\n const matchType = c.req.query(\"matchType\") || undefined;\n const limit = safeInt(c.req.query(\"limit\"));\n\n const items = await store.getResolutionOutcomes(tenantId, { runbookId, resolveMethod, matchType, limit });\n return c.json({ items });\n });\n\n // GET /api/v1/telemetry/failure-patterns\n app.get(\"/failure-patterns\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: \"Tenant required\" }, 400);\n\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const category = c.req.query(\"category\") || undefined;\n const limit = safeInt(c.req.query(\"limit\"));\n\n const items = await store.getTopFailurePatterns(tenantId, { runbookId, category, limit });\n return c.json({ items });\n });\n\n // GET /api/v1/telemetry/suggestion-outcomes\n app.get(\"/suggestion-outcomes\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: \"Tenant required\" }, 400);\n\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const appliedParam = c.req.query(\"applied\");\n const applied = appliedParam !== undefined ? appliedParam === \"true\" : undefined;\n const limit = safeInt(c.req.query(\"limit\"));\n\n const items = await store.getSuggestionOutcomes(tenantId, { runbookId, applied, limit });\n return c.json({ items });\n });\n\n // GET /api/v1/telemetry/stats\n app.get(\"/stats\", async (c) => {\n const tenantId = c.get(\"tenantId\");\n if (!tenantId) return c.json({ error: \"Tenant required\" }, 400);\n\n const runbookId = c.req.query(\"runbookId\") || undefined;\n const fromDate = safeDate(c.req.query(\"fromDate\"));\n const toDate = safeDate(c.req.query(\"toDate\"));\n\n const stats = await store.getAggregateStats(tenantId, { runbookId, fromDate, toDate });\n return c.json(stats);\n });\n\n return app;\n}\n","/**\n * Slack interaction webhook ハンドラ\n *\n * Slack App の「Interactivity」で設定した Request URL:\n * POST https://<server>/api/webhooks/slack\n *\n * 承認カードのボタンクリック → Redis publish → ServerConfirmationProvider が受信。\n *\n * マルチテナント対応: payload を先にパースして jobId を特定し、\n * テナントごとの Signing Secret で署名検証する(parse-first, verify-second)。\n */\n\nimport { Hono } from \"hono\";\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { parseApprovalButtonId } from \"./approval-parser.js\";\nimport { resolveWebhookCredential, type WebhookDeps } from \"./credential-resolver.js\";\nimport { getRedisPublisher } from \"../redis.js\";\n\n/**\n * Slack interaction webhook ルートを生成。\n *\n * @param deps DB・暗号鍵・Redis URL(テナント別クレデンシャル解決用)\n */\nexport function createSlackWebhookRoute(deps: WebhookDeps) {\n const app = new Hono();\n\n app.post(\"/\", async (c) => {\n // 1. 署名ヘッダーチェック\n const timestamp = c.req.header(\"x-slack-request-timestamp\");\n const signature = c.req.header(\"x-slack-signature\");\n if (!timestamp || !signature) {\n return c.text(\"Missing signature headers\", 401);\n }\n\n // リプレイ攻撃防止: 5 分以上前のリクエストは拒否\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - Number(timestamp)) > 300) {\n return c.text(\"Request too old\", 401);\n }\n\n const rawBody = await c.req.text();\n\n // 2. payload パース(application/x-www-form-urlencoded)\n const params = new URLSearchParams(rawBody);\n const payloadStr = params.get(\"payload\");\n if (!payloadStr) {\n return c.text(\"Missing payload\", 400);\n }\n\n let payload: SlackInteractionPayload;\n try {\n payload = JSON.parse(payloadStr);\n } catch {\n return c.text(\"Invalid payload JSON\", 400);\n }\n\n // non-approval interaction → 検証不要で OK\n if (payload.type !== \"block_actions\" || !payload.actions?.length) {\n return c.text(\"OK\", 200);\n }\n\n const action = payload.actions[0];\n\n // 3. action_id からパース(複合 ID: \"rfn-approve:jobId:3\")\n const parsed = parseApprovalButtonId(action.action_id);\n if (!parsed) {\n return c.text(\"OK\", 200);\n }\n\n // 4. テナント別クレデンシャル解決\n const resolved = await resolveWebhookCredential(deps, parsed.jobId, \"slack\");\n if (!resolved?.credentials.SLACK_SIGNING_SECRET) {\n return c.text(\"Invalid webhook\", 401);\n }\n\n // 5. HMAC-SHA256 署名検証(テナントの Signing Secret で)\n const signingSecret = resolved.credentials.SLACK_SIGNING_SECRET;\n const baseString = `v0:${timestamp}:${rawBody}`;\n const expectedSig = `v0=${createHmac(\"sha256\", signingSecret).update(baseString).digest(\"hex\")}`;\n\n if (\n !timingSafeEqual(\n Buffer.from(signature, \"utf8\"),\n Buffer.from(expectedSig, \"utf8\"),\n )\n ) {\n return c.text(\"Invalid signature\", 401);\n }\n\n // 6. Redis publish\n const respondedBy = payload.user?.username ?? payload.user?.id;\n const redis = getRedisPublisher(deps.redisUrl);\n await redis.publish(\n `job:${parsed.jobId}:approval:${parsed.stepOrdinal}`,\n JSON.stringify({ action: parsed.action, respondedBy }),\n );\n\n // 7. 即座に 200 OK(Slack は 3 秒以内のレスポンスを要求)\n return c.text(\"OK\", 200);\n });\n\n return app;\n}\n\n// ── Slack Interaction Payload 型(必要最小限) ──\n\ninterface SlackInteractionPayload {\n type: string;\n actions?: Array<{\n action_id: string;\n value?: string;\n }>;\n user?: {\n id: string;\n username?: string;\n };\n}\n","/**\n * 共通承認ボタン ID パーサー\n *\n * 全プラットフォーム(Slack / Teams / Discord)共通で、\n * ボタン ID \"{actionId}:{jobId}:{stepOrdinal}\" をパースする。\n */\n\nconst ACTION_MAP: Record<string, \"approve\" | \"skip\" | \"abort\"> = {\n \"rfn-approve\": \"approve\",\n \"rfn-skip\": \"skip\",\n \"rfn-abort\": \"abort\",\n};\n\nexport interface ParsedApprovalButton {\n action: \"approve\" | \"skip\" | \"abort\";\n jobId: string;\n stepOrdinal: number;\n}\n\n/**\n * ボタン ID から承認アクション・jobId・stepOrdinal をパースする。\n *\n * フォーマット: \"{actionId}:{jobId}:{stepOrdinal}\"\n * 例: \"rfn-approve:cuid_abc123:5\"\n *\n * @returns パース結果。不正な形式の場合は null。\n */\nexport function parseApprovalButtonId(rawId: string): ParsedApprovalButton | null {\n for (const [prefix, action] of Object.entries(ACTION_MAP)) {\n if (rawId.startsWith(prefix + \":\")) {\n const rest = rawId.slice(prefix.length + 1);\n const colonIdx = rest.lastIndexOf(\":\");\n if (colonIdx === -1) return null;\n const jobId = rest.slice(0, colonIdx);\n const stepOrdinal = Number(rest.slice(colonIdx + 1));\n if (!jobId || Number.isNaN(stepOrdinal)) return null;\n return { action, jobId, stepOrdinal };\n }\n }\n return null;\n}\n","/**\n * Webhook 署名検証用クレデンシャル解決ヘルパー\n *\n * jobId → テナント → DB の notificationCredentials から\n * 該当プラットフォームの署名シークレットを復号して返す。\n *\n * chat-bot-factory.ts と同じ復号パターンを使用。\n */\n\nimport { eq } from \"drizzle-orm\";\nimport { decrypt } from \"../crypto.js\";\nimport { jobs, tenantExecutionSettings } from \"../db/schema.js\";\nimport type { getDb } from \"../db/client.js\";\nimport type { NotificationPlatform } from \"../routes/settings-defaults.js\";\nimport { NOTIFICATION_SENSITIVE_FIELDS } from \"../routes/settings-defaults.js\";\n\ntype Db = ReturnType<typeof getDb>;\n\n/** Webhook ハンドラ共通の依存 */\nexport interface WebhookDeps {\n db: Db;\n encryptionKey: string;\n redisUrl: string;\n}\n\ntype NotificationCredentials = Record<\n string,\n Record<string, string> | undefined\n>;\n\n/**\n * jobId → テナントの復号済みクレデンシャルを解決する。\n *\n * @returns テナントID + 復号済みクレデンシャル。見つからない場合は null。\n */\nexport async function resolveWebhookCredential(\n deps: WebhookDeps,\n jobId: string,\n platform: NotificationPlatform,\n): Promise<{ tenantId: string; credentials: Record<string, string> } | null> {\n // 1. jobId → tenantId\n const job = await deps.db.query.jobs.findFirst({\n where: eq(jobs.id, jobId),\n columns: { tenantId: true },\n });\n if (!job) return null;\n\n // 2. tenantId → notificationCredentials\n const settings = await deps.db.query.tenantExecutionSettings.findFirst({\n where: eq(tenantExecutionSettings.tenantId, job.tenantId),\n columns: { notificationCredentials: true },\n });\n\n const allCreds = settings?.notificationCredentials as\n | NotificationCredentials\n | null\n | undefined;\n const creds = allCreds?.[platform];\n if (!creds) return null;\n\n // 3. sensitive フィールドを復号\n const sensitiveKeys = new Set(\n NOTIFICATION_SENSITIVE_FIELDS[platform] ?? [],\n );\n const decrypted: Record<string, string> = {};\n for (const [key, val] of Object.entries(creds)) {\n if (!val) continue;\n decrypted[key] = sensitiveKeys.has(key)\n ? decrypt(val, deps.encryptionKey)\n : val;\n }\n\n return { tenantId: job.tenantId, credentials: decrypted };\n}\n\n/**\n * 全テナントの Discord public key を返す(PING 検証用)。\n *\n * Discord の PING は URL 設定時のみ発生するため、全テナントの鍵を試行しても\n * パフォーマンス上の問題はない。\n */\nexport async function resolveAllDiscordPublicKeys(\n deps: WebhookDeps,\n): Promise<string[]> {\n const rows = await deps.db.query.tenantExecutionSettings.findMany({\n columns: { notificationCredentials: true },\n });\n\n const keys: string[] = [];\n for (const row of rows) {\n const allCreds = row.notificationCredentials as\n | NotificationCredentials\n | null\n | undefined;\n const discordCreds = allCreds?.discord;\n if (!discordCreds?.DISCORD_PUBLIC_KEY) continue;\n\n try {\n const decryptedKey = decrypt(\n discordCreds.DISCORD_PUBLIC_KEY,\n deps.encryptionKey,\n );\n keys.push(decryptedKey);\n } catch {\n // 復号失敗 → スキップ\n }\n }\n\n return keys;\n}\n","/**\n * Teams Bot Framework webhook ハンドラ\n *\n * Azure Bot Framework の「Messaging endpoint」で設定した URL:\n * POST https://<server>/api/webhooks/teams\n *\n * Adaptive Card のボタンクリック → Redis publish → ServerConfirmationProvider が受信。\n *\n * マルチテナント対応: payload を先にパースして jobId を特定し、\n * テナントごとの App ID で JWT audience を検証する(parse-first, verify-second)。\n */\n\nimport { Hono } from \"hono\";\nimport { createRemoteJWKSet, jwtVerify } from \"jose\";\nimport { parseApprovalButtonId } from \"./approval-parser.js\";\nimport { resolveWebhookCredential, type WebhookDeps } from \"./credential-resolver.js\";\nimport { getRedisPublisher } from \"../redis.js\";\n\n// ── Bot Framework OpenID 設定 ──\n\nconst BOT_FRAMEWORK_OPENID_METADATA =\n \"https://login.botframework.com/v1/.well-known/openidconfiguration\";\n\nconst BOT_FRAMEWORK_ISSUERS = [\n \"https://api.botframework.com\",\n \"https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/\",\n \"https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0\",\n];\n\n/** JWKS セット(遅延初期化 + 自動キャッシュ) */\nlet jwksSet: ReturnType<typeof createRemoteJWKSet> | null = null;\n\nasync function getJwksSet(): Promise<ReturnType<typeof createRemoteJWKSet>> {\n if (jwksSet) return jwksSet;\n\n // OpenID メタデータから jwks_uri を取得\n const res = await fetch(BOT_FRAMEWORK_OPENID_METADATA);\n const metadata = (await res.json()) as { jwks_uri: string };\n jwksSet = createRemoteJWKSet(new URL(metadata.jwks_uri));\n return jwksSet;\n}\n\n/**\n * Bot Framework JWT を検証する。\n * 検証失敗時は例外をスローする。\n */\nasync function verifyBotFrameworkToken(\n token: string,\n teamsAppId: string,\n): Promise<void> {\n const keySet = await getJwksSet();\n await jwtVerify(token, keySet, {\n audience: teamsAppId,\n issuer: BOT_FRAMEWORK_ISSUERS,\n clockTolerance: 300, // 5 分の時刻ずれ許容\n });\n}\n\n/**\n * Teams Bot Framework webhook ルートを生成。\n *\n * @param deps DB・暗号鍵・Redis URL(テナント別クレデンシャル解決用)\n */\nexport function createTeamsWebhookRoute(deps: WebhookDeps) {\n const app = new Hono();\n\n app.post(\"/\", async (c) => {\n // 1. Authorization ヘッダーチェック\n const authHeader = c.req.header(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n return c.text(\"Unauthorized\", 401);\n }\n const token = authHeader.slice(7);\n\n // 2. Activity パース\n const activity = (await c.req.json()) as TeamsActivity;\n\n // non-approval activity → 検証不要で OK\n if (activity.type !== \"invoke\" || activity.name !== \"adaptiveCard/action\") {\n return c.json({ status: 200 });\n }\n\n // 3. actionId からパース\n const actionId = activity.value?.action?.data?.actionId;\n if (!actionId) {\n return c.json({ status: 200 });\n }\n\n const parsed = parseApprovalButtonId(actionId);\n if (!parsed) {\n return c.json({ status: 200 });\n }\n\n // 4. テナント別クレデンシャル解決\n const resolved = await resolveWebhookCredential(deps, parsed.jobId, \"teams\");\n if (!resolved?.credentials.TEAMS_APP_ID) {\n return c.text(\"Invalid webhook\", 401);\n }\n\n // 5. JWT 検証(テナントの App ID で audience 検証)\n try {\n await verifyBotFrameworkToken(token, resolved.credentials.TEAMS_APP_ID);\n } catch {\n return c.text(\"Invalid token\", 401);\n }\n\n // 6. Redis publish\n const respondedBy = activity.from?.name ?? activity.from?.id;\n const redis = getRedisPublisher(deps.redisUrl);\n await redis.publish(\n `job:${parsed.jobId}:approval:${parsed.stepOrdinal}`,\n JSON.stringify({ action: parsed.action, respondedBy }),\n );\n\n // 7. invoke レスポンス(Teams は statusCode 200 の JSON を期待)\n return c.json({ status: 200, type: \"invokeResponse\", value: { status: 200 } });\n });\n\n return app;\n}\n\n// ── Teams Activity 型(必要最小限) ──\n\ninterface TeamsActivity {\n type: string;\n name?: string;\n from?: {\n id: string;\n name?: string;\n };\n value?: {\n action?: {\n type?: string;\n data?: {\n actionId?: string;\n value?: string;\n };\n };\n };\n}\n","/**\n * Discord interaction webhook ハンドラ\n *\n * Discord App の「Interactions Endpoint URL」で設定した URL:\n * POST https://<server>/api/webhooks/discord\n *\n * ボタンクリック(MESSAGE_COMPONENT)→ Redis publish → ServerConfirmationProvider が受信。\n * URL 登録時の PING/PONG 応答にも対応。\n *\n * マルチテナント対応: payload を先にパースして jobId を特定し、\n * テナントごとの Public Key で署名検証する(parse-first, verify-second)。\n * PING は全テナントの Public Key を試行する。\n */\n\nimport { Hono } from \"hono\";\nimport { verify } from \"node:crypto\";\nimport { parseApprovalButtonId } from \"./approval-parser.js\";\nimport {\n resolveWebhookCredential,\n resolveAllDiscordPublicKeys,\n type WebhookDeps,\n} from \"./credential-resolver.js\";\nimport { getRedisPublisher } from \"../redis.js\";\n\n// ── Discord Interaction Types ──\n\n/** @see https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-type */\nconst InteractionType = {\n PING: 1,\n APPLICATION_COMMAND: 2,\n MESSAGE_COMPONENT: 3,\n} as const;\n\n/** @see https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object-interaction-callback-type */\nconst InteractionResponseType = {\n PONG: 1,\n CHANNEL_MESSAGE_WITH_SOURCE: 4,\n DEFERRED_UPDATE_MESSAGE: 6,\n} as const;\n\n/**\n * Ed25519 署名検証(Node.js 組み込み crypto を使用)。\n *\n * Discord は公開鍵を hex エンコードの Ed25519 raw public key として提供する。\n * Node.js の crypto.verify() は DER/SPKI 形式を期待するため変換が必要。\n */\nfunction verifyDiscordSignature(\n publicKeyHex: string,\n signature: string,\n timestamp: string,\n body: string,\n): boolean {\n // Ed25519 raw public key (32 bytes) → DER SPKI 形式に変換\n // SPKI ヘッダー: 30 2a 30 05 06 03 2b 65 70 03 21 00\n const ED25519_SPKI_HEADER = Buffer.from(\n \"302a300506032b6570032100\",\n \"hex\",\n );\n const rawKey = Buffer.from(publicKeyHex, \"hex\");\n const spkiKey = Buffer.concat([ED25519_SPKI_HEADER, rawKey]);\n\n try {\n return verify(\n null, // Ed25519 はアルゴリズム指定不要\n Buffer.from(timestamp + body),\n { key: spkiKey, format: \"der\", type: \"spki\" },\n Buffer.from(signature, \"hex\"),\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Discord interaction webhook ルートを生成。\n *\n * @param deps DB・暗号鍵・Redis URL(テナント別クレデンシャル解決用)\n */\nexport function createDiscordWebhookRoute(deps: WebhookDeps) {\n const app = new Hono();\n\n app.post(\"/\", async (c) => {\n // 1. Ed25519 署名ヘッダーチェック\n const signature = c.req.header(\"X-Signature-Ed25519\");\n const timestamp = c.req.header(\"X-Signature-Timestamp\");\n if (!signature || !timestamp) {\n return c.text(\"Missing signature\", 401);\n }\n\n const rawBody = await c.req.text();\n\n let interaction: DiscordInteraction;\n try {\n interaction = JSON.parse(rawBody) as DiscordInteraction;\n } catch {\n return c.text(\"Invalid JSON\", 400);\n }\n\n // 2. PING 応答(Discord は URL 検証時に PING を送信)\n // PING はどのテナント宛か不明なため、全テナントの公開鍵を試行\n if (interaction.type === InteractionType.PING) {\n const publicKeys = await resolveAllDiscordPublicKeys(deps);\n const verified = publicKeys.some((key) =>\n verifyDiscordSignature(key, signature, timestamp, rawBody),\n );\n if (!verified) {\n return c.text(\"Invalid signature\", 401);\n }\n return c.json({ type: InteractionResponseType.PONG });\n }\n\n // 3. MESSAGE_COMPONENT (type=3) のボタンクリック\n if (interaction.type !== InteractionType.MESSAGE_COMPONENT) {\n return c.json({\n type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,\n data: { content: \"OK\" },\n });\n }\n\n const customId = interaction.data?.custom_id;\n if (!customId) {\n return c.json({ type: InteractionResponseType.DEFERRED_UPDATE_MESSAGE });\n }\n\n const parsed = parseApprovalButtonId(customId);\n if (!parsed) {\n return c.json({ type: InteractionResponseType.DEFERRED_UPDATE_MESSAGE });\n }\n\n // 4. テナント別クレデンシャル解決\n const resolved = await resolveWebhookCredential(deps, parsed.jobId, \"discord\");\n if (!resolved?.credentials.DISCORD_PUBLIC_KEY) {\n return c.text(\"Invalid webhook\", 401);\n }\n\n // 5. Ed25519 署名検証(テナントの Public Key で)\n if (!verifyDiscordSignature(resolved.credentials.DISCORD_PUBLIC_KEY, signature, timestamp, rawBody)) {\n return c.text(\"Invalid signature\", 401);\n }\n\n // 6. Redis publish\n const user = interaction.member?.user ?? interaction.user;\n const respondedBy = user?.global_name ?? user?.username ?? user?.id;\n const redis = getRedisPublisher(deps.redisUrl);\n await redis.publish(\n `job:${parsed.jobId}:approval:${parsed.stepOrdinal}`,\n JSON.stringify({ action: parsed.action, respondedBy }),\n );\n\n // 7. 応答(deferred update: ボタンが「処理中」表示に変わる)\n return c.json({ type: InteractionResponseType.DEFERRED_UPDATE_MESSAGE });\n });\n\n return app;\n}\n\n// ── Discord Interaction 型(必要最小限) ──\n\ninterface DiscordInteraction {\n type: number;\n data?: {\n custom_id?: string;\n component_type?: number;\n };\n member?: {\n user?: DiscordUser;\n };\n user?: DiscordUser;\n}\n\ninterface DiscordUser {\n id: string;\n username?: string;\n global_name?: string;\n}\n"],"mappings":"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","names":["Hono","user","_pool","user","readFile","eq","eq","eq","eq","and","eq","and","eq","eq","logger","eq","and","and","eq","eq","eq","eq","and","desc","sql","count","sql","and","eq","desc","count","logger","eq","isSelfHeal","readFile","readFile","readdir","join","eq","guessMimeType","logger","eq","exploreResult","readdir","readFile","join","ParsedRunbookSchema","RunbookStore","eq","and","eq","and","desc","count","and","eq","desc","count","eq","runbookSteps","count","isNull","and","eq","and","eq","and","user","createMiddleware","createMiddleware","user","createMiddleware","createMiddleware","eq","inngest","row","processedSecrets","updated","plan","eq","z","job","Hono","and","eq","and","eq","eq","and","sql","sql","and","eq","Hono","and","eq","inArray","inngest","Hono","inArray","eq","and","yamlStringify","resolveTenantAIConfig","buildModelFactory","loadServerConfig","ParsedRunbookSchema","Hono","eq","and","count","Hono","eq","count","and","Hono","createHash","eq","and","isNull","createHash","Hono","user","eq","isNull","and","Hono","createHash","eq","Hono","createHash","eq","Hono","eq","and","Hono","eq","and","Hono","eq","Hono","eq","Hono","eq","and","t","z","Hono","eq","and","z","safeInt","Hono","Hono","Hono","Hono","Hono","eq","eq","Hono","Hono","Hono","Hono","Hono","user","Hono"]}
|