Documentation
¶
Overview ¶
Package platform is the platform of one workspace (ADR-0021): it keeps the workspace's members, roles, permissions, invites, projects and the audit log. It runs no containers: agents do. An installation keeps exactly one workspace, made at its first start with its owner. It keeps its own accounts: sign-in (package auth) runs inside it at /auth, for the owner, the members and the invited alone (ADR-0024). It decides permissions itself.
Index ¶
- Constants
- Variables
- func AccessOf(m protoreflect.MethodDescriptor) *workspacev1.Access
- func ChangeOwnerEmail(ctx context.Context, pool *pgxpool.Pool, email string, now time.Time) (string, error)
- type Action
- type Config
- type Extensions
- type Kind
- type Policy
- type PolicyFunc
- type Service
- func (s *Service) ApplyUpdate(ctx context.Context, req *connect.Request[workspacev1.ApplyUpdateRequest]) (*connect.Response[workspacev1.ApplyUpdateResponse], error)
- func (s *Service) CertifySigningKey(ctx context.Context, ...) (*connect.Response[workspacev1.CertifySigningKeyResponse], error)
- func (s *Service) Check() connect.HandlerOption
- func (s *Service) CreateEnvironment(ctx context.Context, ...) (*connect.Response[workspacev1.CreateEnvironmentResponse], error)
- func (s *Service) CreateInvite(ctx context.Context, req *connect.Request[workspacev1.CreateInviteRequest]) (*connect.Response[workspacev1.CreateInviteResponse], error)
- func (s *Service) CreateProject(ctx context.Context, req *connect.Request[workspacev1.CreateProjectRequest]) (*connect.Response[workspacev1.CreateProjectResponse], error)
- func (s *Service) CreateSecretsKey(ctx context.Context, req *connect.Request[workspacev1.CreateSecretsKeyRequest]) (*connect.Response[workspacev1.CreateSecretsKeyResponse], error)
- func (s *Service) CreateServer(ctx context.Context, req *connect.Request[workspacev1.CreateServerRequest]) (*connect.Response[workspacev1.CreateServerResponse], error)
- func (s *Service) DeleteProject(ctx context.Context, req *connect.Request[workspacev1.DeleteProjectRequest]) (*connect.Response[workspacev1.DeleteProjectResponse], error)
- func (s *Service) DeployProduction(ctx context.Context, req *connect.Request[workspacev1.DeployProductionRequest]) (*connect.Response[workspacev1.DeployProductionResponse], error)
- func (s *Service) Enter(w http.ResponseWriter, r *http.Request, email string, authorize url.Values) error
- func (s *Service) GetProjectConfig(ctx context.Context, req *connect.Request[workspacev1.GetProjectConfigRequest]) (*connect.Response[workspacev1.GetProjectConfigResponse], error)
- func (s *Service) GetSecretsKey(ctx context.Context, req *connect.Request[workspacev1.GetSecretsKeyRequest]) (*connect.Response[workspacev1.GetSecretsKeyResponse], error)
- func (s *Service) GetUpdate(context.Context, *connect.Request[workspacev1.GetUpdateRequest]) (*connect.Response[workspacev1.GetUpdateResponse], error)
- func (s *Service) GetWorkspace(ctx context.Context, req *connect.Request[workspacev1.GetWorkspaceRequest]) (*connect.Response[workspacev1.GetWorkspaceResponse], error)
- func (s *Service) Handler() http.Handler
- func (s *Service) JoinServer(ctx context.Context, req *connect.Request[workspacev1.JoinServerRequest]) (*connect.Response[workspacev1.JoinServerResponse], error)
- func (s *Service) ListAudit(ctx context.Context, req *connect.Request[workspacev1.ListAuditRequest]) (*connect.Response[workspacev1.ListAuditResponse], error)
- func (s *Service) ListEnvironments(ctx context.Context, req *connect.Request[workspacev1.ListEnvironmentsRequest]) (*connect.Response[workspacev1.ListEnvironmentsResponse], error)
- func (s *Service) ListInvites(ctx context.Context, _ *connect.Request[workspacev1.ListInvitesRequest]) (*connect.Response[workspacev1.ListInvitesResponse], error)
- func (s *Service) ListMembers(ctx context.Context, _ *connect.Request[workspacev1.ListMembersRequest]) (*connect.Response[workspacev1.ListMembersResponse], error)
- func (s *Service) ListProjectVersions(ctx context.Context, ...) (*connect.Response[workspacev1.ListProjectVersionsResponse], error)
- func (s *Service) ListProjects(ctx context.Context, _ *connect.Request[workspacev1.ListProjectsRequest]) (*connect.Response[workspacev1.ListProjectsResponse], error)
- func (s *Service) ListSecrets(ctx context.Context, req *connect.Request[workspacev1.ListSecretsRequest]) (*connect.Response[workspacev1.ListSecretsResponse], error)
- func (s *Service) ListServers(ctx context.Context, req *connect.Request[workspacev1.ListServersRequest]) (*connect.Response[workspacev1.ListServersResponse], error)
- func (s *Service) ListServiceTypes(context.Context, *connect.Request[workspacev1.ListServiceTypesRequest]) (*connect.Response[workspacev1.ListServiceTypesResponse], error)
- func (s *Service) ListSigningKeys(ctx context.Context, req *connect.Request[workspacev1.ListSigningKeysRequest]) (*connect.Response[workspacev1.ListSigningKeysResponse], error)
- func (s *Service) ListWorkspaces(ctx context.Context, _ *connect.Request[workspacev1.ListWorkspacesRequest]) (*connect.Response[workspacev1.ListWorkspacesResponse], error)
- func (s *Service) PrepareRotation(ctx context.Context, _ *connect.Request[workspacev1.PrepareRotationRequest]) (*connect.Response[workspacev1.PrepareRotationResponse], error)
- func (s *Service) ProvideKeyWraps(ctx context.Context, req *connect.Request[workspacev1.ProvideKeyWrapsRequest]) (*connect.Response[workspacev1.ProvideKeyWrapsResponse], error)
- func (s *Service) PutApp(ctx context.Context, req *connect.Request[workspacev1.PutAppRequest]) (*connect.Response[workspacev1.PutAppResponse], error)
- func (s *Service) PutService(ctx context.Context, req *connect.Request[workspacev1.PutServiceRequest]) (*connect.Response[workspacev1.PutServiceResponse], error)
- func (s *Service) RegisterDeviceKey(ctx context.Context, ...) (*connect.Response[workspacev1.RegisterDeviceKeyResponse], error)
- func (s *Service) RegisterSigningKey(ctx context.Context, ...) (*connect.Response[workspacev1.RegisterSigningKeyResponse], error)
- func (s *Service) RemoveApp(ctx context.Context, req *connect.Request[workspacev1.RemoveAppRequest]) (*connect.Response[workspacev1.RemoveAppResponse], error)
- func (s *Service) RemoveEnvironment(ctx context.Context, ...) (*connect.Response[workspacev1.RemoveEnvironmentResponse], error)
- func (s *Service) RemoveMember(ctx context.Context, req *connect.Request[workspacev1.RemoveMemberRequest]) (*connect.Response[workspacev1.RemoveMemberResponse], error)
- func (s *Service) RemoveSecret(ctx context.Context, req *connect.Request[workspacev1.RemoveSecretRequest]) (*connect.Response[workspacev1.RemoveSecretResponse], error)
- func (s *Service) RemoveServer(ctx context.Context, req *connect.Request[workspacev1.RemoveServerRequest]) (*connect.Response[workspacev1.RemoveServerResponse], error)
- func (s *Service) RemoveService(ctx context.Context, req *connect.Request[workspacev1.RemoveServiceRequest]) (*connect.Response[workspacev1.RemoveServiceResponse], error)
- func (s *Service) RevokeInvite(ctx context.Context, req *connect.Request[workspacev1.RevokeInviteRequest]) (*connect.Response[workspacev1.RevokeInviteResponse], error)
- func (s *Service) RollbackProject(ctx context.Context, req *connect.Request[workspacev1.RollbackProjectRequest]) (*connect.Response[workspacev1.RollbackProjectResponse], error)
- func (s *Service) RotateSecretsKey(ctx context.Context, req *connect.Request[workspacev1.RotateSecretsKeyRequest]) (*connect.Response[workspacev1.RotateSecretsKeyResponse], error)
- func (s *Service) Run(ctx context.Context)
- func (s *Service) SetMemberRole(ctx context.Context, req *connect.Request[workspacev1.SetMemberRoleRequest]) (*connect.Response[workspacev1.SetMemberRoleResponse], error)
- func (s *Service) SetSecret(ctx context.Context, req *connect.Request[workspacev1.SetSecretRequest]) (*connect.Response[workspacev1.SetSecretResponse], error)
- func (s *Service) SetServerProjects(ctx context.Context, ...) (*connect.Response[workspacev1.SetServerProjectsResponse], error)
- func (s *Service) SetTrustRoot(ctx context.Context, req *connect.Request[workspacev1.SetTrustRootRequest]) (*connect.Response[workspacev1.SetTrustRootResponse], error)
- func (s *Service) SignVersion(ctx context.Context, req *connect.Request[workspacev1.SignVersionRequest]) (*connect.Response[workspacev1.SignVersionResponse], error)
- func (s *Service) UpdateProjectSettings(ctx context.Context, ...) (*connect.Response[workspacev1.UpdateProjectSettingsResponse], error)
- func (s *Service) WorkspaceID() string
- type Updates
- type Usage
Constants ¶
const AuthPath = "/auth"
AuthPath is where sign-in lives on the platform's address.
const InviteTTL = 7 * 24 * time.Hour
InviteTTL is how long an invite can be accepted.
Variables ¶
var Kinds = []Kind{InviteMember, JoinMember, CreateProject, AddServer, CreateEnvironment}
Kinds are every action a policy is asked about.
Functions ¶
func AccessOf ¶
func AccessOf(m protoreflect.MethodDescriptor) *workspacev1.Access
AccessOf is the access a method declares in proto; nil when it declares none.
func ChangeOwnerEmail ¶ added in v0.3.0
func ChangeOwnerEmail(ctx context.Context, pool *pgxpool.Pool, email string, now time.Time) (string, error)
ChangeOwnerEmail gives the workspace's owner another email, from the server the platform runs on (Q9: an owner who lost their mailbox): whoever holds the server may. The owner stays the same account — its devices, keys and role — and signs in with the new email; their sessions end. An owner who never signed in becomes whoever signs in first with it. It returns the former email. A running platform learns of it when it restarts.
Types ¶
type Action ¶
type Action struct {
Kind Kind
// Actor is the email of who acts.
Actor string
// Email and Role, of a member; Project and Server, of what is made.
Email, Role string
Project, Server string
Usage Usage
}
Action is what a policy is asked: the action, who asks, and what the workspace holds before it.
type Config ¶
type Config struct {
// PublicURL is the server's address as clients use it. It is the audience of the
// access tokens it accepts: a token for another server — a self-hosted one run by
// someone else, say — does not work here, and ours not there.
PublicURL string
// Workspace and Owner make the workspace at the first start: its name and the email
// of its owner, who becomes its member with the role owner when they first call. Later starts keep what
// is there.
Workspace, Owner string
// Mailer sends sign-in codes and invites; the log when nil.
Mailer mail.Mailer
// TrustProxy takes the client's address from X-Forwarded-For (sign-in limits):
// only behind a proxy that sets it.
TrustProxy bool
Log *slog.Logger
// Now is the clock; time.Now when nil.
Now func() time.Time
// Extensions are what another build adds; the core has none.
Extensions Extensions
// Version is the platform's: what its releases are compared with.
Version string
// Updates is how it learns of new releases and applies one.
Updates Updates
}
Config configures the server.
type Extensions ¶
type Extensions struct {
// Policy is asked before the actions an installation may limit; nil allows all.
Policy Policy
// Setup gives the workspace and its owner at the first start; nil takes
// Config.Workspace and Config.Owner (the flags of devopus-server).
Setup func(ctx context.Context) (workspace, owner string, err error)
// Mount adds handlers to the platform's address: an API of its own, more RPC
// (behind Service.Check). It runs once, in Handler.
Mount func(mux *http.ServeMux, s *Service)
// Plan is what the workspace's people see of its plan; nil shows none.
Plan func(ctx context.Context) *workspacev1.Plan
// SignIn is a sign-in elsewhere the sign-in pages offer next to the email: the
// cloud's site, where the person is signed in already. It ends in Enter. nil
// offers none.
SignIn *auth.External
}
Extensions are what another build of the platform adds to the core (ADR-0021): the core runs with none, and nothing in it knows what fills them.
type Kind ¶
type Kind string
Kind is an action a policy is asked about.
const ( // InviteMember: Email is invited with Role. InviteMember Kind = "member.invite" // JoinMember: Email accepts their invite and joins with Role. JoinMember Kind = "member.join" // CreateProject: Project is made. CreateProject Kind = "project.create" // AddServer: Server, a server of the team, is added. AddServer Kind = "server.add" // CreateEnvironment: an environment of Project on Server is made. CreateEnvironment Kind = "environment.create" )
type Policy ¶
Policy decides whether an installation allows an action: its error, a reason a person reads, refuses it. The caller's role is checked before it.
type PolicyFunc ¶
PolicyFunc is a Policy of a function.
type Service ¶
type Service struct {
workspacev1connect.UnimplementedWorkspaceServiceHandler
// contains filtered or unexported fields
}
Service is the workspace server.
func (*Service) ApplyUpdate ¶ added in v0.2.0
func (s *Service) ApplyUpdate(ctx context.Context, req *connect.Request[workspacev1.ApplyUpdateRequest]) (*connect.Response[workspacev1.ApplyUpdateResponse], error)
func (*Service) CertifySigningKey ¶
func (s *Service) CertifySigningKey(ctx context.Context, req *connect.Request[workspacev1.CertifySigningKeyRequest]) (*connect.Response[workspacev1.CertifySigningKeyResponse], error)
func (*Service) Check ¶
func (s *Service) Check() connect.HandlerOption
Check is the access check of the platform's RPC for handlers an extension mounts: their methods declare access like the core's.
func (*Service) CreateEnvironment ¶
func (s *Service) CreateEnvironment(ctx context.Context, req *connect.Request[workspacev1.CreateEnvironmentRequest]) (*connect.Response[workspacev1.CreateEnvironmentResponse], error)
func (*Service) CreateInvite ¶
func (s *Service) CreateInvite(ctx context.Context, req *connect.Request[workspacev1.CreateInviteRequest]) (*connect.Response[workspacev1.CreateInviteResponse], error)
func (*Service) CreateProject ¶
func (s *Service) CreateProject(ctx context.Context, req *connect.Request[workspacev1.CreateProjectRequest]) (*connect.Response[workspacev1.CreateProjectResponse], error)
func (*Service) CreateSecretsKey ¶
func (s *Service) CreateSecretsKey(ctx context.Context, req *connect.Request[workspacev1.CreateSecretsKeyRequest]) (*connect.Response[workspacev1.CreateSecretsKeyResponse], error)
func (*Service) CreateServer ¶
func (s *Service) CreateServer(ctx context.Context, req *connect.Request[workspacev1.CreateServerRequest]) (*connect.Response[workspacev1.CreateServerResponse], error)
func (*Service) DeleteProject ¶
func (s *Service) DeleteProject(ctx context.Context, req *connect.Request[workspacev1.DeleteProjectRequest]) (*connect.Response[workspacev1.DeleteProjectResponse], error)
func (*Service) DeployProduction ¶
func (s *Service) DeployProduction(ctx context.Context, req *connect.Request[workspacev1.DeployProductionRequest]) (*connect.Response[workspacev1.DeployProductionResponse], error)
func (*Service) Enter ¶ added in v0.4.0
func (s *Service) Enter(w http.ResponseWriter, r *http.Request, email string, authorize url.Values) error
Enter signs in an email an extension has checked (Extensions.SignIn) and sends the browser on: for the CLI's browser sign-in (authorize, its request) to the CLI's callback; for the web, with authorize empty, to the workspace's pages, signed in. Who may sign in is asked as for a code.
func (*Service) GetProjectConfig ¶
func (s *Service) GetProjectConfig(ctx context.Context, req *connect.Request[workspacev1.GetProjectConfigRequest]) (*connect.Response[workspacev1.GetProjectConfigResponse], error)
func (*Service) GetSecretsKey ¶
func (s *Service) GetSecretsKey(ctx context.Context, req *connect.Request[workspacev1.GetSecretsKeyRequest]) (*connect.Response[workspacev1.GetSecretsKeyResponse], error)
func (*Service) GetUpdate ¶ added in v0.2.0
func (s *Service) GetUpdate(context.Context, *connect.Request[workspacev1.GetUpdateRequest]) (*connect.Response[workspacev1.GetUpdateResponse], error)
func (*Service) GetWorkspace ¶
func (s *Service) GetWorkspace(ctx context.Context, req *connect.Request[workspacev1.GetWorkspaceRequest]) (*connect.Response[workspacev1.GetWorkspaceResponse], error)
func (*Service) JoinServer ¶
func (s *Service) JoinServer(ctx context.Context, req *connect.Request[workspacev1.JoinServerRequest]) (*connect.Response[workspacev1.JoinServerResponse], error)
func (*Service) ListAudit ¶
func (s *Service) ListAudit(ctx context.Context, req *connect.Request[workspacev1.ListAuditRequest]) (*connect.Response[workspacev1.ListAuditResponse], error)
func (*Service) ListEnvironments ¶
func (s *Service) ListEnvironments(ctx context.Context, req *connect.Request[workspacev1.ListEnvironmentsRequest]) (*connect.Response[workspacev1.ListEnvironmentsResponse], error)
func (*Service) ListInvites ¶
func (s *Service) ListInvites(ctx context.Context, _ *connect.Request[workspacev1.ListInvitesRequest]) (*connect.Response[workspacev1.ListInvitesResponse], error)
func (*Service) ListMembers ¶
func (s *Service) ListMembers(ctx context.Context, _ *connect.Request[workspacev1.ListMembersRequest]) (*connect.Response[workspacev1.ListMembersResponse], error)
func (*Service) ListProjectVersions ¶
func (s *Service) ListProjectVersions(ctx context.Context, req *connect.Request[workspacev1.ListProjectVersionsRequest]) (*connect.Response[workspacev1.ListProjectVersionsResponse], error)
func (*Service) ListProjects ¶
func (s *Service) ListProjects(ctx context.Context, _ *connect.Request[workspacev1.ListProjectsRequest]) (*connect.Response[workspacev1.ListProjectsResponse], error)
ListProjects shows every project of the workspace: a role holds in all of them.
func (*Service) ListSecrets ¶
func (s *Service) ListSecrets(ctx context.Context, req *connect.Request[workspacev1.ListSecretsRequest]) (*connect.Response[workspacev1.ListSecretsResponse], error)
func (*Service) ListServers ¶
func (s *Service) ListServers(ctx context.Context, req *connect.Request[workspacev1.ListServersRequest]) (*connect.Response[workspacev1.ListServersResponse], error)
func (*Service) ListServiceTypes ¶
func (s *Service) ListServiceTypes(context.Context, *connect.Request[workspacev1.ListServiceTypesRequest]) (*connect.Response[workspacev1.ListServiceTypesResponse], error)
func (*Service) ListSigningKeys ¶
func (s *Service) ListSigningKeys(ctx context.Context, req *connect.Request[workspacev1.ListSigningKeysRequest]) (*connect.Response[workspacev1.ListSigningKeysResponse], error)
func (*Service) ListWorkspaces ¶
func (s *Service) ListWorkspaces(ctx context.Context, _ *connect.Request[workspacev1.ListWorkspacesRequest]) (*connect.Response[workspacev1.ListWorkspacesResponse], error)
ListWorkspaces is the platform's workspace when the caller is a member of it.
func (*Service) PrepareRotation ¶
func (s *Service) PrepareRotation(ctx context.Context, _ *connect.Request[workspacev1.PrepareRotationRequest]) (*connect.Response[workspacev1.PrepareRotationResponse], error)
func (*Service) ProvideKeyWraps ¶
func (s *Service) ProvideKeyWraps(ctx context.Context, req *connect.Request[workspacev1.ProvideKeyWrapsRequest]) (*connect.Response[workspacev1.ProvideKeyWrapsResponse], error)
func (*Service) PutApp ¶
func (s *Service) PutApp(ctx context.Context, req *connect.Request[workspacev1.PutAppRequest]) (*connect.Response[workspacev1.PutAppResponse], error)
func (*Service) PutService ¶
func (s *Service) PutService(ctx context.Context, req *connect.Request[workspacev1.PutServiceRequest]) (*connect.Response[workspacev1.PutServiceResponse], error)
func (*Service) RegisterDeviceKey ¶
func (s *Service) RegisterDeviceKey(ctx context.Context, req *connect.Request[workspacev1.RegisterDeviceKeyRequest]) (*connect.Response[workspacev1.RegisterDeviceKeyResponse], error)
func (*Service) RegisterSigningKey ¶
func (s *Service) RegisterSigningKey(ctx context.Context, req *connect.Request[workspacev1.RegisterSigningKeyRequest]) (*connect.Response[workspacev1.RegisterSigningKeyResponse], error)
func (*Service) RemoveApp ¶
func (s *Service) RemoveApp(ctx context.Context, req *connect.Request[workspacev1.RemoveAppRequest]) (*connect.Response[workspacev1.RemoveAppResponse], error)
func (*Service) RemoveEnvironment ¶
func (s *Service) RemoveEnvironment(ctx context.Context, req *connect.Request[workspacev1.RemoveEnvironmentRequest]) (*connect.Response[workspacev1.RemoveEnvironmentResponse], error)
func (*Service) RemoveMember ¶
func (s *Service) RemoveMember(ctx context.Context, req *connect.Request[workspacev1.RemoveMemberRequest]) (*connect.Response[workspacev1.RemoveMemberResponse], error)
func (*Service) RemoveSecret ¶
func (s *Service) RemoveSecret(ctx context.Context, req *connect.Request[workspacev1.RemoveSecretRequest]) (*connect.Response[workspacev1.RemoveSecretResponse], error)
func (*Service) RemoveServer ¶
func (s *Service) RemoveServer(ctx context.Context, req *connect.Request[workspacev1.RemoveServerRequest]) (*connect.Response[workspacev1.RemoveServerResponse], error)
func (*Service) RemoveService ¶
func (s *Service) RemoveService(ctx context.Context, req *connect.Request[workspacev1.RemoveServiceRequest]) (*connect.Response[workspacev1.RemoveServiceResponse], error)
func (*Service) RevokeInvite ¶
func (s *Service) RevokeInvite(ctx context.Context, req *connect.Request[workspacev1.RevokeInviteRequest]) (*connect.Response[workspacev1.RevokeInviteResponse], error)
func (*Service) RollbackProject ¶
func (s *Service) RollbackProject(ctx context.Context, req *connect.Request[workspacev1.RollbackProjectRequest]) (*connect.Response[workspacev1.RollbackProjectResponse], error)
func (*Service) RotateSecretsKey ¶
func (s *Service) RotateSecretsKey(ctx context.Context, req *connect.Request[workspacev1.RotateSecretsKeyRequest]) (*connect.Response[workspacev1.RotateSecretsKeyResponse], error)
func (*Service) Run ¶
Run does the background work until ctx ends: sign-in's (new signing keys, expired codes and sessions deleted) and, when it checks, asking for new releases.
func (*Service) SetMemberRole ¶
func (s *Service) SetMemberRole(ctx context.Context, req *connect.Request[workspacev1.SetMemberRoleRequest]) (*connect.Response[workspacev1.SetMemberRoleResponse], error)
func (*Service) SetSecret ¶
func (s *Service) SetSecret(ctx context.Context, req *connect.Request[workspacev1.SetSecretRequest]) (*connect.Response[workspacev1.SetSecretResponse], error)
func (*Service) SetServerProjects ¶
func (s *Service) SetServerProjects(ctx context.Context, req *connect.Request[workspacev1.SetServerProjectsRequest]) (*connect.Response[workspacev1.SetServerProjectsResponse], error)
func (*Service) SetTrustRoot ¶
func (s *Service) SetTrustRoot(ctx context.Context, req *connect.Request[workspacev1.SetTrustRootRequest]) (*connect.Response[workspacev1.SetTrustRootResponse], error)
func (*Service) SignVersion ¶
func (s *Service) SignVersion(ctx context.Context, req *connect.Request[workspacev1.SignVersionRequest]) (*connect.Response[workspacev1.SignVersionResponse], error)
func (*Service) UpdateProjectSettings ¶
func (s *Service) UpdateProjectSettings(ctx context.Context, req *connect.Request[workspacev1.UpdateProjectSettingsRequest]) (*connect.Response[workspacev1.UpdateProjectSettingsResponse], error)
func (*Service) WorkspaceID ¶
WorkspaceID is the id of the platform's workspace.
type Updates ¶ added in v0.2.0
type Updates struct {
// Check asks the releases now and then; off for the cloud and air-gapped hosts.
Check bool
// API is the releases API; update.ReleasesAPI when empty.
API string
// Dir is the update folder an installed upgrade unit watches; without it the
// platform tells of releases but cannot apply one.
Dir string
// How tells the owner how to upgrade where it runs when it cannot apply a release
// itself; "sudo devopus-server upgrade" when empty.
How string
}
Updates configures how the platform learns of its new releases (package update).