Files
clawhub/convex/skillsShCatalogCanary.test.ts
Patrick Erichsen 9784710147 fix: separate skill metrics by source (#3228)
* fix: use bookmark icons consistently

* fix: separate skill metrics by source
2026-07-29 22:41:06 -07:00

1175 lines
37 KiB
TypeScript

/// <reference types="vite/client" />
/* @vitest-environment edge-runtime */
import { convexTest } from "convex-test";
import { afterEach, describe, expect, it, vi } from "vitest";
import { api, internal } from "./_generated/api";
import type { Doc, Id } from "./_generated/dataModel";
import canarySkillMarkdown from "./fixtures/patrick-html-canary-SKILL.txt?raw";
import { extractDigestFields } from "./lib/skillSearchDigest";
import schema from "./schema";
const modules = import.meta.glob("./**/*.ts");
const LOCAL_ENV = {
CLAWHUB_SKILLS_SH_ROLLOUT_MODE: "test",
CONVEX_CLOUD_URL: "http://127.0.0.1:3210",
};
const TEST_ENV = {
CLAWHUB_DEPLOYMENT_NAME: "academic-chihuahua-392",
CLAWHUB_DISABLE_CRONS: "1",
CLAWHUB_ENV: "test",
CLAWHUB_SKILLS_SH_ROLLOUT_MODE: "test",
CONVEX_CLOUD_URL: "https://academic-chihuahua-392.convex.cloud",
};
const CANARY_EXTERNAL_ID = "patrick-erichsen/skills/html";
const CANARY_COMMIT = "050daba89f6b6636470add5cb300aac46a412cf8";
const CANARY_CONTENT_HASH = "a47adb2c1ac33c088f664b5187971b63d2b958a7b9f01516d26005ca941a108f";
const CANARY_CONTROL = {
actor: "codex-test",
reason: "exercise the controlled hidden metadata canary",
confirm: "enable-skills-sh-fixture-control",
mode: "fixture" as const,
discoveryEnabled: true,
writesEnabled: true,
scanPlanningEnabled: true,
scanAdmissionEnabled: false,
maxEntriesPerRun: 1,
maxEntriesPerBatch: 1,
maxWritesPerBatch: 2,
maxPlannedScans: 1,
maxScanAdmissionsPerBatch: 0,
maxScanAdmissionsPerRun: 0,
maxScanAdmissionsPerDay: 0,
maxCatalogQueued: 0,
maxCatalogInFlight: 0,
maxNativeQueued: 0,
maxNativeInFlight: 0,
realScanAllowlist: [] as string[],
};
const SOURCE_VERIFICATION = {
githubOwnerId: 20_157_849,
githubCommit: CANARY_COMMIT,
githubContentHash: CANARY_CONTENT_HASH,
githubCheckedAt: "2026-07-22T05:00:00.000Z",
githubFetches: 4,
};
type CatalogTest = ReturnType<typeof convexTest>;
function useEnvironment(env: Record<string, string>) {
for (const name of [
"CLAWHUB_DEPLOYMENT_NAME",
"CLAWHUB_DISABLE_CRONS",
"CLAWHUB_ENV",
"CLAWHUB_PREVIEW",
"CLAWHUB_SKILLS_SH_ROLLOUT_MODE",
"CONVEX_CLOUD_URL",
"CONVEX_DEPLOYMENT",
"CONVEX_SITE_URL",
"DEV_AUTH_CONVEX_DEPLOYMENT",
"VERCEL_ENV",
"VERCEL_TARGET_ENV",
"VITE_CLAWHUB_DEPLOY_ENV",
"VITE_CONVEX_URL",
]) {
vi.stubEnv(name, "");
}
for (const [name, value] of Object.entries(env)) vi.stubEnv(name, value);
}
async function configureCanary(t: CatalogTest) {
return await t.mutation(internal.skillsShCatalog.configureFixtureControlInternal, CANARY_CONTROL);
}
async function runCanary(t: CatalogTest) {
const started = await t.mutation(internal.skillsShCatalog.startFixtureRunInternal, {
fixtureId: "patrick-html-canary-v1",
actor: "codex-test",
reason: "apply one controlled hidden metadata canary",
sourceVerification: SOURCE_VERIFICATION,
});
const run = await t.mutation(internal.skillsShCatalog.processFixtureBatchInternal, {
runId: started.runId,
});
return { runId: started.runId, run };
}
async function sha256Hex(value: Blob | string) {
const bytes =
typeof value === "string"
? new TextEncoder().encode(value)
: new Uint8Array(await value.arrayBuffer());
const digest = await crypto.subtle.digest("SHA-256", bytes);
return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
}
async function storeCanaryArtifact(t: CatalogTest, content = canarySkillMarkdown) {
const blob = new Blob([content], { type: "text/markdown" });
const storageId = await t.run(async (ctx) => await ctx.storage.store(blob));
const sha256 = await sha256Hex(blob);
return {
externalId: CANARY_EXTERNAL_ID,
artifactContentHash: await sha256Hex(`SKILL.md\0${sha256}\n`),
files: [
{
path: "SKILL.md",
size: blob.size,
storageId,
sha256,
contentType: "text/markdown",
},
],
};
}
async function prepareScannedCanary(t: CatalogTest) {
await configureCanary(t);
await runCanary(t);
await t.mutation(internal.skillsShCatalog.configureFixtureControlInternal, {
...CANARY_CONTROL,
mode: "staging-live",
scanAdmissionEnabled: true,
publicVisibilityEnabled: true,
maxWritesPerBatch: 7,
maxScanAdmissionsPerBatch: 1,
maxScanAdmissionsPerRun: 1,
maxScanAdmissionsPerDay: 1,
maxCatalogQueued: 1,
maxCatalogInFlight: 1,
realScanAllowlist: [CANARY_EXTERNAL_ID],
});
const actorUserId = await t.run(
async (ctx) =>
await ctx.db.insert("users", {
handle: "catalog-test-operator",
displayName: "Catalog Test Operator",
role: "admin",
}),
);
const { runId } = await t.mutation(
internal.skillsShCatalog.startControlledCanaryScanRunInternal,
{
actor: "catalog-test-operator",
reason: "scan one exact controlled canary",
},
);
const artifact = await storeCanaryArtifact(t);
await t.action(internal.skillsShCatalog.admitRealScansInternal, {
runId,
externalIds: [CANARY_EXTERNAL_ID],
actorUserId,
artifacts: [artifact],
});
const [attempt] = await t.run(async (ctx) =>
(await ctx.db.query("skillsShCatalogScanAttempts").collect()).filter(
(candidate) => candidate.runId === runId && candidate.status === "queued",
),
);
if (!attempt?.skillScanRequestId || !attempt.securityScanJobId || !attempt.artifactContentHash) {
throw new Error("controlled canary scan admission did not create linked work");
}
await t.run(async (ctx) => {
await ctx.db.patch(attempt._id, { status: "running", updatedAt: Date.now() });
await ctx.db.patch(attempt.skillScanRequestId!, {
status: "running",
updatedAt: Date.now(),
});
await ctx.db.patch(attempt.securityScanJobId!, {
status: "running",
leaseToken: "canary-lease",
leaseExpiresAt: Date.now() + 60_000,
workerId: "canary-worker",
updatedAt: Date.now(),
});
});
return attempt as Doc<"skillsShCatalogScanAttempts"> & {
skillScanRequestId: Id<"skillScanRequests">;
securityScanJobId: Id<"securityScanJobs">;
artifactContentHash: string;
};
}
async function completeScannedCanary(
t: CatalogTest,
attempt: Awaited<ReturnType<typeof prepareScannedCanary>>,
verdict: "clean" | "suspicious" | "malicious" | "failed",
) {
return await t.mutation(internal.securityScan.completeCatalogSkillScanJobInternal, {
attemptId: attempt._id,
scanId: attempt.skillScanRequestId,
jobId: attempt.securityScanJobId,
leaseToken: "canary-lease",
artifactContentHash: attempt.artifactContentHash,
verdict,
runId: "canary-clawscan-run",
llmAnalysis: { status: verdict, checkedAt: Date.now() },
});
}
async function seedNativeSkill(
t: CatalogTest,
options: {
exactSource: boolean;
downloads: number;
bookmarks?: number;
openClawInstalls?: number;
skillsShInstalls?: number;
githubStars?: number;
seedDigest?: boolean;
},
) {
return await t.run(async (ctx) => {
const userId = await ctx.db.insert("users", {
handle: "native-owner",
displayName: "Native Owner",
role: "user",
});
let githubSourceId: Id<"githubSkillSources"> | undefined;
if (options.exactSource) {
githubSourceId = await ctx.db.insert("githubSkillSources", {
repo: "Patrick-Erichsen/skills",
lastSyncStatus: "ok",
createdAt: 1,
updatedAt: 1,
});
}
const skillId = await ctx.db.insert("skills", {
slug: "html",
displayName: options.exactSource ? "HTML Artifact Chooser" : "Native HTML",
ownerUserId: userId,
...(githubSourceId
? {
installKind: "github" as const,
githubSourceId,
githubPath: "skills/html",
githubCurrentCommit: CANARY_COMMIT,
githubCurrentContentHash: CANARY_CONTENT_HASH,
githubCurrentStatus: "present" as const,
githubCurrentCheckedAt: 1,
githubScanStatus: "clean" as const,
}
: {}),
tags: {},
moderationStatus: "active",
statsDownloads: options.downloads,
statsStars: options.bookmarks ?? 0,
statsInstallsCurrent: options.openClawInstalls ?? 0,
statsInstallsAllTime: options.openClawInstalls ?? 0,
statsSkillsShInstalls: options.skillsShInstalls,
statsGithubStars: options.githubStars,
stats: {
downloads: options.downloads,
stars: options.bookmarks ?? 0,
installsCurrent: options.openClawInstalls ?? 0,
installsAllTime: options.openClawInstalls ?? 0,
versions: 0,
comments: 0,
},
createdAt: 1,
updatedAt: 1,
});
if (options.seedDigest) {
const skill = await ctx.db.get(skillId);
if (!skill) throw new Error("seeded native skill missing");
await ctx.db.insert("skillSearchDigest", {
...extractDigestFields(skill),
ownerHandle: "native-owner",
ownerKind: "user",
ownerName: "Native Owner",
ownerDisplayName: "Native Owner",
});
}
return skillId;
});
}
describe("skills.sh controlled hidden metadata canary", () => {
afterEach(() => {
vi.useRealTimers();
vi.unstubAllEnvs();
});
it("records a new external skill without creating native state", async () => {
useEnvironment(LOCAL_ENV);
const t = convexTest(schema, modules);
await configureCanary(t);
const { runId, run } = await runCanary(t);
const readback = await t.query(internal.skillsShCatalog.getRunReconciliationInternal, {
runId,
});
expect(run).toMatchObject({
status: "completed",
counts: {
observed: 1,
inserted: 1,
newExternal: 1,
exactNativeMatches: 0,
routeCollisions: 0,
claimOpportunities: 1,
scansPlanned: 1,
scansAdmitted: 0,
},
});
expect(readback).toMatchObject({
reconciled: true,
mismatches: [],
entries: [
{
externalId: CANARY_EXTERNAL_ID,
githubOwnerId: 20_157_849,
githubPath: "skills/html",
githubCommit: CANARY_COMMIT,
githubContentHash: CANARY_CONTENT_HASH,
publicVisible: false,
reconciliation: {
kind: "new",
claimOpportunity: true,
claimPublisherHandle: "patrick-erichsen",
},
resolution: {
installable: false,
},
},
],
});
expect(await t.run(async (ctx) => await ctx.db.query("skills").collect())).toHaveLength(0);
expect(
await t.run(async (ctx) => await ctx.db.query("securityScanJobs").collect()),
).toHaveLength(0);
});
it("attaches upstream metrics to an exact native match without rewriting native counters", async () => {
vi.useFakeTimers();
useEnvironment(LOCAL_ENV);
const t = convexTest(schema, modules);
const nativeSkillId = await seedNativeSkill(t, {
exactSource: true,
downloads: 143,
bookmarks: 5,
openClawInstalls: 11,
skillsShInstalls: 2,
githubStars: 300,
seedDigest: true,
});
await configureCanary(t);
const { runId, run } = await runCanary(t);
await t.finishAllScheduledFunctions(vi.runAllTimers);
const readback = await t.query(internal.skillsShCatalog.getRunReconciliationInternal, {
runId,
});
const native = await t.run(async (ctx) => await ctx.db.get(nativeSkillId));
const digest = await t.run(async (ctx) =>
ctx.db
.query("skillSearchDigest")
.withIndex("by_skill", (q) => q.eq("skillId", nativeSkillId))
.unique(),
);
expect(run.counts).toMatchObject({
newExternal: 0,
exactNativeMatches: 1,
routeCollisions: 0,
});
expect(readback.entries[0]).toMatchObject({
reconciliation: {
kind: "exact-native",
nativeSkillId,
nativeStatsDownloads: 143,
claimOpportunity: true,
},
});
expect(native).toMatchObject({
_id: nativeSkillId,
statsDownloads: 143,
statsStars: 5,
statsInstallsCurrent: 11,
statsInstallsAllTime: 11,
statsSkillsShInstalls: 17,
statsGithubStars: 321,
stats: {
downloads: 143,
stars: 5,
installsCurrent: 11,
installsAllTime: 11,
},
githubCurrentCommit: CANARY_COMMIT,
githubCurrentContentHash: CANARY_CONTENT_HASH,
});
expect(digest).toMatchObject({
statsDownloads: 143,
statsSkillsShInstalls: 17,
statsGithubStars: 321,
});
});
it("preserves exact-native upstream metric history when the controlled entry is removed", async () => {
vi.useFakeTimers();
useEnvironment(LOCAL_ENV);
const t = convexTest(schema, modules);
const nativeSkillId = await seedNativeSkill(t, {
exactSource: true,
downloads: 143,
bookmarks: 5,
openClawInstalls: 11,
seedDigest: true,
});
await configureCanary(t);
const { runId } = await runCanary(t);
await t.finishAllScheduledFunctions(vi.runAllTimers);
const rollback = await t.mutation(internal.skillsShCatalog.rollbackFixtureRunInternal, {
runId,
actor: "codex-test",
reason: "remove the controlled exact-native metadata",
confirm: "rollback-skills-sh-controlled-canary",
});
const native = await t.run(async (ctx) => await ctx.db.get(nativeSkillId));
const digest = await t.run(async (ctx) =>
ctx.db
.query("skillSearchDigest")
.withIndex("by_skill", (q) => q.eq("skillId", nativeSkillId))
.unique(),
);
expect(rollback).toMatchObject({
deletedEntries: 1,
nativeSkillsChanged: 0,
});
expect(native?.statsSkillsShInstalls).toBe(17);
expect(native?.statsGithubStars).toBe(321);
expect(digest?.statsSkillsShInstalls).toBe(17);
expect(digest?.statsGithubStars).toBe(321);
expect(native).toMatchObject({
statsDownloads: 143,
statsStars: 5,
statsInstallsCurrent: 11,
statsInstallsAllTime: 11,
stats: {
downloads: 143,
stars: 5,
installsCurrent: 11,
installsAllTime: 11,
},
});
});
it("preserves upstream metric history when an exact native match becomes a route collision", async () => {
vi.useFakeTimers();
useEnvironment(LOCAL_ENV);
const t = convexTest(schema, modules);
const nativeSkillId = await seedNativeSkill(t, {
exactSource: true,
downloads: 143,
skillsShInstalls: 2,
githubStars: 300,
seedDigest: true,
});
await configureCanary(t);
await runCanary(t);
await t.finishAllScheduledFunctions(vi.runAllTimers);
await t.run(async (ctx) => {
await ctx.db.patch(nativeSkillId, {
githubCurrentCommit: "f".repeat(40),
});
});
const { run } = await runCanary(t);
await t.finishAllScheduledFunctions(vi.runAllTimers);
const native = await t.run(async (ctx) => await ctx.db.get(nativeSkillId));
const digest = await t.run(async (ctx) =>
ctx.db
.query("skillSearchDigest")
.withIndex("by_skill", (q) => q.eq("skillId", nativeSkillId))
.unique(),
);
expect(run.counts).toMatchObject({
exactNativeMatches: 0,
routeCollisions: 1,
});
expect(native?.statsSkillsShInstalls).toBe(17);
expect(native?.statsGithubStars).toBe(321);
expect(digest?.statsSkillsShInstalls).toBe(17);
expect(digest?.statsGithubStars).toBe(321);
expect(native).toMatchObject({
statsDownloads: 143,
stats: { downloads: 143 },
});
});
it("records a route collision without changing or attaching the native skill", async () => {
useEnvironment(LOCAL_ENV);
const t = convexTest(schema, modules);
const nativeSkillId = await seedNativeSkill(t, { exactSource: false, downloads: 77 });
await configureCanary(t);
const { runId, run } = await runCanary(t);
const readback = await t.query(internal.skillsShCatalog.getRunReconciliationInternal, {
runId,
});
const native = await t.run(async (ctx) => await ctx.db.get(nativeSkillId));
expect(run.counts).toMatchObject({
newExternal: 0,
exactNativeMatches: 0,
routeCollisions: 1,
});
expect(readback.entries[0]).toMatchObject({
reconciliation: {
kind: "route-collision",
nativeSkillId,
nativeStatsDownloads: 77,
claimOpportunity: true,
},
});
expect(native).toMatchObject({
_id: nativeSkillId,
statsDownloads: 77,
stats: { downloads: 77 },
});
expect(native?.ownerPublisherId).toBeUndefined();
});
it("reruns idempotently and rolls back only the hidden canary metadata", async () => {
useEnvironment(LOCAL_ENV);
const t = convexTest(schema, modules);
const nativeSkillId = await seedNativeSkill(t, { exactSource: false, downloads: 91 });
await configureCanary(t);
const first = await runCanary(t);
const repeated = await runCanary(t);
expect(repeated.run.counts).toMatchObject({
observed: 1,
inserted: 0,
updated: 0,
unchanged: 1,
scansPlanned: 0,
routeCollisions: 1,
});
const rollback = await t.mutation(internal.skillsShCatalog.rollbackFixtureRunInternal, {
runId: repeated.runId,
actor: "codex-test",
reason: "remove only the controlled canary metadata",
confirm: "rollback-skills-sh-controlled-canary",
});
const native = await t.run(async (ctx) => await ctx.db.get(nativeSkillId));
const catalogEntries = await t.run(
async (ctx) => await ctx.db.query("skillsShCatalogEntries").collect(),
);
expect(rollback).toMatchObject({
fixtureId: "patrick-html-canary-v1",
deletedEntries: 1,
nativeSkillsChanged: 0,
});
expect(catalogEntries).toHaveLength(0);
expect(native).toMatchObject({
_id: nativeSkillId,
statsDownloads: 91,
stats: { downloads: 91 },
});
expect(first.runId).not.toBe(repeated.runId);
});
it.each(["clean", "suspicious"] as const)(
"publishes only the exact %s canary attempt and resolves a pinned GitHub install",
async (verdict) => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
const attempt = await prepareScannedCanary(t);
await expect(completeScannedCanary(t, attempt, verdict)).resolves.toEqual({
ok: true,
applied: true,
publicVisible: true,
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toMatchObject({
ref: "skills-sh/patrick-erichsen/skills/html",
route: "/skills-sh/patrick-erichsen/skills/html",
artifact: {
contentHash: attempt.artifactContentHash,
files: [
{
path: "SKILL.md",
size: expect.any(Number),
sha256: expect.stringMatching(/^[a-f0-9]{64}$/),
contentType: "text/markdown",
},
],
},
security: {
verdict,
source: "clawhub",
attemptId: attempt._id,
},
install: {
ok: true,
slug: "skills-sh/patrick-erichsen/skills/html",
installKind: "github",
github: {
repo: "patrick-erichsen/skills",
path: "skills/html",
commit: CANARY_COMMIT,
contentHash: CANARY_CONTENT_HASH,
},
},
});
},
);
it("hides a published entry when database discovery is disabled", async () => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
const attempt = await prepareScannedCanary(t);
await completeScannedCanary(t, attempt, "clean");
await t.run(async (ctx) => {
const control = await ctx.db
.query("skillsShCatalogControls")
.withIndex("by_key", (q) => q.eq("key", "global"))
.unique();
if (!control) throw new Error("Missing skills.sh catalog control");
await ctx.db.patch(control._id, { discoveryEnabled: false });
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toBeNull();
});
it("omits verification artifacts when the scan request no longer matches the approved attempt", async () => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
const attempt = await prepareScannedCanary(t);
await completeScannedCanary(t, attempt, "clean");
await t.run(async (ctx) => {
await ctx.db.patch(attempt.skillScanRequestId, {
sha256hash: "0".repeat(64),
});
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toMatchObject({
ref: "skills-sh/patrick-erichsen/skills/html",
artifact: null,
security: { attemptId: attempt._id, verdict: "clean" },
});
});
it("reuses an exact completed canary scan without hiding the published entry", async () => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
const attempt = await prepareScannedCanary(t);
await completeScannedCanary(t, attempt, "clean");
await expect(
t.mutation(internal.skillsShCatalog.startControlledCanaryScanRunInternal, {
actor: "catalog-test-operator",
reason: "repeat the exact approved canary",
}),
).resolves.toEqual({
runId: attempt.runId,
externalId: CANARY_EXTERNAL_ID,
reused: true,
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toMatchObject({
ref: "skills-sh/patrick-erichsen/skills/html",
security: { attemptId: attempt._id, verdict: "clean" },
});
const attempts = await t.run(async (ctx) =>
ctx.db.query("skillsShCatalogScanAttempts").collect(),
);
expect(attempts).toHaveLength(1);
});
it("does not reuse or block on an exact deterministic fixture verdict", async () => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
await configureCanary(t);
const { runId: fixtureRunId } = await runCanary(t);
await t.run(async (ctx) => {
const entry = await ctx.db
.query("skillsShCatalogEntries")
.withIndex("by_external_id", (q) => q.eq("externalId", CANARY_EXTERNAL_ID))
.unique();
if (!entry) throw new Error("controlled canary entry was not created");
await ctx.db.insert("skillsShCatalogScanAttempts", {
entryId: entry._id,
runId: fixtureRunId,
externalId: entry.externalId,
githubOwnerId: entry.githubOwnerId,
owner: entry.owner,
repo: entry.repo,
slug: entry.slug,
githubPath: entry.githubPath,
githubCommit: entry.githubCommit,
githubContentHash: entry.githubContentHash,
sourceContentHash: entry.sourceContentHash,
source: "skills-sh-catalog-fixture",
dispatchKind: "deterministic",
priority: "low",
status: "succeeded",
verdict: "clean",
completedAt: 1,
createdAt: 1,
updatedAt: 1,
});
});
await t.mutation(internal.skillsShCatalog.configureFixtureControlInternal, {
...CANARY_CONTROL,
mode: "staging-live",
scanAdmissionEnabled: true,
publicVisibilityEnabled: true,
maxWritesPerBatch: 7,
maxScanAdmissionsPerBatch: 1,
maxScanAdmissionsPerRun: 1,
maxScanAdmissionsPerDay: 1,
maxCatalogQueued: 1,
maxCatalogInFlight: 1,
realScanAllowlist: [CANARY_EXTERNAL_ID],
});
const actorUserId = await t.run(
async (ctx) =>
await ctx.db.insert("users", {
handle: "catalog-test-operator",
displayName: "Catalog Test Operator",
role: "admin",
}),
);
const started = await t.mutation(
internal.skillsShCatalog.startControlledCanaryScanRunInternal,
{
actor: "catalog-test-operator",
reason: "replace deterministic evidence with a real catalog scan",
},
);
expect(started).toMatchObject({
externalId: CANARY_EXTERNAL_ID,
reused: false,
});
expect(started.runId).not.toBe(fixtureRunId);
await expect(
t.action(internal.skillsShCatalog.admitRealScansInternal, {
runId: started.runId,
externalIds: [CANARY_EXTERNAL_ID],
actorUserId,
artifacts: [await storeCanaryArtifact(t)],
}),
).resolves.toMatchObject({ admitted: 1, skipped: 0 });
});
it("does not let a stale real verdict block an exact replacement scan", async () => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
await configureCanary(t);
const { runId: fixtureRunId } = await runCanary(t);
await t.run(async (ctx) => {
const entry = await ctx.db
.query("skillsShCatalogEntries")
.withIndex("by_external_id", (q) => q.eq("externalId", CANARY_EXTERNAL_ID))
.unique();
if (!entry) throw new Error("controlled canary entry was not created");
await ctx.db.insert("skillsShCatalogScanAttempts", {
entryId: entry._id,
runId: fixtureRunId,
externalId: entry.externalId,
githubOwnerId: entry.githubOwnerId,
owner: entry.owner,
repo: entry.repo,
slug: entry.slug,
githubPath: entry.githubPath,
githubCommit: "1".repeat(40),
githubContentHash: entry.githubContentHash,
sourceContentHash: entry.sourceContentHash,
source: "skills-sh-catalog-test",
dispatchKind: "real",
priority: "low",
status: "succeeded",
verdict: "clean",
completedAt: 1,
createdAt: 1,
updatedAt: 1,
});
});
await t.mutation(internal.skillsShCatalog.configureFixtureControlInternal, {
...CANARY_CONTROL,
mode: "staging-live",
scanAdmissionEnabled: true,
publicVisibilityEnabled: true,
maxWritesPerBatch: 7,
maxScanAdmissionsPerBatch: 1,
maxScanAdmissionsPerRun: 1,
maxScanAdmissionsPerDay: 2,
maxCatalogQueued: 1,
maxCatalogInFlight: 1,
realScanAllowlist: [CANARY_EXTERNAL_ID],
});
const actorUserId = await t.run(
async (ctx) =>
await ctx.db.insert("users", {
handle: "catalog-test-operator",
displayName: "Catalog Test Operator",
role: "admin",
}),
);
const started = await t.mutation(
internal.skillsShCatalog.startControlledCanaryScanRunInternal,
{
actor: "catalog-test-operator",
reason: "replace stale real evidence with an exact scan",
},
);
await expect(
t.action(internal.skillsShCatalog.admitRealScansInternal, {
runId: started.runId,
externalIds: [CANARY_EXTERNAL_ID],
actorUserId,
artifacts: [await storeCanaryArtifact(t)],
}),
).resolves.toMatchObject({ admitted: 1, skipped: 0 });
});
it("rejects a scan artifact that differs from the authenticated GitHub folder", async () => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
await configureCanary(t);
await runCanary(t);
await t.mutation(internal.skillsShCatalog.configureFixtureControlInternal, {
...CANARY_CONTROL,
mode: "staging-live",
scanAdmissionEnabled: true,
publicVisibilityEnabled: true,
maxWritesPerBatch: 7,
maxScanAdmissionsPerBatch: 1,
maxScanAdmissionsPerRun: 1,
maxScanAdmissionsPerDay: 1,
maxCatalogQueued: 1,
maxCatalogInFlight: 1,
realScanAllowlist: [CANARY_EXTERNAL_ID],
});
const actorUserId = await t.run(
async (ctx) =>
await ctx.db.insert("users", {
handle: "catalog-test-operator",
displayName: "Catalog Test Operator",
role: "admin",
}),
);
const { runId } = await t.mutation(
internal.skillsShCatalog.startControlledCanaryScanRunInternal,
{
actor: "catalog-test-operator",
reason: "reject changed canary content",
},
);
const changedArtifact = await storeCanaryArtifact(t, `${canarySkillMarkdown}\nchanged\n`);
await expect(
t.action(internal.skillsShCatalog.admitRealScansInternal, {
runId,
externalIds: [CANARY_EXTERNAL_ID],
actorUserId,
artifacts: [changedArtifact],
}),
).rejects.toThrow("real Test scan artifact does not match authenticated GitHub content");
const attempts = await t.run(async (ctx) =>
ctx.db.query("skillsShCatalogScanAttempts").collect(),
);
expect(attempts).toHaveLength(0);
});
it.each(["malicious", "failed"] as const)(
"keeps a %s canary hidden and non-installable",
async (verdict) => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
const attempt = await prepareScannedCanary(t);
await expect(completeScannedCanary(t, attempt, verdict)).resolves.toEqual({
ok: true,
applied: true,
publicVisible: false,
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toBeNull();
},
);
it.each(["malicious", "failed"] as const)(
"admits a fresh exact attempt after a %s canary scan",
async (verdict) => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
const blockedAttempt = await prepareScannedCanary(t);
await completeScannedCanary(t, blockedAttempt, verdict);
await t.mutation(internal.skillsShCatalog.configureFixtureControlInternal, {
...CANARY_CONTROL,
mode: "staging-live",
scanAdmissionEnabled: true,
publicVisibilityEnabled: true,
maxWritesPerBatch: 7,
maxScanAdmissionsPerBatch: 1,
maxScanAdmissionsPerRun: 1,
maxScanAdmissionsPerDay: 2,
maxCatalogQueued: 1,
maxCatalogInFlight: 1,
realScanAllowlist: [CANARY_EXTERNAL_ID],
});
const retry = await t.mutation(
internal.skillsShCatalog.startControlledCanaryScanRunInternal,
{
actor: "catalog-test-operator",
reason: `retry the exact canary after a ${verdict} scan`,
},
);
expect(retry).toMatchObject({
externalId: CANARY_EXTERNAL_ID,
reused: false,
});
expect(retry.runId).not.toBe(blockedAttempt.runId);
const actorUserId = await t.run(
async (ctx) =>
(await ctx.db
.query("users")
.filter((q) => q.eq(q.field("handle"), "catalog-test-operator"))
.unique())!._id,
);
const artifact = await storeCanaryArtifact(t);
await expect(
t.action(internal.skillsShCatalog.admitRealScansInternal, {
runId: retry.runId,
externalIds: [CANARY_EXTERNAL_ID],
actorUserId,
artifacts: [artifact],
}),
).resolves.toMatchObject({ admitted: 1, skipped: 0 });
},
);
it.each([
["githubPath", "skills/changed"],
["githubCommit", "1".repeat(40)],
["githubContentHash", "2".repeat(64)],
] as const)("rejects a stale callback after the entry %s changes", async (field, value) => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
const attempt = await prepareScannedCanary(t);
await t.run(async (ctx) => {
await ctx.db.patch(attempt.entryId, { [field]: value, updatedAt: Date.now() });
});
await expect(completeScannedCanary(t, attempt, "clean")).resolves.toEqual({
ok: true,
applied: false,
reason: "stale-attempt",
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toBeNull();
});
it("blocks promotion while paused, then supports idempotent publication rollback", async () => {
useEnvironment(TEST_ENV);
const t = convexTest(schema, modules);
const pausedAttempt = await prepareScannedCanary(t);
await t.mutation(internal.skillsShCatalog.setCatalogPausedInternal, {
paused: true,
actor: "catalog-test-operator",
reason: "prove catalog-only pause",
confirm: "set-skills-sh-test-pause",
});
await expect(completeScannedCanary(t, pausedAttempt, "clean")).resolves.toEqual({
ok: true,
applied: true,
publicVisible: false,
});
await t.mutation(internal.skillsShCatalog.setCatalogPausedInternal, {
paused: false,
actor: "catalog-test-operator",
reason: "resume after paused callback proof",
confirm: "set-skills-sh-test-pause",
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toBeNull();
await expect(
t.mutation(internal.skillsShCatalog.startControlledCanaryScanRunInternal, {
actor: "catalog-test-operator",
reason: "publish the exact completed canary after resume",
}),
).resolves.toEqual({
runId: pausedAttempt.runId,
externalId: CANARY_EXTERNAL_ID,
reused: true,
});
const publishedAttempt = pausedAttempt;
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toMatchObject({
security: { attemptId: publishedAttempt._id, verdict: "clean" },
});
await t.mutation(internal.skillsShCatalog.rollbackPublicationInternal, {
externalId: CANARY_EXTERNAL_ID,
attemptId: publishedAttempt._id,
actor: "catalog-test-operator",
reason: "prove exact publication rollback",
confirm: "rollback-skills-sh-test-publication",
});
await expect(
t.run(async (ctx) => await ctx.db.get(publishedAttempt._id)),
).resolves.toMatchObject({
publicationRolledBackAt: expect.any(Number),
});
await expect(completeScannedCanary(t, publishedAttempt, "clean")).resolves.toEqual({
ok: true,
applied: true,
publicVisible: false,
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toBeNull();
await t.mutation(internal.skillsShCatalog.configureFixtureControlInternal, {
...CANARY_CONTROL,
mode: "staging-live",
scanAdmissionEnabled: true,
publicVisibilityEnabled: true,
maxWritesPerBatch: 7,
maxScanAdmissionsPerBatch: 1,
maxScanAdmissionsPerRun: 1,
maxScanAdmissionsPerDay: 2,
maxCatalogQueued: 1,
maxCatalogInFlight: 1,
realScanAllowlist: [CANARY_EXTERNAL_ID],
});
const replacementRun = await t.mutation(
internal.skillsShCatalog.startControlledCanaryScanRunInternal,
{
actor: "catalog-test-operator",
reason: "publish a replacement after rollback",
},
);
const actorUserId = await t.run(
async (ctx) =>
(await ctx.db
.query("users")
.filter((q) => q.eq(q.field("handle"), "catalog-test-operator"))
.first())!._id,
);
await t.action(internal.skillsShCatalog.admitRealScansInternal, {
runId: replacementRun.runId,
externalIds: [CANARY_EXTERNAL_ID],
actorUserId,
artifacts: [await storeCanaryArtifact(t)],
});
const replacementAttempt = await t.run(async (ctx) => {
const attempt = await ctx.db
.query("skillsShCatalogScanAttempts")
.withIndex("by_run", (q) => q.eq("runId", replacementRun.runId))
.unique();
if (!attempt?.skillScanRequestId || !attempt.securityScanJobId) {
throw new Error("replacement canary scan admission did not create linked work");
}
await ctx.db.patch(attempt._id, { status: "running", updatedAt: Date.now() });
await ctx.db.patch(attempt.skillScanRequestId, {
status: "running",
updatedAt: Date.now(),
});
await ctx.db.patch(attempt.securityScanJobId, {
status: "running",
leaseToken: "replacement-lease",
leaseExpiresAt: Date.now() + 60_000,
workerId: "replacement-worker",
updatedAt: Date.now(),
});
return attempt;
});
await t.mutation(internal.securityScan.completeCatalogSkillScanJobInternal, {
attemptId: replacementAttempt._id,
scanId: replacementAttempt.skillScanRequestId!,
jobId: replacementAttempt.securityScanJobId!,
leaseToken: "replacement-lease",
artifactContentHash: replacementAttempt.artifactContentHash!,
verdict: "clean",
runId: "replacement-clawscan-run",
llmAnalysis: { status: "clean", checkedAt: Date.now() },
});
await expect(
t.mutation(internal.skillsShCatalog.rollbackPublicationInternal, {
externalId: CANARY_EXTERNAL_ID,
attemptId: publishedAttempt._id,
actor: "catalog-test-operator",
reason: "retry the old rollback after replacement publication",
confirm: "rollback-skills-sh-test-publication",
}),
).resolves.toMatchObject({
externalId: CANARY_EXTERNAL_ID,
publicVisible: true,
alreadyRolledBack: true,
});
await expect(
t.query(api.skillsShCatalog.getPublicEntry, {
owner: "patrick-erichsen",
repo: "skills",
slug: "html",
}),
).resolves.toMatchObject({
security: { attemptId: replacementAttempt._id, verdict: "clean" },
});
});
});