organization

package
v0.1.0-alpha.8 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package organization provides optional PostgreSQL/SQLite tenant membership and session context.

Index

Constants

View Source
const (
	InviteOperation            plugin.Operation = "organization.invite"
	AcceptOperation            plugin.Operation = "organization.accept"
	RevokeInvitationOperation  plugin.Operation = "organization.invitation.revoke"
	RemoveMemberOperation      plugin.Operation = "organization.member.remove"
	TransferOwnershipOperation plugin.Operation = "organization.ownership.transfer"
	InvitationLifetime                          = 24 * time.Hour
)
View Source
const CreateOperation plugin.Operation = "organization.create"
View Source
const ID = "organization"
View Source
const RenameOperation plugin.Operation = "organization.rename"
View Source
const SelectOperation plugin.Operation = "organization.select"

Variables

This section is empty.

Functions

func Contract

func Contract() plugin.Definition

func PruneExpired

func PruneExpired(ctx context.Context, store storage.Store, before time.Time, limit int) (int64, error)

PruneExpired removes at most limit (1..1000) expired invitations. The cutoff is clamped to database time and persisted ownership permits offline cleanup.

Types

type Invitation

type Invitation struct {
	ID             string    `json:"id"`
	OrganizationID string    `json:"organizationId"`
	Email          string    `json:"email"`
	ExpiresAt      time.Time `json:"expiresAt"`
}

Invitation contains public metadata. IssuedInvitation.Token is returned only after commit; the host delivers it to Email without logging or URL analytics.

type IssuedInvitation

type IssuedInvitation struct {
	Invitation Invitation   `json:"invitation"`
	Token      sigil.Secret `json:"-"`
}

type Membership

type Membership struct {
	OrganizationID string    `json:"organizationId"`
	UserID         string    `json:"userId"`
	Role           Role      `json:"role"`
	CreatedAt      time.Time `json:"createdAt"`
}

type Organization

type Organization struct {
	ID        string    `json:"id"`
	Name      string    `json:"name"`
	CreatedAt time.Time `json:"createdAt"`
}

type Permission

type Permission string

Permission names the library's organization actions, not arbitrary application resources.

const (
	PermissionRead              Permission       = "read"
	PermissionRename            Permission       = "rename"
	PermissionInvite            Permission       = "invite"
	PermissionRevokeInvitation  Permission       = "invitation.revoke"
	PermissionRemoveMember      Permission       = "member.remove"
	PermissionChangeRole        Permission       = "member.role.change"
	PermissionTransferOwnership Permission       = "ownership.transfer"
	ChangeRoleOperation         plugin.Operation = "organization.member.role.change"
)

type Plugin

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

func New

func New() *Plugin

func (*Plugin) AcceptInvitation

func (p *Plugin) AcceptInvitation(ctx context.Context, id string, token sigil.Secret) (Tenant, error)

AcceptInvitation requires the authenticated account's current verified email. Consumption and membership insertion commit together. Existing members retain their role; acceptance never promotes a member or downgrades an owner.

func (*Plugin) Active

func (p *Plugin) Active(ctx context.Context) (Tenant, error)

func (*Plugin) Bind

func (p *Plugin) Bind(a *sigil.Auth) error

func (*Plugin) ChangeRole

func (p *Plugin) ChangeRole(ctx context.Context, id, userID string, role Role) (Tenant, error)

ChangeRole changes an existing non-owner to member or admin. Only the live owner can do so; ownership changes must use TransferOwnership. The returned tenant describes the target. Existing sessions observe the role on next use.

func (*Plugin) Create

func (p *Plugin) Create(ctx context.Context, name string) (Tenant, error)

Create atomically creates an organization and the caller's owner membership.

func (*Plugin) Definition

func (p *Plugin) Definition() plugin.Definition

func (*Plugin) Get

func (p *Plugin) Get(ctx context.Context, id string) (Tenant, error)

func (*Plugin) Invite

func (p *Plugin) Invite(ctx context.Context, id, email string) (IssuedInvitation, error)

Invite issues a member invitation bound to a canonical email and tenant. Reissuing for the same tenant/email invalidates every earlier invitation.

func (*Plugin) RemoveMember

func (p *Plugin) RemoveMember(ctx context.Context, id, userID string) error

RemoveMember permits owners to remove non-owners, admins to remove regular members, and any non-owner to leave. The sole owner must transfer first. Cascades clear every active selection.

func (*Plugin) Rename

func (p *Plugin) Rename(ctx context.Context, id, name string) (Tenant, error)

Rename requires recent authentication and owner or admin permission.

func (*Plugin) RevokeInvitation

func (p *Plugin) RevokeInvitation(ctx context.Context, id, invitationID string) error

func (*Plugin) SetActive

func (p *Plugin) SetActive(ctx context.Context, id string) (Tenant, error)

func (*Plugin) TransferOwnership

func (p *Plugin) TransferOwnership(ctx context.Context, id, userID string) (Tenant, error)

TransferOwnership atomically promotes an existing member and demotes the caller. Exactly one owner exists at commit. Outstanding invitations are revoked so authority granted by the former owner does not survive transfer.

func (*Plugin) WithActive

func (p *Plugin) WithActive(ctx context.Context, op plugin.Operation, fn func(storage.Tx, Tenant) error) error

WithActive resolves the session selection and rechecks membership on every call. A missing selection (including removal) fails closed with forbidden.

func (*Plugin) WithPermission

func (p *Plugin) WithPermission(ctx context.Context, id string, permission Permission, op plugin.Operation, fn func(storage.Tx, Tenant) error) error

WithPermission checks a live role and session and holds tenant locks through the callback commit. Administrative permissions require recent sensitive assurance. The host must still bind application resources to this tenant.

func (*Plugin) WithTenant

func (p *Plugin) WithTenant(ctx context.Context, id string, op plugin.Operation, fn func(storage.Tx, Tenant) error) error

WithTenant authorizes live membership and runs trusted application work in the same transaction. Always scope resource queries to tenant.Organization.ID. Never retain tx or use this snapshot as a later authorization decision.

type Role

type Role string

Role is a closed organization role. Unknown roles grant no permissions.

const (
	RoleOwner  Role = "owner"
	RoleAdmin  Role = "admin"
	RoleMember Role = "member"
)

func (Role) Allows

func (r Role) Allows(p Permission) bool

Allows evaluates the role matrix only. It does not authenticate a caller or establish freshness. Use WithPermission for an atomic authorization decision. Removal additionally restricts the target: admins may remove only members.

type Tenant

type Tenant struct {
	Organization Organization `json:"organization"`
	Membership   Membership   `json:"membership"`
}

Jump to

Keyboard shortcuts

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