v1.0.0: breaking-release cut for remaining public-API and credential migrations

Author: teng-linCreated Sep 6, 2026Updated Sep 6, 2026
Labelsenhancementdo-not-implement-yetP2

Why this exists

v1 remaining work used to live in #2181, #2182, and #2319. Those issues are stale against current main (after #2355 / #2375). This epic is the v1.0.0 breaking-release checklist.

Implement from committed docs, not from the closed issues and not from uncommitted docs/plans/ files:

Latest published release at the 2026-09-06 audit: v0.8.2. A source comment or _deprecation.py row that says since=0.9.0 is not a shipped notice. The breaking release cannot be the same release that first introduces a warning.

ADR-0039 is already accepted. This epic is the breaking implementation and release gate.

Children

  • #2377 — Android/Web credential types, client.auth, refresh_auth(), from_storage loader selection, AuthTokens freeze
  • #2378 — remove NotebookLMClient.rpc_call and the Android Web compatibility sidecar
  • #2379 — default-behavior flips that have their own notice windows (artifact absence, bound Web settings, mind-map terminal, download prefetch). These may slip past v1.0.0.

Eligibility before any breaking PR lands

  • A stable release after v0.8.2 has shipped every registered warning this cut will remove (client_legacy_constructor_options, client_legacy_from_storage_options, client_rpc_call_web, client_rpc_call_android, artifact_poll_follower_options, artifact_poll_follower_callback, auth_tokens_replace_cookie_jar, decoder-factory keys, mcp_confirmed_name_references, plus any new credential-surface warnings)
  • One MINOR interval has elapsed after that notice release
  • Re-run the GitHub release/tag audit immediately before scheduling v1.0.0
  • scripts/audit_public_api_compat.py --check-stale allowlist matches actual reported breaks (no invented allowances for private/behavioral shapes)
  • scripts/check_deprecation_targets.py is green; the v1 runway table in tests/_guardrails/_v100_breaks.py is drained
  • Clean-process Android: import notebooklm, construct, open, refresh, and typed namespace calls load no notebooklm._web* modules and make no NotebookLM homepage / batchexecute request

