@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.
- package/dist/db/schema/tenants.js +2 -2
- package/dist/db/seed-platform-service-tenant.d.ts +6 -0
- package/dist/db/seed-platform-service-tenant.js +42 -0
- package/drizzle/migrations/0013_platform_service_tenant_type.sql +3 -0
- package/package.json +1 -1
- package/src/db/schema/tenants.ts +2 -2
- package/src/db/seed-platform-service-tenant.ts +55 -0
|
@@ -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,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
|
+
}
|
package/package.json
CHANGED
package/src/db/schema/tenants.ts
CHANGED
|
@@ -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
|
+
}
|