From be5246f67216ebb9176ce819c29dbc232bf049fb Mon Sep 17 00:00:00 2001 From: givemethatsewon Date: Fri, 19 Jun 2026 01:49:20 +0900 Subject: [PATCH] Sync Colab skill auth docs --- README.md | 2 +- docs/01_session_management.md | 3 ++- skills/colab-operator/SKILL.md | 14 +++++++------- tests/test_readme.py | 11 +++++++++++ 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index da4a972..d61c6cb 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ Run `colab --help` to view specific options, defaults, and detailed he | `colab update [--install]` | Check for a newer release (and optionally upgrade the CLI in place) | ### Global Options -* `--auth {oauth2,adc}` — Authentication strategy for the Colab API (default: `adc`). +* `--auth {oauth2,adc}` — Authentication strategy for the Colab API (default: `oauth2`). * `-c, --client-oauth-config PATH` — Path to public OAuth client credentials configuration (default: `~/.colab-cli-oauth-config.json`). * `--config PATH` — Path to local session metadata storage (default: `~/.config/colab-cli/sessions.json`). * `--logtostderr` — Direct debug logging output to stderr. diff --git a/docs/01_session_management.md b/docs/01_session_management.md index 189cbe0..b66e6eb 100644 --- a/docs/01_session_management.md +++ b/docs/01_session_management.md @@ -1,5 +1,6 @@ --- log: +2026-06-19: Synced the implementation details with the current auth architecture. The default OAuth2 provider now uses the remote copy-paste flow, and ADC remains available via `--auth=adc`; the old local-server OAuth wording was stale after the 2026-06-11 automation/auth update. 2026-06-15: Switched the keep-alive daemon from the `colab.pa.googleapis.com` `RuntimeService/KeepAliveAssignment` RPC to a Tunnel Frontend HTTP ping (`GET /tun/m//keep-alive/` with `X-Colab-Tunnel: Google`) on `colab.research.google.com`. The RPC required `serviceusage` consumer access to Colab's internal project `1014160490159`, which ordinary user accounts lack, so every external user hit HTTP 403 `USER_PROJECT_DENIED` and their CLI sessions were idle-pruned within minutes (issue #14). Reproduced live with a third-party account; verified the tunnel ping is accepted by the same bearer-token credential that already works for `assign`. A `ReadTimeout` on the ping is treated as success (TFE records activity before forwarding to the often-non-responding VM). Generalized the pre-flight remediation messaging away from the now-irrelevant `colaboratory`/`pa.googleapis.com` framing, and removed the dead grpc-web client-registry/API-key code. 2026-06-10: Replaced the POSIX-only `fcntl.flock` file locking in `_LockedFileStore` with the cross-platform `filelock` library (reported broken on Windows). Reads use `ReadWriteLock.read_lock()` (shared) and writes use `write_lock()` (exclusive), preserving the original `LOCK_SH`/`LOCK_EX` semantics. The lock is constructed with `is_singleton=False` so two `StateStore` instances for the same path in one process don't collapse into a single reentrant lock (which would raise `RuntimeError` on multi-threaded write contention). Added shared-read, cross-process exclusion, and multi-thread/multi-process regression tests. --- @@ -87,7 +88,7 @@ To prevent Colab VMs from being deleted due to idle timeouts (standard is ~90 mi - **Resource Usage**: Add real-time resource usage (CPU/RAM/GPU) to the `status` output by executing a diagnostic snippet on the VM. ## Implementation Details -- **Authentication**: Uses `google-auth-oauthlib` to perform a local server OAuth flow. +- **Authentication**: Uses `google-auth-oauthlib` for the default OAuth2 remote copy-paste flow, or Application Default Credentials when `--auth=adc` is selected. - **Global Flags**: - `-c`, `--client-oauth-config`: Path to the client secrets JSON file (default: `~/.colab-cli-oauth-config.json`). - `--config`: Path to the session state JSON file (default: `~/.config/colab-cli/sessions.json`). diff --git a/skills/colab-operator/SKILL.md b/skills/colab-operator/SKILL.md index 30d2539..4498dcf 100644 --- a/skills/colab-operator/SKILL.md +++ b/skills/colab-operator/SKILL.md @@ -26,8 +26,8 @@ by running `uv tool install google-colab-cli` or `pip install google-colab-cli`. - **`colab` is fire-and-forget.** Each command authenticates, does one thing, and exits. A detached background daemon (spawned by `colab new`) handles keep-alive; you don't manage it. ## Authentication (the #1 thing that blocks agents) -- The global flag is `--auth={adc,oauth2}` and the **default is `adc`** (Application Default Credentials). It must come *before* the subcommand: `colab --auth=adc new -s x`. -- **ADC setup** (most reliable for headless/agent use). The Colab backends need a specific scope set, so re-mint ADC with all four scopes: +- The global flag is `--auth={oauth2,adc}` and the **default is `oauth2`**. It must come *before* the subcommand: `colab --auth=adc new -s x`. +- **ADC setup** (most reliable for headless/agent use when ambient Google credentials are preferred). The Colab backends need a specific scope set, so re-mint ADC with all four scopes: ```bash gcloud auth application-default login \ --scopes=openid,\ @@ -35,10 +35,10 @@ by running `uv tool install google-colab-cli` or `pip install google-colab-cli`. https://www.googleapis.com/auth/userinfo.email,\ https://www.googleapis.com/auth/colaboratory ``` - Why all four: `userinfo.email` (session backend `colab.research.google.com`, else 401), `colaboratory` (RuntimeService `colab.pa.googleapis.com` keep-alive, else 403), `openid`+`cloud-platform` (mandated by gcloud itself; it rejects scope lists missing `cloud-platform`). -- **oauth2 setup**: `colab --auth=oauth2 ` triggers a browser consent flow on first use (token cached at `~/.config/colab-cli/token.json`). Requires a client config at `~/.colab-cli-oauth-config.json` (or `-c PATH`). The browser step means it usually needs a human; prefer ADC for agents. -- **Verify auth in one shot**: `colab sessions` (read-only, lists server assignments) or `colab whoami` (hidden debug command: prints the active email, scopes, audience, and expiry). When any call 403s against `colab.pa.googleapis.com`, the cause is almost always a missing scope — `colab whoami` shows it instantly. -- **`colab new` pre-flights the keep-alive RPC** right after allocating. If your token lacks the `colaboratory` scope it unassigns the fresh VM (so you don't leak a billable assignment) and prints the exact remediation. Follow that message rather than retrying blindly. + Why all four: `userinfo.email` is required by the session backend at `colab.research.google.com`; `colaboratory` is retained for forward compatibility and other Colab features; `openid`+`cloud-platform` are mandated by `gcloud` itself, which rejects scope lists missing `cloud-platform`. +- **oauth2 setup**: `colab --auth=oauth2 ` triggers a remote copy-paste browser consent flow on first use (token cached at `~/.config/colab-cli/token.json`). If no explicit `-c PATH` or `~/.colab-cli-oauth-config.json` is present, the CLI falls back to its bundled OAuth config. The browser/code step means it usually needs a human; prefer ADC for unattended agents. +- **Verify auth in one shot**: `colab sessions` (read-only, lists server assignments) or `colab whoami` (hidden debug command: prints the active email, scopes, audience, and expiry). When a session operation fails with 401/403, first verify identity and scopes rather than retrying blindly. +- **`colab new` pre-flights keep-alive** right after allocating. Keep-alive now uses the same `colab.research.google.com` tunnel credential path as assignment, so scope failures should normally surface at assignment time; if pre-flight does fail with a scope error, the CLI unassigns the fresh VM (so you don't leak a billable assignment) and prints provider-specific remediation. - **Do NOT confuse `colab auth` with CLI authentication.** `colab auth` injects *VM-side* GCP credentials into the running kernel (so notebook code can call BigQuery/GCS); it is orthogonal to how the CLI itself authenticates. Never suggest "run `colab auth`" to fix a CLI 401/403 — that's a scope/identity problem fixed via the `gcloud` command above. ## Workflow @@ -86,4 +86,4 @@ by running `uv tool install google-colab-cli` or `pip install google-colab-cli`. ## Recovery - "Session not found" / 404 / 401 on exec: the backend pruned the VM. `colab exec`/`repl` detect this and clean up local state automatically — run `colab sessions` and re-create with `colab new`. - Execution timeout or wedged kernel: `colab restart-kernel -s ` (keeps the VM, resets the kernel), or `colab stop` then `colab new`. -- Keep-alive daemon died (`colab log` shows `keep_alive_stopped reason=consecutive_4xx_errors`): almost always the missing `colaboratory` scope — re-auth per the Authentication section. +- Keep-alive daemon died (`colab log` shows `keep_alive_stopped reason=consecutive_4xx_errors`): inspect the logged status/body. A real 4xx usually means the assignment expired or credentials are wrong; read-timeouts on the tunnel keep-alive path are treated as success. diff --git a/tests/test_readme.py b/tests/test_readme.py index 30746b9..d629b71 100644 --- a/tests/test_readme.py +++ b/tests/test_readme.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from pathlib import Path from unittest.mock import patch, mock_open, MagicMock from typer.testing import CliRunner import pytest @@ -90,3 +91,13 @@ def test_readme_failure(mock_resources): result = runner.invoke(app, ["README"]) assert result.exit_code == 1 assert "README.md content not available" in result.output + + +def test_auth_docs_match_current_cli_default(): + repo_root = Path(__file__).resolve().parents[1] + readme = (repo_root / "README.md").read_text() + skill = (repo_root / "skills" / "colab-operator" / "SKILL.md").read_text() + + assert "default: `oauth2`" in readme + assert "default is `oauth2`" in skill + assert "RuntimeService `colab.pa.googleapis.com` keep-alive" not in skill