90adcb4379
* 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>
93 lines
3.5 KiB
Markdown
93 lines
3.5 KiB
Markdown
# How to contribute
|
|
|
|
We'd love to accept your patches and contributions to this project.
|
|
|
|
## Before you begin
|
|
|
|
### Sign our Contributor License Agreement
|
|
|
|
Contributions to this project must be accompanied by a
|
|
[Contributor License Agreement](https://cla.developers.google.com/about) (CLA).
|
|
You (or your employer) retain the copyright to your contribution; this simply
|
|
gives us permission to use and redistribute your contributions as part of the
|
|
project.
|
|
|
|
If you or your current employer have already signed the Google CLA (even if it
|
|
was for a different project), you probably don't need to do it again.
|
|
|
|
Visit <https://cla.developers.google.com/> to see your current agreements or to
|
|
sign a new one.
|
|
|
|
### Review our community guidelines
|
|
|
|
This project follows
|
|
[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
|
|
|
|
## Contribution process
|
|
|
|
### Code reviews
|
|
|
|
All submissions, including submissions by project members, require review. We
|
|
use GitHub pull requests for this purpose. Consult
|
|
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
|
information on using pull requests.
|
|
|
|
### Updating CI Smoketest Credentials
|
|
|
|
If the OAuth refresh token used in the GitHub Actions smoketest expires or needs additional scopes, you can generate a new one and update the repository secret using the GitHub CLI (`gh`).
|
|
|
|
1. **Set the credentials file path to output plaintext JSON**:
|
|
```bash
|
|
export GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=smoketest-creds.json
|
|
```
|
|
|
|
2. **Authenticate with the required scopes**:
|
|
```bash
|
|
cargo run -- auth login --scopes https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/gmail.readonly,https://www.googleapis.com/auth/calendar.readonly,https://www.googleapis.com/auth/presentations.readonly,https://www.googleapis.com/auth/tasks.readonly
|
|
```
|
|
|
|
3. **Export and set the GitHub actions secret**:
|
|
```bash
|
|
cargo run --quiet -- auth export --unmasked | base64 | gh secret set GOOGLE_CREDENTIALS_JSON
|
|
```
|
|
|
|
4. **Clean up**:
|
|
```bash
|
|
rm smoketest-creds.json
|
|
unset GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE
|
|
```
|
|
|
|
## Development Patterns
|
|
|
|
### Changesets
|
|
|
|
Every PR must include a changeset file at `.changeset/<descriptive-name>.md`:
|
|
|
|
```markdown
|
|
---
|
|
"@googleworkspace/cli": patch
|
|
---
|
|
|
|
Brief description of the change
|
|
```
|
|
|
|
Use `patch` for fixes/chores, `minor` for new features, `major` for breaking changes.
|
|
|
|
### Input Validation & URL Safety
|
|
|
|
This CLI is designed to be invoked by AI/LLM agents, so all user-supplied inputs must be treated as potentially adversarial. See [AGENTS.md](../AGENTS.md#input-validation--url-safety) for the full reference. The key rules are:
|
|
|
|
| What you're doing | What to use |
|
|
|---|---|
|
|
| Accepting a file path (`--output-dir`, `--dir`) | `validate::validate_safe_output_dir()` or `validate_safe_dir_path()` |
|
|
| Embedding a value in a URL path segment | `helpers::encode_path_segment()` |
|
|
| Passing query parameters | reqwest `.query()` builder (never string interpolation) |
|
|
| Using a resource name in a URL (`--project`, `--space`) | `helpers::validate_resource_name()` |
|
|
| Accepting an enum flag (`--msg-format`) | clap `value_parser` (see `gmail/mod.rs`) |
|
|
|
|
### Testing Expectations
|
|
|
|
- All new validation logic must include **both happy-path and error-path tests**
|
|
- Tests that modify the process CWD must use `#[serial]` from `serial_test`
|
|
- Tempdir paths should be canonicalized before use to handle macOS `/var` → `/private/var` symlinks
|
|
- Run the full suite before submitting: `cargo test && cargo clippy -- -D warnings` |