feat: [TESIS-41] add row-level multi-tenancy ORM scoping - #32
Open
TomasMartin2004 wants to merge 3 commits into
Open
feat: [TESIS-41] add row-level multi-tenancy ORM scoping#32TomasMartin2004 wants to merge 3 commits into
TomasMartin2004 wants to merge 3 commits into
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…y injection Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ed scoping Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket de Jira
https://proyectofinalfrlp.atlassian.net/browse/TESIS-41
Descripción
Implementa el aislamiento de datos row-level a nivel ORM. El
company_idvalidado del JWT se inyecta en un contexto global por request (Current) y un concernCompanyScopedagrega un default scopeWHERE company_id = ?a todos los modelos con tenencia, además de forzar elcompany_iddel contexto al crear registros (ignorando cualquier valor del payload).Decisión de diseño: el ADR-003 mostraba el
default_scopedirecto enApplicationRecord, pero eso rompe las tablas globales sincompany_id(companies,services). Se optó por un concern opt-in por modelo — exactamente lo que la card pide al exceptuar "modelos base de configuración global" — y se actualizaron ADR-003 yarchitecture.mdpara reflejarlo.Current(ActiveSupport::CurrentAttributes) concompany_idyuser, seteado enApplicationController#set_current_tenanta partir del usuario autenticado.CompanyScoped: default scope por tenant +before_validation on: :createque fuerzacompany_id = Current.company_id.User,WarehouseyCompanyIntegration(CompanyyServicequedan fuera: son el tenant y plantillas globales).rescue_from ActiveRecord::RecordNotFound→ 404 JSON enApplicationController: buscar un registro de otra empresa por id devuelve 404, nunca 403.Model.unscoped(documentado en ADR-003 y architecture.md). ConCurrentsin setear (login, seeds) el scope no aplica.Evidencia visual
Cómo probar
bundle exec rspec spec/models/concerns/company_scoped_spec.rb— cubre: listado scopeado por tenant,findcross-tenant →RecordNotFound, create ignoracompany_iddel payload,unscopedve todo, contexto nil sin scope.rails console:Current.company_id = Company.first.id; Warehouse.all.to_sql→ incluyeWHERE "warehouses"."company_id" = ....Warehouse.find(<id de otra empresa>)→ActiveRecord::RecordNotFound.Warehouse.create!(name: 'X', zip_code: '1', address: 'Y', company_id: <otra empresa>)→ queda con elcompany_iddel contexto.Warehouse.unscoped.count→ ve todos los registros.POST /api/v1/auth/login), usar el token; cualquier endpoint futuro queda scopeado automáticamente por elcompany_iddel JWT.Impacto y consideraciones
¿Introduce breaking changes?
No — con
Currentsin setear el comportamiento es idéntico al actual (seeds, specs existentes y login no cambian).¿Requiere nuevas variables de entorno?
No.
¿Afecta la arquitectura o genera un nuevo patrón?
Sí — todo modelo nuevo con
company_iddebe incluirCompanyScoped. ADR-003 ydocs/guidelines/architecture.mdactualizados en este PR.