From 71a338b816c6e58b276f3d27de4da73724b4afa7 Mon Sep 17 00:00:00 2001 From: Yangjunjie Lin Date: Sun, 13 Sep 2026 13:11:48 +0100 Subject: [PATCH 1/2] release: record verified v2.1.0 publication and finalize current guides --- CHANGELOG.md | 1 + CONTRIBUTING.md | 2 +- README.md | 4 +- SECURITY.md | 7 +- docs/README.md | 8 +- docs/maintenance.md | 8 +- docs/migration/v1-to-v2.md | 10 +- docs/native/android-getting-started.md | 12 +- docs/native/architecture.md | 4 +- docs/native/compatibility.md | 8 +- docs/native/cross-platform-wrapper-plan.md | 4 +- docs/native/ios-getting-started.md | 10 +- docs/platform-compatibility.md | 2 +- docs/releases/v2.1.0.md | 10 +- docs/sdk/api-stability.md | 8 +- docs/sdk/public-api.md | 8 +- docs/sdk/usage.md | 4 +- docs/sdk/worker-deployment.md | 2 +- .../v2.1.0/v2.1.0-publication-record.json | 464 ++++++++++++++++++ 19 files changed, 529 insertions(+), 47 deletions(-) create mode 100644 release/stable/v2.1.0/v2.1.0-publication-record.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 355bf0c..ca74d94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes follow semantic versioning. - Added explicit privacy modes and a default-disabled demo, with a same-origin rate/size/time-limited backend. - Existing barcode decoding remains local and independent of network analysis. Published 2.0.0 and 2.0.1 artifacts and historical evidence are unchanged. - Added source-bound independent npm and Native artifact rebuilds, detached CI provenance for the new package's 2FA-protected first publication, and immutable versioned qualification records. Actual publication is verified separately from qualification. +- Completed all 11 npm 2.1.0 publications with exact downloaded-byte and cryptographic provenance verification. Preserved the initial Registry provenance rejection and its independently rebuilt, additive correction without changing the signed tag or frozen artifacts; appended the actual publication record. ## 2.0.1 — Scanner lifecycle and runtime hardening diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 60845af..db5ea43 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -Thank you for helping maintain Scanly's focused, local-first barcode scanning SDK scope. The public v2.0.1 format set is QR Code, Data Matrix, PDF417, Code 128, EAN-13, EAN-8, UPC-A, and UPC-E. +Thank you for helping maintain Scanly's focused, local-first barcode scanning SDK scope. The public v2.1.0 format set is QR Code, Data Matrix, PDF417, Code 128, EAN-13, EAN-8, UPC-A, and UPC-E. ## Setup diff --git a/README.md b/README.md index ef3817e..3a94257 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Privacy-first, local-only barcode scanning SDK for Web, Node.js, React, iOS, and ## Install -The 2.1.0 release line is software-qualified. Registry publication is finalized separately through the signed release workflow; see the [release notes](docs/releases/v2.1.0.md) and versioned release records below. +All 11 public SDK packages are published at 2.1.0 with verified provenance and exact frozen artifact hashes. See the [release notes](docs/releases/v2.1.0.md) and [immutable publication record](release/stable/v2.1.0/v2.1.0-publication-record.json). Choose the package for your runtime. Browser, Node, and React packages already include their required Scanly workspace dependencies. @@ -181,6 +181,8 @@ Detailed Alpha, Beta, and RC development evidence is preserved in [development h - [v2.1.0 release notes](docs/releases/v2.1.0.md) - [v2.1.0 qualification manifest](release/stable/v2.1.0/v2.1.0-manifest.json) +- [v2.1.0 publication record](release/stable/v2.1.0/v2.1.0-publication-record.json) +- [v2.1.0 additive provenance correction](release/stable/v2.1.0/v2.1.0-provenance-recovery.json) - [v2.1.0 checksums](release/stable/v2.1.0/checksums.sha256) - [v2.1.0 SBOM](release/stable/v2.1.0/sbom.cdx.json) - [v2.0.1 release notes](docs/releases/v2.0.1.md) diff --git a/SECURITY.md b/SECURITY.md index 770da26..58dcffa 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,15 +2,16 @@ ## Supported versions -v2.0.1 is the current Stable release. +v2.1.0 is the current Stable release. | Version | Security support | | --- | --- | +| 2.1.x | Supported; current Stable line | | 2.0.x | Supported | | 1.x | Best-effort security fixes only | | Alpha, Beta, and RC builds | Unsupported historical development builds | -Security fixes normally target the latest supported patch in the 2.0 line. Support does not expand the public API or physical-device qualification claims of a released version. +Security fixes normally target the latest supported patch in the 2.1 line, with applicable fixes considered for supported 2.0.x releases. Support does not expand the public API or physical-device qualification claims of a released version. ## Reporting a vulnerability @@ -34,4 +35,6 @@ Dependency audit results are recorded rather than hidden. Breaking forced upgrad The shipped SDK has no analytics, remote tracking, image upload, remote logging, or diagnostic endpoint. Image pixels and decoded content must not be logged by default. Any future diagnostics must be opt-in and redact both classes of data. +The separate `@scanly/url-safety` module is disabled by default. Network analysis may share only an already-decoded HTTP(S) URL after explicit opt-in; scanner images and frames remain local. Remote inspection is server-only and SSRF-controlled. Provider secrets stay on the server, sensitive query values are redacted from diagnostics and LLM evidence, and LLM output cannot override authoritative threat intelligence. See [URL Safety security and privacy boundaries](docs/url-safety.md). + See the [threat model](docs/security/threat-model.md) and [secure integration guide](docs/security/secure-integration.md). diff --git a/docs/README.md b/docs/README.md index ad6ff4f..00127cf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,6 +10,7 @@ ## API and capabilities - [Public API](sdk/public-api.md) +- [Opt-in Link Intelligence / URL Safety](url-safety.md) - [API stability](sdk/api-stability.md) - [Error catalog](sdk/error-catalog.md) - [Cross-platform contract](sdk/cross-platform-contract.md) @@ -36,10 +37,15 @@ ## Migration, benchmarking, and release integrity -- [Migrate from v1 to v2.0.1](migration/v1-to-v2.md) +- [Migrate from v1 to v2.1.0](migration/v1-to-v2.md) - [Post-release Physical Device Validation](physical-device-validation.md) - [Benchmark methodology](benchmarking/methodology.md) - [Benchmark provenance](benchmarking/provenance.md) +- [v2.1.0 release notes](releases/v2.1.0.md) +- [v2.1.0 qualification manifest](../release/stable/v2.1.0/v2.1.0-manifest.json) +- [v2.1.0 publication record](../release/stable/v2.1.0/v2.1.0-publication-record.json) +- [v2.1.0 checksums](../release/stable/v2.1.0/checksums.sha256) +- [v2.1.0 SBOM](../release/stable/v2.1.0/sbom.cdx.json) - [v2.0.1 release notes](releases/v2.0.1.md) - [v2.0.1 qualification manifest](../release/stable/v2.0.1/v2.0.1-manifest.json) - [v2.0.1 checksums](../release/stable/v2.0.1/checksums.sha256) diff --git a/docs/maintenance.md b/docs/maintenance.md index baa6762..3088bfc 100644 --- a/docs/maintenance.md +++ b/docs/maintenance.md @@ -1,6 +1,6 @@ # Maintenance policy -Scanly v2.0.1 is the current Stable SDK line. Maintenance prioritizes security, correctness, compatibility, performance, physical qualification, bug fixes, patch releases, and carefully scoped minor releases. New work must preserve the local-only privacy boundary and the public eight-format contract. +Scanly v2.1.0 is the current Stable SDK line. Maintenance prioritizes security, correctness, compatibility, performance, physical qualification, bug fixes, patch releases, and carefully scoped minor releases. New work must preserve local barcode decoding, the separate opt-in URL Intelligence boundary, and the public eight-format contract. ## Supported toolchain @@ -18,12 +18,12 @@ Scanly v2.0.1 is the current Stable SDK line. Maintenance prioritizes security, - Release qualification is recorded in versioned evidence committed through `develop`; only `main` and `develop` are retained as long-lived branches. - Immutable tags and evidence preserve released history; never move or rebuild a published tag. -For a normal v2.0.1 bug fix: +For a normal bug fix to the 2.1 line: ```text develop -> fix branch -> PR to develop -> versioned qualification evidence -> PR from develop to main --> signed v2.0.1 tag -> GitHub Release -> npm / Native publication +-> signed next-patch tag -> GitHub Release -> npm / Native publication -> synchronize main back into develop ``` @@ -61,7 +61,7 @@ Dependabot opens small npm and GitHub Actions groups. Merge security patches pro ## Physical qualification -Automated browser, simulator, and emulator coverage is not physical-device qualification. The v2.0.0 physical validation program remains `POST_RELEASE_VALIDATION_PENDING` under Issue #13; v2.0.1 does not claim physical PASS or reinterpret those zero evidence counts. +Automated browser, simulator, and emulator coverage is not physical-device qualification. The v2.0.0 physical validation program remains `POST_RELEASE_VALIDATION_PENDING` under Issue #13; neither v2.0.1 nor v2.1.0 claims physical PASS or reinterprets those zero evidence counts. When that program completes, do not modify v2.0.0 binaries or the qualification/publication records. Add `release/stable/v2.0.0-physical-qualification-record.json` containing the released artifact hashes, real device matrix, 30/60-minute soak evidence, and false-positive gate. The release evidence chain is Qualification → Publication → Physical Qualification. diff --git a/docs/migration/v1-to-v2.md b/docs/migration/v1-to-v2.md index cbed8db..6ee6833 100644 --- a/docs/migration/v1-to-v2.md +++ b/docs/migration/v1-to-v2.md @@ -1,6 +1,6 @@ -# Migrating from Scanly v1 to v2.0.1 +# Migrating from Scanly v1 to v2.1.0 -Scanly v2.0.1 is the current Stable SDK. Migrate by selecting the runtime package instead of importing repository-internal v1 modules. +Scanly v2.1.0 is the current Stable SDK. Migrate by selecting the runtime package instead of importing repository-internal v1 modules. ## Install a public package @@ -40,7 +40,7 @@ Camera composition uses `BrowserCameraSource` and the ScannerSession runtime. Ca ## Formats and scenarios -v2.0.1 supports QR Code, Data Matrix, PDF417, Code 128, EAN-13, EAN-8, UPC-A, and UPC-E. The default remains QR-only for compatibility; opt into additional formats explicitly or use a multi-format built-in scenario. +v2.1.0 supports QR Code, Data Matrix, PDF417, Code 128, EAN-13, EAN-8, UPC-A, and UPC-E. The default remains QR-only for compatibility; opt into additional formats explicitly or use a multi-format built-in scenario. ```ts const router = createNodeCaptureRouter({ @@ -52,7 +52,7 @@ The lower-level `decodePixelBuffer` adapter requires a caller-supplied engine ex ## Native availability -- iOS 13+: `ScanlySDK` source package under `native/ios` at tag `v2.0.1`. -- Android API 24+: `scanly-sdk-2.0.1.aar` from the v2.0.1 GitHub Release for `arm64-v8a` and `x86_64`. +- iOS 13+: `ScanlySDK` source package under `native/ios` at tag `v2.1.0`. +- Android API 24+: `scanly-sdk-2.1.0.aar` from the v2.1.0 GitHub Release for `arm64-v8a` and `x86_64`. See the [iOS](../native/ios-getting-started.md) and [Android](../native/android-getting-started.md) guides. Physical-device qualification remains pending under Issue #13 and is not implied by automated simulator/emulator coverage. diff --git a/docs/native/android-getting-started.md b/docs/native/android-getting-started.md index b7f8475..dcb2484 100644 --- a/docs/native/android-getting-started.md +++ b/docs/native/android-getting-started.md @@ -1,20 +1,20 @@ -# Scanly SDK v2.0.1 for Android +# Scanly SDK v2.1.0 for Android -Scanly SDK v2.0.1 is distributed as `scanly-sdk-2.0.1.aar` on the [v2.0.1 GitHub Release](https://github.com/Yangjunjie-Lin/Scanly/releases/tag/v2.0.1). Maven Central is **not published and not required for v2.0.1**; do not use `implementation("io.scanly:scanly-sdk:2.0.1")`. +Scanly SDK v2.1.0 is distributed as `scanly-sdk-2.1.0.aar` on the [v2.1.0 GitHub Release](https://github.com/Yangjunjie-Lin/Scanly/releases/tag/v2.1.0). Maven Central is **not published and not required for v2.1.0**; do not use `implementation("io.scanly:scanly-sdk:2.1.0")`. ## Install the AAR -1. Download `scanly-sdk-2.0.1.aar` from the GitHub Release. -2. Place it at `app/libs/scanly-sdk-2.0.1.aar`. +1. Download `scanly-sdk-2.1.0.aar` from the GitHub Release. +2. Place it at `app/libs/scanly-sdk-2.1.0.aar`. 3. Add the file dependency: ```kotlin dependencies { - implementation(files("libs/scanly-sdk-2.0.1.aar")) + implementation(files("libs/scanly-sdk-2.1.0.aar")) } ``` -Verify the AAR against `release/stable/v2.0.1/checksums.sha256` or the checksum attached to the GitHub Release before integration. +Verify the AAR against `release/stable/v2.1.0/checksums.sha256` or the checksum attached to the GitHub Release before integration. ## CameraX quick start diff --git a/docs/native/architecture.md b/docs/native/architecture.md index 47cb231..64773a4 100644 --- a/docs/native/architecture.md +++ b/docs/native/architecture.md @@ -1,6 +1,6 @@ # Native mobile architecture -Scanly SDK v2.0.1 uses one shared ZXing-C++ decode implementation behind a +Scanly SDK v2.1.0 uses one shared ZXing-C++ decode implementation behind a stable C ABI. The web runtime continues to use the pinned ZXing-C++ WASM adapter; Swift and Kotlin do not select independent decoder libraries. @@ -29,7 +29,7 @@ and typed failures. Complex C++ types never cross the ABI. ## Session strategy -v2.0.1 uses the platform-wrapper strategy for frame scheduling, lifecycle, +v2.1.0 uses the platform-wrapper strategy for frame scheduling, lifecycle, latest-frame admission, repeat suppression, and stale-result discard. The portable C++ boundary remains decode-only. Cross-platform session behavior is constrained by deterministic contracts and may be converged further in a future minor release; diff --git a/docs/native/compatibility.md b/docs/native/compatibility.md index 3076ed7..803f383 100644 --- a/docs/native/compatibility.md +++ b/docs/native/compatibility.md @@ -1,21 +1,21 @@ # Native compatibility -Scanly Native SDK v2.0.1 is a Stable software release. Automated build and fixture coverage is verified; post-release physical qualification remains pending. +Scanly Native SDK v2.1.0 is a Stable software release. Automated build and fixture coverage is verified; post-release physical qualification remains pending. | Target | Minimum / ABI | Distribution | Automated verification | Physical status | | --- | --- | --- | --- | --- | -| iOS | iOS 13; Swift tools 5.9; current supported Xcode capable of Swift 5.9 packages | SPM source package at `native/ios` in tag `v2.0.1` | Swift build/test, simulator, unsigned device compilation | `POST_RELEASE_VALIDATION_PENDING` | +| iOS | iOS 13; Swift tools 5.9; current supported Xcode capable of Swift 5.9 packages | SPM source package at `native/ios` in tag `v2.1.0` | Swift build/test, simulator, unsigned device compilation | `POST_RELEASE_VALIDATION_PENDING` | | Android | API 24; Java 17 | GitHub Release AAR | AAR, unit/lint, x86_64 emulator fixture smoke | `POST_RELEASE_VALIDATION_PENDING` | | Android ABI | `arm64-v8a`, `x86_64` | AAR native libraries | both `.so` entries required | `POST_RELEASE_VALIDATION_PENDING` | | `armeabi-v7a` | unsupported | not shipped | omission verified | `unsupported` | Supported public formats are QR Code, Data Matrix, PDF417, Code 128, EAN-13, EAN-8, UPC-A, and UPC-E. Shared native fixtures cover all eight formats plus one two-symbol QR Code + Code 128 image. -Distribution boundaries for v2.0.1: +Distribution boundaries for v2.1.0: - Swift Package Manager source package: shipped under the immutable Git tag; use exact-tag checkout plus the local `native/ios` package path because the repository root has no Package.swift. - Android AAR: shipped through the GitHub Release. - CocoaPods and Maven Central: not published. -- App Store, Google Play, React Native, and Flutter: not SDK distribution channels for v2.0.1. +- App Store, Google Play, React Native, and Flutter: not SDK distribution channels for v2.1.0. Simulator or emulator PASS never implies physical iPhone or Android PASS. Any unavailable toolchain lane reports `NOT_RUN` or `NOT_TESTED`, not PASS. Physical validation continues under [Issue #13](https://github.com/Yangjunjie-Lin/Scanly/issues/13). diff --git a/docs/native/cross-platform-wrapper-plan.md b/docs/native/cross-platform-wrapper-plan.md index 641deda..d834df8 100644 --- a/docs/native/cross-platform-wrapper-plan.md +++ b/docs/native/cross-platform-wrapper-plan.md @@ -1,6 +1,6 @@ # React Native and Flutter wrapper plan -Scanly v2.0.1 does not publish React Native or Flutter adapters. The Native APIs are +Scanly v2.1.0 does not publish React Native or Flutter adapters. The Native APIs are kept wrapper-friendly by using immutable value results, typed platform errors, explicit decoder/session disposal, bounded multiple-result arrays, and the stable C ABI beneath both platforms. @@ -16,4 +16,4 @@ with destroy and must copy borrowed result views before freeing the result set. Before either publication: freeze native API snapshots, run the unified shared fixture vectors, add wrapper lifecycle/memory soak, and complete physical -validation. No wrapper publication is part of v2.0.1. +validation. No wrapper publication is part of v2.1.0. diff --git a/docs/native/ios-getting-started.md b/docs/native/ios-getting-started.md index 83e5ce6..4ce4852 100644 --- a/docs/native/ios-getting-started.md +++ b/docs/native/ios-getting-started.md @@ -1,13 +1,13 @@ -# ScanlySDK v2.0.1 for iOS +# ScanlySDK v2.1.0 for iOS -ScanlySDK v2.0.1 is a Stable Swift Package Manager source package for iOS 13+. CocoaPods is not a v2.0.1 distribution channel. +ScanlySDK v2.1.0 is a Stable Swift Package Manager source package for iOS 13+. CocoaPods is not a v2.1.0 distribution channel. ## Install from the immutable tag -The package manifest lives at `native/ios/Package.swift`, not the repository root. Swift Package Manager cannot resolve this repository as a remote versioned dependency using the root Git URL. For v2.0.1, check out the immutable tag and add the subdirectory as a local package: +The package manifest lives at `native/ios/Package.swift`, not the repository root. Swift Package Manager cannot resolve this repository as a remote versioned dependency using the root Git URL. For v2.1.0, check out the immutable tag and add the subdirectory as a local package: ```bash -git clone --branch v2.0.1 --depth 1 https://github.com/Yangjunjie-Lin/Scanly.git +git clone --branch v2.1.0 --depth 1 https://github.com/Yangjunjie-Lin/Scanly.git ``` In Xcode choose **File → Add Package Dependencies → Add Local** and select `Scanly/native/ios`, then add the `ScanlySDK` product to the app target. A Package.swift-based host can use a local path: @@ -18,7 +18,7 @@ dependencies: [ ] ``` -The checked-out `v2.0.1` tag is the version pin. Standard remote root-URL resolution such as `.package(url: ..., from: "2.0.1")` requires a root package manifest and is not supported by this repository layout. +The checked-out `v2.1.0` tag is the version pin. Standard remote root-URL resolution such as `.package(url: ..., from: "2.1.0")` requires a root package manifest and is not supported by this repository layout. ## Decode diff --git a/docs/platform-compatibility.md b/docs/platform-compatibility.md index f46aae7..aa6c363 100644 --- a/docs/platform-compatibility.md +++ b/docs/platform-compatibility.md @@ -1,6 +1,6 @@ # Platform compatibility matrix -Scanly v2.0.1 is the current Stable software line. The physical matrix below remains the post-release v2.0.0 qualification program tracked by Issue #13, not a publication gate and not a physical PASS claim for v2.0.1. +Scanly v2.1.0 is the current Stable software line. The physical matrix below remains the post-release v2.0.0 qualification program tracked by Issue #13, not a publication gate and not a physical PASS claim for v2.1.0. Allowed runtime statuses are `verified`, `partially-verified`, `unsupported`, `unavailable`, and `not-tested`. `verified` means automated evidence unless a row explicitly identifies an admitted physical session. diff --git a/docs/releases/v2.1.0.md b/docs/releases/v2.1.0.md index 86dcd2d..51c4bf4 100644 --- a/docs/releases/v2.1.0.md +++ b/docs/releases/v2.1.0.md @@ -1,6 +1,6 @@ # Scanly SDK v2.1.0 -Status: release-qualified candidate. Registry publication and post-publication verification are tracked separately; this document is not a publication record. +Status: published Stable release. All 11 npm packages have `latest=2.1.0`, exact downloaded artifact bytes, and cryptographically verified Registry provenance. See the [immutable publication record](../../release/stable/v2.1.0/v2.1.0-publication-record.json) for the signed tag, GitHub Release, artifact, provenance and production identities. Physical validation remains pending under Issue #13. ## New: Link Intelligence @@ -22,11 +22,11 @@ Remote URL inspection uses SSRF controls. LLM output is advisory. Threat-intelli ## Compatibility -Existing v2 scanner APIs remain compatible. URL intelligence is an independent, default-disabled module, not part of decoder scheduling. Native version metadata advances with the release line; Native build/signing/artifact qualification must be repeated before publication. Existing Native evidence is not rebranded as 2.1.0 evidence. +Existing v2 scanner APIs remain compatible. URL intelligence is an independent, default-disabled module, not part of decoder scheduling. Native build/signing/artifact qualification was repeated for this release, including two independent exact-source builds; existing Native evidence was not rebranded as 2.1.0 evidence. ## Qualification -All software, browser, API/package, security, Native, SBOM/license, artifact/reproducibility, signing and publication gates must pass on the final release identity. Feature-branch test results are development evidence only. See [URL safety architecture](../url-safety.md) and the candidate qualification record when available. Issue #13 remains independent. +Software, browser, API/package, security, Native, SBOM/license, artifact/reproducibility, signing and publication checks passed. The [frozen qualification manifest](../../release/stable/v2.1.0/v2.1.0-manifest.json) binds the exact product source and its evidence; the separate publication record binds the actual published identities. Feature-branch test results remain development evidence only. See [URL safety architecture](../url-safety.md). Issue #13 remains independent. The Stable manifest generator refuses new-version generation without `STABLE_QUALIFICATION_RECORD`: an exact-source `scanly-release-qualification-1` record with version, sourceCommit, sourceTree and content-addressed PASS evidence (`path`, `sha256`, `sourceCommit`) for software, apiAbi, security, sbom, licenses, native, npmReproducibility, signing, publicationCredentials and deployment. Fresh public signing metadata and two independent npm build/hash maps are required. Legacy 2.0.x GO/credential/reproducibility claims cannot be inherited. @@ -39,3 +39,7 @@ The first Registry submission was rejected with E422: although the original Sigs [The additive recovery record](../../release/stable/v2.1.0/v2.1.0-provenance-recovery.json) preserves this failure and binds replacement proofs to two fresh independent GitHub-hosted builds. All 11 rebuilt tarballs match the frozen release byte-for-byte; all 22 replacement bundles are signature-, identity-, and subject-verified. The workflow source is now first and the exact product source remains a separate explicit dependency. The signed tag, original manifest, original provenance, and frozen artifacts remain unchanged. Use `npm run stable:bootstrap -- --qualified-provenance-recovery` only with this verified additive record. The command rechecks the live successful workflow, both independent signed URL Safety bundles, exact artifact hashes, original qualification, and owner authentication before requesting publication. A completed build or local signature check is not proof of Registry acceptance; post-publication checks remain mandatory. + +Registry acceptance of the corrected proof and all 11 downloaded packages was subsequently verified. The URL Safety attestation identifies build run `34754673547`; the existing ten packages identify OIDC publication run `34726283486`. The initial post-publish 404 was a Registry propagation delay and resolved without republishing. New-package Trusted Publisher setup is a separate maintenance authorization, not the source of this first-publication provenance. + +The publication record lists the 27 GitHub Release assets and their actual SHA-256 digests. The standalone `THIRD_PARTY_NOTICES` asset uses CRLF checkout line endings (its text matches the signed tag); the other 26 asset digests match exact signed-tag file bytes. No asset was replaced during this verification. diff --git a/docs/sdk/api-stability.md b/docs/sdk/api-stability.md index 0750101..9b305d5 100644 --- a/docs/sdk/api-stability.md +++ b/docs/sdk/api-stability.md @@ -1,14 +1,14 @@ # Public API stability -Scanly SDK v2.0.1 classifies public APIs as Stable, Experimental, or Internal. `ScannerSession`, +Scanly SDK v2.1.0 classifies public APIs as Stable, Experimental, or Internal. `ScannerSession`, `BarcodeTracker`, and `BatchScanSession` are Stable. The DPM profile is Experimental and opt-in. Recovery implementations, worker internals, and camera implementation details are Internal. CaptureRouter remains the authoritative execution boundary. Public declarations and export maps for core, -browser, node, react, scenario schema, and engine packages are hashed in +browser, node, react, parsers, URL Safety, scenario schema, and engine packages are hashed in `api-snapshots/public-api.json`. -CI rebuilds declarations and fails on an unexpected snapshot change. Intentional +CI rebuilds declarations and fails on an unexpected snapshot change. Intentional public API changes require semantic-version classification, declaration review, migration notes, and an explicit snapshot update. Native ESM import and installed-tarball checks remain separate gates. The C ABI snapshot additionally checks exported @@ -17,4 +17,4 @@ symbols, enum values, and normalized struct layouts. Internal attempt plans, coordinate matrices, benchmark fixture results, and camera `InternalTrack` state are not promoted to application contracts. Registries remain extension APIs with explicit register/replace/dispose lifecycle -rules. Breaking changes after v2.0.0 require a new major release and qualification cycle. v2.0.1 changes only exported version-literal values; it adds no public API member or state variant. +rules. Breaking changes after v2.0.0 require a new major release and qualification cycle. v2.1.0 adds the backward-compatible, optional `@scanly/url-safety` package and its Node-only `/server` entry; existing scanner APIs remain compatible. URL Safety has its own analysis status and never adds AI latency or failure to the barcode decoding state machine. See [Link Intelligence](../url-safety.md). diff --git a/docs/sdk/public-api.md b/docs/sdk/public-api.md index d40f7d5..d879d1e 100644 --- a/docs/sdk/public-api.md +++ b/docs/sdk/public-api.md @@ -2,10 +2,12 @@ ## Version policy -- SDK package version: `2.0.1` (Stable patch release; physical validation pending) +- SDK package version: `2.1.0` (Stable minor release; physical validation pending) ## Camera platform surface +The optional `@scanly/url-safety` package provides local analysis, a deterministic risk engine, client/cache/controller APIs, and a separate Node-only `/server` analyzer with provider adapters and safe fetching. It is not part of the scanner's default decode pipeline. See the [URL Safety API and integration guide](../url-safety.md). + `@scanly/browser` exports `CameraConstraintPolicy`, `DeviceDiagnostics`, `CameraRecoveryPolicy`, and `CameraRecoveryController`. Constraint negotiation requests ideal facing mode, resolution, and frame rate, then removes optional preferences through a bounded fallback sequence. An explicit device ID remains exact unless the caller deliberately chooses ideal matching. `ScannerSession.getDeviceDiagnostics()` returns camera API reports without filling missing fields. Camera lifecycle events invalidate generations so results from an old camera, orientation, resolution, or background interval cannot become new public state. Recovery is bounded; exhausted recovery produces `camera_recovery_failed`. @@ -85,7 +87,7 @@ Historical real-time development evidence uses 20 scenario-specific Ground Truth `npm run api:snapshot` and `npm run api:diff` validate the package-root declarations. Their presence here does not assert that a particular GitHub PR head has passed the Public API workflow. -The v2.0.1 Stable APIs follow semantic versioning. Supported deprecated APIs receive at least one minor-release migration window unless a security fix requires removal. +The v2.1.0 Stable APIs follow semantic versioning. Supported deprecated APIs receive at least one minor-release migration window unless a security fix requires removal. ## Authoritative execution API @@ -128,6 +130,6 @@ When `output.includeAttempts` is enabled, `attempts` contains a bounded, payload ## Supported capability versus vocabulary -Scanly SDK v2.0.1 publicly supports `qr_code`, `data_matrix`, `pdf417`, `code_128`, `ean_13`, `ean_8`, `upc_a`, and `upc_e`. Deferred ZXing formats are not in the public union. jsQR and ZXing-JS report QR-only capabilities; the pinned ZXing-C++ WASM engine reports the eight verified mappings. A scenario requesting a format with no registered engine returns `unsupported_format` during compilation. +Scanly SDK v2.1.0 publicly supports `qr_code`, `data_matrix`, `pdf417`, `code_128`, `ean_13`, `ean_8`, `upc_a`, and `upc_e`. Deferred ZXing formats are not in the public union. jsQR and ZXing-JS report QR-only capabilities; the pinned ZXing-C++ WASM engine reports the eight verified mappings. A scenario requesting a format with no registered engine returns `unsupported_format` during compilation. `FormatSelection` accepts a non-empty list, normalizes duplicates, rejects deferred/unknown formats, and is propagated through Router, Worker, Node, and native decode options. QR-only remains the default when no explicit selection or non-QR scenario is supplied. diff --git a/docs/sdk/usage.md b/docs/sdk/usage.md index b2b4f14..5040344 100644 --- a/docs/sdk/usage.md +++ b/docs/sdk/usage.md @@ -1,6 +1,6 @@ -# Scanly SDK v2.0.1 usage +# Scanly SDK v2.1.0 usage -Scanly SDK v2.0.1 packages are published Stable packages. Browser, Node, and React packages declare all required Scanly dependencies; install only the public runtime package your application uses. +Scanly SDK v2.1.0 packages are published Stable packages. Browser, Node, and React packages declare all required Scanly dependencies; install only the public runtime package your application uses. ## Browser diff --git a/docs/sdk/worker-deployment.md b/docs/sdk/worker-deployment.md index 9dbabb5..b56455b 100644 --- a/docs/sdk/worker-deployment.md +++ b/docs/sdk/worker-deployment.md @@ -1,6 +1,6 @@ # Worker and WASM deployment -`@scanly/browser` v2.0.1 creates a module Worker with a relative ESM asset URL. The package emits `dist/worker/decode-worker.js`; bundlers must copy or chunk the Worker and the packaged ZXing-C++ WASM asset into the application deployment. +`@scanly/browser` v2.1.0 creates a module Worker with a relative ESM asset URL. The package emits `dist/worker/decode-worker.js`; bundlers must copy or chunk the Worker and the packaged ZXing-C++ WASM asset into the application deployment. The default Browser composition is jsQR → lazy ZXing-C++ WASM → ZXing-JS. Worker ownership is persistent across scans and releases when the session is disposed. Terminating a Worker rejects pending work, prevents stale delivery, and releases its WASM realm; cancellation during synchronous native execution suppresses late delivery rather than preempting native code. diff --git a/release/stable/v2.1.0/v2.1.0-publication-record.json b/release/stable/v2.1.0/v2.1.0-publication-record.json new file mode 100644 index 0000000..7f5f7aa --- /dev/null +++ b/release/stable/v2.1.0/v2.1.0-publication-record.json @@ -0,0 +1,464 @@ +{ + "schemaVersion": "scanly-stable-publication-record-1", + "version": "2.1.0", + "qualificationManifest": { + "path": "release/stable/v2.1.0/v2.1.0-manifest.json", + "sha256": "89faaff164bafde1033264380f5d19b7c1c168f97d4fc4120a4f4c695686e142" + }, + "gitTag": { + "name": "v2.1.0", + "object": "18874fffe7380190ac36d01128ed69f8c6e0dd69", + "target": "d825d32051514a69f07e545e5a52ad6a73cffef7", + "objectType": "tag", + "signing": { + "status": "GITHUB_VERIFIED", + "verified": true, + "reason": "valid", + "verifiedAt": "2026-09-12T23:45:28Z" + } + }, + "githubRelease": { + "id": 387738256, + "tag": "v2.1.0", + "name": "Scanly SDK v2.1.0 — Link Intelligence", + "publishedAt": "2026-09-12T23:46:22Z", + "url": "https://github.com/Yangjunjie-Lin/Scanly/releases/tag/v2.1.0", + "draft": false, + "prerelease": false, + "assetsVerified": [ + { + "id": 560161821, + "name": "artifact-manifest.json", + "size": 10239, + "digest": "sha256:9b7b07cc8d23950ffb0c6b26b4c10f706f42a6338c2cc27dfe228f762badddc4" + }, + { + "id": 560161823, + "name": "checksums.sha256", + "size": 1611, + "digest": "sha256:b13da82604a1aacc247e38247bf3c7987b5ddf2760c82402ba5a0d175595a83b" + }, + { + "id": 560161826, + "name": "license-inventory.json", + "size": 79377, + "digest": "sha256:929a90ce66b7605fdb09ddd6aabbc2780c8a9aeb97867df030517234d6fd00ff" + }, + { + "id": 560161852, + "name": "Package.swift", + "size": 1180, + "digest": "sha256:24d04f5d3a67c55aee95af7b4bf158f359a0c4b4da3f37b7df173269bd9af66f" + }, + { + "id": 560161822, + "name": "physical-validation-status.json", + "size": 1101, + "digest": "sha256:c7dc34a4f7517e83a5c120700898e8ebbb90fa49464c19415205144a633f99f3" + }, + { + "id": 560161832, + "name": "publication-credentials.json", + "size": 4005, + "digest": "sha256:6e1b1df97fc4fa822ecc7182840ddcf3c910b315d61204d50c9bd1b70d60ba2d" + }, + { + "id": 560161839, + "name": "qualification-input.json", + "size": 15611, + "digest": "sha256:a42ec5c90457b5f14290ac585e083bbb63e74f540110b05771b90a1bcc8272d6" + }, + { + "id": 560161834, + "name": "release-policy.json", + "size": 890, + "digest": "sha256:a0599ed33282bd6361cf0bd979369c3b553fe7a2cd7f3c8b09df61e172bbb49d" + }, + { + "id": 560161830, + "name": "reproducibility.json", + "size": 6886, + "digest": "sha256:21e10a04433ba57c6d1396bc13126e75cc29c2d7d1b1f21f1e2562468738b2a3" + }, + { + "id": 560161820, + "name": "sbom.cdx.json", + "size": 122332, + "digest": "sha256:2b204af3904f6994eb4c69535cbdda4e79cb320f89dc09b798e87dfc0bd99697" + }, + { + "id": 560161862, + "name": "scanly-benchmark-2.1.0.tgz", + "size": 12489, + "digest": "sha256:468b1cf37bf229029651fa1e6d6ec63414902578ea1f34b1f8632704ee47e9dd" + }, + { + "id": 560161864, + "name": "scanly-browser-2.1.0.tgz", + "size": 112845, + "digest": "sha256:c173f88dab2a0402ee549c9e609868c2b50145a8096ecc3c0c668a2823b92727" + }, + { + "id": 560161865, + "name": "scanly-core-2.1.0.tgz", + "size": 133351, + "digest": "sha256:7a529c1c940ace1d961bd1df668f668623bcbac1527827579433efffeb10e416" + }, + { + "id": 560161851, + "name": "scanly-core.h", + "size": 8005, + "digest": "sha256:82dee124d9b88e8ee2c9ea6727a83a3a9e08fb6b70ca753c404928d70624d07a" + }, + { + "id": 560161866, + "name": "scanly-engine-jsqr-2.1.0.tgz", + "size": 2737, + "digest": "sha256:b530dcb7949290f068fa3dd3805c0ee23b26d4554cc920f058f1c6c6f3afc68b" + }, + { + "id": 560161869, + "name": "scanly-engine-zxing-cpp-wasm-2.1.0.tgz", + "size": 472873, + "digest": "sha256:5215d8e09ff67ea07cececae51d34a975ae0396723ab235c627081568b1b796c" + }, + { + "id": 560161875, + "name": "scanly-engine-zxing-js-2.1.0.tgz", + "size": 3188, + "digest": "sha256:420c12ac6a7170c004cee7ce25af9e69f56165b1d50e31ebb1acf4eb03b2eecf" + }, + { + "id": 560161879, + "name": "scanly-node-2.1.0.tgz", + "size": 4163, + "digest": "sha256:13207d6afba9038cf721bb9462ff096aedaa658ed22596c10f5529eb08fc3573" + }, + { + "id": 560161878, + "name": "scanly-parsers-2.1.0.tgz", + "size": 5415, + "digest": "sha256:2d71b9713d1b8d084b8c9bdeb0ffbe079b3df54a16488e50dabe857c374cb868" + }, + { + "id": 560161882, + "name": "scanly-react-2.1.0.tgz", + "size": 2873, + "digest": "sha256:e709ec6f963a91f593a55efcda65e5cf524774154496a1011d8474bb7ab9b8ff" + }, + { + "id": 560161885, + "name": "scanly-scenario-schema-2.1.0.tgz", + "size": 10376, + "digest": "sha256:b55e951e1fcd5e129200beab60ee057dee23d4694409df75d007c0953a7e90b1" + }, + { + "id": 560161848, + "name": "scanly-sdk-2.1.0.aar", + "size": 1221160, + "digest": "sha256:44297a5a8b89762a68ccdde61cf107661c8dc7e2b6eb1117f534ce1c67c5098b" + }, + { + "id": 560161891, + "name": "scanly-url-safety-2.1.0.tgz", + "size": 35468, + "digest": "sha256:72bbd5974b2a0b0c2c1ded6098c249084df0fbffe50a937ef96e68902b914a87" + }, + { + "id": 560161831, + "name": "signing-manifest.json", + "size": 3631, + "digest": "sha256:dc435518ff3ce80ecabb6ff6780df7a63648bdadcf3903aafadc3f2393d81987" + }, + { + "id": 560161858, + "name": "THIRD_PARTY_NOTICES", + "size": 968, + "digest": "sha256:d6150ff4b3ae92eb261e61f958f718c13933cdbb3887f4f3b25c06d2fd18c9e8" + }, + { + "id": 560161847, + "name": "v2.1.0-manifest.json", + "size": 5055, + "digest": "sha256:89faaff164bafde1033264380f5d19b7c1c168f97d4fc4120a4f4c695686e142" + }, + { + "id": 560161845, + "name": "v2.1.0-manifest.json.sha256", + "size": 87, + "digest": "sha256:1c91413877b841aab01df952d18f66fd3555adda7bdbcb9184adaa623a7f35bc" + } + ] + }, + "npm": [ + { + "name": "@scanly/benchmark", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-biYsH3DfjMA9MPjQltfPP8+685LV6ef+pKw9pNPQmPlcnwZLanXHOLSemEtBdrHit6DWSOh3vGJhlivL7GDVzw==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fbenchmark@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "5eff3dde07f58f79bddd44c5ca4956701c24c8b76e9b74c57629ec95697f6e6d" + } + }, + { + "name": "@scanly/browser", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-B/+iB6oqgmCbDoCK6SIcPHc1kEBrP+Ed1F5M+YQPwWIXDkLv2o2C73Kzm58zMI6E24GKAjnlY7N8ZtAIx2jPPg==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fbrowser@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "16de0a38bc9669256a060d56b416780ea69876a64f4c39920baf124a8eed46c3" + } + }, + { + "name": "@scanly/core", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-xqgSMSh/jJt6fjBIH2XUl0lncbAD19MRSgvHzewDuqyAG6psCVl4uR139I7EiaAyBVCCic383um3Kl6OrRDivQ==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fcore@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "c0b7183cda254ba4c8ddc80f4920f7a0a8626c3ba7ecb2c69da0bd9b4baf42d1" + } + }, + { + "name": "@scanly/engine-jsqr", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-RVCntWGW4/aG3kHPJ4+fKMmp1XzLbmJ3oP9wfs2EIsJNC6U/Y4UdGBtLCLYgJvxdKzGRxSK8nDjXdFoNWIVNNQ==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fengine-jsqr@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "a51d9e9557e760d922a30ad1b1ece539eaa4b62393c859f873d9802b09cb0e66" + } + }, + { + "name": "@scanly/engine-zxing-cpp-wasm", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-RnNMScwHdrJu3B+mJh94oCim3Q7JenQzzSIQFkiDb666BMVH6QUQNy+n2kEz0DA/hRGM7CsXEAWBoWDLBHu8OQ==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fengine-zxing-cpp-wasm@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "019411aa1013eee30ac277d51a20adc7cb677c0813cea920127e0b7000da41d3" + } + }, + { + "name": "@scanly/engine-zxing-js", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-SafGPd9jF7lmLxvkXZK46pKJ+7UdTTZKXB4+iZ6CEBr9Jo0mqK8ly4pzm9TSE/I+pJnUy1sA6V//bcfPzw0P2g==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fengine-zxing-js@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "a4f53ba31bf0070319889845ed6a56157a602991cbc283b15aeb503ae144cade" + } + }, + { + "name": "@scanly/node", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-iPQEwVnUAKSgPv8AKUrSB23BfbyEslPDP8i3Qrl1vsw11gLp+lKf8MqR3GNRSKgHjVVkiAlzpjxJoqfG0dwzfg==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fnode@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "9a42fc108d733928e8015559ba2385276c540aad58c0cc984237a4cab28d525b" + } + }, + { + "name": "@scanly/parsers", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-GqaDNAfp0mrQKxYPJTeW5z2VF8XJql1tZHlfzMN1kfTRmX9EP/W6NPDAX+o1ybsheyORb0skGO8E8Jmoi1lHVQ==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fparsers@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "f0ced465bed2864781f02e1efb6ed98b2cf565c5c8eee6308da2390c22f3dd8f" + } + }, + { + "name": "@scanly/react", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-jCuO6QiqCXznwTKk+9NnHhJkZl7UzTSn3jzFIYjoAKy9LdjSVc2xD3hraGODENgwGhH7bIxxt+CAvaiHQfCklw==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2freact@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "a11b9765753ff2d6967848a2303ba0f3fe0f930e602a551ccea53229eece6a6d" + } + }, + { + "name": "@scanly/scenario-schema", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-lz/Do4epePj1LmOoL1dM+CnCvdErtbCtf1dmIG6GECadDmmq6Q60X1YPeUqSI/lCIBDVS8ikDoKuMsAnRo7dvg==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2fscenario-schema@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/tags/v2.1.0", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/stable-npm-publish.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34726283486/attempts/1", + "bundleSha256": "e74df0562165462a689a0cf7d56cbc95d09ac6f449b67015923daaa80fc5a29a" + } + }, + { + "name": "@scanly/url-safety", + "version": "2.1.0", + "distTag": "latest", + "distTagVersion": "2.1.0", + "registry": "https://registry.npmjs.org/", + "published": true, + "provenance": "VERIFIED_ATTESTATION_PRESENT", + "integrity": "sha512-Jp4vLtfbtxkmserzPgbfjtF88aCqFrdBJS+ixZo5KViNdUnlqmZV0UK/8bGYA9uK1b85SVYt9NZeulOoTVMcXg==", + "attestationUrl": "https://registry.npmjs.org/-/npm/v1/attestations/@scanly%2furl-safety@2.1.0", + "provenanceIdentity": { + "workflow": { + "ref": "refs/heads/codex/v2.1-npm-provenance-recovery", + "repository": "https://github.com/Yangjunjie-Lin/Scanly", + "path": ".github/workflows/v2.1-artifact-qualification.yml" + }, + "invocationId": "https://github.com/Yangjunjie-Lin/Scanly/actions/runs/34754673547/attempts/1", + "bundleSha256": "9efc900e995d0f33c17625dbc8c5c2c281e50844250c3a0e2da3ff28a6add0d3" + } + } + ], + "spm": { + "tag": "v2.1.0", + "packageSwiftPath": "native/ios/Package.swift", + "artifactPackageSwiftPath": "release/stable/v2.1.0/artifacts/ios/Package.swift", + "artifactPackageSwiftSha256": "24d04f5d3a67c55aee95af7b4bf158f359a0c4b4da3f37b7df173269bd9af66f", + "resolutionStatus": "SOURCE_PACKAGE_MANIFEST_VERIFIED", + "remoteRootVersionResolution": "UNSUPPORTED_REPOSITORY_LAYOUT_USE_EXACT_TAG_CHECKOUT" + }, + "android": { + "distribution": "GITHUB_RELEASE_ASSET", + "releaseAssetId": 560161848, + "filename": "scanly-sdk-2.1.0.aar", + "url": "https://github.com/Yangjunjie-Lin/Scanly/releases/download/v2.1.0/scanly-sdk-2.1.0.aar", + "sha256": "44297a5a8b89762a68ccdde61cf107661c8dc7e2b6eb1117f534ce1c67c5098b", + "size": 1221160, + "mavenCentral": "NOT_PUBLISHED_FOR_V2.1.0" + }, + "web": { + "productionUrl": "https://qr-decoder-theta.vercel.app", + "deploymentUrl": "https://qr-decoder-q1l35nlrl-yangjunjie-lins-projects.vercel.app", + "deploymentId": "dpl_HxbnobbmCZKiHSZpcVkg1PfWbKeF", + "sourceCommit": "a7a9ae241760ee510acb9f0a0cfcd4801963a0c4", + "status": "READY", + "checkedAt": "2026-09-13T12:05:22.285Z", + "qualifiedDeployment": { + "id": "dpl_ZmfWuc5AHqoSn77tsAWFnyeVmb2Y", + "url": "https://qr-decoder-lpc6qiyx6-yangjunjie-lins-projects.vercel.app", + "sourceCommit": "6b017b53a4404f4feab776ac111b0ea9dacf2734" + }, + "qualifiedProductFilesUnchanged": true, + "httpStatus": 200 + }, + "physicalValidation": { + "status": "POST_RELEASE_VALIDATION_PENDING", + "issue": 13, + "physicalMobileDeviceCount": 0, + "physicalLongSessionCount": 0 + }, + "createdAt": "2026-09-13T12:05:22.020Z", + "recordedFromGitState": { + "ref": "codex/v2.1-publication-record", + "commit": "a7a9ae241760ee510acb9f0a0cfcd4801963a0c4", + "tree": "63bf1819ab91f4c6a4e0504b5ca0d5ab5ac2d6f4" + }, + "provenanceRecovery": { + "path": "release/stable/v2.1.0/v2.1.0-provenance-recovery.json", + "sha256": "c9abb705c75594780b36a0c9777f13e7110b8c0e87d40715ea50835a8552bb1b", + "runId": 34754673547 + } +} From 78faa4fe6495e58b23e4a8261312811e83769518 Mon Sep 17 00:00:00 2001 From: Yangjunjie Lin Date: Sun, 13 Sep 2026 13:34:25 +0100 Subject: [PATCH 2/2] docs: align current symbology guide with v2.1.0 --- docs/symbologies.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/symbologies.md b/docs/symbologies.md index 240746b..e5359d2 100644 --- a/docs/symbologies.md +++ b/docs/symbologies.md @@ -1,6 +1,6 @@ # Supported barcode formats -Scanly SDK v2.0.1 exposes an explicit eight-format public contract. The default scenario remains `formats: ["qr_code"]` for compatibility; applications opt into additional formats or select a multi-format scenario. +Scanly SDK v2.1.0 exposes an explicit eight-format public contract. The default scenario remains `formats: ["qr_code"]` for compatibility; applications opt into additional formats or select a multi-format scenario. | Format | Public ID | Class | Default engine support | Notes | | --- | --- | --- | --- | --- | @@ -21,7 +21,7 @@ const router = createNodeCaptureRouter({ }); ``` -Deferred formats—including Micro QR, rMQR, Aztec, Micro PDF417, DotCode, MaxiCode, GS1 DataBar/Composite, postal codes, Codabar, Code 39, Code 93, and ITF—are not part of the v2.0.x public union. Upstream ZXing support does not make a format public. +Deferred formats—including Micro QR, rMQR, Aztec, Micro PDF417, DotCode, MaxiCode, GS1 DataBar/Composite, postal codes, Codabar, Code 39, Code 93, and ITF—are not part of the v2.1.0 public union. Upstream ZXing support does not make a format public. Direct Part Mark Data Matrix uses the opt-in `dpm-experimental` recovery profile. It is not DPM or industrial certification. Difficult, occluded, low-contrast, or strongly distorted symbols can still fail.