@crawlcheck/sdk 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
2
  "name": "@crawlcheck/sdk",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.1",
4
+ "description": "Typed client for the CrawlCheck API (generated from its OpenAPI document) and the zero-dependency offline verifier for evidence bundles and remediation receipts.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "test",
17
+ "README.md"
18
+ ],
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "sideEffects": false,
23
+ "homepage": "https://crawlcheck.io/sdk",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/emmanuelorta/crawlcheck.git",
27
+ "directory": "sdk"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/emmanuelorta/crawlcheck/issues"
31
+ },
32
+ "keywords": [
33
+ "crawlcheck",
34
+ "verification",
35
+ "evidence",
36
+ "ai-crawlers",
37
+ "openapi",
38
+ "ed25519",
39
+ "merkle",
40
+ "opentimestamps"
41
+ ],
42
+ "scripts": {
43
+ "test": "node --test test/*.test.js"
44
+ }
45
+ }
@@ -0,0 +1,45 @@
1
+ // Runs against the live API. npm test
2
+ import test from "node:test"; import assert from "node:assert/strict";
3
+ import { CrawlCheck, verifyBundle, verifyReceipt, CrawlCheckError } from "../dist/index.js";
4
+ const c = new CrawlCheck();
5
+
6
+ test("conformance: every published fixture gives its expected output through this package's verifier", async () => {
7
+ const r = await c.conformance();
8
+ const bad = r.results.filter((x) => !x.ok);
9
+ assert.equal(bad.length, 0, bad.map((x) => x.name + ": " + x.diffs.join("; ")).join("\n"));
10
+ assert.ok(r.results.length >= 19, "fixtures: " + r.results.length);
11
+ });
12
+
13
+ test("conformance: the one receipt a verifier cannot reject offline is rejected by comparing published key ids", async () => {
14
+ const ids = await c.publishedKeyIds();
15
+ const ix = await (await fetch(c.base + "/conformance/index.json")).json();
16
+ const f = ix.fixtures.find((x) => x.name === "receipt-foreign-key"), good = ix.fixtures.find((x) => x.name === "receipt-valid");
17
+ const forged = await (await fetch(f.file)).json(), real = await (await fetch(good.file)).json();
18
+ assert.equal((await verifyReceipt(forged)).verified, true, "offline it verifies");
19
+ assert.ok(!ids.includes(forged.signature.kid), "and its key id is not published");
20
+ assert.ok(ids.includes(real.signature.kid), "while the real receipt's key id is");
21
+ });
22
+
23
+ test("live machine record: typed fields present, evidence links resolve, offline bundle verification agrees", async () => {
24
+ const mr = await c.machineRecord({ domain: "crawlcheck.io" });
25
+ assert.equal(mr.kind, "crawlcheck-machine-record");
26
+ assert.ok(mr.subject && mr.observation && mr.evidence);
27
+ const id = mr.subject.report_id;
28
+ const v = await c.verifyOffline(id);
29
+ assert.ok(v.checks.length >= 11);
30
+ assert.equal(v.checks.filter((x) => x.ok === false).length, 0, JSON.stringify(v.checks.filter((x) => x.ok === false)));
31
+ assert.ok(["manifest_hash", "key_id", "signature"].every((k) => v.checks.find((x) => x.id === k).ok === true), "manifest checks pass on a live record");
32
+ });
33
+
34
+ test("a tampered live bundle fails offline", async () => {
35
+ const mr = await c.machineRecord({ domain: "crawlcheck.io" });
36
+ const b = await c.bundle(mr.subject.report_id);
37
+ b.manifest.body += " ";
38
+ const v = await verifyBundle(b);
39
+ assert.equal(v.verified, false);
40
+ assert.equal(v.checks.find((x) => x.id === "manifest_hash").ok, false);
41
+ });
42
+
43
+ test("locked data surfaces as a typed error, not a crash", async () => {
44
+ await assert.rejects(c.impact({ domain: "wikipedia.org" }), (e) => e instanceof CrawlCheckError && e.locked === true && e.status === 403);
45
+ });