From 458df3002b2ebe434acbd06c1fdef3daaae14271 Mon Sep 17 00:00:00 2001 From: hzongquan Date: Sat, 15 Aug 2026 20:05:59 +0800 Subject: [PATCH 1/2] chore: use publishable Pontx runtime releases --- package.json | 4 ++-- pnpm-lock.yaml | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 4e01afa..c7aace8 100644 --- a/package.json +++ b/package.json @@ -57,8 +57,8 @@ "access": "public" }, "dependencies": { - "@pontx/sdk": "1.0.0-beta.9", - "pontx": "1.0.0-beta.16" + "@pontx/sdk": "1.0.0-beta.11", + "pontx": "1.0.0-beta.18" }, "devDependencies": { "@types/node": "^22.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6134253..e343867 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,11 +9,11 @@ importers: .: dependencies: '@pontx/sdk': - specifier: 1.0.0-beta.9 - version: 1.0.0-beta.9(typescript@5.9.3) + specifier: 1.0.0-beta.11 + version: 1.0.0-beta.11(typescript@5.9.3) pontx: - specifier: 1.0.0-beta.16 - version: 1.0.0-beta.16 + specifier: 1.0.0-beta.18 + version: 1.0.0-beta.18 devDependencies: '@types/node': specifier: ^22.0.0 @@ -502,8 +502,8 @@ packages: cpu: [x64] os: [linux] - '@pontx/sdk@1.0.0-beta.9': - resolution: {integrity: sha512-PLumKBXtJTfy/IAzSmXOywegmHbUmnrpFUpIkmGm7kptnbjP/evOXLfK3fTdT3INbuOsnUGUU9q5YiI9HveGEw==} + '@pontx/sdk@1.0.0-beta.11': + resolution: {integrity: sha512-5IJeVEFyv9Iy/NdHp9bTl9gOt6R2mvxMrhrrUo5xK3m5CcuidHI/9cU467NyC67/vaYmeUfcGWetRq7buOqtCA==} engines: {node: '>=18.0.0'} peerDependencies: typescript: '>=5.0.0' @@ -514,8 +514,8 @@ packages: zod: optional: true - '@pontx/spec@1.0.0-beta.7': - resolution: {integrity: sha512-HJ2MLJO3idicuLn4BR/y/NsLB6ZAik+ej0sGM8aPPO2IYJLYyrDUdP2SCaVEoWpszyEv5rYOAKMrh9CDzOS4cw==} + '@pontx/spec@1.0.0-beta.9': + resolution: {integrity: sha512-/l/HSW6Kac0o7QGkF3lZQqtatUb/7CE48FYY9MkMRcSbQ5dgDwaWFIXvQ8uFvkiQc09EBA4VOlkEWpIfOorakw==} '@rollup/rollup-android-arm-eabi@4.62.4': resolution: {integrity: sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==} @@ -891,8 +891,8 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pontx@1.0.0-beta.16: - resolution: {integrity: sha512-LvBMj0Q92uqUOolSmnOHV6rabp7LtPCHMBEC4NxU0uTzB82JTzw4XVj4rLv7M7Zj8/wAqynUqIDOJVz9633fGA==} + pontx@1.0.0-beta.18: + resolution: {integrity: sha512-hPOK4Omezg5lkoItH+fK+TUPca5flhoCy47oAvkoMbBGhmPMeKtwGy8C674AypugBnKukaAVuccKj8KzdSEJGg==} engines: {node: '>=18.0.0'} hasBin: true @@ -1366,13 +1366,13 @@ snapshots: '@napi-rs/lzma-linux-x64-gnu@1.5.1': optional: true - '@pontx/sdk@1.0.0-beta.9(typescript@5.9.3)': + '@pontx/sdk@1.0.0-beta.11(typescript@5.9.3)': dependencies: - '@pontx/spec': 1.0.0-beta.7 + '@pontx/spec': 1.0.0-beta.9 optionalDependencies: typescript: 5.9.3 - '@pontx/spec@1.0.0-beta.7': + '@pontx/spec@1.0.0-beta.9': dependencies: immer: 10.2.0 lodash: 4.18.1 @@ -1739,9 +1739,9 @@ snapshots: mlly: 1.8.2 pathe: 2.0.3 - pontx@1.0.0-beta.16: + pontx@1.0.0-beta.18: dependencies: - '@pontx/spec': 1.0.0-beta.7 + '@pontx/spec': 1.0.0-beta.9 baidu-translate-service: 2.2.4 commander: 13.1.0 esbuild: 0.20.2 From 2fd22601a4c31165d8792285f5ca865feadb7307 Mon Sep 17 00:00:00 2001 From: hzongquan Date: Sat, 15 Aug 2026 20:10:45 +0800 Subject: [PATCH 2/2] test: verify canonical Pinhere discovery bytes --- README.md | 5 +-- scripts/lib/canonical-discovery.mjs | 56 +++++++++++++++++++++++++++ scripts/verify-release-readiness.mjs | 7 ++++ source.provenance.json | 5 ++- test/unit/canonical-discovery.test.ts | 36 +++++++++++++++++ 5 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 scripts/lib/canonical-discovery.mjs create mode 100644 test/unit/canonical-discovery.test.ts diff --git a/README.md b/README.md index 19f64dc..d4ce520 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,8 @@ canonical PontxSpec. This repository is generated from the MIT-licensed, product-owned contract in [`jasonHzq/pinhere`](https://github.com/jasonHzq/pinhere). The source and package are ready for public review, but npm publication remains fail-closed -until `pinhere.dev` serves the production API and canonical -`/.well-known/pontx.json` discovery resource. The current Vercel Preview is not -the canonical production origin. +until the canonical `https://pinhere.dev/.well-known/pontx.json` response is +DNS-reachable and byte-for-byte matches the pinned canonical JSON contract. ## Safety boundary diff --git a/scripts/lib/canonical-discovery.mjs b/scripts/lib/canonical-discovery.mjs new file mode 100644 index 0000000..b297def --- /dev/null +++ b/scripts/lib/canonical-discovery.mjs @@ -0,0 +1,56 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; + +export function sha256(bytes) { + return createHash("sha256").update(bytes).digest("hex"); +} + +export function canonicalJsonBytes(bytes) { + return Buffer.from(JSON.stringify(JSON.parse(Buffer.from(bytes).toString("utf8"))), "utf8"); +} + +export async function verifyCanonicalDiscovery({ + url, + sourceBytes, + expectedCanonicalJsonSha256, + fetchImpl = fetch, +}) { + const source = JSON.parse(Buffer.from(sourceBytes).toString("utf8")); + const expected = canonicalJsonBytes(sourceBytes); + assert.equal( + sha256(expected), + expectedCanonicalJsonSha256, + "Release blocked: pinned canonical JSON hash does not match the source contract.", + ); + + let response; + try { + response = await fetchImpl(url, { + headers: { accept: "application/json" }, + signal: AbortSignal.timeout(20_000), + }); + } catch (error) { + throw new Error(`Release blocked: canonical discovery fetch failed (${error.message}).`); + } + assert(response.ok, + `Release blocked: canonical discovery returned HTTP ${response.status}.`); + assert.match(response.headers.get("content-type") ?? "", /^application\/json(?:;|$)/i, + "Release blocked: canonical discovery must return application/json."); + + const actual = Buffer.from(await response.arrayBuffer()); + assert.equal( + sha256(actual), + expectedCanonicalJsonSha256, + "Release blocked: canonical discovery bytes do not match the pinned canonical JSON contract.", + ); + let parsed; + try { + parsed = JSON.parse(actual.toString("utf8")); + } catch (error) { + throw new Error(`Release blocked: canonical discovery is not valid JSON (${error.message}).`); + } + assert.deepEqual(parsed, source, + "Release blocked: canonical discovery JSON differs from the pinned source contract."); + + return { sha256: sha256(actual), bytes: actual.length }; +} diff --git a/scripts/verify-release-readiness.mjs b/scripts/verify-release-readiness.mjs index e9a7afc..3e3d4c3 100644 --- a/scripts/verify-release-readiness.mjs +++ b/scripts/verify-release-readiness.mjs @@ -2,6 +2,7 @@ import assert from "node:assert/strict"; import { execFileSync } from "node:child_process"; import { readFile } from "node:fs/promises"; import { resolve } from "node:path"; +import { verifyCanonicalDiscovery } from "./lib/canonical-discovery.mjs"; const packageJson = JSON.parse(await readFile(resolve("package.json"), "utf8")); const provenance = JSON.parse(await readFile(resolve("source.provenance.json"), "utf8")); @@ -18,6 +19,12 @@ assert.equal(provenance.source.license, packageJson.license, "Release blocked: package and contract provenance licenses differ."); assert.equal(provenance.discovery.status, "verified", "Release blocked: canonical Pinhere discovery is not verified."); +const sourceBytes = await readFile(resolve("pontx-spec.json")); +await verifyCanonicalDiscovery({ + url: provenance.discovery.url, + sourceBytes, + expectedCanonicalJsonSha256: provenance.discovery.canonicalJsonSha256, +}); assert(!/(?:^|\s)(?:link|file|workspace):|^\s*overrides\s*:/im.test(`${workspace}\n${lockfile}`), "Release blocked: local dependency links or workspace overrides remain."); diff --git a/source.provenance.json b/source.provenance.json index c90f547..3341e8d 100644 --- a/source.provenance.json +++ b/source.provenance.json @@ -11,7 +11,8 @@ }, "discovery": { "url": "https://pinhere.dev/.well-known/pontx.json", - "status": "domain-unregistered", + "status": "pending-dns-verification", + "canonicalJsonSha256": "7a98a17ca28eca19325b0aaa5b02fd54a119c1e36adcf99ea40bf1896c777d3c", "verifiedAt": "2026-08-15" }, "output": { @@ -20,6 +21,6 @@ "proxyDisabledOperations": 34 }, "releaseBlockedBy": [ - "pinhere.dev is unregistered, so the canonical production API and discovery URL are unreachable" + "pinhere.dev is attached to the production deployment but its DNS and canonical discovery bytes are not yet verified" ] } diff --git a/test/unit/canonical-discovery.test.ts b/test/unit/canonical-discovery.test.ts new file mode 100644 index 0000000..6c4c4d2 --- /dev/null +++ b/test/unit/canonical-discovery.test.ts @@ -0,0 +1,36 @@ +import { createHash } from "node:crypto"; +import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; +import { expect, test } from "vitest"; +import { + canonicalJsonBytes, + verifyCanonicalDiscovery, +} from "../../scripts/lib/canonical-discovery.mjs"; + +const sourceBytes = await readFile(resolve("pontx-spec.json")); +const canonicalBytes = canonicalJsonBytes(sourceBytes); +const canonicalHash = createHash("sha256").update(canonicalBytes).digest("hex"); + +test("verifies a canonical discovery response against the pinned source contract", async () => { + await expect(verifyCanonicalDiscovery({ + url: "https://pinhere.dev/.well-known/pontx.json", + sourceBytes, + expectedCanonicalJsonSha256: canonicalHash, + fetchImpl: async () => new Response(canonicalBytes, { + status: 200, + headers: { "content-type": "application/json; charset=utf-8" }, + }), + })).resolves.toMatchObject({ sha256: canonicalHash, bytes: canonicalBytes.length }); +}); + +test("rejects a discovery response with noncanonical bytes", async () => { + await expect(verifyCanonicalDiscovery({ + url: "https://pinhere.dev/.well-known/pontx.json", + sourceBytes, + expectedCanonicalJsonSha256: canonicalHash, + fetchImpl: async () => new Response("{}", { + status: 200, + headers: { "content-type": "application/json" }, + }), + })).rejects.toThrow("canonical discovery bytes do not match"); +});