Build the agent-native compute CRM platform
CI / verify (push) Successful in 3m6s

This commit is contained in:
2026-08-13 01:39:01 -07:00
parent bfd2f8d95a
commit 853bde2265
160 changed files with 61812 additions and 483 deletions
@@ -0,0 +1 @@
ALTER TYPE "public"."pig_security_tier" ADD VALUE 'government' BEFORE 'secure_cloud';
@@ -0,0 +1 @@
ALTER TYPE "public"."pig_fact_status" ADD VALUE 'approved' BEFORE 'proposed';
@@ -0,0 +1,16 @@
CREATE TABLE "platform_settings" (
"id" text PRIMARY KEY DEFAULT 'default' NOT NULL,
"piggy_model" text DEFAULT 'nvidia/nemotron-3-nano-30b-a3b' NOT NULL,
"piggy_inference_base" text DEFAULT 'https://api.pinference.ai/api/v1' NOT NULL,
"piggy_enabled" boolean DEFAULT false NOT NULL,
"prime_api_key_encrypted" text,
"prime_api_key_updated_at" timestamp with time zone,
"prime_sync_enabled" boolean DEFAULT false NOT NULL,
"prime_sync_interval_minutes" integer DEFAULT 30 NOT NULL,
"updated_by_user_id" uuid,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "platform_settings_singleton_check" CHECK ("platform_settings"."id" = 'default'),
CONSTRAINT "platform_settings_sync_interval_check" CHECK ("platform_settings"."prime_sync_interval_minutes" BETWEEN 1 AND 1440)
);
--> statement-breakpoint
ALTER TABLE "platform_settings" ADD CONSTRAINT "platform_settings_updated_by_user_id_users_id_fk" FOREIGN KEY ("updated_by_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
@@ -0,0 +1,33 @@
CREATE TABLE "notification_outbox" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"provider" text NOT NULL,
"kind" text NOT NULL,
"link_id" uuid,
"workspace_id" text,
"destination" text NOT NULL,
"payload" jsonb NOT NULL,
"idempotency_key" text NOT NULL,
"status" text DEFAULT 'pending' NOT NULL,
"attempts" integer DEFAULT 0 NOT NULL,
"max_attempts" integer DEFAULT 5 NOT NULL,
"due_at" timestamp with time zone DEFAULT now() NOT NULL,
"leased_until" timestamp with time zone,
"leased_by" text,
"delivered_at" timestamp with time zone,
"external_id" text,
"error" text,
"requested_by_user_id" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
DROP INDEX "channel_links_platform_channel_key";--> statement-breakpoint
ALTER TABLE "channel_links" ADD COLUMN "workspace_id" text DEFAULT '' NOT NULL;--> statement-breakpoint
ALTER TABLE "channel_links" ADD COLUMN "linked_by_user_id" uuid;--> statement-breakpoint
ALTER TABLE "channel_links" ADD COLUMN "updated_at" timestamp with time zone DEFAULT now() NOT NULL;--> statement-breakpoint
ALTER TABLE "notification_outbox" ADD CONSTRAINT "notification_outbox_link_id_channel_links_id_fk" FOREIGN KEY ("link_id") REFERENCES "public"."channel_links"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "notification_outbox" ADD CONSTRAINT "notification_outbox_requested_by_user_id_users_id_fk" FOREIGN KEY ("requested_by_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "notification_outbox_idempotency_key" ON "notification_outbox" USING btree ("idempotency_key");--> statement-breakpoint
CREATE INDEX "notification_outbox_claimable_idx" ON "notification_outbox" USING btree ("provider","status","due_at");--> statement-breakpoint
CREATE INDEX "notification_outbox_link_idx" ON "notification_outbox" USING btree ("link_id");--> statement-breakpoint
ALTER TABLE "channel_links" ADD CONSTRAINT "channel_links_linked_by_user_id_users_id_fk" FOREIGN KEY ("linked_by_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "channel_links_platform_workspace_channel_key" ON "channel_links" USING btree ("platform","workspace_id","channel_id");
@@ -0,0 +1,14 @@
CREATE TABLE "import_identities" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"entity" text NOT NULL,
"key_column" text NOT NULL,
"key_value" text NOT NULL,
"record_id" uuid NOT NULL,
"imported_by_user_id" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "import_identities" ADD CONSTRAINT "import_identities_imported_by_user_id_users_id_fk" FOREIGN KEY ("imported_by_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "import_identities_source_key" ON "import_identities" USING btree ("entity","key_column","key_value");--> statement-breakpoint
CREATE INDEX "import_identities_record_idx" ON "import_identities" USING btree ("entity","record_id");
@@ -0,0 +1,25 @@
CREATE TABLE "notion_connections" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" uuid NOT NULL,
"workspace_id" text NOT NULL,
"workspace_name" text,
"workspace_icon" text,
"bot_id" text,
"credentials_encrypted" text NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "notion_oauth_states" (
"state_hash" text PRIMARY KEY NOT NULL,
"user_id" uuid NOT NULL,
"verifier_hash" text NOT NULL,
"expires_at" timestamp with time zone NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "notion_connections" ADD CONSTRAINT "notion_connections_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "notion_oauth_states" ADD CONSTRAINT "notion_oauth_states_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "notion_connections_user_workspace_key" ON "notion_connections" USING btree ("user_id","workspace_id");--> statement-breakpoint
CREATE INDEX "notion_connections_user_idx" ON "notion_connections" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "notion_oauth_states_expiry_idx" ON "notion_oauth_states" USING btree ("expires_at");
@@ -0,0 +1,26 @@
CREATE TABLE "google_connections" (
"user_id" uuid PRIMARY KEY NOT NULL,
"refresh_token_encrypted" text NOT NULL,
"access_token_encrypted" text,
"access_token_expires_at" timestamp with time zone,
"scopes" jsonb DEFAULT '[]'::jsonb NOT NULL,
"connected_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "google_oauth_flows" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" uuid NOT NULL,
"state_hash" text NOT NULL,
"browser_binding_hash" text NOT NULL,
"pkce_verifier_encrypted" text NOT NULL,
"expires_at" timestamp with time zone NOT NULL,
"consumed_at" timestamp with time zone,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "google_connections" ADD CONSTRAINT "google_connections_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "google_oauth_flows" ADD CONSTRAINT "google_oauth_flows_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "google_oauth_flows_state_hash_key" ON "google_oauth_flows" USING btree ("state_hash");--> statement-breakpoint
CREATE INDEX "google_oauth_flows_expiry_idx" ON "google_oauth_flows" USING btree ("expires_at");--> statement-breakpoint
CREATE INDEX "google_oauth_flows_user_idx" ON "google_oauth_flows" USING btree ("user_id");
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+50 -1
View File
@@ -22,6 +22,55 @@
"when": 1786588874252,
"tag": "0002_invite_reuse",
"breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1786600259806,
"tag": "0003_amazing_miss_america",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1786602049010,
"tag": "0004_fact_approval",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1786611600000,
"tag": "0005_platform_settings",
"breakpoints": true
},
{
"idx": 6,
"version": "7",
"when": 1786611700000,
"tag": "0006_dazzling_forge",
"breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1786611800000,
"tag": "0007_nasty_vanisher",
"breakpoints": true
},
{
"idx": 8,
"version": "7",
"when": 1786611900000,
"tag": "0008_easy_scalphunter",
"breakpoints": true
},
{
"idx": 9,
"version": "7",
"when": 1786612000000,
"tag": "0009_warm_metal_master",
"breakpoints": true
}
]
}
}
+11 -32
View File
@@ -33,6 +33,13 @@ import {
timestamp,
uuid,
} from 'drizzle-orm/pg-core';
import { ALLOCATION_STATUSES, GUARANTEE_TYPES } from '@pig/core';
export {
ALLOCATION_STATUSES,
CONSUMING_ALLOCATION_STATUSES,
RESERVING_ALLOCATION_STATUSES,
} from '@pig/core';
export type { AllocationStatus } from '@pig/core';
import { capacityCommitments } from './supply';
import { demandDeals } from './demand';
import { users } from './identity';
@@ -95,7 +102,7 @@ export const allocations = pgTable(
* allocations are shown separately so a seller can see what the pipeline
* would do to utilisation without letting forecasts pollute the actuals.
*/
status: text('status').notNull().default('planned'),
status: text('status', { enum: ALLOCATION_STATUSES }).notNull().default('planned'),
/**
* A capacity HOLD with an expiry.
@@ -129,7 +136,9 @@ export const allocations = pgTable(
* system answer "can I actually sell this?" rather than "is something
* technically free?"
*/
guaranteeType: text('guarantee_type').notNull().default('committed'),
guaranteeType: text('guarantee_type', { enum: GUARANTEE_TYPES })
.notNull()
.default('committed'),
priority: integer('priority').notNull().default(100),
/**
@@ -160,35 +169,5 @@ export const allocations = pgTable(
],
);
/**
* Statuses that actually consume committed capacity.
*
* Kept here beside the column it describes so the definition cannot drift away
* from the schema. Utilisation and idle-capacity figures filter on this;
* including `planned` would let optimistic forecasting hide idle hardware.
*/
export const CONSUMING_ALLOCATION_STATUSES = ['committed', 'active', 'completed'] as const;
/**
* Statuses that block the capacity from being sold to somebody else.
*
* Deliberately WIDER than the set that counts toward utilisation and margin.
* A live hold must remove inventory from availability otherwise two sellers
* promise the same GPUs while not yet counting as sold, because it has not
* been. Conflating "cannot be offered to anyone else" with "earning revenue"
* is how a pipeline of optimistic holds comes to look like a full book.
*/
export const RESERVING_ALLOCATION_STATUSES = [
'planned',
...CONSUMING_ALLOCATION_STATUSES,
] as const;
export const ALLOCATION_STATUSES = [
'planned',
...CONSUMING_ALLOCATION_STATUSES,
'released',
] as const;
export type AllocationStatus = (typeof ALLOCATION_STATUSES)[number];
export type Allocation = typeof allocations.$inferSelect;
export type NewAllocation = typeof allocations.$inferInsert;
+20
View File
@@ -218,3 +218,23 @@ export const complianceArtifacts = pgTable(
export type ExportAuthorization = typeof exportAuthorizations.$inferSelect;
export type ComplianceDecision = typeof complianceDecisions.$inferSelect;
export type ComplianceArtifact = typeof complianceArtifacts.$inferSelect;
export type ComplianceMatchDecision = Pick<
ComplianceDecision,
'decision' | 'supersededAt'
>;
/**
* Whether a recorded export-control predicate permits a prospective match.
*
* `undefined` means no buyer-specific evaluation was requested, as in a generic
* inventory search. Once evaluation is requested, absence, review, block and a
* superseded allow all fail closed. Security classification is not a substitute
* for an export-control determination.
*/
export function complianceDecisionAllowsMatch(
decision: ComplianceMatchDecision | null | undefined,
): boolean {
if (decision === undefined) return true;
return decision?.decision === 'allow' && decision.supersededAt === null;
}
+11 -1
View File
@@ -214,15 +214,25 @@ export const channelLinks = pgTable(
id: uuid('id').primaryKey().defaultRandom(),
/** 'slack' | 'buzz' — kept as text so a new platform needs no migration. */
platform: text('platform').notNull(),
/** Slack channel ids are unique only inside a workspace. Buzz uses ''. */
workspaceId: text('workspace_id').notNull().default(''),
channelId: text('channel_id').notNull(),
channelName: text('channel_name'),
accountId: uuid('account_id').references(() => accounts.id, { onDelete: 'cascade' }),
/** Notify on stage changes, idle-capacity alerts, renewals due. */
notifyOn: jsonb('notify_on').$type<string[]>().notNull().default([]),
linkedByUserId: uuid('linked_by_user_id').references(() => users.id, {
onDelete: 'set null',
}),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},
(t) => [
uniqueIndex('channel_links_platform_channel_key').on(t.platform, t.channelId),
uniqueIndex('channel_links_platform_workspace_channel_key').on(
t.platform,
t.workspaceId,
t.channelId,
),
index('channel_links_account_idx').on(t.accountId),
],
);
+44
View File
@@ -0,0 +1,44 @@
import { index, jsonb, pgTable, text, timestamp, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
import { users } from './identity';
/** One least-privilege Google Sheets connection per PIG user. */
export const googleConnections = pgTable('google_connections', {
userId: uuid('user_id')
.primaryKey()
.references(() => users.id, { onDelete: 'cascade' }),
/** Purpose-bound AES-256-GCM envelopes. Tokens are never returned by the API. */
refreshTokenEncrypted: text('refresh_token_encrypted').notNull(),
accessTokenEncrypted: text('access_token_encrypted'),
accessTokenExpiresAt: timestamp('access_token_expires_at', { withTimezone: true }),
scopes: jsonb('scopes').$type<string[]>().notNull().default([]),
connectedAt: timestamp('connected_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
});
/**
* Short-lived OAuth proof material stays server-side. State is hashed and the
* PKCE verifier encrypted so a database read cannot complete an OAuth flow.
*/
export const googleOauthFlows = pgTable(
'google_oauth_flows',
{
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
stateHash: text('state_hash').notNull(),
browserBindingHash: text('browser_binding_hash').notNull(),
pkceVerifierEncrypted: text('pkce_verifier_encrypted').notNull(),
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
consumedAt: timestamp('consumed_at', { withTimezone: true }),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
},
(table) => [
uniqueIndex('google_oauth_flows_state_hash_key').on(table.stateHash),
index('google_oauth_flows_expiry_idx').on(table.expiresAt),
index('google_oauth_flows_user_idx').on(table.userId),
],
);
export type GoogleConnection = typeof googleConnections.$inferSelect;
export type GoogleOauthFlow = typeof googleOauthFlows.$inferSelect;
+33
View File
@@ -0,0 +1,33 @@
import { index, pgTable, text, timestamp, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
import { users } from './identity';
/**
* Durable source identities make repeated imports updates rather than duplicate
* creates. Raw spreadsheet content stays out of the database; only the user's
* chosen stable key and the PIG record it resolved to are retained.
*/
export const importIdentities = pgTable(
'import_identities',
{
id: uuid('id').primaryKey().defaultRandom(),
entity: text('entity').notNull(),
keyColumn: text('key_column').notNull(),
keyValue: text('key_value').notNull(),
recordId: uuid('record_id').notNull(),
importedByUserId: uuid('imported_by_user_id').references(() => users.id, {
onDelete: 'set null',
}),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},
(table) => [
uniqueIndex('import_identities_source_key').on(
table.entity,
table.keyColumn,
table.keyValue,
),
index('import_identities_record_idx').on(table.entity, table.recordId),
],
);
export type ImportIdentity = typeof importIdentities.$inferSelect;
+5
View File
@@ -16,6 +16,7 @@
*/
export * from './enums';
export * from './identity';
export * from './settings';
export * from './crm';
export * from './supply';
export * from './demand';
@@ -24,3 +25,7 @@ export * from './contracts';
export * from './compliance';
export * from './agent';
export * from './fields';
export * from './integrations';
export * from './imports';
export * from './google';
export * from './notion';
+44
View File
@@ -0,0 +1,44 @@
import { index, integer, jsonb, pgTable, text, timestamp, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
import { channelLinks } from './crm';
import { users } from './identity';
/**
* External delivery is a separate durable concern from the CRM transaction.
* A deal write only adds a row here; a provider-specific worker owns network
* failure, retry and completion without holding the request thread open.
*/
export const notificationOutbox = pgTable(
'notification_outbox',
{
id: uuid('id').primaryKey().defaultRandom(),
provider: text('provider').notNull(),
kind: text('kind').notNull(),
linkId: uuid('link_id').references(() => channelLinks.id, { onDelete: 'set null' }),
workspaceId: text('workspace_id'),
destination: text('destination').notNull(),
payload: jsonb('payload').$type<Record<string, unknown>>().notNull(),
idempotencyKey: text('idempotency_key').notNull(),
status: text('status').notNull().default('pending'),
attempts: integer('attempts').notNull().default(0),
maxAttempts: integer('max_attempts').notNull().default(5),
dueAt: timestamp('due_at', { withTimezone: true }).notNull().defaultNow(),
leasedUntil: timestamp('leased_until', { withTimezone: true }),
leasedBy: text('leased_by'),
deliveredAt: timestamp('delivered_at', { withTimezone: true }),
externalId: text('external_id'),
error: text('error'),
requestedByUserId: uuid('requested_by_user_id').references(() => users.id, {
onDelete: 'set null',
}),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
},
(t) => [
uniqueIndex('notification_outbox_idempotency_key').on(t.idempotencyKey),
index('notification_outbox_claimable_idx').on(t.provider, t.status, t.dueAt),
index('notification_outbox_link_idx').on(t.linkId),
],
);
export type NotificationOutboxItem = typeof notificationOutbox.$inferSelect;
+45
View File
@@ -0,0 +1,45 @@
import { index, pgTable, text, timestamp, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
import { users } from './identity';
/**
* A Notion grant belongs to the person who completed OAuth. Credentials are a
* single authenticated-encryption envelope so no token-shaped value is ever
* queryable, searchable, or accidentally selected as ordinary metadata.
*/
export const notionConnections = pgTable(
'notion_connections',
{
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
workspaceId: text('workspace_id').notNull(),
workspaceName: text('workspace_name'),
workspaceIcon: text('workspace_icon'),
botId: text('bot_id'),
credentialsEncrypted: text('credentials_encrypted').notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},
(table) => [
uniqueIndex('notion_connections_user_workspace_key').on(table.userId, table.workspaceId),
index('notion_connections_user_idx').on(table.userId),
],
);
/**
* OAuth attempts survive multiple API processes but not replay. Only hashes
* are durable; the browser verifier is an HttpOnly, short-lived cookie.
*/
export const notionOauthStates = pgTable(
'notion_oauth_states',
{
stateHash: text('state_hash').primaryKey(),
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
verifierHash: text('verifier_hash').notNull(),
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
},
(table) => [index('notion_oauth_states_expiry_idx').on(table.expiresAt)],
);
export type NotionConnection = typeof notionConnections.$inferSelect;
export type NotionOauthState = typeof notionOauthStates.$inferSelect;
+42
View File
@@ -0,0 +1,42 @@
import {
boolean,
check,
integer,
pgTable,
text,
timestamp,
uuid,
} from 'drizzle-orm/pg-core';
import { sql } from 'drizzle-orm';
import { users } from './identity';
/** Workspace-wide controls. The check keeps this deliberately single-tenant. */
export const platformSettings = pgTable(
'platform_settings',
{
id: text('id').primaryKey().default('default'),
piggyModel: text('piggy_model').notNull().default('nvidia/nemotron-3-nano-30b-a3b'),
piggyInferenceBase: text('piggy_inference_base')
.notNull()
.default('https://api.pinference.ai/api/v1'),
piggyEnabled: boolean('piggy_enabled').notNull().default(false),
/** AES-256-GCM envelope. Its key lives outside the database. */
primeApiKeyEncrypted: text('prime_api_key_encrypted'),
primeApiKeyUpdatedAt: timestamp('prime_api_key_updated_at', { withTimezone: true }),
primeSyncEnabled: boolean('prime_sync_enabled').notNull().default(false),
primeSyncIntervalMinutes: integer('prime_sync_interval_minutes').notNull().default(30),
updatedByUserId: uuid('updated_by_user_id').references(() => users.id, {
onDelete: 'set null',
}),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},
(t) => [
check('platform_settings_singleton_check', sql`${t.id} = 'default'`),
check(
'platform_settings_sync_interval_check',
sql`${t.primeSyncIntervalMinutes} BETWEEN 1 AND 1440`,
),
],
);
export type PlatformSettings = typeof platformSettings.$inferSelect;
+50 -20
View File
@@ -35,6 +35,7 @@
* is more useful than one that opens on a loss, which reads as a broken
* product rather than an under-utilised book.
*/
import { ALLOCATION_STATUSES, type AllocationStatus } from '@pig/core';
import { and, eq, like, or } from 'drizzle-orm';
import { createDatabase } from '../client';
import {
@@ -47,6 +48,7 @@ import {
contracts,
contractObligations,
demandDeals,
type NewAllocation,
sites,
slaTerms,
supplyDeals,
@@ -59,6 +61,10 @@ const day = 86_400_000;
const now = Date.now();
const at = (days: number) => new Date(now + days * day);
function isAllocationStatus(value: string): value is AllocationStatus {
return (ALLOCATION_STATUSES as readonly string[]).includes(value);
}
/** GPU-hours for a block, allowing for a maintenance/ramp haircut. */
const hours = (gpus: number, days: number, efficiency = 0.94) =>
String(Math.round(gpus * 24 * days * efficiency));
@@ -153,7 +159,12 @@ const DEMAND = [
},
request: { gpuType: 'H200', gpuCount: 256, fastFabric: true, maxPriceCents: 285 },
// Draws from the CoreWeave block.
allocation: { supplier: 'coreweave.com', share: 0.76, priceCents: 271, status: 'active' },
allocation: {
supplier: 'coreweave.com',
share: 0.76,
priceCents: 271,
status: 'active',
},
},
{
account: `${PREFIX}Verity Health AI`,
@@ -178,7 +189,12 @@ const DEMAND = [
allowedRegions: ['eu-north', 'eu-west'],
certifications: ['ISO 27001', 'SOC 2 Type II'],
},
allocation: { supplier: 'nebius.com', share: 0.55, priceCents: 249, status: 'committed' },
allocation: {
supplier: 'nebius.com',
share: 0.55,
priceCents: 249,
status: 'committed',
},
},
{
account: `${PREFIX}Northwind Robotics`,
@@ -195,7 +211,12 @@ const DEMAND = [
dpaExecuted: true,
},
request: { gpuType: 'B200', gpuCount: 32, fastFabric: true, maxPriceCents: 460 },
allocation: { supplier: 'crusoe.ai', share: 0.74, priceCents: 441, status: 'active' },
allocation: {
supplier: 'crusoe.ai',
share: 0.74,
priceCents: 441,
status: 'active',
},
},
{
account: `${PREFIX}Tessellate Labs`,
@@ -215,7 +236,13 @@ const DEMAND = [
// A HOLD, not a sale. The deal has not closed, so this reserves capacity
// without counting as revenue — the distinction the capacity view exists
// to make visible.
allocation: { supplier: 'runpod.io', share: 0.55, priceCents: 168, status: 'planned', holdDays: 12 },
allocation: {
supplier: 'runpod.io',
share: 0.55,
priceCents: 168,
status: 'planned',
holdDays: 12,
},
},
{
account: `${PREFIX}Aurelian Systems`,
@@ -554,7 +581,10 @@ async function seedDemo() {
.limit(1);
if (commitment) {
await db.insert(allocations).values({
if (!isAllocationStatus(d.allocation.status)) {
throw new Error(`Invalid demo allocation status: ${d.allocation.status}`);
}
const allocationRow = {
capacityCommitmentId: commitmentId,
demandDealId: deal.id,
gpuHours: String(
@@ -568,7 +598,8 @@ async function seedDemo() {
priority: d.allocation.status === 'planned' ? 100 : 10,
holdExpiresAt: d.allocation.holdDays ? at(d.allocation.holdDays) : null,
notes: d.account,
});
} satisfies NewAllocation;
await db.insert(allocations).values(allocationRow);
}
}
}
@@ -613,20 +644,19 @@ async function seedDemo() {
.limit(1);
if (commitment && !existingResearch) {
await db
.insert(allocations)
.values({
capacityCommitmentId: coreweave,
internalTeam: 'research',
gpuHours: String(Math.round(Number(commitment.totalGpuHours) * 0.08)),
pricePerGpuHourCents: 0,
startsAt: commitment.startsAt,
endsAt: commitment.endsAt,
status: 'active',
guaranteeType: 'internal',
priority: 200,
notes: RESEARCH_NOTE,
});
const researchAllocationRow = {
capacityCommitmentId: coreweave,
internalTeam: 'research',
gpuHours: String(Math.round(Number(commitment.totalGpuHours) * 0.08)),
pricePerGpuHourCents: 0,
startsAt: commitment.startsAt,
endsAt: commitment.endsAt,
status: 'active',
guaranteeType: 'internal',
priority: 200,
notes: RESEARCH_NOTE,
} satisfies NewAllocation;
await db.insert(allocations).values(researchAllocationRow);
}
}