@wopr-network/platform-core 1.39.7 → 1.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ export const tenants = pgTable("tenants", {
4
4
  id: text("id").primaryKey(), // nanoid or crypto.randomUUID()
5
5
  name: text("name").notNull(),
6
6
  slug: text("slug").unique(),
7
- type: text("type").notNull(), // "personal" | "org"
7
+ type: text("type").notNull(), // "personal" | "org" | "platform_service"
8
8
  ownerId: text("owner_id").notNull(), // user who created it
9
9
  billingEmail: text("billing_email"),
10
10
  createdAt: bigint("created_at", { mode: "number" })
@@ -14,5 +14,5 @@ export const tenants = pgTable("tenants", {
14
14
  index("idx_tenants_slug").on(table.slug),
15
15
  index("idx_tenants_owner").on(table.ownerId),
16
16
  index("idx_tenants_type").on(table.type),
17
- check("chk_tenants_type", sql `${table.type} IN ('personal', 'org')`),
17
+ check("chk_tenants_type", sql `${table.type} IN ('personal', 'org', 'platform_service')`),
18
18
  ]);
@@ -0,0 +1,6 @@
1
+ import type { DrizzleDb } from "./index.js";
2
+ export interface PlatformServiceSeedResult {
3
+ tenantId: string;
4
+ serviceKey: string | null;
5
+ }
6
+ export declare function seedPlatformServiceTenant(db: DrizzleDb): Promise<PlatformServiceSeedResult>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Idempotent seed: creates the holyship-platform internal billing tenant
3
+ * with a stable service key for platform-to-gateway LLM billing.
4
+ *
5
+ * Safe to call on every boot — skips if the tenant already exists.
6
+ */
7
+ import { createHash, randomBytes } from "node:crypto";
8
+ import { eq } from "drizzle-orm";
9
+ import { gatewayServiceKeys } from "./schema/gateway-service-keys.js";
10
+ import { tenants } from "./schema/tenants.js";
11
+ const PLATFORM_TENANT_ID = "holyship-platform";
12
+ const PLATFORM_TENANT_SLUG = "holyship-platform";
13
+ const PLATFORM_INSTANCE_ID = "holyship-platform-internal";
14
+ export async function seedPlatformServiceTenant(db) {
15
+ // Check if tenant already exists
16
+ const existing = await db.select({ id: tenants.id }).from(tenants).where(eq(tenants.id, PLATFORM_TENANT_ID)).limit(1);
17
+ if (existing.length > 0) {
18
+ return { tenantId: PLATFORM_TENANT_ID, serviceKey: null };
19
+ }
20
+ // Create the platform_service tenant
21
+ await db.insert(tenants).values({
22
+ id: PLATFORM_TENANT_ID,
23
+ name: "Holy Ship Platform",
24
+ slug: PLATFORM_TENANT_SLUG,
25
+ type: "platform_service",
26
+ ownerId: "system",
27
+ billingEmail: null,
28
+ createdAt: Date.now(),
29
+ });
30
+ // Generate a service key and store its hash
31
+ const rawKey = `sk-hs-${randomBytes(24).toString("hex")}`;
32
+ const keyHash = createHash("sha256").update(rawKey).digest("hex");
33
+ await db.insert(gatewayServiceKeys).values({
34
+ id: crypto.randomUUID(),
35
+ keyHash,
36
+ tenantId: PLATFORM_TENANT_ID,
37
+ instanceId: PLATFORM_INSTANCE_ID,
38
+ createdAt: Date.now(),
39
+ revokedAt: null,
40
+ });
41
+ return { tenantId: PLATFORM_TENANT_ID, serviceKey: rawKey };
42
+ }
@@ -0,0 +1,3 @@
1
+ ALTER TABLE "tenants" DROP CONSTRAINT "chk_tenants_type";
2
+ --> statement-breakpoint
3
+ ALTER TABLE "tenants" ADD CONSTRAINT "chk_tenants_type" CHECK ("tenants"."type" IN ('personal', 'org', 'platform_service'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wopr-network/platform-core",
3
- "version": "1.39.7",
3
+ "version": "1.40.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -7,7 +7,7 @@ export const tenants = pgTable(
7
7
  id: text("id").primaryKey(), // nanoid or crypto.randomUUID()
8
8
  name: text("name").notNull(),
9
9
  slug: text("slug").unique(),
10
- type: text("type").notNull(), // "personal" | "org"
10
+ type: text("type").notNull(), // "personal" | "org" | "platform_service"
11
11
  ownerId: text("owner_id").notNull(), // user who created it
12
12
  billingEmail: text("billing_email"),
13
13
  createdAt: bigint("created_at", { mode: "number" })
@@ -18,6 +18,6 @@ export const tenants = pgTable(
18
18
  index("idx_tenants_slug").on(table.slug),
19
19
  index("idx_tenants_owner").on(table.ownerId),
20
20
  index("idx_tenants_type").on(table.type),
21
- check("chk_tenants_type", sql`${table.type} IN ('personal', 'org')`),
21
+ check("chk_tenants_type", sql`${table.type} IN ('personal', 'org', 'platform_service')`),
22
22
  ],
23
23
  );
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Idempotent seed: creates the holyship-platform internal billing tenant
3
+ * with a stable service key for platform-to-gateway LLM billing.
4
+ *
5
+ * Safe to call on every boot — skips if the tenant already exists.
6
+ */
7
+ import { createHash, randomBytes } from "node:crypto";
8
+ import { eq } from "drizzle-orm";
9
+ import type { DrizzleDb } from "./index.js";
10
+ import { gatewayServiceKeys } from "./schema/gateway-service-keys.js";
11
+ import { tenants } from "./schema/tenants.js";
12
+
13
+ const PLATFORM_TENANT_ID = "holyship-platform";
14
+ const PLATFORM_TENANT_SLUG = "holyship-platform";
15
+ const PLATFORM_INSTANCE_ID = "holyship-platform-internal";
16
+
17
+ export interface PlatformServiceSeedResult {
18
+ tenantId: string;
19
+ serviceKey: string | null; // null if tenant + key already existed
20
+ }
21
+
22
+ export async function seedPlatformServiceTenant(db: DrizzleDb): Promise<PlatformServiceSeedResult> {
23
+ // Check if tenant already exists
24
+ const existing = await db.select({ id: tenants.id }).from(tenants).where(eq(tenants.id, PLATFORM_TENANT_ID)).limit(1);
25
+
26
+ if (existing.length > 0) {
27
+ return { tenantId: PLATFORM_TENANT_ID, serviceKey: null };
28
+ }
29
+
30
+ // Create the platform_service tenant
31
+ await db.insert(tenants).values({
32
+ id: PLATFORM_TENANT_ID,
33
+ name: "Holy Ship Platform",
34
+ slug: PLATFORM_TENANT_SLUG,
35
+ type: "platform_service",
36
+ ownerId: "system",
37
+ billingEmail: null,
38
+ createdAt: Date.now(),
39
+ });
40
+
41
+ // Generate a service key and store its hash
42
+ const rawKey = `sk-hs-${randomBytes(24).toString("hex")}`;
43
+ const keyHash = createHash("sha256").update(rawKey).digest("hex");
44
+
45
+ await db.insert(gatewayServiceKeys).values({
46
+ id: crypto.randomUUID(),
47
+ keyHash,
48
+ tenantId: PLATFORM_TENANT_ID,
49
+ instanceId: PLATFORM_INSTANCE_ID,
50
+ createdAt: Date.now(),
51
+ revokedAt: null,
52
+ });
53
+
54
+ return { tenantId: PLATFORM_TENANT_ID, serviceKey: rawKey };
55
+ }