Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,33 @@ jobs:

- name: Check dependency hygiene
run: bun run check:deps

rust-validation:
name: Cross-validate vectors against the Rust reference
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

# The runner image ships a stable Rust toolchain.
- name: Validate against bc-tags (default build)
working-directory: tests/rust-validation
run: cargo run --release --locked -- ../vectors/vectors.json

- name: Validate the bignum recipe (num-bigint build)
working-directory: tests/rust-validation
run: cargo run --release --locked --features bignum -- ../vectors/vectors.json

# The identifier check must bite: the swapped-label fixture fails with
# exactly two identifier mismatches.
- name: Reject the swapped-identifier fixture
working-directory: tests/rust-validation
run: |
set +e
output=$(cargo run --release --locked --quiet -- fixtures/swapped-identifiers.json 2>&1 >/dev/null)
status=$?
set -e
printf '%s\n' "$output"
test "$status" -eq 1
test "$(printf '%s\n' "$output" | grep -c '^MISMATCH ident ')" -eq 2
34 changes: 31 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
# Changelog

## 1.0.0-beta.2
## 1.0.0-beta.3 - 2026-09-14

Requires `@blockchaincommons/dcbor` ^1.0.0-beta.3. The registry produced by
`registerTags` matches `bc_tags::register_tags_in` probe for probe.

### Changed

- **Tags 2 and 3 are unnamed in the default registry**, as in the reference's
default build: dcbor names the bignum tags only on request
(`registerStandardTags(store, { bignum: true })`), and `bc-tags` depends on
dcbor without its `num-bigint` feature, so `registerTags` now produces the
same registry as `bc_tags::register_tags_in`. The registry vector and golden
snapshot are regenerated and the differential pins the flip. For the
`num-bigint` registry call `registerStandardTags(store, { bignum: true })`
**before** `registerTags(store)`, the reference's registration order.
- **The IANA tag numbers are written in this package.** dcbor 1.0.0-beta.3 no
longer exports numeric `TAG_URI`, `TAG_UUID` and `TAG_ENCODED_CBOR`, so 32,
37 and 24 are literals here, as `bc-tags` writes them. Values and names are
unchanged.
- `registerTags` registers `ALL_TAGS` directly (dcbor's `registerAll` takes
any iterable); no copy is made.

### Fixed

- Documentation: a conflicting registration throws dcbor's `CborError` (code
`Custom`) with the reference's panic text, not a bare `Error`;
`registerTags` registers the `date` tag only, not the bignum tags.

## 1.0.0-beta.2 - 2026-09-12

Documents the registry behavior and updates repository tooling. Public tag values,
names, and registration logic are unchanged.
Expand All @@ -11,6 +39,6 @@ names, and registration logic are unchanged.
TypeScript always registers tags 2 and 3; Rust requires `num-bigint`.
The Rust harness enables that feature and matches 75 tags and 80 probes.

## 1.0.0-beta.1
## 1.0.0-beta.1 - 2026-09-09

Initial beta implementation.
Initial beta implementation.
26 changes: 12 additions & 14 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
- [ ] The tags are now canonical `@blockchaincommons/dcbor` `Tag` values, not
`dcbor-compat` ones. If you build tagged CBOR with them, use dcbor.
- [ ] `registerTagsIn(store)` → `registerTags(store)`; `registerTags()` is unchanged.
- [ ] `registerTags` no longer names tags 2 and 3 (the reference's default
build leaves them unnamed). If you relied on `positive-bignum` /
`bignum(…)` output, call `registerStandardTags(store, { bignum: true })`
before `registerTags(store)`.
- [ ] `SEED_V1`, `EC_KEY_V1`, `SSKR_SHARE_V1` and the other `*_V1` tags moved
under `LEGACY_TAGS` (`LEGACY_TAGS.SEED_V1`).
- [ ] Import `getGlobalTagsStore` and `TagsStore` from
Expand Down Expand Up @@ -56,10 +60,14 @@ They are still in `ALL_TAGS` and still registered by `registerTags()`.

## 4. Registration semantics

