Skip to content

feat: optional access key - #71

Merged
TenGosc007 merged 20 commits into
mainfrom
feat/optional-access-key
Oct 16, 2026
Merged

TenGosc007 merged 20 commits into
mainfrom
feat/optional-access-key

Conversation

@TenGosc007

Copy link
Copy Markdown
Collaborator

Summary

initialize(accessKey, libraryId) no longer requires a non-empty API access
key — public playback needs no credentials. Passing a blank key (or
null/undefined) selects playback-only mode on both platforms:
management, upload, and broadcast calls report not-initialized errors until
a real key is provided.

On iOS a blank key reaches the SDK as nil, so public playback sends no
AccessKey header. On Android the bridge no longer rejects blank keys —
upstream BunnyStreamConfig still requires a non-blank key (tracked by a
TODO in BunnyStreamPlayerModule), so Android keyless playback unblocks
automatically with a future native SDK release.

The example app gates features accordingly: Direct video play and resume
positions work with just a library ID, while library lists, uploads, and
broadcasting stay gated on the API key. Docs updated to describe the
playback-only mode.

Type of Change

  • Bug fix
  • Feature
  • Documentation
  • Refactor or cleanup
  • CI/build/release
  • Breaking change

Affected Areas

  • TurboModule / native modules
  • API client
  • Upload
  • Player (VOD)
  • Player (live)
  • Broadcaster
  • Codegen / spec files
  • Example app
  • Documentation
  • Build or package configuration

Testing

  • yarn typecheck
  • yarn lint
  • yarn test — 261 tests incl. new keyless-initialization and
    playback-only example tests
  • Android example builds (yarn android in example/) —
    :bunny.net_stream-react-native:assembleRelease
  • iOS example builds (yarn ios in example/)
  • Manual playback/upload/broadcast test
  • Not run, reason: iOS verified by swiftc -parse on changed files and
    upstream SDK source review; manual playback verification pending on
    device.

Library User Impact

Public API change: initialize accepts string | null | undefined for
accessKey (previously string, blank values threw). A blank key selects
playback-only mode — BunnyStreamApi, BunnyStreamUpload, and
BunnyStreamBroadcaster report not-initialized errors until a real key is
provided. Fully backward compatible: existing callers with a real key see
no behavior change.

Platform note: iOS keyless playback works today; Android keyless playback
is unblocked at the bridge but still requires an upstream
bunny-stream-android change (BunnyStreamConfig rejects blank keys) —
documented via a TODO in BunnyStreamPlayerModule.kt.

AI Assistance

  • No substantial AI assistance was used.
  • AI helped with this PR; I reviewed and understand the final changes.

Checklist

  • The PR is focused on one clear change.
  • native-sdk-baselines.json points to a public, merged native SDK commit or tag when native APIs are required.
  • Public API or behavior changes are documented (README / docs).
  • Tests or manual verification are included where appropriate.
  • No secrets, access keys, private URLs, certificates, or provisioning profiles are included.

@TenGosc007 TenGosc007 self-assigned this Oct 14, 2026
@TenGosc007
TenGosc007 changed the base branch from main to chore/skd-update October 14, 2026 09:36
@TenGosc007
TenGosc007 added this pull request to stack #72 October 14, 2026 09:36
@TenGosc007
TenGosc007 marked this pull request as ready for review October 15, 2026 18:32
Base automatically changed from chore/skd-update to main October 16, 2026 11:45
TenGosc007 and others added 14 commits October 16, 2026 13:45
Public playback needs no API credentials: initialize('', libraryId)
selects playback-only mode, while management, upload, and broadcast
calls report not-initialized errors until a real key is provided.

On iOS a blank key reaches the SDK as nil, so public playback sends no
AccessKey header. On Android the bridge no longer rejects blank keys;
upstream BunnyStreamConfig still requires a non-blank key, tracked by a
TODO in BunnyStreamPlayerModule.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The example now initializes with just a library ID — an empty access key
selects playback-only mode. Home gates features accordingly: direct play
and resume positions need only the library ID, while library lists,
uploads, and broadcasting stay gated on the API key. Settings lets the
key be left empty and explains the difference.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Bump the Android baseline to pull/83/head (3bd37c9), staged locally as
net.bunny:*:4.2.0-pr83. The nullable BunnyStreamConfig.accessKey there
means playback-only initialization now works on Android: the bridge maps
a blank key to null and the upstream SDK restricts keyless instances to
the public /play endpoints, failing management calls with a terminal
InvalidState before any network I/O.

