Files
js/tsup.config.ts
zeekay c86c75efb0 feat(cap): real capability lifecycle — issue/attenuate/verify/verifyChain/revoke
Port the ZAP capability layer to TypeScript at src/cap.ts, the byte-for-byte
peer of github.com/zap-proto/go/cap (SPEC.md §2.3/§3/§4 + capabilities_kinds.md).
Exported at @zap-proto/zap/cap; the universal root stays browser-safe.

- Cap view/builder over the zero-copy runtime for capabilities.zap (v1.1, 3408B
  Sig footer); Capability/Caveat/Revocation codec vendored in, as Go vendors
  capabilities_zap.go into package cap.
- canonicalBytes: Capability[0..164) || canonical(Caveats) — byte-identical to
  Go's signed scope; heap-indirection excluded so it is identical across runtimes.
- issue + attenuate: mint-time delegation gate (parent PermAttenuate or
  Kind==Delegate), monotonic perm narrowing, holder→issuer linkage, expiry
  shrink-only. Signs canonicalBytes.
- verify + verifyChain: all SPEC §2.3 invariants (monotonic perms, holder
  linkage, target invariance, root zero-Parent, delegation gate) + FAIL-CLOSED
  scheme dispatch (reject 0x00/unknown; never downgrade; never return ok on an
  unverified sig).
- capId = SHA-256(canonicalBytes || Sig) (spec-corrected from BLAKE3).
- Schemes: Ed25519 MANDATORY via node:crypto (synchronous, RFC 8032, raw seed
  framed into PKCS8/SPKI). ML-DSA-65 / hybrid / secp256k1 fail-closed unless a
  schemeVerify hook is wired — the JS runtime fabricates no PQ verify.
- Zero npm runtime deps preserved (node:crypto is stdlib); synchronous API
  matching Go exactly, no async contagion through the auth primitive.

Cross-language KAT (interop proof): test/cap_go_kat.hex is a Go-signed cap over
a fixed Ed25519 seed (32x0x42); test/cap_kat.test.ts decodes it, asserts JS
canonicalBytes + capId match Go's, verifies the Go Ed25519 sig in JS -> true,
and a tampered variant -> false. Re-issuing the same inputs+seed in JS
reproduces Go's exact CapID (1b809edc...), signature, and full wire bytes.

Tests: 110 pass (66 pre-existing + 44 new mirroring Go's 34 cap tests:
happy/attenuate-refuses/chain-rejects/fail-closed/revocation + KAT + custom
Signer). Bump @zap-proto/zap 1.4.2 -> 1.5.0.
2026-06-21 01:15:57 -07:00

32 lines
1.1 KiB
TypeScript

// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
import { defineConfig } from "tsup";
// Two output shapes from one source tree:
//
// 1. The library entries (index, node, cap) — ESM `.js` with .d.ts, matching
// the package `exports` map. `index` is universal (browser-safe); `node`
// adds the Node-only TCP transport; `cap` is the capability runtime
// (reaches node:crypto for synchronous Ed25519 + SHA-256).
// 2. The `zapgen` CLI — a single ESM `.mjs` bundle under dist/bin with its
// `#!/usr/bin/env node` shebang preserved, referenced by package `bin`.
export default defineConfig([
{
entry: ["src/index.ts", "src/node.ts", "src/cap.ts"],
format: "esm",
dts: true,
clean: true,
sourcemap: false,
},
{
entry: { "bin/zapgen": "src/bin/zapgen.ts" },
format: "esm",
outExtension: () => ({ js: ".mjs" }),
dts: false,
clean: false,
sourcemap: false,
// tsup preserves a leading shebang from the entry file automatically.
},
]);