docs(deploy): record browser route release
This commit is contained in:
1 parent
24ce10d5a1
commit
23c163e65e
12 files changed
+87
-95
No files matched your search
@@ -2,9 +2,9 @@
|
||||
|
||||
Screener is a private, low-latency screen-sharing project for one game player and a small group of friends. Its accepted media target is WebRTC P2P-first, with an SFU virtual parent feeding only the necessary roots and optional authenticated TURN for explicitly supported restrictive networks. Roots continue distributing to bounded peer descendants; this is not an always-SFU conferencing design. Viewers should be able to join from a desktop or mobile browser without installing the sender application.
|
||||
|
||||
The first measurable Web proof of concept is implemented. A host captures a screen, window, or browser tab and shares a numeric room code. Rooms default to a private fragment invitation whose capability authorizes only one room; a Host may explicitly choose public watching by room code after site access. During a share, the host can change between three ceiling profiles without reopening the source picker: 1080p60 at 8 Mbps, 1080p30 at 5 Mbps, and 720p30 at 3 Mbps. The host can also temporarily pause the picture or switch sources. Rooms are random and temporary by default. A site-access-protected deployment can optionally use SQLite-backed room numbers starting at `1`, reusable links, and a waiting state after sharing stops. Lightweight deployments may keep independent direct WebRTC connections. The flagship deployment enables the all-room controller with bounded peer descendants and LiveKit SFU roots; short-lived TURN may be authorized only for a controller-selected exceptional media edge. The default room capacity is eight viewers and deployments may configure 1 through 16, but that admission limit is not a performance promise.
|
||||
The first measurable Web proof of concept is implemented. A host captures a screen, window, or browser tab and shares a numeric room code. Rooms default to a private fragment invitation whose capability authorizes only one room; a Host may explicitly choose public watching by room code after site access. During a share, the host can change between three ceiling profiles without reopening the source picker: 1080p60 at 8 Mbps, 1080p30 at 5 Mbps, and 720p30 at 3 Mbps. The host can also temporarily pause the picture or switch sources. Rooms are random and temporary by default. A site-access-protected deployment can optionally use SQLite-backed room numbers starting at `1`, reusable links, and a waiting state after sharing stops. Lightweight deployments may keep independent direct WebRTC connections. The flagship deployment enables the all-room controller with bounded peer descendants and one LiveKit Host publication serving admitted Viewer subscriptions; short-lived TURN may be authorized only for a controller-selected exceptional media edge. Production admits 20 viewers and deployments may configure 1 through 20, but that admission limit is not a performance promise.
|
||||
|
||||
This is not yet a broadly validated production release; [Current status](./docs/status.md) owns the deployed revision and validation evidence. The current flagship boundary is the all-room bounded peer/SFU-UDP controller, with ordinary peer ICE kept STUN-only and short-lived TURN limited to controller-selected exceptional media edges. The optional Windows native sender remains source-only and is not a production runtime. Mobile devices are Web viewers only; ordinary Android and iOS browsers do not expose reliable screen capture for a Web Host. Real cross-network SFU/TURN media, game audio, a sustained 1:8 room, mobile browser lifecycle behavior, and latency targets still require the documented manual test matrix.
|
||||
This is not yet a broadly validated product release; [Current status](./docs/status.md) owns the deployed revision and validation evidence. The deployed flagship boundary is the all-room bounded peer/SFU-UDP controller on `screener-v7`, with ordinary peer ICE kept STUN-only and short-lived TURN limited to controller-selected exceptional media edges. The optional Windows native sender remains source-only and is not a production runtime. Mobile devices are Web viewers only; ordinary Android and iOS browsers do not expose reliable screen capture for a Web Host. Real cross-network SFU/TURN media, game audio, a sustained public-network 1:20 session, mobile browser lifecycle behavior, and latency targets still require the documented manual test matrix.
|
||||
|
||||
## Run locally
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
# Project Documentation
|
||||
|
||||
- [需求理解](./需求理解.md): current product scope, priorities, constraints, and acceptance criteria.
|
||||
- [方案设计](./方案设计.md): accepted implementation design; unfinished production release and validation are tracked in the current TODO ledger.
|
||||
- [方案设计](./方案设计.md): accepted implementation design; unfinished release and validation work is tracked in the current TODO ledger.
|
||||
- [Project memory](./project-memory.md): durable current product and source snapshot to read at the start of future work.
|
||||
- [Current status](./status.md): bounded current/index snapshot of production, active milestones, decisions, blockers, and links to detail.
|
||||
- [Verification status](./verification-status.md): demand-loaded ledger of current cross-cutting evidence, open proof boundaries, and expensive-test applicability.
|
||||
@@ -24,7 +24,7 @@
|
||||
- [ADR-0001](./adr/0001-p2p-first-media-topology.md): historical P2P-first baseline; later access and automatic-routing decisions supersede its stale current-state details.
|
||||
- [ADR-0002](./adr/0002-memory-resident-protected-rooms.md): four-digit leased in-memory rooms, local Host defaults, scoped Viewer grants, and orthogonal code entry.
|
||||
- [ADR-0004](./adr/0004-peer-assisted-media-experiment.md): historical standard-WebRTC peer-assisted experiment and reusable evidence.
|
||||
- [ADR-0005](./adr/0005-automatic-hybrid-media-routing.md): accepted and source-implemented automatic P2P-first single-reconcile route model, capacity/accounting, fallback roles, and exact first-frame transaction; production release and validation remain in the current TODO.
|
||||
- [ADR-0005](./adr/0005-automatic-hybrid-media-routing.md): accepted, implemented, and deployed automatic P2P-first single-reconcile route model, capacity/accounting, fallback roles, and exact first-frame transaction; remaining real-network validation is tracked in verification status.
|
||||
- [ADR-0006](./adr/0006-fixed-high-native-sender-canary.md): proposed fixed-`HIGH` native canary, current no-go result, and staged revalidation boundary.
|
||||
- [ADR-0007](./adr/0007-demand-driven-dual-representation-quality.md): accepted path-isolated `HIGH + at most one LOW` policy, optional idle-layer stop, evidence contract, and SVC boundary.
|
||||
- [ADR-0008](./adr/0008-window-scoped-audio-capture.md): browser window-audio hint and the Windows WASAPI process-loopback boundary.
|
||||
|
||||
@@ -31,8 +31,8 @@ contradict the private-room cost model or duplicate mature WebRTC capabilities.
|
||||
## Current Ownership
|
||||
|
||||
[ADR-0005](./0005-automatic-hybrid-media-routing.md) owns current routing
|
||||
invariants and assisted-route roles; Browser source migration is complete while
|
||||
production release and validation remain in the current TODO. [ADR-0004](./0004-peer-assisted-media-experiment.md)
|
||||
invariants and assisted-route roles; the Browser `screener-v7` migration is
|
||||
implemented and deployed, while real-network validation remains open. [ADR-0004](./0004-peer-assisted-media-experiment.md)
|
||||
owns only historical peer-assisted evidence. Access and room lifetime are owned
|
||||
by [ADR-0002](./0002-memory-resident-protected-rooms.md).
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ADR-0005: Automatic Hybrid Media Routing
|
||||
|
||||
- Status: Accepted; source runtime implemented, production release pending
|
||||
- Status: Accepted; source runtime implemented and deployed
|
||||
- Date: 2026-08-20
|
||||
- Last updated: 2026-08-23
|
||||
|
||||
@@ -307,10 +307,12 @@ disappears. A multi-process application deployment requires a shared atomic
|
||||
admission and lifecycle owner before it may claim these values are
|
||||
deployment-wide.
|
||||
|
||||
## Current Production Divergence
|
||||
## Current Deployment Boundary
|
||||
|
||||
Production release `9461e20` predates the implemented source runtime. Its exact
|
||||
behavior and rollback boundary are owned by the deployment document.
|
||||
Production release `6b87732` runs the `screener-v7` Browser runtime. Its exact
|
||||
configuration, rollback artifacts, and postflight evidence are owned by the
|
||||
deployment document; real heterogeneous-network and SFU/TURN media validation
|
||||
remains open.
|
||||
|
||||
## Acceptance Boundary
|
||||
|
||||
|
||||
+34
-37
@@ -1,8 +1,8 @@
|
||||
# Minimal Deployment
|
||||
|
||||
Last verified against upstream documentation: 2026-08-22.
|
||||
Last verified against upstream documentation: 2026-08-23.
|
||||
|
||||
This page records exact release `9461e20` production facts and the current source
|
||||
This page records exact release `6b87732` production facts and the current source
|
||||
deployment contract. Product direction and pending migrations are owned by
|
||||
[project memory](./project-memory.md) and [the TODO ledger](./todo.md).
|
||||
|
||||
@@ -25,26 +25,25 @@ tracked coturn example remains `stun-only`; the shared host retains its older
|
||||
authenticated-relay daemon configuration and firewall range. The application
|
||||
does not pre-advertise TURN credentials to ordinary peers.
|
||||
|
||||
Production currently runs exact `9461e207af62b4f38f6b7a8aa16f8beb49e0e4ee`
|
||||
from `/opt/screener/releases/9461e20`; immediate rollback is
|
||||
`/opt/screener/releases/21d5cd9f7139`. Local and public health return 200;
|
||||
Screener, LiveKit, coturn, and nginx are active, and Screener reports
|
||||
`NRestarts=0`.
|
||||
Production runs exact `6b87732b5f97b7836f628a2c333d0c3f05990c99`, release
|
||||
`6b87732`, from `/opt/screener/releases/6b87732`. The immutable source archive
|
||||
SHA-256 is
|
||||
`3e88575e3842074f3ecb5dcbd548c159d13a113316d70f680ac6629e39a7f733`.
|
||||
Immediate rollback is `/opt/screener/releases/9461e20`, with the verified
|
||||
pre-cutover SQLite/environment/LiveKit backup at
|
||||
`/opt/screener/backups/6b87732-precutover-20260823T115350Z`. Local and public
|
||||
health return 200; Screener, LiveKit, coturn, and nginx are active, and the
|
||||
restarted Screener/LiveKit services report `NRestarts=0`.
|
||||
|
||||
The current release deploys the bounded pre-share health/WSS/STUN self-check,
|
||||
privacy-safe click-only diagnostic JSON export, room admission default eight
|
||||
with explicit limits from one through sixteen, bounded signaling-partition
|
||||
recovery, and peer-quality MBB. An ordinary Viewer with a peer/SFU upstream or
|
||||
the Host may own one separately budgeted provisional child. The endpoint-cap environment is unset,
|
||||
so the production default yields Host two and ordinary Browser Viewer one; the
|
||||
wire remains unchanged. The retained capacity-two/cap3 sixteen-Viewer
|
||||
and resource runs are historical ordinary-PC experiments only and do not define
|
||||
release policy or close performance gates.
|
||||
The release also deploys the identity-bound relayed-detail presentation, root <=2 controller/token invariant,
|
||||
Host-publication edge accounting, zero-child assignment/subscriber retention,
|
||||
and `dynacast: false` with ordered active `q,h`. These are bounded control-plane
|
||||
and publisher-configuration guarantees; real shaped LiveKit packet flow, BWE
|
||||
downshift/recovery, and resource cost remain open.
|
||||
The release deploys the single Browser `screener-v7` wire, 20-Viewer room
|
||||
admission, the uniform endpoint media-copy cap `2`, the one-controller
|
||||
exact-candidate route runtime, and stale-client rejection before room
|
||||
authority. LiveKit is dedicated, has `room.auto_create: false` and
|
||||
`max_participants: 21`, and is admitted to one global publication ingress plus
|
||||
twenty subscription egress handles. Selected TURN has two logical allocations.
|
||||
These bounds are fail-safe admissions, not throughput or quality claims.
|
||||
The retained local 20-Viewer Browser smoke and open real-network boundaries are
|
||||
owned by [verification status](./verification-status.md).
|
||||
|
||||
## Topology and prerequisites
|
||||
|
||||
@@ -141,9 +140,9 @@ TURN when configured; only an unavailable logical ingress uses the Host
|
||||
publication/SFU path. A Host-SFU ingress may itself use selected TURN. LiveKit
|
||||
participants receive only revision-bound `sfu-config` URL/token messages and
|
||||
negotiate within LiveKit's separate ICE domain. The selected-edge TURN
|
||||
config/wire is deployed in the current `9461e20` release with one UDP URL and a
|
||||
120-second credential TTL. It was not exercised by a real media session during
|
||||
this cutover.
|
||||
config/wire is deployed in the current `6b87732` release with one UDP URL, a
|
||||
120-second credential TTL, and two logical allocations. It was not exercised by
|
||||
a real media session during this cutover.
|
||||
|
||||
`PEER_ASSISTED_MEDIA=true` is the process-wide topology/SFU switch. Every normal
|
||||
room gets its own bounded controller state; ordinary peer connections remain
|
||||
@@ -198,7 +197,7 @@ manager or a cross-platform Node command such as:
|
||||
node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'))"
|
||||
```
|
||||
|
||||
Use this next-release baseline for the current source candidate:
|
||||
Use this production baseline template:
|
||||
|
||||
```dotenv
|
||||
NODE_ENV=production
|
||||
@@ -288,10 +287,9 @@ key, even blank, fails startup.
|
||||
`ROOM_DATABASE_PATH` is optional but requires `SITE_ACCESS_PASSWORD`.
|
||||
Omit the database path to keep random temporary rooms; `ROOM_TTL_SECONDS`
|
||||
applies only to those rooms.
|
||||
Production `9461e20` defaults `MAX_VIEWERS_PER_ROOM` to 8 and accepts 1 through
|
||||
16. Current source accepts 1 through 20, and the next-release baseline above
|
||||
explicitly selects 20 after the route-release smoke passes. It is an admission
|
||||
limit, not evidence that the publisher can sustain that many streams.
|
||||
Production `6b87732` accepts 1 through 20 and explicitly selects 20. This is an
|
||||
admission limit, not evidence that every publisher, network, or quality profile
|
||||
can sustain that many streams.
|
||||
`ENDPOINT_MEDIA_COPY_CAPACITY` defaults to 2 and accepts only 1, 2, or 3. It is
|
||||
the single server-authoritative steady outbound media-copy cap for Host and
|
||||
Viewer endpoints; role, browser, UA, and visibility do not create another tier.
|
||||
@@ -305,12 +303,11 @@ TURN allocation admission.
|
||||
Supplying the removed `MAX_PEER_RELAY_DOWNSTREAM_EDGES`, even blank, fails
|
||||
startup.
|
||||
|
||||
Production release `9461e20` still runs the legacy Host-2/Browser-1 policy on
|
||||
wire `screener-v5`. Deploy the current source server and Browser assets
|
||||
atomically on `screener-v7`; stale Browser and executable-sender wires must fail
|
||||
Production release `6b87732` runs the current source server and Browser assets
|
||||
atomically on `screener-v7`; stale Browser and executable-sender wires fail
|
||||
before room authority. Native senders and helpers are outside this release.
|
||||
Restore the exact prior environment, server, and Web assets together when
|
||||
rolling back.
|
||||
Restore the exact prior environment, LiveKit configuration, database backup,
|
||||
server, and Web assets together when rolling back.
|
||||
|
||||
The four `LIVEKIT_*` values must either all be absent or all be present, and a
|
||||
complete tuple requires `PEER_ASSISTED_MEDIA=true` plus explicit positive
|
||||
@@ -613,11 +610,11 @@ Run these checks from real external networks before calling the deployment usabl
|
||||
ends clearly without ICE/TCP, TURN/TCP, or a long pseudo-connected path.
|
||||
5. Exercise root departure, reconnect, SFU unavailable, route prepare rollback,
|
||||
stop, and source/profile changes. Unaffected subtrees must not migrate.
|
||||
6. Repeat at 1, 3, 5, and 8 viewers across representative consumer networks.
|
||||
6. Repeat at 1, 3, 5, and 20 viewers across representative consumer networks.
|
||||
Record selected protocol, RTT, bitrate, frame rate, packet loss, publisher
|
||||
upload/encode load, LiveKit ingress/egress, and final decoded quality. A real
|
||||
1:20 session remains unverified until the route-release smoke passes; this
|
||||
longer matrix remains the heterogeneous-network quality gate.
|
||||
public-network 1:20 session remains unverified; the passed local synthetic
|
||||
1:20 smoke does not replace this heterogeneous-network quality gate.
|
||||
|
||||
References: [coturn 4.17.2 release](https://github.com/coturn/coturn/releases/tag/4.17.2),
|
||||
[pinned turnserver documentation](https://github.com/coturn/coturn/blob/4.17.2/README.turnserver),
|
||||
|
||||
@@ -29,16 +29,16 @@ Last updated: 2026-08-23
|
||||
- Canonical source is the root `main` branch. Audit/integration boundaries require it to be clean, and new branches/worktrees start from its exact commit only after accepted truth is merged.
|
||||
- Current source admits up to `20` Viewers and implements the uniform `1/2/3` endpoint cap, single Browser `screener-v7` wire, exact prepare candidate, first-decoded-frame commit, strict rollback revision, decoded-progress stall, and one event-driven room controller. Older Browser and executable-sender wires fail before room authority. SFU admission uses exact publication and Viewer-subscription handles with explicit no-default ingress/egress capacities and a listener-fenced dedicated LiveKit owner. Selected TURN uses its own explicit no-default deployment capacity and exact logical-allocation ledger shared by independent peer edges and Host-SFU ingress.
|
||||
- The accepted room model is not implemented on current source. Source still exposes mutually exclusive `private-link | public-watch`, random 12-digit temporary rooms, optional SQLite persistent rooms, and `ROOM_TTL_SECONDS`; production also remains SQLite-backed. Do not report four-digit leases, orthogonal code/grant access, local preference replay, or SQLite removal as shipped until that scoped implementation is validated and deployed.
|
||||
- Production runs exact `9461e207af62b4f38f6b7a8aa16f8beb49e0e4ee`, release `9461e20`, wire `screener-v5`; `21d5cd9f7139` is the rollback release.
|
||||
- Production still enforces Host downstream `2`, ordinary Browser downstream `1`, deployment values `1/2`, a fixed SFU-root limit of `2`, and legacy publication/selected accounting. This is a dated implementation divergence, not current product policy.
|
||||
- Production has automatic routing, bad-relay corroboration, peer-quality make-before-break with Viewer and Host provisional parents, selected-edge transport, stable route/connection details, 64/128/256 audio choices, access controls, self-check, diagnostic export, and signaling watchdog behavior.
|
||||
- Production runs exact `6b87732b5f97b7836f628a2c333d0c3f05990c99`, release `6b87732`, wire `screener-v7`; `9461e20` is the rollback release.
|
||||
- Production implements the current endpoint-cap and route-controller contract, admits 20 Viewers, uses LiveKit admission of one publication ingress plus 20 subscription egress handles on a dedicated non-auto-create instance, and bounds selected TURN to two logical allocations.
|
||||
- Production retains access controls, self-check, diagnostic export, signaling watchdog behavior, 64/128/256 audio choices, and selected-edge transport. Real heterogeneous-network and SFU/TURN media evidence remains open.
|
||||
- `screener`, LiveKit, coturn, and nginx are healthy; local and public health return 200 and `screener` has `NRestarts=0`. Deployment detail is owned by [deployment](./deployment.md).
|
||||
- Chrome loopback, cap2/cap3, short resource, recovery, MBB, and A/V fixtures are bounded evidence only. They do not establish quality, resource limits, or product policy.
|
||||
|
||||
## Current Priority
|
||||
|
||||
1. Keep this truth set and [the TODO ledger](./todo.md) concise and internally consistent.
|
||||
2. Release the converged Browser route source first. Then release live audio and paused video-codec switching, follow with evidence-led H.264 diagnosis, the strict-NAT emulator gate, connection feedback, the accepted memory-resident room/access slice, and the remaining functional roadmap. Distribution packaging starts only after those TODOs are complete. Parallel branches may finish earlier but do not change this merge/deployment order.
|
||||
2. Release live audio and paused video-codec switching next, follow with evidence-led H.264 diagnosis, the strict-NAT emulator gate, connection feedback, the accepted memory-resident room/access slice, and the remaining functional roadmap. Distribution packaging starts only after those TODOs are complete. Parallel branches may finish earlier but do not change this merge/deployment order.
|
||||
|
||||
## Working Rules
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
low latency, and bounded host media fanout
|
||||
- Status: research and dated route evidence. Current invariants and assisted
|
||||
transport roles are in [ADR-0005](../adr/0005-automatic-hybrid-media-routing.md);
|
||||
Browser source migration is complete, while production release and validation
|
||||
remain in [the TODO ledger](../todo.md).
|
||||
the Browser source migration is deployed, while real-network validation
|
||||
remains in [verification status](../verification-status.md).
|
||||
|
||||
## Historical Candidate Route Ladder
|
||||
|
||||
@@ -592,10 +592,10 @@ contract and is outside this wave.
|
||||
| Route | Where copies are emitted | Endpoint cost | Evidence status |
|
||||
| --- | --- | --- | --- |
|
||||
| Direct host P2P | Host emits one copy per Viewer | Host upload and sender pipelines grow with Viewers | Baseline evidence; current capacity is owned by the product contract |
|
||||
| Bounded browser relay DAG | Host and each Web relay emit at most the configured endpoint cap | Ordinary browser, but every relay decodes and re-encodes and adds a hop | Current source admits up to 20; production remains default eight/maximum 16 until the 20-Viewer release smoke passes |
|
||||
| Bounded browser relay DAG | Host and each Web relay emit at most the configured endpoint cap | Ordinary browser, but every relay decodes and re-encodes and adds a hop | Source and production admit up to 20; the local 20-Viewer smoke passed, while heterogeneous networks remain open |
|
||||
| Native shared-encode host | Host targets one encode for standard WebRTC edges | libwebrtc public-API proxy risk spike, with Pion as fallback | Research evidence; still pays per-edge upload |
|
||||
| Native volunteer encoded-RTP relay | Each volunteer forwards one encoded copy | Native install, RTP/RTCP forwarding, packaging, and opt-in relay policy | Research only; no current product authorization |
|
||||
| SFU service | SFU emits authorized subscription copies | Service pays measured egress; an authoritative Host publisher supplies media | Functional evidence and source topology/admission exist; production release and real-network validation remain open |
|
||||
| SFU service | SFU emits authorized subscription copies | Service pays bounded egress; an authoritative Host publisher supplies media | Source topology/admission are deployed; real LiveKit media and network validation remain open |
|
||||
| Additional server-assisted paths | SFU/TURN emits authorized copies | Additional central ingress, egress, or allocation cost | Accepted resource-admission input; validate each bounded path at release |
|
||||
| SVC plus multiple trees | Peers emit striped layer copies across several trees | Layer scheduling, reassembly, redundancy, and more churn state | Separate conditional spike; target endpoint upload near `B` |
|
||||
| Network coding | Peers or servers emit coded blocks | Generations, buffering, decoding, integrity, and a custom media plane | Trace/FEC spike only; optimize loss recovery, not clean bandwidth |
|
||||
|
||||
@@ -31,9 +31,10 @@ Current high-signal boundary:
|
||||
|
||||
- docs/status.md owns the exact source/production/hold state.
|
||||
- docs/todo.md is the only executable work ledger and owns ordering.
|
||||
- ADR-0005 owns the accepted automatic route model. The Browser route source is
|
||||
implemented on main but production remains on the older release; do not rerun
|
||||
broad or executable/native test suites unless the current acceptance boundary
|
||||
- ADR-0005 owns the accepted automatic route model. The Browser `screener-v7`
|
||||
source is implemented and deployed as release `6b87732`; real external-network
|
||||
and SFU/TURN media evidence remains open. Do not rerun broad or
|
||||
executable/native test suites unless the current acceptance boundary
|
||||
specifically requires them.
|
||||
- ADR-0002 owns the newly accepted room model: one process-memory RoomStore,
|
||||
random free four-digit codes, configurable 24-hour dormant leases, restart
|
||||
|
||||
+14
-19
@@ -6,16 +6,16 @@ This is the current execution index. Git history owns completed timelines; [veri
|
||||
|
||||
## Production
|
||||
|
||||
- `https://share.bonfire.icu` runs exact `9461e207af62b4f38f6b7a8aa16f8beb49e0e4ee`, release `9461e20`, wire `screener-v5`; `21d5cd9f7139` is the rollback release.
|
||||
- `screener`, LiveKit, coturn, and nginx are active; local/public health return 200, `screener` has `NRestarts=0`, and SQLite schema v3 remains protected with mode 0600.
|
||||
- Production has automatic routing, bad-relay handling, peer-quality make-before-break, Viewer/Host provisional parents, selected-edge transport, stable connection details, 64/128/256 audio choices, access/privacy controls, self-check, diagnostic export, and signaling watchdog behavior.
|
||||
- Exact deployed routing remains Host downstream `2`, ordinary Browser downstream `1`, deployment values `1/2`, fixed SFU roots `2`, and legacy publication/selected accounting. This is production fact only; it differs from the accepted endpoint-cap direction.
|
||||
- `https://share.bonfire.icu` runs exact `6b87732b5f97b7836f628a2c333d0c3f05990c99`, release `6b87732`, wire `screener-v7`; `9461e20` is the rollback release and its pre-cutover environment/config/SQLite backup is retained.
|
||||
- `screener`, LiveKit, coturn, and nginx are active; local/public health return 200, both restarted services report `NRestarts=0`, and SQLite schema v3 remains protected with mode 0600.
|
||||
- Production admits one Host plus 20 Viewers, applies endpoint capacity `2`, rejects stale Browser and executable-sender wires before room authority, and runs the one-controller exact-candidate route model. LiveKit is dedicated with `room.auto_create: false`, `max_participants: 21`, global admission `1` publication ingress / `20` subscription egress; selected TURN has `2` logical allocations.
|
||||
- Production still has access/privacy controls, self-check, diagnostic export, signaling watchdog behavior, 64/128/256 audio choices, and selected-edge transport. These deployment facts do not close the real heterogeneous-network, SFU/TURN media, mobile, or endurance evidence boundaries.
|
||||
|
||||
## Current Source
|
||||
|
||||
- Canonical source is the root `main` branch; auxiliary branches and worktrees do not own current truth. The documentation-only route/room truth and handoff checkpoint is part of this canonical state; start dependent work only from that exact root `main` commit.
|
||||
- Canonical source is the root `main` branch; auxiliary branches and worktrees do not own current truth. Audit/integration boundaries require a clean root, and dependent work starts only from its exact commit.
|
||||
- Current source implements one steady outbound media-copy cap for every non-server endpoint: default `2`, static `1/2/3`, a peer child or Host publication consumes one slot, upstream receive is free, a committed selected TURN transport replaces the same copy while hidden carry consumes another, and no Browser/UA/visibility tier exists. One shared guard owns the accounting and transition work is bounded by `min(C + 1, 3)`.
|
||||
- Current source and accepted room admission support one Host plus up to `20` Viewers. Focused controller coverage includes `C=1/2/3` and a 20-Viewer graph; real Browser resource and media measurements remain release evidence.
|
||||
- Current source and production admission support one Host plus up to `20` Viewers. Focused controller coverage includes `C=1/2/3`, a 20-Viewer graph, and the passed local 20-Viewer Browser smoke; real external-network media and resource measurements remain open.
|
||||
- The single Browser `screener-v7` boundary rejects stale Browser and executable-sender wires before room authority and carries the exact deployment cap plus exact prepare candidate in the authenticated route contract.
|
||||
- Current source also implements explicit no-default SFU ingress/egress capacities and exact `reserved | committed | draining` accounting. The listener owner reconciles its dedicated non-auto-create LiveKit namespace before serving, creates each generation before token issuance, releases only after delete-plus-absence proof, and reclaims Host-offline generations through bounded exact-participant checks. Selected TURN has an independent explicit no-default deployment capacity; one process-local ledger charges every exact peer-selected edge and Host-SFU ingress through reserve, commit, drain, and release.
|
||||
- Current source implements automatic P2P-first routing with one active upstream, an acyclic source-reachable graph, exact Browser v7 prepare tuple, first-decoded-frame make-before-break, strict rollback revision, and bounded wait or failure.
|
||||
@@ -27,26 +27,21 @@ This is the current execution index. Git history owns completed timelines; [veri
|
||||
|
||||
## Current Milestone
|
||||
|
||||
1. Release the implemented generic route loop on the single Browser `screener-v7` wire after its remaining production acceptance boundary.
|
||||
2. Release live audio-ceiling mutation and paused-share codec switching on the resulting generation/transition boundary.
|
||||
3. Reproduce the H.264 startup report before any codec-specific repair, and build the strict-NAT emulator gate before any manually approved canary in an operator-owned test room.
|
||||
4. Add first-frame-driven Viewer connection stages, then implement the accepted memory-resident room/access slice and finish the remaining accepted functional and real-network work.
|
||||
5. Validate and deploy each coherent slice in this order with its focused browser/network/resource and rollback gates; distribution packaging remains outside this milestone.
|
||||
1. Release live audio-ceiling mutation and paused-share codec switching on the deployed generation/transition boundary.
|
||||
2. Reproduce the H.264 startup report before any codec-specific repair, and build the strict-NAT emulator gate before any manually approved canary in an operator-owned test room.
|
||||
3. Add first-frame-driven Viewer connection stages, then implement the accepted memory-resident room/access slice and finish the remaining accepted functional and real-network work.
|
||||
4. Validate and deploy each coherent slice in this order with its focused browser/network/resource and rollback gates; distribution packaging remains outside this milestone.
|
||||
|
||||
## Active Boundaries
|
||||
|
||||
- `fix/configurable-relay-cap` is an old, incomplete draft and must not be merged as-is.
|
||||
- Open PR #192 and the Native stack are evidence/research, not pending product releases. Native senders, capture helpers, shared-encode executables, and their test binaries are outside the current route release and are not built or run in this milestone.
|
||||
- Open PR #192 and the Native stack are evidence/research, not pending product releases. Native senders, capture helpers, shared-encode executables, and their test binaries are outside the current Browser milestone and are not built or run.
|
||||
- Deployed surfaces and retained candidates that still need product decisions are indexed only in [the TODO ledger](./todo.md); do not extend or roll them back automatically.
|
||||
- Room entry, sharing controls, ID lifetime, and storage semantics are settled in the owning requirements/design/ADR and queued after the route boundary. Current source remains divergent until that complete slice replaces the old access and persistence model atomically.
|
||||
- Real SFU/TURN recovery, heterogeneous networks, mobile lifecycle, audio/A-V device behavior, and endurance/resource measurements remain external acceptance evidence, not blockers for unrelated reversible work.
|
||||
|
||||
## Current Hold
|
||||
|
||||
The route model and Browser source are complete and merged. Work is intentionally paused before
|
||||
production release or any later TODO until the owner chooses the next action. Production therefore
|
||||
remains on `9461e20` / `screener-v5`; source completion must not be reported as deployment.
|
||||
|
||||
If the owner resumes the route release, do not repeat the full local suite. Run one resource-limited
|
||||
20-Viewer Browser smoke, then production preflight, deploy, postflight, and rollback verification.
|
||||
The dedicated LiveKit instance and measured SFU/TURN capacities remain required deployment inputs.
|
||||
The Browser route is implemented and deployed. Later TODO work is intentionally paused until the
|
||||
owner chooses the next slice; do not start live audio, codec switching, room implementation, route
|
||||
rollback, Native/executable work, or broad cleanup without a new instruction.
|
||||
+5
-6
@@ -6,12 +6,11 @@ Only items in **Now** are executable after their stated decision gate. A branch
|
||||
|
||||
## Now
|
||||
|
||||
1. **Release the converged Browser route (held pending owner direction).** The one-controller `screener-v7` source is implemented, merged, typechecked, and focused-review clean. Start no release action until the owner resumes this item. Then run one resource-limited 20-Viewer Browser smoke that records route convergence, first-frame or bounded failure, endpoint sender counts, application CPU/memory, and SFU/TURN usage, followed by production preflight, deploy, postflight, and rollback verification. The existing Chrome attempt never reached a Browser/media run and must not be counted or retried unchanged; [verification status](./verification-status.md) owns that boundary. Do not repeat the full local suite or build/run Native, helper, shared-encode, Go test, or hardware executable artifacts.
|
||||
2. **Switch screen-audio ceilings live.** Keep Opus fixed and serialize 64/128/256 kbps desired profile updates across every current Host, relay, and SFU audio sender. Each endpoint uses fresh `getParameters()`/`setParameters()` readback, ignores stale completions, retains media plus its prior applied value on failure, and applies the latest desired value to future edges. Do not add a remote applied-ack protocol or claim room-wide atomic convergence in this slice.
|
||||
3. **Switch video codec while paused.** After the route/media-generation boundary is available, serialize the change with route mutation, freeze exact current route/media bindings, hold new joins, renegotiate P2P/relay and republish SFU while paused, then verify actual codec plus decoded frames on resume. A binding invalidated by leave or hard route failure exits this proof set and waits for routing to rebuild from the final committed preference after the bounded codec transaction settles. On failure pause again and perform bounded rollback; rollback proves the prior preference was reapplied plus a newly negotiated actual codec and decoded progress, not literal equality with the old actual codec. Zero targets update only the future-edge preference. Reset `automatic` with empty codec preferences. This is a paused bounded-gap transaction; unpaused make-before-break is a later extension.
|
||||
4. **Diagnose the production H.264/blur report.** Reproduce exact release `769de201f7cc` against current `main` on the same Host/browser/driver/game and one wired direct Viewer, changing one variable at a time. Implement a codec-specific repair only if codec/encoder evidence identifies it; otherwise fix the proven capture, sender, BWE, or lifecycle cause.
|
||||
5. **Gate the strict-NAT guessed-candidate experiment.** Build only the isolated endpoint-dependent NAT emulator and browser harness first. Standard ICE must fail in the owned fixture, the capped candidate set must pass the documented repeatability, deadline, privacy, and cleanup gates in stable Chrome and Firefox, and fallback must remain unchanged. Only then may one manually approved, operator-owned test room run a default-off, kill-switched canary with explicit consent from both endpoints and exact room/edge/generation/budget bounds; failure closes the candidate. Do not ship guessed candidates to ordinary rooms or infer NAT type from IP, UA, carrier, or two STUN observations.
|
||||
6. **Make Viewer connection progress explicit.** Derive one stable stage from existing access, route, peer/SFU, media, autoplay, and bounded-failure state. Keep the overlay until a composited current-generation frame, show `Play` only for actual autoplay rejection, preserve a still-valid old frame during recovery, and expose retry only through the bounded controller. Measure the existing token-free SFU prewarm and route stages before adding another connection mechanism.
|
||||
1. **Switch screen-audio ceilings live.** Keep Opus fixed and serialize 64/128/256 kbps desired profile updates across every current Host, relay, and SFU audio sender. Each endpoint uses fresh `getParameters()`/`setParameters()` readback, ignores stale completions, retains media plus its prior applied value on failure, and applies the latest desired value to future edges. Do not add a remote applied-ack protocol or claim room-wide atomic convergence in this slice.
|
||||
2. **Switch video codec while paused.** Serialize the change with route mutation, freeze exact current route/media bindings, hold new joins, renegotiate P2P/relay and republish SFU while paused, then verify actual codec plus decoded frames on resume. A binding invalidated by leave or hard route failure exits this proof set and waits for routing to rebuild from the final committed preference after the bounded codec transaction settles. On failure pause again and perform bounded rollback; rollback proves the prior preference was reapplied plus a newly negotiated actual codec and decoded progress, not literal equality with the old actual codec. Zero targets update only the future-edge preference. Reset `automatic` with empty codec preferences. This is a paused bounded-gap transaction; unpaused make-before-break is a later extension.
|
||||
3. **Diagnose the production H.264/blur report.** Reproduce exact release `769de201f7cc` against the deployed route release on the same Host/browser/driver/game and one wired direct Viewer, changing one variable at a time. Implement a codec-specific repair only if codec/encoder evidence identifies it; otherwise fix the proven capture, sender, BWE, or lifecycle cause.
|
||||
4. **Gate the strict-NAT guessed-candidate experiment.** Build only the isolated endpoint-dependent NAT emulator and browser harness first. Standard ICE must fail in the owned fixture, the capped candidate set must pass the documented repeatability, deadline, privacy, and cleanup gates in stable Chrome and Firefox, and fallback must remain unchanged. Only then may one manually approved, operator-owned test room run a default-off, kill-switched canary with explicit consent from both endpoints and exact room/edge/generation/budget bounds; failure closes the candidate. Do not ship guessed candidates to ordinary rooms or infer NAT type from IP, UA, carrier, or two STUN observations.
|
||||
5. **Make Viewer connection progress explicit.** Derive one stable stage from existing access, route, peer/SFU, media, autoplay, and bounded-failure state. Keep the overlay until a composited current-generation frame, show `Play` only for actual autoplay rejection, preserve a still-valid old frame during recovery, and expose retry only through the bounded controller. Measure the existing token-free SFU prewarm and route stages before adding another connection mechanism.
|
||||
|
||||
## Queued After Route
|
||||
|
||||
|
||||
@@ -10,20 +10,18 @@ Capacity and routing entries below describe the exact tested source or release o
|
||||
|
||||
## Deployment Evidence
|
||||
|
||||
- Production runs exact `9461e207af62b4f38f6b7a8aa16f8beb49e0e4ee`, release `9461e20`, with `21d5cd9f7139` retained for rollback.
|
||||
- Local/public health return 200; `screener`, LiveKit, coturn, and nginx are active; `screener` reports zero restarts. SQLite v3 has five rooms, SHA-256 `aef724ae52c4107be8ec8791e72f8dcaa11b0ec849fb432d022e2cfb9cfe0974`, owner `screener:screener`, and mode 0600.
|
||||
- Room admission defaults to eight and accepts explicit limits from one through sixteen. In the exact release, the unset endpoint-cap environment yielded Host2/ordinary Browser Viewer1, active/provisional/selected overlays were charged, SFU roots were limited to two, and one `peer-selected` lease was allowed per room excluding Host ingress. Those are release facts only. Current source uses steady endpoint cap `2` with static `1/2/3`, Host-publication slot accounting, same-edge TURN transport, and independent bounded server admission.
|
||||
- The deployed SFU path enforces the release's controller/token root cap, Host-publication edge accounting, zero-child assignment/subscriber retention, and `dynacast: false`. The tagged local gate covers those release invariants; the accepted route migration still requires real shaped LiveKit packet flow, BWE downshift/recovery, and resource validation.
|
||||
- Share audio presets and local-only Host SFU, codec/encoder, A/V, and selected-candidate diagnostics are deployed. Their target-browser field availability and actual media values remain unverified.
|
||||
- The bounded pre-share self-check, privacy-safe local JSON export, signaling-partition recovery, and peer-quality MBB are deployed. An ordinary Viewer with a peer/SFU upstream or the Host may own a separately budgeted provisional child. Real-route behavior remains part of the routing gate.
|
||||
- Earlier exact-`16f6eab` evidence proves active Host ingress only; it does not prove the current release, initial Viewer ingress, healthy reselection, last-mile quality, or TURN performance.
|
||||
- Production runs exact `6b87732b5f97b7836f628a2c333d0c3f05990c99`, release `6b87732`, wire `screener-v7`, from `/opt/screener/releases/6b87732`; the immutable archive SHA-256 is `3e88575e3842074f3ecb5dcbd548c159d13a113316d70f680ac6629e39a7f733`. `9461e20` remains the rollback release, and `/opt/screener/backups/6b87732-precutover-20260823T115350Z` contains the verified pre-cutover SQLite/environment/LiveKit configuration.
|
||||
- The 2026-08-23 postflight found `screener`, LiveKit, coturn, and nginx active with zero restarts after cutover; local and public `/healthz` returned 200. The deployed browser bundle is `assets/index-BzbOwAcC.js`, SHA-256 `680bc27dcb3951cdbde54acaa4c7a456682946c1ba72076e956fc9ce6525f91f`, matching the locally built artifact and containing the single `screener-v7` wire literal.
|
||||
- Production uses endpoint capacity `2`, room admission `20`, a dedicated LiveKit instance with `room.auto_create: false` and `max_participants: 21`, global SFU admission `1` ingress / `20` egress, and selected TURN admission `2`. These are conservative bounded admissions, not throughput or quality claims. LiveKit listed zero rooms after startup, and SQLite v3 remains integrity-ok with six rooms, owner `screener:screener`, and mode 0600.
|
||||
- Rollback evidence confirms the old release entrypoint is readable, every pre-cutover backup checksum passes, the backed-up database remains schema v3/integrity-ok with six rooms, and the current and rollback release regular-file sets share zero inodes.
|
||||
- Share audio presets, local-only diagnostics, self-check, diagnostic export, signaling-partition recovery, and selected-edge transport remain deployed surfaces. Their real-route media behavior and target-browser field availability remain unverified.
|
||||
|
||||
## Retained Functional Evidence
|
||||
|
||||
- Exact source `31e323e2754fcfde15f7b4d69e925ec71e2795cb` passed repository hygiene, TypeScript typecheck, client/server builds, all 660 Web tests, all Native Go packages, `go vet`, and two independent P0/P1 reviews. The tests cover strict v6 endpoint-cap authentication, ordinary active/waiting authorization and grace promotion, Native cap propagation and admission, and peer-assisted cap rejection. This is local state-machine/build evidence, not a complete Native physical-slot matrix or production, browser-quality, or heterogeneous-network acceptance.
|
||||
- Exact Wave B implementation source `815c6174d411c55648daf5cd6ac4c42f64effff9`, based on `d1ba2e52919225e67ad0c8dd2b660f333fbc88fd`, passed its 372-test SFU-admission gate, all 690 Web tests, TypeScript typecheck, and client/server builds. Focused tests cover reserved/committed/draining accounting, reserve-before-token enforcement, explicit room lifecycle, listener-owner startup fencing, restart cleanup, stale-token replay boundaries, Host-offline reclamation, shutdown races, and two-room global admission. This is fake-control-plane and local state-machine evidence, not a real LiveKit process/JWT replay, packet-flow, multi-process, deployment-capacity, or production proof.
|
||||
- Exact route source `4e0a922` passed repository hygiene, TypeScript typecheck, and 84 focused controller, runtime, protocol, transition, decoded-stall, and SFU-admission tests. During the same convergence, the full 557-test Web suite and client/server builds passed before the final no-consumer cleanup. The two independent route audits' model and wire findings are incorporated, and final static review found no remaining P0/P1. No Browser, Native, Go, helper, hardware, or executable test ran in the final pass; this is source and state-machine evidence, not production or heterogeneous-network proof.
|
||||
- A 2026-08-23 attempt to start the required one-Host/20-Viewer Browser smoke produced `RunCount=0`: the Windows Chrome launcher exited before its CDP endpoint was ready, so no room, route, media, or resource measurement ran. This is harness infrastructure evidence, neither a route pass nor a route failure; do not retry the unchanged launcher.
|
||||
- Exact source `6b87732` passed the required one-Host/20-Viewer local Browser smoke on Windows Node 24.19.0 / Chrome 151.0.7922.174, using 720p30 synthetic canvas media, endpoint cap `2`, a 30-second measurement window, and report SHA-256 `1347E036BB9AC35D51B4ED9B215290E742715128C7F3056D8FEB185CC84456D6`. All six checks passed: 20/20 Viewers had live clean upstreams and increasing decoded frames, Host and relay sender counts stayed at two, topology was coherent, and no orphan SFU publication appeared. Maximum authenticate-to-first-decoded latency was 958 ms; the final graph had two Host children and eighteen peer descendants. The application Node process consumed about 0.95 additional CPU seconds over the 54-second observation window, peaked near 284 MiB RSS, and settled near 162 MiB; isolated Chromium averaged 761% CPU over its valid 25.97-second process interval. The harness did not configure LiveKit or TURN, so their observed usage was zero and this loopback is not a public-network, SFU/TURN, quality, or endurance claim.
|
||||
- Current source TURN-admission unit and signaling tests cover independent peer and Host-SFU logical edges, shared capacity exhaustion, exact reserve/commit/drain/release identity, current-share cleanup, and graceful shutdown. This is local authorization evidence, not real coturn, network-media, or production-capacity proof.
|
||||
- Chrome 151 synthetic `1/3/5/8` and 720p30 runs preserved bounded fanout and decoding. A `9461e20`-era three-Viewer rerun kept Host2/Browser Viewer1, decoded every Viewer, and recovered a hard first-level relay departure in 5,380 ms; it did not exercise quality-triggered MBB. Sixteen-Viewer cap2/cap3 loopbacks decoded all Viewers and a ten-second follow-up recorded guarded sender and aggregate Chromium CPU evidence, but resolution/FPS remained low and the ordinary-PC data cannot rank caps, select product policy, or prove sustainable heterogeneous-network quality. See [peer-assisted media](./research/peer-assisted-media.md).
|
||||
- Chrome 151 with local LiveKit 1.13.5/client 2.22.0 proved one SFU/UDP root after `q,f` -> `q,h`: decoded frames advanced 3 -> 23, rendered frames reached 26, Host used one edge, leaves were clean, and TURN was absent. This is functional evidence only. See [low-server media routes](./research/low-server-media-routes.md).
|
||||
@@ -37,9 +35,9 @@ Capacity and routing entries below describe the exact tested source or release o
|
||||
|
||||
- Routing: verify current-release initial ingress, exact candidate first-frame commit and rollback, `peer-selected` expiry/failure, relay-ingress reparent with subtree retention, disconnect/effective-capacity drain, pause/resume, and bounded failure on real browser/media paths. Silent control partitions may wait 30 to 60 seconds for heartbeat detection before the default five-second grace; a non-paused decoded-frame stall may invalidate only that exact child edge.
|
||||
- Quality: production startup blur remains unclassified. One same-`balanced` local A/B retained route/PC/SSRC/track while 720p rose to 1080p, but natural ramp prevents causal, production, or SFU conclusions. Correlate Host capture/encode/send with Viewer receive/decode before changing policy.
|
||||
- Relay resources: current Browser source has the authenticated `1/2/3` endpoint-cap boundary and focused state coverage, while production `9461e20` remains Host2/ordinary Browser Viewer1 and rejects Viewer child2 regardless of advertised capacity. CPU/GPU/upload and heterogeneous-network measurements remain evidence, not authority to change the contract.
|
||||
- Room scale: accepted and current-source admission is 20 Viewers plus one Host; production remains eight by default. Focused controller coverage converges 20 Viewers under `C=1/2/3`, but the route release still needs one resource-limited Browser smoke for first-frame or bounded-failure behavior, endpoint copies, application CPU/memory, and SFU/TURN accounting.
|
||||
- SFU: production `9461e20` deploys ordered `q,h`, roots <=2, and Dynacast off. Those are release facts; current source uses one Host publication with exact Viewer subscriptions and no fixed root-count or room-wide lease rule. Real LiveKit lifecycle/JWT replay and shaped packet-flow, BWE downshift/recovery, resource, and SFU-fed first-child evidence remain open. Use Linux `tc` or an authorized public canary for per-leaf shaping, never CDP throttling.
|
||||
- Relay resources: source and production expose the authenticated `1/2/3` endpoint-cap boundary, and the 20-Viewer loopback observed maximum Host and relay active-media edges of two at cap `2`. CPU/GPU/upload and heterogeneous-network measurements remain diagnostics, not authority to change the contract.
|
||||
- Room scale: source and production admit 20 Viewers plus one Host, and focused plus local Browser convergence evidence covers that bound. A real public-network 1:20 session, quality, and sustained resource matrix remain open.
|
||||
- SFU: production uses one Host publication with exact Viewer subscriptions and no fixed root-count or room-wide lease rule. Real LiveKit lifecycle/JWT replay, shaped packet-flow, BWE downshift/recovery, resource use, and SFU-fed first-child evidence remain open. Use Linux `tc` or an authorized public canary for per-leaf shaping, never CDP throttling.
|
||||
- Audio: verify the 64/128/256 kbps Share settings, negotiated/observed bitrate, audible music quality, route changes, and game A/V synchronization. Bitrate settings are ceilings, not quality proof.
|
||||
- Observability: the UI and local stats plumbing are deployed, including identity-bound relayed-detail retention and export freshness guards, but target-browser availability and actual values remain unverified for Host SFU sender evidence, codec/fmtp and encoder implementation/power efficiency, media-source and encoded FPS, A/V playout/jitter/concealment, selected candidate endpoints, and bounded same-pair STUN-response observation. These fields diagnose and have no recovery authority; they do not by themselves prove hardware encode, synchronization quality, or route quality.
|
||||
- Mobile: Android/iOS remain Viewer-only. Autoplay, rotation, iOS lock-screen/page reclamation, background reconnection, and network changes need device evidence. AirPlay/system mirroring is Viewer-local output, not a portable in-app WebRTC output contract.
|
||||
|
||||
+1
-1
@@ -360,7 +360,7 @@ Token-free SFU standby prewarm 保持可选且不创建 participant、publicatio
|
||||
8. 当前发布只验收 Web Host、Viewer 和 browser relay。Native sender、capture helper 与 shared-encode executable 排在整体 roadmap 最后,不参与当前构建、路由验收或发布。
|
||||
9. 当前功能、NAT 与真实网络 TODO 完成后,再分别设计和交付公网服务器一键部署包与完全不依赖外部服务的本地 Host-server 包。
|
||||
|
||||
生产仍运行 `screener-v5`;route release source 使用 `screener-v7`。内部不兼容 wire/schema 原子切换,Git commit 承担回滚,不保留兼容实现。
|
||||
生产已运行 `screener-v7` route release `6b87732`。内部不兼容 wire/schema 原子切换,Git commit 与部署备份承担回滚,不保留兼容实现。
|
||||
|
||||
任何一步只实现当前消费者需要的接口。不得为未来账号、第三种媒体拓扑或原生 sender 预建抽象层。
|
||||
|
||||
|
||||
Reference in new issue
Block a user