Skip to content
View Nizoka's full-sized avatar

Block or report Nizoka

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
Nizoka/README.md
the native family — pdfnative (ISO 32000-1), zipnative (ISO/IEC 21320-1), pkinative (RFC 5280)

Nizoka

Zero-dependency TypeScript engines for the formats nobody wants to reimplement — PDF, ZIP, PKI.

Most of this code was drafted by AI agents. None of it was shipped by one: there is no long-lived publish token anywhere in this ecosystem, so the only path to the registry is a release a human cut by hand. How this is built ↓

Start here

npm install pdfnative
import { buildDocumentPDFBytes, extractText } from 'pdfnative';

const pdf = buildDocumentPDFBytes({
  title: 'Hello',
  blocks: [{ type: 'paragraph', text: 'Hello, world.' }],
});

extractText(pdf)[0].text; // 'Hello, world.' — it parses, too

Prefer a shell? npx pdfnative-cli render -o out.pdf. Driving an agent? npx pdfnative-mcp. Same engine behind all three.

The native family

The engine is the library; the CLI is the trust boundary the engine refuses to be; the MCP server is the same capability, addressable by an agent. Each engine exiles its integrations — filesystem sinks, process I/O, the MCP SDK — into satellite repos, so the core can stay dependency-free.

Package Latest Engine What it does
pdfnative npm — 0 deps. PDF engine — ISO 32000-1, PDF/A-1b→3b, PDF/X-4, PAdES B-B→B-LTA signing, 27 scripts shaped with GSUB/GPOS, no fontkit
pdfnative-cli npm pdfnative range 21 commands — render, sign, verify, LTV, inspect, compare, batch
pdfnative-mcp npm pdfnative range 28 MCP tools, no network path by default
pdfnative-react npm pdfnative peer range JSX → PDF. No DOM, no headless browser, no SaaS round-trip
zipnative npm — 0 deps. ZIP engine — own DEFLATE/INFLATE, Zip64, random access without extracting, incremental edits without recompression
zipnative-cli npm zipnative range 15 commands — zip-slip, symlink, bomb and duplicate guards on by default
zipnative-mcp npm zipnative range 13 MCP tools, sandboxed to one directory, verified by realpath
pkinative npm — 0 deps. PKI engine — X.509 and ASN.1 DER, RFC 5280 paths with CRL/OCSP, CMS and RFC 3161 timestamps, PKCS#8/#12; every signature through Web Crypto
pkinative-cli npm pkinative range 18 commands — inspect, verify, issue, sign; every one of the engine's 294 exports, offline, --json for agents

Engine is the range each satellite declares on its engine, read live from npm. A caret range takes every engine minor without a satellite release, so an engine can lead its satellites — and the Latest column shows by how much.

Engines carry zero runtime dependencies. The CLIs add none beyond their engine; the MCP servers add the MCP SDK and zod, pdfnative-react adds react-reconciler — and nothing else. For scale, measured 2026-07-28: pdfkit ships 6 runtime dependencies, pdf-lib 4, jsPDF 3, pdfmake 3.

One API surface. Node.js ≥ 22 and browsers run in CI; Deno, Bun and Workers follow from the architecture but are not yet a tested matrix. MIT, all of it.

The doctrine

Four rules, inherited down the family. Each is enforced by code somewhere — and the row says where.

Rule Enforced by
Zero runtime dependencies The engines declare no dependencies at all. In pdfnative and pkinative, tree-shaking probes bundle isolated imports against byte budgets and forbidden-marker assertions — importing a color parser must not drag in an AES S-box.
Secure-by-default parsing Every loop over untrusted bytes consults a named limit, the riskiest tagged with its CWE. pkinative's ASN.1 decoder is iterative: depth is a bounded number, never the call stack.
Determinism as a product feature Byte-identical output, buffered or streaming, serial or parallel — and across runtimes under deterministic: true. Changing those bytes is a semver-major.
No I/O in the engine No filesystem, no network, no process, no eval. The only node: touch is an optional zlib fast path that the pure-TypeScript codec replaces when it is absent. In pkinative an architecture test decides this from the syntax tree and fails the build.

How this is built

Every repo carries AGENTS.md, .github/AGENT_RULES.md and a machine-readable .github/ai-governance.json. They assign exactly one role to the agent and one to the human:

You act as a draftsman, never as an autonomous submitter.

"human_in_the_loop": {
  "role_of_agent": "draftsman",
  "gate": "A human MUST explicitly review, sign off on, and trigger any …"
}

In full, the gate ends: the agent's authority ends at producing a local draft plus a compliance report. That is the policy. This is the enforcement: in every repo but zipnative-cli and zipnative-mcp, a PreToolUse hook denies npm publish, gh pr create, gh release and any git push — including when the command is buried inside $( ), sh -c or a node -e payload. Its rule table has its own test file. Weaken the governance and the build fails.

agent drafts
   ↓
