chore(release): bump to 0.8.4
v0.8.3's published binaries could never start the public relay; this release carries that fix, the build guard that keeps a malformed injected hub from shipping again, the control-plane failure classification, and the update-check fallback. The prebuilt op-auth libraries are version-pinned through their signed provenance, so a 0.8.4 build requires 0.8.4 artifacts; the 0.8.3 archives are refused rather than silently linked.
This commit is contained in:
parent
59be2b27f3
commit
4fb4cc0071
82
Cargo.lock
generated
82
Cargo.lock
generated
|
|
@ -3636,7 +3636,7 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-acp"
|
name = "op-acp"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"op-ai",
|
"op-ai",
|
||||||
|
|
@ -3651,11 +3651,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-ai"
|
name = "op-ai"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-ai-skills"
|
name = "op-ai-skills"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"include_dir",
|
"include_dir",
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
|
|
@ -3665,7 +3665,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-auth-bridge"
|
name = "op-auth-bridge"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
|
|
@ -3678,7 +3678,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-chrome-extension-core"
|
name = "op-chrome-extension-core"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
"op-html",
|
"op-html",
|
||||||
|
|
@ -3689,7 +3689,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-cli"
|
name = "op-cli"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
|
|
@ -3707,7 +3707,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-codegen"
|
name = "op-codegen"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
|
|
@ -3721,7 +3721,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab"
|
name = "op-collab"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"blake3",
|
"blake3",
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
|
|
@ -3735,7 +3735,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-host"
|
name = "op-collab-host"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
|
|
@ -3766,7 +3766,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-policy-file"
|
name = "op-collab-policy-file"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"blake3",
|
"blake3",
|
||||||
|
|
@ -3782,7 +3782,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-relay-client"
|
name = "op-collab-relay-client"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"op-collab-relay-protocol",
|
"op-collab-relay-protocol",
|
||||||
|
|
@ -3795,7 +3795,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-relay-control-plane"
|
name = "op-collab-relay-control-plane"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
|
|
@ -3810,7 +3810,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-relay-locator-hsm"
|
name = "op-collab-relay-locator-hsm"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"cryptoki",
|
"cryptoki",
|
||||||
|
|
@ -3828,7 +3828,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-relay-locator-server"
|
name = "op-collab-relay-locator-server"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"base64",
|
"base64",
|
||||||
|
|
@ -3857,7 +3857,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-relay-protocol"
|
name = "op-collab-relay-protocol"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"blake3",
|
"blake3",
|
||||||
|
|
@ -3871,7 +3871,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-relay-server"
|
name = "op-collab-relay-server"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"blake3",
|
"blake3",
|
||||||
|
|
@ -3897,7 +3897,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-smoke"
|
name = "op-collab-smoke"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|
@ -3910,7 +3910,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-collab-transport"
|
name = "op-collab-transport"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
|
|
@ -3933,7 +3933,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-config-store"
|
name = "op-config-store"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
@ -3941,7 +3941,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-design-lint"
|
name = "op-design-lint"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
"op-util",
|
"op-util",
|
||||||
|
|
@ -3951,7 +3951,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-editor-core"
|
name = "op-editor-core"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glam",
|
"glam",
|
||||||
"jian-core",
|
"jian-core",
|
||||||
|
|
@ -3967,7 +3967,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-editor-host-core"
|
name = "op-editor-host-core"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
"op-ai",
|
"op-ai",
|
||||||
|
|
@ -3984,7 +3984,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-editor-ui"
|
name = "op-editor-ui"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"base64",
|
"base64",
|
||||||
|
|
@ -4005,7 +4005,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-figma"
|
name = "op-figma"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"flate2",
|
"flate2",
|
||||||
|
|
@ -4020,7 +4020,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-git"
|
name = "op-git"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"git2",
|
"git2",
|
||||||
"op-config-store",
|
"op-config-store",
|
||||||
|
|
@ -4031,7 +4031,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-host-desktop"
|
name = "op-host-desktop"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_macos",
|
"accesskit_macos",
|
||||||
|
|
@ -4104,7 +4104,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-host-native"
|
name = "op-host-native"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"casement",
|
"casement",
|
||||||
|
|
@ -4137,7 +4137,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-host-services"
|
name = "op-host-services"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"agent",
|
"agent",
|
||||||
"anthropic-agent-sdk",
|
"anthropic-agent-sdk",
|
||||||
|
|
@ -4182,7 +4182,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-host-web"
|
name = "op-host-web"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"base64",
|
"base64",
|
||||||
|
|
@ -4210,7 +4210,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-host-web-server"
|
name = "op-host-web-server"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"op-host-services",
|
"op-host-services",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
@ -4218,7 +4218,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-html"
|
name = "op-html"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
|
|
@ -4233,14 +4233,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-i18n"
|
name = "op-i18n"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"op-html",
|
"op-html",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-mcp"
|
name = "op-mcp"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
"jian-scene",
|
"jian-scene",
|
||||||
|
|
@ -4260,7 +4260,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-opmerge"
|
name = "op-opmerge"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
@ -4269,7 +4269,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-orchestrator"
|
name = "op-orchestrator"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
|
|
@ -4289,7 +4289,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-pen-loader"
|
name = "op-pen-loader"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jian-core",
|
"jian-core",
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
|
|
@ -4305,14 +4305,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-process-io"
|
name = "op-process-io"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-rpc-transport"
|
name = "op-rpc-transport"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
@ -4320,7 +4320,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-smoke"
|
name = "op-smoke"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"agent",
|
"agent",
|
||||||
"futures",
|
"futures",
|
||||||
|
|
@ -4340,11 +4340,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-util"
|
name = "op-util"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-web-sdk"
|
name = "op-web-sdk"
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"jian-ops-schema",
|
"jian-ops-schema",
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ exclude = [
|
||||||
default-members = ["crates/op-host-desktop", "crates/op-cli", "crates/op-host-web-server"]
|
default-members = ["crates/op-host-desktop", "crates/op-cli", "crates/op-host-web-server"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.8.3"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
# 1.87 floor: op-mcp's `script` feature (enabled unconditionally by
|
# 1.87 floor: op-mcp's `script` feature (enabled unconditionally by
|
||||||
# op-host-services + op-orchestrator) depends on rquickjs 0.12, whose
|
# op-host-services + op-orchestrator) depends on rquickjs 0.12, whose
|
||||||
|
|
|
||||||
156
RELEASE_NOTES/v0.8.4.md
Normal file
156
RELEASE_NOTES/v0.8.4.md
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
# OpenPencil v0.8.4 — The Public Relay Actually Works
|
||||||
|
|
||||||
|
`v0.8.4` is a corrective release. `v0.8.3` shipped collaboration end to end, but
|
||||||
|
in the published builds the **public relay could never start**: every attempt —
|
||||||
|
China region or Global, owner or guest — ended with "the public relay is
|
||||||
|
temporarily unavailable." The service was healthy the whole time. The binaries
|
||||||
|
were not.
|
||||||
|
|
||||||
|
The cause was a single space character. This release fixes it, and then fixes
|
||||||
|
the three separate reasons that one character was able to reach users and stay
|
||||||
|
invisible for so long: a build that could not detect it, an error that lied
|
||||||
|
about it, and a diagnostic path that erased it.
|
||||||
|
|
||||||
|
A second, unrelated failure goes with it — the in-app update check reporting
|
||||||
|
"cannot reach the release server, check your network connection" on networks
|
||||||
|
that were working fine.
|
||||||
|
|
||||||
|
## Highlights
|
||||||
|
|
||||||
|
- **Public relay works in published builds.** The hub endpoints baked into the
|
||||||
|
release binaries were malformed; corrected at the source.
|
||||||
|
- **A malformed hub endpoint now fails the build.** It can no longer ship.
|
||||||
|
- **Relay errors tell the truth.** A refused sign-in, a rate-limited hub, an
|
||||||
|
unreachable network and a broken build are four different messages now, not
|
||||||
|
one.
|
||||||
|
- **Update checks survive shared IP addresses.** The probe falls back to the
|
||||||
|
releases Atom feed when GitHub's anonymous API quota is exhausted.
|
||||||
|
|
||||||
|
## The Relay Fix
|
||||||
|
|
||||||
|
### What happened
|
||||||
|
|
||||||
|
The production hub URLs are deliberately absent from the open-source tree. The
|
||||||
|
release pipeline injects them at compile time from repository secrets, and
|
||||||
|
`relay_bootstrap_select.rs` reads them with `option_env!`.
|
||||||
|
|
||||||
|
Both secrets had been saved with a **leading space**:
|
||||||
|
|
||||||
|
```
|
||||||
|
" https://op.zseven.cn/api/v1/collaboration/bootstrap"
|
||||||
|
" https://op.zseven.tech/api/v1/collaboration/bootstrap"
|
||||||
|
```
|
||||||
|
|
||||||
|
`option_env!` bakes the value in exactly as stored, space and all. The runtime
|
||||||
|
endpoint policy is deliberately strict — it rejects any value where
|
||||||
|
`value.trim() != value` — so the injected endpoint parsed as *no usable hub*,
|
||||||
|
and every relay attempt failed before a single packet left the machine.
|
||||||
|
|
||||||
|
Because both secrets carried the space, switching regions changed nothing. And
|
||||||
|
because the bad character is invisible in every log, every dashboard, and every
|
||||||
|
`strings` dump of the binary, nothing pointed at it.
|
||||||
|
|
||||||
|
### Why it shipped
|
||||||
|
|
||||||
|
A guard for exactly this already existed —
|
||||||
|
`injected_bootstrap_urls_pass_the_endpoint_policy_or_stay_absent` — and it
|
||||||
|
passed, vacuously. Repository secrets are not exposed to the CI **test** job, so
|
||||||
|
the assertion took its "no hubs injected, nothing to validate" branch on every
|
||||||
|
run. The **release** job is the one that receives the secrets, and it ran no
|
||||||
|
such assertion.
|
||||||
|
|
||||||
|
The fix moves the check where neither job can miss it: a build script on
|
||||||
|
`op-collab-host` validates the injected endpoints at compile time and fails the
|
||||||
|
build with an actionable message.
|
||||||
|
|
||||||
|
```
|
||||||
|
error: failed to run custom build command for `op-collab-host`
|
||||||
|
OPENPENCIL_BUILD_COLLAB_BOOTSTRAP_URL_CN is not a usable collaboration hub URL
|
||||||
|
(the value has leading or trailing whitespace). Expected exactly
|
||||||
|
`https://<host>/api/v1/collaboration/bootstrap` with no surrounding
|
||||||
|
whitespace; check the repository secret for a stray space or trailing newline.
|
||||||
|
```
|
||||||
|
|
||||||
|
An absent variable stays valid — open-source and fork builds legitimately carry
|
||||||
|
no production hub, and continue to build.
|
||||||
|
|
||||||
|
## Honest Failure Reporting
|
||||||
|
|
||||||
|
The single space was hard to find because the code actively hid it. Three
|
||||||
|
changes fix that, and they outlive this particular bug.
|
||||||
|
|
||||||
|
- **A broken build no longer poses as an outage.** An injected endpoint that
|
||||||
|
fails the policy now reports as *not configured* rather than *temporarily
|
||||||
|
unavailable*. The old copy invited the user to wait for a condition that could
|
||||||
|
never resolve on its own.
|
||||||
|
- **Control-plane failures are classified.** Every call to the relay locator —
|
||||||
|
route publication, pairing-code publication, pairing-code claim — used to end
|
||||||
|
in `map_err(|_| RelayUnavailable)`. An expired collaboration ticket, a
|
||||||
|
rate-limited hub, an unreachable network and a malformed response all reached
|
||||||
|
the user as the same sentence. A refused ticket (HTTP 401/403) is now a
|
||||||
|
sign-in problem, a rate-limited hub (HTTP 429) is now a retry-later problem,
|
||||||
|
and only genuine transport and protocol faults remain "relay unavailable".
|
||||||
|
This also gives `collab.error.rateLimited`, translated in all 15 locales since
|
||||||
|
`v0.8.3`, its first real producer.
|
||||||
|
- **Stage diagnostics, without credentials.** Control-plane failures write one
|
||||||
|
line naming the stage and the failure class. Only the failure enum — which
|
||||||
|
carries no payload — and a `&'static str` variant tag are ever formatted; the
|
||||||
|
error's own `Display` is deliberately never used, so a future payload field
|
||||||
|
cannot leak into a support log. A test enforces that every tag stays a bare
|
||||||
|
variant name.
|
||||||
|
|
||||||
|
## Update Check
|
||||||
|
|
||||||
|
The in-app update check reported "cannot reach the release server, check your
|
||||||
|
network connection" for users whose network was fine. GitHub's anonymous API
|
||||||
|
allows 60 requests per hour **per source IP**, so anyone behind a shared egress
|
||||||
|
— corporate NAT, a VPN, most China-region proxies — can find the quota already
|
||||||
|
spent by strangers:
|
||||||
|
|
||||||
|
```
|
||||||
|
403 {"message":"API rate limit exceeded for <shared-egress-ip>."}
|
||||||
|
```
|
||||||
|
|
||||||
|
The probe now falls back to the releases **Atom feed**, which is served by
|
||||||
|
`github.com` rather than `api.github.com` and is not on that quota. The JSON API
|
||||||
|
stays the first choice for its richer response; the feed only has to cover the
|
||||||
|
case where the API refuses to answer at all. Drafts never appear in the feed,
|
||||||
|
which is the same rule the API path already applied.
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Public relay unusable in all published `v0.8.3` builds, in both service
|
||||||
|
regions, for owners and guests alike.
|
||||||
|
- Update check failing with a network error on shared egress IP addresses.
|
||||||
|
- A misconfigured relay build reporting as a temporary service outage.
|
||||||
|
- Expired collaboration tickets, rate-limited hubs and network faults sharing
|
||||||
|
one indistinguishable relay error.
|
||||||
|
|
||||||
|
## Upgrade Notes and Compatibility
|
||||||
|
|
||||||
|
- **Upgrade to restore the public relay.** No server-side change is needed and
|
||||||
|
no action is required from you beyond installing this release — the `v0.8.3`
|
||||||
|
hubs, regions and pairing codes were correct throughout. Local-network
|
||||||
|
collaboration was never affected.
|
||||||
|
- **Pairing codes and sessions are unchanged.** The 10-character region-tagged
|
||||||
|
pairing code, the wire protocol, and the bootstrap document format are
|
||||||
|
identical to `v0.8.3`; a `v0.8.4` peer and a `v0.8.3` peer interoperate on any
|
||||||
|
path a `v0.8.3` peer could already reach.
|
||||||
|
- **Sign-in prompts may replace relay errors.** With ticket rejection now
|
||||||
|
classified, a session whose sign-in has lapsed reports that directly instead
|
||||||
|
of blaming the relay. This surfaces a pre-existing condition; it is not a new
|
||||||
|
restriction.
|
||||||
|
- **Building from source with production hubs.** If you inject
|
||||||
|
`OPENPENCIL_BUILD_COLLAB_BOOTSTRAP_URL_CN` / `_GLOBAL`, they must now be exact
|
||||||
|
— `https://<host>/api/v1/collaboration/bootstrap`, lowercase host, no
|
||||||
|
surrounding whitespace — or the build fails. Builds that inject neither are
|
||||||
|
unaffected.
|
||||||
|
- **Prebuilt `op-auth` libraries are version-pinned.** Their signed provenance
|
||||||
|
records the product version, so the `v0.8.4` artifacts are required for a
|
||||||
|
`v0.8.4` build; a `v0.8.3` artifact is refused rather than silently linked.
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
Thanks to everyone who reported the relay failure and stayed with the
|
||||||
|
investigation through the server, the gateway, the trust chain and the build
|
||||||
|
pipeline before it came down to one byte in a repository secret.
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
},
|
},
|
||||||
"op-web-sdk": {
|
"op-web-sdk": {
|
||||||
"name": "@zseven-w/op-web-sdk",
|
"name": "@zseven-w/op-web-sdk",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jsdom": "^25.0.0",
|
"jsdom": "^25.0.0",
|
||||||
"tsup": "^8.0.0",
|
"tsup": "^8.0.0",
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
},
|
},
|
||||||
"op-web-sdk-react": {
|
"op-web-sdk-react": {
|
||||||
"name": "@zseven-w/op-web-sdk-react",
|
"name": "@zseven-w/op-web-sdk-react",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zseven-w/op-web-sdk": "workspace:*",
|
"@zseven-w/op-web-sdk": "workspace:*",
|
||||||
},
|
},
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
},
|
},
|
||||||
"op-web-sdk-vue": {
|
"op-web-sdk-vue": {
|
||||||
"name": "@zseven-w/op-web-sdk-vue",
|
"name": "@zseven-w/op-web-sdk-vue",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zseven-w/op-web-sdk": "workspace:*",
|
"@zseven-w/op-web-sdk": "workspace:*",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "__MSG_extName__",
|
"name": "__MSG_extName__",
|
||||||
"description": "__MSG_extDescription__",
|
"description": "__MSG_extDescription__",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"minimum_chrome_version": "103",
|
"minimum_chrome_version": "103",
|
||||||
"action": {
|
"action": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@zseven-w/op-web-sdk-react",
|
"name": "@zseven-w/op-web-sdk-react",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"description": "React adapter for the OpenPencil read-only web viewer SDK",
|
"description": "React adapter for the OpenPencil read-only web viewer SDK",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export const VERSION = '0.8.3';
|
export const VERSION = '0.8.4';
|
||||||
export { DesignProvider, useViewer } from './use-viewer.js';
|
export { DesignProvider, useViewer } from './use-viewer.js';
|
||||||
export { useDocument, useViewport, useActivePage } from './hooks.js';
|
export { useDocument, useViewport, useActivePage } from './hooks.js';
|
||||||
export { DesignView, type DesignViewProps } from './design-view.js';
|
export { DesignView, type DesignViewProps } from './design-view.js';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@zseven-w/op-web-sdk-vue",
|
"name": "@zseven-w/op-web-sdk-vue",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"description": "Vue 3 adapter for the OpenPencil read-only web viewer SDK",
|
"description": "Vue 3 adapter for the OpenPencil read-only web viewer SDK",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export const VERSION = '0.8.3';
|
export const VERSION = '0.8.4';
|
||||||
export { viewerKey } from './injection.js';
|
export { viewerKey } from './injection.js';
|
||||||
export { provideViewer, provideViewerRef, useViewer } from './use-viewer.js';
|
export { provideViewer, provideViewerRef, useViewer } from './use-viewer.js';
|
||||||
export { useDocument, useViewport, useActivePage } from './composables.js';
|
export { useDocument, useViewport, useActivePage } from './composables.js';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@zseven-w/op-web-sdk",
|
"name": "@zseven-w/op-web-sdk",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"description": "Read-only OpenPencil .op viewer SDK for the web (wasm-backed)",
|
"description": "Read-only OpenPencil .op viewer SDK for the web (wasm-backed)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Public entry for the OpenPencil read-only web SDK core.
|
// Public entry for the OpenPencil read-only web SDK core.
|
||||||
export const VERSION = '0.8.3';
|
export const VERSION = '0.8.4';
|
||||||
export { createViewer, OpViewer } from './viewer.js';
|
export { createViewer, OpViewer } from './viewer.js';
|
||||||
export type { Viewport, CreateViewerOptions, PenDocument, PenPage } from './types.js';
|
export type { Viewport, CreateViewerOptions, PenDocument, PenPage } from './types.js';
|
||||||
export type { ViewerEvent } from './events.js';
|
export type { ViewerEvent } from './events.js';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@zseven-w/openpencil-packages",
|
"name": "@zseven-w/openpencil-packages",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Web SDK workspace for OpenPencil (the Rust product lives in ../crates). Hosts the wasm-backed op-web-sdk viewer family plus the JS build glue that feeds the Rust web target.",
|
"description": "Web SDK workspace for OpenPencil (the Rust product lives in ../crates). Hosts the wasm-backed op-web-sdk viewer family plus the JS build glue that feeds the Rust web target.",
|
||||||
"author": {
|
"author": {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue