Documentation
¶
Overview ¶
Package docsaccess is the client half of CF Access integration for the internal docs surface. It lets `da` reach pages under /internal/ on the docs host (e.g. the maintainer-only Starlight build) by attaching a developer's Cloudflare Access service-token headers — CF-Access-Client-Id and CF-Access-Client-Secret — sourced from the local credential store.
Scope boundary: this package only ATTACHES an already-issued service token to outbound requests. The per-user minting endpoint (Cloudflare API POST .../access/service_tokens), which would create those tokens, is the remaining piece and is intentionally not implemented here — it needs a maintainer-provided scoped CF API token to call. Until that lands a developer stores their issued id/secret under the cf-access-client-id / cf-access-client-secret credential ids and this client uses them.
Index ¶
Constants ¶
const ( CredClientID = "cf-access-client-id" CredClientSecret = "cf-access-client-secret" )
Credential ids the resolver is queried with. They match the ids a developer registers their issued CF Access service token under in the credential store.
Variables ¶
var ErrInsecureScheme = errors.New("docsaccess: refusing to attach CF Access credential over non-HTTPS transport")
ErrInsecureScheme signals that a gated /internal/* request used a non-HTTPS scheme. The CF Access service-token headers are bearer-equivalent secrets; attaching them to a plaintext (http://) request would expose the token to any on-path observer. The client refuses to attach over a non-TLS transport and fails loudly rather than leaking the credential.
var ErrMissingCredential = errors.New("docsaccess: missing CF Access service-token credential")
ErrMissingCredential signals that a request targeting the gated /internal/* surface could not be authenticated because a required CF Access credential is absent. The caller asked for protected access; sending an unauthenticated request would silently fail at the edge, so the client fails loudly instead.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client decorates outbound HTTP requests with CF Access service-token headers when, and only when, they target the gated internal docs surface.
func New ¶
New builds a Client. By default it resolves credentials through a freshly constructed credstore.NewLoader() and gates the host from DA_DOCS_HOST (or agorcha.dev). Options override either collaborator.
func (*Client) Decorate ¶
Decorate attaches the CF Access service-token headers to req IFF it targets the gated internal docs surface (host == docsHost AND path under /internal/).
Behavior:
- Non-matching request (public path, or a different host): nothing is set and nil is returned — the request is left exactly as given.
- Matching request with both credentials available: both CF-Access headers are set and nil is returned.
- Matching request with EITHER credential missing/empty: NO header is set (no partial auth) and ErrMissingCredential is returned, so the caller fails loudly rather than firing an unauthenticated request at the edge.
The secret value is never logged; only the credential id and the gating decision are ever surfaced.
func (*Client) HTTPClient ¶
func (c *Client) HTTPClient(base http.RoundTripper) *http.Client
HTTPClient returns an *http.Client whose transport auto-attaches the CF Access headers for gated requests. base may be nil (http.DefaultTransport).
func (*Client) Transport ¶
func (c *Client) Transport(base http.RoundTripper) http.RoundTripper
Transport returns an http.RoundTripper that auto-attaches the CF Access headers (via Decorate) before delegating to base. base may be nil, in which case http.DefaultTransport is used. A decoration error (a gated request with no credential) aborts the round trip with that error rather than sending an unauthenticated request.
type CredResolver ¶
CredResolver is the narrow token source the client depends on (interface-DI, docs/TEST_SEAMS.md). *credstore.Loader satisfies it directly; tests inject a fake to drive the present / missing / partial-credential branches.
type Option ¶
type Option func(*Client)
Option customizes a Client at construction.
func WithDocsHost ¶
WithDocsHost overrides the gated docs host (defaults to DA_DOCS_HOST, else agorcha.dev). The value is matched host-only; any port on the request URL is ignored.
func WithResolver ¶
func WithResolver(r CredResolver) Option
WithResolver sets the credential source. Production passes a *credstore.Loader; tests pass a fake CredResolver.