forked from EduCraft/curriculum-project-hub
77 lines
2.8 KiB
TypeScript
77 lines
2.8 KiB
TypeScript
/**
|
|
* Local dev bootstrap for an Alpha Silo on Windows / non-systemd hosts.
|
|
*
|
|
* The production bootstrap-silo CLI is Linux-only (requires root uid 0,
|
|
* systemctl, root-owned files). This script calls the same
|
|
* `bootstrapAlphaSilo` invariants directly, sourcing credentials from the
|
|
* local `.env` and the dev keyring. Idempotent: re-running is a no-op once
|
|
* the Silo Organization exists.
|
|
*
|
|
* Usage: npx tsx scripts/dev-bootstrap-silo.ts
|
|
*/
|
|
import "dotenv/config";
|
|
import { PrismaClient } from "@prisma/client";
|
|
import { bootstrapAlphaSilo } from "../src/deployment/bootstrap-silo.js";
|
|
import { loadLocalSecretKeyring, LocalSecretEnvelope } from "../src/security/secretEnvelope.js";
|
|
|
|
function requiredEnv(name: string): string {
|
|
const v = process.env[name]?.trim();
|
|
if (v === undefined || v === "") throw new Error(`missing required env: ${name}`);
|
|
return v;
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
const databaseUrl = requiredEnv("DATABASE_URL");
|
|
const keyring = await loadLocalSecretKeyring();
|
|
const secrets = new LocalSecretEnvelope(keyring);
|
|
const prisma = new PrismaClient({ datasources: { db: { url: databaseUrl } }, log: [] });
|
|
|
|
const organizationId = requiredEnv("HUB_SILO_ORGANIZATION_ID");
|
|
const feishuAppId = requiredEnv("FEISHU_APP_ID");
|
|
const feishuAppSecret = requiredEnv("FEISHU_APP_SECRET");
|
|
const feishuBotOpenId = requiredEnv("FEISHU_BOT_OPEN_ID");
|
|
const providerAuthToken = requiredEnv("ANTHROPIC_AUTH_TOKEN");
|
|
const providerBaseUrl = process.env["ANTHROPIC_BASE_URL"]?.trim() || "https://openrouter.ai/api";
|
|
const anthropicApiKey = process.env["ANTHROPIC_API_KEY"]?.trim() || "";
|
|
|
|
try {
|
|
const result = await bootstrapAlphaSilo(
|
|
prisma,
|
|
secrets,
|
|
{
|
|
organization: {
|
|
id: organizationId,
|
|
slug: "local-dev",
|
|
name: "Local Dev Silo",
|
|
},
|
|
owner: {
|
|
openId: feishuBotOpenId,
|
|
displayName: "Local Dev Owner",
|
|
},
|
|
feishu: {
|
|
appId: feishuAppId,
|
|
appSecret: feishuAppSecret,
|
|
botOpenId: feishuBotOpenId,
|
|
},
|
|
provider: {
|
|
providerId: "openrouter",
|
|
baseUrl: providerBaseUrl,
|
|
authToken: providerAuthToken,
|
|
...(anthropicApiKey !== "" ? { anthropicApiKey } : {}),
|
|
},
|
|
},
|
|
// Skip live network probes in local dev — Feishu/OpenRouter reachability
|
|
// is not required to seed the encrypted envelope rows.
|
|
{ feishu: async () => {}, provider: async () => {} },
|
|
);
|
|
console.log("bootstrap result:", JSON.stringify(result, null, 2));
|
|
} finally {
|
|
await prisma.$disconnect();
|
|
}
|
|
}
|
|
|
|
main().catch((error: unknown) => {
|
|
console.error("[dev-bootstrap-silo] failed:", error instanceof Error ? error.message : String(error));
|
|
process.exitCode = 1;
|
|
});
|