// Package connector_throttle provides a per-(NamedCredential, endpointClass)
// rate-limit substrate for outbound connector calls (NCRM-INT-04B, #1447).
//
// This package ships the full substrate: the real in-process token-bucket
// Service (golang.org/x/time/rate, debt-aware idle-TTL eviction, canonical
// credentialID keying), the SQL-backed LimitProvider reading
// _System_ConnectorRateLimit, and the ComponentKindConnectorRateLimit
// pack-installable component + sweeper that populates the table.
//
// SCOPE: #1447's v1 acceptance contract is now satisfied by the runtime
// composition root wiring this Service into connector_callout.Engine and by
// Engine.Do calling Throttle() before outbound requests. The remaining
// multi-process quota aggregation caveat below is a v2 limitation, not part of
// the v1 closure contract.
//
// # Usage (INT-08 HubSpot client and future connector clients)
//
//	wait, release, err := throttle.Throttle(ctx, "my-connector-prod", "crm.objects.read")
//	if err != nil { return err }
//	defer release() // returns the reservation to the bucket on abort; no-op on success
//	if wait > 0 {
//	    select {
//	    case <-ctx.Done(): return ctx.Err() // defer release() reclaims the token
//	    case <-time.After(wait):
//	    }
//	}
//	// proceed with external request
//
// # Architecture
//
// Rate-limit policies are authored exclusively in connector pack metadata.
// The pack-installer writes rows to _System_ConnectorRateLimit (BLOCKED from
// generic CRUD); NewSQLLimitProvider reads those rows at throttle time.
// Bucket state is keyed by (canonicalID, endpointClass) where canonicalID
// is the stable Definition.ID — not the raw credentialRef. This ensures
// case-variant DeveloperNames (utf8mb4_unicode_ci collation) share one bucket
// and cannot bypass per-credential quota.
//
// # v1 LIMITATION (acknowledged)
//
// v1 LIMITATION (acknowledged): bucket state is in-process only. Multi-replica
// deployments multiply the effective quota by replica count. Cross-process
// aggregation is tracked as a named follow-up; until that follow-up ships, this
// substrate is NOT promoted to "the L0 quota SSoT" in NexusCRM docs.
package connector_throttle
