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
20 changes: 20 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,27 @@ jobs:
- run: pnpm example
- run: pnpm test:demo
- run: pnpm test:comparison
- run: pnpm test:workflows
- run: pnpm test:package
workflow-pdf:
name: PDF extraction and lookup
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444
with:
node-version: 24
package-manager-cache: false
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0
with:
python-version: '3.14'
- run: npm install -g pnpm@11.25.0
- run: pnpm install --frozen-lockfile --ignore-scripts
- run: pnpm build
- run: pnpm test:workflows
- run: python -m pip install -r examples/workflows/requirements-pdf.txt
- run: python examples/workflows/pdf.py --check
browsers:
name: Chromium / Firefox / WebKit
runs-on: ubuntu-latest
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## Unreleased

- Add a local PDF/phone lookup experiment comparing existing identifiers, a simple
alias and RefMint. Record 54 synthetic cases, input lengths and logical lookup calls;
include costs that favor existing identifiers and aliases. No human-performance claim.
- Verify identifiers extracted from a deterministic sample PDF against the same lookup
model; test the browser form, permitted scope and wrong-record cases.
- Clarify when RefMint is unnecessary, alpha/API versus frozen v1 format commitments,
and why checksums cannot replace authorization or regulated identifiers.
- Runtime APIs and wire formats are unchanged. No new npm runtime dependencies.

## 0.1.0-alpha.2 — 2026-10-27

