localowner

package
v0.47.8 Latest Latest
Warning

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

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

Documentation

Overview

Package localowner realizes and verifies the init-owned human identity in the local PocketID runtime without exposing its bootstrap credential.

Index

Constants

View Source
const StepUpCallbackPath = "/api/v1/identity/step-up/callback"
View Source
const StepUpClientID = "stackkits-owner-step-up"

Variables

View Source
var ErrStepUpRejected = errors.New("localowner: current PocketID owner approval required")

Functions

func ApplicationOIDCClientID added in v0.47.3

func ApplicationOIDCClientID(workloadRef string) string

ApplicationOIDCClientID is the stable Pocket ID client ID of a workload.

func ApplicationOIDCClientSecretRef added in v0.47.3

func ApplicationOIDCClientSecretRef(workloadRef string) string

ApplicationOIDCClientSecretRef is the custody ref of a workload's issued Pocket ID client secret.

func ConsumeRemoteActionApproval

func ConsumeRemoteActionApproval(workspaceRoot string, receipt json.RawMessage, expected RemoteActionApprovalBinding, trust StepUpTrust, now time.Time) error

ConsumeRemoteActionApproval is a cross-process no-replace replay journal in existing local custody. A crash after consumption leaves the approval spent; resume through the executor's existing operation journal, never replay it.

func NormalizeStepUpOrigin

func NormalizeStepUpOrigin(origin string) (string, error)

NormalizeStepUpOrigin keeps registration, the browser Origin and OAuth callback on one canonical HTTPS origin. Unsupported host forms fail during startup.

func StepUpNonce

func StepUpNonce(binding RemoteActionApprovalBinding) (string, error)

func VerifyRemoteActionApproval

func VerifyRemoteActionApproval(ctx context.Context, workspaceRoot, origin string, receipt json.RawMessage, expected RemoteActionApprovalBinding) error

VerifyRemoteActionApproval requires the live Home owner/client projection and consumes the exact approval before the caller dispatches any mutation.

func VerifyRemoteActionApprovalClaims

func VerifyRemoteActionApprovalClaims(receipt json.RawMessage, expected RemoteActionApprovalBinding, trust StepUpTrust, now time.Time) error

VerifyRemoteActionApprovalClaims verifies the independent human signature. It performs no mutation. The executor must consume the approval durably before its first side effect, using ConsumeRemoteActionApproval or its existing replay journal, after all action, device, target and current Home-trust admission.

Types

type ApplicationOIDCClient added in v0.47.3

type ApplicationOIDCClient struct {
	ClientID string
	Issuer   string
}

ApplicationOIDCClient is the secret-free result: the client ID and the issuer URL the application discovers Pocket ID at.

type ApplicationOIDCClientRequest added in v0.47.3

type ApplicationOIDCClientRequest struct {
	// RequiredPrivilege comes from the validated catalog endpoint. Empty keeps
	// the existing household application policy; vault always requires vault.
	RequiredPrivilege string
	// Public is admitted only for the governed Smart Home PKCE integration.
	Public   bool
	ClientID string
	Name     string
	// CallbackURL keeps the single-callback contract for existing callers.
	// CallbackURLs is used by applications such as Immich that own several
	// exact browser and mobile callbacks. Callers set exactly one form.
	CallbackURL  string
	CallbackURLs []string
	SecretRef    string
}

ApplicationOIDCClientRequest names one application's governed Pocket ID client. The client ID is stable per workload; SecretRef is the custody ref the issued client secret is stored under.

type DomainMigration added in v0.47.7

type DomainMigration struct {
	From   string   `json:"from"`
	To     string   `json:"to"`
	Status string   `json:"status"`
	Next   []string `json:"next"`
}

DomainMigration reports local preparation, never runtime deployment or login.

type DomainMigrationIntent added in v0.47.7

type DomainMigrationIntent interface {
	Candidate([]byte) ([]byte, error)
	Persist(workspace, specPath string, before, after []byte) error
}