1. Credential surface (see #2377)

Today every client, including backend="android", takes a mutable Web-shaped AuthTokens and from_storage(backend="android") still GETs the NotebookLM homepage to fill CSRF/session fields for the deprecated sidecar.

At v1:

  • Direct construction is NotebookLMClient(credential: AuthTokens | AndroidMasterToken, *, config=None)
  • Backend comes from config.backend / NOTEBOOKLM_BACKEND / Web default; a credential never selects the backend
  • Web + AndroidMasterToken, or Android + AuthTokens, raises ConfigurationError before filesystem, extras, or network
  • Android from_storage reads master_token.json only; ignores NOTEBOOKLM_AUTH_JSON; no cookie file; no homepage GET
  • client.auth is immutable Web AuthTokens or secret-free AndroidAuth (email, android_id)
  • refresh_auth() returns None; Android re-mints bearer only; allow_headless=True is Web-only
  • get_account_authuser() raises UnsupportedOperationError on Android
  • ADR-0016’s “everyone aliases the same mutable AuthTokens” rule is superseded (logger name notebooklm._core stays)

2. Raw RPC escape hatch (see #2378)

0.x already has client.raw.call / unary / unary_stream and warns on rpc_call. v1 must:

  • Delete NotebookLMClient.rpc_call
  • Delete _client_compat.LazyWebSidecar and build_compatibility_runtime
  • Android clients that never used the hatch must never materialise Web Kernel / RpcExecutor / cookies

Replacement: Web client.raw.call(RPCMethod, params); Android client.raw.unary / unary_stream. Mixed use is two clients.

3. Freeze AuthTokens (lands with #2377)

Remove the 0.x cookie/I/O compatibility surface. Destination shape is ADR-0032: frozen initial_cookies: CookieJar plus scalars. CookieJar stays an ordered sequence, not a Mapping.

  • Remove AuthTokens.from_storage(...) (warning shipped v0.8.1)
  • Remove sync AuthTokens(..., storage_path=..., cookie_jar=None) storage/network __post_init__ (warning shipped v0.8.1)
  • Remove flat_cookies (warning shipped v0.8.1)
  • Remove replace_cookie_jar() (source warning only; needs a shipped release)
  • Remove fields/properties cookies, cookie_jar, cookie_snapshot, jar, cookie_header, cookie_header_for
  • Class-signature allowlist for the shape change (cookies/cookie_jarinitial_cookies)

4. Other scheduled v1 removals (this epic; no extra design)

Constructor / factory

  • Remove non-default flat tuning keywords on NotebookLMClient(...) (timeout, keepalive, retry ceilings, limits, upload/RPC concurrency, upload_timeout, on_rpc_event, cookie_saver/cookie_rotator, chat_timeout, chat_response_max_bytes, import_research_timeout, …). Replacement: config=ClientConfig(...) with notebooklm.options groups. auth/credential stay outside config. Registry: client_legacy_constructor_options (unshipped).
  • Same for from_storage(...) flat tuning. path, profile, allow_headless remain loader inputs. Registry: client_legacy_from_storage_options (unshipped).

Artifact polling

  • wait_for_completion followers use their own timeout/interval/not-found options instead of the first waiter’s. Registry: artifact_poll_follower_options (unshipped).
  • Follower on_status_change receives every observed status, not final-only. Registry: artifact_poll_follower_callback (unshipped).

Public Web-row decoder factories (unshipped since=0.9.0 warnings)

  • Artifact.from_api_response / Artifact.from_mind_map
  • Collection.from_api_response / Label.from_api_response / Notebook.from_api_response
  • ShareStatus.from_api_response / SharedUser.from_api_response
  • Source.from_api_response / Source.from_row

Replacement: typed client.* APIs. There is no supported public raw-row decoder.

MCP confirmation

  • A confirming mutation must resubmit canonical notebook_id and target IDs from the needs_confirmation preview. Names/partial IDs are rejected. Registry: mcp_confirmed_name_references (unshipped). NOTEBOOKLM_MCP_STRICT_IDS=1 already rejects names in 0.x.

Client factory / profile paths (warnings already shipped)

  • Remove await NotebookLMClient.from_storage(...) (__await__; warned since v0.5.0). Use async with.
  • Remove pre-profiles home-root fallback (~/.notebooklm/storage_state.json outside profiles/<name>/; warned since v0.8.1).

Misnamed public fields (docs-only / property warning already shipped)

  • Remove ChatReference.answer_start_char / answer_end_char (use fragment_start_char / fragment_end_char)
  • Remove Notebook.modified_at (use last_viewed_at)
  • Remove NotebookMetadata.modified_at (property; warned since v0.8.1)

Private persistence facade

  • Delete src/notebooklm/_auth/storage.py once first-party imports are gone. Canonical writes already live in ProfileStore / credential_io (ADR-0034). This is not a public API break; do not invent an allowed_breaks row for it.

5. Independently gated defaults (see #2379)

Do not flip these just because v1.0.0 happens. Each needs its own shipped notice (or preview) and interval. If ineligible, keep the 0.x default past v1.

  • Artifact get / get_or_none incomplete no-hit, and Android get_prompt(require_complete=False)
  • Omitted Web request settings: live env vs construction-bound
  • Web waited interactive mind-map hydration after FAILED/REMOVED
  • Raw download-prefetch keywords on download_*

Out of scope

  • Do not implement ClientAuth / ClientAuthSnapshot / public LiveAuthState from #2181 / #2182
  • Do not make CookieJar a Mapping
  • Do not add MCP/REST tools for namespace parity
  • Do not silently change 0.x Android bootstrap (homepage GET + Web AuthTokens) before this cut
  • Do not treat a source comment or unreleased registry row as shipped warning evidence