Commit Graph

901 Commits (96d22abe99b64d87b71901cf989358351f35aa5d)
 

Author SHA1 Message Date
zijiren 96d22abe99
fix(webrtc): use public STUN by default (#427)
## Summary

- disable the built-in SyncTV STUN server by default across application,
Compose, image, environment, and Helm configuration
- default `webrtc.externalIceServers` to Cloudflare and Google public
STUN endpoints while preserving persisted overrides and explicit `[]`
- update deployment validation, tests, examples, and English/Chinese
documentation

Tailscale is not included because it publishes STUN endpoints through
its dynamic DERP map and does not provide a stable general-purpose
hostname suitable for this default.

## Testing

- `cargo fmt --all -- --check`
- `cargo test -p synctv-core --test global_settings_registry_tests`
- `cargo test -p synctv-core
test_runtime_settings_default_to_public_stun_servers`
- `cargo test -p synctv default_webrtc_config_disables_builtin_stun`
- `cargo check --workspace --all-targets`
- `bash scripts/validate-helm.sh`
- Compose configuration rendering
- `npm run validate:content`
- `npm run check`
- `git diff --check`
1 month ago
zijiren 8711158d60
refactor: remove low-value thin wrappers (#426)
## Summary

- remove unused compatibility APIs and low-value forwarding wrappers
across the workspace
- inline service, repository, provider, cluster, proxy, and protocol
paths while preserving existing behavior
- remove stale dependencies, metrics, tests, and SQLx metadata generated
for deleted queries

## Validation

- `cargo check --workspace --all-targets`
- `cargo fmt --all -- --check`
- `git diff --check`
- relevant test suites: 1,408 passed, 184 ignored
- broader test run: 2,286 passed
1 month ago
zijiren b74e8c279c
fix(room): enforce member-owned resource lifecycle (#425)
## Summary
- preserve room membership and owned resources across global bans while
blocking browsing and playback until unban
- clean up member-owned media and dynamic playlists on leave, kick, and
account deletion while preserving ordinary shared playlists
- enforce lifecycle checks for playback, history, dynamic browsing,
direct IDs, backend generation, publish keys, RTMP, and historical
dynamic ancestors
- serialize playback transitions with ban and lifecycle cleanup
transactions and emit realtime outbox events atomically

## Verification
- `make fmt-check`
- `make clippy-check`
- `make nextest-default` (5238 passed, 1596 skipped)
- 15 targeted ignored Testcontainers lifecycle/concurrency tests passed
- `make sqlx-prepare` with only changed offline query cache entries
retained
1 month ago
zijiren 77b8632124
feat(playlist): add browse access controls (#423) 1 month ago
zijiren 716a28087a
feat(presence): separate members and guests (#422)
## Summary

- split room, node, and global presence into authenticated member and
anonymous guest counts
- deduplicate member and guest actors independently while retaining
total connection counts
- update discovery ordering and realtime online-count messages to use
the separated values
- remove the previous mixed online-user field as a breaking protocol
change

Frontend: https://github.com/synctv-org/synctv-app/pull/41

## Verification

- make nextest-default (5231 passed)
- make clippy-check
- make proto-freshness
- cargo fmt --all -- --check
- git diff --check
1 month ago
zijiren 503880e6a1
chore(deps): update backend dependencies (#421)
## Summary
- update pinned backend dependencies and regenerate Cargo.lock
- keep intentional compatibility pins for bincode, testcontainers,
rand/sha2 aliases, and the combine patch
- update streaming encoder configuration and resolve current Clippy
compatibility

## Validation
- cargo check --workspace --all-targets
- cargo test --workspace --lib
- make nextest-default
- make clippy-check
- make proto-freshness
- make check-all-targets
- cargo fmt --all -- --check
- cargo audit --quiet
- cargo deny check
- cargo update --dry-run

All backend checks passed.
1 month ago
zijiren c80f660637
feat(cli): allow system room visibility updates (#420)
## Summary

- allow `synctv room visibility` to omit the actor and run as an
authenticated management-plane operation
- preserve optional `--username`, `--user-id`, and `--email` actor
selection for normal room permission enforcement
- keep the permission bypass confined to the management service and
reuse the same visibility update, cache invalidation, and guest
revocation behavior

Follow-up to #419.

## Validation

- `cargo fmt --all -- --check`
- `cargo check -p synctv-core -p synctv-management -p synctv`
- `cargo clippy -p synctv-core -p synctv-management -p synctv
--all-targets -- -D warnings`
- `cargo test -p synctv room_visibility` (3 passed)
- verified `synctv room visibility --help` shows actor selectors as
optional and still requires exactly one of `--public` or `--private`
1 month ago
zijiren 198cd5a9cb
feat: separate room visibility from guest settings (#419)
## Summary

- store room public visibility as a first-class database field
independent of password and guest settings
- expose visibility through client, management, HTTP, gRPC, CLI,
discovery, and room creation review flows
- add `synctv room visibility ROOM_ID --public|--private` for changing
existing rooms with an explicit actor
- deny anonymous guest access to private rooms while preserving
authenticated member access
- revoke existing guest sessions immediately when a room becomes private
without disconnecting authenticated members

## Validation

- `cargo fmt --all -- --check`
- `cargo clippy -p synctv-core -p synctv-api-common -p synctv-api-http
-p synctv-api-grpc -p synctv --all-targets -- -D warnings`
- `cargo clippy -p synctv-management -p synctv --all-targets -- -D
warnings`
- `cargo check -p synctv-core -p synctv-api-common -p synctv-api-http -p
synctv-api-grpc -p synctv`
- `cargo check -p synctv-management -p synctv`
- `cargo test -p synctv room_visibility`
- verified `synctv room visibility --help` renders the required actor
and exactly one of `--public` or `--private`
- targeted realtime bridge, guest principal, realtime event, and room
service tests
- real macOS client verification: changing a public room to private
terminated the guest connection in about two seconds with
`REALTIME_TERMINATION_CODE_GUEST_ACCESS_REVOKED`; authenticated users
remained connected
1 month ago
zijiren 4a5f7630ad
feat: add publish key lifecycles (#418)
## Summary

- add single-use, reusable expiring, and permanent RTMP publish keys
- validate lifecycle and expiration combinations in the core service
- expose lifecycle fields through HTTP, management gRPC, and CLI
- keep JTI consumption limited to single-use keys

## Validation

- `cargo fmt --all -- --check`
- `make clippy-check`
- `make check-all-targets`
- `cargo test -p synctv-core service::publish_key::tests`
1 month ago
zijiren 90b8abf1e6
fix(auth): warn on weak JWT secrets (#417)
## Summary

- keep JWT minimum length and character-class requirements as blocking
validation errors
- downgrade heuristic quality checks such as low diversity, repeated
patterns, and low entropy to startup warnings
- emit configuration warnings after logging initialization, with stderr
fallback for config validation and unknown settings
- count Unicode characters consistently in secret length, entropy, and
pattern checks

## Tests

- `cargo test -p synctv-core service::auth::jwt::tests`
- `cargo test -p synctv app_config::validation::tests`
- `cargo test -p synctv config_loader::tests`
- `cargo check -p synctv`
- `cargo fmt --all -- --check`
1 month ago
zijiren 6b884e9964
fix(bilibili): restore subtitles and dynamic live danmaku (#415)
## Summary
- Propagate dynamic playlist identity into Bilibili playback generation
and expose room-scoped live danmaku SSE.
- Resolve each SSE connection against the current playlist target and
provider instance, retaining the playlist credential owner.
- Restore loopback-only PostgreSQL and Redis ports in the development
Compose profile so host-based `make dev-serve` can connect.

## Validation
- `cargo clippy -p synctv-core -p synctv-api-common -p synctv-api-http
--all-targets -- -D warnings`
- `cargo test -p synctv-core
dynamic_live_playback_has_a_live_danmaku_track`
- `cargo test -p synctv-api-common
dynamic_live_danmaku_provider_converts_to_room_scoped_endpoint`
- `cargo test -p synctv-api-http`
- `docker compose -p synctv-dev -f docker-compose.dev.yml config -q`
1 month ago
zijiren 5afaad79ff
fix(realtime): separate presence events from disconnects (#416)
## Summary
- Route `UserLeft` through room presence delivery only.
- Reserve disconnect signals and access-revocation events for
terminating realtime sessions.
- Keep cross-replica presence coverage and explicitly release E2E test
infrastructure.

## Testing
- `make nextest`
- `cargo nextest run -p synctv-api-common --no-fail-fast`
- `cargo nextest run -p synctv-realtime --no-fail-fast`
- `cargo nextest run -p synctv-api --test websocket_test
websocket_e2e::test_ws_cross_replica_same_user_partial_disconnect_does_not_emit_user_left
--run-ignored ignored-only --no-fail-fast`
1 month ago
zijiren 980c409e26
chore(docker): keep database and cache internal (#414)
## Changes
- Remove PostgreSQL and Redis host port publications from production and
development Compose files.
- Keep application connectivity through the existing Compose networks
and service names.

## Validation
- docker compose -f docker-compose.dev.yml config --quiet
- git diff --check
1 month ago
zijiren d560b8efce
fix: harden Bilibili playback reliability (#412)
## Summary

- Treat explicit null collection fields in Bilibili VOD playback
responses as empty collections.
- Cover DASH streams, backup URLs, Dolby audio, supported formats, DURL
responses, subtitles, video pages, UGC collections, and PGC episodes.
- Resolve Bilibili DASH resources from versioned playback metadata and
provide every equivalent CDN URL to the existing candidate executor.
- Prefer the URL selected by the player, then retry primary and backup
CDNs before committing the downstream response.

## Root cause

Bilibili occasionally emits explicit null for fields normally
represented as JSON arrays, which caused playback/start deserialization
errors. Proxy DASH resource requests also used a single CDN even though
the provider response included backup URLs.

## Validation

- cargo fmt --all -- --check
- cargo check for synctv-api-common, synctv-api-http, and
synctv-api-grpc
- synctv-media-providers Bilibili tests: 91 passed
- synctv-core Bilibili tests: 17 passed, 2 ignored
- candidate executor tests: 2 passed
- Real playback/start, proxy MPD, Range request, CDN fault injection,
dev build, and dev smoke checks
1 month ago
zijiren dd80379d67
feat(provider): improve media discovery and direct playback (#411) 1 month ago
zijiren 2f61d0e8de
release: prepare v1.0.2 (#408)
## Summary

- bump the Cargo workspace to 1.0.2
- synchronize Helm chart and documentation versions

## Verification

- `make fmt-check`
- `make clippy-check`
- `make nextest-default` (5,186 passed)
- `make nextest-ignored` (1,585 passed)
- `make validate-helm`
1 month ago
E-larex c30d3e40b1
fix(oauth2): accept trailing slash in OIDC issuer (#401)
Fix OIDC ID Token validation when the provider returns an issuer with a
trailing slash.

SyncTV removes trailing slashes from the configured issuer, but
`jsonwebtoken` previously performed an exact issuer check before
SyncTV's normalized issuer comparison. This caused valid tokens from
providers such as Authentik to fail with `InvalidIssuer`.

The JWT validation now accepts both trailing-slash variants of the same
issuer while continuing to reject unrelated issuers.

Added RS256/JWKS regression tests covering both accepted configurations
and a different-issuer rejection case.
1 month ago
zijiren 9e0e0c280e
chore(dev): remove background server targets (#407)
## Summary

- remove the `dev-start` and `dev-stop` Makefile targets and related
documentation
- keep `dev-serve` as the foreground development server entry point
- make the provider smoke test own and clean up its server process
- keep `dev-down` and `dev-clean` scoped to Compose services

## Verification

- `bash -n scripts/dev-e2e-smoke.sh`
- Makefile dry runs for `dev-serve`, `dev-down`, and `dev-clean`
- `make help` target inspection
- `git diff --check`
- existing development backend health check
1 month ago
zijiren b6acab535e
fix: type playback identities and stabilize FNOS playback (#400) 1 month ago
zijiren a6c0af59ff
fix(settings): recover stale version fences (#399)
## Changes
- roll back local and Redis reservations when a settings transaction
aborts
- atomically reconcile stale committed fences against the database
version
- repair runtime-setting fences during startup and before writes
- retry paths now refresh fence state after SQL optimistic-lock
conflicts

## Verification
- cargo test -p synctv-core --lib
- cargo check --workspace
- cargo clippy -p synctv-core -p synctv-api-common --all-targets -- -D
warnings
- real HTTP regression with Redis fence seeded above the database
version
1 month ago
zijiren 0043ec8b2e
feat(providers): unify discovery and playback routing (#397)
## Summary

- expose server-side provider discovery and listing for media and
dynamic playlist variants
- keep provider-specific playback proxy policy inside each provider and
add meaningful prefer/only controls
- harden Emby item classification, cloud/NAS playback routing,
account-bound credentials, and unknown source-config fields
- add real Docker fixtures and end-to-end smoke coverage for Nextcloud,
Seafile, Emby, Jellyfin, OpenList, and provider playback

Related App PR: https://github.com/synctv-org/synctv-app/pull/18

## Testing

- cargo +nightly check --workspace --locked
- cargo +nightly test -p synctv-media-providers seafile::client::tests
--locked
- bash -n scripts/dev-e2e-smoke.sh
- scripts/dev-e2e-smoke.sh with real Docker services and playback URL
downloads
- git diff --check
1 month ago
zijiren 9bc010c568
fix: classify forced realtime disconnects (#395)
## Summary

- send a typed realtime termination message before server-initiated
WebSocket disconnects
- restore the view_playback_history permission bit across effective
permissions and runtime settings round trips
- remove the unused common ErrorCode enum and document the dedicated
termination codes

## Validation

- make nextest: 6715 passed
- make clippy
- git diff --check
1 month ago
zijiren da1abd1a68
feat: add recoverable resource deletion lifecycle (#394)
## Summary

- Add recoverable soft deletion for users, rooms, playlists, media, and
chat messages, with retention-based physical cleanup.
- Hide deleted users and owned resources from active API, room,
playback, messaging, and realtime paths while preserving restoration
metadata.
- Add user lifecycle administration across HTTP, gRPC, management
runtime, and SyncTV CLI, including deleted-user listing and restore
operations.
- Add lifecycle migration, cleanup orchestration, audit fields,
resource-change events, and refreshed SQLx offline metadata.

## Design

- Model account, administrator, system, room, and user deletion sources
explicitly so cascade ownership and audit history remain deterministic.
- Release email and OAuth identity occupancy during deletion;
restoration reclaims available identities and reports conflicts
according to restore options.
- Preserve recoverable aggregate rows during the retention window,
remove ephemeral membership and playback state immediately, and purge
expired data in dependency order.
- Wait for realtime observation acknowledgements before publishing
lifecycle changes to avoid subscription registration races.

## Verification

- `make nextest`: 6707 passed, 0 skipped
- `make clippy`: passed for the workspace and all targets
- `make clippy-check`: passed
- `cargo fmt --all -- --check`: passed
- `git diff --check`: passed
2 months ago
zijiren c0e3c2dae5
fix(docs): preserve TAR end-of-archive blocks (#389)
## Summary
- Allocate an explicit TAR output buffer sized to the written bytes plus
two 512-byte end blocks.
- Copy the archive payload into the buffer so TAR downloads always
include the required zero blocks.

## Testing
- `npm run validate` from `docs/`
- TAR end-block assertion with `tar-js`
2 months ago
zijiren e42aed8b9f
fix(docs): package Compose environment files as TAR (#388)
## Summary
- Fix Compose environment archive filenames for issue #385.
- Provide a lazy-loaded TAR download containing all three environment
files.
- Use Starlight code blocks for environment previews and built-in copy
controls.
- Document Linux hidden files and the `ls -a` command after extraction.

## Testing
- `npm run validate` (from `docs/)
2 months ago
zijiren 8208b5a27f
fix(account): skip standalone room outbox events (#387)
## Summary
- persist deleted-room events only when the prepared event requires the
realtime outbox
- keep local post-commit fanout for standalone deployments
- prevent account closure from failing when cluster mode is disabled

## Verification
- cargo fmt --all -- --check
- cargo check -p synctv-api-common -p synctv-api-grpc -p synctv-api-http
- cargo test -p synctv-core deleted_room_outbox_config --lib
2 months ago
zijiren f4665ebea4
Merge pull request #382 from synctv-org/codex/apple-review-docs
docs(apple): explain Developer ID browser authentication
2 months ago
zijiren233 6eeb974c9b
docs(apple): explain Developer ID browser authentication 2 months ago
zijiren 4b1e677d21
Merge pull request #381 from zijiren233/codex/fix-compose-validation-fallback
fix(helm): validate configurable compose image
2 months ago
zijiren233 daeb66b1b5
fix(helm): validate configurable compose image 2 months ago
zijiren eb8968384e
Merge pull request #380 from zijiren233/codex/fix-compose-image-fallback
fix(compose): make image tag configurable
2 months ago
zijiren233 917ea99946
fix(compose): make image tag configurable 2 months ago
dependabot[bot] 8160c113a5
chore(deps): bump the npm_and_yarn group across 1 directory with 14 updates (#379)
Bumps the npm_and_yarn group with 8 updates in the /docs directory:

| Package | From | To |
| --- | --- | --- |
| [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) | `6.2.1` | `7.2.0` |
| [sharp](https://github.com/lovell/sharp) | `0.34.5` | `0.35.3` |
| [dompurify](https://github.com/cure53/DOMPurify) | `3.4.2` | `3.4.13` |
| [fast-uri](https://github.com/fastify/fast-uri) | `3.1.0` | `3.1.5` |
| [ip-address](https://github.com/beaugunderson/ip-address) | `10.2.0` | `10.4.0` |
| [mermaid](https://github.com/mermaid-js/mermaid) | `11.14.0` | `11.16.1` |
| [svgo](https://github.com/svg/svgo) | `4.0.1` | `4.0.2` |
| [ws](https://github.com/websockets/ws) | `8.20.0` | `8.21.3` |



Updates `astro` from 6.2.1 to 7.2.0
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@7.2.0/packages/astro)

Updates `sharp` from 0.34.5 to 0.35.3
- [Release notes](https://github.com/lovell/sharp/releases)
- [Commits](https://github.com/lovell/sharp/compare/v0.34.5...v0.35.3)

Updates `devalue` from 5.8.0 to 5.9.0
- [Release notes](https://github.com/sveltejs/devalue/releases)
- [Changelog](https://github.com/sveltejs/devalue/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/devalue/compare/v5.8.0...v5.9.0)

Updates `dompurify` from 3.4.2 to 3.4.13
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.2...3.4.13)

Updates `esbuild` from 0.27.7 to 0.28.1
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.7...v0.28.1)

Updates `fast-uri` from 3.1.0 to 3.1.5
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.0...v3.1.5)

Updates `ip-address` from 10.2.0 to 10.4.0
- [Release notes](https://github.com/beaugunderson/ip-address/releases)
- [Commits](https://github.com/beaugunderson/ip-address/compare/v10.2.0...v10.4.0)

Updates `js-yaml` from 4.1.1 to 4.3.1
- [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.1/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.1...4.3.1)

Updates `mermaid` from 11.14.0 to 11.16.1
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Commits](https://github.com/mermaid-js/mermaid/compare/mermaid@11.14.0...mermaid@11.16.1)

Updates `nanoid` from 3.3.12 to 3.3.18
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/3.3.18/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.12...3.3.18)

Updates `postcss` from 8.5.13 to 8.5.26
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.13...8.5.26)

Updates `svgo` from 4.0.1 to 4.0.2
- [Release notes](https://github.com/svg/svgo/releases)
- [Commits](https://github.com/svg/svgo/compare/v4.0.1...v4.0.2)

Updates `vite` from 7.3.2 to 8.2.1
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.2.1/packages/vite)

Updates `ws` from 8.20.0 to 8.21.3
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.20.0...8.21.3)

---
updated-dependencies:
- dependency-name: astro
  dependency-version: 7.2.0
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: sharp
  dependency-version: 0.35.3
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: devalue
  dependency-version: 5.9.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: dompurify
  dependency-version: 3.4.13
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: esbuild
  dependency-version: 0.28.1
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: fast-uri
  dependency-version: 3.1.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: ip-address
  dependency-version: 10.4.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: js-yaml
  dependency-version: 4.3.1
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: mermaid
  dependency-version: 11.16.1
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: nanoid
  dependency-version: 3.3.18
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: postcss
  dependency-version: 8.5.26
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: svgo
  dependency-version: 4.0.2
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: vite
  dependency-version: 8.2.1
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: ws
  dependency-version: 8.21.3
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2 months ago
zijiren 11f1e8effc
release: prepare v1.0.1
Merge the backend release version synchronization.
2 months ago
zijiren 1716af8321
feat(oauth2): add provider modes and native Apple flow
Merge reviewed OAuth provider mode and native Apple flow changes.
2 months ago
zijiren233 794b4d158f
ci: align checks with repository policies 2 months ago
zijiren233 d81e731203
docs: add Compose environment generator 2 months ago
zijiren233 343bd027cb
test: use portable ffmpeg build 2 months ago
zijiren233 0dcc27feee
docs: fix client download links 2 months ago
zijiren233 5425eaf436 chore: replace synctv-org backend with SyncTV v1.0.0 2 months ago
zijiren233 c04106b55a fix: docker build --version 11 months ago
zijiren233 394e065083 chore: bump go mod 11 months ago
zijiren233 d0c433c030 fix: docker build use go cross 11 months ago
zijiren233 c6be2bc40f feat: enable freebsd cgo 11 months ago
zijiren233 13c93e17c9 feat: echo commit 11 months ago
zijiren233 254a621b3b fix: build config 11 months ago
zijiren233 b08b584e66 fix: build script 11 months ago
zijiren233 ff29d6ef8b fix: build target remove frebsd amd/arm and netbsd 1 year ago
zijiren233 a2ca2fd27f chore: bump go mod 1 year ago
zijiren233 aa27d0051e fix: ci lint 1 year ago