onboarding

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseInviteCode

func ParseInviteCode(raw string) (code, origin string, err error)

ParseInviteCode extracts the invite code, and the backend origin it names, from whatever form the member pasted.

Three forms are accepted: the bare code, the desktop deep link, and the join-page URL whose fragment carries the code (a fragment never reaches server logs). Only the https form knows where the Project lives, so only it returns an origin; the other two return an empty one, meaning "the backend the caller selected". This is what lets a member on a purely local profile paste a link and join a team Project on a server this Mac has never used, without being asked which server that was.

func ValidateAPIOrigin

func ValidateAPIOrigin(raw string) (string, error)

ValidateAPIOrigin canonicalizes a backend origin a member supplied.

The rule is exactly hosted.New's, because that is the client every later call goes through: an HTTPS origin, or loopback HTTP for a backend running on this Mac, with no path, query, fragment, or userinfo. Checking it here means the member is told at the field rather than by the first request that fails.

Types

type CredentialStore

type CredentialStore interface {
	Put(context.Context, string, string) error
	Get(context.Context, string) (string, error)
	Delete(context.Context, string) error
}

type Options

type Options struct {
	ConfigRoot, RepositoryRoot, ProjectLabel, DeviceLabel, AppVersion string
	// DisplayName is optional; empty means the member has not chosen one yet.
	DisplayName string
	// SkipInvite creates the Project without minting a one-use invite. A local
	// Project has no second member to hand one to, and offering a code is how a
	// screen implies that inviting somebody is the next step (ADR-072).
	SkipInvite bool
}

type ResetOutcome

type ResetOutcome struct {
	Status            hosted.CredentialStatus
	BackendID         string
	APIBaseURL        string
	DeviceID          string
	ClearedWorkspaces int
	CredentialDeleted bool
}

ResetOutcome describes what a reset changed on this device.

func ResetAll

func ResetAll(ctx context.Context, configRoot string, force bool) ([]ResetOutcome, error)

ResetAll runs Reset for every backend on the profile, which is what a member asking to forget this Mac entirely means. It reports each backend's outcome and stops at the first refusal, so a working enrollment is never erased on the way to a broken one.

type Result

type Result struct {
	ProjectID, DeviceID, WorkspaceID, WorkstreamID string
	JoinCode, DashboardTicket                      string
}

type Service

type Service struct {
	Backend  config.Backend
	Client   func(token string) (API, error)
	Creds    CredentialStore
	Register func(context.Context, string, string, string, config.Workspace) error
}

Service is one onboarding flow against one backend. The backend travels with the flow rather than with the profile: a Mac holds a device identity per backend (ADR-069, ADR-074), so "which server" and "which credential" are one question and are answered together.

func New

func New(backend config.Backend) Service

func (Service) Create

func (s Service) Create(ctx context.Context, options Options) (Result, error)

func (Service) CreateAdditional

func (s Service) CreateAdditional(ctx context.Context, options Options, deviceID, token string) (Result, error)

CreateAdditional creates another Project for a device that is already enrolled in the local profile. The existing credential is deliberately reused: one per-user service has one device identity across its Projects. Unlike first enrollment, a local registration failure must never revoke the shared device and strand its existing Projects.

func (Service) CreateOnNewBackend

func (s Service) CreateOnNewBackend(ctx context.Context, options Options) (Result, error)

CreateOnNewBackend creates a Project on this flow's backend, whether or not the profile has used that backend before.

A backend the profile has never seen gets a device identity minted for it; one it already has an identity for reuses that identity, because a second credential for the same server would strand the Projects the first one holds. Both cases are one member action - "add a Project on this server" - so the choice is made here rather than in each caller.

func (Service) CredentialState

func (s Service) CredentialState(ctx context.Context, configRoot string) (hosted.CredentialStatus, config.Config, error)

CredentialState reports whether the credential stored for this flow's backend is still accepted by it. A backend this profile has no device identity for is reported as OK because there is nothing that could have been rejected.

It is per backend, not per profile: one revoked team Project says nothing about the local Project beside it.

func (Service) Join

func (s Service) Join(ctx context.Context, options Options, joinCode string) (Result, error)

func (Service) JoinAdditional

func (s Service) JoinAdditional(ctx context.Context, options Options, deviceID, token, joinCode string) (Result, error)

JoinAdditional redeems an invite for a device that is already enrolled in the local profile, adding a second Project without a second device identity.

It is the join counterpart of CreateAdditional and shares its rule: the existing credential is reused, and a local registration failure must never revoke the shared device and strand the Projects this Mac already has. That is why it does not route through Join, whose rollback revokes the device it just created - here that device is the one holding every other Project.

func (Service) JoinOnNewBackend

func (s Service) JoinOnNewBackend(ctx context.Context, options Options, joinCode string) (Result, error)

JoinOnNewBackend redeems an invite on this flow's backend, minting a device identity for a backend the profile has never used and reusing the one it has otherwise. Joining a friend's team Project from a purely local profile is the first case, and it is the common one.

func (Service) Reset

func (s Service) Reset(ctx context.Context, configRoot string, force bool) (ResetOutcome, error)

Reset forgets this device's identity on one backend so the member can enroll against it again. It deletes that backend's stored credential and removes the backend, its Projects, and the repositories registered to them. Every other backend on the profile is untouched, which is the whole point of binding Projects to backends: a revoked team Project must not take the local Project down with it.

It refuses unless that backend has actually rejected the credential. Being offline is not being locked out, and erasing a working enrollment cannot be undone. force exists for support and headless recovery, where the operator has already established that the enrollment is dead.

Jump to

Keyboard shortcuts

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