feat(rbac): initial stable release v0.9.0

Foundational identity and permission types for role-based access control — bit-set PermissionMask, immutable Identity value type, and PermissionProvider interface.

What's included:
- `Identity` value type with NewIdentity / WithTenant constructors and SetInContext / FromContext context helpers
- `Permission` (int64 bit position) and `PermissionMask` (int64 bit-set) with O(1) Has and non-mutating Grant
- `PermissionProvider` interface for DB-backed ResolveMask(ctx, uid, resource) resolution

Tested-via: todo-api POC integration
Reviewed-against: docs/adr/
This commit is contained in:
2026-03-18 13:25:43 -06:00
commit 0864f031a1
17 changed files with 940 additions and 0 deletions

39
permission.go Normal file
View File

@@ -0,0 +1,39 @@
package rbac
// Permission is a named bit position (062) representing a single capability.
//
// Applications define their own constants using this type:
//
// const (
// Read rbac.Permission = 0
// Write rbac.Permission = 1
// Delete rbac.Permission = 2
// )
//
// The zero value (0) is a valid permission representing the first bit.
type Permission int64
// PermissionMask is a resolved bit-mask for a user on a specific resource.
// It is returned by [PermissionProvider.ResolveMask] and checked with [PermissionMask.Has].
type PermissionMask int64
// Has reports whether the given permission bit is set in the mask.
// Returns false for out-of-range values (p < 0 or p >= 63).
func (m PermissionMask) Has(p Permission) bool {
if p < 0 || p >= 63 {
return false
}
return (int64(m) & (1 << uint(p))) != 0
}
// Grant returns a new mask with the bit for p set.
// The receiver is not modified.
// Useful for building masks in tests and in-memory [PermissionProvider] implementations:
//
// mask := rbac.PermissionMask(0).Grant(Read).Grant(Write)
func (m PermissionMask) Grant(p Permission) PermissionMask {
if p < 0 || p >= 63 {
return m
}
return PermissionMask(int64(m) | (1 << uint(p)))
}