v0.10.0¶
Release Date: 2026-08-23
Overview¶
This release adds automatic retry and rate limiting to the client, three
new idea-related resources (endorsements, portal users, and
organizations), manual progress and workflow-status fields across
Feature/Initiative/Release, a graphql.SetCustomFieldValues wrapper that
surfaces payload-level validation errors, and a new omniroadmap/
adapter package implementing omniroadmap-core's provider.Provider
interface.
Highlights¶
- Automatic retry and rate limiting - the client now retries 429/5xx
responses with backoff and jitter by default, and can proactively
throttle outgoing requests for bulk operations (
WithMaxRetries,WithRequestsPerSecond,RateLimitFromError) - Idea endorsements, users, and organizations -
ListIdeaEndorsements,ListIdeaUsers/GetIdeaUser,ListIdeaOrganizations/GetIdeaOrganization - Manual progress and workflow status -
Progress/ProgressSourceon Feature, Initiative, and Release, plusWorkflowStatuson Release (there's no standalone "released" flag - Released is derived from whichever workflow status the product defines as released) graphql.SetCustomFieldValueswrapper - surfaces field-level validation errors that Aha can return inside an otherwise-successful GraphQL response, so a rejected/unknown custom field key never looks like a silent success- New
omniroadmappackage - adapts*aha.Clienttoomniroadmap-core'sprovider.Providerinterface for roadmap- aggregation consumers likeplexusone/dashforge
Installation¶
What's New¶
Retry and Rate Limiting¶
client, err := aha.NewClient(
aha.WithMaxRetries(5), // default: 3
aha.WithRequestsPerSecond(15), // default: 0 (unlimited/reactive only)
)
// ...
if rl := aha.RateLimitFromError(err); rl != nil {
fmt.Printf("%d/%d remaining, resets at %s\n", rl.Remaining, rl.Limit, rl.Reset)
}
Idea Endorsements, Users, and Organizations¶
// Endorsements (votes) on an idea, with voter identity
endorsements, err := client.ListIdeaEndorsements(ctx, "IDEA-123")
// Idea portal users and organizations (voter/customer identity)
users, err := client.ListIdeaUsers(ctx)
user, err := client.GetIdeaUser(ctx, "USER-ID")
orgs, err := client.ListIdeaOrganizations(ctx)
org, err := client.GetIdeaOrganization(ctx, "ORG-ID")
Progress and Workflow Status¶
feature, err := client.UpdateFeature(ctx, "PROD-123",
aha.WithUpdateFeatureProgressSource("progress_manual"),
aha.WithUpdateFeatureProgress(75),
aha.WithUpdateFeatureEpic("PROD-E-1"),
)
initiative, err := client.UpdateInitiative(ctx, "PROD-I-1",
aha.WithUpdateInitiativeProgressSource("progress_manual"),
aha.WithUpdateInitiativeProgress(30),
)
release, err := client.UpdateRelease(ctx, "PROD-R-1",
aha.WithReleaseProgressSource("progress_manual"),
aha.WithReleaseProgress(90),
aha.WithReleaseWorkflowStatus("Shipped"),
)
GraphQL Custom Field Wrapper¶
values, err := graphql.SetCustomFieldValues(ctx, client,
"FEATURE-ID",
generated.CustomFieldableTypeEnumFeature,
map[string]any{
"priority_score": 85,
"customer_segment": "Enterprise",
},
)
omniroadmap Provider Adapter¶
import "github.com/grokify/aha-go/omniroadmap"
p := omniroadmap.NewProvider(client, omniroadmap.WithProductID("PROD"))
items, err := p.ListItems(ctx, &provider.ListItemsRequest{})
See the omniroadmap package docs for details.
New SDK Methods¶
| Method | Description |
|---|---|
ListIdeaEndorsements |
List endorsements (votes) on an idea, with voter identity |
ListIdeaUsers / GetIdeaUser |
List/get idea portal users |
ListIdeaOrganizations / GetIdeaOrganization |
List/get idea portal organizations |
RateLimitFromError |
Extract Aha's rate-limit headers from a client error |
graphql.SetCustomFieldValues |
Set custom field values, surfacing payload-level errors as a Go error |
New Functional Options¶
| Option | Description |
|---|---|
WithRetryDisabled |
Disable automatic retry of 429/5xx responses |
WithMaxRetries |
Set the maximum retry attempts (default: 3) |
WithRequestsPerSecond |
Proactively throttle outgoing requests |
WithUpdateFeatureProgressSource / WithUpdateFeatureProgress |
Set a feature's manual progress |
WithUpdateFeatureEpic |
Set a feature's epic |
WithUpdateFeatureOriginalEstimate / WithUpdateFeatureRemainingEstimate |
Set a feature's estimates |
WithUpdateFeatureReleasePhase |
Set a feature's release phase |
WithUpdateInitiativeProgressSource / WithUpdateInitiativeProgress |
Set an initiative's manual progress |
WithReleaseProgressSource / WithReleaseProgress |
Set a release's manual progress |
WithReleaseWorkflowStatus |
Transition a release's workflow status |
WithReleaseExternalReleaseDate / WithReleaseDevelopmentStartedOn |
Set release dates |
Upgrade Notes¶
This is a backward-compatible release. No breaking changes from v0.9.0.
If you called generated.SetCustomFieldValues directly with a
[]generated.CustomFieldValueInput and read .Value as
*map[string]any, note that CustomFieldValueInput.Value and
CustomFieldValue.Value are now plain any (matching Aha's actual bare
scalar values) rather than *map[string]any — switch to the new
graphql.SetCustomFieldValues(ctx, client, recordID, recordType, map[string]any{...})
wrapper, which also surfaces payload-level validation errors.
Commits¶
| Hash | Description |
|---|---|
9c6659e |
feat: add automatic retry and rate limiting to Client |
c54d8f7 |
test: add tests for retry, rate limiting, and rate-limit error parsing |
961676c |
fix(deps): pin ysmood/fetchup via replace directive for go-rod compatibility |
e9c3b04 |
feat(openapi): add idea endorsements, users, and organizations resources |
7b93159 |
chore(codegen): regenerate ogen client for idea voter/organization resources |
c0f19e7 |
feat(idea): add ListIdeaEndorsements, ListIdeaUsers/GetIdeaUser, ListIdeaOrganizations/GetIdeaOrganization |
e1ca536 |
test(idea): add tests for endorsement, idea user, and idea organization methods |
5361ef2 |
feat(feature): add progress, epic, and estimate/release-phase update options |
b528074 |
feat(initiative): add progress calculation fields |
c66b309 |
feat(release): add progress, workflow status, and development/external release dates |
7c30fb6 |
test: add tests for feature, initiative, and release progress/workflow updates |
65e8cfe |
fix(graphql): correct custom field value scalar binding for genqlient |
7356fdd |
feat(graphql): add SetCustomFieldValues wrapper surfacing payload errors |
d81b885 |
test(graphql): add tests for custom field value wrapper and scalar binding fix |
1c257e7 |
feat(omniroadmap): add Aha provider adapter for omniroadmap-core |
367671d |
docs: document OpenAPI workflow and SetCustomFieldValues wrapper usage |
7a04194 |
docs: add CLAUDE.md repo guidance for Claude Code |