diff --git a/convex/httpApiV1.handlers.test.ts b/convex/httpApiV1.handlers.test.ts index 73ddbd01..cdef83b0 100644 --- a/convex/httpApiV1.handlers.test.ts +++ b/convex/httpApiV1.handlers.test.ts @@ -37,6 +37,7 @@ const { const { fetchGitHubRepositoryIdentity, verifyGitHubActionsTrustedPublishJwt } = await import("./lib/githubActionsOidc"); const { buildBundleFingerprint } = await import("./lib/skillCards"); +const { sha256Hex } = await import("./lib/clawpack"); const { publishVersionForUser } = await import("./skills"); const { __handlers } = await import("./httpApiV1"); @@ -14385,6 +14386,8 @@ describe("httpApiV1 handlers", () => { it("npm mirror tarball downloads record package installs and download metrics", async () => { vi.stubEnv("TRUST_FORWARDED_IPS", "true"); + const tarballBytes = new TextEncoder().encode("tarball"); + const artifactSha256 = await sha256Hex(tarballBytes); const runQuery = vi.fn(async (_query: unknown, args: Record) => { if ("name" in args && !("paginationOpts" in args)) { return { @@ -14418,6 +14421,7 @@ describe("httpApiV1 handlers", () => { files: [], artifactKind: "npm-pack", clawpackStorageId: "storage:clawpack", + clawpackSha256: artifactSha256, npmIntegrity: "sha512-demo", npmShasum: "d".repeat(40), npmTarballName: "demo-plugin-1.0.0.tgz", @@ -14436,7 +14440,7 @@ describe("httpApiV1 handlers", () => { runQuery, runMutation, storage: { - get: vi.fn(async () => new Blob(["tarball"], { type: "application/octet-stream" })), + get: vi.fn(async () => new Blob([tarballBytes], { type: "application/octet-stream" })), }, }), new Request("https://example.com/api/npm/demo-plugin/-/demo-plugin-1.0.0.tgz", { @@ -14445,6 +14449,9 @@ describe("httpApiV1 handlers", () => { ); expect(response.status).toBe(200); + expect(new Uint8Array(await response.arrayBuffer())).toEqual(tarballBytes); + expect(response.headers.get("X-ClawHub-Artifact-Sha256")).toBe(artifactSha256); + expect(response.headers.get("ETag")).toBe(`"sha256:${artifactSha256}"`); expect(runMutation).toHaveBeenCalledWith( internal.packages.recordPackageInstallInternal, expect.objectContaining({ @@ -15708,6 +15715,40 @@ describe("httpApiV1 handlers", () => { }, ); + it("rejects loose Claw files before multipart storage when the experiment is enabled", async () => { + vi.stubEnv("CLAWHUB_EXPERIMENTAL_CLAWS", "1"); + vi.mocked(getOptionalApiTokenUserId).mockResolvedValue("users:1" as never); + vi.mocked(requirePackagePublishAuth).mockResolvedValue({ + kind: "user", + userId: "users:1", + user: { _id: "users:1", handle: "p" }, + } as never); + const form = packagePublishForm(packagePublishMetadata({ family: "claw" })); + form.append("files", new File(["manifest"], "CLAW.md", { type: "text/markdown" })); + const storageStore = vi.fn(); + const runAction = vi.fn(); + + const response = await __handlers.publishPackageV1Handler( + makeCtx({ + runAction, + runMutation: vi.fn().mockResolvedValue(okRate()), + storage: { store: storageStore }, + }), + new Request("https://example.com/api/v1/packages", { + method: "POST", + headers: { Authorization: "Bearer clh_test" }, + body: form, + }), + ); + + expect(response.status).toBe(400); + expect(await response.text()).toBe( + "Claw publication requires an already-built package tarball (.tgz)", + ); + expect(storageStore).not.toHaveBeenCalled(); + expect(runAction).not.toHaveBeenCalled(); + }); + it("package publish rejects browser session auth when token auth is not an API token", async () => { vi.mocked(getAuthUserId).mockResolvedValue("users:session" as never); vi.mocked(requirePackagePublishAuth).mockRejectedValue(new Error("Unauthorized")); @@ -15888,10 +15929,7 @@ describe("httpApiV1 handlers", () => { user: { _id: "users:1", handle: "p" }, } as never); const runMutation = vi.fn().mockResolvedValue(okRate()); - const runAction = vi - .fn() - .mockResolvedValue({ ok: true, packageId: "pkg:claw", releaseId: "rel:claw" }); - const storageStore = vi.fn(async () => `storage:${storageStore.mock.calls.length}`); + const storageStore = vi.fn(async (_blob: Blob) => `storage:${storageStore.mock.calls.length}`); const pack = npmPackFixture({ "package/package.json": JSON.stringify({ name: "demo-claw", @@ -15901,6 +15939,13 @@ describe("httpApiV1 handlers", () => { "package/CLAW.md": "---\nschemaVersion: 1\nagent:\n id: demo-claw\n---\nYou are a focused demo agent.\n", }); + const artifactSha256 = await sha256Hex(pack); + const runAction = vi.fn().mockResolvedValue({ + ok: true, + packageId: "pkg:claw", + releaseId: "rel:claw", + artifactSha256, + }); const form = new FormData(); form.set( "payload", @@ -15909,6 +15954,7 @@ describe("httpApiV1 handlers", () => { family: "claw", version: "1.0.0", changelog: "init", + expectedArtifactSha256: artifactSha256, }), ); form.append( @@ -15928,12 +15974,17 @@ describe("httpApiV1 handlers", () => { ); expect(response.status).toBe(200); + await expect(response.json()).resolves.toMatchObject({ artifactSha256 }); expect(storageStore).toHaveBeenCalledTimes(3); + const storedArtifact = storageStore.mock.calls[0]?.[0]; + expect(storedArtifact).toBeInstanceOf(Blob); + expect(new Uint8Array(await (storedArtifact as Blob).arrayBuffer())).toEqual(pack); expect(runAction).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ payload: expect.objectContaining({ family: "claw", + expectedArtifactSha256: artifactSha256, artifact: expect.objectContaining({ kind: "npm-pack", npmFileCount: 2 }), files: [ expect.objectContaining({ path: "package.json" }), @@ -15944,6 +15995,79 @@ describe("httpApiV1 handlers", () => { ); }); + it.each([ + { + label: "package name", + metadata: { name: "other-claw", version: "1.0.0" }, + digest: "actual", + message: "Claw package name mismatch", + }, + { + label: "package version", + metadata: { name: "demo-claw", version: "2.0.0" }, + digest: "actual", + message: "Claw package version mismatch", + }, + { + label: "artifact digest", + metadata: { name: "demo-claw", version: "1.0.0" }, + digest: "0".repeat(64), + message: "Claw artifact SHA-256 mismatch", + }, + ])("rejects a Claw tarball with mismatched $label before storing it", async (testCase) => { + vi.stubEnv("CLAWHUB_EXPERIMENTAL_CLAWS", "1"); + vi.mocked(getOptionalApiTokenUserId).mockResolvedValue("users:1" as never); + vi.mocked(requirePackagePublishAuth).mockResolvedValue({ + kind: "user", + userId: "users:1", + user: { _id: "users:1", handle: "p" }, + } as never); + const pack = npmPackFixture({ + "package/package.json": JSON.stringify({ + name: "demo-claw", + version: "1.0.0", + openclaw: { claw: "CLAW.md" }, + }), + "package/CLAW.md": "---\nschemaVersion: 1\nagent:\n id: demo-claw\n---\nDemo.\n", + }); + const expectedArtifactSha256 = + testCase.digest === "actual" ? await sha256Hex(pack) : testCase.digest; + const form = packagePublishForm({ + ...packagePublishMetadata({ + family: "claw", + name: testCase.metadata.name, + version: testCase.metadata.version, + }), + expectedArtifactSha256, + }); + form.append( + "clawpack", + new File([bytesToArrayBuffer(pack)], "demo-claw-1.0.0.tgz", { + type: "application/octet-stream", + }), + ); + const storageStore = vi.fn(); + const runAction = vi.fn(); + + const response = await __handlers.publishPackageV1Handler( + makeCtx({ + runAction, + runMutation: vi.fn().mockResolvedValue(okRate()), + storage: { store: storageStore }, + }), + new Request("https://example.com/api/v1/packages", { + method: "POST", + headers: { Authorization: "Bearer clh_test" }, + body: form, + }), + ); + + expect(response.status).toBe(400); + expect(await response.text()).toContain(testCase.message); + expect(storageStore).not.toHaveBeenCalled(); + expect(runAction).not.toHaveBeenCalled(); + }); + it("staged ClawPack publish derives artifact metadata from stored bytes", async () => { vi.mocked(getOptionalApiTokenUserId).mockResolvedValue("users:1" as never); vi.mocked(requirePackagePublishAuth).mockResolvedValue({ @@ -16237,6 +16361,7 @@ describe("httpApiV1 handlers", () => { userId: "users:publisher", packageId: "packages:demo", releaseId: "packageReleases:demo", + artifactSha256: "a".repeat(64), name: "@openclaw/demo", version: "1.0.0", status: "finalized", @@ -16259,6 +16384,7 @@ describe("httpApiV1 handlers", () => { attemptId: "publishAttempts:demo", packageId: "packages:demo", releaseId: "packageReleases:demo", + artifactSha256: "a".repeat(64), name: "@openclaw/demo", version: "1.0.0", status: "finalized", diff --git a/convex/httpApiV1/packagesV1.ts b/convex/httpApiV1/packagesV1.ts index 70875446..472a49cd 100644 --- a/convex/httpApiV1/packagesV1.ts +++ b/convex/httpApiV1/packagesV1.ts @@ -1439,6 +1439,32 @@ async function buildPackagePublishRequestFromClawPack( return { ...metadata, files, artifact }; } +function assertClawPackPublicationIdentity( + metadata: PackagePublishMetadata, + parsed: ParsedPackageClawPack, +) { + if (metadata.family !== "claw") return; + const expectedName = tryNormalizePackageName(metadata.name); + if (!expectedName || parsed.packageName !== expectedName) { + throw new Error( + `Claw package name mismatch: expected ${expectedName ?? metadata.name}, got ${parsed.packageName}`, + ); + } + const expectedVersion = metadata.version.trim(); + if (parsed.packageVersion !== expectedVersion) { + throw new Error( + `Claw package version mismatch: expected ${expectedVersion}, got ${parsed.packageVersion}`, + ); + } + const expectedDigest = metadata.expectedArtifactSha256?.trim().toLowerCase(); + if (!expectedDigest) throw new Error("Claw publication requires expectedArtifactSha256"); + if (expectedDigest !== parsed.artifactSha256) { + throw new Error( + `Claw artifact SHA-256 mismatch: expected ${expectedDigest}, got ${parsed.artifactSha256}`, + ); + } +} + const PACKAGE_PUBLISH_FILE_FIELDS = ["files"] as const; const PACKAGE_PUBLISH_TARBALL_FIELDS = ["clawpack"] as const; const PACKAGE_PUBLISH_FORM_FIELDS = new Set([ @@ -1489,6 +1515,9 @@ async function parseMultipartPackagePublish( PACKAGE_PUBLISH_FILE_FIELDS, "Package publish file uploads must be files", ); + if (metadata.family === "claw" && !tarballPart) { + throw new Error("Claw publication requires an already-built package tarball (.tgz)"); + } if (tarballPart) { if (fileParts.length > 0) { @@ -1498,6 +1527,7 @@ async function parseMultipartPackagePublish( await consumePackageTarballUploadTicket(ctx, auth, tarballPart); const artifactBytes = await readStoredPackageTarball(ctx, tarballPart.storageId); const parsed = await parseClawPack(artifactBytes); + assertClawPackPublicationIdentity(metadata, parsed); return await buildPackagePublishRequestFromClawPack( ctx, metadata, @@ -1522,6 +1552,7 @@ async function parseMultipartPackagePublish( } const artifactBytes = new Uint8Array(await tarballEntry.arrayBuffer()); const parsed = await parseClawPack(artifactBytes); + assertClawPackPublicationIdentity(metadata, parsed); const artifactStorageId = await ctx.storage.store( new Blob([bytesToArrayBuffer(artifactBytes)], { type: "application/octet-stream" }), ); @@ -2426,6 +2457,7 @@ type PackagePublishAttemptStatusResult = { userId: Id<"users">; packageId: Id<"packages">; releaseId: Id<"packageReleases">; + artifactSha256?: string; name: string; version: string; status: @@ -2482,6 +2514,7 @@ export async function publishAttemptsGetRouterV1Handler(ctx: ActionCtx, request: attemptId: attempt.attemptId, packageId: attempt.packageId, releaseId: attempt.releaseId, + ...(attempt.artifactSha256 ? { artifactSha256: attempt.artifactSha256 } : {}), name: attempt.name, version: attempt.version, status: attempt.status, diff --git a/convex/migrations.ts b/convex/migrations.ts index 7dc25bcf..5ae89057 100644 --- a/convex/migrations.ts +++ b/convex/migrations.ts @@ -196,7 +196,10 @@ async function classifySuspiciousPublishAttemptPublicState( ) .unique(); if (!release) return "replay_missing"; - if (release.softDeletedAt || release.integritySha256 !== attempt.artifactFingerprint) { + const matchesArtifact = + release.integritySha256 === attempt.artifactFingerprint || + (pkg.family === "claw" && release.clawpackSha256 === attempt.artifactFingerprint); + if (release.softDeletedAt || !matchesArtifact) { return "public_conflict"; } return "replay_identical"; diff --git a/convex/packages.public.test.ts b/convex/packages.public.test.ts index 7a360894..2f0bc613 100644 --- a/convex/packages.public.test.ts +++ b/convex/packages.public.test.ts @@ -16,6 +16,7 @@ import { getPackageReleaseScanBackfillBatchInternal, getByName, list, + publishRelease, publishPackageForTrustedPublisherInternal, publishPackageForUserInternal, generateChangelogPreview, @@ -42,6 +43,7 @@ import { resolvePackageAppealForUserInternal, upsertOfficialPluginMigrationForUserInternal, getVersionByName, + getVersionByNameForViewerInternal, getVersionSecurityByNameForViewerInternal, insertReleaseInternal, cleanupReassignedPackageReleaseTagsInternal, @@ -56,6 +58,7 @@ import { listPublicNewPluginsPage, listPageForViewerInternal, listVersions, + listVersionsForViewerInternal, listVersionsForManager, updateReleaseLlmAnalysisInternal, updateReleaseStaticScanInternal, @@ -135,6 +138,12 @@ const getVersionByNameHandler = ( { package: { name: string; scanStatus?: string }; version: { version: string } } | null > )._handler; +const getVersionByNameForViewerInternalHandler = ( + getVersionByNameForViewerInternal as unknown as WrappedHandler< + { name: string; version: string; viewerUserId?: string }, + { package: { name: string }; version: { version: string; clawpackStorageId?: string } } | null + > +)._handler; const getVersionSecurityByNameForViewerInternalHandler = ( getVersionSecurityByNameForViewerInternal as unknown as WrappedHandler< { name: string; version: string; viewerUserId?: string }, @@ -246,6 +255,20 @@ const listVersionsHandler = ( } > )._handler; +const listVersionsForViewerInternalHandler = ( + listVersionsForViewerInternal as unknown as WrappedHandler< + { + name: string; + viewerUserId?: string; + paginationOpts: { cursor: string | null; numItems: number }; + }, + { + page: Array<{ version: string; clawpackStorageId?: string }>; + isDone: boolean; + continueCursor: string; + } + > +)._handler; const listVersionsForManagerHandler = ( listVersionsForManager as unknown as WrappedHandler< { @@ -277,7 +300,7 @@ const insertReleaseInternalHandler = ( }; name: string; displayName: string; - family: "skill" | "code-plugin" | "bundle-plugin"; + family: "skill" | "code-plugin" | "bundle-plugin" | "claw"; version: string; publicationStatus?: "pending" | "published"; changelog: string; @@ -328,6 +351,7 @@ const findPackagePublishResultInternalHandler = ( name: string; version: string; integritySha256: string; + clawpackSha256?: string; ownerUserId: string; ownerPublisherId?: string; }, @@ -421,6 +445,9 @@ const publishPackageForUserInternalHandler = ( unknown > )._handler; +const publishReleaseHandler = ( + publishRelease as unknown as WrappedHandler<{ payload: unknown }, unknown> +)._handler; const publishPackageForTrustedPublisherInternalHandler = ( publishPackageForTrustedPublisherInternal as unknown as WrappedHandler< { @@ -7122,6 +7149,51 @@ describe("packages public queries", () => { expect(releaseIndexNames).toContain("by_package_active_created"); }); + it("keeps ClawPack storage ids on internal downloadable version projections", async () => { + const release = makeReleaseDoc({ + files: [], + artifactKind: "npm-pack", + clawpackStorageId: "storage:clawpack", + clawpackSha256: "a".repeat(64), + }); + const { ctx } = makePackageCtx({ + pkg: makePackageDoc({ family: "claw" }), + latestRelease: release, + versionRelease: release, + versionsPage: { + page: [ + release, + makeReleaseDoc({ + _id: "packageReleases:legacy", + version: "0.9.0", + files: [], + }), + ], + isDone: true, + continueCursor: "", + }, + }); + + const listed = await listVersionsForViewerInternalHandler(ctx, { + name: "demo-plugin", + paginationOpts: { cursor: null, numItems: 10 }, + }); + const exact = await getVersionByNameForViewerInternalHandler(ctx, { + name: "demo-plugin", + version: "1.0.0", + }); + + expect(listed.page[0]).toMatchObject({ + version: "1.0.0", + clawpackStorageId: "storage:clawpack", + }); + expect(exact?.version).toMatchObject({ + version: "1.0.0", + clawpackStorageId: "storage:clawpack", + }); + expect(listed.page[1]).not.toHaveProperty("clawpackStorageId"); + }); + it("fills public package version pages after skipping pending releases", async () => { const releases = [ makeReleaseDoc({ @@ -8555,6 +8627,40 @@ describe("packages public queries", () => { }); }); + it("does not recover a Claw publish result for different exact artifact bytes", async () => { + const ctx = { + db: { + query: vi.fn((table: string) => ({ + withIndex: vi.fn(() => ({ + unique: vi.fn().mockResolvedValue( + table === "packages" + ? makePackageDoc({ + family: "claw", + ownerUserId: "users:owner", + ownerPublisherId: "publishers:owner", + }) + : makeReleaseDoc({ + integritySha256: "same-extracted-files", + clawpackSha256: "a".repeat(64), + }), + ), + })), + })), + }, + }; + + await expect( + findPackagePublishResultInternalHandler(ctx as never, { + name: "demo-claw", + version: "1.0.0", + integritySha256: "same-extracted-files", + clawpackSha256: "b".repeat(64), + ownerUserId: "users:owner", + ownerPublisherId: "publishers:owner", + }), + ).resolves.toBeNull(); + }); + it("does not recover pending package publish results as public successes", async () => { const release = makeReleaseDoc({ integritySha256: "abc123", @@ -9791,6 +9897,103 @@ describe("packages public queries", () => { expect(ctx.patch).not.toHaveBeenCalled(); }); + it("rejects a Claw version retry when the exact artifact digest differs", async () => { + const ctx = makeInsertReleaseCtx(makePackageDoc({ family: "claw" }), [ + makeReleaseDoc({ + _id: "packageReleases:existing", + version: "1.0.0", + integritySha256: "same-extracted-files", + clawpackSha256: "a".repeat(64), + }), + ]); + + await expect( + insertReleaseInternalHandler(ctx, { + actorUserId: "users:owner", + ownerUserId: "users:owner", + name: "demo-claw", + displayName: "Demo Claw", + family: "claw", + version: "1.0.0", + changelog: "retry", + tags: ["latest"], + summary: "demo", + files: [], + integritySha256: "same-extracted-files", + clawpackSha256: "b".repeat(64), + allowExistingRelease: true, + }), + ).rejects.toThrow("Version 1.0.0 already exists. Increment the version number and try again."); + }); + + it("treats an ordinary-user exact Claw artifact retry as idempotent", async () => { + const artifactSha256 = "a".repeat(64); + const ctx = makeInsertReleaseCtx(makePackageDoc({ family: "claw" }), [ + makeReleaseDoc({ + _id: "packageReleases:existing", + version: "1.0.0", + integritySha256: "same-extracted-files", + clawpackSha256: artifactSha256, + }), + ]); + + await expect( + insertReleaseInternalHandler(ctx, { + actorUserId: "users:owner", + ownerUserId: "users:owner", + name: "demo-claw", + displayName: "Demo Claw", + family: "claw", + version: "1.0.0", + changelog: "retry", + tags: ["latest"], + summary: "demo", + files: [], + integritySha256: "same-extracted-files", + clawpackSha256: artifactSha256, + }), + ).resolves.toMatchObject({ + ok: true, + packageId: "packages:demo", + releaseId: "packageReleases:existing", + }); + }); + + it.each(["pending", "blocked"] as const)( + "does not report a %s exact Claw release as published", + async (publicationStatus) => { + const artifactSha256 = "a".repeat(64); + const ctx = makeInsertReleaseCtx(makePackageDoc({ family: "claw" }), [ + makeReleaseDoc({ + _id: "packageReleases:pending", + version: "1.0.0", + publicationStatus, + integritySha256: "same-extracted-files", + clawpackSha256: artifactSha256, + }), + ]); + + await expect( + insertReleaseInternalHandler(ctx, { + actorUserId: "users:owner", + ownerUserId: "users:owner", + name: "demo-claw", + displayName: "Demo Claw", + family: "claw", + version: "1.0.0", + changelog: "retry", + tags: ["latest"], + summary: "demo", + files: [], + integritySha256: "same-extracted-files", + clawpackSha256: artifactSha256, + }), + ).rejects.toThrow( + "Version 1.0.0 already exists. Increment the version number and try again.", + ); + }, + ); + it("keeps an initial beta-only package publish off latest", async () => { const ctx = makeInsertReleaseCtx( makePackageDoc({ @@ -9876,6 +10079,19 @@ describe("packages public queries", () => { ).rejects.toThrow("Skill packages must use the skills publish flow"); }); + it("requires the exact-artifact HTTP flow for public Claw publishes", async () => { + await expect( + publishReleaseHandler({} as never, { + payload: { + name: "demo-claw", + family: "claw", + version: "1.0.0", + }, + }), + ).rejects.toThrow("Claw packages must use the exact-artifact HTTP publish flow"); + expect(getAuthUserId).not.toHaveBeenCalled(); + }); + it("rejects Claw publication before mutation when the experimental gate is disabled", async () => { const previous = process.env.CLAWHUB_EXPERIMENTAL_CLAWS; delete process.env.CLAWHUB_EXPERIMENTAL_CLAWS; @@ -9933,6 +10149,7 @@ describe("packages public queries", () => { const previous = process.env.CLAWHUB_EXPERIMENTAL_CLAWS; process.env.CLAWHUB_EXPERIMENTAL_CLAWS = "1"; const longClawDescription = "x".repeat(1_100); + const artifactSha256 = "a".repeat(64); const storedFiles = new Map([ [ "storage:package", @@ -10000,6 +10217,7 @@ describe("packages public queries", () => { family: "claw", version: "1.0.0", changelog: "init", + expectedArtifactSha256: artifactSha256, files: [ { path: "package.json", size: 1, storageId: "storage:package", sha256: "package" }, { @@ -10027,6 +10245,18 @@ describe("packages public queries", () => { sha256: "bootstrap", }, ], + artifact: { + kind: "npm-pack", + storageId: "storage:archive", + sha256: artifactSha256, + size: 3, + format: "tgz", + npmIntegrity: "sha512-demo", + npmShasum: "b".repeat(40), + npmTarballName: "demo-claw-1.0.0.tgz", + npmUnpackedSize: 3, + npmFileCount: 3, + }, }, }), ).resolves.toEqual({ @@ -10034,6 +10264,7 @@ describe("packages public queries", () => { packageId: "packages:claw", releaseId: "releases:claw-1", publicationStatus: "published", + artifactSha256, }); expect(runMutation).toHaveBeenCalledWith( @@ -10041,10 +10272,10 @@ describe("packages public queries", () => { expect.objectContaining({ family: "claw", summary: expect.any(String), - artifactKind: "legacy-zip", - clawpackStorageId: "storage:legacy-zip", - clawpackSha256: expect.stringMatching(/^[a-f0-9]{64}$/), - clawpackSize: expect.any(Number), + artifactKind: "npm-pack", + clawpackStorageId: "storage:archive", + clawpackSha256: artifactSha256, + clawpackSize: 3, clawManifestSummary: expect.objectContaining({ agent: expect.objectContaining({ id: "demo-claw", @@ -10068,6 +10299,243 @@ describe("packages public queries", () => { } }); + it("reuses an in-flight staged Claw publish for the same user and artifact", async () => { + const previousStage = process.env.CLAWHUB_STAGED_PREPUBLICATION_PUBLISHES; + process.env.CLAWHUB_STAGED_PREPUBLICATION_PUBLISHES = "1"; + const artifactSha256 = "a".repeat(64); + const storedFiles = new Map([ + [ + "storage:package", + JSON.stringify({ + name: "demo-claw", + version: "1.0.0", + openclaw: { claw: "manifests/CLAW.md" }, + }), + ], + [ + "storage:claw", + "---\nschemaVersion: 1\nagent:\n id: demo-claw\n name: Demo Claw\n---\nRun the demo workflow precisely.\n", + ], + ["storage:profile", "schemaVersion: 1\nagent:\n tools:\n profile: coding\n"], + ]); + const existingPackage = makePackageDoc({ + family: "claw", + ownerUserId: "users:owner", + ownerPublisherId: "publishers:owner", + }); + const existingRelease = makeReleaseDoc({ + _id: "packageReleases:pending", + packageId: "packages:demo", + publicationStatus: "pending", + clawpackSha256: artifactSha256, + }); + const runMutation = vi.fn(async (_ref: unknown, args: Record) => { + if (args.minimumRole === "publisher") { + return { publisherId: "publishers:owner", linkedUserId: "users:owner" }; + } + throw new Error("retry should not create another release or publish attempt"); + }); + const runQuery = vi + .fn() + .mockResolvedValueOnce(existingPackage) + .mockResolvedValueOnce(null) + .mockResolvedValueOnce({ + _id: "users:owner", + githubCreatedAt: Date.now() - 20 * 24 * 60 * 60 * 1000, + }) + .mockResolvedValueOnce({ + _id: "users:owner", + role: "user", + githubCreatedAt: Date.now() - 20 * 24 * 60 * 60 * 1000, + }) + .mockResolvedValueOnce({ + _id: "publishers:owner", + kind: "user", + handle: "owner", + linkedUserId: "users:owner", + }) + .mockResolvedValueOnce(existingRelease) + .mockResolvedValueOnce({ + attemptId: "publishAttempts:pending", + status: "pending_checks", + reusable: true, + packageId: "packages:demo", + releaseId: "packageReleases:pending", + artifactFingerprint: artifactSha256, + }); + const ctx = { + runQuery, + runMutation, + scheduler: { runAfter: vi.fn() }, + storage: { + get: vi.fn(async (storageId: string) => { + const content = storedFiles.get(storageId); + return content === undefined ? null : new Blob([content]); + }), + store: vi.fn(async () => "storage:legacy-zip"), + }, + }; + + try { + await expect( + publishPackageForUserInternalHandler(ctx as never, { + actorUserId: "users:owner", + payload: { + name: "demo-claw", + displayName: "Demo Claw", + family: "claw", + version: "1.0.0", + changelog: "retry", + ownerHandle: "owner", + expectedArtifactSha256: artifactSha256, + files: [ + { path: "package.json", size: 1, storageId: "storage:package", sha256: "package" }, + { + path: "manifests/CLAW.md", + size: 1, + storageId: "storage:claw", + sha256: "claw", + }, + { + path: "profiles/openclaw.yml", + size: 1, + storageId: "storage:profile", + sha256: "profile", + }, + ], + artifact: { + kind: "npm-pack", + storageId: "storage:archive", + sha256: artifactSha256, + size: 3, + format: "tgz", + npmIntegrity: "sha512-demo", + npmShasum: "b".repeat(40), + npmTarballName: "demo-claw-1.0.0.tgz", + npmUnpackedSize: 3, + npmFileCount: 3, + }, + }, + }), + ).resolves.toMatchObject({ + ok: true, + status: "pending", + packageId: "packages:demo", + releaseId: "packageReleases:pending", + artifactSha256, + publicationStatus: "pending", + attemptId: "publishAttempts:pending", + }); + + expect(runMutation).toHaveBeenCalledTimes(1); + expect(runQuery).toHaveBeenLastCalledWith( + expect.anything(), + expect.objectContaining({ + kind: "package", + slug: "demo-claw", + version: "1.0.0", + userId: "users:owner", + ownerUserId: "users:owner", + ownerPublisherId: "publishers:owner", + artifactFingerprint: artifactSha256, + }), + ); + + runQuery + .mockResolvedValueOnce(existingPackage) + .mockResolvedValueOnce(null) + .mockResolvedValueOnce({ + _id: "users:owner", + githubCreatedAt: Date.now() - 20 * 24 * 60 * 60 * 1000, + }) + .mockResolvedValueOnce({ + _id: "users:owner", + role: "user", + githubCreatedAt: Date.now() - 20 * 24 * 60 * 60 * 1000, + }) + .mockResolvedValueOnce({ + _id: "publishers:owner", + kind: "user", + handle: "owner", + linkedUserId: "users:owner", + }) + .mockResolvedValueOnce(existingRelease) + .mockResolvedValueOnce(null) + .mockResolvedValueOnce({ + attemptId: "publishAttempts:different-artifact", + }); + + await expect( + publishPackageForUserInternalHandler(ctx as never, { + actorUserId: "users:owner", + payload: { + name: "demo-claw", + displayName: "Demo Claw", + family: "claw", + version: "1.0.0", + changelog: "different artifact", + ownerHandle: "owner", + expectedArtifactSha256: "c".repeat(64), + files: [ + { path: "package.json", size: 1, storageId: "storage:package", sha256: "package" }, + { + path: "manifests/CLAW.md", + size: 1, + storageId: "storage:claw", + sha256: "claw", + }, + { + path: "profiles/openclaw.yml", + size: 1, + storageId: "storage:profile", + sha256: "profile", + }, + ], + artifact: { + kind: "npm-pack", + storageId: "storage:archive", + sha256: "c".repeat(64), + size: 3, + format: "tgz", + npmIntegrity: "sha512-different", + npmShasum: "d".repeat(40), + npmTarballName: "demo-claw-1.0.0.tgz", + npmUnpackedSize: 3, + npmFileCount: 3, + }, + }, + }), + ).rejects.toThrow( + "Version 1.0.0 already exists. Increment the version number and try again.", + ); + + expect(runQuery).toHaveBeenLastCalledWith( + expect.anything(), + expect.objectContaining({ + kind: "package", + slug: "demo-claw", + version: "1.0.0", + }), + ); + expect(runQuery.mock.calls.at(-1)?.[1]).not.toHaveProperty("artifactFingerprint"); + expect(runMutation).toHaveBeenCalledTimes(2); + expect(runMutation).not.toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + packageId: existingPackage._id, + releaseId: existingRelease._id, + createdNewParent: expect.anything(), + }), + ); + } finally { + if (previousStage === undefined) { + delete process.env.CLAWHUB_STAGED_PREPUBLICATION_PUBLISHES; + } else { + process.env.CLAWHUB_STAGED_PREPUBLICATION_PUBLISHES = previousStage; + } + } + }); + it("keeps raw package publishes behind the per-file size limit", async () => { const ctx = { runQuery: vi diff --git a/convex/packages.ts b/convex/packages.ts index 5d2e19d8..c9ffb700 100644 --- a/convex/packages.ts +++ b/convex/packages.ts @@ -3215,7 +3215,11 @@ export const listVersionsForViewerInternal = internalQuery({ const result = await paginatePublishedPackageReleases(ctx, pkg._id, args.paginationOpts); return { ...result, - page: result.page.map((release) => toPublicPackageRelease(release, pkg.family)), + page: result.page.map((release) => ({ + ...toPublicPackageRelease(release, pkg.family), + // Internal HTTP handlers need the opaque storage id to stream exact ClawPack bytes. + ...(release.clawpackStorageId ? { clawpackStorageId: release.clawpackStorageId } : {}), + })), }; }, }); @@ -3319,7 +3323,11 @@ export const getVersionByNameForViewerInternal = internalQuery({ if (!publicPackage) return null; return { package: publicPackage, - version: toPublicPackageRelease(release, pkg.family), + version: { + ...toPublicPackageRelease(release, pkg.family), + // Internal HTTP handlers need the opaque storage id to stream exact ClawPack bytes. + ...(release.clawpackStorageId ? { clawpackStorageId: release.clawpackStorageId } : {}), + }, }; }, }); @@ -5051,6 +5059,7 @@ export const findPackagePublishResultInternal = internalQuery({ name: v.string(), version: v.string(), integritySha256: v.string(), + clawpackSha256: v.optional(v.string()), ownerUserId: v.id("users"), ownerPublisherId: v.optional(v.id("publishers")), }, @@ -5064,7 +5073,14 @@ export const findPackagePublishResultInternal = internalQuery({ q.eq("packageId", pkg._id).eq("version", args.version), ) .unique(); - if (!isPublishedPackageRelease(release) || release.integritySha256 !== args.integritySha256) { + const matchesExactClawArtifact = + pkg.family !== "claw" || + (typeof args.clawpackSha256 === "string" && release?.clawpackSha256 === args.clawpackSha256); + if ( + !isPublishedPackageRelease(release) || + release.integritySha256 !== args.integritySha256 || + !matchesExactClawArtifact + ) { return null; } return { ok: true as const, packageId: pkg._id, releaseId: release._id }; @@ -8272,6 +8288,28 @@ async function publishPackageImpl( throw new ConvexError(`Claw package name must use canonical form ${name}`); } const version = assertPackageVersion(family, payload.version); + if (family === "claw") { + if (payload.artifact?.kind !== "npm-pack") { + throw new ConvexError("Claw publication requires an already-built package tarball (.tgz)"); + } + const expectedArtifactSha256 = payload.expectedArtifactSha256?.trim().toLowerCase(); + if (!expectedArtifactSha256) { + throw new ConvexError("Claw publication requires expectedArtifactSha256"); + } + if (!/^[a-f0-9]{64}$/.test(expectedArtifactSha256)) { + throw new ConvexError( + "Claw expectedArtifactSha256 must be a 64-character SHA-256 hex digest", + ); + } + if (!/^[a-f0-9]{64}$/.test(payload.artifact.sha256)) { + throw new ConvexError("Claw artifact SHA-256 must be a 64-character lowercase hex digest"); + } + if (expectedArtifactSha256 !== payload.artifact.sha256) { + throw new ConvexError( + `Claw artifact SHA-256 mismatch: expected ${expectedArtifactSha256}, got ${payload.artifact.sha256}`, + ); + } + } const existingPackage = await runQueryRef | null>( ctx, internalRefs.packages.getPackageByNameInternal, @@ -8720,6 +8758,8 @@ async function publishPackageImpl( clawManifestSummary: validatedClaw?.summary, source: effectiveSource, }; + const publishedArtifactSha256 = family === "claw" ? packageInsertArgs.clawpackSha256 : undefined; + const attemptArtifactFingerprint = publishedArtifactSha256 ?? integritySha256; const inspectorFindings = inspectorResult?.warnings.map((finding) => @@ -8735,20 +8775,106 @@ async function publishPackageImpl( { packageId: existingPackage._id, version }, ); } - const existingAttempt = await runQueryRef }>( - ctx, - internalRefs.publishAttempts.findExistingPublishAttemptForArtifactInternal, - { - kind: "package", - slug: name, - version, - }, - ); + const existingAttempt = await runQueryRef; + status: string; + reusable: boolean; + packageId?: Id<"packages">; + releaseId?: Id<"packageReleases">; + result?: { + ok: true; + packageId: Id<"packages">; + releaseId: Id<"packageReleases">; + }; + }>(ctx, internalRefs.publishAttempts.findExistingPublishAttemptForArtifactInternal, { + kind: "package", + slug: name, + version, + ...(family === "claw" + ? { + userId: actorUserId, + ownerUserId, + ownerPublisherId, + artifactFingerprint: attemptArtifactFingerprint, + } + : {}), + }); if (existingAttempt) { + const reusableClawAttempt = + family === "claw" && + existingAttempt.reusable && + existingPackage !== null && + !existingPackage.softDeletedAt && + existingAttempt.packageId !== undefined && + existingAttempt.packageId === existingPackage._id && + existingAttempt.releaseId !== undefined && + existingRelease !== null && + existingAttempt.releaseId === existingRelease._id && + !existingRelease.softDeletedAt && + existingRelease.ownerDeletedAt === undefined && + existingRelease.manualModeration?.state !== "quarantined" && + existingRelease.manualModeration?.state !== "revoked" && + resolvePackageReleaseScanStatus(existingRelease) !== "malicious" && + (existingAttempt.status === "finalized" + ? isPublishedPackageRelease(existingRelease) + : existingRelease.publicationStatus === "pending"); + if (reusableClawAttempt) { + if (existingAttempt.status === "finalized") { + if (!existingAttempt.result) { + throw new ConvexError("Finalized publish attempt is missing its package result."); + } + if (auth.kind === "github-actions") { + await runMutationRef(ctx, internalRefs.packagePublishTokens.revokeInternal, { + tokenId: auth.publishToken._id, + }); + } + const finalizedResult = { + ...existingAttempt.result, + publicationStatus: "published" as const, + artifactSha256: publishedArtifactSha256, + }; + return inspectorFindings.length > 0 + ? { ...finalizedResult, inspectorFindings } + : finalizedResult; + } + if (auth.kind === "github-actions") { + await runMutationRef(ctx, internalRefs.packagePublishTokens.revokeInternal, { + tokenId: auth.publishToken._id, + }); + } + return { + ok: true as const, + status: "pending" as const, + packageId: existingAttempt.packageId, + releaseId: existingAttempt.releaseId, + artifactSha256: publishedArtifactSha256, + publicationStatus: "pending" as const, + attemptId: existingAttempt.attemptId, + packageName: name, + version, + ...(inspectorFindings.length > 0 ? { inspectorFindings } : {}), + }; + } throw new ConvexError( `Version ${version} already exists. Increment the version number and try again.`, ); } + if (family === "claw") { + const conflictingAttempt = await runQueryRef }>( + ctx, + internalRefs.publishAttempts.findExistingPublishAttemptForArtifactInternal, + { + kind: "package", + slug: name, + version, + }, + ); + if (conflictingAttempt) { + throw new ConvexError( + `Version ${version} already exists. Increment the version number and try again.`, + ); + } + } if (existingPackage && existingRelease) { if (!existingRelease.softDeletedAt && existingRelease.publicationStatus === "pending") { await runMutationRef(ctx, internalRefs.packages.discardPendingPackagePublicationInternal, { @@ -8796,9 +8922,9 @@ async function publishPackageImpl( ownerUserId, name, version, - integritySha256, + artifactFingerprint: attemptArtifactFingerprint, }), - artifactFingerprint: integritySha256, + artifactFingerprint: attemptArtifactFingerprint, files, clawpackStorageId: packageInsertArgs.clawpackStorageId, scanContext: buildPackagePublishAttemptScanContext(packageInsertArgs), @@ -8856,6 +8982,7 @@ async function publishPackageImpl( const finalizedResult = { ...staged.result, publicationStatus: "published" as const, + ...(publishedArtifactSha256 ? { artifactSha256: publishedArtifactSha256 } : {}), }; return inspectorFindings.length > 0 ? { ...finalizedResult, inspectorFindings } @@ -8867,6 +8994,7 @@ async function publishPackageImpl( status: "pending" as const, packageId: pendingResult.packageId, releaseId: pendingResult.releaseId, + ...(publishedArtifactSha256 ? { artifactSha256: publishedArtifactSha256 } : {}), publicationStatus: "pending" as const, attemptId: staged.attemptId, packageName: name, @@ -8966,6 +9094,7 @@ async function publishPackageImpl( const publishedResult = { ...publishResult, publicationStatus: "published" as const, + ...(publishedArtifactSha256 ? { artifactSha256: publishedArtifactSha256 } : {}), }; return inspectorFindings.length > 0 ? { ...publishedResult, inspectorFindings } : publishedResult; } @@ -9011,6 +9140,14 @@ export const publishRelease: ReturnType = action({ payload: v.any(), }, handler: async (ctx, args) => { + if ( + args.payload && + typeof args.payload === "object" && + !Array.isArray(args.payload) && + (args.payload as Record).family === "claw" + ) { + throw new ConvexError("Claw packages must use the exact-artifact HTTP publish flow"); + } const { userId } = await requireUserFromAction(ctx); const stagePrePublicationChecks = stagedPrePublicationPublishesEnabled(); return await publishPackageImpl(ctx, { kind: "user", actorUserId: userId }, args.payload, { @@ -9071,6 +9208,7 @@ export const finalizePackagePublishAttemptInternal = internalAction({ name?: string; version?: string; integritySha256?: string; + clawpackSha256?: string; ownerUserId?: Id<"users">; ownerPublisherId?: Id<"publishers">; }; @@ -9087,6 +9225,7 @@ export const finalizePackagePublishAttemptInternal = internalAction({ name: insertArgs.name, version: insertArgs.version, integritySha256: insertArgs.integritySha256, + clawpackSha256: insertArgs.clawpackSha256, ownerUserId: insertArgs.ownerUserId, ownerPublisherId: insertArgs.ownerPublisherId, }) @@ -9184,7 +9323,7 @@ function buildPackagePublishAttemptIdempotencyKey(args: { ownerPublisherId?: Id<"publishers">; name: string; version: string; - integritySha256: string; + artifactFingerprint: string; }) { return [ "package", @@ -9192,7 +9331,7 @@ function buildPackagePublishAttemptIdempotencyKey(args: { args.ownerPublisherId ?? args.ownerUserId, args.name, args.version, - args.integritySha256, + args.artifactFingerprint, ].join(":"); } @@ -11186,10 +11325,28 @@ export const insertReleaseInternal = internalMutation({ ) .unique(); if (releaseExists) { + const matchesExactClawArtifact = + args.family !== "claw" || + (typeof args.clawpackSha256 === "string" && + releaseExists.clawpackSha256 === args.clawpackSha256); + const matchesExistingOwner = + args.ownerPublisherId !== undefined + ? existing.ownerPublisherId === args.ownerPublisherId + : existing.ownerPublisherId === undefined && existing.ownerUserId === args.ownerUserId; + const allowExactClawRetry = + args.family === "claw" && matchesExistingOwner && matchesExactClawArtifact; + const canReuseExistingRelease = + args.allowExistingRelease || + (allowExactClawRetry && + isPublishedPackageRelease(releaseExists) && + releaseExists.manualModeration?.state !== "quarantined" && + releaseExists.manualModeration?.state !== "revoked" && + resolvePackageReleaseScanStatus(releaseExists) !== "malicious"); if ( - args.allowExistingRelease && + canReuseExistingRelease && !releaseExists.softDeletedAt && - releaseExists.integritySha256 === args.integritySha256 + releaseExists.integritySha256 === args.integritySha256 && + matchesExactClawArtifact ) { return { ok: true as const, diff --git a/convex/publishAttempts.test.ts b/convex/publishAttempts.test.ts index 4708f055..e3ee8278 100644 --- a/convex/publishAttempts.test.ts +++ b/convex/publishAttempts.test.ts @@ -7,6 +7,8 @@ import { completePendingPublishAttemptChecksInternal, createPackagePublishAttemptInternal, createSkillPublishAttemptInternal, + findExistingPublishAttemptForArtifactInternal, + getPackagePublishAttemptStatusInternal, recordSkillPublishAttemptFinalizedInternal, releasePackagePublishAttemptFinalizationClaimInternal, releaseSkillPublishAttemptFinalizationClaimInternal, @@ -57,8 +59,167 @@ const createPackagePublishAttemptHandler = ( _handler: (ctx: unknown, args: unknown) => Promise; } )._handler; +const getPackagePublishAttemptStatusHandler = ( + getPackagePublishAttemptStatusInternal as unknown as { + _handler: (ctx: unknown, args: unknown) => Promise; + } +)._handler; + +const findExistingPublishAttemptForArtifactHandler = ( + findExistingPublishAttemptForArtifactInternal as unknown as { + _handler: (ctx: unknown, args: unknown) => Promise; + } +)._handler; + +function makeAttemptLookupCtx(attempts: Array>) { + let requestedStatus = ""; + const indexQuery = { + eq: vi.fn((field: string, value: unknown) => { + if (field === "status") requestedStatus = String(value); + return indexQuery; + }), + }; + return { + db: { + query: vi.fn(() => ({ + withIndex: vi.fn( + (_indexName: string, buildQuery: (query: typeof indexQuery) => unknown) => { + requestedStatus = ""; + buildQuery(indexQuery); + return { + order: vi.fn(() => ({ + take: vi.fn(async () => + attempts.filter((attempt) => attempt.status === requestedStatus), + ), + })), + }; + }, + ), + })), + }, + }; +} describe("publishAttempts", () => { + it("returns a finalized package attempt only for the exact actor, owner, and artifact", async () => { + const result = { + ok: true, + packageId: "packages:demo", + releaseId: "packageReleases:demo", + }; + const attempt = { + _id: "publishAttempts:demo", + kind: "package", + status: "finalized", + userId: "users:publisher", + ownerUserId: "users:owner", + ownerPublisherId: "publishers:owner", + packageId: result.packageId, + packageReleaseId: result.releaseId, + slug: "demo-claw", + version: "1.0.0", + artifactFingerprint: "exact-fingerprint", + result, + }; + const ctx = makeAttemptLookupCtx([attempt]); + const args = { + kind: "package", + slug: "demo-claw", + version: "1.0.0", + userId: "users:publisher", + ownerUserId: "users:owner", + ownerPublisherId: "publishers:owner", + artifactFingerprint: "exact-fingerprint", + }; + + await expect(findExistingPublishAttemptForArtifactHandler(ctx, args)).resolves.toMatchObject({ + attemptId: attempt._id, + status: "finalized", + reusable: true, + packageId: result.packageId, + releaseId: result.releaseId, + result, + }); + + for (const mismatch of [ + { artifactFingerprint: "different-fingerprint" }, + { userId: "users:different" }, + { ownerUserId: "users:different" }, + { ownerPublisherId: "publishers:different" }, + ]) { + await expect( + findExistingPublishAttemptForArtifactHandler(ctx, { ...args, ...mismatch }), + ).resolves.toBeNull(); + } + }); + + it("reports an exact terminal package attempt as non-reusable", async () => { + const attempt = { + _id: "publishAttempts:blocked", + kind: "package", + status: "blocked", + userId: "users:owner", + ownerUserId: "users:owner", + packageId: "packages:demo", + packageReleaseId: "packageReleases:demo", + slug: "demo-claw", + version: "1.0.0", + artifactFingerprint: "exact-fingerprint", + }; + + await expect( + findExistingPublishAttemptForArtifactHandler(makeAttemptLookupCtx([attempt]), { + kind: "package", + slug: "demo-claw", + version: "1.0.0", + userId: "users:owner", + ownerUserId: "users:owner", + artifactFingerprint: "exact-fingerprint", + }), + ).resolves.toMatchObject({ + attemptId: attempt._id, + status: "blocked", + reusable: false, + }); + }); + + it("returns the stored package artifact digest while publication is pending", async () => { + const get = vi + .fn() + .mockResolvedValueOnce({ + _id: "publishAttempts:demo", + kind: "package", + userId: "users:publisher", + packageId: "packages:demo", + packageReleaseId: "packageReleases:demo", + slug: "demo-claw", + version: "1.0.0", + status: "pending_checks", + checks: { + trufflehog: { status: "pending" }, + clawscan: { status: "pending" }, + }, + }) + .mockResolvedValueOnce({ clawpackSha256: "a".repeat(64) }); + + await expect( + getPackagePublishAttemptStatusHandler( + { + db: { + normalizeId: vi.fn(() => "publishAttempts:demo"), + get, + }, + }, + { attemptId: "publishAttempts:demo" }, + ), + ).resolves.toMatchObject({ + attemptId: "publishAttempts:demo", + artifactSha256: "a".repeat(64), + status: "pending_checks", + }); + expect(get).toHaveBeenNthCalledWith(2, "packageReleases:demo"); + }); + it("schedules exact dispatch for fresh skill attempts", async () => { vi.stubEnv("SECURITY_SCAN_EVENT_DISPATCH_ENABLED", "1"); vi.stubEnv("GITHUB_APP_ID", "configured"); diff --git a/convex/publishAttempts.ts b/convex/publishAttempts.ts index 95ccc132..be70ecf6 100644 --- a/convex/publishAttempts.ts +++ b/convex/publishAttempts.ts @@ -289,7 +289,9 @@ export const findExistingPublishAttemptForArtifactInternal = internalQuery({ slug: v.string(), version: v.string(), userId: v.optional(v.id("users")), + ownerUserId: v.optional(v.id("users")), ownerPublisherId: v.optional(v.id("publishers")), + artifactFingerprint: v.optional(v.string()), }, handler: async (ctx, args) => { for (const status of PUBLISH_ATTEMPT_STATUSES) { @@ -305,7 +307,22 @@ export const findExistingPublishAttemptForArtifactInternal = internalQuery({ .order("desc") .take(25); const match = attempts.find((attempt) => { - if (args.kind === "package") return true; + if (args.kind === "package") { + if (args.artifactFingerprint === undefined) return true; + if (attempt.artifactFingerprint !== args.artifactFingerprint) return false; + if (args.ownerPublisherId !== undefined) { + return ( + attempt.ownerPublisherId === args.ownerPublisherId && + attempt.userId === args.userId && + attempt.ownerUserId === args.ownerUserId + ); + } + return ( + attempt.ownerPublisherId === undefined && + attempt.userId === args.userId && + attempt.ownerUserId === args.ownerUserId + ); + } if (args.ownerPublisherId !== undefined) { return attempt.ownerPublisherId === args.ownerPublisherId; } @@ -318,6 +335,11 @@ export const findExistingPublishAttemptForArtifactInternal = internalQuery({ kind: match.kind, slug: match.slug, version: match.version, + reusable: !isTerminalRetriableAttemptStatus(match.status), + packageId: match.packageId, + releaseId: match.packageReleaseId, + artifactFingerprint: match.artifactFingerprint, + result: match.result, }; } } @@ -426,11 +448,13 @@ export const getPackagePublishAttemptStatusInternal = internalQuery({ if (!attempt || attempt.kind !== "package" || !attempt.packageId || !attempt.packageReleaseId) { return null; } + const release = await ctx.db.get(attempt.packageReleaseId); return { attemptId: attempt._id, userId: attempt.userId, packageId: attempt.packageId, releaseId: attempt.packageReleaseId, + ...(release?.clawpackSha256 ? { artifactSha256: release.clawpackSha256 } : {}), name: attempt.slug, version: attempt.version, status: attempt.status, @@ -890,7 +914,10 @@ export const claimPendingPublishAttemptChecksInternal = internalMutation({ } } else if (attempt.kind === "package" && attempt.packageReleaseId) { const release = await ctx.db.get(attempt.packageReleaseId); - if (release?.integritySha256 === attempt.artifactFingerprint) { + const releaseFingerprint = release?.clawManifestSummary + ? release.clawpackSha256 + : release?.integritySha256; + if (release && releaseFingerprint === attempt.artifactFingerprint) { existingClawscanAnalysis = reusableClawscanAnalysis(release.llmAnalysis); } } diff --git a/docs/claws.md b/docs/claws.md index 871ab8b5..25a234e9 100644 --- a/docs/claws.md +++ b/docs/claws.md @@ -124,28 +124,38 @@ exact. Other harnesses may bind the same application needs using their own native profile model; the portable manifest does not impose a capability-name registry. -## Validate and publish +## Validate, build, and publish -Preview the package without uploading it: +Validate the source project and build its deterministic artifact with +OpenClaw: ```bash -clawhub package publish . --family claw --dry-run +openclaw claws validate . +openclaw claws build . --out ./github-triage-1.0.0.tgz ``` -When the target ClawHub deployment has experimental Claws enabled, publish -through the existing authenticated package flow: +Preview that exact artifact without uploading it, then publish it through the +existing authenticated package flow: ```bash -clawhub package publish . --family claw +clawhub package publish ./github-triage-1.0.0.tgz --family claw --dry-run +clawhub package publish ./github-triage-1.0.0.tgz --family claw --wait ``` The CLI detects `family: claw` when `package.json` contains `openclaw.claw`, so `--family claw` is optional for a well-formed package. +Experimental Claw publication accepts only an already-built npm-pack `.tgz`, +not a source directory or GitHub checkout. The CLI sends the local artifact +SHA-256 with the request; ClawHub verifies it against the uploaded bytes before +publication and returns the same digest through pending and final responses. + Publication rejects: - a missing, invalid, or escaping `openclaw.claw` path; +- a source folder instead of a built `.tgz`; - package identity or version mismatches; +- a missing or mismatched expected artifact SHA-256; - malformed `CLAW.md` frontmatter or manifest fields; - a non-empty `CLAW.md` body combined with an explicit `SOUL.md` destination; - missing workspace source files or portable path collisions; @@ -156,7 +166,8 @@ Publication rejects: Accepted packages continue through ClawHub's existing ownership, moderation, static scanning, release, and artifact storage pipeline. The stored release retains the exact artifact plus a non-sensitive summary for later search and -detail surfaces; it does not duplicate the full manifest into Convex storage. +detail surfaces; downloads return those same bytes and digest, and ClawHub does +not duplicate the full manifest into Convex storage. ## Discover published Claws diff --git a/docs/cli.md b/docs/cli.md index fc15ad02..a740b4df 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -667,6 +667,10 @@ clawhub publisher create opik --display-name "Opik" - `.tgz` sources are treated as ClawPack. The CLI uploads the exact npm-pack bytes and uses the extracted `package/` contents only for validation and metadata prefill. +- Experimental Claws must be published from an already-built `.tgz`. Claw + source folders and GitHub sources are rejected; use `openclaw claws build` + first. The publish request binds the local SHA-256, and ClawHub returns that + digest after accepting the exact bytes. - Code-plugin folders are packed into a ClawPack npm tarball before upload so OpenClaw installs can verify the exact artifact. Bundle-plugin folders still use the extracted-file publish path. @@ -712,7 +716,7 @@ clawhub package publish ./my-plugin-1.2.3.tgz --family code-plugin --wait #### Local folder flow For code plugins, folder publish builds and uploads a ClawPack artifact from -the package folder: +the package folder. This convenience does not apply to Claws: ```bash clawhub package publish ./my-plugin --family code-plugin --dry-run diff --git a/e2e/local-auth/exact-claw-artifact.pw.test.ts b/e2e/local-auth/exact-claw-artifact.pw.test.ts new file mode 100644 index 00000000..d9739601 --- /dev/null +++ b/e2e/local-auth/exact-claw-artifact.pw.test.ts @@ -0,0 +1,222 @@ +import { spawn, spawnSync } from "node:child_process"; +import { createHash } from "node:crypto"; +import { mkdtempSync, readFileSync, rmSync, writeFileSync, mkdirSync } from "node:fs"; +import { tmpdir } from "node:os"; +import path from "node:path"; +import { expect, test } from "@playwright/test"; +import { completeMockPrePublicationChecks } from "./helpers"; + +test.setTimeout(180_000); + +test.skip( + process.env.VITE_ENABLE_DEV_AUTH !== "1", + "exact Claw artifact proof requires the local dev auth runner", +); + +function localConvexDeployment() { + const raw = readFileSync(".convex/local/default/config.json", "utf8"); + const parsed = JSON.parse(raw) as { deploymentName?: unknown }; + if (typeof parsed.deploymentName !== "string" || !parsed.deploymentName) { + throw new Error("Local Convex deployment name was not available"); + } + return `local:${parsed.deploymentName}`; +} + +function extractLastJsonObject(output: string) { + const trimmed = output.trim(); + for (let index = 0; index < trimmed.length; index += 1) { + if (trimmed[index] !== "{") continue; + const candidate = trimmed.slice(index); + try { + return JSON.parse(candidate) as Record; + } catch { + // Convex and the CLI may print status lines before their JSON payload. + } + } + throw new Error(`No JSON object in output:\n${output}`); +} + +function runDevSeed(functionName: string, args: Record) { + const result = spawnSync( + "bunx", + [ + "convex", + "run", + "--typecheck", + "disable", + "--codegen", + "disable", + functionName, + JSON.stringify(args), + ], + { + cwd: process.cwd(), + env: { ...process.env, CONVEX_DEPLOYMENT: localConvexDeployment() }, + encoding: "utf8", + }, + ); + if (result.status !== 0) { + throw new Error( + [`Failed to run ${functionName}.`, result.stdout.trim(), result.stderr.trim()].join("\n"), + ); + } + return extractLastJsonObject(result.stdout) as T; +} + +function sha256(bytes: Uint8Array) { + return createHash("sha256").update(bytes).digest("hex"); +} + +function runCli(args: string[], env: NodeJS.ProcessEnv) { + return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => { + const child = spawn("bun", ["packages/clawhub/src/cli.ts", ...args], { + cwd: process.cwd(), + env, + stdio: ["ignore", "pipe", "pipe"], + }); + let stdout = ""; + let stderr = ""; + child.stdout.setEncoding("utf8"); + child.stderr.setEncoding("utf8"); + child.stdout.on("data", (chunk: string) => { + stdout += chunk; + }); + child.stderr.on("data", (chunk: string) => { + stderr += chunk; + }); + child.once("error", reject); + child.once("exit", (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + return; + } + reject(new Error(`ClawHub CLI exited ${code}.\nstdout:\n${stdout}\nstderr:\n${stderr}`)); + }); + }); +} + +test("publishes, polls, retries, and downloads the exact Claw tarball", async ({ request }) => { + const root = mkdtempSync(path.join(tmpdir(), "clawhub-exact-claw-proof-")); + const sourceDir = path.join(root, "source"); + const configPath = path.join(root, "config.json"); + const suffix = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`; + const packageName = `exact-claw-proof-${suffix}`; + const version = "1.0.0"; + const registry = process.env.VITE_CONVEX_SITE_URL; + if (!registry) throw new Error("VITE_CONVEX_SITE_URL is required"); + + try { + mkdirSync(path.join(sourceDir, "manifests"), { recursive: true }); + mkdirSync(path.join(sourceDir, "profiles"), { recursive: true }); + writeFileSync( + path.join(sourceDir, "package.json"), + JSON.stringify({ + name: packageName, + version, + openclaw: { claw: "manifests/CLAW.md" }, + }), + ); + writeFileSync( + path.join(sourceDir, "manifests", "CLAW.md"), + `---\nschemaVersion: 1\nagent:\n id: ${packageName}\n name: Exact Claw Proof\n---\nPreserve the exact published artifact.\n`, + ); + writeFileSync( + path.join(sourceDir, "profiles", "openclaw.yml"), + "schemaVersion: 1\nagent: {}\n", + ); + + const pack = spawnSync("npm", ["pack", "--json", "--pack-destination", root], { + cwd: sourceDir, + encoding: "utf8", + }); + if (pack.status !== 0) { + throw new Error(`npm pack failed.\n${pack.stdout}\n${pack.stderr}`); + } + const packResult = JSON.parse(pack.stdout) as Array<{ filename: string }>; + const artifactPath = path.join(root, packResult[0]?.filename ?? ""); + const artifactBytes = readFileSync(artifactPath); + const artifactSha256 = sha256(artifactBytes); + + const fixtures = runDevSeed<{ + user: { token: string }; + }>("devSeed:seedCliRoleHelpFixtures", {}); + const cliEnv = { + ...process.env, + CLAWHUB_CONFIG_PATH: configPath, + CLAWHUB_REGISTRY: registry, + CLAWHUB_SITE: process.env.PLAYWRIGHT_BASE_URL ?? registry, + }; + const login = spawnSync( + "bun", + [ + "packages/clawhub/src/cli.ts", + "--registry", + registry, + "login", + "--token", + fixtures.user.token, + ], + { cwd: process.cwd(), env: cliEnv, encoding: "utf8" }, + ); + if (login.status !== 0) { + throw new Error(`CLI login failed.\n${login.stdout}\n${login.stderr}`); + } + + const publishArgs = [ + "--registry", + registry, + "--no-input", + "package", + "publish", + artifactPath, + "--family", + "claw", + "--wait", + "--wait-timeout", + "120", + "--json", + ]; + const publication = runCli(publishArgs, cliEnv); + const claim = await completeMockPrePublicationChecks({ + kind: "package", + slug: packageName, + version, + }); + expect(claim.claim.artifactFingerprint).toBe(artifactSha256); + const published = extractLastJsonObject((await publication).stdout); + expect(published).toMatchObject({ + publicationStatus: "published", + artifactSha256, + }); + + const packagePath = encodeURIComponent(packageName); + const download = await request.get( + `${registry}/api/v1/packages/${packagePath}/versions/${version}/artifact/download`, + ); + const downloadedBytes = await download.body(); + expect(download.status(), downloadedBytes.toString("utf8")).toBe(200); + const downloadedSha256 = sha256(downloadedBytes); + expect(downloadedSha256).toBe(artifactSha256); + + const retried = extractLastJsonObject((await runCli(publishArgs, cliEnv)).stdout); + expect(retried).toMatchObject({ + publicationStatus: "published", + artifactSha256, + }); + + console.log( + `EXACT_CLAW_ARTIFACT_PROOF ${JSON.stringify({ + packageName, + version, + publicationStatus: published.publicationStatus, + uploadedSha256: artifactSha256, + attemptSha256: claim.claim.artifactFingerprint, + responseSha256: published.artifactSha256, + downloadedSha256, + retrySha256: retried.artifactSha256, + })}`, + ); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); diff --git a/packages/clawhub/README.md b/packages/clawhub/README.md index e1169b1b..1fad4cc1 100644 --- a/packages/clawhub/README.md +++ b/packages/clawhub/README.md @@ -88,6 +88,16 @@ For code plugins, folder publish builds and uploads a ClawPack artifact from the package folder. Bundle-plugin folders still use the extracted-file publish path. +Experimental Claws use an exact-artifact flow. Build with OpenClaw, then give +ClawHub the resulting `.tgz`; Claw source-folder publication is rejected: + +```bash +openclaw claws validate . +openclaw claws build . --out ./my-claw-1.0.0.tgz +clawhub package publish ./my-claw-1.0.0.tgz --family claw --dry-run +clawhub package publish ./my-claw-1.0.0.tgz --family claw --wait +``` + Use `clawhub package download` to resolve the published artifact through ClawHub's explicit artifact route. ClawPack downloads are verified against npm integrity/shasum plus ClawHub SHA-256; legacy package versions still download diff --git a/packages/clawhub/src/cli/commands/packages.test.ts b/packages/clawhub/src/cli/commands/packages.test.ts index e040f469..97951a77 100644 --- a/packages/clawhub/src/cli/commands/packages.test.ts +++ b/packages/clawhub/src/cli/commands/packages.test.ts @@ -2600,10 +2600,13 @@ describe("package commands", () => { "package/CLAW.md": "---\nschemaVersion: 1\nagent:\n id: demo-claw\n---\n# Demo Claw\n", }), ); + const packBytes = new Uint8Array(await readFile(join(workdir, packName))); + const artifactSha256 = artifactIdentity(packBytes).sha256; httpMocks.apiRequestForm.mockResolvedValueOnce({ ok: true, packageId: "pkg_claw", releaseId: "rel_claw", + artifactSha256, }); await cmdPublishPackage(makeOpts(workdir), packName); @@ -2612,6 +2615,7 @@ describe("package commands", () => { name: "demo-claw", family: "claw", version: "1.0.0", + expectedArtifactSha256: artifactSha256, }); const uploaded = getPublishForm().get("clawpack"); expect(uploaded).toBeInstanceOf(File); @@ -2622,6 +2626,81 @@ describe("package commands", () => { } }); + it("fails closed when ClawHub does not confirm the submitted Claw digest", async () => { + const workdir = await makeTmpWorkdir(); + try { + const packName = "demo-claw-1.0.0.tgz"; + await writeFile( + join(workdir, packName), + npmPackFixture({ + "package/package.json": JSON.stringify({ + name: "demo-claw", + version: "1.0.0", + openclaw: { claw: "CLAW.md" }, + }), + "package/CLAW.md": "---\nschemaVersion: 1\nagent:\n id: demo-claw\n---\n# Demo Claw\n", + }), + ); + httpMocks.apiRequestForm.mockResolvedValueOnce({ + ok: true, + packageId: "pkg_claw", + releaseId: "rel_claw", + artifactSha256: "0".repeat(64), + }); + + await expect(cmdPublishPackage(makeOpts(workdir), packName)).rejects.toThrow( + "ClawHub artifact SHA-256 mismatch", + ); + expect(httpMocks.apiRequestForm).toHaveBeenCalledTimes(1); + } finally { + await rm(workdir, { recursive: true, force: true }); + } + }); + + it("fails closed when a finalized Claw publish reports a different digest", async () => { + const workdir = await makeTmpWorkdir(); + try { + const packName = "demo-claw-1.0.0.tgz"; + const pack = npmPackFixture({ + "package/package.json": JSON.stringify({ + name: "demo-claw", + version: "1.0.0", + openclaw: { claw: "CLAW.md" }, + }), + "package/CLAW.md": "---\nschemaVersion: 1\nagent:\n id: demo-claw\n---\n# Demo Claw\n", + }); + await writeFile(join(workdir, packName), pack); + const artifactSha256 = artifactIdentity(pack).sha256; + httpMocks.apiRequestForm.mockResolvedValueOnce({ + ok: true, + packageId: "pkg_claw", + releaseId: "rel_pending", + publicationStatus: "pending", + attemptId: "attempt_1", + artifactSha256, + }); + httpMocks.apiRequest.mockResolvedValueOnce({ + attemptId: "attempt_1", + packageId: "pkg_claw", + releaseId: "rel_published", + name: "demo-claw", + version: "1.0.0", + status: "finalized", + publicationStatus: "published", + terminal: true, + checks: makePublishAttemptChecks(), + artifactSha256: "0".repeat(64), + }); + + await expect(cmdPublishPackage(makeOpts(workdir), packName, { wait: true })).rejects.toThrow( + "ClawHub artifact SHA-256 mismatch", + ); + expect(httpMocks.apiRequest).toHaveBeenCalledTimes(1); + } finally { + await rm(workdir, { recursive: true, force: true }); + } + }); + it("mints a short-lived publish token from GitHub Actions OIDC in CI", async () => { const workdir = await makeTmpWorkdir(); try { @@ -3175,7 +3254,7 @@ describe("package commands", () => { } }); - it("detects, validates, and publishes a Claw package", async () => { + it("validates a Claw source folder but requires a built tarball for publication", async () => { const workdir = await makeTmpWorkdir(); try { const folder = join(workdir, "github-triage"); @@ -3228,19 +3307,10 @@ describe("package commands", () => { ].join("\n"), "utf8", ); - httpMocks.apiRequestForm.mockResolvedValueOnce({ - ok: true, - packageId: "pkg_claw", - releaseId: "rel_claw", - }); - - await cmdPublishPackage(makeOpts(workdir), "github-triage"); - - expect(getPublishPayload()).toMatchObject({ - name: "@acme/github-triage", - family: "claw", - version: "1.0.0", - }); + await expect(cmdPublishPackage(makeOpts(workdir), "github-triage")).rejects.toThrow( + "Claw publication requires an already-built package tarball (.tgz)", + ); + expect(httpMocks.apiRequestForm).not.toHaveBeenCalled(); } finally { await rm(workdir, { recursive: true, force: true }); } diff --git a/packages/clawhub/src/cli/commands/packages.ts b/packages/clawhub/src/cli/commands/packages.ts index 61b5ad26..454b337b 100644 --- a/packages/clawhub/src/cli/commands/packages.ts +++ b/packages/clawhub/src/cli/commands/packages.ts @@ -281,6 +281,7 @@ type PackagePublishPayload = { family: PublishablePackageFamily; version: string; changelog: string; + expectedArtifactSha256?: string; manualOverrideReason?: string; tags: string[]; categories?: string[]; @@ -310,9 +311,22 @@ type PackagePublishPlan = { commit?: string; files: number; totalBytes: number; + artifactSha256?: string; }; }; +function assertClawPublishArtifactDigest( + plan: PackagePublishPlan, + result: { artifactSha256?: string }, +) { + if (plan.payload.family !== "claw") return; + if (result.artifactSha256 !== plan.payload.expectedArtifactSha256) { + fail( + `ClawHub artifact SHA-256 mismatch: expected ${plan.payload.expectedArtifactSha256}, got ${result.artifactSha256 ?? "missing"}`, + ); + } +} + type PackedClawPack = { path: string; file: PackageFile; @@ -1002,6 +1016,7 @@ export async function cmdPublishPackage( }, ApiV1PackagePublishResponseSchema, ); + assertClawPublishArtifactDigest(plan, result); let finalResult: ApiV1PackagePublishResponse | ApiV1PackagePublishAttemptResponse = result; if (options.wait && result.publicationStatus !== "published") { @@ -1033,6 +1048,7 @@ export async function cmdPublishPackage( return publishToken; }, }); + assertClawPublishArtifactDigest(plan, finalResult); } const publicationStatus = finalResult.publicationStatus; @@ -1049,6 +1065,7 @@ export async function cmdPublishPackage( ...plan.output, status: outputStatus, releaseId: finalResult.releaseId, + artifactSha256: finalResult.artifactSha256, publicationStatus, attemptId: finalResult.attemptId, inspectorFindings: result.inspectorFindings, @@ -2542,6 +2559,9 @@ async function preparePackagePublishPlan( if (!validation.ok) { fail(validation.issues.map((issue) => `${issue.path}: ${issue.message}`).join(" ")); } + if (!clawpackOnDisk) { + fail("Claw publication requires an already-built package tarball (.tgz)"); + } } if (family === "code-plugin" && !clawpackOnDisk) { @@ -2587,6 +2607,9 @@ async function preparePackagePublishPlan( family, version, changelog, + ...(family === "claw" && clawpackOnDisk + ? { expectedArtifactSha256: digestHex(clawpackOnDisk.bytes, "sha256") } + : {}), ...(options.manualOverrideReason?.trim() ? { manualOverrideReason: options.manualOverrideReason.trim() } : {}), @@ -2638,6 +2661,9 @@ async function preparePackagePublishPlan( ...(source?.commit ? { commit: source.commit } : {}), files: filesOnDisk.length, totalBytes, + ...(family === "claw" && clawpackOnDisk + ? { artifactSha256: digestHex(clawpackOnDisk.bytes, "sha256") } + : {}), }, }; } diff --git a/packages/clawhub/src/schema/packages.ts b/packages/clawhub/src/schema/packages.ts index a2e9d3bb..c99f488e 100644 --- a/packages/clawhub/src/schema/packages.ts +++ b/packages/clawhub/src/schema/packages.ts @@ -325,6 +325,7 @@ const PackagePublishMetadataFields = { family: PackageFamilySchema, version: "string", changelog: "string", + expectedArtifactSha256: "string?", manualOverrideReason: "string?", channel: PackageChannelSchema.optional(), tags: "string[]?", @@ -935,6 +936,7 @@ export const ApiV1PackagePublishResponseSchema = type({ ok: "true", packageId: "string", releaseId: "string", + artifactSha256: "string?", publicationStatus: '"pending"|"published"?', attemptId: "string?", inspectorFindings: type({ @@ -976,6 +978,7 @@ export const ApiV1PackagePublishAttemptResponseSchema = type({ attemptId: "string", packageId: "string", releaseId: "string", + artifactSha256: "string?", name: "string", version: "string", status: PackagePublishAttemptStatusSchema, diff --git a/packages/clawhub/src/schema/schemas.test.ts b/packages/clawhub/src/schema/schemas.test.ts index e21f790c..660ccc81 100644 --- a/packages/clawhub/src/schema/schemas.test.ts +++ b/packages/clawhub/src/schema/schemas.test.ts @@ -140,6 +140,7 @@ describe("packages/clawhub skill metadata schema", () => { ok: true, packageId: "packages:demo", releaseId: "packageReleases:demo", + artifactSha256: "a".repeat(64), publicationStatus: "pending", attemptId: "publishAttempts:demo", }, @@ -147,6 +148,7 @@ describe("packages/clawhub skill metadata schema", () => { ); expect(parsed.releaseId).toBe("packageReleases:demo"); + expect(parsed.artifactSha256).toBe("a".repeat(64)); expect(parsed.publicationStatus).toBe("pending"); expect(parsed.attemptId).toBe("publishAttempts:demo"); }); @@ -158,6 +160,7 @@ describe("packages/clawhub skill metadata schema", () => { attemptId: "publishAttempts:demo", packageId: "packages:demo", releaseId: "packageReleases:demo", + artifactSha256: "a".repeat(64), name: "@openclaw/demo", version: "1.0.0", status: "finalized", @@ -172,6 +175,7 @@ describe("packages/clawhub skill metadata schema", () => { ); expect(parsed.publicationStatus).toBe("published"); + expect(parsed.artifactSha256).toBe("a".repeat(64)); expect(parsed.terminal).toBe(true); expect(parsed.checks.clawscan.status).toBe("clean"); }); diff --git a/packages/schema/dist/packages.d.ts b/packages/schema/dist/packages.d.ts index fa70fcd6..a1dc380e 100644 --- a/packages/schema/dist/packages.d.ts +++ b/packages/schema/dist/packages.d.ts @@ -268,6 +268,7 @@ export declare const PackagePublishMetadataSchema: import("arktype/internal/vari family: "bundle-plugin" | "claw" | "code-plugin" | "skill"; version: string; changelog: string; + expectedArtifactSha256?: string | undefined; manualOverrideReason?: string | undefined; channel?: "community" | "official" | "private" | undefined; tags?: string[] | undefined; @@ -296,6 +297,7 @@ export declare const ServerPackagePublishRequestSchema: import("arktype/internal family: "bundle-plugin" | "claw" | "code-plugin" | "skill"; version: string; changelog: string; + expectedArtifactSha256?: string | undefined; manualOverrideReason?: string | undefined; channel?: "community" | "official" | "private" | undefined; tags?: string[] | undefined; @@ -1217,6 +1219,7 @@ export declare const ApiV1PackagePublishResponseSchema: import("arktype/internal ok: true; packageId: string; releaseId: string; + artifactSha256?: string | undefined; publicationStatus?: "pending" | "published" | undefined; attemptId?: string | undefined; inspectorFindings?: { @@ -1248,6 +1251,7 @@ export declare const ApiV1PackagePublishAttemptResponseSchema: import("arktype/i attemptId: string; packageId: string; releaseId: string; + artifactSha256?: string | undefined; name: string; version: string; status: "blocked" | "expired" | "failed" | "finalized" | "finalizing" | "pending_checks" | "ready_to_finalize"; diff --git a/packages/schema/dist/packages.js b/packages/schema/dist/packages.js index 627a05ad..71556529 100644 --- a/packages/schema/dist/packages.js +++ b/packages/schema/dist/packages.js @@ -260,6 +260,7 @@ const PackagePublishMetadataFields = { family: PackagePublishFamilySchema, version: "string", changelog: "string", + expectedArtifactSha256: "string?", manualOverrideReason: "string?", channel: PackageChannelSchema.optional(), tags: "string[]?", @@ -763,6 +764,7 @@ export const ApiV1PackagePublishResponseSchema = type({ ok: "true", packageId: "string", releaseId: "string", + artifactSha256: "string?", publicationStatus: '"pending"|"published"?', attemptId: "string?", inspectorFindings: type({ @@ -792,6 +794,7 @@ export const ApiV1PackagePublishAttemptResponseSchema = type({ attemptId: "string", packageId: "string", releaseId: "string", + artifactSha256: "string?", name: "string", version: "string", status: PackagePublishAttemptStatusSchema, diff --git a/packages/schema/dist/packages.js.map b/packages/schema/dist/packages.js.map index c0efa831..fde7abd5 100644 --- a/packages/schema/dist/packages.js.map +++ b/packages/schema/dist/packages.js.map @@ -1 +1 @@ -{"version":3,"file":"packages.js","sourceRoot":"","sources":["../src/packages.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"packages.js","sourceRoot":"","sources":["../src/packages.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/schema/src/packages.ts b/packages/schema/src/packages.ts index 159469e1..296f9898 100644 --- a/packages/schema/src/packages.ts +++ b/packages/schema/src/packages.ts @@ -354,6 +354,7 @@ const PackagePublishMetadataFields = { family: PackagePublishFamilySchema, version: "string", changelog: "string", + expectedArtifactSha256: "string?", manualOverrideReason: "string?", channel: PackageChannelSchema.optional(), tags: "string[]?", @@ -971,6 +972,7 @@ export const ApiV1PackagePublishResponseSchema = type({ ok: "true", packageId: "string", releaseId: "string", + artifactSha256: "string?", publicationStatus: '"pending"|"published"?', attemptId: "string?", inspectorFindings: type({ @@ -1012,6 +1014,7 @@ export const ApiV1PackagePublishAttemptResponseSchema = type({ attemptId: "string", packageId: "string", releaseId: "string", + artifactSha256: "string?", name: "string", version: "string", status: PackagePublishAttemptStatusSchema, diff --git a/packages/schema/src/schemas.test.ts b/packages/schema/src/schemas.test.ts index 9626f412..a199a1e6 100644 --- a/packages/schema/src/schemas.test.ts +++ b/packages/schema/src/schemas.test.ts @@ -131,6 +131,7 @@ describe("clawhub-schema", () => { ok: true, packageId: "packages:demo", releaseId: "packageReleases:demo", + artifactSha256: "a".repeat(64), publicationStatus: "pending", attemptId: "publishAttempts:demo", }, @@ -138,6 +139,7 @@ describe("clawhub-schema", () => { ); expect(response.releaseId).toBe("packageReleases:demo"); + expect(response.artifactSha256).toBe("a".repeat(64)); expect(response.publicationStatus).toBe("pending"); expect(response.attemptId).toBe("publishAttempts:demo"); }); @@ -149,6 +151,7 @@ describe("clawhub-schema", () => { attemptId: "publishAttempts:demo", packageId: "packages:demo", releaseId: "packageReleases:demo", + artifactSha256: "a".repeat(64), name: "@openclaw/demo", version: "1.0.0", status: "blocked", @@ -164,6 +167,7 @@ describe("clawhub-schema", () => { ); expect(response.publicationStatus).toBe("blocked"); + expect(response.artifactSha256).toBe("a".repeat(64)); expect(response.terminal).toBe(true); expect(response.checks.clawscan.status).toBe("blocked"); }); diff --git a/scripts/run-playwright-local-auth.ts b/scripts/run-playwright-local-auth.ts index 26bf2315..5ea8dee1 100644 --- a/scripts/run-playwright-local-auth.ts +++ b/scripts/run-playwright-local-auth.ts @@ -506,6 +506,7 @@ async function main() { `AUTH_GITHUB_ID=${e2eEnv.AUTH_GITHUB_ID}`, `AUTH_GITHUB_SECRET=${e2eEnv.AUTH_GITHUB_SECRET}`, "CLAWHUB_DISABLE_CRONS=1", + "CLAWHUB_EXPERIMENTAL_CLAWS=1", "CLAWHUB_SKILLS_SH_ROLLOUT_MODE=test", `CLAWHUB_EMAIL_CAPTURE_FILE=${e2eEnv.CLAWHUB_EMAIL_CAPTURE_FILE}`, ...(deployment ? [`CONVEX_DEPLOYMENT=${deployment}`] : []), @@ -555,6 +556,7 @@ async function main() { { name: "AUTH_GITHUB_ID", value: e2eEnv.AUTH_GITHUB_ID ?? "local-dev" }, { name: "AUTH_GITHUB_SECRET", value: e2eEnv.AUTH_GITHUB_SECRET ?? "local-dev" }, { name: "CLAWHUB_DISABLE_CRONS", value: "1" }, + { name: "CLAWHUB_EXPERIMENTAL_CLAWS", value: "1" }, { name: "CLAWHUB_SKILLS_SH_ROLLOUT_MODE", value: "test" }, { name: "CLAWHUB_EMAIL_CAPTURE_FILE", value: e2eEnv.CLAWHUB_EMAIL_CAPTURE_FILE ?? "" }, { name: "CLAWHUB_STAGED_PREPUBLICATION_PUBLISHES", value: "1" }, diff --git a/specs/claws.md b/specs/claws.md index b152e250..72758114 100644 --- a/specs/claws.md +++ b/specs/claws.md @@ -118,3 +118,23 @@ Convex storage. The server rejects `family: claw` before mutation when the experimental gate is disabled; the gate does not bypass ownership, moderation, scanning, or release invariants when enabled. + +Experimental Claw publication is exact-artifact-only: + +- The publisher must submit an already-built npm-pack `.tgz`; source folders, + GitHub checkouts, extracted-file payloads, and the legacy public-action path + cannot publish a Claw release. +- The publisher supplies the canonical lowercase SHA-256 of that tarball. + ClawHub recomputes the digest from the uploaded bytes before mutation and + rejects a missing or mismatched digest. +- The verified tarball digest remains the artifact identity through staged + scanning, finalization, publication status responses, and exact-byte + download. +- Staged retry identity includes the actor, owner, package name, version, and + verified artifact digest. Only an exact retry may reuse the same active + pending attempt or active published release. A different actor, owner, or + digest, a terminal attempt, or a deleted, blocked, quarantined, revoked, or + malicious release remains a version conflict. +- Retry compatibility is scoped to Claws. Existing non-Claw package behavior + and historical attempt recovery remain unchanged unless they already carry + the exact artifact metadata required by their own contract. diff --git a/specs/security-moderation.md b/specs/security-moderation.md index 2cdf2ac0..901c6424 100644 --- a/specs/security-moderation.md +++ b/specs/security-moderation.md @@ -303,6 +303,23 @@ See also: [acceptable-usage.md](./acceptable-usage.md) for the marketplace polic - For tarball uploads, ClawHub stores the uploaded tarball, derives its artifact hashes and npm metadata, and derives package file metadata from the tarball contents. +- Experimental `family: claw` publication requires one already-built npm-pack + `.tgz` plus the publisher-computed canonical lowercase SHA-256. It must not + accept source directories, GitHub checkout sources, extracted-file + publication, or the legacy public-action path. The HTTP boundary recomputes + the digest from the accepted tarball bytes before creating or reusing any + release state. +- A Claw staged-attempt key binds actor, owner, normalized package name, + version, and verified tarball digest. Only that exact tuple may reuse an + active pending attempt or active published release. Different artifacts or + owners and terminal, deleted, blocked, quarantined, revoked, or malicious + state must preserve the version conflict rather than being reused or + discarded. +- Claw pending and final publication responses expose the verified artifact + SHA-256. Polling must preserve the same digest, and the package artifact + download must serve the exact stored tarball bytes whose SHA-256 matches that + value. Trusted publish tokens accepted by an idempotent retry are revoked on + the same success boundary as a newly created attempt. - A staged publish attempt is not a successful release. ClawHub dispatches an exact pre-publication worker through the production GitHub App as soon as the attempt becomes pending; the scheduled worker remains recovery for missed