All notable changes to this project will be documented in this file.
- TTY detection with fail-fast: all interactive prompts now return a descriptive error instead of hanging when stdin is not a terminal (pipes, CI, LLM agents)
--output json/-o jsonglobal flag for machine-readable output on all commands (grant,env,status,revoke,favorites list)grant listcommand to discover eligible cloud targets and Entra ID groups without triggering elevation; supports--provider,--groups,--refresh, and--output jsongrant statusnow shows remaining session time instead of total duration for sessions elevated viagrantorgrant env; sessions elevated outside the CLI continue to show total durationgrant statusnow resolves group names from the groups eligibility API — group sessions displayGroup: CloudAdmins in Contosoinstead ofGroup: d554b344-uuid in 29cb7961-uuid- JSON output for
grant statusincludes new additive fields:remainingSeconds(omitted when unknown) andgroupName(omitted when unresolved) - Session elevation timestamps tracked locally in
~/.grant/cache/session_timestamps.jsonwith automatic cleanup of stale entries
- Elevation requests no longer fail with
context deadline exceededwhen the interactive target selector takes longer than 30 seconds
- golangci-lint configuration (
.golangci.yml) with 19 linters enabled and Go best practices applied
- Verbose logging (
--verbose/-v) now produces output for all commands, not just those usingSCAAccessService - Commands
update,version,login,logout,configure, andfavoritesnow emit SDK-format verbose logs (grant | timestamp | INFO | message)
- Migrated 4 ad-hoc
[verbose]/Warning:messages infetchStatusData,buildDirectoryNameMap,buildWorkspaceNameMap, andfetchEligibilityto use the SDK logger for consistent format - Removed
errWriter io.Writerparameter fromfetchStatusData,buildDirectoryNameMap,buildWorkspaceNameMap, andfetchGroupsEligibility(verbose output now goes through SDK logger, not injected writer)
grant updatecommand for self-updating the binary via GitHub Releases usingrhysd/go-github-selfupdate
- Local file-based eligibility cache (
~/.grant/cache/) with 4-hour default TTL — skips API roundtrip on subsequent runs --refreshflag ongrantandgrant envto bypass the eligibility cache and fetch fresh datacache_ttlconfig option in~/.grant/config.yamlto customize cache TTL (e.g.,cache_ttl: 2h)--groupsflag on root command to show only Entra ID groups in the interactive selector--group/-gflag on root command for direct group membership elevation (grant --group "Cloud Admins")grant --favorite <name>now handles both cloud and group favorites directlygrant revokecommand for session revocation with three modes: direct (by session ID),--all, and interactive (multi-select); works with both cloud and group sessions--yes/-yflag ongrant revoketo skip confirmation for scripting--provider/-pflag ongrant revoke --alland interactive mode to filter by cloud provider- Session ID displayed in
grant statusoutput for easy reference withgrant revoke
grant favorites addinteractive selector now shows both cloud roles and Entra ID groups in a unified list (previously cloud-only)- Group membership elevation merged into root command —
grantinteractive selector shows both cloud roles and Entra ID groups in a unified list - Eligibility caching now covers all commands (
grant status,grant revoke,grant favorites add) — previously onlygrantandgrant envused the cache grant statusnow fetches sessions and eligibility data concurrently, reducing wall-clock time by ~2sgrant revokeinteractive mode now fetches workspace names concurrently across CSPs
grant revokenow rejects--providerin direct mode (session IDs are already explicit)grant statussession formatting reuses sharedui.FormatSessionOptioninstead of duplicated logicbuildWorkspaceNameMapmoved to sharedcmd/helpers.goto eliminate cross-command dependency- Group favorites now verify DirectoryID, preventing wrong-group elevation when multiple directories have identically-named groups
grant statusnow resolves directory names for group sessions viabuildDirectoryNameMapbuildDirectoryNameMapnow handles nil eligibility response gracefullygrant favorites addnow resolves directory names for groups, matching root command display (Directory: X / Group: Y)
grant groupssubcommand — functionality absorbed into the root command with--groupsand--groupflags
- Interactive selector UI (arrows, highlighting) was written to stdout, breaking
eval $(grant env ...)— now redirected to stderr
- AWS elevation support (
--provider aws) grant envcommand for AWS credential export:eval $(grant env --provider aws)- Multi-CSP support: omitting
--providerfetches eligibility from all providers and shows combined results - Provider label
(azure)/(aws)in interactive selector when showing all providers - Non-interactive
favorites addwith--targetand--roleflags for scripting - Optional name argument for
favorites add— name can be prompted after interactive target selection - 30-second API request timeouts on all SCA API calls
- Workspace name resolution in
grant statusvia eligibility API cross-reference - Simplified bug report issue template
--providerflag no longer defaults to Azure; omit to see all providers- Identity URL is now optional in
grant configure— the SDK auto-discovers it from the username favorites removewith no arguments now shows a helpful error with usage hint- Verbose hint suppressed for argument validation errors where it adds no value
- Improved help text with examples and cross-references for all favorites subcommands
config.Load()now propagates non-ErrNotExist errors (e.g., permission denied) instead of silently returning defaultsfavorites addwith partial flags (--targetwithout--role) no longer requires authentication before reporting the validation error- Case-insensitive target matching for
--targetand--roleflags - Double error output from Cobra eliminated (
SilenceErrors,SilenceUsage) io.ReadAllerrors in SCA service error-response paths now produce fallback messages instead of empty strings- Error messages lowercased per Go conventions
- Multi-CSP eligibility queries run concurrently when
--provideris omitted
- Unused
--durationflag (was parsed but never sent to API) CSPGCPconstant (re-add when GCP is implemented)