Second prerelease, including the existing-ID API, compatibility checks, comparison form and measured optimizations. Available as a GitHub package archive and on npm under the `alpha` tag. The npm publication updates installation/release documentation only; runtime, declarations, package metadata and measured evidence match the original GitHub archive byte for byte.
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,20 @@ The image is generated from [recorded evidence](docs/evidence.json). See [measur

## Try it

**Would an extra reference help?** Try the new current-source
[PDF/phone lookup experiment](docs/workflows.md): existing number or hostname,
five-character alias, and RefMint on the same records. The sample fleet code is
49 printed characters versus an 8-character hostname; the invoice code is 21 versus
a 15-character invoice number. The checksum rejects selected typos, but no human-entry
advantage has been established. [When RefMint is unnecessary](docs/when-not-to-use.md).

Install the current alpha from npm:

```sh
npm install refmint@alpha
```

To pin this release, use `npm install --save-exact refmint@0.1.0-alpha.2`. The `alpha` tag is intentional: this is a prerelease, and no stable `latest` release is advertised. Registry installation does not require an npm account or the URL-dependency flag below.
To pin this release, use `npm install --save-exact refmint@0.1.0-alpha.2`. This is a prerelease even when the `latest` registry tag resolves to it; npm availability does not make its API stable. Registry installation does not require an npm account or the URL-dependency flag below.

The GitHub package archive remains available as an alternative:

Expand Down
43 changes: 43 additions & 0 deletions docs/when-not-to-use.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# When RefMint is unnecessary

Start with the identifier and search workflow users already know.

| Situation | Prefer |
| --- | --- |
| Existing invoice/quote numbers or hostnames are short and lookup works | Keep them; a second identifier creates training and maintenance cost |
| People paste a link, scan a QR code, or never type an identifier | Improve that flow first; no manual-entry benefit has been demonstrated |
| A five-character local alias handles the support case | A small unique alias mapping, if its lifecycle is manageable |
| You need compact general-purpose random IDs | An established ID generator; checksum overhead may not help |
| A regulated number or a string with leading zeros must be preserved | Keep its exact string; the uint64 codec is not a numbering-system replacement |
| Your dependency policy excludes prereleases | Wait or use a supported stable alternative |
| You need a credential, signature, unguessable access link or encrypted ID | An appropriate security design; never a public checksum |

RefMint is worth evaluating when people repeatedly enter a **public** reference and
the application benefits from consistent namespaces, display forms and diagnostics.
There is no demonstrated human-entry speedup, reduced support cost, or confirmed need
in Octofleet/Invoice Builder from the current synthetic demo.

## npm availability and compatibility are separate

The package is **alpha**, even when `npm install refmint` resolves to it. Registry tags
are distribution pointers; they do not certify stability. Pin the reviewed version and
check your organization's policy before adopting it.

The existing-ID **v1 wire contract is already frozen**: canonical encoding and accepted
presentation forms must remain compatible; incompatible formats require a new version
and reader. That commitment is described in [format-v1.md](format-v1.md) and checked
with frozen vectors. It does not promise a stable alpha API, operational support, or
that an application can safely remove old readers. Keep version/kind/namespace choices
with your schema and test migrations. npm publication alone adds no compatibility promise.

For the separate random-reference API, persist the configured prefix and payload length;
do not recalculate them from the current row count. See [SPEC.md](../SPEC.md).

## A checksum is not authorization

Anyone can generate or recompute a checksum, including for another valid existing ID.
The codec is reversible and does not hide sequential IDs. Always enforce authorization
on the server and confirm the intended record before sensitive actions. Error detection
does not prove the sender, document authenticity, record existence or permission.

[Evaluate all three routes](workflows.md) before adding another reference to a product.
72 changes: 72 additions & 0 deletions docs/workflow-results.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Local lookup results

Synthetic fixtures, recorded 28 October 2026. No production support cases or human timing data.

| Domain | Route | Canonical characters | Printed characters |
| --- | --- | ---: | ---: |
| fleet | existing | 8 | 8 |
| fleet | alias | 5 | 5 |
| fleet | refmint | 41 | 49 |
| invoice | existing | 15 | 15 |
| invoice | alias | 5 | 5 |
| invoice | refmint | 19 | 21 |

| Domain | Route | Case | Result | Logical lookups | Different record from intended? |
| --- | --- | --- | --- | ---: | --- |
| fleet | existing | Exact | found | 1 | no |
| fleet | existing | Printed / pasted | found | 1 | no |
| fleet | existing | One-symbol change | found | 1 | yes |
| fleet | existing | Truncated | ambiguous | 1 | no |
| fleet | existing | Wrong record type | not_found | 1 | no |
| fleet | existing | Valid but unknown | not_found | 1 | no |
| fleet | existing | Outside allowed scope | not_found | 1 | no |
| fleet | existing | Another valid code | found | 1 | yes |
| fleet | existing | Empty | invalid (input) | 0 | no |
| fleet | alias | Exact | found | 1 | no |
| fleet | alias | Printed / pasted | found | 1 | no |
| fleet | alias | One-symbol change | found | 1 | yes |
| fleet | alias | Truncated | not_found | 1 | no |
| fleet | alias | Wrong record type | not_found | 1 | no |
| fleet | alias | Valid but unknown | not_found | 1 | no |
| fleet | alias | Outside allowed scope | not_found | 1 | no |
| fleet | alias | Another valid code | found | 1 | yes |
| fleet | alias | Empty | invalid (input) | 0 | no |
| fleet | refmint | Exact | found | 1 | no |
| fleet | refmint | Printed / pasted | found | 1 | no |
| fleet | refmint | One-symbol change | invalid (checksum) | 0 | no |
| fleet | refmint | Truncated | invalid (checksum) | 0 | no |
| fleet | refmint | Wrong record type | invalid (prefix) | 0 | no |
| fleet | refmint | Valid but unknown | not_found | 1 | no |
| fleet | refmint | Outside allowed scope | not_found | 1 | no |
| fleet | refmint | Another valid code | found | 1 | yes |
| fleet | refmint | Empty | invalid (input) | 0 | no |
| invoice | existing | Exact | found | 1 | no |
| invoice | existing | Printed / pasted | found | 1 | no |
| invoice | existing | One-symbol change | found | 1 | yes |
| invoice | existing | Truncated | not_found | 1 | no |
| invoice | existing | Wrong record type | not_found | 1 | no |
| invoice | existing | Valid but unknown | not_found | 1 | no |
| invoice | existing | Outside allowed scope | not_found | 1 | no |
| invoice | existing | Another valid code | found | 1 | yes |
| invoice | existing | Empty | invalid (input) | 0 | no |
| invoice | alias | Exact | found | 1 | no |
| invoice | alias | Printed / pasted | found | 1 | no |
| invoice | alias | One-symbol change | found | 1 | yes |
| invoice | alias | Truncated | not_found | 1 | no |
| invoice | alias | Wrong record type | not_found | 1 | no |
| invoice | alias | Valid but unknown | not_found | 1 | no |
| invoice | alias | Outside allowed scope | not_found | 1 | no |
| invoice | alias | Another valid code | found | 1 | yes |
| invoice | alias | Empty | invalid (input) | 0 | no |
| invoice | refmint | Exact | found | 1 | no |
| invoice | refmint | Printed / pasted | found | 1 | no |
| invoice | refmint | One-symbol change | invalid (checksum) | 0 | no |
| invoice | refmint | Truncated | invalid (checksum) | 0 | no |
| invoice | refmint | Wrong record type | invalid (prefix) | 0 | no |
| invoice | refmint | Valid but unknown | not_found | 1 | no |
| invoice | refmint | Outside allowed scope | not_found | 1 | no |
| invoice | refmint | Another valid code | found | 1 | yes |
| invoice | refmint | Empty | invalid (input) | 0 | no |

A valid code for another record still passes its checksum. Scope restrictions apply equally to all routes.
The one-symbol cases were selected to expose a failure mode, not sampled to estimate its frequency.
Loading
Loading