MigrateBasementDomain requires the caller's explicit owner approval and idle lifecycle mutation lock. All local writes are authenticated and replayable. The existing user subjects, client secrets, CA and signing keys stay intact.

type HouseholdUser

type HouseholdUser struct {
	Username    string
	Email       string
	DisplayName string
	Status      string
	ExpiresAt   time.Time
	SetupURL    string
}

HouseholdUser is one non-owner PocketID subject in the household group.

type HouseholdUserSpec

type HouseholdUserSpec struct {
	Username    string
	Email       string
	DisplayName string
}

HouseholdUserSpec is the owner-supplied identity for one household member.

type OwnerActivation

type OwnerActivation struct {
	Status    string
	Origin    string
	ExpiresAt time.Time
	SetupURL  string
}

OwnerActivation is the owner-bound passkey enrollment state. SetupURL is returned only by the explicit activation operation and must remain transient.

type OwnerEmailVerification added in v0.47.7

type OwnerEmailVerification struct {
	Status string
}

OwnerEmailVerification records only the current PocketID readback. Pending means the owner must request and consume the mailed token in their own authenticated PocketID session; administrator custody cannot perform that confirmation on the owner's behalf.

type RemoteActionApproval

type RemoteActionApproval struct {
	IDToken string `json:"idToken"`
}

RemoteActionApproval preserves the actual PocketID signature. A lifecycle owner-key signature cannot replace this token or satisfy human approval. Treat this structure as a credential: never put it in logs or public receipts.

type RemoteActionApprovalBinding

type RemoteActionApprovalBinding struct {
	ActionDigest  string    `json:"actionDigest"`
	PlanHash      string    `json:"planHash"`
	Action        string    `json:"action"`
	OwnerRef      string    `json:"ownerRef"`
	HomeSiteRef   string    `json:"homeSiteRef"`
	TargetSiteRef string    `json:"targetSiteRef"`
	TargetNodeRef string    `json:"targetNodeRef"`
	IssuedAt      time.Time `json:"issuedAt"`
	ExpiresAt     time.Time `json:"expiresAt"`
}

RemoteActionApprovalBinding is supplied by the admitted action receiver, never copied from the receipt. ActionDigest covers the unsigned action envelope, including its nonce and idempotency key, but excludes the approval itself.

type Result

type Result struct {
	Binding        localevidence.OwnerRuntimeBinding
	EnrollmentPath string
}

type Service

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

func NewService

func NewService(workspaceRoot string) (*Service, error)

func (*Service) ActivateHouseholdUser added in v0.47.7

func (s *Service) ActivateHouseholdUser(ctx context.Context, username string) (HouseholdUser, error)

ActivateHouseholdUser reissues enrollment for the same non-owner subject. It preserves memberships and data and refuses owner/admin identity changes.

func (*Service) AddHouseholdUser

func (s *Service) AddHouseholdUser(ctx context.Context, spec HouseholdUserSpec) (HouseholdUser, error)

AddHouseholdUser creates a non-admin PocketID subject in the household group and returns a one-time passkey enrollment URL. Owners, admins and break-glass identities are refused.

func (*Service) ConfigureOwnerEmailVerification added in v0.47.7

func (s *Service) ConfigureOwnerEmailVerification(ctx context.Context, email string, smtp pocketid.SMTPConfiguration) (OwnerEmailVerification, error)

ConfigureOwnerEmailVerification configures authenticated SMTP delivery for the exact bound owner and reports whether PocketID has observed a real email confirmation. It deliberately works before passkey activation so automatic application setup cannot prevent the owner from reaching activation.

func (*Service) EnsureApplicationOIDCClient added in v0.47.3

func (s *Service) EnsureApplicationOIDCClient(ctx context.Context, request ApplicationOIDCClientRequest) (ApplicationOIDCClient, error)

