Documentation
¶
Index ¶
- Constants
- Variables
- type Auditor
- type Clock
- type EmailSender
- type Invitation
- type InvitationWithWorkspace
- type Member
- type Page
- type PoolDeps
- type Repo
- type RoleConfig
- type ShareLink
- type Workspace
- type WorkspaceConfig
- type WorkspaceMembership
- type WorkspaceService
- func (s *WorkspaceService) AcceptInvitation(ctx context.Context, p *webx.Principal, invID string) (Workspace, error)
- func (s *WorkspaceService) Create(ctx context.Context, p *webx.Principal, slug, name string) (Workspace, error)
- func (s *WorkspaceService) CreateShareLink(ctx context.Context, actor *webx.Principal, wsID, role string, maxUses int, ...) (ShareLink, string, error)
- func (s *WorkspaceService) DeclineInvitation(ctx context.Context, p *webx.Principal, invID string) error
- func (s *WorkspaceService) DeleteWorkspace(ctx context.Context, p *webx.Principal, workspaceID string) error
- func (s *WorkspaceService) EffectivePerms(ctx context.Context, wsID, role string) ([]authz.Permission, error)
- func (s *WorkspaceService) Invite(ctx context.Context, actor *webx.Principal, wsID, rawEmail, role string) (Invitation, error)
- func (s *WorkspaceService) Leave(ctx context.Context, p *webx.Principal, wsID string) error
- func (s *WorkspaceService) ListInvitations(ctx context.Context, _ *webx.Principal, wsID string, page, pageSize int) (Page[Invitation], error)
- func (s *WorkspaceService) ListMembers(ctx context.Context, wsID string, page, pageSize int) (Page[Member], error)
- func (s *WorkspaceService) ListMine(ctx context.Context, p *webx.Principal) ([]WorkspaceMembership, error)
- func (s *WorkspaceService) ListRoleConfigs(ctx context.Context, actor *webx.Principal, wsID string) ([]RoleConfig, []authz.Permission, error)
- func (s *WorkspaceService) ListShareLinks(ctx context.Context, _ *webx.Principal, wsID string, page, pageSize int) (Page[ShareLink], error)
- func (s *WorkspaceService) MyInvitations(ctx context.Context, p *webx.Principal) ([]InvitationWithWorkspace, error)
- func (s *WorkspaceService) RedeemShareLink(ctx context.Context, p *webx.Principal, code string) (Workspace, error)
- func (s *WorkspaceService) RemoveMember(ctx context.Context, actor *webx.Principal, wsID, targetUserID string) error
- func (s *WorkspaceService) RenameWorkspace(ctx context.Context, p *webx.Principal, workspaceID, name string) (Workspace, error)
- func (s *WorkspaceService) ResetRolePerms(ctx context.Context, actor *webx.Principal, wsID, role string) error
- func (s *WorkspaceService) RevokeInvitation(ctx context.Context, actor *webx.Principal, wsID, invID string) error
- func (s *WorkspaceService) RevokeShareLink(ctx context.Context, actor *webx.Principal, wsID, linkID string) error
- func (s *WorkspaceService) SetRolePerms(ctx context.Context, actor *webx.Principal, wsID, role string, ...) (*RoleConfig, error)
- func (s *WorkspaceService) TransferOwnership(ctx context.Context, actor *webx.Principal, wsID, newOwnerUserID string) error
- func (s *WorkspaceService) UpdateMemberRole(ctx context.Context, actor *webx.Principal, wsID, targetUserID, newRole string) error
- func (s *WorkspaceService) WithHooks(h workspace.WorkspaceHooks) *WorkspaceService
Constants ¶
const ( DefaultPageSize = 50 MaxPageSize = 200 )
Variables ¶
var ErrDuplicate = errors.New("duplicate")
var ErrLastOwner = errors.New("last active owner protected")
var ErrNotFound = errors.New("not found")
Functions ¶
This section is empty.
Types ¶
type EmailSender ¶
type Invitation ¶
type InvitationWithWorkspace ¶
type InvitationWithWorkspace struct {
Invitation
WorkspaceName string `json:"workspace_name"`
WorkspaceSlug string `json:"workspace_slug"`
}
type Repo ¶
type Repo interface {
CreateWorkspaceWithOwner(ctx context.Context, slug, name, ownerUserID string, now time.Time) (Workspace, error)
ListWorkspacesByUser(ctx context.Context, userID string) ([]WorkspaceMembership, error)
GetWorkspace(ctx context.Context, id string) (Workspace, bool, error)
CountWorkspacesByUser(ctx context.Context, userID string) (int, error)
GetMember(ctx context.Context, workspaceID, userID string) (Member, bool, error)
IsMemberByEmail(ctx context.Context, workspaceID, email string) (bool, error)
ListMembers(ctx context.Context, workspaceID string, page, pageSize int) (Page[Member], error)
CountActiveOwners(ctx context.Context, workspaceID string) (int, error)
UpdateMemberRole(ctx context.Context, workspaceID, userID, newRole string, now time.Time) error
SoftRemoveMember(ctx context.Context, workspaceID, userID, removedBy string, now time.Time) error
CreateInvitation(ctx context.Context, workspaceID, email, role, createdBy string, expiresAt time.Time) (Invitation, error)
ListInvitations(ctx context.Context, workspaceID string, page, pageSize int) (Page[Invitation], error)
RevokeInvitation(ctx context.Context, workspaceID, invitationID string, now time.Time) error
HasPendingInvitation(ctx context.Context, workspaceID, email string) (bool, error)
PendingInvitationsByEmail(ctx context.Context, email string) ([]InvitationWithWorkspace, error)
AcceptInvitation(ctx context.Context, invitationID, userID, email string, now time.Time) (Workspace, error)
DeclineInvitation(ctx context.Context, invitationID, email string, now time.Time) error
RunInTx(ctx context.Context, fn func(ctx context.Context, tx pgx.Tx) error) error
CountWorkspacesByUserForCreateTx(ctx context.Context, tx pgx.Tx, userID string) (int, error)
CreateWorkspaceWithOwnerTx(ctx context.Context, tx pgx.Tx, slug, name, ownerUserID string, now time.Time) (Workspace, error)
// CreatePersonalWorkspaceTx inserts the ADR 0016 personal workspace —
// kind='personal', name 'Personal', the plan's default (free) — plus the
// owner membership, on the caller's transaction. The partial unique index
// uq_workspace_personal(created_by) makes a second insert for the same
// owner fail with ErrDuplicate: provisioning callers treat that as
// "already provisioned".
CreatePersonalWorkspaceTx(ctx context.Context, tx pgx.Tx, slug, ownerUserID string, now time.Time) (Workspace, error)
AcceptInvitationTx(ctx context.Context, tx pgx.Tx, invitationID, userID, email string, now time.Time) (Workspace, error)
UpdateWorkspaceName(ctx context.Context, id, name string, now time.Time) error
DeleteWorkspaceCascade(ctx context.Context, tx pgx.Tx, workspaceID string) error
GetMemberUserStatus(ctx context.Context, workspaceID, userID string) (Member, string, bool, error)
OldestActiveOwner(ctx context.Context, workspaceID string) (Member, bool, error)
TransferOwnershipTx(ctx context.Context, tx pgx.Tx, workspaceID, fromUserID, toUserID string) error
// Role-config write side (read side lives in authz's Provider). An
// override row REPLACES the role's built-in permission set entirely —
// not a merge.
ListRoleOverrides(ctx context.Context, workspaceID string) (map[string][]authz.Permission, error)
UpsertRolePerms(ctx context.Context, workspaceID, role string, perms []authz.Permission, now time.Time) error
DeleteRolePerms(ctx context.Context, workspaceID, role string) error
}
type RoleConfig ¶ added in v0.4.0
type RoleConfig struct {
Role string `json:"role"`
Perms []authz.Permission `json:"perms"`
Overridden bool `json:"overridden"`
Defaults []authz.Permission `json:"defaults"`
}
RoleConfig is one row of the workspace role-permission matrix: the role's effective permission set plus whether it comes from an override row (an override REPLACES the built-in set — not a merge) and what the built-in default is.
type WorkspaceConfig ¶
type WorkspaceConfig struct {
MaxPerUser int
}
WorkspaceConfig configures the workspace service. The zero value is safe: MaxPerUser <= 0 (including the unset zero value) means unlimited workspaces per user; only an explicit positive value caps creation (orkome F10 — the old "0 blocks everything, -1 is unlimited" reading violated Go zero-value conventions and disguised itself as E_QUOTA_EXCEEDED).
type WorkspaceMembership ¶
type WorkspaceService ¶
type WorkspaceService struct {
// contains filtered or unexported fields
}
func NewWorkspaceService ¶
func NewWorkspaceService(repo Repo, az *authz.Authorizer, mail EmailSender, auditor Auditor, cfg WorkspaceConfig, now Clock) *WorkspaceService
func (*WorkspaceService) AcceptInvitation ¶
func (*WorkspaceService) CreateShareLink ¶
func (*WorkspaceService) DeclineInvitation ¶
func (*WorkspaceService) DeleteWorkspace ¶
func (*WorkspaceService) EffectivePerms ¶ added in v0.9.2
func (s *WorkspaceService) EffectivePerms(ctx context.Context, wsID, role string) ([]authz.Permission, error)
EffectivePerms returns the given role's effective permission set in a workspace: owner carries the full registered catalog (owner permissions are immutable by design); admin/member use their override row when one exists, otherwise their built-in defaults. Used by the HTTP layer to attach role_perms to workspace responses.
func (*WorkspaceService) Invite ¶
func (s *WorkspaceService) Invite(ctx context.Context, actor *webx.Principal, wsID, rawEmail, role string) (Invitation, error)
func (*WorkspaceService) ListInvitations ¶
func (s *WorkspaceService) ListInvitations(ctx context.Context, _ *webx.Principal, wsID string, page, pageSize int) (Page[Invitation], error)
func (*WorkspaceService) ListMembers ¶
func (*WorkspaceService) ListMine ¶
func (s *WorkspaceService) ListMine(ctx context.Context, p *webx.Principal) ([]WorkspaceMembership, error)
func (*WorkspaceService) ListRoleConfigs ¶ added in v0.4.0
func (s *WorkspaceService) ListRoleConfigs(ctx context.Context, actor *webx.Principal, wsID string) ([]RoleConfig, []authz.Permission, error)
ListRoleConfigs returns the full matrix (defaults, overrides, effective sets) plus the permission vocabulary for the management UI.
func (*WorkspaceService) ListShareLinks ¶
func (*WorkspaceService) MyInvitations ¶
func (s *WorkspaceService) MyInvitations(ctx context.Context, p *webx.Principal) ([]InvitationWithWorkspace, error)
func (*WorkspaceService) RedeemShareLink ¶
func (*WorkspaceService) RemoveMember ¶
func (*WorkspaceService) RenameWorkspace ¶
func (*WorkspaceService) ResetRolePerms ¶ added in v0.4.0
func (s *WorkspaceService) ResetRolePerms(ctx context.Context, actor *webx.Principal, wsID, role string) error
ResetRolePerms removes the override row so the role falls back to its built-in set. Idempotent: resetting a role without an override succeeds.
func (*WorkspaceService) RevokeInvitation ¶
func (*WorkspaceService) RevokeShareLink ¶
func (*WorkspaceService) SetRolePerms ¶ added in v0.4.0
func (s *WorkspaceService) SetRolePerms(ctx context.Context, actor *webx.Principal, wsID, role string, perms []authz.Permission) (*RoleConfig, error)
SetRolePerms writes a role override. The write boundary IS the drift guard (ADR 0012): every permission must exist in the code-registered catalog — UI-edited data cannot drift from the vocabulary because unknown permissions are rejected fail-closed at write time.
func (*WorkspaceService) TransferOwnership ¶
func (*WorkspaceService) UpdateMemberRole ¶
func (*WorkspaceService) WithHooks ¶
func (s *WorkspaceService) WithHooks(h workspace.WorkspaceHooks) *WorkspaceService