Repository navigation
Conversation
…RBAC matrix) - Add FacilityMember model: user↔facility with role enum (owner|staff), unique constraint on userId - Add FacilityInvite model: hashed token, expiring TTL, single-use, conditional update - Migrate existing 1:1 FacilityProfile/User links to FacilityMember with role=owner - FacilityProfile.userId removes @unique (constraint now in FacilityMember) - Member management: owners can list/remove staff; cannot remove last owner - Owner-only invariant: staff cannot invite, remove, list invites, or revoke (403) - Last owner cannot be removed from facility - User cannot belong to two facilities (DB unique constraint on FacilityMember.userId) - Invite acceptance: new user (create account + FacilityMember) and existing user (add to facility) - Facilitiy guard middleware: resolves membership via FacilityMember, exposes facilityId + role - Owner-only guard for management endpoints - FulfillmentRecord.actorUserId: records acting staff user, nullable for legacy rows - Updated ARCHITECTURE.md §4 with FacilityMember/FacilityInvite models and attribution field - Updated ARCHITECTURE_ESSENTIALS.md data model map - Updated ROADMAP.md: issue DocForum#75 status changed to Done - Updated docs/api/README.md with new facility API endpoints - Updated backend/src/modules/facilities/ with full implementation - Updated backend/src/middleware/facility-guard.ts with membership resolution
…fixed roles, no RBAC matrix) - Add FacilityMember and FacilityInvite models with FacilityRole enum - Migrate existing FacilityProfile/User links to FacilityMember (role=owner) - Implement invite flow (create, accept, list, revoke) - Facility guard middleware (requireFacility, requireFacilityOwner) - Owner-only route guards - Update ARCHITECTURE.md, ARCHITECTURE_ESSENTIALS.md, ROADMAP.md - Fix integration test setup (bcrypt, migration reset, type fields)
|
@dahmeezy Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
|
@dahmeezy Thanks for the PR. It can't be merged yet. To unblock it: CI is failing. Here's what broke:
Please fix these errors and run the same steps locally before pushing ( Branch protection also requires the branch to be up to date with Push to this same branch and CI will re-run. Once it's green and conflict-free, it'll be reviewed for merge. |
|
@dahmeezy This PR now has merge conflicts with git fetch upstream # upstream = https://github.com/DocForum/docforum-core.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-leaseThe usual culprits are shared files like Automated message. It won't repeat unless the PR conflicts again after your next push. |
Closes #75
What changed and why
FacilityProfilewas 1:1 withUser, so a pharmacy with several pharmacists shared one login and lost attribution (PRD §7). This adds multiple staff accounts per facility with exactly two fixed roles (owner,staff) and no permissions matrix.Schema and migration
FacilityRoleenum (owner | staff), enforced at DB level.FacilityMembermodel (userIdunique,facilityId,role).FacilityInvitemodel (tokenHashunique,expiresAt,role,facilityId).Usernow relates toFacilityMemberinstead ofFacilityProfile.20261019131059_add_facility_member_and_invitecreates the tables and converts every existingFacilityProfile/Userpair into aFacilityMemberwithrole=owner.Services
members.ts: getMembers, createMember, removeMember, isOwner, isMember. The last owner cannot be removed.invites.ts: createInvite, acceptInvite, listInvites, revokeInvite. Tokens are random and stored as SHA-256 hashes (never plaintext). Expiry uses the configured TTL. Tokens are single-use, consumed with a conditional update.Middleware (
middleware/facility-guard.ts)requireFacilityresolves membership viaFacilityMemberand exposesfacilityIdandmemberRole.requireFacilityOwnerguards management endpoints.requireFacilityMemberis the general guard.Attribution
userIdis recorded alongside the facility on fulfillment events (append-only). [VERIFY: list each fulfillment action now attributed, and confirm production code writes the actor, not only tests.]Docs
ARCHITECTURE.md §4, ARCHITECTURE_ESSENTIALS.md (data model map, role guardrail), ROADMAP.md (#75 under Phase 5).
Design decisions
FacilityMember.userId).Evidence for reviewer checks
grep -rniE "role" backend/src backend/prisma | grep -iE "admin|manager|viewer"output showing no third role.]Test status
npm run typecheck: [paste output]npm test: 93 passingnpm run test:integration: 9 failures, 3 skips (NOT green). Cause: test DB schema is not built from the real migrations (LoginAttempt table mismatch). [Update once fixed.]Open items
FacilityProfile.userIdcolumn was dropped, and that nothing still reads it. [VERIFY.]