EnsureApplicationOIDCClient registers or converges a governed, PKCE-enabled Pocket ID client for one application, restricted to the same owner groups as the TinyAuth gate, and keeps its secret in local custody as an issued secret. An existing client keeps its secret while custody holds it; a client whose secret custody was lost receives a new secret. The exact public Smart Home client never issues or custodies a secret.

func (*Service) EnsureImmichUserClaims added in v0.47.7

func (s *Service) EnsureImmichUserClaims(ctx context.Context) error

EnsureImmichUserClaims converges the application role of the exact signed owner and every household subject before Photos is applied. It preserves unrelated per-user claims, memberships, credentials and Pocket ID admin flags. Verify never calls this mutating operation. Callers hold the lifecycle lock.

func (*Service) ExchangeStepUpCode

func (s *Service) ExchangeStepUpCode(ctx context.Context, origin, code, verifier string, expected RemoteActionApprovalBinding) (json.RawMessage, error)

ExchangeStepUpCode uses only the fixed local PocketID endpoint. Neither an incoming token nor discovery metadata may redirect a request to another host.

func (*Service) IssueOwnerActivation

func (s *Service) IssueOwnerActivation(ctx context.Context) (OwnerActivation, error)

IssueOwnerActivation mints a fresh one-time URL for an owner who has not registered a passkey and retires the previously issued link first, so an owner who opened a link without finishing enrollment is never handed the consumed code again and at most one activation link stays redeemable. It never mints a link for an active owner.

func (*Service) ListHouseholdUsers

func (s *Service) ListHouseholdUsers(ctx context.Context) ([]HouseholdUser, error)

ListHouseholdUsers returns non-admin PocketID subjects in the household group.

func (*Service) MigrateBasementDomain added in v0.47.7

func (s *Service) MigrateBasementDomain(ctx context.Context, specPath string, intent DomainMigrationIntent, quiesceRuntime bool) (DomainMigration, error)

func (*Service) OwnerActivationStatus

func (s *Service) OwnerActivationStatus(ctx context.Context) (OwnerActivation, error)

OwnerActivationStatus verifies the exact owner runtime binding and reports completion from PocketID's passkey records.

func (*Service) PrepareStepUp

func (s *Service) PrepareStepUp(ctx context.Context, origin string) (StepUpTrust, error)

PrepareStepUp binds a dedicated confidential PKCE client to an explicitly configured HTTPS server origin. Existing clients are verified, never silently rewritten.

func (*Service) ReadStepUpTrust

func (s *Service) ReadStepUpTrust(ctx context.Context, origin string) (StepUpTrust, error)

ReadStepUpTrust verifies current owner, client and public signing keys without creating or changing identity resources. The remote peer enrollment owner may project this trust only through its existing authenticated custody contract.

func (*Service) Realize

func (s *Service) Realize(ctx context.Context) (Result, error)

Realize creates the exact desired PocketID owner once, persists a private one-time passkey-enrollment URL, and records a secret-free signed binding to ownerRef and the step-ca certificate chain.

A reset host answers as an empty PocketID: reachable, unbootstrapped, and without the subject, groups, or client the workspace recorded. Realize treats that as work to redo rather than as a reason to refuse, so re-running an install rebuilds the owner from the custody that survived on disk.

func (*Service) RemoveHouseholdUser

func (s *Service) RemoveHouseholdUser(ctx context.Context, username string) error

RemoveHouseholdUser deletes one household subject. Owner and admin identities are refused.

func (*Service) Verify

Verify performs only authenticated readback. It verifies custody and the signed binding before any network request and never creates or updates a PocketID resource.

type StepUpTrust

type StepUpTrust struct {
	Issuer      string
	Subject     string
	OwnerRef    string
	HomeSiteRef string
	Keys        jose.JSONWebKeySet
}

StepUpTrust must come from admitted Home identity custody. A caller must never accept issuer, subject, or keys supplied alongside an untrusted approval. Remote consumers also need a current admitted client/owner projection: offline verification alone cannot discover a disabled owner or changed client policy.

Jump to

Keyboard shortcuts

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