Namespace company skill identities

Persist canonical namespaced skill keys, split adapter runtime names from skill keys, and update portability/import flows to carry the canonical identity end-to-end.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Dotta
2026-03-16 18:27:20 -05:00
parent bb46423969
commit 5890b318c4
39 changed files with 9902 additions and 309 deletions

View File

@@ -0,0 +1,27 @@
ALTER TABLE "company_skills" ADD COLUMN "key" text;--> statement-breakpoint
UPDATE "company_skills"
SET "key" = CASE
WHEN COALESCE("metadata"->>'sourceKind', '') = 'paperclip_bundled' THEN 'paperclipai/paperclip/' || "slug"
WHEN (COALESCE("metadata"->>'sourceKind', '') = 'github' OR "source_type" = 'github')
AND COALESCE("metadata"->>'owner', '') <> ''
AND COALESCE("metadata"->>'repo', '') <> ''
THEN lower("metadata"->>'owner') || '/' || lower("metadata"->>'repo') || '/' || "slug"
WHEN COALESCE("metadata"->>'sourceKind', '') = 'managed_local' THEN 'company/' || "company_id"::text || '/' || "slug"
WHEN (COALESCE("metadata"->>'sourceKind', '') = 'url' OR "source_type" = 'url')
THEN 'url/'
|| COALESCE(
NULLIF(regexp_replace(lower(regexp_replace(COALESCE("source_locator", ''), '^https?://([^/]+).*$','\1')), '[^a-z0-9._-]+', '-', 'g'), ''),
'unknown'
)
|| '/'
|| substr(md5(COALESCE("source_locator", "slug")), 1, 10)
|| '/'
|| "slug"
WHEN "source_type" = 'local_path' AND COALESCE("source_locator", '') <> ''
THEN 'local/' || substr(md5("source_locator"), 1, 10) || '/' || "slug"
ELSE 'company/' || "company_id"::text || '/' || "slug"
END
WHERE "key" IS NULL;--> statement-breakpoint
ALTER TABLE "company_skills" ALTER COLUMN "key" SET NOT NULL;--> statement-breakpoint
DROP INDEX IF EXISTS "company_skills_company_slug_idx";--> statement-breakpoint
CREATE UNIQUE INDEX "company_skills_company_key_idx" ON "company_skills" USING btree ("company_id","key");

File diff suppressed because it is too large Load Diff

View File

@@ -246,6 +246,13 @@
"when": 1773697572188,
"tag": "0034_fat_dormammu",
"breakpoints": true
},
{
"idx": 35,
"version": "7",
"when": 1773703213570,
"tag": "0035_colorful_rhino",
"breakpoints": true
}
]
}

View File

@@ -14,6 +14,7 @@ export const companySkills = pgTable(
{
id: uuid("id").primaryKey().defaultRandom(),
companyId: uuid("company_id").notNull().references(() => companies.id),
key: text("key").notNull(),
slug: text("slug").notNull(),
name: text("name").notNull(),
description: text("description"),
@@ -29,7 +30,7 @@ export const companySkills = pgTable(
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
},
(table) => ({
companySlugUniqueIdx: uniqueIndex("company_skills_company_slug_idx").on(table.companyId, table.slug),
companyKeyUniqueIdx: uniqueIndex("company_skills_company_key_idx").on(table.companyId, table.key),
companyNameIdx: index("company_skills_company_name_idx").on(table.companyId, table.name),
}),
);