Another grabbag of updates, focused on multi-tenancy, access control, rate limiting, and a dashboard UI.
tenants and members
The demo app now has tenants – namespaces for resources. Users can create tenants, invite members, and manage membership. If you invite someone who doesn't have an account yet, the invitation is stored as "pending" and resolved when they register. Each user has a personal tenant.
type TenantType string
const (
TenantPersonal TenantType = "personal"
TenantOrganization TenantType = "organization"
)
type Tenant struct {
ID core.ID
Name string
Type TenantType
}
type MemberStatus string
const (
MemberInvited MemberStatus = "invited"
MemberActive MemberStatus = "active"
)
type TenantMember struct {
TenantID core.ID
UserID core.ID
Status MemberStatus
}
roles and grants
Started on a simple RBAC model. Roles are collections of actions. Groups are collections of users. Grants assign a role to a principal (user or group).
// RoleID is a globally unique role identifier that encodes its namespace
// as the first path segment. System roles use the reserved "app" namespace
// (e.g. "app.editor"). Custom tenant roles use the tenant ID as
// the namespace (e.g. "01ABC...XYZ.custom_editor").
//
// RoleID must have at least two segments: <namespace>.<name>
type RoleID string
type Role struct {
ID RoleID
Name string
Actions []Action
}
type Grant struct {
PrincipalID core.ID
RoleID RoleID
}
type Group struct {
ID core.ID
Path core.Path
Name string
}
By convention, roles can be namespaced to a specific tenant by prefixing the role ID (see RoleID above) with the tenant ID. This convention allows system-wide roles to easily exist in the app.* namespace.
rate limiting
The core/throttle package provides a token bucket implementation:
type TokenBucket interface {
Take(ctx context.Context, key string, capacity int, refillRate float64) (bool, error)
Reset(ctx context.Context, key string) error
}
Four backends: in-memory, sqlite, postgres, and redis. The first use case in the demo app is login throttling – limiting login attempts per email to slow down brute force attacks.
dashboard
The demo app now has a dashboard and admin UI, built with Mithril.js and backed by RPC endpoints. It's the first real exercise of the routes.RPC approach in the demo. Users can manage tenants, members, groups, roles, and grants. The admin panel provides a system-wide view.
smaller things
core/dbigotPaginateandScanAllhelpers to reduce boilerplate.
what's next
The access control story needs more work – connecting roles and grants to the Guard interface, adding permission checks, and figuring out how it all works with paths and hierarchies.
Thoughts? Email blog@atlas9.dev.