Commit Graph

59 Commits

Author SHA1 Message Date
jpoehnelt-bot b5c8ef8002 feat(apps-script): add +pull, +open, +run, +logs helpers with .clasp.json support
Generate Skills / Generate and commit skills (push) Has been cancelled
- Add +pull: download project files to local directory with filename sanitization
- Add +open: open script editor in browser
- Add +run: execute functions with cloud-platform scope and contextual error hints
  (extracts GCP project number from OAuth client ID for setup guidance)
- Add +logs: view execution logs via processes.listScriptProcesses
- Add .clasp.json support: auto-resolve scriptId/rootDir for all helpers
- Add clasp_config.rs module with path traversal validation
- Add validate_script_filename() for safe file writes during +pull
- Regenerate skills for new helper commands
2026-03-04 14:52:15 -07:00
jpoehnelt-bot 2bbe1472c1 ci: harden publish-skills workflow
- Pin clawhub@0.7.0 for supply-chain safety
- Add concurrency group to prevent parallel publishes
- Add PR dry-run validation
- Guard against missing CLAWHUB_TOKEN secret
- Add changeset file
2026-03-04 12:11:54 -07:00
jpoehnelt-bot 274063a52e ci: use documented clawhub sync flags 2026-03-04 12:11:54 -07:00
jpoehnelt-bot b4e437148c ci: add workflow to publish OpenClaw skills to ClawHub 2026-03-04 12:11:54 -07:00
googleworkspace-bot 3346f9d68c chore: release versions (#61)
* chore: release versions

* chore: regenerate skills [skip ci]

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-04 12:00:30 -07:00
Justin Poehnelt 670267f6ec feat: add gws mcp server (#58)
* feat: add gws mcp server

Adds a new `gws mcp` subcommand that starts a Model Context Protocol
(MCP) server over stdio, exposing Google Workspace APIs as structured
tools to any MCP-compatible client.

- New `src/mcp_server.rs`: JSON-RPC stdio transport, handles
  `initialize`, `tools/list`, and `tools/call`
- Tool discovery dynamically builds schemas from Google Discovery Docs
- Filtering via `-s <services>` flag (e.g. `-s drive,gmail` or `-s all`)
- `-w/--workflows` and `-e/--helpers` flags for optional extras
- stderr startup warning when no services are configured
- Refactored `executor::execute_method` to support output capture
  (returns `Option<Value>` instead of printing to stdout) so the MCP
  transport is not corrupted
- Updated README.md with MCP Server section and usage examples

* fix: address PR review comments

- Add stderr warning when discovery doc fails to load (mcp_server.rs)
- Remove redundant 'all' string check in service validation (mcp_server.rs)
- Validate upload path to prevent arbitrary file reads - security fix (mcp_server.rs)
- Remove redundant inner capture_output check in handle_binary_response (executor.rs)
- Add changeset for minor version bump

* fix: resolve CI lint, fmt, and test failures

- cargo fmt: format all changed files
- clippy: add #[allow(clippy::too_many_arguments)] on private handle_json_response
- clippy: collapse else { if } to else if in executor.rs
- clippy: replace svc_name.clone() with std::slice::from_ref in mcp_server.rs
- clippy: replace index-based loop with iterator in walk path resolution
- test: add ::<()> turbofish annotation to handle_error_response test calls
  to fix E0282 type inference errors
2026-03-04 11:58:28 -07:00
Justin Poehnelt 8c1042afc1 fix: use gl-rust/ prefix in x-goog-api-client header (#59)
Co-authored-by: jpoehnelt-bot <jpoehnelt-bot@users.noreply.github.com>
2026-03-04 11:57:52 -07:00
Justin Poehnelt 3de97622a3 docs: fix gws setup → gws auth setup (fixes #56, #57) (#60)
Co-authored-by: jpoehnelt-bot <jpoehnelt-bot@users.noreply.github.com>
2026-03-04 11:57:16 -07:00
googleworkspace-bot 206fd46f1e chore: release versions (#54)
Release / plan (push) Has been cancelled
Release / publish-npm (push) Has been cancelled
Release / announce (push) Has been cancelled
Release / build-local-artifacts (${{ join(matrix.targets, ', ') }}) (push) Has been cancelled
Release / build-global-artifacts (push) Has been cancelled
Release / host (push) Has been cancelled
v0.2.2
2026-03-04 01:04:28 -07:00
Justin Poehnelt 16bbab5ddd chore: fix changesets 2026-03-04 01:03:08 -07:00
Justin Poehnelt 8a40dbaa2a Merge pull request #53 from googleworkspace/feat/auto-generate-skills-workflow
ci: auto-generate and commit skills on branch push
2026-03-04 01:01:45 -07:00
Justin Poehnelt 77f0f04be7 Merge pull request #52 from googleworkspace/fix/atomic-credential-writes
fix: atomic credential file writes to prevent corruption on crash (fixes #42)
2026-03-04 01:01:41 -07:00
Justin Poehnelt e41bd89574 Merge pull request #51 from googleworkspace/fix/table-flatten-and-unicode
fix(table): flatten nested objects to dot-notation, safe multi-byte truncation (fixes #40 #43)
2026-03-04 01:01:37 -07:00
Justin Poehnelt ab6c45e4b5 Merge pull request #49 from googleworkspace/fix/unknown-format-warning
fix: warn to stderr when unknown --format value is provided (fixes #38)
2026-03-04 01:01:33 -07:00
Justin Poehnelt 666f9a88f4 fix(auth): support --help / -h flag on auth subcommand (fixes #26) (#48)
* fix(auth): support --help / -h flag on auth subcommand (fixes #26)

* add changeset
2026-03-04 00:59:10 -07:00
Justin Poehnelt 9935ddee39 ci: auto-generate and commit skills on branch push 2026-03-04 00:57:29 -07:00
Justin Poehnelt 173d15572f fix: add YAML document separators when paginating (fixes #39) (#50) 2026-03-04 00:56:26 -07:00
Justin Poehnelt f91f9e0114 style: cargo fmt 2026-03-04 00:54:37 -07:00
Justin Poehnelt ee35e4ab0c fix: warn to stderr when unknown --format value is provided (fixes #38) 2026-03-04 00:54:34 -07:00
Justin Poehnelt 0603bce410 fix: atomic credential file writes to prevent corruption on crash (fixes #42) 2026-03-04 00:52:59 -07:00
Justin Poehnelt bcd24011d0 fix(table): flatten nested objects to dot-notation, safe multi-byte truncation (fixes #40 #43) 2026-03-04 00:50:36 -07:00
googleworkspace-bot 7e73fda87a chore: release versions (#46) 2026-03-04 00:43:54 -07:00
jpoehnelt-bot 4b868c7327 docs(gws-shared): add community guidance for stars + issue hygiene (#41)
* docs(gws-shared): add community issue and starring guidance

* feat: add community links to gws help output

* fix(ci): move community section into generate-skills template + add changeset
2026-03-04 00:35:32 -07:00
jpoehnelt-bot e094b02dbe fix: YAML block scalar and repeated --page-all headers in CSV/table (#37)
- YAML: only emit block scalar (|) for strings with genuine newlines;
  single-line strings containing '#' or ':' are now double-quoted instead,
  e.g. 'drive#file' renders as '"drive#file"' not a block scalar.
- --page-all: CSV/table formats no longer re-emit column headers on
  every page; headers appear only on the first page.  A new public
  format_value_paginated() helper replaces the now-removed
  format_value_compact().
- Add unit tests for both fixes (8 new test cases in formatter.rs).
2026-03-04 00:35:27 -07:00
jpoehnelt-bot ee2e216c10 fix: narrow default OAuth scopes to avoid restricted_client, improve non-interactive setup UX (#30)
* fix: narrow default OAuth scopes to avoid restricted_client, add --full flag, improve non-interactive setup UX

Fixes #24, #25

- DEFAULT_SCOPES now aliases MINIMAL_SCOPES (no pubsub/cloud-platform)
  which avoids Google's restricted_client 403 on unverified OAuth apps
- Add FULL_SCOPES and --full flag for users who need the broader set
- Replace cryptic 'run setup interactively' error with step-by-step
  manual OAuth console instructions including URLs, options A/B/C

* chore: add changeset

* chore: cargo fmt

* fix: refactor format! with backslash continuations to concat! macro

Address Gemini review (PR #30): replace hard-to-read backslash line
continuations in large format! macros with concat! for clearer structure:
- manual_oauth_instructions(): full step-by-step guide
- stage_configure_oauth() wizard show_message: interactive prompt text

No functional change; output text is identical.
2026-03-04 00:35:22 -07:00
jpoehnelt-bot de2787e90f feat(error): detect accessNotConfigured and guide users to enable APIs (#33)
* feat(error): detect accessNotConfigured and guide users to enable APIs

When the Google API returns a 403 with reason accessNotConfigured,
gws now:
- Extracts the GCP Console enable URL from the error message.
- Adds an optional enable_url field to the JSON error output.
- Prints an actionable hint with the enable URL to stderr.

Also adds extract_enable_url() helper with tests, and a Troubleshooting
section to README.

Fixes #31

* fix(error): trim trailing punctuation from accessNotConfigured enable URL
2026-03-04 00:30:51 -07:00
jpoehnelt-bot f281797d07 docs(auth): add manual OAuth client and browser consent guidance (#29)
* docs(auth): add manual OAuth client/browser guidance

* docs(auth): use canonical Cloud Console URLs for OAuth consent/credentials

Update the OAuth setup section to use the canonical, stable Cloud Console
URLs as suggested in Gemini review (PR #29):
- /auth/overview → /apis/credentials/consent (matches the actual page title)
- /auth/clients  → /apis/credentials (more direct, avoids redirect)
2026-03-04 00:26:34 -07:00
Justin Poehnelt 214fc18d4f ci: skip smoketest on fork pull requests (#47) 2026-03-04 00:24:13 -07:00
jpoehnelt-bot 6ae74271f9 fix(auth): stabilize encrypted credential key fallback (#28)
* fix(auth): stabilize encryption key fallback across runs

* chore: add changeset for auth encryption key fix

* chore: cargo fmt

* fix(auth): address Gemini review comments - OnceLock expect + permission warnings

- Replace unwrap_or(candidate) with expect() in cache_key closure for clearer
  OnceLock race invariant: if set() fails, get() is guaranteed to return Some
- Emit eprintln! warnings (rather than silently ignoring) when set_permissions
  fails on the encryption key directory, matching the warning pattern used
  throughout the codebase (src/auth_commands.rs, helpers/workflows.rs, etc.)
2026-03-04 00:19:42 -07:00
Justin Poehnelt bdb458bd1c docs: update link 2026-03-03 18:39:29 -07:00
googleworkspace-bot 7ba65cf3a9 chore: release versions (#20)
Release / plan (push) Has been cancelled
Release / build-local-artifacts (${{ join(matrix.targets, ', ') }}) (push) Has been cancelled
Release / build-global-artifacts (push) Has been cancelled
Release / host (push) Has been cancelled
Release / publish-npm (push) Has been cancelled
Release / announce (push) Has been cancelled
v0.2.0
2026-03-03 18:37:15 -07:00
Justin Poehnelt 90adcb4379 fix: harden URL encoding and input validation for AI/LLM callers (#21)
* refactor: replace manual urlencoded() with reqwest .query() builder

Remove duplicate hand-rolled urlencoded() functions from workflows.rs
and calendar.rs. All query parameters are now passed via reqwest's
.query() API, which handles percent-encoding correctly and completely.

* fix: percent-encode path parameters to prevent path traversal

Use percent_encoding::utf8_percent_encode for calendar_id, cal.id,
message_id, and file_id before interpolating into URL path segments.
Addresses code review feedback on security regression.

* fix: add shared URL safety helpers for path params

Add encode_path_segment() for single-segment IDs and
validate_resource_name() for multi-segment resource names.

encode_path_segment: percent-encodes all non-alphanumeric chars,
used for calendar IDs, file IDs, and message IDs.

validate_resource_name: rejects path traversal (..) and control
chars while preserving intentional / structure, used for Chat
space names, task list IDs, and subscription names. Returns clear
error messages for LLM callers.

* test: add AI edge case tests for URL safety helpers

Cover query/fragment injection, double-encoding, unicode, spaces,
path traversal via encoding, control chars (CR/tab), and clear
error message assertions for LLM callers.

* fix: warn on stderr when API calls fail silently

- Daily briefing calendar events fetch
- Daily briefing tasks fetch
- Daily summary calendar events fetch
- Daily summary unread email count fetch

Addresses PR review feedback about confusing silent failures,
especially for LLM callers that cannot see visual cues.

* fix: harden input validation for AI/LLM callers

- Add src/validate.rs with validate_safe_output_dir, validate_msg_format,
  and validate_safe_dir_path helpers
- Validate --output-dir against path traversal in gmail +watch and
  events +subscribe
- Validate --msg-format against allowlist in gmail +watch
- Validate --dir against path traversal in script +push
- Add clap value_parser constraint for --msg-format
- Document input validation patterns in AGENTS.md

Closes #23

* chore: add changesets for PR #21 commits

* test: add comprehensive test coverage for input validation handlers

* docs: document input validation and URL safety patterns in AGENTS.md and CONTRIBUTING.md

* fix: address PR review comments — reject ?/# in resource names, validate subscription arg, remove redundant validate_msg_format

* fix: store validated PathBuf, remove dead code, delete duplicate SubscribeConfig

Addresses review comments:
- Store validated PathBuf from validate_safe_output_dir instead of
  discarding it (output_dir is now Option<PathBuf>)
- Remove duplicate SubscribeConfig from events/mod.rs
- Delete unused validate_msg_format (clap value_parser handles this)
- Remove all #[allow(dead_code)] annotations

* fix: per-segment traversal check in validate_resource_name, fix docs

* fix: harden security validation and deduplicate logic

---------

Co-authored-by: jpoehnelt-bot <jpoehnelt-bot@users.noreply.github.com>
2026-03-03 18:36:41 -07:00
Justin Poehnelt 76643573b3 test: add test for missing error paths in load_client_config (#19) 2026-03-03 17:20:56 -07:00
Justin Poehnelt e71ce292b2 fix: Gemini extension installation issue and update docs (#16)
* Fix Gemini extension installation issue and update docs

- Removed redundant authentication settings from `gemini-extension.json`.
- Added Gemini extension installation section to `README.md`.
- Added Gemini agent rules of engagement to `CONTEXT.md`.
- Added a changeset file for the patch.

Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>

* docs: simplify gemini part

Removed installation section and optimization tips for gws in the README.

* fix: remove template sanitization settings from config

Removed settings related to template sanitization.

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>
2026-03-03 15:03:32 -08:00
Justin Poehnelt c11d3c452d test: Add test for EncryptedTokenStorage::new (#17) 2026-03-03 15:03:10 -08:00
Justin Poehnelt b0d0b95d07 feat: skills expansion (#18)
* wip

* feat: replace admin recipes with 50 consumer-focused recipes

- Remove all admin/security/IT recipes (offboard-user, audit-user-login, etc.)
- Remove enterprise-only recipes (initiate-litigation-hold)
- Replace dangerous recipes (setup-email-forwarding -> create-gmail-filter)
- Remove recipes overlapping with gws-workflow-* helpers
- Remove thin 2-step recipes better served as helpers
- Add 50 curated consumer recipes for Gmail, Drive, Docs, Calendar, Sheets
- Update README: link to docs/skills.md, update skill count to 100+
- Fix clippy needless_borrow warnings in generate_skills.rs
- Fix lefthook.yml: run fmt/clippy sequentially (parallel causes races)

---------

Co-authored-by: jpoehnelt-bot <jpoehnelt-bot@users.noreply.github.com>
2026-03-03 15:02:34 -08:00
googleworkspace-bot 62868840b5 chore: release versions (#15)
Release / plan (push) Has been cancelled
Release / build-global-artifacts (push) Has been cancelled
Release / build-local-artifacts (${{ join(matrix.targets, ', ') }}) (push) Has been cancelled
Release / host (push) Has been cancelled
Release / publish-npm (push) Has been cancelled
Release / announce (push) Has been cancelled
v0.1.5
2026-03-03 13:58:16 -07:00
Justin Poehnelt d29f41ecf7 fix(docs): improve README typography and spacing (#14)
* fix(docs): improve README typography and spacing

- Remove center alignment for tagline and badges to match left-aligned body
- Add `<br>` after badges for visual separation before install block
- Increase whitespace above install block to emphasize it
- Add an empty line above `> [!IMPORTANT]` block to decouple it from previous paragraph

Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>

* Update README.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* docs: improve README typography and layout

- Remove center alignment from tagline and badges
- Add space below badges
- Adjust spacing around install code block (remove borders, add empty line above)
- Add empty line above IMPORTANT callout

Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>

* docs: refine copy after install code block

- Change "When Google adds an API endpoint" to "When Google Workspace adds an API endpoint or method" to be more accurate.

Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>

* docs: remove horizontal borders from README

Per user request, removed all remaining Markdown horizontal rules (`---`) throughout `README.md` to create a cleaner, borderless design. All previous typography and spacing improvements remain intact.

Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-03 12:53:14 -08:00
googleworkspace-bot d93a621a74 chore: release versions (#12)
Release / plan (push) Has been cancelled
Release / build-global-artifacts (push) Has been cancelled
Release / build-local-artifacts (${{ join(matrix.targets, ', ') }}) (push) Has been cancelled
Release / host (push) Has been cancelled
Release / publish-npm (push) Has been cancelled
Release / announce (push) Has been cancelled
v0.1.4
2026-03-03 12:15:04 -08:00
Justin Poehnelt d990dcc119 docs: make README banner full-width and add changeset (#13)
Co-authored-by: jpoehnelt-bot <jpoehnelt-bot@users.noreply.github.com>
2026-03-03 12:55:03 -07:00
Justin Poehnelt adb2cfa8dc fix: decrypt token cache before extracting refresh token (#11) 2026-03-03 11:49:55 -08:00
Justin Poehnelt a73ff26522 docs: improve readme 2026-03-03 11:59:56 -07:00
googleworkspace-bot 1f9a37871d chore: release versions (#10)
Release / plan (push) Has been cancelled
Release / build-local-artifacts (${{ join(matrix.targets, ', ') }}) (push) Has been cancelled
Release / build-global-artifacts (push) Has been cancelled
Release / host (push) Has been cancelled
Release / publish-npm (push) Has been cancelled
Release / announce (push) Has been cancelled
v0.1.3
2026-03-03 11:14:56 -07:00
Justin Poehnelt c714f4b9c9 fix: use correct npm-scope/npm-package config keys for cargo-dist (#9)
* fix: use correct npm-scope/npm-package config keys for cargo-dist

* chore: add changeset

* docs: add changeset instructions to AGENTS.md
2026-03-03 11:13:33 -07:00
googleworkspace-bot 827b9da8a1 chore: release versions (#8)
Release / plan (push) Has been cancelled
Release / build-local-artifacts (${{ join(matrix.targets, ', ') }}) (push) Has been cancelled
Release / build-global-artifacts (push) Has been cancelled
Release / host (push) Has been cancelled
Release / publish-npm (push) Has been cancelled
Release / announce (push) Has been cancelled
v0.1.2
2026-03-03 10:48:41 -07:00
Justin Poehnelt 3cd4d522b2 fix: sync Cargo.toml version with changesets (#7) 2026-03-03 09:46:45 -08:00
Justin Poehnelt fd99954627 fix: use custom tag-release script for private packages 2026-03-03 10:24:27 -07:00
googleworkspace-bot 86ceb2f822 chore: release versions (#6)
Release / plan (push) Has been cancelled
Release / build-local-artifacts (${{ join(matrix.targets, ', ') }}) (push) Has been cancelled
Release / build-global-artifacts (push) Has been cancelled
Release / host (push) Has been cancelled
Release / publish-npm (push) Has been cancelled
Release / announce (push) Has been cancelled
v0.1.1
2026-03-03 09:21:46 -08:00
Justin Poehnelt 4d4cabeb16 ci: add concurrency controls to cancel stale PR runs 2026-03-03 10:13:44 -07:00
Justin Poehnelt 30d929b218 docs: fix gif, readme, etc (#5) 2026-03-03 09:11:29 -08:00