Use computed permissions for group membership instead of direct relations
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 52/100
- Tipo de issue
- Refactorización
- Claridad
- Bastante claro
- Estado de actividad
- Tranquilo
- Stack tecnológico
- go
- Área
- authorization, backend
Línea de trabajo
Comienza con base_schema.zed y core/group/service.go:168-221, y luego busca referencias a group#member. Verifica cómo las políticas de organización y proyecto exponen la pertenencia antes de cambiar el esquema del grupo y eliminar la creación directa de relaciones de AddMember y addOwner. El trabajo está terminado cuando la pertenencia a grupos utiliza las políticas de forma coherente y todas las referencias a group#member utilizan el permiso calculado.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Problem
Group membership currently uses direct group#member@user relations, while organization and project membership use policies (role bindings). This inconsistency means groups require special handling.
Current State
| Resource | How membership works |
|---|---|
| Organization | Policies (role bindings) |
| Project | Policies (role bindings) |
| Group | Direct group#member@user relation |
When a user is added to a group, we create both a policy AND a direct relation.
Source: core/group/service.go:168-191
// AddMember adds a subject(user) to group as member
func (s Service) AddMember(ctx context.Context, groupID string, principal authenticate.Principal) error {
// first create a policy for the user as member of the group
if err := s.addMemberPolicy(ctx, groupID, principal); err != nil {
return err
}
// then create a relation between group and user as member
rel := relation.Relation{
Object: relation.Object{
ID: groupID,
Namespace: schema.GroupNamespace,
},
Subject: relation.Subject{
ID: principal.ID,
Namespace: principal.Type,
},
RelationName: schema.MemberRelationName,
}
if _, err := s.relationService.Create(ctx, rel); err != nil {
return err
}
return nil
}
Same pattern exists for addOwner at lines 193-221.
Proposed State
| Resource | How membership works |
|---|---|
| Organization | Policies (role bindings) |
| Project | Policies (role bindings) |
| Group | Policies (role bindings) |
Group membership becomes computed from policies, just like org and project.
How it works
Schema change:
// Before
definition group {
relation member: app/user // direct relation
permission get = ... + member
}
// After
definition group {
relation granted: app/rolebinding
permission members = granted->app_group_member // computed from policies
permission get = ...
}
SpiceDB resolves group members by:
- Find all role bindings granted to the group
- Filter to those with "Group Member" role
- Return their bearers
Tested in AuthZed Playground - this approach works.
Benefits
| Benefit | Description |
|---|---|
| Consistency | All resources (org, project, group) use the same pattern |
| Single source of truth | Membership determined by policies only, no sync issues |
| Simpler code | Remove direct relation management for groups |
| SDK simplicity | Same role-based API for all resources |
Potential Downsides
| Concern | Impact | Mitigation |
|---|---|---|
| Query complexity | Membership is computed, not direct lookup | SpiceDB optimizes and caches these |
| Schema migration | Need to update SpiceDB schema | Can be done incrementally |
| Breaking change | External systems using group#member relation |
Document in release notes |
Code Changes
- Update
base_schema.zed- changegroup#memberfrom relation to computed permission core/group/service.go-AddMember: removerelationService.Createcall, keep only policycore/group/service.go-addOwner: removerelationService.Createcall, keep only policy- Update references from
group#membertogroup#members(the computed permission)
- Lenguaje dominante
- Go
- Estrellas
- 344
- Forks
- 48
- Merge medio
- 1 d 22 h
- PR fusionados (30 d)
- 38
Preparar el entorno
- Incluye un Dockerfile o un archivo de Docker Compose
- Tiene una plantilla de pull request
- Sin guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de raystack/frontier
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 62/100
Los mantenedores suelen responder en 1 día
-
Deleting an organization that has a disabled project fails and leaves it without ownersPosiblemente ocupada @rohilsurana la tomó hace 5 días. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 62/100
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 52/100
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 58/100
Los mantenedores suelen responder en 1 día
Todos los issues de raystack/frontier
Issues similares
-
small item
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
canonical/pebble#1127 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 89/100
open-policy-agent/opa#9366 · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
defect
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
nats-io/nats-server#8752 ·
Los mantenedores suelen responder en 1 día
-
enhancement needs-acceptance wg/router-models-inference-runtime
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
vllm-project/semantic-router#5015 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
fileserver: precompressed sidecar's Content-Encoding and Content-Length end up on error responsesPosiblemente ocupada @NitinKumar004 la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
caddyserver/caddy#8204 ·
Los mantenedores suelen responder en 1 día