Help us shape the future of Go! Take the 2026 Go Developer Survey

holds

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 22, 2026 License: AGPL-3.0 Imports: 8 Imported by: 0

Documentation

Overview

Package holds reads Staff holds (ADR 0009): the reversible freezes a service sets on a Workspace's outbound sending. It is the one place that decides a hold is active, so the send path, the site API and the console agree: a hold is active while its expiry is after the clock, and a lapsed one is ignored at once, with no cleanup job.

It also sets (idempotently) and clears a hold for the service endpoints in ee/staff, which only authorize and validate. It works through the scoped client and holds no raw client.

Index

Constants

View Source
const (
	ReasonSuspended       = "workspace_suspended"
	ReasonPendingDeletion = "workspace_pending_deletion"
	ReasonStaff           = "staff_hold"
)

The Workspace-level reasons a send is Held. They describe the Workspace, not one send, so they live with the holds (ADR 0009) and Outbound send reports them. Suspension (ADR 0007) is neither a Hold row nor the pending-deletion Hold: it keeps its own state and fields, and only its reason code is declared here.

View Source
const KeyPendingDeletion = "pending_deletion"

KeyPendingDeletion is the key of the pending-deletion Hold (ADR 0043).

Variables

This section is empty.

Functions

func ActiveAt

func ActiveAt(now time.Time) predicate.Hold

ActiveAt is the one rule for an active hold: its expiry is after now. It exists only as this SQL predicate; every read passes it.

func Message

func Message(reason string) string

Message words a Workspace-level reason for a human, "" for any other reason. Outbound send's Detail reads it, so every surface that reports a Held outcome agrees.

Types

type Change

type Change struct {
	Hold    *ent.Hold
	Changed bool
}

Change is the outcome of setting or clearing a hold: the hold concerned (nil when a clear found none) and whether the call changed anything.

func Clear

func Clear(ctx context.Context, s *ent.Scoped, key string) (Change, error)

Clear removes the hold under key. Clearing a missing hold succeeds and changes nothing.

func Set

func Set(ctx context.Context, s *ent.Scoped, key, setBy string, in Input) (Change, error)

Set sets the hold under key on the scope's Workspace, or renews it when it exists: one call does both and repeating it is harmless (Changed is false when the stored hold already says what in says). setBy names who set it.

type Holds

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

Holds answers the send path's "may this Workspace send now" from the standing. The one thing that varies between editions is whether Staff holds are honoured (the `staff` license); it is the one function the constructor takes.

func New

func New(honoured func() bool, now func() time.Time) *Holds

New builds the module. honoured reports whether Staff holds count at all (deletion and suspension always do); now is the clock a hold's expiry is read against.

func (*Holds) Reason

func (h *Holds) Reason(ctx context.Context, s *ent.Scoped) (string, error)

Reason is the reason a send is Held for the scope's Workspace, "" when it may send.

func (*Holds) Standing

func (h *Holds) Standing(ctx context.Context, s *ent.Scoped) (Standing, error)

Standing is the standing of the scope's Workspace now, as this instance honours it.

type Input

type Input struct {
	ReasonCode string
	Message    string
	// ActionURL is where the Workspace's Owners and Admins can resolve the hold; nil for none.
	ActionURL *string
	ExpiresAt time.Time
}

Input is what a setter states about a hold.

type Standing

type Standing struct {
	// Deletion is the pending-deletion Hold of a deleted Workspace, nil for a live one.
	// It is not a row: Workspace deletion is its own source and lifts on restore. It
	// lasts to the erase date, the end of the window.
	Deletion *ent.Hold
	// SuspendedAt is when the Workspace was suspended (ADR 0007), nil when it is not.
	SuspendedAt *time.Time
	// Staff are the active Staff holds by key: none without the `staff` license.
	Staff []*ent.Hold
}

Standing is a Workspace's standing: its independent freeze sources, never merged (glossary: Workspace suspension and Staff hold are independent reasons). Reason names the one a send reports, in priority order: deletion, suspension, Staff holds.

func Read

func Read(ctx context.Context, s *ent.Scoped, now time.Time, staffHonoured bool) (Standing, error)

Read is the standing of the scope's Workspace at now, one query for its row and one for its active Staff holds (none are read without the license).

func (Standing) Holds

func (st Standing) Holds() []*ent.Hold

Holds is the list the owner sees: the pending-deletion Hold, if any, then the Staff holds. Suspension is not in it: it is the SuspendedAt field.

func (Standing) Reason

func (st Standing) Reason() string

Reason is the reason a send is Held, "" when the Workspace may send.

Jump to

Keyboard shortcuts

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