Skip to content

Publish readiness, CLI exit codes and audit hardening - #6

Merged
0xNyk merged 3 commits into
mainfrom
chore/publish-readiness
Nov 3, 2026
Merged

0xNyk merged 3 commits into
mainfrom
chore/publish-readiness

Conversation

@0xNyk

@0xNyk 0xNyk commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Stacked on #5. Retarget to main once #5 merges. This addresses the non-blocking findings from the 2026-11-03 audit. No change to SPEC v1 hashing or serialization; test-vectors/v1.json is byte-identical.

Publish readiness

  • publishConfig sets access: public and provenance: true.
  • prepublishOnly fails if LICENSE or NOTICE is missing or differs from the root copies, or if dist is missing. The cross-platform pack-files.mjs replaces cp and rm -rf.
  • New publish.yml: workflow_dispatch (a dry run by default) plus release published. It checks that the tag matches the version, and runs with id-token: write and actions pinned by SHA. The npm token is referenced only as secrets.NPM_TOKEN, which the owner adds. Publishing is manual and owner-only.
  • CI gets a new package job: it packs on Node 24, then installs the tarball and runs --help and an example on Node 20 and on Node 24. engines is >=20, which the tarball run checks.

CLI

  • Exit codes are documented per reason in the package README:
    • 0: verified.
    • 1: data mismatch. bad_signature and tx_mismatch move here, because the signed bytes contradict the RPC.
    • 2: usage or environment error, or a check that was not performed. This includes the new signature_unverified, returned when --verify-signature was asked for but no Ed25519 is available.
  • --signer must decode to 32 bytes of base58. --max-signatures must be a plain positive integer.
  • New CHARTRUNNER_RPC_URL environment variable; --rpc overrides it.

SDK

  • canonicalJson rejects array, null, primitive and class-instance rows. SPEC §3 already requires a flat object.
  • Equivocation scan: if the RPC does not report memo, the result is scan_incomplete, instead of up to 100k serial getTransaction calls.
  • New rpc.test.ts cases:
    • a v0 transaction with loaded addresses;
    • an operator that co-signs but is not the fee payer (refused);
    • a user-kind signer;
    • plain-string account keys.

Docs

  • Proof mode binds count only as an upper bound (SPEC §8 and both READMEs).
  • Live figures are dated.
  • @types/node is pinned.

Checks: 246 tests (up from 233), build, lint, typecheck, vectors:check, examples, and the public-repo leak scan all pass.

0xNyk added 3 commits November 3, 2026 19:58
…cans

Package and CI
- publishConfig (public, provenance); prepack/build use a cross-platform node
  script; prepublishOnly fails without LICENSE, NOTICE or a built dist/
- publish.yml: manual (release published or dispatch, dry run by default),
  pinned actions, id-token for provenance, NPM_TOKEN by name only
- engines.node >=20 (global WebCrypto + fetch); the bin falls back to dist/
  on a Node without type stripping; @types/node pinned exactly
- CI: package job packs the tarball, installs it in an empty project and runs
  the bin and the offline example on Node 20 and 24

CLI
- --verify-signature without Ed25519 exits 2 (signature_unverified)
- --signer must be a base58 32-byte address (usage error, exit 2)
- --max-signatures takes plain decimal digits only
- CHARTRUNNER_RPC_URL when --rpc is absent; --rpc wins
- bad_signature and tx_mismatch are mismatches (exit 1); table in README

SDK
- canonicalJson rejects arrays, null, primitives and class instances as rows
- checkEquivocation: a signature entry without a reported memo ends the scan
  as scan_incomplete instead of reading every transaction serially

Docs: live figures marked as of their date; SPEC 8 and READMEs say proof
mode binds count only as an upper bound. No hash, serialization or vector
changed.
…ent; plain rows from another realm

publish.yml: a real publish (release or a dispatch with dry_run off) refuses unless the release
targets main or the dispatch runs on main; the job runs in the 'npm' environment so the owner can
require a reviewer. canonicalJson accepts an object literal from another realm (vm, iframe), whose
Object.prototype differs; class instances are still refused. Review follow-ups on #6.
@0xNyk
0xNyk changed the base branch from feat/battle-kind to main November 3, 2026 19:14
@0xNyk
0xNyk merged commit 951b375 into main Nov 3, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant