Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
a75ad7b678
|
|||
|
18fcd2bee3
|
1
.gitea/CODEOWNERS
Normal file
1
.gitea/CODEOWNERS
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* @go/CoreDevelopers @go/Agents
|
||||||
23
CHANGELOG.md
23
CHANGELOG.md
@@ -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
2
go.mod
@@ -1,3 +1,3 @@
|
|||||||
module code.nochebuena.dev/go/rbac
|
module code.nochebuena.dev/go/rbac
|
||||||
|
|
||||||
go 1.25
|
go 1.26
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user