Add atomic organization role administration
verify / verify (push) Successful in 3m39s

This commit is contained in:
2026-09-03 22:51:53 -04:00
parent 17bd9453e2
commit fe6bd94c9a
13 changed files with 549 additions and 12 deletions
+6
View File
@@ -54,3 +54,9 @@ application concern belongs in the shared module.
service now permits an explicit development port only when applications opt
in and the RP ID is `localhost` or reserved `.test`; production origins keep
the original portless default.
- Gamertan's staff-access page exposed a dangerous composition gap between
individual grant/revoke calls. Foundations now owns one optimistic,
transactional direct-role replacement that preserves the final active
owner and appends its audit before commit. The application still owns route
authorization, role presentation, CSRF, and the exact fresh-passkey
operation binding.
+1 -1
View File
@@ -26,7 +26,7 @@ The packages are ordinary Go imports. Pin the current preview and verify its
module checksum:
```bash
go get gamertan.com/web/requestmeta@v0.1.0-preview.15
go get gamertan.com/web/requestmeta@v0.1.0-preview.16
go mod verify
```
+1 -1
View File
@@ -18,7 +18,7 @@ import "gamertan.com/web/requestmeta"
and request the containing module at an exact version:
```bash
go get gamertan.com/web/requestmeta@v0.1.0-preview.15
go get gamertan.com/web/requestmeta@v0.1.0-preview.16
```
Only imported packages are compiled and linked. The packages nevertheless
+12
View File
@@ -22,6 +22,18 @@ team membership can be removed independently. Configure `OwnerRole` when
constructing the service before exposing membership-removal operations. The
SQLite adapter then refuses to suspend or remove the final active direct owner.
For a reviewed access-administration page, use `organizations.Members` to list
bounded active and suspended memberships, and
`access.OrganizationUserBindings` to list only current direct,
organization-wide user roles. The latter intentionally excludes team grants
and project, environment, or service bindings. Replace a member's direct role
with `access.ReplaceOrganizationUserRole`, passing the exact displayed binding
IDs as `ExpectedBindingIDs`. The SQLite adapter serializes that replacement,
rejects stale state, writes the new binding and audit event atomically, and
will not demote the final active direct owner. The application must still
authorize the administrator and bind any required fresh passkey assertion to
the organization, target user, target role, and expected IDs.
`access.Service` evaluates a permission against a complete resource scope:
```go