Skip to content

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/ProgressSource on Feature, Initiative, and Release, plus WorkflowStatus on Release (there's no standalone "released" flag - Released is derived from whichever workflow status the product defines as released)
  • graphql.SetCustomFieldValues wrapper - 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 omniroadmap package - adapts *aha.Client to omniroadmap-core's provider.Provider interface for roadmap- aggregation consumers like plexusone/dashforge

Installation

go get github.com/grokify/aha-go@v0.10.0

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

Contributors