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.
This commit is contained in:
2026-05-07 22:46:44 -06:00
parent 0864f031a1
commit 18fcd2bee3
5 changed files with 51 additions and 0 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/),
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
### Added

View File

@@ -11,8 +11,15 @@ package rbac
// )
//
// 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
// 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.
// It is returned by [PermissionProvider.ResolveMask] and checked with [PermissionMask.Has].
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")
}
}
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",
// "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:
//
// type staticProvider struct {