{"_id":"@aioschema/js","_rev":"2-de94d169b9dd4f5f78562ae71860c23c","name":"@aioschema/js","dist-tags":{"latest":"0.5.6"},"versions":{"0.5.5":{"name":"@aioschema/js","version":"0.5.5","keywords":["aioschema","provenance","content-integrity","manifest","cryptographic-hash","ed25519","bitcoin","opentimestamps","ai-content","chain-of-custody"],"author":{"name":"Ovidiu Ancuta","email":"ovidiu@aioschema.org"},"license":"SEE LICENSE IN LICENSE.md","_id":"@aioschema/js@0.5.5","maintainers":[{"name":"aioschema-admin","email":"npm@aioschema.org"}],"homepage":"https://aioschema.org","bugs":{"url":"https://github.com/aioschema/aioschema/issues"},"dist":{"shasum":"945b498002a4d36307483fd2365733d3caebf246","tarball":"https://registry.npmjs.org/@aioschema/js/-/js-0.5.5.tgz","fileCount":4,"integrity":"sha512-xgSze7YUym+Uiv6f0lm5y5KEyXTZw4N4uJc/P7QouTBKXn8Wv1txjI16VCJ1cXSfSDKysW0XLflxL1c4oLQilQ==","signatures":[{"sig":"MEUCIQCoZbgUOThsDGFfB/xhBbKLFtoH1zFvmWS/qgCvPiEPWgIgKlYPPE7GEeH9UJuWPoMyQDt35P1sBN3b5T9s3mOdKCQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31851},"main":"aioschema_v055.js","engines":{"node":">=18"},"gitHead":"0839f80ca4eecb6d36bbe3b55fa5e1913fa692ca","_npmUser":{"name":"aioschema-admin","email":"npm@aioschema.org"},"repository":{"url":"git+https://github.com/aioschema/aioschema.git","type":"git","directory":"implementations/js"},"_npmVersion":"10.9.2","description":"AIOSchema v0.5.5 — Node.js reference implementation library.","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/js_0.5.5_1774051285764_0.13278242319426048","host":"s3://npm-registry-packages-npm-production"}},"0.5.6":{"name":"@aioschema/js","version":"0.5.6","description":"AIOSchema v0.5.6 — Node.js reference implementation library.","main":"aioschema_v055.js","keywords":["aioschema","provenance","content-integrity","manifest","cryptographic-hash","ed25519","ai-content","chain-of-custody"],"author":{"name":"Ovidiu Ancuta","email":"ovidiu@aioschema.org"},"license":"SEE LICENSE IN LICENSE.md","homepage":"https://aioschema.org","repository":{"type":"git","url":"git+https://github.com/aioschema/aioschema.git","directory":"implementations/js"},"bugs":{"url":"https://github.com/aioschema/aioschema/issues"},"engines":{"node":">=18"},"_id":"@aioschema/js@0.5.6","gitHead":"eab55b4630519682d68a15a51dc0540b2e312d7b","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-G9T8pFInaFCiwYFws1xEB2ZLmSHf+NCfyZqTDJlRkvV/wpUOgUImpcOkOWeCQLqS2glVRnYZhHndVNzjcBQnXg==","shasum":"dc5509ea09501963d8cd572feb20c677fcad3c61","tarball":"https://registry.npmjs.org/@aioschema/js/-/js-0.5.6.tgz","fileCount":4,"unpackedSize":39948,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICLv8dWYnGO/PX1CJQ0R9eFh7uvn6Ep6WHxoReXvjhOKAiEA3zdfL6O3tixdgeVY83NX5okOgD1jjsAKemzJXsw9Gfc="}]},"_npmUser":{"name":"aioschema-admin","email":"npm@aioschema.org"},"directories":{},"maintainers":[{"name":"aioschema-admin","email":"npm@aioschema.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/js_0.5.6_1780937917669_0.6303966997649588"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-21T00:01:25.613Z","modified":"2026-06-08T16:58:38.000Z","0.5.5":"2026-03-21T00:01:25.943Z","0.5.6":"2026-06-08T16:58:37.805Z"},"bugs":{"url":"https://github.com/aioschema/aioschema/issues"},"author":{"name":"Ovidiu Ancuta","email":"ovidiu@aioschema.org"},"license":"SEE LICENSE IN LICENSE.md","homepage":"https://aioschema.org","keywords":["aioschema","provenance","content-integrity","manifest","cryptographic-hash","ed25519","ai-content","chain-of-custody"],"repository":{"type":"git","url":"git+https://github.com/aioschema/aioschema.git","directory":"implementations/js"},"description":"AIOSchema v0.5.6 — Node.js reference implementation library.","maintainers":[{"name":"aioschema-admin","email":"npm@aioschema.org"}],"readme":"<!-- SPDX-License-Identifier: Apache-2.0 -->\n<!-- Copyright 2026 Ovidiu Ancuta -->\n<!-- aioschema/js v0.5.6 | AIOSchema spec v0.5.6 | https://aioschema.org -->\n\n# AIOSchema v0.5.6 — Node.js Reference Implementation\n\nCryptographic content provenance for Node.js. Generates, anchors, and verifies\n[AIOSchema](https://aioschema.org) v0.5.6 manifests.\n\n```js\nconst aios = require(\"./aioschema_v056.js\");\n\nconst asset  = require(\"fs\").readFileSync(\"report.pdf\");\nconst manifest = aios.generateManifest(asset, { algorithm: \"sha256\" });\nconst result   = await aios.verifyManifest(asset, manifest);\n\nconsole.log(result.success);     // true\nconsole.log(result.match_type);  // \"hard\"\n```\n\n---\n\n## Requirements\n\n- Node.js 18 or later (uses `node:test`, `node:crypto`)\n- Zero external npm dependencies\n\n---\n\n## Quick start\n\n### Level 1 — Hash binding (unsigned)\n\n```js\nconst aios = require(\"./aioschema_v056.js\");\nconst fs   = require(\"fs\");\n\nconst asset    = fs.readFileSync(\"image.png\");\nconst manifest = aios.generateManifest(asset, { algorithm: \"sha256\" });\n\n// Save sidecar\nfs.writeFileSync(\"image.png.aios.json\", JSON.stringify(manifest, null, 2));\n\n// Verify later\nconst loaded = JSON.parse(fs.readFileSync(\"image.png.aios.json\"));\nconst result = await aios.verifyManifest(fs.readFileSync(\"image.png\"), loaded);\nconsole.log(result.success);    // true\nconsole.log(result.match_type); // \"hard\"\n```\n\n### Level 2 — Signed manifest (Ed25519)\n\n```js\nconst aios = require(\"./aioschema_v056.js\");\nconst fs   = require(\"fs\");\n\n// Generate a keypair (32-byte seed, keep secret)\nconst { seed, publicKey } = aios.generateKeyPair();\nconst creatorId = aios.creatorIdFromPublicKey(publicKey);\n\nconst asset = fs.readFileSync(\"video.mp4\");\n\nconst manifest = aios.generateManifest(asset, {\n  algorithm: \"sha256\",\n  creatorId,\n  seed,\n  extensions: {\n    public_key: Buffer.from(publicKey).toString(\"base64\"),\n  },\n});\n\n// Verify — public key is embedded, no external key needed\nconst result = await aios.verifyManifest(asset, manifest);\nconsole.log(result.success);                    // true\nconsole.log(result.signature_verified);         // true\nconsole.log(result.manifest_signature_verified);// true\nconsole.log(result.public_key_fingerprint_match);// true\n```\n\n### AI disclosure (EU AI Act Article 50)\n\n```js\nconst manifest = aios.generateManifest(asset, {\n  algorithm: \"sha256\",\n  extensions: {\n    ai_declaration: {\n      disclosure_required: true,\n      ai_generated:        true,\n      ai_manipulated:      false,\n      human_reviewed:      true,\n      standard_editing:    false,\n    },\n  },\n});\n```\n\n### Multi-hash manifest\n\n```js\n// hash_original becomes an array — any supported hash passes verification\nconst manifest = aios.generateManifest(asset, {\n  algorithms: [\"sha256\", \"sha384\"],\n});\n// manifest.core.hash_original → [\"sha256-...\", \"sha384-...\"]\n```\n\n---\n\n## API reference\n\n### `generateManifest(data, options)`\n\nGenerates an AIOSchema v0.5.6 manifest for the given asset.\n\n**Parameters**\n\n- `data` — `Buffer` — asset bytes\n- `options`:\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `algorithm` | `string` | `\"sha256\"` | Primary hash algorithm (`\"sha256\"`, `\"sha384\"`, `\"sha3-256\"`) |\n| `algorithms` | `string[]` | — | Multiple algorithms — produces array `hash_original` |\n| `creatorId` | `string` | anonymous UUID v7 | Override `creator_id` |\n| `seed` | `Buffer` | — | Ed25519 seed (32 bytes) — enables Level 2 signing |\n| `extensions` | `object` | `{}` | Merged into the `extensions` block |\n\n**Returns** `object` — the manifest (`{ core, extensions }`)\n\n---\n\n### `verifyManifest(data, manifest, options?)`\n\nRuns the full §10 verification procedure against the asset bytes.\n\n**Parameters**\n\n- `data` — `Buffer` — asset bytes\n- `manifest` — `object` — manifest to verify\n- `options`:\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `verifyAnchor` | `boolean` | `false` | Call `anchorResolver` to check the anchor |\n| `anchorResolver` | `function` | — | `async (anchorUri) => { asset_id, core_fingerprint, timestamp }` |\n| `publicKeyHex` | `string` | — | Override public key for signature verification (usually not needed — use `extensions.public_key`) |\n\n**Returns** `Promise<VerificationResult>`\n\n---\n\n### `VerificationResult`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `success` | `boolean` | Overall pass/fail |\n| `message` | `string` | Human-readable result |\n| `match_type` | `\"hard\"` \\| `\"soft\"` \\| `null` | How the hash matched |\n| `signature_verified` | `boolean` | Core Ed25519 signature verified |\n| `manifest_signature_verified` | `boolean` | Full manifest signature verified |\n| `public_key_fingerprint_match` | `boolean` | `extensions.public_key` fingerprint matched `creator_id` (§11.3) |\n| `anchor_checked` | `boolean` | Anchor reference was resolved |\n| `anchor_verified` | `boolean` | Anchor record matched manifest |\n| `warnings` | `string[]` | Non-fatal issues |\n\n---\n\n### `generateKeyPair()`\n\nGenerates an Ed25519 keypair using OS CSPRNG.\n\n**Returns** `{ seed: Buffer, publicKey: Buffer }` — both 32 bytes\n\n---\n\n### `creatorIdFromPublicKey(publicKey)`\n\nDerives the `ed25519-fp-<32hex>` creator ID from a public key.\n\n**Parameters** — `publicKey: Buffer` — 32-byte Ed25519 public key  \n**Returns** `string` — e.g. `\"ed25519-fp-7fcc5530c17565c99ea02d846ab0b5eb\"`\n\n---\n\n### Constants\n\n| Export | Value | Description |\n|--------|-------|-------------|\n| `SPEC_VERSION` | `\"0.5.6\"` | AIOSchema spec version |\n| `CORE_HASH_FIELDS` | `string[]` | Fields that feed `core_fingerprint` (§5.6) |\n| `MAX_EXTENSION_SIZE_BYTES` | `4096` | Hard ceiling on `extensions` block (§6.3) |\n\n---\n\n## What's in v0.5.6\n\n- **`extensions.public_key`** — embed Ed25519 public key in the manifest; verifier\n  cross-checks its SHA-256 fingerprint against `creator_id` for self-contained L2\n  verification with no out-of-band key lookup (§11.3)\n- **`extensions.ai_declaration`** — structured EU AI Act Article 50 disclosure fields;\n  constraint enforced by verifier: `standard_editing=true` requires `disclosure_required=false` (§11.1)\n- **Multi-hash `hash_original`** — array form; any supported algorithm match passes\n  verification (§5.5)\n- **Extension size enforcement** — `extensions` block capped at 4,096 bytes (§6.3)\n- **`previous_version_anchor`** — provenance chain linking manifest versions (§5.1)\n- **`extensions.description`** — human-readable provenance note, max 256 chars (§17.5.1)\n\n---\n\n## Running the tests\n\n```bash\n# 42 unit tests (Node built-in test runner, no dependencies)\nnode unit_tests_node.js\n\n# 18 cross-implementation verification vectors\nnode cross_verify_node.js\n```\n\nTest breakdown:\n\n| Suite | Count | File |\n|-------|-------|------|\n| `computeHash` | 8 | `unit_tests_node.js` |\n| `parseHashPrefix` | 4 | `unit_tests_node.js` |\n| `canonicalJson` | 6 | `unit_tests_node.js` |\n| `canonicalBytes` | 2 | `unit_tests_node.js` |\n| `safeEqual` | 3 | `unit_tests_node.js` |\n| `verifyManifest` (CV-07–CV-14 + misc) | 11 | `unit_tests_node.js` |\n| `verifyManifest` (TV-19–TV-24, v0.5.6) | 6 | `unit_tests_node.js` |\n| `CORE_HASH_FIELDS` | 2 | `unit_tests_node.js` |\n| **Total unit tests** | **42** | |\n| Cross-implementation vectors (CV-01–CV-18) | 18 | `cross_verify_node.js` |\n\n---\n\n## Conformance\n\nThis implementation passes the full AIOSchema conformance suite:\n\n- **42 unit tests**\n- **24 conformance vectors** (TV-01–TV-24, §5.4)\n- **18 cross-verification vectors** (CV-01–CV-18) — tested against the Python,\n  TypeScript, Go, Rust, and .NET reference implementations\n\nAll six implementations are cryptographically interoperable. A manifest signed\nby any implementation verifies correctly in all others.\n\n---\n\n## Implementation notes\n\n- Zero npm dependencies — `node:crypto` and `node:test` only\n- Ed25519 via `node:crypto` (`generateKeyPairSync`, `createSign`, `createVerify`)\n- SHA-256, SHA-384, SHA3-256 via `node:crypto`\n- Canonical JSON: recursive key sort, compact separators, UTF-8 — §5.6 conformant\n- `asset_id` uses UUID v7 (time-ordered) for stable, sortable identifiers\n- `creator_id` uses UUID v7 (anonymous) or `ed25519-fp-<32hex>` (attributed)\n- Timing-safe comparison throughout (`timingSafeEqual` — §12.1)\n- `hash_original` accepts both string (legacy) and array (multi-hash) forms —\n  see §5.5 implementation note for deserialization guidance\n\n---\n\n## File structure\n\n```\nimplementations/js/\n├── aioschema_v056.js       # Main implementation\n├── unit_tests_node.js      # 42 unit tests (node:test)\n├── cross_verify_node.js    # 18 cross-implementation vectors\n├── package.json            # version 0.5.6\n└── README.md               # This file\n```\n\n---\n\n## Links\n\n- **Specification:** [aioschema.org](https://aioschema.org)\n- **Field reference:** [aioschema.org/field-reference/v0-5-6/](https://aioschema.org/field-reference/v0-5-6/)\n- **Hub and tools:** [aioschemahub.com](https://aioschemahub.com)\n- **All implementations:** [github.com/aioschema/aioschema](https://github.com/aioschema/aioschema)\n- **License:** Apache-2.0\n\n<!-- end aioschema/js v0.5.6 | AIOSchema spec v0.5.6 | https://aioschema.org -->","readmeFilename":"README.md"}