backend

package
v1.59.0 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package backend is the contract a directory backend implements: read-only access to one tenant's accounts, groups and domains, plus the credential handling that gets there.

Every read is a read. A backend never writes to the directory; the one mutating call is Backend.Revoke, which invalidates the hub's own credential at the backend when a workspace is disconnected.

Google Workspace is the first implementation. A second backend (Microsoft Entra) implements this same interface, and nothing above this package knows which one it is talking to — see docs/development/extending.md.

Index

Constants

View Source
const (
	// CredentialOAuth is a refresh token minted by admin consent; it acts
	// as the account that consented.
	CredentialOAuth = "oauth"
	// CredentialServiceAccountKey is a key with domain-wide delegation,
	// impersonating a named admin.
	CredentialServiceAccountKey = "service-account-key"
)

The credential kinds, in the same vocabulary the hub records on a workspace. They are strings rather than an enum because they are also what a store writes down and reads back after a restart.

Variables

View Source
var ErrUnavailable = errors.New("backend: the directory could not be asked")

ErrUnavailable marks a failure that means "could not ask", as opposed to "asked, and was refused".

The distinction is the whole of whether a retry is honest. A directory that answers 503 has told us nothing about the credential, and recording that as a failed probe says a credential is broken when a provider was briefly down. A directory that answers 403 HAS told us something, and retrying it would only delay the truth.

A backend wraps its transient failures with this; everything else is taken at its word.

View Source
var ErrUnsupported = errors.New("backend: unsupported operation")

ErrUnsupported is returned by an operation a backend cannot perform: revoking a service-account key, for instance, which is retired at the backend's own console rather than through an API.

Functions

This section is empty.

Types

type Account

type Account struct {
	// Email is the primary address, lower-cased.
	Email string
	// Live is false for a suspended account.
	Live bool
	// GivenName and FamilyName are empty when the backend cannot supply
	// them; callers must tolerate that.
	GivenName  string
	FamilyName string
}

Account is one address's standing in a directory.

A suspended account is present with Live false. A deleted account is absent — the distinction matters, because both are "gone" to a consumer but only the first can come back.

type Backend

type Backend interface {
	// Kind names the implementation: "google", "entra", "fake".
	Kind() string

	// Tenant returns the tenant id and its current domain list.
	Tenant(ctx context.Context) (Tenant, error)

	// Probe exercises the credential now. A nil error means reads are
	// working at this moment; anything else makes the tenant's domains
	// non-authoritative until a later probe succeeds.
	Probe(ctx context.Context) error

	// Accounts returns every account in the tenant. All or an error.
	Accounts(ctx context.Context) ([]Account, error)

	// Groups returns every group with its flat membership. All or an
	// error, and atomic per group.
	Groups(ctx context.Context) ([]Group, error)

	// Account returns one account. found=false is an authoritative
	// absence: the backend answered not-found. A non-nil error means the
	// read failed and nothing may be concluded from it.
	Account(ctx context.Context, email string) (account Account, found bool, err error)

	// GroupsOf returns the addresses of the groups one account belongs to.
	GroupsOf(ctx context.Context, email string) ([]string, error)

	// Revoke invalidates the hub's credential at the backend. It returns
	// [ErrUnsupported] when the credential kind cannot be revoked, which a
	// caller treats as "deleted locally, retire the credential yourself".
	Revoke(ctx context.Context) error
}

Backend reads one tenant.

Implementations must be safe for concurrent use: the hub probes, refreshes and answers point reads from different goroutines.

type Credential

type Credential struct {
	// Type is one of the credential kinds above.
	Type string
	// Admin is the account the credential acts as. Stored beside the
	// secret because reopening needs it and rediscovering it would cost a
	// round trip on every start.
	Admin string
	// Data is the secret. Treat it as opaque: only the backend that
	// issued it knows its shape.
	Data []byte
}

Credential is everything needed to reopen a backend after a restart, and nothing else.

It exists because a workspace connected in a console has no other home: the deployment never saw the credential, so if the hub does not write it down, a restart silently loses a directory. Data is the secret itself — a refresh token, a service-account key — and never leaves a store, a Portable implementation, or the opener that reads it back.

type Group

type Group struct {
	// Email is the group's address, lower-cased.
	Email string
	// Members are addresses, lower-cased. A group read is atomic: a
	// backend returns every member or an error, never a partial list.
	Members []string
}

Group is one group and its flat membership. Nested groups are NOT expanded: a member that is itself a group appears as its address.

type Portable

type Portable interface {
	Credential() Credential
}

Portable is a backend that can be written down and opened again. A backend that cannot — a fixture, a demonstration tenant — simply does not implement it, and nothing persists it.

type Tenant

type Tenant struct {
	// ID is the backend's own tenant identifier (Google: the customer id).
	ID string
	// Domains are lower-cased and include every domain of the tenant.
	Domains []string
}

Tenant identifies the directory a credential reaches, and the domains it claims. Domains are discovered on every probe, never configured, so a domain moving between tenants is followed without an edit anywhere.

Directories

Path Synopsis
Package fake is a directory backend held in memory, with a scriptable failure for every operation.
Package fake is a directory backend held in memory, with a scriptable failure for every operation.
Package google reads a Google Workspace through the Admin SDK.
Package google reads a Google Workspace through the Admin SDK.

Jump to

Keyboard shortcuts

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