• v1.0.0 18fcd2bee3

    Rene Nochebuena released this 2026-05-07 22:51:01 -06:00 | 1 commits to main since this release

    v1.0.0

    code.nochebuena.dev/go/rbac

    Overview

    rbac v1.0.0 commits the foundational identity and permission API as stable.
    The Identity value type, PermissionMask bit-set, context helpers, and
    PermissionProvider interface are unchanged from v0.9.0 and are now
    production-validated across httpauth, httpauth-firebase, and httpauth-jwt.

    What Changed Since v0.9.0

    New: MaxPermission constant

    const MaxPermission Permission = 62
    

    Makes the valid bit range explicit. Applications can use it in validation and
    the constant is now referenced in the Permission type godoc alongside the
    boundary behavior of Has and Grant.

    Documentation: audit logging policy

    PermissionProvider godoc now documents that audit logging of permission checks
    is out of scope for this package. Log denials and grants inside PermissionProvider
    implementations or in the middleware layer that calls them.

    Full API (stable)

    Permission int64 — bit position (0–MaxPermission). Applications define their
    own constants. Has and Grant silently ignore values outside the valid range.

    MaxPermission Permission = 62 — highest valid bit position.

    PermissionMask int64 — resolved bit-set for a user on a resource.

    • Has(p Permission) bool — O(1) check; returns false for out-of-range p
    • Grant(p Permission) PermissionMask — returns a new mask with bit set; receiver unchanged

    Identity — value type carrying UID, TenantID, DisplayName, Email.

    • NewIdentity(uid, displayName, email string) Identity
    • (Identity).WithTenant(id string) Identity — returns copy; receiver unchanged

    SetInContext(ctx, Identity) context.Context

    FromContext(ctx) (Identity, bool)

    PermissionProvider interfaceResolveMask(ctx, uid, resource string) (PermissionMask, error)

    Migration from v0.9.0

    No breaking changes. The only addition is the MaxPermission constant.

    go get code.nochebuena.dev/go/rbac@v1.0.0
    
    Downloads
  • v0.9.0 0864f031a1

    Release 0.9.0 Stable

    Rene Nochebuena released this 2026-03-18 13:27:28 -06:00 | 2 commits to main since this release

    v0.9.0

    code.nochebuena.dev/go/rbac

    Overview

    rbac provides the foundational identity and permission types for role-based access control in a Go service. It defines the Identity value type (the authenticated principal), the PermissionMask bit-set type (a resolved set of capabilities for a user on a resource), and the PermissionProvider interface (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

    • Permissionint64 type representing a named bit position (0–62) for a single capability
    • PermissionMaskint64 type representing a resolved bit-set of permissions
    • PermissionMask.Has(p Permission) bool — O(1) check whether a permission bit is set; returns false for out-of-range values
    • PermissionMask.Grant(p Permission) PermissionMask — returns a new mask with the given bit set; does not mutate the receiver
    • Identity — value type carrying UID, TenantID, DisplayName, and Email for an authenticated principal
    • NewIdentity(uid, displayName, email string) Identity — constructs an Identity from token authentication data; TenantID is left empty for later enrichment
    • Identity.WithTenant(id string) Identity — returns a copy of the Identity with TenantID set; does not mutate the receiver
    • SetInContext(ctx, Identity) context.Context — stores an Identity in a context using a private key
    • FromContext(ctx) (Identity, bool) — retrieves the Identity stored by SetInContext; returns zero value and false if absent
    • PermissionProvider interface — ResolveMask(ctx, uid, resource string) (PermissionMask, error) for DB-backed permission resolution

    Installation

    require code.nochebuena.dev/go/rbac v0.9.0
    

    Design Highlights

    • Permissions are bit positions packed into an int64 mask, giving O(1) Has checks and compact storage; applications define their own Permission constants — none are defined in this package (see docs/adr/ADR-001-bitset-permissions.md).
    • Identity is a value type (not a pointer) — it is copied on every enrichment call, preventing nil bugs and accidental mutation from concurrent middleware (see docs/adr/ADR-002-identity-value-type.md).
    • The rbac package owns the context key for Identity via an unexported authContextKey{} struct type, preventing collisions with keys from other packages (see docs/adr/ADR-003-identity-context-ownership.md).
    • TenantID is an optional enrichment field; PermissionProvider implementations retrieve the tenant from FromContext(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.Has is a pure in-memory operation — denials and grants are not recorded anywhere by the framework.
    • PermissionProvider.ResolveMask results 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 Has and Grant — 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.
    • FromContext returns the zero-value Identity and false when no identity is present; callers must handle the ok == false case, especially in unauthenticated paths.

    v0.9.0 → v1.0.0 Roadmap

    • Validate the Identity value type and PermissionMask bit-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 WithTenant and SetInContext.

    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