2 Commits

Author SHA1 Message Date
a75ad7b678 chore: bump go directive from 1.25 to 1.26 2026-05-12 02:06:45 +00:00
18fcd2bee3 feat(rbac)!: promote to v1.0.0 — MaxPermission constant, audit logging policy
Add MaxPermission constant (62) to make the valid bit range explicit in the API.
Document in PermissionProvider that audit logging belongs in the application layer.
API committed as stable: Identity, PermissionMask, context helpers, and
PermissionProvider interface are unchanged from v0.9.0.
2026-05-07 22:46:44 -06:00
6 changed files with 52 additions and 1 deletions

1
.gitea/CODEOWNERS Normal file
View File

@@ -0,0 +1 @@
* @go/CoreDevelopers @go/Agents

View File

@@ -5,6 +5,29 @@ All notable changes to this module will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.0] — 2026-05-08
### Added
- `MaxPermission Permission = 62` — exported constant that makes the valid bit range
explicit in the API; applications can use it in validation code and it is referenced
in the `Permission` type godoc
### Changed
- `Permission` type godoc updated to reference `MaxPermission` and document that
values outside `[0, MaxPermission]` are silently ignored
- `PermissionProvider` godoc updated to document 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
### Unchanged
Identity, PermissionMask (Has, Grant), context helpers (SetInContext, FromContext),
and the PermissionProvider interface are API-compatible with v0.9.0.
[1.0.0]: https://code.nochebuena.dev/go/rbac/releases/tag/v1.0.0
## [0.9.0] - 2026-03-18 ## [0.9.0] - 2026-03-18
### Added ### Added

2
go.mod
View File

@@ -1,3 +1,3 @@
module code.nochebuena.dev/go/rbac module code.nochebuena.dev/go/rbac
go 1.25 go 1.26

View File

@@ -11,8 +11,15 @@ package rbac
// ) // )
// //
// The zero value (0) is a valid permission representing the first bit. // The zero value (0) is a valid permission representing the first bit.
// Valid positions are 0 through [MaxPermission] (62); values outside that
// range are silently ignored by [PermissionMask.Has] and [PermissionMask.Grant].
type Permission int64 type Permission int64
// MaxPermission is the highest valid bit position (62).
// Permission constants defined by the application must be in the range
// [0, MaxPermission]. Bit 63 is reserved for the sign bit of the underlying int64.
const MaxPermission Permission = 62
// PermissionMask is a resolved bit-mask for a user on a specific resource. // PermissionMask is a resolved bit-mask for a user on a specific resource.
// It is returned by [PermissionProvider.ResolveMask] and checked with [PermissionMask.Has]. // It is returned by [PermissionProvider.ResolveMask] and checked with [PermissionMask.Has].
type PermissionMask int64 type PermissionMask int64

View File

@@ -93,3 +93,19 @@ func TestPermissionMask_Grant_DoesNotMutateReceiver(t *testing.T) {
t.Error("Grant mutated the receiver; PermissionMask must be a value type") t.Error("Grant mutated the receiver; PermissionMask must be a value type")
} }
} }
func TestMaxPermission(t *testing.T) {
if MaxPermission != 62 {
t.Errorf("MaxPermission = %d, want 62", MaxPermission)
}
// MaxPermission must be usable as a valid bit position.
mask := PermissionMask(0).Grant(MaxPermission)
if !mask.Has(MaxPermission) {
t.Error("MaxPermission bit not set after Grant")
}
// One past the limit must be rejected.
mask2 := PermissionMask(0).Grant(MaxPermission + 1)
if mask2 != 0 {
t.Error("Grant(MaxPermission+1) must return the original mask unchanged")
}
}

View File

@@ -11,6 +11,10 @@ import "context"
// The resource string identifies what is being accessed (e.g. "orders", // The resource string identifies what is being accessed (e.g. "orders",
// "invoices"). Its meaning is defined by the application. // "invoices"). Its meaning is defined by the application.
// //
// Audit logging of permission checks is out of scope for this package.
// Log denials and grants inside your PermissionProvider implementation or in
// the middleware layer that calls it.
//
// Example in-memory implementation for tests: // Example in-memory implementation for tests:
// //
// type staticProvider struct { // type staticProvider struct {