Documentation
¶
Overview ¶
Package admin holds the control plane's use cases: the lifecycle of a tenant, as multi-tenancy.md §5 draws it.
Authorisation here is the scope alone, checked in this layer (rule 2): the role matrix is a tenant's internal order, and the operator acting on the control plane is deliberately not a member of the tenants they administer. `admin:tenants` is carried only by a personal access token minted for exactly this - never by a session (identity.md §15.4, catalogue.SessionScopes).
Index ¶
- Constants
- func ExportArchiveName(tenantID shared.ID, at time.Time) string
- func InstanceLevelOf(document map[string]any) (identityrepo.InstanceLevel, error)
- func InstanceProviderOutput(configured domainidentity.IdentityProvider) usecase.Output
- func OfferedAiOutput(offered integration.AiProvider) usecase.Output
- func PlatformDeliveryOutput(d integration.PlatformDelivery) usecase.Output
- func PlatformSubscriptionOutput(s integration.PlatformSubscription) usecase.Output
- type AccessibilityWarnings
- type AccountSeeder
- type AddOperator
- type BucketSeeder
- type CancelInstanceIdentityProviderWithdrawal
- type CancelTenantDeletion
- type ChangeInstallationPreset
- type ChangePlan
- type CloseTenantPassword
- type ConfigureInstanceAiCommand
- type ConfigureInstanceAiProvider
- type ConfigureInstanceIdentityProvider
- type ContainerSeeder
- type CreateInstallationPreset
- type CreateInstanceBackupTarget
- type CreatePlan
- type CreatePlatformSubscription
- type DeleteInstanceBackupTarget
- type DeletePlatformSubscription
- type DeletionScheduled
- type DeliveryCursors
- type EndPasswordOpening
- type EntitlementGate
- type EventRendering
- type ExportAccepted
- type ExportArchiveRequest
- type ExportQuota
- type ExportTargets
- type ExportTenant
- type ExportTenantCommand
- type FileSubscription
- type HardDeleteOutcome
- type HardDeleteTenant
- type InstallationPresetCommand
- type InstallationPresetFileOutcome
- type InstallationPresetWriter
- type InstanceAiWriter
- type InstanceBackupTargetWriter
- type InstanceProviderWriter
- type InstanceWriter
- type JobQueue
- type JournalPage
- type LabelSeeder
- type LifecycleShift
- type LimitExceeded
- type ListInstallationPresets
- type ListInstanceAiProviders
- type ListInstanceBackupTargets
- type ListInstanceIdentityProviders
- type ListInstanceJournal
- type ListOperators
- type ListPlans
- type ListPlatformDeliveries
- type ListPlatformEvents
- type ListPlatformSubscriptions
- type ListTenants
- type MembershipSeeder
- type MintedPlatformSubscription
- type MoveTenantPlan
- type MoveTenantPlanCommand
- type MovedTenant
- type OpenTenantPassword
- type OpenTenantPasswordCommand
- type OpeningNotices
- type OperatorsFromEnvironment
- type PasswordOpeningWriter
- type PausedAutomations
- type PlanCommand
- type PlanFileOutcome
- type PlanView
- type PlanWriter
- type PlatformCursors
- type PlatformDeliveriesPage
- type PlatformEventsPage
- type PlatformFileOutcome
- type PlatformJobs
- type PlatformRegister
- type PlatformWriter
- type ProvisionTenant
- func (h ProvisionTenant) Descriptor() usecase.Descriptor
- func (h ProvisionTenant) Execute(ctx context.Context, actor appshared.ActorContext, cmd ProvisionTenantCommand) (ProvisionedTenant, error)
- func (h ProvisionTenant) SeedWorkspace(ctx context.Context, actor appshared.ActorContext, tenant domain.Tenant, ...) (shared.ID, shared.ID, error)
- type ProvisionTenantCommand
- type ProvisionedTenant
- type QueryTenants
- type QuotaChange
- type ReadInstanceOverview
- type ReadInstanceSettings
- type ReadPlan
- type ReadPlatformSubscription
- type ReadTenant
- type ReadUsage
- type RecoverWorkspace
- type RedeliverPlatformSubscription
- type RedemptionTokens
- type RegisterState
- type RegisterWarnings
- type RemoveInstanceAiProvider
- type RemoveInstanceIdentityProvider
- type RemoveOperator
- type RemovePlan
- type RequestTenantDeletion
- type RequestTenantDeletionCommand
- type RestoreOperator
- type RestoredOperator
- type ResumeTenant
- type RotatePlatformSubscriptionSecret
- type SingleOperatorResolver
- type SuspendTenant
- type SweepPlatformEvents
- type TargetStore
- type TellExportFinished
- type TenantExportArchivist
- type TenantReader
- type TestInstanceBackupTarget
- type UpdatePlatformSubscription
- type UpdatePlatformSubscriptionCommand
- type UpdateTenant
- type UpdateTenantCommand
- type UpdateTenantQuotas
- type UpdateTenantQuotasCommand
- type UsageDay
- type UsageMetric
- type UsagePage
- type UsageQuery
- type WithdrawCommand
- type WithdrawInstallationPreset
- type WithdrawInstanceIdentityProvider
- type WorkspaceUsage
- type WriteInstanceSettings
- func (h WriteInstanceSettings) Descriptor() usecase.Descriptor
- func (h WriteInstanceSettings) Execute(ctx context.Context, actor appshared.ActorContext, ...) (identityrepo.InstanceLevel, error)
- func (h WriteInstanceSettings) ExecuteAsFile(ctx context.Context, level identityrepo.InstanceLevel, source string) (identityrepo.InstanceLevel, error)
Constants ¶
const ( CancelTenantDeletionName = "CancelTenantDeletion" // TenantDeletionCancelledAction is written into the tenant's own trail: its members are // entitled to see that their workspace was to be deleted and was not (audit.md §6). TenantDeletionCancelledAction audit.Action = "tenant.deletion_cancelled" )
const ( RequestTenantDeletionName = "RequestTenantDeletion" // TenantDeletionRequestedAction is the last entry a tenant's trail can carry about its own // end: the hard delete itself has no trail left to write into (audit.md §6). TenantDeletionRequestedAction audit.Action = "tenant.deletion_requested" )
const ( ExportTenantName = "ExportTenant" // TenantExportedAction is the trail's record that a copy of the whole workspace left the // installation - a warning, the DSR export's reasoning: "who took a copy of whose data, and // where to" is a question with an answer. It goes into the exported workspace's own trail, // where its administrator can see it (audit.md §5). TenantExportedAction audit.Action = "tenant.exported" )
const ( ListInstallationPresetsName = "ListInstallationPresets" CreateInstallationPresetName = "CreateInstallationPreset" ChangeInstallationPresetName = "ChangeInstallationPreset" WithdrawInstallationPresetName = "WithdrawInstallationPreset" )
const ( ReadInstanceSettingsName = "ReadInstanceSettings" WriteInstanceSettingsName = "WriteInstanceSettings" ListOperatorsName = "ListOperators" AddOperatorName = "AddOperator" RemoveOperatorName = "RemoveOperator" )
const ( ListInstanceAiProvidersName = "ListInstanceAiProviders" ConfigureInstanceAiProviderName = "ConfigureInstanceAiProvider" RemoveInstanceAiProviderName = "RemoveInstanceAiProvider" )
const ( ListInstanceBackupTargetsName = "ListInstanceBackupTargets" CreateInstanceBackupTargetName = "CreateInstanceBackupTarget" TestInstanceBackupTargetName = "TestInstanceBackupTarget" DeleteInstanceBackupTargetName = "DeleteInstanceBackupTarget" )
const ( ReadInstanceOverviewName = "ReadInstanceOverview" ListInstanceJournalName = "ListInstanceJournal" )
const ( ListInstanceIdentityProvidersName = "ListInstanceIdentityProviders" ConfigureInstanceIdentityProviderName = "ConfigureInstanceIdentityProvider" RemoveInstanceIdentityProviderName = "RemoveInstanceIdentityProvider" )
const ( WithdrawInstanceIdentityProviderName = "WithdrawInstanceIdentityProvider" CancelInstanceIdentityProviderWithdrawalName = "CancelInstanceIdentityProviderWithdrawal" )
const ( ListTenantsName = "ListTenants" SuspendTenantName = "SuspendTenant" ResumeTenantName = "ResumeTenant" // TenantSuspendedAction and TenantResumedAction are written into the tenant's own trail: // its members are entitled to see that their workspace was suspended, and when it came back // (audit.md §6). The suspension is WARNING - it is the entry somebody investigating "why // did every call fail at 14:02" is looking for. TenantSuspendedAction audit.Action = "tenant.suspended" TenantResumedAction audit.Action = "tenant.resumed" )
const ( MoveTenantPlanName = "MoveTenantPlan" // TenantPlanChangedAction is written into the workspace's own trail and the instance journal: // its people are entitled to see when their limits and features changed and from which plan to // which (UC-INS-13 check 6). TenantPlanChangedAction audit.Action = "tenant.plan_changed" )
const ( OpenTenantPasswordName = "OpenTenantPassword" CloseTenantPasswordName = "CloseTenantPassword" // TenantPasswordOpenedAction and TenantPasswordClosedAction are written into the workspace's own // trail. The opening is WARNING: it is the entry somebody asking "how did a password get in while // we only use our directory" is looking for. TenantPasswordOpenedAction audit.Action = "tenant.password_opened" TenantPasswordClosedAction audit.Action = "tenant.password_closed" )
const ( // OpeningEndedByOperator is an operator closing it before its time. OpeningEndedByOperator = "OPERATOR" // OpeningEndedExpired is its time passing. The password closed at that moment whatever was // recorded; this is the entry that says so afterwards. OpeningEndedExpired = "EXPIRED" )
How an opening ended, as the close's entries say it. Named without "password", NewOpening's reason: these are codes, not credentials.
const ( ListPlansName = "ListPlans" ReadPlanName = "ReadPlan" CreatePlanName = "CreatePlan" ChangePlanName = "ChangePlan" RemovePlanName = "RemovePlan" )
const ( ListPlatformEventsName = "ListPlatformEvents" // PlatformEventsRetainDays is how long the installation's events are kept, and so how far back // a cursor may reach (docs/privacy/data-catalog.md): long enough for a platform down over a // holiday, short enough not to keep a reference longer than the deliveries do. PlatformEventsRetainDays = 30 )
const ( ListPlatformSubscriptionsName = "ListPlatformSubscriptions" CreatePlatformSubscriptionName = "CreatePlatformSubscription" ReadPlatformSubscriptionName = "ReadPlatformSubscription" )
const ( UpdatePlatformSubscriptionName = "UpdatePlatformSubscription" DeletePlatformSubscriptionName = "DeletePlatformSubscription" RotatePlatformSubscriptionSecretName = "RotatePlatformSubscriptionSecret" )
const ( ListPlatformDeliveriesName = "ListPlatformDeliveries" RedeliverPlatformSubscriptionName = "RedeliverPlatformSubscription" )
const ( ProvisionTenantName = "ProvisionTenant" // TenantProvisionedAction is the audit code, written into the new tenant's own trail: its // members are entitled to see how their workspace began (audit.md §6). TenantProvisionedAction audit.Action = "tenant.provisioned" )
const ( UpdateTenantQuotasName = "UpdateTenantQuotas" // TenantQuotasChangedAction is the trail's record that the wall moved. Warning, the backup // schedule's reasoning: a quota decides what a workspace may hold from now on, without // anybody being asked again. TenantQuotasChangedAction audit.Action = "tenant.quotas_changed" )
const ( UpdateTenantName = "UpdateTenant" ReadTenantName = "ReadTenant" QueryTenantsName = "QueryTenants" // TenantReferenceChangedAction is written into the workspace's trail - masked - and the journal, // without the value. TenantReferenceChangedAction audit.Action = "tenant.reference_changed" )
const AccessibilityCommand = "hubctl admin settings set legal.accessibility_url <address>"
AccessibilityCommand is how an operator sets the statement from a terminal, which the hint names beside the screen. Not a sentence: the catalogue says what to do with it.
const DeletionGrace = 30 * 24 * time.Hour
DeletionGrace is §5's 30 days, by the clock: the hard delete job's RunAt, and the purge_after the guard re-reads when that moment comes.
const HeldPurgeRetry = 24 * time.Hour
HeldPurgeRetry is how often the grace job of a workspace under a legal hold looks again. Nobody can lift a hold in a workspace whose people are shut out, so the release seeds nothing; the job that waits is what makes the deletion follow within a day of the last release, whatever lifted it.
const PlatformEventsRetention = PlatformEventsRetainDays * 24 * time.Hour
PlatformEventsRetention is the window as a duration.
const ( // PlatformSweepInterval is how often the sweep comes back. Daily would do for a 30-day window; // hourly keeps each pass small. PlatformSweepInterval = time.Hour )
const (
ReadUsageName = "ReadUsage"
)
const RestoreCommand = "hubtask operator add --workspace <short name> --email <address>"
RestoreCommand is the command the health report names for an installation nobody can run (UC-INS-03 check 4). Not a sentence: the catalogue says what to do with it.
Variables ¶
This section is empty.
Functions ¶
func ExportArchiveName ¶
ExportArchiveName is the archive's name at the target. Its own prefix, deliberately outside `hubtask-backup-<tenant>-`: the generation pruning counts and deletes under that prefix, and an export must not be pruned as though it were a generation (tenant-export.md §1). A restore can still name it by path.
func InstanceLevelOf ¶
func InstanceLevelOf(document map[string]any) (identityrepo.InstanceLevel, error)
InstanceLevelOf is `instanceLevelFrom` for the one caller outside this package: the instance file, the third of §5's three doors, which goes through the same reading the other two do.
func InstanceProviderOutput ¶
func InstanceProviderOutput(configured domainidentity.IdentityProvider) usecase.Output
InstanceProviderOutput is the operator's projection: a workspace's, and the count beside it. The count is in this one and in no other, because only the installation may know it (ADR-0076 §1).
func OfferedAiOutput ¶
func OfferedAiOutput(offered integration.AiProvider) usecase.Output
OfferedAiOutput is what an operator reads of an offered model: everything but the key.
func PlatformDeliveryOutput ¶
func PlatformDeliveryOutput(d integration.PlatformDelivery) usecase.Output
PlatformDeliveryOutput is the contract's PlatformDelivery.
func PlatformSubscriptionOutput ¶
func PlatformSubscriptionOutput(s integration.PlatformSubscription) usecase.Output
PlatformSubscriptionOutput is the contract's PlatformSubscription.
Types ¶
type AccessibilityWarnings ¶
type AccessibilityWarnings struct {
Tenancy env.TenancyMode
Settings identityrepo.InstanceSettings
UnitOfWork persistence.UnitOfWork
}
AccessibilityWarnings is the health report's hint that an installation serving other people names no accessibility statement (UC-ID-18).
Only where the installation runs workspaces for others - multi mode, a provider for consumers or for companies - and never on a private installation, which owes nobody a statement (P-10). Only the installation's own link counts: a provider whose workspaces each set their own still offers the sign-in card of every workspace that set none. Advice rather than a fault, because a provider may lawfully owe none (UC-ID-18, *Where it ends*): a level that cannot be read gives no hint, and says so in the log.
type AccountSeeder ¶
The remaining collaborators, each as the one-method slice provisioning actually uses - a seeded row is inserted and never read back, and a fake of one method is a test that stays about provisioning.
type AddOperator ¶
type AddOperator struct{ Writer InstanceWriter }
AddOperator puts an account in the register.
func (AddOperator) Descriptor ¶
func (h AddOperator) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (AddOperator) Execute ¶
func (h AddOperator) Execute( ctx context.Context, actor appshared.ActorContext, accountID shared.ID, ) error
Execute adds. An account that is already an operator is not an error: the caller asked for somebody to be one, and they are.
func (AddOperator) ExecuteByAddress ¶
func (h AddOperator) ExecuteByAddress( ctx context.Context, actor appshared.ActorContext, slug, email string, ) error
ExecuteByAddress names the account the way a person can: the workspace it is in, and the address it signs in with.
The identifier form stays — a script that already has one keeps working — and this is the form a screen uses, because an account id is not something an operator can look up at all: `account` is behind row level security, so the control plane cannot list accounts across workspaces. Resolution happens through the register's own narrow door and answers one identifier or nothing.
type BucketSeeder ¶
The remaining collaborators, each as the one-method slice provisioning actually uses - a seeded row is inserted and never read back, and a fake of one method is a test that stays about provisioning.
type CancelInstanceIdentityProviderWithdrawal ¶
type CancelInstanceIdentityProviderWithdrawal struct{ Writer InstanceProviderWriter }
CancelInstanceIdentityProviderWithdrawal keeps offering it.
func (CancelInstanceIdentityProviderWithdrawal) Descriptor ¶
func (h CancelInstanceIdentityProviderWithdrawal) Descriptor() usecase.Descriptor
func (CancelInstanceIdentityProviderWithdrawal) Execute ¶
func (h CancelInstanceIdentityProviderWithdrawal) Execute( ctx context.Context, actor appshared.ActorContext, id shared.ID, stepUpToken string, ) (domainidentity.IdentityProvider, error)
Execute cancels.
type CancelTenantDeletion ¶
type CancelTenantDeletion struct {
Tenants adminrepo.Tenants
Automations PausedAutomations
Journal adminrepo.Journal
Audit audit.Sink
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
// Platform tells a purchase platform the deletion was called off (UC-INS-14).
Platform platform.Recorder
}
CancelTenantDeletion is §5's edge back from PENDING_DELETION (UC-INS-08 check 5): the workspace returns to the status it was requested from - SUSPENDED where none was kept, so nobody regains access the operator did not choose - the deadline is cleared, and the rules the request switched off are switched back on.
No step-up and no typed name: it removes nothing and returns access, as ResumeTenant does. No hold check either: a legal hold keeps a pending workspace pending, and this is the way out of that state (data-protection.md §5) - the holds stay as they are. What it may not meet is a purge that has begun; the grace job's mark in the row refuses it from then on.
func (CancelTenantDeletion) Descriptor ¶
func (h CancelTenantDeletion) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (CancelTenantDeletion) Execute ¶
func (h CancelTenantDeletion) Execute( ctx context.Context, actor appshared.ActorContext, tenantID shared.ID, ) (domain.TenantStatus, error)
Execute calls the deletion off and answers the status the workspace is in afterwards.
type ChangeInstallationPreset ¶
type ChangeInstallationPreset struct{ Writer InstallationPresetWriter }
ChangeInstallationPreset changes one.
func (ChangeInstallationPreset) Descriptor ¶
func (h ChangeInstallationPreset) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ChangeInstallationPreset) Execute ¶
func (h ChangeInstallationPreset) Execute( ctx context.Context, actor appshared.ActorContext, id shared.ID, cmd InstallationPresetCommand, expected *int, ) (domain.InstallationPreset, error)
Execute changes it. With `expected`, a preset somebody changed since it was read is refused.
type ChangePlan ¶
type ChangePlan struct{ Writer PlanWriter }
ChangePlan replaces a plan's display name and values.
func (ChangePlan) Descriptor ¶
func (h ChangePlan) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ChangePlan) Execute ¶
func (h ChangePlan) Execute( ctx context.Context, actor appshared.ActorContext, cmd PlanCommand, expected *int, ) (PlanView, error)
Execute changes it. With `expected`, a plan somebody saved since it was read is refused.
type CloseTenantPassword ¶
type CloseTenantPassword struct{ Writer PasswordOpeningWriter }
CloseTenantPassword ends an opening before its time.
func (CloseTenantPassword) Descriptor ¶
func (h CloseTenantPassword) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (CloseTenantPassword) Execute ¶
func (h CloseTenantPassword) Execute( ctx context.Context, actor appshared.ActorContext, tenantID shared.ID, ) (adminrepo.TenantRecord, error)
Execute closes it. A workspace with no opening answers as it is.
type ConfigureInstanceAiCommand ¶
type ConfigureInstanceAiCommand struct {
ID shared.ID
DisplayName string
Processor string
Kind integration.AiProviderKind
BaseURL string
CompletionModel string
EmbeddingModel string
Jurisdiction integration.AiJurisdiction
// APIKey is present only when the caller sent one: absent keeps the stored key on a change,
// present and empty clears it.
APIKey secret.Secret
APIKeyPresent bool
}
ConfigureInstanceAiCommand is the input, typed. A zero ID offers a new model.
type ConfigureInstanceAiProvider ¶
type ConfigureInstanceAiProvider struct{ Writer InstanceAiWriter }
ConfigureInstanceAiProvider offers a model, or changes one.
func (ConfigureInstanceAiProvider) Descriptor ¶
func (h ConfigureInstanceAiProvider) Descriptor() usecase.Descriptor
func (ConfigureInstanceAiProvider) Execute ¶
func (h ConfigureInstanceAiProvider) Execute( ctx context.Context, actor appshared.ActorContext, cmd ConfigureInstanceAiCommand, ) (integration.AiProvider, error)
Execute validates, checks the transfer, seals the key and stores the lot - in that order, so a refused model leaves no envelope and no row behind.
type ConfigureInstanceIdentityProvider ¶
type ConfigureInstanceIdentityProvider struct{ Writer InstanceProviderWriter }
ConfigureInstanceIdentityProvider adds or replaces one of them.
func (ConfigureInstanceIdentityProvider) Descriptor ¶
func (h ConfigureInstanceIdentityProvider) Descriptor() usecase.Descriptor
func (ConfigureInstanceIdentityProvider) Execute ¶
func (h ConfigureInstanceIdentityProvider) Execute( ctx context.Context, actor appshared.ActorContext, cmd identityservice.ConfigureIdentityProviderCommand, ) (domainidentity.IdentityProvider, error)
Execute writes it.
The system scope rather than the installation's, for `WriteInstanceSettings`' reason: an installation scope is read-only by construction, and this is the scope with no tenant that may write. What bounds it is the same as there - every table with a tenant column stays invisible, and the provider row this reaches is the one whose tenant is NULL.
type ContainerSeeder ¶
type ContainerSeeder interface {
Insert(ctx context.Context, container work.Container) (work.Container, error)
}
The remaining collaborators, each as the one-method slice provisioning actually uses - a seeded row is inserted and never read back, and a fake of one method is a test that stays about provisioning.
type CreateInstallationPreset ¶
type CreateInstallationPreset struct{ Writer InstallationPresetWriter }
CreateInstallationPreset adds one.
func (CreateInstallationPreset) Descriptor ¶
func (h CreateInstallationPreset) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (CreateInstallationPreset) Execute ¶
func (h CreateInstallationPreset) Execute( ctx context.Context, actor appshared.ActorContext, cmd InstallationPresetCommand, ) (domain.InstallationPreset, error)
Execute creates it.
type CreateInstanceBackupTarget ¶
type CreateInstanceBackupTarget struct{ Writer InstanceBackupTargetWriter }
CreateInstanceBackupTarget configures one.
func (CreateInstanceBackupTarget) Descriptor ¶
func (h CreateInstanceBackupTarget) Descriptor() usecase.Descriptor
func (CreateInstanceBackupTarget) Execute ¶
func (h CreateInstanceBackupTarget) Execute( ctx context.Context, actor appshared.ActorContext, cmd backupservice.CreateBackupTargetCommand, stepUpToken string, ) (domain.Target, error)
Execute validates, opens, seals and stores - the step-up first, so a refused proof leaves no envelope behind - and journals the configuration, never the credential.
type CreatePlan ¶
type CreatePlan struct{ Writer PlanWriter }
CreatePlan writes a new plan.
func (CreatePlan) Descriptor ¶
func (h CreatePlan) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (CreatePlan) Execute ¶
func (h CreatePlan) Execute(ctx context.Context, actor appshared.ActorContext, cmd PlanCommand) (PlanView, error)
Execute creates it.
type CreatePlatformSubscription ¶
type CreatePlatformSubscription struct{ Writer PlatformWriter }
CreatePlatformSubscription subscribes a purchase platform: every installation event is sent to the target, signed with the secret answered here once.
func (CreatePlatformSubscription) Descriptor ¶
func (h CreatePlatformSubscription) Descriptor() usecase.Descriptor
func (CreatePlatformSubscription) Execute ¶
func (h CreatePlatformSubscription) Execute( ctx context.Context, actor appshared.ActorContext, target, stepUpToken string, ) (MintedPlatformSubscription, error)
Execute checks, seals and stores - the step-up first, so a refused proof leaves nothing behind.
type DeleteInstanceBackupTarget ¶
type DeleteInstanceBackupTarget struct{ Writer InstanceBackupTargetWriter }
DeleteInstanceBackupTarget removes one, and its sealed credential. Nothing at the target is touched. One that is not there is not an error.
func (DeleteInstanceBackupTarget) Descriptor ¶
func (h DeleteInstanceBackupTarget) Descriptor() usecase.Descriptor
type DeletePlatformSubscription ¶
type DeletePlatformSubscription struct{ Writer PlatformWriter }
DeletePlatformSubscription unsubscribes; the deliveries go with it, the events stay readable.
func (DeletePlatformSubscription) Descriptor ¶
func (h DeletePlatformSubscription) Descriptor() usecase.Descriptor
func (DeletePlatformSubscription) Execute ¶
func (h DeletePlatformSubscription) Execute(ctx context.Context, actor appshared.ActorContext, id shared.ID) error
Execute removes it.
type DeletionScheduled ¶
DeletionScheduled is the answer: when the grace runs out.
type DeliveryCursors ¶
type DeliveryCursors interface {
EncodeID(id shared.ID) string
DecodeID(cursor string) (shared.ID, error)
}
DeliveryCursors turn the last delivery of a page into an opaque cursor and back.
type EndPasswordOpening ¶
type EndPasswordOpening struct{ Writer PasswordOpeningWriter }
EndPasswordOpening records the end of an opening whose time has passed (KindPasswordOpeningEnd).
The password closed at that moment whatever this does: the end is honoured where the opening is read. What is left is what a person can see - the trail entry, the journal entry, the notices - written here, in the workspace's own transaction, once.
type EntitlementGate ¶
type EntitlementGate struct {
Plans repository.Entitlements
UnitOfWork persistence.UnitOfWork
}
EntitlementGate refuses an operation whose feature the caller's workspace's plan leaves out (multi-tenancy.md §4.2): one place, on the registry every door comes through - REST, MCP and a rule's action - rather than a check in each of the operations that declare a feature.
It asks before the operation's own authorisation does. What a plan leaves out is no secret in the workspace - `/meta/capabilities` answers it to every signed-in person there - and the refusal names only the feature.
func (EntitlementGate) LeftOut ¶
func (g EntitlementGate) LeftOut(ctx context.Context, actor appshared.ActorContext) (entitlement.LeftOut, error)
LeftOut answers what the actor's workspace's plan leaves out, in its own read - which joins the transaction the caller already runs in, as a rule's action does. An actor without a workspace, or a gate wired without a reader, reads an empty set.
func (EntitlementGate) Wrap ¶
func (g EntitlementGate) Wrap(observe usecase.Middleware) usecase.Middleware
Wrap puts the gate inside the composition root's middleware, so that the metric and the span still count an operation the plan refuses.
type EventRendering ¶
EventRendering turns an envelope into the CloudEvent a subscriber receives - the adapter's mapping, so the feed answers the very document a delivery sends.
type ExportAccepted ¶
ExportAccepted is the 202: the job, and the export's own identity (which is also the archive_id in the manifest at the target).
type ExportArchiveRequest ¶
ExportArchiveRequest is what the job carries, decoded here rather than in the worker (ADR-0008): the payload's shape belongs beside the code that wrote it.
func ExportRequestOf ¶
ExportRequestOf reads the job payload back.
type ExportQuota ¶
ExportQuota is the concurrency ceiling of multi-tenancy.md §4, resolved per workspace by the quota engine rather than held as this use case's own constants.
type ExportTargets ¶
ExportTargets answers whether an export could write to a target now: the workspace's own or the installation's, existing and enabled (backup.ExportStoreOpener).
type ExportTenant ¶
type ExportTenant struct {
Tenants adminrepo.Tenants
// Targets checks the target when the export is accepted, so a wrong identifier is a refusal
// the operator sees rather than a job that fails. Nil skips the check.
Targets ExportTargets
Quota ExportQuota
Jobs JobQueue
Audit audit.Sink
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
}
ExportTenant accepts one workspace export: a job that writes the complete, documented archive of tenant-export.md to a configured backup target. It works for ACTIVE, SUSPENDED and PENDING_DELETION workspaces alike - the suspended and the leaving are exactly who needs it - and it is audited with its target, never its content.
func (ExportTenant) Descriptor ¶
func (h ExportTenant) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ExportTenant) Execute ¶
func (h ExportTenant) Execute( ctx context.Context, actor appshared.ActorContext, cmd ExportTenantCommand, ) (ExportAccepted, error)
Execute enqueues the export.
type ExportTenantCommand ¶
ExportTenantCommand is the input, typed.
type FileSubscription ¶
FileSubscription is a subscription the instance file declares, its secret read from the file it names.
type HardDeleteOutcome ¶
type HardDeleteOutcome struct {
// Deleted is false when the guard held the act back: the deadline moved, the status is not
// PENDING_DELETION any more, or the tenant is already gone. Nothing was changed then.
Deleted bool
// Held is a workspace a legal hold keeps: it stays pending until the last hold is lifted
// (data-protection.md §5), and nothing of it was touched.
Held bool
// RunAgainIn is when the job is to come back: a day while a hold stands, the time left while
// the deadline still runs. Zero ends the job.
RunAgainIn time.Duration
Footprint adminrepo.Footprint
BytesObjects int
TrailEntries int64
JobsRemoved int
}
HardDeleteOutcome is what one pass reports: counts, for the job's own log line and nothing else - the durable record is the evidence entry.
type HardDeleteTenant ¶
type HardDeleteTenant struct {
Tenants adminrepo.Tenants
// Holds are the workspace's legal holds in force; while any stands nothing falls.
Holds lifecyclerepo.LegalHolds
Purge adminrepo.Purge
Journal adminrepo.Journal
Store storage.ObjectStore
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
// Platform tells a purchase platform the workspace is gone, and removes the platform's
// reference from the workspace's kept events with it (UC-INS-14, multi-tenancy.md §4.3).
Platform platform.Recorder
}
HardDeleteTenant is §5's final act, run by the grace job the deletion request seeded.
Not a use case in the registry: no credential can ask for it, only the clock. It deletes the media bytes store-first (ReconcileMedia's order), then in one transaction fells the structure, clears what no cascade reaches, writes the evidence entry, purges the trail through migration 0067's narrow act, and lets the tenant row's cascade take the rest - evidence and act commit together, so there is never a deletion without evidence.
It is safe to run twice: the byte deletion tolerates absent objects, and the final guard re-reads the two facts the grace could have changed before anything falls. Before the first byte it marks the row, which is what a cancel of the deletion is refused by from then on.
func (HardDeleteTenant) Execute ¶
func (h HardDeleteTenant) Execute( ctx context.Context, tenantID, jobID shared.ID, ) (HardDeleteOutcome, error)
Execute performs one hard delete. jobID names the queue row running this pass, which survives to report its own completion.
type InstallationPresetCommand ¶
type InstallationPresetCommand struct {
Name *string
// From is one of Hubtask's presets whose values the preset takes, before Settings.
From domain.PresetKey
Settings domain.StructureValues
// IsDefault makes the preset the default, or none the default.
IsDefault *bool
// Locks is the whole set of locks, where LocksSet says the caller named it.
Locks []string
LocksSet bool
// Whole is the instance file's reading: the document describes the preset entirely, so its
// settings start from Hubtask's default where it names no preset of Hubtask's.
Whole bool
}
InstallationPresetCommand is what a create or a change carries. A field left nil or unset is left as it is; a create starts from Hubtask's default.
type InstallationPresetFileOutcome ¶
InstallationPresetFileOutcome is what writing the file's presets came to: nothing in single mode, and how many were created, changed and withdrawn.
type InstallationPresetWriter ¶
type InstallationPresetWriter struct {
Instance InstanceWriter
Presets workrepo.InstallationPresets
Profiles metarepo.CapabilityProfiles
Tenancy env.TenancyMode
Text text.Normalizer
}
InstallationPresetWriter is what the preset use cases share: the instance writer for the register, the level and the journal; the presets; the profiles they are held to; the mode.
func (InstallationPresetWriter) ApplyFile ¶
func (w InstallationPresetWriter) ApplyFile( ctx context.Context, documents []map[string]any, enforce bool, source string, ) (InstallationPresetFileOutcome, error)
ApplyFile writes the instance file's presets, the third door (ADR-0070 §5) for them: `seed` writes them where the installation has none yet; `enforce` writes them at every start and withdraws the presets the file no longer names. A preset is known by its name. Each passes the reading and the checks the API's writes pass, as the file (UC-INS-18 check 1).
type InstanceAiWriter ¶
type InstanceAiWriter struct {
// Instance carries the scope, the register, the journal, the clock and the identifiers.
Instance InstanceWriter
Offered integrationrepo.OfferedAiProviders
// Encryptor seals the key between the request and the store.
Encryptor crypto.Encryptor
// ThirdCountryConfirmed is the installation's confirmation of third-country transfers, the
// same one a workspace's own model is held to: an offered model outside the EEA is a transfer
// whoever chooses it makes.
ThirdCountryConfirmed bool
}
InstanceAiWriter is the control plane's half of the AI provider store.
func (InstanceAiWriter) ApplyFile ¶
func (w InstanceAiWriter) ApplyFile( ctx context.Context, models []ConfigureInstanceAiCommand, enforce bool, source string, ) error
ApplyFile is the instance file's door (ADR-0070 §5, D9 of the readiness record): the models the file names, matched to offered ones by name. `seed` offers them only where nothing is offered yet; `enforce` makes the file the list - named models are offered or changed, and every other offered model is withdrawn. A model whose key the file names by variable gets it; one whose key it does not name keeps the sealed one. The journal names the file.
type InstanceBackupTargetWriter ¶
type InstanceBackupTargetWriter struct {
Instance InstanceWriter
Targets backuprepo.Targets
// Backup prepares and probes a target exactly as a workspace's is prepared and probed.
Backup backupservice.Writer
StepUp stepup.Verifier
}
InstanceBackupTargetWriter is the control plane's half of the targets: the backup context's validation, sealing and probe, under the installation's scope and the operator's authorisation.
type InstanceProviderWriter ¶
type InstanceProviderWriter struct {
// Instance carries the pair every operation here demands - the scope, then the register - and
// the journal the installation's own events are read from.
Instance InstanceWriter
// Providers is the store, read and written under the scope that has no tenant.
Providers identityrepo.IdentityProviders
// Configure is the writer the workspace's own half uses. Shared on purpose.
Configure identityservice.IdentityProviderWriter
// Tenants lists the workspaces a removal tells its people in (ADR-0078 §6). It reads through
// the installation's enumerator, so where that answers none - an owner without the right to
// read across workspaces (multi-tenancy.md §2.1.1) - no workspace is told. Nil tells nobody.
Tenants adminrepo.Tenants
}
InstanceProviderWriter is the control plane's half of the provider store.
type InstanceWriter ¶
type InstanceWriter struct {
Settings identityrepo.InstanceSettings
// Tenancy is the mode: in multi mode plans exist, and the account link's lock binds them.
Tenancy env.TenancyMode
Operators identityrepo.Operators
Journal adminrepo.Journal
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
}
InstanceWriter is what the control plane's instance use cases share.
type JobQueue ¶
JobQueue is the one-method slice the deletion request needs of the queue: seeding the grace job, and pulling the tenant's backup poller forward.
type JournalPage ¶
type JournalPage struct {
Entries []adminrepo.InstanceEvent
Page adminrepo.PageInfo
}
JournalPage is one page of it.
type LabelSeeder ¶
The remaining collaborators, each as the one-method slice provisioning actually uses - a seeded row is inserted and never read back, and a fake of one method is a test that stays about provisioning.
type LifecycleShift ¶
type LifecycleShift struct {
Tenants adminrepo.Tenants
Journal adminrepo.Journal
Audit audit.Sink
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
// Tenancy is read by the suspension alone: in single mode it is refused (requireMulti).
Tenancy env.TenancyMode
// Platform tells a purchase platform the workspace was suspended or is active again (UC-INS-14).
Platform platform.Recorder
}
LifecycleShift is the shared shape of the two one-write edges: suspend and resume.
type LimitExceeded ¶
LimitExceeded is one capacity over its resolved limit, the operator's exception included.
type ListInstallationPresets ¶
type ListInstallationPresets struct{ Writer InstallationPresetWriter }
ListInstallationPresets answers the installation's presets.
func (ListInstallationPresets) Descriptor ¶
func (h ListInstallationPresets) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ListInstallationPresets) Execute ¶
func (h ListInstallationPresets) Execute( ctx context.Context, actor appshared.ActorContext, ) ([]domain.InstallationPreset, error)
Execute lists them.
type ListInstanceAiProviders ¶
type ListInstanceAiProviders struct{ Writer InstanceAiWriter }
ListInstanceAiProviders answers what the installation offers.
func (ListInstanceAiProviders) Descriptor ¶
func (h ListInstanceAiProviders) Descriptor() usecase.Descriptor
func (ListInstanceAiProviders) Execute ¶
func (h ListInstanceAiProviders) Execute( ctx context.Context, actor appshared.ActorContext, ) ([]integration.AiProvider, error)
Execute reads them, without a key.
type ListInstanceBackupTargets ¶
type ListInstanceBackupTargets struct{ Writer InstanceBackupTargetWriter }
ListInstanceBackupTargets answers the installation's targets, without a credential.
func (ListInstanceBackupTargets) Descriptor ¶
func (h ListInstanceBackupTargets) Descriptor() usecase.Descriptor
func (ListInstanceBackupTargets) Execute ¶
func (h ListInstanceBackupTargets) Execute( ctx context.Context, actor appshared.ActorContext, ) ([]domain.Target, error)
Execute reads them.
type ListInstanceIdentityProviders ¶
type ListInstanceIdentityProviders struct{ Writer InstanceProviderWriter }
ListInstanceIdentityProviders answers what the installation offers.
func (ListInstanceIdentityProviders) Descriptor ¶
func (h ListInstanceIdentityProviders) Descriptor() usecase.Descriptor
func (ListInstanceIdentityProviders) Execute ¶
func (h ListInstanceIdentityProviders) Execute( ctx context.Context, actor appshared.ActorContext, ) ([]domainidentity.IdentityProvider, error)
Execute reads them.
Under the installation's own scope, which answers exactly the rows that belong to no workspace: the read policy admits a tenant's own rows and the tenant-less ones, and there is no tenant here.
type ListInstanceJournal ¶
type ListInstanceJournal struct{ Writer InstanceWriter }
ListInstanceJournal answers the installation's own record, newest first.
func (ListInstanceJournal) Descriptor ¶
func (h ListInstanceJournal) Descriptor() usecase.Descriptor
func (ListInstanceJournal) Execute ¶
func (h ListInstanceJournal) Execute( ctx context.Context, actor appshared.ActorContext, filter adminrepo.JournalFilter, cursor string, size int, ) (JournalPage, error)
Execute reads one page.
type ListOperators ¶
type ListOperators struct{ Writer InstanceWriter }
ListOperators answers the register.
func (ListOperators) Descriptor ¶
func (h ListOperators) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ListOperators) Execute ¶
func (h ListOperators) Execute( ctx context.Context, actor appshared.ActorContext, ) ([]identityrepo.Operator, error)
Execute lists it.
type ListPlans ¶
type ListPlans struct{ Writer PlanWriter }
ListPlans answers the plans not removed.
func (ListPlans) Descriptor ¶
func (h ListPlans) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
type ListPlatformDeliveries ¶
type ListPlatformDeliveries struct {
Writer PlatformWriter
Deliveries adminrepo.PlatformDeliveries
Cursors DeliveryCursors
}
ListPlatformDeliveries answers what was sent to a subscription and what became of it, newest first, a page at a time (UC-INS-14 check 5).
func (ListPlatformDeliveries) Descriptor ¶
func (h ListPlatformDeliveries) Descriptor() usecase.Descriptor
func (ListPlatformDeliveries) Execute ¶
func (h ListPlatformDeliveries) Execute( ctx context.Context, actor appshared.ActorContext, id shared.ID, status, cursor string, size int, ) (PlatformDeliveriesPage, error)
Execute reads one page.
type ListPlatformEvents ¶
type ListPlatformEvents struct {
Writer InstanceWriter
Events adminrepo.PlatformEvents
Cursors PlatformCursors
Rendering EventRendering
Tenancy env.TenancyMode
}
ListPlatformEvents reads the installation's events forward from a cursor (UC-INS-14 check 6): the same events the installation's subscriptions are sent, so a platform that was down reads what it missed. Numbered in commit order, so a page never skips an event that commits later.
func (ListPlatformEvents) Descriptor ¶
func (h ListPlatformEvents) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ListPlatformEvents) Execute ¶
func (h ListPlatformEvents) Execute( ctx context.Context, actor appshared.ActorContext, cursor string, size int, ) (PlatformEventsPage, error)
Execute reads one page.
type ListPlatformSubscriptions ¶
type ListPlatformSubscriptions struct{ Writer PlatformWriter }
ListPlatformSubscriptions answers the installation's subscriptions.
func (ListPlatformSubscriptions) Descriptor ¶
func (h ListPlatformSubscriptions) Descriptor() usecase.Descriptor
func (ListPlatformSubscriptions) Execute ¶
func (h ListPlatformSubscriptions) Execute( ctx context.Context, actor appshared.ActorContext, ) ([]integration.PlatformSubscription, error)
Execute reads them.
type ListTenants ¶
type ListTenants struct {
Tenants adminrepo.Tenants
UnitOfWork persistence.UnitOfWork
// Clock judges whether an operator's opening still stands. Nil answers none: without a moment
// an ended opening would read as one in force.
Clock clock.Clock
}
ListTenants answers the installation's workspaces - the one legitimate enumerator (multi-tenancy.md §2.1), behind the admin scope, through the installation-scoped read path.
func (ListTenants) Descriptor ¶
func (h ListTenants) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ListTenants) Execute ¶
func (h ListTenants) Execute( ctx context.Context, actor appshared.ActorContext, ) ([]adminrepo.TenantRecord, error)
Execute lists the workspaces, oldest first.
type MembershipSeeder ¶
type MembershipSeeder interface {
Grant(ctx context.Context, grant domain.Grant) (held domain.Grant, created bool, err error)
}
The remaining collaborators, each as the one-method slice provisioning actually uses - a seeded row is inserted and never read back, and a fake of one method is a test that stays about provisioning.
type MintedPlatformSubscription ¶
type MintedPlatformSubscription struct {
Subscription integration.PlatformSubscription
Secret secret.Secret
}
MintedPlatformSubscription is the subscription with its secret, in clear, for the only time.
type MoveTenantPlan ¶
type MoveTenantPlan struct {
Writer PlanWriter
Tenants adminrepo.Tenants
Quotas quotarepo.Store
// Usage counts what the workspace holds, for the limits it is now over. Nil answers none.
Usage quotarepo.Usage
Audit audit.Sink
// Platform tells a purchase platform the workspace moved (UC-INS-14).
Platform platform.Recorder
}
MoveTenantPlan moves a workspace between plans. Nothing is copied into the workspace and nothing is deleted: what the plan decides applies at the workspace's next request (UC-INS-13 checks 2, 4).
func (MoveTenantPlan) Descriptor ¶
func (h MoveTenantPlan) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (MoveTenantPlan) Execute ¶
func (h MoveTenantPlan) Execute( ctx context.Context, actor appshared.ActorContext, cmd MoveTenantPlanCommand, ) (MovedTenant, error)
Execute moves it.
type MoveTenantPlanCommand ¶
type MoveTenantPlanCommand struct {
TenantID shared.ID
Plan string
// ExpectedVersion is the workspace's version as the caller last read it; nil moves whatever
// stands. A stale one is refused, so a late retry of an older move cannot undo a newer one.
ExpectedVersion *int
// DryRun answers what the move would change and writes nothing.
DryRun bool
}
MoveTenantPlanCommand puts one workspace on a plan, or on none where Plan is empty.
type MovedTenant ¶
type MovedTenant struct {
Tenant adminrepo.TenantRecord
FeaturesResting []plan.Feature
ExceptionsKept []string
// LimitsExceeded is every counted capacity the workspace now holds more of than its limit
// allows: nothing is removed, the next creation is refused (P-03).
LimitsExceeded []LimitExceeded
}
MovedTenant is what a move answers: the workspace on its plan, the features its plan now leaves out, and the limits for which it keeps an operator's exception - the exception stays the last word, so a platform that sold an add-on sees where to set it again (multi-tenancy.md §4.3).
type OpenTenantPassword ¶
type OpenTenantPassword struct{ Writer PasswordOpeningWriter }
OpenTenantPassword opens the password for one named workspace.
func (OpenTenantPassword) Descriptor ¶
func (h OpenTenantPassword) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (OpenTenantPassword) Execute ¶
func (h OpenTenantPassword) Execute( ctx context.Context, actor appshared.ActorContext, cmd OpenTenantPasswordCommand, ) (adminrepo.TenantRecord, error)
Execute opens it.
type OpenTenantPasswordCommand ¶
type OpenTenantPasswordCommand struct {
TenantID shared.ID
// Hours is how long it stands. The channel fills in the default day where the caller named none,
// so that a zero somebody sent is refused rather than read as "the default".
Hours int
Requester string
Reason string
// StepUpToken is the step-up proof (identity.md §16), consumed by this one request.
StepUpToken string
}
OpenTenantPasswordCommand is the input, typed.
type OpeningNotices ¶
type OpeningNotices interface {
PasswordOpened(ctx context.Context, tenantID shared.ID, until time.Time) error
PasswordClosed(ctx context.Context, tenantID shared.ID, ended string) error
}
OpeningNotices tells a workspace's administrators about an opening of its password (ADR-0078 §3): when it opens, with its end, and when it closes, with how. Called inside the transaction that opened or closed it, so the act and its notices commit together.
type OperatorsFromEnvironment ¶
type OperatorsFromEnvironment struct {
Entries []env.OperatorEntry
Operators identityrepo.Operators
Single SingleOperatorResolver
Journal adminrepo.Journal
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
}
OperatorsFromEnvironment is HUBTASK_OPERATORS (UC-INS-02 checks 4, 5): every entry whose account exists is put into the register, at start and again as accounts come to exist; an entry whose account does not exist yet waits, and the health report names it.
The environment adds and never removes: an operator added through the screen stays when the variable no longer names them, and one the variable names stays when somebody removes it from the variable. Authorisation is the configuration itself - whoever sets the server's environment runs the installation - so nothing here asks for a scope, and nothing here is on a route.
func (OperatorsFromEnvironment) Apply ¶
func (o OperatorsFromEnvironment) Apply(ctx context.Context) ([]env.OperatorEntry, error)
Apply adds every entry whose account exists, records each one that was not in the register yet, and answers the entries still waiting for their account.
func (OperatorsFromEnvironment) Pending ¶
func (o OperatorsFromEnvironment) Pending(ctx context.Context) ([]env.OperatorEntry, error)
Pending answers, without writing, the entries whose account does not exist yet.
type PasswordOpeningWriter ¶
type PasswordOpeningWriter struct {
// Instance is the scope and the register (ADR-0070 §1), checked as for every instance act.
Instance InstanceWriter
Tenants adminrepo.Tenants
Journal adminrepo.Journal
Audit audit.Sink
// Jobs seeds the job that records the end once the time has passed - in the workspace's own
// write, because nothing may enumerate workspaces to find openings that ended.
Jobs JobQueue
// Notices tells the workspace's administrators. Nil tells nobody, which is the shape of a test
// about something else, never of the server (cmd/server wires it).
Notices OpeningNotices
StepUp stepup.Verifier
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
// Text brings the requester and the reason to normal form C.
Text text.Normalizer
}
PasswordOpeningWriter is what opening and closing share.
type PausedAutomations ¶
type PausedAutomations interface {
Resume(ctx context.Context, tenantID shared.ID, now time.Time) (int, error)
}
PausedAutomations switches back on the rules a deletion request switched off, inside the cancel's transaction, and reports how many. Implemented by the automation package, which owns how a schedule's next moment is worked out.
type PlanCommand ¶
PlanCommand is what a create or a change carries.
type PlanFileOutcome ¶
PlanFileOutcome is what writing the file's plans came to: nothing in single mode, where plans do not exist, and the plans an enforcing file no longer names that stayed because workspaces are on them.
type PlanView ¶
PlanView is a plan as the control plane answers it: the plan and how many workspaces are on it.
type PlanWriter ¶
type PlanWriter struct {
Instance InstanceWriter
Plans adminrepo.Plans
Tenancy env.TenancyMode
}
PlanWriter is what the plan use cases share: the instance writer for the register, the level and the journal, the plans, and the mode - plans exist in multi mode only.
func (PlanWriter) ApplyFile ¶
func (w PlanWriter) ApplyFile( ctx context.Context, documents []map[string]any, enforce bool, source string, ) (PlanFileOutcome, error)
ApplyFile writes the instance file's plans, the third door (ADR-0070 §5) for plans: `seed` writes them where no plan exists yet; `enforce` writes them at every start and removes the plans the file no longer names - except one a workspace is on, which no door can remove and which is answered as kept. It goes through the same reading and the same checks the API does, as the file, so a plan a file may set is one the API accepts (UC-INS-13 check 7).
type PlatformCursors ¶
type PlatformCursors interface {
Encode(position adminrepo.PlatformPosition) string
Decode(cursor string) (adminrepo.PlatformPosition, error)
}
PlatformCursors turns a position in the installation's events into an opaque cursor and back. An interface here and a keyed HMAC in the adapters, for the trigger cursor's reason: the installation secret has no business above them.
type PlatformDeliveriesPage ¶
type PlatformDeliveriesPage struct {
Deliveries []integration.PlatformDelivery
Next shared.ID
More bool
}
PlatformDeliveriesPage is one page.
type PlatformEventsPage ¶
type PlatformEventsPage struct {
Events []map[string]any
Cursor adminrepo.PlatformPosition
More bool
}
PlatformEventsPage is one read: the rendered events, oldest first, the position after them, and whether to read again at once.
type PlatformFileOutcome ¶
type PlatformFileOutcome struct {
Skipped bool
// Seeded is false where `seed` found subscriptions standing and left them as they are.
Seeded bool
Created, Rotated, Kept, Removed int
}
PlatformFileOutcome is what applying the file did.
type PlatformJobs ¶
type PlatformJobs interface {
Enqueue(ctx context.Context, request queue.Request) (shared.ID, error)
}
PlatformJobs is where a redelivered dead letter's attempt is asked for.
type PlatformRegister ¶
type PlatformRegister interface {
RegisteredServiceAccount(ctx context.Context, accountID shared.ID) (bool, error)
}
PlatformRegister answers whether the operator register holds an account's own row as a service account's - not the empty register's owner, whom `Holds` also admits (migration 0106), and not a person.
type PlatformWriter ¶
type PlatformWriter struct {
Instance InstanceWriter
Subscriptions adminrepo.PlatformSubscriptions
Encryptor crypto.Encryptor
Entropy clock.Entropy
StepUp stepup.Verifier
// Register waives the step-up for a service account it names as one, as the deletion request
// does: the platform runs its own subscription. Nil demands it of everybody.
Register PlatformRegister
Tenancy env.TenancyMode
// Enforced is the instance file deciding the subscriptions: a change through the API is
// refused, as the file's plans are.
Enforced bool
}
PlatformWriter is the control plane's half of the installation's subscriptions for a purchase platform (UC-INS-14): the operator's authorisation, multi mode, the sealing of the secret and the step-up a new address demands.
func (PlatformWriter) ApplyFile ¶
func (w PlatformWriter) ApplyFile(ctx context.Context, declared []FileSubscription, enforce bool) (PlatformFileOutcome, error)
ApplyFile writes the file's subscriptions, as the file.
`seed` writes them once, where no subscription stands yet, and leaves them the operator's from then on - a later start that put the file's secret back would undo a rotation the platform was already given. `enforce` makes the file the whole set at every start: a target it names is kept and marked as the file's, its secret rotated only where the file's differs, so a restart writes nothing; every other subscription goes. Single mode keeps none. Every subscription the file creates, rotates or removes is journalled.
type ProvisionTenant ¶
type ProvisionTenant struct {
Tenants adminrepo.Tenants
// Plans holds the plan a workspace starts on. Nil provisions on none, as an installation
// without plans does.
Plans adminrepo.Plans
Journal adminrepo.Journal
Accounts AccountSeeder
// Domains brings the owner's address to its stored form.
Domains text.DomainEncoder
// Text brings the seeded names to normal form C: they are rendered from the catalogue in the
// workspace's language, and a translator's file is as free to carry combining marks as a
// keyboard is (i18n-l10n.md §5).
Text text.Normalizer
Redemption RedemptionTokens
Grants MembershipSeeder
Containers ContainerSeeder
Buckets BucketSeeder
Labels LabelSeeder
Events outbox.Events
Changes changelog.ChangeLog
Audit audit.Sink
// Platform tells a purchase platform the workspace exists (UC-INS-14).
Platform platform.Recorder
// Renderer names the seeded structure in the workspace's own locale: the names are content
// once created, so they are written in the language the workspace declared, not in a code
// (i18n-l10n.md §2, rule 8 - the backend renders here because creation is the boundary).
Renderer i18n.Renderer
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
HLC clock.HLCSource
Entropy clock.Entropy
// Tenancy is the installation's mode. Provisioning a second workspace only exists in multi
// mode: single mode's whole contract is "exactly one tenant, no selection" (§1).
Tenancy env.TenancyMode
// Hosts records the one host the new workspace answers at. Optional: a build wired
// without it provisions without a host - nothing resolves through the table, so a missing row
// costs nothing.
Hosts identityrepo.TenantHosts
// Jobs seeds the new workspace's retention sweep in the provisioning transaction
// (data-retention.md §5): nothing may enumerate tenants (multi-tenancy.md §2.1), so the write
// that creates the workspace asks for it. Nil is a build without a queue, which only a test makes.
Jobs JobQueue
// RetentionInterval is the sweep's own cadence, the first run one interval out.
RetentionInterval time.Duration
// InstallationHost is this installation's own host, from which the canonical one is derived: the
// slug in front of it in multi mode, and the host itself in single mode. From the configured
// base URL at composition, never from a request - a host a caller chooses is a host a caller
// could claim.
InstallationHost string
// Instance is the installation's level, whose language and zone a workspace provisioned without
// its own starts with. Nil is a build without the level: `en` and `UTC`.
Instance identityrepo.InstanceSettings
}
ProvisionTenant creates a workspace with its defaults, exactly the §5 table: the tenant row, the owner as an invited account with a redemption token, the OWNER membership, a default hub, an example collection, standard buckets and labels - one transaction, so a workspace either exists whole or not at all. Idempotent under `Idempotency-Key` through the middleware every POST already has.
func (ProvisionTenant) Descriptor ¶
func (h ProvisionTenant) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry (usecase.Descriptor's contract).
func (ProvisionTenant) Execute ¶
func (h ProvisionTenant) Execute( ctx context.Context, actor appshared.ActorContext, cmd ProvisionTenantCommand, ) (ProvisionedTenant, error)
Execute provisions the workspace and answers the owner's way in.
func (ProvisionTenant) SeedWorkspace ¶
func (h ProvisionTenant) SeedWorkspace( ctx context.Context, actor appshared.ActorContext, tenant domain.Tenant, owner domain.Account, now time.Time, ) (shared.ID, shared.ID, error)
SeedWorkspace writes a new workspace as multi-tenancy.md §5 draws it, inside the caller's transaction, which must run in the new tenant's own scope: the tenant row, the owner account as given, the OWNER membership, the canonical host, the default hub and example collection with their buckets and labels, the provisioning in the new trail and the first retention sweep. It answers the default hub and the example collection.
Provisioning and the first start's setup both call it, so a workspace is the same however it began; what differs - the owner's way in and the journal's entry - stays with each caller.
type ProvisionTenantCommand ¶
type ProvisionTenantCommand struct {
Slug string
DisplayName string
DefaultLocale string
DefaultTimeZone string
OwnerEmail string
// OwnerDisplayName may be empty; the address stands in until the person introduces
// themselves.
OwnerDisplayName string
// Plan is the short name of the plan the workspace starts on, empty for none
// (multi-tenancy.md §4.2).
Plan string
// ExternalReference is a purchase platform's own reference for the workspace, empty for none
// (multi-tenancy.md §4.3).
ExternalReference string
}
ProvisionTenantCommand is the input, typed.
type ProvisionedTenant ¶
type ProvisionedTenant struct {
Tenant domain.Tenant
// Plan is the plan the workspace started on, and Version the row's version once it is there.
Plan string
ExternalReference string
Version int
OwnerAccountID shared.ID
OwnerRedemption secret.Secret
DefaultHubID shared.ID
ExampleCollectionID shared.ID
}
ProvisionedTenant is what the one answer carries - including the owner's redemption token, shown for the only time (T-18's "shown once").
type QueryTenants ¶
type QueryTenants struct{ Reader TenantReader }
QueryTenants answers a page of the workspaces matching the filters.
func (QueryTenants) Descriptor ¶
func (h QueryTenants) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (QueryTenants) Execute ¶
func (h QueryTenants) Execute( ctx context.Context, actor appshared.ActorContext, query adminrepo.TenantQuery, ) ([]adminrepo.TenantRecord, adminrepo.PageInfo, error)
Execute answers one page.
type QuotaChange ¶
type QuotaChange struct {
Quota string
// Value is the new ceiling (0 = unlimited); nil clears the override.
Value *int64
}
QuotaChange is one key's instruction: set a ceiling, or clear the override back to the mode's default. Absent keys are simply not in the list.
type ReadInstanceOverview ¶
type ReadInstanceOverview struct {
Writer InstanceWriter
// Installation is the census, through the one function that answers it.
Installation adminrepo.Installation
}
ReadInstanceOverview answers how big this installation is and how its workspaces stand.
func (ReadInstanceOverview) Descriptor ¶
func (h ReadInstanceOverview) Descriptor() usecase.Descriptor
func (ReadInstanceOverview) Execute ¶
func (h ReadInstanceOverview) Execute( ctx context.Context, actor appshared.ActorContext, ) (adminrepo.Census, error)
Execute reads it.
type ReadInstanceSettings ¶
type ReadInstanceSettings struct{ Writer InstanceWriter }
ReadInstanceSettings answers what the installation has decided.
func (ReadInstanceSettings) Descriptor ¶
func (h ReadInstanceSettings) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ReadInstanceSettings) Execute ¶
func (h ReadInstanceSettings) Execute( ctx context.Context, actor appshared.ActorContext, ) (identityrepo.InstanceLevel, error)
Execute reads the level.
type ReadPlan ¶
type ReadPlan struct{ Writer PlanWriter }
ReadPlan answers one plan.
func (ReadPlan) Descriptor ¶
func (h ReadPlan) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
type ReadPlatformSubscription ¶
type ReadPlatformSubscription struct{ Writer PlatformWriter }
ReadPlatformSubscription answers one.
func (ReadPlatformSubscription) Descriptor ¶
func (h ReadPlatformSubscription) Descriptor() usecase.Descriptor
func (ReadPlatformSubscription) Execute ¶
func (h ReadPlatformSubscription) Execute( ctx context.Context, actor appshared.ActorContext, id shared.ID, ) (integration.PlatformSubscription, error)
Execute reads it.
type ReadTenant ¶
type ReadTenant struct{ Reader TenantReader }
ReadTenant answers one workspace.
func (ReadTenant) Descriptor ¶
func (h ReadTenant) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ReadTenant) Execute ¶
func (h ReadTenant) Execute(ctx context.Context, actor appshared.ActorContext, id shared.ID) (adminrepo.TenantRecord, error)
Execute reads one workspace.
type ReadUsage ¶
type ReadUsage struct {
Writer InstanceWriter
Ledger adminrepo.UsageLedger
Tenancy env.TenancyMode
}
ReadUsage answers each workspace's use per metric and day for billing (UC-INS-14 checks 4 and 8): only while the operator has switched metering on, a page of workspaces at a time.
func (ReadUsage) Descriptor ¶
func (h ReadUsage) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ReadUsage) Execute ¶
func (h ReadUsage) Execute(ctx context.Context, actor appshared.ActorContext, query UsageQuery) (UsagePage, error)
Execute reads one page.
type RecoverWorkspace ¶
type RecoverWorkspace struct {
Tenants adminrepo.Tenants
UnitOfWork persistence.UnitOfWork
Resume ResumeTenant
Cancel CancelTenantDeletion
}
RecoverWorkspace is the rest of the way back into a locked installation (UC-INS-03): run on the machine as `hubtask workspace resume|cancel-deletion --workspace <short name>`, it makes the same transition as ResumeTenant and CancelTenantDeletion - the same guards, the same trail entry, the same journal entry - for a workspace whose every operator is locked out by the very state it is in. A single-mode installation's only workspace suspended, or set for deletion, before the server refused both is that case (multi-tenancy.md §5).
The door is access to the machine, as for RestoreOperator: the actor it hands the two use cases holds `admin:tenants` for that one workspace and is recorded as the machine. No register check - the register's accounts are the ones the state locks out - and no route: it has no Descriptor, because a registered use case is reachable from outside, and this one mints its own actor.
func (RecoverWorkspace) CancelDeletionBySlug ¶
func (h RecoverWorkspace) CancelDeletionBySlug(ctx context.Context, slug string) (domain.TenantStatus, error)
CancelDeletionBySlug calls off the pending deletion of the workspace a short name names, and answers the status the workspace is in afterwards - SUSPENDED where the request found it so.
func (RecoverWorkspace) ResumeBySlug ¶
func (h RecoverWorkspace) ResumeBySlug(ctx context.Context, slug string) error
ResumeBySlug reactivates the suspended workspace a short name names. An active one is left as it is; one pending deletion is refused as the API refuses it - the cancel comes first.
type RedeliverPlatformSubscription ¶
type RedeliverPlatformSubscription struct {
Writer PlatformWriter
Deliveries adminrepo.PlatformDeliveries
Jobs PlatformJobs
}
RedeliverPlatformSubscription queues every dead letter of a subscription again, with the event identifier it always had and its attempts counting on (UC-INS-14 checks 5 and 6).
func (RedeliverPlatformSubscription) Descriptor ¶
func (h RedeliverPlatformSubscription) Descriptor() usecase.Descriptor
func (RedeliverPlatformSubscription) Execute ¶
func (h RedeliverPlatformSubscription) Execute(ctx context.Context, actor appshared.ActorContext, id shared.ID) (int, error)
Execute queues them in bounded batches, each in a transaction of its own; a dead letter another redelivery took meanwhile is queued by that one alone.
type RedemptionTokens ¶
type RedemptionTokens interface {
SetRedemptionToken(
ctx context.Context, accountID shared.ID, presented domain.Token,
expiresAt, now time.Time,
) (bool, error)
}
RedemptionTokens is the one-method slice provisioning needs of the sign-in accounts: storing the owner's way in.
type RegisterState ¶
type RegisterState interface {
State(ctx context.Context) (workspaces, operators int64, err error)
}
RegisterState answers how many workspaces and operators the installation has.
type RegisterWarnings ¶
type RegisterWarnings struct {
State RegisterState
Environment OperatorsFromEnvironment
UnitOfWork persistence.UnitOfWork
}
RegisterWarnings is the health report's view of who runs the installation (UC-INS-02 check 4, UC-INS-03 check 4), read live for each report:
- an installation with more than one workspace and nobody in the register - counted as `is_operator` counts, so exactly where nobody can reach the control plane - names the command that restores an operator from the machine;
- each HUBTASK_OPERATORS entry whose account does not exist yet;
- and a register that could not be read says so, rather than reading as "fine" (P-11).
type RemoveInstanceAiProvider ¶
type RemoveInstanceAiProvider struct{ Writer InstanceAiWriter }
RemoveInstanceAiProvider withdraws an offered model. Every workspace that chose it stops getting answers at its next call; its own configuration, if it has one, is untouched (ADR-0072 §5).
func (RemoveInstanceAiProvider) Descriptor ¶
func (h RemoveInstanceAiProvider) Descriptor() usecase.Descriptor
func (RemoveInstanceAiProvider) Execute ¶
func (h RemoveInstanceAiProvider) Execute(ctx context.Context, actor appshared.ActorContext, id shared.ID) error
Execute removes it. An unknown model is not an error: removing it is somebody making sure.
type RemoveInstanceIdentityProvider ¶
type RemoveInstanceIdentityProvider struct{ Writer InstanceProviderWriter }
RemoveInstanceIdentityProvider takes one away.
func (RemoveInstanceIdentityProvider) Descriptor ¶
func (h RemoveInstanceIdentityProvider) Descriptor() usecase.Descriptor
func (RemoveInstanceIdentityProvider) Execute ¶
func (h RemoveInstanceIdentityProvider) Execute( ctx context.Context, actor appshared.ActorContext, id shared.ID, stepUpToken string, ) error
Execute removes it - only once its offer has ended, or where no workspace uses it (ADR-0077 §2). Removal deletes every connection between a person and the provider, which offering it again would not restore, so it comes after a withdrawal that announced itself; *Withdraw now* is the answer to a compromised provider. It is journalled, and the accounts it signed in keep their rows and their live sessions: what they lose is the way back, exactly as when a workspace removes its own.
type RemoveOperator ¶
type RemoveOperator struct{ Writer InstanceWriter }
RemoveOperator takes one out.
func (RemoveOperator) Descriptor ¶
func (h RemoveOperator) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (RemoveOperator) Execute ¶
func (h RemoveOperator) Execute( ctx context.Context, actor appshared.ActorContext, accountID shared.ID, ) error
Execute removes, unless it would empty the register.
type RemovePlan ¶
type RemovePlan struct{ Writer PlanWriter }
RemovePlan ends a plan no workspace is on. Its short name stays taken.
func (RemovePlan) Descriptor ¶
func (h RemovePlan) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (RemovePlan) Execute ¶
func (h RemovePlan) Execute(ctx context.Context, actor appshared.ActorContext, name string) error
Execute removes it.
type RequestTenantDeletion ¶
type RequestTenantDeletion struct {
Tenants adminrepo.Tenants
Journal adminrepo.Journal
Automations adminrepo.Automations
// Holds are the workspace's legal holds in force: the request is refused while any stands
// (data-protection.md §5).
Holds lifecyclerepo.LegalHolds
Jobs JobQueue
StepUp stepup.Verifier
// Register waives the step-up for a service account it names. Nil demands it of everybody.
Register PlatformRegister
Audit audit.Sink
// Platform tells a purchase platform the deletion was requested (UC-INS-14).
Platform platform.Recorder
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
IDs clock.IDGenerator
// Tenancy refuses the request in single mode (requireMulti).
Tenancy env.TenancyMode
}
RequestTenantDeletion moves the workspace to PENDING_DELETION (§5): access blocked from the next request on, automations disabled visibly, the export machinery woken one last time, and the hard delete seeded as a job by this very write (multi-tenancy.md §2.1: nothing enumerates tenants, so there is no sweeper to find pending deletions - the request that creates the debt creates the job). It demands a step-up and the typed workspace name, the restore precedent: the two things a stolen admin token does not have. A purchase platform's service account in the register sends the typed name alone (UC-INS-08 check 7): a step-up is a person's proof, which a machine cannot give.
func (RequestTenantDeletion) Descriptor ¶
func (h RequestTenantDeletion) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (RequestTenantDeletion) Execute ¶
func (h RequestTenantDeletion) Execute( ctx context.Context, actor appshared.ActorContext, cmd RequestTenantDeletionCommand, ) (DeletionScheduled, error)
Execute schedules the deletion.
type RequestTenantDeletionCommand ¶
type RequestTenantDeletionCommand struct {
TenantID shared.ID
// Confirmation is the workspace's display name, typed exactly - the restore precedent.
Confirmation string
// StepUpToken is the step-up proof (identity.md §16), consumed by this one request. A purchase
// platform's service account sends none (waivesStepUp).
StepUpToken string
}
RequestTenantDeletionCommand is the input, typed.
type RestoreOperator ¶
type RestoreOperator struct{ Writer InstanceWriter }
RestoreOperator is the way back into an installation nobody can run (UC-INS-03): run on the machine as `hubtask operator add --workspace <short name> --email <address>`, with the server's own configuration and database connection.
No scope and no register check, and deliberately so: the door is access to the machine, which is what the person who could otherwise fix this with a database shell already has. That is also why it is not in the registry: nothing registered is reachable without a route, and this must have none (UC-INS-03 *Where it ends*).
func (RestoreOperator) Execute ¶
func (h RestoreOperator) Execute(ctx context.Context, slug, email string) (RestoredOperator, error)
Execute adds the account an address names in a workspace, and records it as done from the machine. An address that matches no account is the one refusal the screen gives too, which says nothing about other workspaces.
type RestoredOperator ¶
RestoredOperator says which account it was and whether it was added just now.
type ResumeTenant ¶
type ResumeTenant struct{ LifecycleShift }
ResumeTenant is §5's one write back: the next request of the tenant's people works again.
func (ResumeTenant) Descriptor ¶
func (h ResumeTenant) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (ResumeTenant) Execute ¶
func (h ResumeTenant) Execute( ctx context.Context, actor appshared.ActorContext, tenantID shared.ID, ) error
Execute reactivates the workspace.
type RotatePlatformSubscriptionSecret ¶
type RotatePlatformSubscriptionSecret struct{ Writer PlatformWriter }
RotatePlatformSubscriptionSecret issues a new signing secret, answered once; deliveries are signed with it from this moment.
func (RotatePlatformSubscriptionSecret) Descriptor ¶
func (h RotatePlatformSubscriptionSecret) Descriptor() usecase.Descriptor
func (RotatePlatformSubscriptionSecret) Execute ¶
func (h RotatePlatformSubscriptionSecret) Execute( ctx context.Context, actor appshared.ActorContext, id shared.ID, stepUpToken string, ) (MintedPlatformSubscription, error)
Execute rotates it, the step-up first.
type SingleOperatorResolver ¶
type SingleOperatorResolver interface {
ResolveSingle(ctx context.Context, email string) (shared.ID, error)
}
SingleOperatorResolver finds an address in a single-mode installation's one workspace.
type SuspendTenant ¶
type SuspendTenant struct{ LifecycleShift }
SuspendTenant flips the middleware: the tenant's people answer 403 tenant_suspended on their very next request, the data remains, the read export still works (multi-tenancy.md §5).
func (SuspendTenant) Descriptor ¶
func (h SuspendTenant) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (SuspendTenant) Execute ¶
func (h SuspendTenant) Execute( ctx context.Context, actor appshared.ActorContext, tenantID shared.ID, ) error
Execute suspends the workspace.
type SweepPlatformEvents ¶
type SweepPlatformEvents struct {
Events adminrepo.PlatformEvents
// Deliveries are swept on the same clock: a settled delivery untouched for 30 days, its dead
// letter included, which can no longer be redelivered once its event is gone. Nil sweeps none.
Deliveries adminrepo.PlatformDeliveries
Jobs JobQueue
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
Tenancy env.TenancyMode
}
SweepPlatformEvents removes the installation's events and their deliveries past their 30 days (data-catalog.md). An installation job: it runs under the system scope, which reaches the policy-free tables and no workspace's rows.
type TargetStore ¶
type TargetStore interface {
OpenTarget(ctx context.Context, tenantID, targetID shared.ID) (backupstorage.Store, error)
}
TargetStore opens a configured backup target - the seam the audit and DSR exports write through: an export needs somewhere to put bytes and has no business with a target's credentials.
type TellExportFinished ¶
type TellExportFinished struct {
Platform platform.Recorder
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
}
TellExportFinished tells a purchase platform that a workspace's export has been written (UC-INS-14). The export's job runs outside a transaction and may run again after it wrote the archive, so the event is written in a transaction of its own and keyed by the export: once, however often the job runs.
type TenantExportArchivist ¶
type TenantExportArchivist struct {
Targets TargetStore
Rows backuprepo.Export
Objects storage.ObjectStore
Cipher crypto.StreamCipher
Snapshot persistence.Snapshot
Clock clock.Clock
// SchemaVersion and ProductVersion go into the manifest: what an archive has to record is
// the build that wrote it.
SchemaVersion string
ProductVersion string
}
TenantExportArchivist writes the archive the job owes: the Hubtask archive of tenant-export.md, FULL, unencrypted, media and audit included, credentials redacted - through the same writer and the same row-level-security path a backup uses (T-20).
func (TenantExportArchivist) Write ¶
func (a TenantExportArchivist) Write( ctx context.Context, in ExportArchiveRequest, ) (archive.Manifest, error)
Write produces one archive and answers its manifest.
type TenantReader ¶
type TenantReader struct {
Writer PlanWriter
Finder adminrepo.TenantFinder
}
TenantReader reads workspaces for the control plane: one by its identifier, or a page of those matching a platform's filters.
type TestInstanceBackupTarget ¶
type TestInstanceBackupTarget struct{ Writer InstanceBackupTargetWriter }
TestInstanceBackupTarget probes one.
func (TestInstanceBackupTarget) Descriptor ¶
func (h TestInstanceBackupTarget) Descriptor() usecase.Descriptor
func (TestInstanceBackupTarget) Execute ¶
func (h TestInstanceBackupTarget) Execute( ctx context.Context, actor appshared.ActorContext, id shared.ID, ) (backupservice.Probe, error)
Execute reads the target and its sealed credential in the installation's scope, probes outside any transaction, and writes down what the probe found.
type UpdatePlatformSubscription ¶
type UpdatePlatformSubscription struct{ Writer PlatformWriter }
UpdatePlatformSubscription changes a subscription's target or pauses and resumes it. A new target demands a fresh step-up; pausing and resuming do not - they send less, or what was sent before.
func (UpdatePlatformSubscription) Descriptor ¶
func (h UpdatePlatformSubscription) Descriptor() usecase.Descriptor
func (UpdatePlatformSubscription) Execute ¶
func (h UpdatePlatformSubscription) Execute( ctx context.Context, actor appshared.ActorContext, cmd UpdatePlatformSubscriptionCommand, ) (integration.PlatformSubscription, error)
Execute changes it, guarded on the version read or the one the caller names.
type UpdatePlatformSubscriptionCommand ¶
type UpdatePlatformSubscriptionCommand struct {
ID shared.ID
TargetURL string
State string
ExpectedVersion int
StepUpToken string
}
UpdatePlatformSubscriptionCommand is the change. Empty fields are left alone.
type UpdateTenant ¶
type UpdateTenant struct {
Writer PlanWriter
Tenants adminrepo.Tenants
Finder adminrepo.TenantFinder
Audit audit.Sink
}
UpdateTenant sets or clears a platform's reference on a workspace.
func (UpdateTenant) Descriptor ¶
func (h UpdateTenant) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (UpdateTenant) Execute ¶
func (h UpdateTenant) Execute( ctx context.Context, actor appshared.ActorContext, cmd UpdateTenantCommand, ) (adminrepo.TenantRecord, error)
Execute sets it. A workspace leaving can still have its reference cleared - it stays taken through the grace, and a platform provisioning that customer again clears it first - until its purge begins.
type UpdateTenantCommand ¶
UpdateTenantCommand carries the reference; empty clears it.
type UpdateTenantQuotas ¶
type UpdateTenantQuotas struct {
Tenants adminrepo.Tenants
Store quotarepo.Store
Usage quotarepo.Usage
Audit audit.Sink
UnitOfWork persistence.UnitOfWork
Clock clock.Clock
Tenancy env.TenancyMode
}
UpdateTenantQuotas is the operator's write on a workspace's §4 ceilings: partial by design, version-guarded, audited field by field.
func (UpdateTenantQuotas) Descriptor ¶
func (h UpdateTenantQuotas) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (UpdateTenantQuotas) Execute ¶
func (h UpdateTenantQuotas) Execute( ctx context.Context, actor appshared.ActorContext, cmd UpdateTenantQuotasCommand, ) ([]quotaservice.Standing, error)
Execute applies the changes and answers the resolved standings.
type UpdateTenantQuotasCommand ¶
type UpdateTenantQuotasCommand struct {
TenantID shared.ID
Changes []QuotaChange
}
UpdateTenantQuotasCommand is the input, typed.
type UsageMetric ¶
UsageMetric is how one metric is counted and by which day (multi-tenancy.md §4.3).
func UsageMetrics ¶
func UsageMetrics() []UsageMetric
UsageMetrics is the vocabulary in the contract's order: the quotas' own names.
type UsagePage ¶
type UsagePage struct {
Workspaces []WorkspaceUsage
Metrics []UsageMetric
FinalThrough time.Time
Next string
More bool
}
UsagePage is one read.
type UsageQuery ¶
UsageQuery is what a read asks.
type WithdrawCommand ¶
WithdrawCommand is the input, typed. A zero At is the default notice; one that has come is now.
type WithdrawInstallationPreset ¶
type WithdrawInstallationPreset struct{ Writer InstallationPresetWriter }
WithdrawInstallationPreset removes one. Hubs and collections made from it keep their settings.
func (WithdrawInstallationPreset) Descriptor ¶
func (h WithdrawInstallationPreset) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
type WithdrawInstanceIdentityProvider ¶
type WithdrawInstanceIdentityProvider struct{ Writer InstanceProviderWriter }
WithdrawInstanceIdentityProvider announces the end of an offer, or ends it now.
func (WithdrawInstanceIdentityProvider) Descriptor ¶
func (h WithdrawInstanceIdentityProvider) Descriptor() usecase.Descriptor
func (WithdrawInstanceIdentityProvider) Execute ¶
func (h WithdrawInstanceIdentityProvider) Execute( ctx context.Context, actor appshared.ActorContext, cmd WithdrawCommand, ) (domainidentity.IdentityProvider, error)
Execute withdraws.
type WorkspaceUsage ¶
WorkspaceUsage is one workspace's days, per metric.
type WriteInstanceSettings ¶
type WriteInstanceSettings struct{ Writer InstanceWriter }
WriteInstanceSettings replaces the level whole.
func (WriteInstanceSettings) Descriptor ¶
func (h WriteInstanceSettings) Descriptor() usecase.Descriptor
Descriptor is the catalogue entry.
func (WriteInstanceSettings) Execute ¶
func (h WriteInstanceSettings) Execute( ctx context.Context, actor appshared.ActorContext, level identityrepo.InstanceLevel, expected int, ) (identityrepo.InstanceLevel, error)
Execute writes the level on a person's behalf, made on the version `expected` (UC-INS-09 check 8). Zero means the caller named none, and the level is compared with the version read in the same transaction - so two saves at once still refuse the second, as the workspace's own does.
func (WriteInstanceSettings) ExecuteAsFile ¶
func (h WriteInstanceSettings) ExecuteAsFile( ctx context.Context, level identityrepo.InstanceLevel, source string, ) (identityrepo.InstanceLevel, error)
Execute writes it.
A `PUT` rather than a merge, because a merge over eighteen switches that can each be absent has no way to say "unset this one" - and "the operator decided nothing here" is a value the resolver acts on, so it has to be expressible. ExecuteAsFile writes the level on behalf of the instance file, at start-up.
**The one caller that is not a person**, and the one that may write while a file enforces — because it *is* the file. It carries no actor: there is nobody to authorise, nothing has a session yet, and the journal records the source rather than a name. Everything else about it is the same write, including the entry in the journal, which is what makes a change that arrived from a repository as visible as one somebody clicked.
It compares no version: the file is the source and wins. In `enforce` every replica writes it at start, and a refusal here would stop a start over a race between two copies of the same file.
Source Files
¶
- AccessibilityWarning.go
- Cancel.go
- Deletion.go
- Entitlements.go
- Export.go
- ExportFinished.go
- HardDelete.go
- InstallationPresets.go
- Instance.go
- InstanceAi.go
- InstanceBackupTargets.go
- InstanceOverview.go
- InstanceProvider.go
- InstanceProviderWithdrawal.go
- InstanceValues.go
- Lifecycle.go
- MovePlan.go
- OperatorsFromEnvironment.go
- PasswordOpening.go
- Plans.go
- PlatformEvents.go
- PlatformSubscriptions.go
- PlatformSweep.go
- Provision.go
- Quotas.go
- RecoverWorkspace.go
- Reference.go
- RestoreOperator.go
- Usage.go