local reproduction
   ↓
zero-dependency check
   ↓
draft + compliance report
   ↓
human reviews & signs off   ← the gate
   ↓
human submits. never the agent.

And the line the agent must repeat before every submission, straight out of ai-governance.json: anything submitted is published under the human's GitHub identity, and the human shares responsibility for the content.

Agents draft. Gates decide. A human signs.

Verified, not claimed

Every line below is a CI job against an outside corpus — not a badge someone drew.

  • veraPDF — PDF/A conformance across the pdfnative repos, including negative canaries the validator is required to reject. Blocking in three of them; still advisory in pdfnative-mcp.
  • ISO/IEC 21320-1 — clause by clause, fail-closed, on Linux and Windows. No external ZIP validator exists — JHOVE has no ZIP module — so this one is the project's own; the corpus and its negative canaries are what make it a test rather than a claim.
  • x509-limbo, Wycheproof + NIST PKITS — 30 361 certificates, 1 530 ECDSA vectors, the 405 PKITS certificates and 224 signed S/MIME messages, pinned by commit and SHA-256, differentially cross-checked against OpenSSL. The 565 refusals sit in a reviewed baseline, frozen with their codes for the whole 1.x line.
  • npm Trusted Publishing (OIDC) + SLSA provenance — on all nine published packages. No long-lived token exists anywhere.

Every engine, and every satellite but zipnative-cli and zipnative-mcp, holds the numbers its docs quote to a single source of truth — an ecosystem.json or its own data registries — and a verify:docs step breaks the build when the prose disagrees.

Latest release

pkinative-cli 1.0 shipped on 2026-10-08 — the engine's command line, with pkinative as its one runtime dependency. 18 commands reach every one of pkinative's 294 exports, and a test proves it; nothing is fetched from the network, and --json gives scripts and agents a stable contract: the report on stdout, one envelope on stderr, pkinative's codes verbatim.

pkinative 1.0 shipped on 2026-10-04 — a zero-dependency PKI engine, extracted from pdfnative's signature stack and destined to return to it.

It reads certificates strictly — DER by default, BER only on request — and verifies them the whole way: signatures, RFC 5280 §6 paths, CRL and OCSP revocation, host names and key purposes. It reads, builds and verifies CMS SignedData and RFC 3161 timestamps, opens PKCS#8 and PKCS#12 into non-extractable Web Crypto keys, and creates certificates and certification requests. Secret-dependent cryptography is never written in TypeScript here: Web Crypto does every signature.

The 1.x promise has three legs — the export surface, the error codes, and the decision surface: which certificate is refused, with which code. Each is a frozen snapshot that a build rule holds, not a sentence. Stated plainly: there is no external security audit at 1.0; what stands in its place is listed in its SECURITY.md.

Next: pkinative-mcp, pinning pkinative ^1.0.0 — CLI first, then MCP, the order both elders followed — and then pdfnative's own signature stack moving onto pkinative.

Of the TypeScript PKI libraries measured on 2026-09-19, only pkinative and micro509 ship zero dependencies — asn1js 3, pkijs 6, @peculiar/x509 11.


MIT · pdfnative.dev · zipnative.dev · pkinative.dev · Sponsor on GitHub

Pinned Loading

  1. pdfnative pdfnative Public

    Lightweight, zero-dependency PDF engine in pure TypeScript. Fast on-device generation (no Chromium). Create, parse, sign, and modify ISO 32000-1 docs. Supports PDF/A, PDF/UA, BiDi, and font shaping.

    TypeScript 15 1

  2. zipnative zipnative Public

    Zero-dependency ZIP engine in pure TypeScript — random-access reads, secure-by-default extraction (zip-slip & zip-bomb guards), deterministic reproducible archives, streaming, in-place incremental …

    TypeScript

  3. pkinative pkinative Public

    Zero-dependency PKI toolkit in pure TypeScript. Parse and verify X.509 certificates (RFC 5280 paths, CRL, OCSP, host names), CMS signatures and RFC 3161 timestamps; open PKCS#8/#12 keys; create cer…

    TypeScript

  4. pdfnative-cli pdfnative-cli Public

    High-performance, zero-dependency CLI for the pdfnative engine. Automate JSON-to-PDF/A rendering, digital signatures (RSA/ECDSA), and compliance inspection within CI/CD pipelines via shell-pipe wor…

    TypeScript

  5. pdfnative-mcp pdfnative-mcp Public

    Official Model Context Protocol (MCP) server for local-first PDF/A generation. Empowers AI agents (Claude, Cursor, Zed) to securely create, sign (PAdES), verify, and transform documents with barcod…

    TypeScript 2

  6. zipnative-cli zipnative-cli Public

    Agent-grade ZIP CLI on the zipnative engine — create deterministic, reproducible archives, list and inspect without extracting, extract with zip-slip / zip-bomb / symlink guards, verify, stream, mo…

    TypeScript