publishToMavenLocal requires GPG signing upstream, so
scripts/publish-android-sdk.mjs now builds the modules and stages
unsigned AAR+POM+module metadata into ~/.m2/repository directly
(including :recording, which the old script skipped). mavenLocal() is
registered last in android/build.gradle so released versions still
resolve from Maven Central; -PbunnyStreamSdkVersion overrides the pin.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…here

Direct live play mirrors the upstream Android demo play-a-stream-by-id
flow: a new modal on the Home screen accepts a stream ID (defaulting to
the configured library) and opens the live player without listing, which
keeps it usable in playback-only mode — public live streams resolve via
the SDK /live/{id}/play endpoint.

Also fixes token-auth signing keys leaking from .env directly: Player,
VideoList, and LiveStreams screens now sign playback tokens with the
configured (stored) access key, so a key entered via Settings is honored.
The live player getLiveStream enrichment is skipped entirely in
playback-only mode instead of logging a missing-key failure, and the
unconfigured empty-state message now says listing needs an API key.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
DirectVideoPlayModal and DirectLivePlayModal were near-identical (load
last-used values, field + library inputs, cancel/confirm row). Extract the
common UI and state into DirectPlayModal; the wrappers now only supply the
labels, env defaults, and their own storage keys.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The key field placeholder now says it can be left empty, and the hint
below it reflects the current mode: full access with a key, playback-only
without one.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
key={row[0]} produced an undefined key — and the React "unique key"
warning — whenever the speeds list was short enough to leave an empty
second row.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
src/__tests__/example.playbackErrors.test.ts imports ACCESS_DENIED_MESSAGE
and NOT_FOUND_MESSAGE via requireActual; unexporting them broke the suite.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@TenGosc007
TenGosc007 force-pushed the feat/optional-access-key branch from 369d260 to e071052 Compare October 16, 2026 11:45
TenGosc007 and others added 6 commits October 16, 2026 15:20
Bumps mavenVersion to a mavenLocal build of main@641565e (merge of #87),
which composes the User-Agent as platform UA + bunny-stream-android/<ver>
(<device type>) + integrator. The wrapper already forwards its version as
the integrator, so requests now carry e.g. Dalvik/2.1.0 (...)
bunny-stream-android/4.2.1-pr87 (mobile) bunny-stream-react-native/<ver>.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
PR #88 merged into main at 08bff6a after 4.2.0 was tagged, superseding
the previous 4.2.1-pr87 pin (641565e). This local mavenLocal build
carries both #87 (User-Agent format) and #88 (Enterprise DRM limits
on Widevine L3 devices).
Intersect setVideoQuality overrides with the SDK's L3 rendition cap so a
quality request cannot exceed what the license allows — "auto" previously
wiped the cap entirely. Surface the SDK's pre-load security-level refusal
as a structured onError (nativeCode ERROR_CODE_DRM_SYSTEM_ERROR) instead
of only a message string, so JS can classify it as terminal.

The example maps the media3 DRM error family to a "can't be played on
this device" state with no retry — the hardware level cannot change.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Document the new drm/ package in ARCHITECTURE.md, describe the Widevine
L3 cap and security-level refusal in the secure-playback and
handle-errors guides, and note the cap intersection on the public
VideoQualityPreference type. Renames the view helper to drmMaxVideoSize
to mirror the SDK's naming.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
4.2.1 is now published to Maven Central (tag 08bff6a) and already
contains the PR #87 User-Agent format and PR #88 Widevine L3 handling,
so the local 4.2.1-pr88 mavenLocal pin is no longer needed.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@TenGosc007
TenGosc007 merged commit 2e6819d into main Oct 16, 2026
3 checks passed
@TenGosc007
TenGosc007 deleted the feat/optional-access-key branch October 16, 2026 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants