Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/platform/security/rbac.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 09015496d565a172bcaa15cfe9a8e4b072b13df0 |
| Branch | workstream-b-screenmatch |
| Path or archive member | internal/platform/security/rbac.go |
| Original SHA-256 | 6a72a444ab4a86cbcd374ddc1de88b309cc638d7ee63e75d97e96e892ce8e090 |
| Git blob SHA | 0f0ba60bd77071d2b23ef4192bcc44e84d079bbe |
| Reading-copy SHA-256 | 6a72a444ab4a86cbcd374ddc1de88b309cc638d7ee63e75d97e96e892ce8e090 |
Every recorded occurrence
These 21 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-b-screenmatch | 09015496d565a172bcaa15cfe9a8e4b072b13df0 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-a-opportunity-intelligence | 1675031db74316e100782d063e9eda1a597fe3a1 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-d-command-center | 255e7d1d420abf5e277d0cd8c9b14f6f72b6acb9 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | w0-aedt-compliance | 39df94f92b2a33f852481fe1954dabed841524bb | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-d-missionmatch | 3be46ba89edb737182075a2b320509b42dc916f8 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-e-dataflow-deploy | 433815a042f9741411e60fa553fe72143e9b10db | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-e-commercial-stubs | 4437da660539284a400ee380b9b427a300c369ee | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-c-slatematch | 5cd60c918301b46ecd6ed3e03e20c395da0062e2 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | ruthless-debug-sweep | b7d742f8f032984be3817efffa3eb8b13b651c1f | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-b-sam-contract-awards | d5101cceb98e70000cebb31d3e7ac73d747d3a6d | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-a-shared-core | e0de03ac3a1ec826bd15d0e048e3b02baa23eeff | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-c-slatematch | 5cd60c918301b46ecd6ed3e03e20c395da0062e2 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-d-command-center | 255e7d1d420abf5e277d0cd8c9b14f6f72b6acb9 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-e-dataflow-deploy | 433815a042f9741411e60fa553fe72143e9b10db | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | ruthless-debug-sweep | b7d742f8f032984be3817efffa3eb8b13b651c1f | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-a-opportunity-intelligence | 1675031db74316e100782d063e9eda1a597fe3a1 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-b-screenmatch | 09015496d565a172bcaa15cfe9a8e4b072b13df0 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-e-commercial-stubs | 4437da660539284a400ee380b9b427a300c369ee | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-d-missionmatch | 3be46ba89edb737182075a2b320509b42dc916f8 | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | workstream-b-sam-contract-awards | d5101cceb98e70000cebb31d3e7ac73d747d3a6d | Open original |
| Janady13/missionmatch / internal/platform/security/rbac.go | w0-aedt-compliance | 39df94f92b2a33f852481fe1954dabed841524bb | Open original |
Recovered source transcript
Download complete source text ↓133 lines · 4.9 KB
package security
// Role is the tenant role enum already enforced by the users table CHECK constraint. The five roles
// form an ordered hierarchy for the RequireRole comparison, but capabilities are assigned explicitly
// per role below, not implied by rank alone.
type Role string
const (
RoleOwner Role = "owner"
RoleAdmin Role = "admin"
RoleRecruiter Role = "recruiter"
RoleMember Role = "member"
RoleViewer Role = "viewer"
)
// Capability is a fine grained permission checked at the API. Handlers gate on a Capability rather
// than a role so the policy lives in one table and the UI never has to hide a control to enforce
// access.
type Capability string
const (
CapCandidateRead Capability = "candidate.read"
CapCandidateWrite Capability = "candidate.write"
CapRequirementEdit Capability = "requirement.write"
CapSlateEdit Capability = "slate.write"
CapSearchRun Capability = "search.run"
CapExportRun Capability = "export.run"
CapSourcingRead Capability = "sourcing.read" // see sourced candidate contact fields and the sourcing log
CapPrivacyErase Capability = "privacy.erase" // hard delete a sourced candidate and their PII
CapUserInvite Capability = "user.invite"
CapUserRoleChange Capability = "user.role.change"
CapUserDisable Capability = "user.disable"
CapOrgSettings Capability = "org.settings.write"
CapAuditRead Capability = "audit.read"
CapComplianceRead Capability = "compliance.read" // adverse impact report, AEDT inventory and model registry, retention
)
// roleRank orders the hierarchy for AtLeast and for bounding invited roles. Higher is more
// privileged.
var roleRank = map[Role]int{
RoleViewer: 0,
RoleMember: 1,
RoleRecruiter: 2,
RoleAdmin: 3,
RoleOwner: 4,
}
// capabilityRoles is the authoritative permission matrix. owner holds every capability. admin manages
// recruiter, member, and viewer accounts and runs the recruiting workflow, but cannot change org
// settings or manage other admins and owners (those are owner only and are further guarded by the
// separation of duties checks in the auth service). The two privacy capabilities gate the sourced
// candidate contact fields, the sourcing log, and erasure: sourcing.read goes to the roles that
// actually source (owner, admin, recruiter) and the destructive privacy.erase is held tighter
// (owner, admin).
var capabilityRoles = map[Capability][]Role{
CapCandidateRead: {RoleOwner, RoleAdmin, RoleRecruiter, RoleMember, RoleViewer},
CapSearchRun: {RoleOwner, RoleAdmin, RoleRecruiter, RoleMember, RoleViewer},
CapCandidateWrite: {RoleOwner, RoleAdmin, RoleRecruiter},
CapRequirementEdit: {RoleOwner, RoleAdmin, RoleRecruiter},
CapSlateEdit: {RoleOwner, RoleAdmin, RoleRecruiter},
CapExportRun: {RoleOwner, RoleAdmin, RoleRecruiter},
CapSourcingRead: {RoleOwner, RoleAdmin, RoleRecruiter},
CapPrivacyErase: {RoleOwner, RoleAdmin},
CapUserInvite: {RoleOwner, RoleAdmin},
CapUserRoleChange: {RoleOwner, RoleAdmin},
CapUserDisable: {RoleOwner, RoleAdmin},
CapAuditRead: {RoleOwner, RoleAdmin},
CapComplianceRead: {RoleOwner, RoleAdmin},
CapOrgSettings: {RoleOwner},
}
// capabilitySet is the matrix indexed for O(1) lookup, built once at init.
var capabilitySet = func() map[Role]map[Capability]bool {
set := map[Role]map[Capability]bool{
RoleOwner: {}, RoleAdmin: {}, RoleRecruiter: {}, RoleMember: {}, RoleViewer: {},
}
for cap, roles := range capabilityRoles {
for _, role := range roles {
set[role][cap] = true
}
}
return set
}()
// ValidRole reports whether role is one of the five known roles.
func ValidRole(role Role) bool {
_, ok := roleRank[role]
return ok
}
// Has reports whether role holds the capability.
func Has(role Role, cap Capability) bool {
caps, ok := capabilitySet[role]
if !ok {
return false
}
return caps[cap]
}
// AtLeast reports whether role is at or above min in the hierarchy. Unknown roles are never at least
// anything.
func AtLeast(role, min Role) bool {
r, ok := roleRank[role]
if !ok {
return false
}
m, ok := roleRank[min]
if !ok {
return false
}
return r >= m
}
// OutRanks reports whether actor is strictly more privileged than other. It is the core separation of
// duties predicate: a user may only invite, role change, disable, or reset the MFA of someone they
// outrank, never a peer or a superior, and never themselves.
func OutRanks(actor, other Role) bool {
a, ok := roleRank[actor]
if !ok {
return false
}
o, ok := roleRank[other]
if !ok {
return false
}
return a > o
}
// CanInvite reports whether an actor may invite a user with the given role. The invited role must be
// strictly below the actor's own role, so an admin can invite recruiter, member, and viewer but
// never another admin or an owner, and owners are created only through provisioning, never an invite.
func CanInvite(actor, invited Role) bool { return OutRanks(actor, invited) }