diff --git a/docs/release/contract.md b/docs/release/contract.md new file mode 100644 index 000000000..15194b2b6 --- /dev/null +++ b/docs/release/contract.md @@ -0,0 +1,102 @@ +# Stable npm release contract + +This contract governs `releases/v1/latest.json`, `releases/v1/releases/.json`, and unauthenticated `GET https://api.diffex.ai/api/latest-version`. +The CLI monorepo publishes records after checking every public workspace package at its exact version and confirming tarball availability. +The public API Worker validates the stored record and projects the public response without querying npm per request. +The marker means npm-verified stable release availability at publication time. +The release workflow publishes the GitHub Release after the announcement, so the marker alone does not guarantee publicly available binary assets or their upgrade path. +Integrity metadata is validated structurally; this contract does not claim that the publisher downloads tarballs and recomputes their digests. + +## Stored record + +Records are JSON objects with exactly these required fields. +Unknown fields are rejected at the root and within packages; schema changes require coordinated publisher and consumer updates. +Records have no top-level `packageName`, `channel`, or `note`. + +| Field | Requirement | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| `schemaVersion` | JSON number `1`. | +| `version` | Canonical stable `major.minor.patch` string, each component `0` or a nonzero decimal digit followed by decimal digits. | +| `sourceCommit` | Full Git SHA-1 as exactly 40 lowercase hexadecimal characters. | +| `publishedAt` | Real UTC calendar timestamp in the publisher's `YYYY-MM-DDTHH:mm:ss.sssZ` format, round-tripping through `Date.toISOString()`. | +| `packages` | Nonempty array of package objects with unique names, including exactly one `@diffexai/diffex`. | + +Versions exclude prereleases, build metadata, leading `v`, leading zeroes, surrounding whitespace, and trailing newlines. +Components are decimal integers without a JavaScript safe-integer ceiling; the publisher compares them with `BigInt`. +Consumers must reject unsupported numeric ranges rather than rounding them or constructing a different installation target. + +Each package has exactly `name`, `version`, `tarball`, and `integrity`. +Names use lowercase npm-style names, optionally scoped, matching `(?:@[a-z0-9][a-z0-9._-]*/)?[a-z0-9][a-z0-9._-]*` in full, with at most 214 characters. +Every package version equals the record version, including the canonical CLI package. +The Worker does not hardcode the workspace package inventory; verifying completeness against the source checkout belongs to release CI. +Package order has no meaning. + +Tarballs are canonical absolute HTTPS URLs that round-trip through `URL.href`, without embedded username, password, or fragment. +Integrity is one `sha256`, `sha384`, or `sha512` SRI digest with canonical padded base64 encoding and the corresponding 32, 48, or 64 decoded bytes. +Empty values, malformed encodings, unsupported algorithms, and multiple digests are rejected. +Tarball URLs, integrity, commit, timestamp, and workspace inventory stay out of the public latest-version response. + +The publisher validates new records before writing either key and validates existing records before using them for repeat publication or latest-pointer comparisons. +Existing malformed records fail closed and are not treated as missing. +Publication still requires npm verification, immutable versioned records, and conditional latest-pointer writes that cannot regress the version. + +## HTTP behavior + +| Condition | Status | JSON body | Additional header | +| ------------------------------------------------------------------------ | ------ | ------------------------------------------------------------------- | ----------------- | +| Valid stored release | `200` | `{"version":"","packageName":"@diffexai/diffex"}` | None | +| Latest object absent | `404` | `{"error":"no_published_release"}` | None | +| Invalid JSON, invalid record, read/body failure, or inaccessible storage | `503` | `{"error":"release_unavailable"}` | None | +| Method other than `GET` | `405` | `{"error":"method_not_allowed"}` | `Allow: GET` | + +All responses use `Content-Type: application/json; charset=utf-8` and `Cache-Control: no-store`. +The HTTP runtime suppresses the body for `HEAD`, while preserving the `405` status and headers. +Method rejection takes precedence over release availability and should happen before storage access. +Only absence of the fixed latest object means no published release; JSON `null`, denied access, malformed content, and a missing binding mean unavailable. +Internal exception messages must never enter responses. +The endpoint has no caller-dependent version filtering, authentication, cookies, or credential selection and ignores query parameters. +Equal, older, and newer callers receive the same verified release. +There is no npm-tag, Pi, binary URL, or other fallback authority. +Unsupported paths, including trailing-slash and suffix variants, remain `404 {"error":"not_found"}` at the Worker routing boundary. + +## Ownership and conformance + +The cloud implementation lives in `services/public-api/src/release-contract.ts` and `latest-version-response.ts`. +The CLI counterpart lives in `packages/coding-agent/src/utils/release-contract.ts` and is used by the publisher. +The cloud fixture corpus is `services/public-api/fixtures/release-contract.json`; its CLI copy is `scripts/fixtures/release-contract.json`. +This document is mirrored as cloud `docs/release-contract.md` and CLI `docs/release/contract.md`. +The fixtures are synthetic examples, never proof of an actual published version. + +When either side changes, update both copies of this document and the fixture corpus, run both repositories' contract tests and required quality gates, and include companion PR links. +From the cloud root, compare the two checkouts with: + +```sh +node scripts/check-release-contract.mjs /path/to/diffex-new +``` + +Run cloud contract tests from `services/public-api`: + +```sh +npm run test -- tests/unit/release-contract.test.ts +npm run check +``` + +Run publisher tests from the CLI root and consumer fixture tests from `packages/coding-agent`: + +```sh +node --test scripts/release-contract.test.mjs scripts/publish-release-announcement.test.mjs +node ../../node_modules/vitest/dist/cli.js --run test/release-contract.test.ts +``` + +The contract corpus covers required fields and types, stable version exclusions, package identity and uniqueness, lockstep versions, timestamp, commit, URL, integrity, unknown fields, public projection, and all HTTP outcomes. +Command-level publisher tests validate actual emitted records against the corpus rules with controlled npm responses and intercepted storage operations. +All temporary publisher fixtures are removed after testing, and these checks need no staging or production credentials. + +## Integration status + +Record validation and response projection are defined and tested locally. +The existing Worker shell continues returning unavailable until R2 reads and lookup outcome mapping are connected. +The live CLI checker still uses its previous authority and parsing behavior; the strict consumer parser is available for the separately planned endpoint migration. +Its existing update-note behavior has not been changed by defining a response with no note field. +There is no deployed R2-to-HTTP-to-CLI E2E path in this change, and fixture tests do not claim deployed routing or live installation readiness. +The landing application and authenticated Render `/v1` contracts require no change for this contract definition. diff --git a/docs/release/publication.md b/docs/release/publication.md index 15a575c5a..d94b275f8 100644 --- a/docs/release/publication.md +++ b/docs/release/publication.md @@ -47,6 +47,10 @@ If enforced read-only storage access is required, configure a separate read-only ## Publication invariants +The [stable release contract](contract.md) specifies the exact stored schema and public HTTP projection. +The publisher now enforces that schema for both new and existing records. +The consumer fixture suite prepares strict parsing for the future endpoint migration. + Before any write, the publisher inventories every non-private workspace package and requires its version to match the requested canonical stable semver. It checks exact npm package identity and version, integrity metadata, and tarball availability for all packages. Requests have a 30-second timeout, npm propagation retries have a ten-minute budget, and storage commands have a one-minute timeout. diff --git a/packages/coding-agent/src/utils/release-contract.ts b/packages/coding-agent/src/utils/release-contract.ts new file mode 100644 index 000000000..112728492 --- /dev/null +++ b/packages/coding-agent/src/utils/release-contract.ts @@ -0,0 +1,103 @@ +// Kept in agreement with the CLI publisher through the shared contract fixtures. +export const RELEASE_PACKAGE_NAME = "@diffexai/diffex"; + +export interface ReleasePackage { + name: string; + version: string; + tarball: string; + integrity: string; +} + +export interface ReleaseRecord { + schemaVersion: 1; + version: string; + sourceCommit: string; + publishedAt: string; + packages: ReleasePackage[]; +} + +export interface LatestVersion { + version: string; + packageName: typeof RELEASE_PACKAGE_NAME; +} + +function matches(value: unknown, pattern: RegExp): value is string { + return typeof value === "string" && pattern.exec(value)?.[0] === value; +} + +export function isStableVersion(value: unknown): value is string { + return matches(value, /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/); +} + +function hasFields(value: unknown, fields: string[]): value is Record { + return ( + typeof value === "object" && + value !== null && + !Array.isArray(value) && + Object.keys(value).length === fields.length && + fields.every((field) => Object.hasOwn(value, field)) + ); +} + +function isTarball(value: unknown): value is string { + if (typeof value !== "string" || value.trim() !== value) return false; + try { + const url = new URL(value); + return url.protocol === "https:" && url.href === value && !url.username && !url.password && !url.hash; + } catch { + return false; + } +} + +function isIntegrity(value: unknown): value is string { + if (typeof value !== "string") return false; + const match = /^(sha256|sha384|sha512)-([A-Za-z0-9+/]+={0,2})$/.exec(value); + if (!match || match[0] !== value) return false; + try { + const decoded = atob(match[2]); + return decoded.length === Number(match[1].slice(3)) / 8 && btoa(decoded) === match[2]; + } catch { + return false; + } +} + +export function isReleaseRecord(value: unknown): value is ReleaseRecord { + if ( + !hasFields(value, ["schemaVersion", "version", "sourceCommit", "publishedAt", "packages"]) || + value.schemaVersion !== 1 || + !isStableVersion(value.version) || + !matches(value.sourceCommit, /^[a-f0-9]{40}$/) || + !matches(value.publishedAt, /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/) || + !Number.isFinite(Date.parse(value.publishedAt)) || + new Date(value.publishedAt).toISOString() !== value.publishedAt || + !Array.isArray(value.packages) || + value.packages.length === 0 + ) { + return false; + } + + const names = new Set(); + for (const pkg of value.packages) { + if ( + !hasFields(pkg, ["name", "version", "tarball", "integrity"]) || + !matches(pkg.name, /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/) || + pkg.name.length > 214 || + names.has(pkg.name) || + pkg.version !== value.version || + !isTarball(pkg.tarball) || + !isIntegrity(pkg.integrity) + ) { + return false; + } + names.add(pkg.name); + } + return names.has(RELEASE_PACKAGE_NAME); +} + +export function isLatestVersion(value: unknown): value is LatestVersion { + return ( + hasFields(value, ["version", "packageName"]) && + isStableVersion(value.version) && + value.packageName === RELEASE_PACKAGE_NAME + ); +} diff --git a/packages/coding-agent/test/release-contract.test.ts b/packages/coding-agent/test/release-contract.test.ts new file mode 100644 index 000000000..2102ab248 --- /dev/null +++ b/packages/coding-agent/test/release-contract.test.ts @@ -0,0 +1,13 @@ +import { readFileSync } from "node:fs"; +import { describe, expect, it } from "vitest"; +import { isLatestVersion } from "../src/utils/release-contract.ts"; + +const fixtures = JSON.parse( + readFileSync(new URL("../../../scripts/fixtures/release-contract.json", import.meta.url), "utf8"), +) as { responses: { name: string; status: number; body: unknown; valid: boolean }[] }; + +describe("Diffex latest-version consumer contract", () => { + it.each(fixtures.responses)("validates $name", (fixture) => { + expect(fixture.status === 200 && isLatestVersion(fixture.body)).toBe(fixture.valid); + }); +}); diff --git a/scripts/fixtures/release-contract.json b/scripts/fixtures/release-contract.json new file mode 100644 index 000000000..64e8dfbd1 --- /dev/null +++ b/scripts/fixtures/release-contract.json @@ -0,0 +1,2269 @@ +{ + "valid": [ + { + "name": "publisher-shaped record", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "leap day", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2024-02-29T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "reordered packages", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "unscoped workspace name", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "diffex-helper", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "sha256 integrity", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "sha384 integrity", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha384-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "stable version 0.0.0", + "value": { + "schemaVersion": 1, + "version": "0.0.0", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "0.0.0", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "0.0.0", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "stable version 9007199254740993.0.0", + "value": { + "schemaVersion": 1, + "version": "9007199254740993.0.0", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "9007199254740993.0.0", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "9007199254740993.0.0", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + } + ], + "invalid": [ + { + "name": "invalid record type None", + "value": null + }, + { + "name": "invalid record type []", + "value": [] + }, + { + "name": "invalid record type True", + "value": true + }, + { + "name": "invalid record type 1", + "value": 1 + }, + { + "name": "invalid record type record", + "value": "record" + }, + { + "name": "missing schemaVersion", + "value": { + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "missing version", + "value": { + "schemaVersion": 1, + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "missing sourceCommit", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "missing publishedAt", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "missing packages", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z" + } + }, + { + "name": "invalid schema 0", + "value": { + "schemaVersion": 0, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid schema 2", + "value": { + "schemaVersion": 2, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid schema 1", + "value": { + "schemaVersion": "1", + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid schema None", + "value": { + "schemaVersion": null, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version ''", + "value": { + "schemaVersion": 1, + "version": "", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version None", + "value": { + "schemaVersion": 1, + "version": null, + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version 123", + "value": { + "schemaVersion": 1, + "version": 123, + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version '01.2.3'", + "value": { + "schemaVersion": 1, + "version": "01.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version '1.02.3'", + "value": { + "schemaVersion": 1, + "version": "1.02.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version '1.2.03'", + "value": { + "schemaVersion": 1, + "version": "1.2.03", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version 'v1.2.3'", + "value": { + "schemaVersion": 1, + "version": "v1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version '1.2.3-beta.1'", + "value": { + "schemaVersion": 1, + "version": "1.2.3-beta.1", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version '1.2.3+build'", + "value": { + "schemaVersion": 1, + "version": "1.2.3+build", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version '1.2'", + "value": { + "schemaVersion": 1, + "version": "1.2", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version '1.2.3\\n'", + "value": { + "schemaVersion": 1, + "version": "1.2.3\n", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version ' 1.2.3'", + "value": { + "schemaVersion": 1, + "version": " 1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid version '1.2.3 '", + "value": { + "schemaVersion": 1, + "version": "1.2.3 ", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid commit ''", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid commit None", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": null, + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid commit 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid commit 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid commit 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid commit 'gggggggggggggggggggggggggggggggggggggggg'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "gggggggggggggggggggggggggggggggggggggggg", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid commit 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\n'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid publication time ''", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid publication time None", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": null, + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid publication time '2026-02-30T00:00:00.000Z'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-02-30T00:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid publication time '2026-09-10'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid publication time '2026-09-10T00:00:00Z'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T00:00:00Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid publication time '2026-09-10T00:00:00.000+00:00'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T00:00:00.000+00:00", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid publication time '2026-09-10T25:00:00.000Z'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T25:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package collection 41", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": null + } + }, + { + "name": "invalid package collection 42", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": {} + } + }, + { + "name": "invalid package collection 43", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [] + } + }, + { + "name": "invalid package collection 44", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package collection 45", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package collection 46", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package collection 47", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + null, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "missing package name", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "missing package version", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "missing package tarball", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "missing package integrity", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package name ''", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package name None", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": null, + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package name 'UPPER'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "UPPER", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package name '@scope'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@scope", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package name 'bad name'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "bad name", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package name '../package'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "../package", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package name 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid package name 'name\\n'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "name\n", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "foreign canonical identity", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@foreign/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "mismatched package version 0", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.4", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "mismatched package version 1", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.4", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball ''", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball None", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": null, + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball 'relative.tgz'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "relative.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball 'http://registry.npmjs.org/a.tgz'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "http://registry.npmjs.org/a.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball 'https://user:pass@example.invalid/a.tgz'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://user:pass@example.invalid/a.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball 'https://example.invalid/a.tgz#fragment'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://example.invalid/a.tgz#fragment", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball ' https://example.invalid/a.tgz'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": " https://example.invalid/a.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball 'https://example.invalid/a.tgz\\n'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://example.invalid/a.tgz\n", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid tarball 'https://EXAMPLE.invalid/a.tgz'", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://EXAMPLE.invalid/a.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid integrity 72", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid integrity 73", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": null + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid integrity 74", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha1-AAAAAAAAAAAAAAAAAAAAAAAAAAA=" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid integrity 75", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-controlled-fixture" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid integrity 76", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-YQ==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid integrity 77", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid integrity 78", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "invalid integrity 79", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + }, + { + "name": "unknown root field", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ], + "note": "unexpected" + } + }, + { + "name": "unknown package field", + "value": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "extra": true + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + } + } + ], + "http": [ + { + "name": "published", + "method": "GET", + "lookup": "record", + "status": 200, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store" + }, + "body": { + "version": "1.2.3", + "packageName": "@diffexai/diffex" + } + }, + { + "name": "no release", + "method": "GET", + "lookup": "missing", + "status": 404, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store" + }, + "body": { + "error": "no_published_release" + } + }, + { + "name": "invalid record", + "method": "GET", + "lookup": "invalid", + "status": 503, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store" + }, + "body": { + "error": "release_unavailable" + } + }, + { + "name": "storage failure", + "method": "GET", + "lookup": "unavailable", + "status": 503, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store" + }, + "body": { + "error": "release_unavailable" + } + }, + { + "name": "unsupported POST", + "method": "POST", + "lookup": "record", + "status": 405, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store", + "allow": "GET" + }, + "body": { + "error": "method_not_allowed" + } + }, + { + "name": "unsupported PUT", + "method": "PUT", + "lookup": "record", + "status": 405, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store", + "allow": "GET" + }, + "body": { + "error": "method_not_allowed" + } + }, + { + "name": "unsupported PATCH", + "method": "PATCH", + "lookup": "record", + "status": 405, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store", + "allow": "GET" + }, + "body": { + "error": "method_not_allowed" + } + }, + { + "name": "unsupported DELETE", + "method": "DELETE", + "lookup": "record", + "status": 405, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store", + "allow": "GET" + }, + "body": { + "error": "method_not_allowed" + } + }, + { + "name": "unsupported OPTIONS", + "method": "OPTIONS", + "lookup": "record", + "status": 405, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store", + "allow": "GET" + }, + "body": { + "error": "method_not_allowed" + } + }, + { + "name": "unsupported HEAD", + "method": "HEAD", + "lookup": "record", + "status": 405, + "headers": { + "content-type": "application/json; charset=utf-8", + "cache-control": "no-store", + "allow": "GET" + }, + "body": { + "error": "method_not_allowed" + } + } + ], + "responses": [ + { + "name": "published", + "status": 200, + "body": { + "version": "1.2.3", + "packageName": "@diffexai/diffex" + }, + "valid": true + }, + { + "name": "no release", + "status": 404, + "body": { + "error": "no_published_release" + }, + "valid": false + }, + { + "name": "invalid record", + "status": 503, + "body": { + "error": "release_unavailable" + }, + "valid": false + }, + { + "name": "storage failure", + "status": 503, + "body": { + "error": "release_unavailable" + }, + "valid": false + }, + { + "name": "unsupported POST", + "status": 405, + "body": { + "error": "method_not_allowed" + }, + "valid": false + }, + { + "name": "unsupported PUT", + "status": 405, + "body": { + "error": "method_not_allowed" + }, + "valid": false + }, + { + "name": "unsupported PATCH", + "status": 405, + "body": { + "error": "method_not_allowed" + }, + "valid": false + }, + { + "name": "unsupported DELETE", + "status": 405, + "body": { + "error": "method_not_allowed" + }, + "valid": false + }, + { + "name": "unsupported OPTIONS", + "status": 405, + "body": { + "error": "method_not_allowed" + }, + "valid": false + }, + { + "name": "unsupported HEAD", + "status": 405, + "body": { + "error": "method_not_allowed" + }, + "valid": false + }, + { + "name": "invalid success shape 10", + "status": 200, + "body": null, + "valid": false + }, + { + "name": "invalid success shape 11", + "status": 200, + "body": [], + "valid": false + }, + { + "name": "invalid success shape 12", + "status": 200, + "body": {}, + "valid": false + }, + { + "name": "invalid success shape 13", + "status": 200, + "body": { + "schemaVersion": 1, + "version": "1.2.3", + "sourceCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "publishedAt": "2026-09-10T12:00:00.000Z", + "packages": [ + { + "name": "@diffexai/diffex-ai", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex-ai/-/diffex-ai-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + { + "name": "@diffexai/diffex", + "version": "1.2.3", + "tarball": "https://registry.npmjs.org/@diffexai/diffex/-/diffex-1.2.3.tgz", + "integrity": "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + } + ] + }, + "valid": false + }, + { + "name": "invalid success shape 14", + "status": 200, + "body": { + "version": "1.2.3" + }, + "valid": false + }, + { + "name": "invalid success shape 15", + "status": 200, + "body": { + "version": "1.2.3", + "packageName": "@foreign/diffex" + }, + "valid": false + }, + { + "name": "invalid success shape 16", + "status": 200, + "body": { + "version": "1.2.3", + "packageName": "@diffexai/diffex", + "note": "hello" + }, + "valid": false + }, + { + "name": "invalid response version 'v1.2.3'", + "status": 200, + "body": { + "version": "v1.2.3", + "packageName": "@diffexai/diffex" + }, + "valid": false + }, + { + "name": "invalid response version '01.2.3'", + "status": 200, + "body": { + "version": "01.2.3", + "packageName": "@diffexai/diffex" + }, + "valid": false + }, + { + "name": "invalid response version '1.2.3-beta.1'", + "status": 200, + "body": { + "version": "1.2.3-beta.1", + "packageName": "@diffexai/diffex" + }, + "valid": false + }, + { + "name": "invalid response version '1.2.3+build'", + "status": 200, + "body": { + "version": "1.2.3+build", + "packageName": "@diffexai/diffex" + }, + "valid": false + }, + { + "name": "invalid response version '1.2.3\\n'", + "status": 200, + "body": { + "version": "1.2.3\n", + "packageName": "@diffexai/diffex" + }, + "valid": false + }, + { + "name": "invalid response version 123", + "status": 200, + "body": { + "version": 123, + "packageName": "@diffexai/diffex" + }, + "valid": false + } + ] +} diff --git a/scripts/fixtures/release-publication/registry.mjs b/scripts/fixtures/release-publication/registry.mjs index c892ea9e1..0cd7d699b 100644 --- a/scripts/fixtures/release-publication/registry.mjs +++ b/scripts/fixtures/release-publication/registry.mjs @@ -30,7 +30,7 @@ globalThis.fetch = async (input, options) => { version: pkg.version, dist: { tarball: `https://tarballs.example.invalid/${encodeURIComponent(pkg.name)}/${pkg.version}.tgz`, - integrity: "sha512-controlled-fixture", + integrity: `sha512-${"A".repeat(86)}==`, }, }); } diff --git a/scripts/publish-release-announcement.mjs b/scripts/publish-release-announcement.mjs index 8c581de7f..5f9238f51 100644 --- a/scripts/publish-release-announcement.mjs +++ b/scripts/publish-release-announcement.mjs @@ -6,6 +6,7 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { pathToFileURL } from "node:url"; import { isDeepStrictEqual } from "node:util"; +import { isReleaseRecord, isStableVersion } from "../packages/coding-agent/src/utils/release-contract.ts"; import { getPublicWorkspacePackages } from "./release-packages.mjs"; const RELEASES_PREFIX = "releases/v1"; @@ -40,7 +41,7 @@ function parseArgs(args) { if (!options.bucket) throw new Error("--bucket is required"); if (!options.endpoint) throw new Error("--endpoint is required"); - if (!options.version || !STABLE_SEMVER_RE.test(options.version)) { + if (!isStableVersion(options.version)) { throw new Error("--version must be a stable semver version"); } return options; @@ -165,14 +166,8 @@ function readRelease(bucket, endpoint, key, outputPath) { } catch { throw new Error("Diffex release record is not valid JSON."); } - if ( - typeof release !== "object" || - release === null || - Array.isArray(release) || - typeof release.version !== "string" || - !STABLE_SEMVER_RE.test(release.version) - ) { - throw new Error("Diffex release record has an invalid version."); + if (!isReleaseRecord(release)) { + throw new Error("Invalid release record in storage."); } return { etag: metadata.ETag, version: release.version, release, body }; } @@ -202,7 +197,9 @@ function putJson(bucket, endpoint, path, key, cacheControl, condition) { export function compareReleaseVersions(left, right) { const leftMatch = STABLE_SEMVER_RE.exec(left); const rightMatch = STABLE_SEMVER_RE.exec(right); - if (!leftMatch || !rightMatch) throw new Error("Release versions must be stable semver versions."); + if (!isStableVersion(left) || !isStableVersion(right) || !leftMatch || !rightMatch) { + throw new Error("Release versions must be stable semver versions."); + } for (const index of [1, 2, 3]) { const leftPart = BigInt(leftMatch[index]); @@ -252,6 +249,7 @@ async function main() { publishedAt: new Date().toISOString(), packages: publishedPackages, }; + if (!isReleaseRecord(release)) throw new Error("Invalid release record; publication refused."); const temporaryDirectory = mkdtempSync(join(tmpdir(), "diffex-release-announcement-")); try { const releasePath = join(temporaryDirectory, "release.json"); diff --git a/scripts/publish-release-announcement.test.mjs b/scripts/publish-release-announcement.test.mjs index a52d9704b..d7458910e 100644 --- a/scripts/publish-release-announcement.test.mjs +++ b/scripts/publish-release-announcement.test.mjs @@ -193,3 +193,15 @@ test("version comparison rejects noncanonical versions and avoids numeric precis } assert.equal(compareReleaseVersions("9007199254740993.0.0", "9007199254740992.0.0"), 1); }); + +test("publisher rejects a noncanonical source commit before storing records", () => { + const fixture = createPublicationFixture(); + try { + const result = fixture.run("0.0.3", { commit: "not-a-commit" }); + assert.equal(result.status, 1); + assert.match(result.stderr, /Invalid release record/); + assert.deepEqual(fixture.state().objects, {}); + } finally { + fixture.cleanup(); + } +}); diff --git a/scripts/release-contract.test.mjs b/scripts/release-contract.test.mjs new file mode 100644 index 000000000..ad20d3cb2 --- /dev/null +++ b/scripts/release-contract.test.mjs @@ -0,0 +1,54 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import test from "node:test"; +import { isLatestVersion, isReleaseRecord } from "../packages/coding-agent/src/utils/release-contract.ts"; +import { createPublicationFixture } from "./fixtures/release-publication/harness.mjs"; + +const fixtures = JSON.parse(readFileSync(new URL("./fixtures/release-contract.json", import.meta.url), "utf8")); +for (const { name, value } of fixtures.valid) { + test(`accepts ${name}`, () => assert.equal(isReleaseRecord(value), true)); +} +for (const { name, value } of fixtures.invalid) { + test(`rejects ${name}`, () => assert.equal(isReleaseRecord(value), false)); +} +for (const fixture of fixtures.responses) { + test(`response ${fixture.name}`, () => { + assert.equal(fixture.status === 200 && isLatestVersion(fixture.body), fixture.valid); + }); +} +test("real publisher output conforms to the shared Worker record contract", () => { + const fixture = createPublicationFixture(); + try { + const result = fixture.run("1.2.3"); + assert.equal(result.status, 0, result.stderr); + for (const body of Object.values(fixture.state().objects)) { + const record = JSON.parse(body); + assert.equal(isReleaseRecord(record), true); + assert.equal(record.packages.length, fixture.packageCount); + assert.deepEqual( + { + version: record.version, + packageName: record.packages.find((pkg) => pkg.name === "@diffexai/diffex").name, + }, + fixtures.http[0].body, + ); + } + } finally { + fixture.cleanup(); + } +}); +test("publisher rejects every invalid stored latest record without replacing its bytes", () => { + const fixture = createPublicationFixture(); + try { + for (const { name, value } of fixtures.invalid) { + const body = JSON.stringify(value); + fixture.seed({ "releases/v1/latest.json": body }); + const result = fixture.run("1.2.3"); + assert.equal(result.status, 1, name); + assert.match(result.stderr, /Invalid release record/, name); + assert.equal(fixture.state().objects["releases/v1/latest.json"], body, name); + } + } finally { + fixture.cleanup(); + } +});