-
Release 0.9.0 Stable
released this
2026-03-18 13:27:28 -06:00 | 0 commits to main since this releasev0.9.0
code.nochebuena.dev/go/rbacOverview
rbacprovides the foundational identity and permission types for role-based access control in a Go service. It defines theIdentityvalue type (the authenticated principal), thePermissionMaskbit-set type (a resolved set of capabilities for a user on a resource), and thePermissionProviderinterface (the contract for DB-backed permission resolution). Every other module that needs to carry or inspect an authenticated identity imports this package; it has no micro-lib dependencies of its own, only stdlib.What's Included
Permission—int64type representing a named bit position (0–62) for a single capabilityPermissionMask—int64type representing a resolved bit-set of permissionsPermissionMask.Has(p Permission) bool— O(1) check whether a permission bit is set; returns false for out-of-range valuesPermissionMask.Grant(p Permission) PermissionMask— returns a new mask with the given bit set; does not mutate the receiverIdentity— value type carryingUID,TenantID,DisplayName, andEmailfor an authenticated principalNewIdentity(uid, displayName, email string) Identity— constructs an Identity from token authentication data;TenantIDis left empty for later enrichmentIdentity.WithTenant(id string) Identity— returns a copy of the Identity withTenantIDset; does not mutate the receiverSetInContext(ctx, Identity) context.Context— stores an Identity in a context using a private keyFromContext(ctx) (Identity, bool)— retrieves the Identity stored bySetInContext; returns zero value and false if absentPermissionProviderinterface —ResolveMask(ctx, uid, resource string) (PermissionMask, error)for DB-backed permission resolution
Installation
require code.nochebuena.dev/go/rbac v0.9.0Design Highlights
- Permissions are bit positions packed into an
int64mask, giving O(1)Haschecks and compact storage; applications define their ownPermissionconstants — none are defined in this package (seedocs/adr/ADR-001-bitset-permissions.md). Identityis a value type (not a pointer) — it is copied on every enrichment call, preventing nil bugs and accidental mutation from concurrent middleware (seedocs/adr/ADR-002-identity-value-type.md).- The
rbacpackage owns the context key forIdentityvia an unexportedauthContextKey{}struct type, preventing collisions with keys from other packages (seedocs/adr/ADR-003-identity-context-ownership.md). TenantIDis an optional enrichment field;PermissionProviderimplementations retrieve the tenant fromFromContext(ctx)when needed, so multi-tenancy does not require threading an extra parameter through every call site.
Known Limitations & Edge Cases
- There is no audit logging of permission checks.
PermissionMask.Hasis a pure in-memory operation — denials and grants are not recorded anywhere by the framework. PermissionProvider.ResolveMaskresults are not cached by this package. Implementations that hit a database on every call must implement their own caching layer; a hot permission check path with no cache will produce one DB round-trip per check.- Permissions at bit positions 63 and above are silently ignored by
HasandGrant— no error or panic is produced. Applications must keep their constants in the range 0–62. - Role-to-permission mapping tables are out of scope. The bit-set model is deliberately flat; if role inheritance or hierarchical permissions are required, callers must implement that logic in their
PermissionProvider. FromContextreturns the zero-valueIdentityandfalsewhen no identity is present; callers must handle theok == falsecase, especially in unauthenticated paths.
v0.9.0 → v1.0.0 Roadmap
- Validate the
Identityvalue type andPermissionMaskbit-set model under production multi-tenant workloads, confirming that the context key collision policy holds across all imported packages. - Consider providing a reference caching wrapper for
PermissionProvider(e.g. TTL-based in-memory cache) to reduce DB pressure without requiring every application to implement its own. - Decide whether audit logging of permission checks (denials at minimum) belongs in this package, in a wrapper type, or in the application layer, and document the recommended pattern.
- Validate that 63 permission bits is sufficient for known use cases; document the upper bound explicitly in the package godoc.
- Achieve production validation of concurrent middleware enrichment via
WithTenantandSetInContext.
v0.9.0 rationale: The API is stable and intentional — designed through multiple architecture reviews and tested end-to-end via the todo-api POC (SQLite, RBAC, middleware stack, HTTP handlers). The module is not yet battle-tested in production for all edge cases, and the pre-1.0 designation preserves the option for minor API refinements based on real-world use.
Downloads