-
Notifications
You must be signed in to change notification settings - Fork 0
Comparing changes
Open a pull request
base repository: basecamp/basecamp-cli
base: v0.2.1
head repository: basecamp/basecamp-cli
compare: v0.2.2
- 10 commits
- 54 files changed
- 1 contributor
Commits on Mar 3, 2026
-
Configuration menu - View commit details
-
Copy full SHA for 1c011d7 - Browse repository at this point
Copy the full SHA 1c011d7View commit details -
Render todos as markdown task lists (#178)
* Add task list markdown renderer with grouped output Introduce MarkdownListView schema type with style and group_by fields. When a schema declares style: tasklist, RenderListMarkdown renders - [ ] / - [x] checkbox items instead of GFM pipe tables. Items are grouped by a dot-path field (e.g. bucket.name) with headings suppressed for single groups and "Other" for items missing the group field. Adds PresentOption/WithGroupBy for dynamic group-by override, and removes empty-slice bail in both presentStyled and presentMarkdown so empty results are handled consistently by the renderers (both paths now emit *No results* for empty data). * Add DisplayData and WithGroupBy to output envelope DisplayData (json:"-") provides alternate data for styled/markdown rendering while keeping Data untouched for JSON serialization. This lets commands preserve wrapper structs for machine output while presenting unwrapped slices through the schema-aware presenter. WithGroupBy threads a presenter option through the envelope to override the schema's default group_by field at render time. * Render reports assigned as markdown task lists Wire up reports assigned to use WithEntity("todo") + WithDisplayData for schema-aware rendering. JSON output preserves the full wrapper struct; styled/markdown output presents the unwrapped todos through the task list renderer. --group-by date maps to due_on grouping. Adds output-layer tests for DisplayData contract (JSON uses Data, markdown/styled use DisplayData) and presenter tests for task list rendering, grouping, override, empty states, and Other heading. * Fix date label and people name extraction in task list renderer Only use "due:" prefix for `due_on` fields; other date columns use their field label. Extract people names directly from the raw array value instead of splitting the formatted comma-joined string, which broke names containing commas (e.g. "Park, Joon-seo").Configuration menu - View commit details
-
Copy full SHA for c516df5 - Browse repository at this point
Copy the full SHA c516df5View commit details -
Fix AI labeler removing and re-adding the same label (#179)
Check current labels before modifying. Only remove classification labels that differ from the chosen one and are actually present; only add the chosen label if it's not already there. Eliminates no-op label churn on synchronize events.
Configuration menu - View commit details
-
Copy full SHA for 6b9ef89 - Browse repository at this point
Copy the full SHA 6b9ef89View commit details -
Fix 86 CodeQL findings across Go, Python, and CI workflows (#177)
* Sanitize paths from env vars and OS APIs to fix CodeQL go/path-injection Apply filepath.Clean() at source functions where environment variables (XDG_CONFIG_HOME, XDG_CACHE_HOME, HOME) and OS APIs (UserHomeDir, UserCacheDir, UserConfigDir) produce tainted values. This breaks CodeQL's taint chain for ~69 downstream path-injection findings. Uses "fallback first, then clean non-empty" pattern to avoid filepath.Clean("") returning "." which would redirect to CWD. Falls back to os.TempDir() when home directory is unavailable. * Strip newlines from auth token output to fix CodeQL log-injection * Validate editor path with LookPath to fix CodeQL command-injection exec.LookPath() is recognized by CodeQL as a sanitizer for the command-injection finding on $EDITOR-derived exec.Command calls. * Guard float-to-int conversion with 2^53 precision bound to fix CodeQL integer-overflow float64 can only represent consecutive integers exactly up to 2^53. Check range before casting to int64 to avoid undefined behavior for large floats. Adds boundary tests for precision edge cases. * Add workflow permissions and pin action tags for CodeQL security findings - Add top-level permissions: contents: read to test.yml (7 findings) - Pin golangci-lint-action and actions/cache to commit hashes in release.yml * Add is_dir() guards in doc_parity.py before glob/rglob callsConfiguration menu - View commit details
-
Copy full SHA for 0257161 - Browse repository at this point
Copy the full SHA 0257161View commit details -
Add config trust model for authority keys (#181)
* Add TrustStore for opt-in config file trust Introduce TrustStore type persisted at ~/.config/basecamp/trusted-configs.json. Path-based trust (not content-based) allows authority keys from local/repo configs when explicitly approved via the trust store. Canonical paths (EvalSymlinks + Abs) prevent symlink bypasses. When a file is deleted, parent-directory symlink resolution preserves canonical form so stale entries can still be revoked. * Wire trust store into config loading loadFromFile now accepts a *TrustStore parameter. Authority keys (base_url, default_profile, profiles) from local/repo sources are accepted when the file is trusted, rejected otherwise. Warnings include the exact file path with shell-safe quoting so users can copy-paste the remediation command. Export RepoConfigPath for reuse by the trust subcommand. * Add config trust/untrust subcommands basecamp config trust [path] — approve a local/repo config for authority keys basecamp config untrust [path] — revoke trust (works even if file was deleted) basecamp config trust --list — show all trusted paths config set now warns when writing authority keys to untrusted local config. Trust and untrust use separate path resolution: trust requires the file to exist, untrust accepts explicit nonexistent paths for stale entry cleanup. * Harden canonicalizePath and use POSIX shell quoting in warnings canonicalizePath now only falls back to the absolute path on fs.ErrNotExist; other EvalSymlinks errors (permission denied, etc.) return "" to fail closed on the security boundary. Warning messages use POSIX single-quote escaping instead of Go %q double-quoting, preventing shell metacharacter expansion when users copy-paste the suggested trust command.
Configuration menu - View commit details
-
Copy full SHA for 701669a - Browse repository at this point
Copy the full SHA 701669aView commit details -
Restore error guards on AI labeler edit calls (#180)
The label snapshot can go stale between gh pr view and the subsequent edits if another workflow or human changes labels concurrently. Keep the 2>/dev/null || true guards so a race doesn't fail the job.
Configuration menu - View commit details
-
Copy full SHA for f5f188f - Browse repository at this point
Copy the full SHA f5f188fView commit details -
Convert HTML content to markdown in presenter output (#184)
* Detect bc-attachment tags as HTML in IsHTML Pure bc-attachment payloads (Basecamp mentions, file references) without wrapping <div>/<p> tags bypassed HTML detection because reSafeTag did not include bc-attachment. This caused raw tags to leak through formatText() and every downstream renderer. * Convert HTML to markdown in presenter output The Basecamp API returns Trix HTML in content, description, and body fields. The TUI already converts via richtext.HTMLToMarkdown → glamour, but the CLI presenter rendered strings verbatim, leaking <div>, <br>, <bc-attachment>, <blockquote>, etc. into every output mode. - formatText() now detects HTML and converts to markdown at the universal formatting point, so all output modes benefit - singleLine() helper collapses multi-line converted content for compact renderers (list rows, task items, table cells, metadata) - RenderHeadline() normalizes HTML headlines and strips emphasis markers that would nest with the bold/primary rendering context * Address review feedback on HTML-to-markdown conversion - singleLine: add fast-path when no newlines to avoid slice allocation on the common case (every cell/value in list rendering) - RenderHeadline: replace blanket strings.ReplaceAll("**","") with regex that unwraps **...** pairs, preserving literal ** in content like 2**10 - Narrow doc comment to describe bold-only unwrapping, not general emphasisConfiguration menu - View commit details
-
Copy full SHA for 88114fa - Browse repository at this point
Copy the full SHA 88114faView commit details
Commits on Mar 4, 2026
-
Add macOS code signing and notarization (#185)
* Add macOS code signing and notarization via GoReleaser Use GoReleaser v2's native notarize.macos support (powered by embedded quill) to sign and notarize darwin binaries on the existing Ubuntu runner. The enabled gate requires all five MACOS_* secrets to be present, cleanly skipping for forks and local builds. Explicit ids: [basecamp] prevents accidental scope expansion if new build targets are added. * Wire macOS signing secrets and preflight check into release workflow Pass MACOS_SIGN_P12, MACOS_SIGN_PASSWORD, MACOS_NOTARY_KEY, MACOS_NOTARY_KEY_ID, and MACOS_NOTARY_ISSUER_ID to GoReleaser. A preflight step on the canonical repo fails fast if any secret is missing, preventing silent publication of unsigned macOS binaries. Forks skip the check via github.repository guard. Bump release job timeout from 15m to 45m for notarization wait headroom. * Fix cosign verification in install script to use bundle format The release workflow produces checksums.txt.bundle (cosign v2 bundle), not the separate .sig/.pem files the installer was trying to download. Switch to --bundle flag to match actual release assets. * Use non-empty check instead of isEnvSet for notarize guard GitHub Actions sets missing secrets as empty strings, so isEnvSet returns true even on forks without secrets configured. Switch to Go template truthiness (empty string is falsy) so the notarize block is skipped when secrets are absent. * Document macOS signing secrets and notarization in RELEASING.md * Move macOS signing secrets to release environment Add `environment: release` to the release job so signing credentials are only accessible to that specific job context. Isolates the Developer ID cert and App Store Connect API key from other workflows.
Configuration menu - View commit details
-
Copy full SHA for 5512797 - Browse repository at this point
Copy the full SHA 5512797View commit details -
Support custom OAuth redirect_uri (#186)
* Support custom OAuth redirect_uri via env var and programmatic override Users with their own OAuth client credentials registered on Launchpad need the CLI's redirect_uri to match their app's registered callback. The CLI previously hardcoded http://127.0.0.1:8976/callback with no way to override it. Add resolveOAuthCallback() with precedence chain: LoginOptions.RedirectURI > BASECAMP_OAUTH_REDIRECT_URI env var > CallbackAddr-derived > hardcoded default Validate all redirect URIs (including default) against RFC 8252 loopback rules: http scheme, loopback host, explicit port, no userinfo/query/fragment. Rename credential env vars to BASECAMP_OAUTH_CLIENT_ID/SECRET with strict pairing (both required when either is set). BC3 DCR clients registered with a custom redirect URI are not persisted to client.json, preventing stale credentials on subsequent runs without the override. Closes #183 * Document custom OAuth credential env vars in README * Address review: derive customRedirect inside registerBC3Client, fix test isolation - Remove `customRedirect bool` parameter from `registerBC3Client`; derive it from `opts.RedirectURI != defaultRedirectURI` inside the function - Add `XDG_CONFIG_HOME` override in `TestRegisterBC3Client_UsesResolvedRedirectURI` to prevent writing to the developer's real config dir - Use full env var names in README sentence
Configuration menu - View commit details
-
Copy full SHA for 8990b3d - Browse repository at this point
Copy the full SHA 8990b3dView commit details -
Add --subscribe / --no-subscribe to recording creation commands (#187)
* Bump SDK to v0.2.2 Picks up Subscriptions field on create request types (CreateMessageRequest, CreateDocumentRequest, CreateScheduleEntryRequest). * Add --subscribe / --no-subscribe to recording creation commands Controls who gets subscribed and notified when creating messages, docs, and schedule entries. Critical for bot/agent use cases that need silent creation. --no-subscribe subscribe nobody (no notifications) --subscribe "X,Y" subscribe specific people (names, emails, IDs, "me") Mutually exclusive. Neither flag preserves server default (everyone). Explicit --subscribe with no resolvable people is a hard error, including --subscribe "" (via cmd.Flags().Changed detection). Available on: message, messages create, docs create, schedule create. Closes #182 * Address PR review feedback - Wrap ParseInt error in resolvePersonIDs for better diagnostics - Add happy-path tests verifying --no-subscribe sends empty subscriptions array and default omits the field entirely - Update --no-subscribe help text to "Don't subscribe anyone else" since the server always auto-subscribes the creator
Configuration menu - View commit details
-
Copy full SHA for fea17f4 - Browse repository at this point
Copy the full SHA fea17f4View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v0.2.1...v0.2.2