`registerTags(store)` calls dcbor's `registerStandardTags(store)` (date and
bignum tags with their summarizers) and then registers `ALL_TAGS`. It is
idempotent. Registering a value that is already present under a *different*
name throws, as dcbor's store does.
`registerTags(store)` calls dcbor's `registerStandardTags(store)` (the `date`
tag and its summarizer; tags 2 and 3 stay unnamed, as in the reference's
default build) and then registers `ALL_TAGS`. It is idempotent, and a name
already registered under another value moves to this package's value, as the
reference's `insert_all` does. Registering a value that is already present
under a *different* name throws dcbor's `CborError` (code `Custom`) with the
reference's panic text; tags registered earlier in the call stay registered
and the rejected entry is unchanged.

## 5. Identity and immutability

Expand All @@ -69,13 +77,3 @@ Tags compare by value: `TAG_ENVELOPE === Tag.from(200, "envelope")` is
Every constant is frozen. `(TAG_ENVELOPE as any).name = "x"` used to
succeed in `@bcts/tags` and silently rename the wire tag for every later
`registerTags()`; it now throws a `TypeError`.

## 6. Node and TypeScript floors

Node **22.12** and TypeScript **5.7**. The IIFE / global-script build is
gone; use the ESM or CJS entry.

## 7. What did not change

- Every tag value and name, and the registration order.
- `registerTags()` with no argument.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ registerTags();
getGlobalTagsStore().nameForValue(TAG_ENVELOPE.value); // "envelope"

// Or into a store of your own. A value already registered under a
// different name throws (dcbor's Error); the same name is a no-op.
// different name throws dcbor's CborError (code Custom); the same name is a no-op.
const store = new TagsStore();
registerTags(store);

Expand All @@ -56,13 +56,13 @@ Runnable examples live in the [`examples/`](https://github.com/BlockchainCommons

### Version History

- **1.0.0-beta.3 (September 14, 2026)** - Requires `@blockchaincommons/dcbor` ^1.0.0-beta.3, so tags 2 and 3 are unnamed; conflicts documented as dcbor's `CborError`.
- **1.0.0-beta.2 (September 12, 2026)** - Documents the bignum-registration difference from Rust builds without `num-bigint`.
- **1.0.0-beta.1 (September 9, 2026)** - Initial beta implementation.

### Roadmap

- Continued testing and auditing on the path from beta to a stable **1.0.0** release.
- Continued parity with the Rust reference implementation as it evolves (see [`RUST_DIVERGENCES.md`](./RUST_DIVERGENCES.md)).

### Dependencies

Expand Down
70 changes: 0 additions & 70 deletions RUST_DIVERGENCES.md

This file was deleted.

19 changes: 13 additions & 6 deletions api/index.d.mts
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,22 @@ export declare const ALL_TAGS: readonly Tag[];
//#region src/register.d.ts
/**
* Register dcbor's standard tags and every tag in {@link ALL_TAGS} into
* `store` (default: the global store).
* `store` (default: the global store), in the reference's order: `date`
* (tag 1) with its summarizer, then the 75 tags of this package.
*
* Idempotent: the store compares names, so a value already registered under
* the same name is a no-op, which is what makes repeated calls safe.
* Idempotent: a value already registered under the same name is a no-op,
* and a name already registered under another value moves to this
* package's value, as the reference's `insert_all` does. Tags 2 and 3 stay
* unnamed, as in the reference's default build; for the `num-bigint`
* registry call `registerStandardTags(store, { bignum: true })` before this
* function.
*
* @param store - The store to register into; defaults to dcbor's global store.
* @throws {Error} dcbor's store throws a bare `Error` when a value is
* already registered under a *different* name
* (`Attempt to register tag: 200 'foo' with different name: 'envelope'`).
* @throws {CborError} Code `Custom` (dcbor's store) when a value is already
* registered under a different name; the message is the reference's panic
* text, e.g. `Attempt to register tag: 200 'foo' with different name: 'envelope'`.
* Tags registered earlier in the same call stay registered, and the rejected
* entry is unchanged.
*/
export declare function registerTags(store?: TagsStore): void;
//#endregion
Expand Down
Loading