feedback

package
v0.27.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 10, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package feedback holds what `basecamp feedback` shares with the rest of the CLI: whether Basecamp advertises the feedback endpoint to this person, the cached answer, the override that forces it, and the hint error output carries while it is advertised.

The feature ships dark. Basecamp answers GET /{account}/feedback.json with 200 when feedback is on for the person and 404 when it is off, so the CLI advertises nothing — no command in help or completions, no hint — until a detection has seen a 200 or BASECAMP_FEEDBACK forces it on.

Index

Constants

View Source
const EnvOverride = "BASECAMP_FEEDBACK"

EnvOverride forces the feature on (1/true/yes/on) or off (0/false/no/off), skipping detection. Any other value is ignored.

View Source
const Hint = "If this looks like a problem with Basecamp, `basecamp feedback` reports it to the Basecamp team."

Hint is the line error output carries while feedback is advertised. It describes; it never tells the reader to do anything.

View Source
const MaxDetails = 2000

MaxDetails is the server's cap on details, in characters.

View Source
const NotAvailable = "Feedback is not available."

NotAvailable is everything `basecamp feedback` says when the feature is off.

View Source
const Path = "/feedback.json"

Path is the account-relative endpoint: GET discovers, POST submits.

View Source
const RefreshTimeout = 2 * time.Second

RefreshTimeout bounds the background detection a command runs after it has already talked to Basecamp.

View Source
const Surface = "cli"

Surface is what the CLI reports itself as. `basecamp mcp` has no feedback tool, so the CLI never sends cli_mcp.

View Source
const TTL = 24 * time.Hour

TTL is how long a detection answer stands before a refresh is due.

Variables

View Source
var Categories = []string{"bug", "missing_capability", "confusing", "praise", "other"}

Categories are the values the server accepts for category.

Functions

func Credential

func Credential(storedKey string) string

Credential names the credential a request goes out with, without holding it: a BASECAMP_TOKEN, which wins over any stored credential, by a short digest of the token, and otherwise the stored credential's key (a profile, or the host for the default login).

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err is the server's 404 — the feature is off.

func Key

func Key(baseURL, accountID, credential string) string

Key names one person's view of one account on one Basecamp host. Basecamp can answer differently for two people in the same account, so the answer is kept per credential: credential names the one in use (see Credential).

func Override

func Override() (enabled, set bool)

Override reports whether BASECAMP_FEEDBACK forces the feature, and which way.

func ValidCategory

func ValidCategory(c string) bool

ValidCategory reports whether c is one the server accepts.

func WantsHint

func WantsHint(err error) bool

WantsHint reports whether a failed command's error is one the hint belongs on: an answer from Basecamp itself (a server error, a refused request, a missing resource). Usage mistakes, auth, rate limits and the network are the caller's to fix, so they never carry it.

Types

type Getter

type Getter interface {
	Get(ctx context.Context, path string) (*basecamp.Response, error)
}

Getter is the slice of the SDK's account client detection needs.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is the cached detection state, one entry per Basecamp host, account and credential. It lives in the CLI's default cache directory rather than a profile's, because help is rendered before any profile is resolved.

func DefaultStore

func DefaultStore() *Store

DefaultStore returns the store in BASECAMP_CACHE_DIR, or the default cache directory when that is unset.

func NewStore

func NewStore(dir string) *Store

NewStore returns a store kept in dir.

func (*Store) Advertised

func (s *Store) Advertised(key string) bool

Advertised reports the cached answer for one account. A stale answer still counts until a refresh replaces it.

func (*Store) AnyAdvertised

func (s *Store) AnyAdvertised() bool

AnyAdvertised reports whether any account has a cached 200. Help uses this: it is rendered before the account is known, and showing the command for an account where it is off costs only a "not available" when it is run.

func (*Store) BeginRefresh

func (s *Store) BeginRefresh(key string) bool

BeginRefresh notes a detection attempt before it is made, so the failure backoff holds even if the attempt never finishes, and reports whether the note was stored. Where the state cannot be written no answer could be kept either, and every later command would find a refresh due and probe again: a false return means skip the probe.

func (*Store) Detect

func (s *Store) Detect(ctx context.Context, api Getter, key string) (bool, error)

Detect asks Basecamp whether feedback is on for this person and records the answer: 200 means advertised, 404 means not. Any other outcome records a failed attempt, keeps the previous answer, and is returned.

func (*Store) Enabled

func (s *Store) Enabled(key string) bool

Enabled reports whether feedback is on for an account: the override when it is set, the cached answer otherwise.

func (*Store) NeedsRefresh

func (s *Store) NeedsRefresh(key string) bool

NeedsRefresh reports whether the account's answer is due for a detection. A time in the future, from a clock set back since, counts as due, so a wrong clock can't hold the cached answer until it catches up.

func (*Store) Record

func (s *Store) Record(key string, advertised bool)

Record stores a detection answer for the account.

func (*Store) Visible

func (s *Store) Visible() bool

Visible reports whether the command belongs in help and completions: the override when it is set, any cached 200 otherwise.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL