Expose PUT /api/service/project-members for external apps that authenticate with only the API key, reusing portal validation while keeping acting-based writes unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
4.5 KiB
service-project-members
Purpose
Service-to-service API для upsert участника проекта Merakomis без impersonation сотрудника (только API-ключ).
Requirements
Requirement: Service upsert project team member
The system SHALL expose PUT /api/service/project-members that creates or updates a row in tMerakomisTeamMember for the given project_id and emp_id.
The endpoint MUST resolve team from tMerakomisProject.team for project_id.
If a row with the same (team, emp) already exists, the system MUST UPDATE it; otherwise MUST INSERT.
The request MUST require X-Api-Key (or Authorization: Bearer) when the server API key is configured.
The request MUST NOT require X-Acting-Emp-Id.
The system MUST NOT apply portal Rules::isRwMember / can_write_project_member checks for this endpoint.
Required JSON fields: project_id, emp_id, section_id, role.
Optional JSON fields: active (default true), text (default empty string).
The response MUST include ok: true and a member object with the same fields as one item of GET /api/project-members (member_id, emp_id, emp_name, project_id, project_code, project_name, step_name, status, status_name, archive, archive_date, section_id, section_name, role, active).
Scenario: Add new member with API key only
- WHEN a valid API key is provided
- AND
X-Acting-Emp-Idis omitted - AND no
tMerakomisTeamMemberrow exists for(team, emp) - AND
section_idis allowed forproject_id - AND
emp_idrefers to a non-archived, non-removed employee - AND
roleis a valid member role - THEN system inserts a new TeamMember row
- AND returns
200withok: trueand the new member object includingmember_id
Scenario: Update existing member with API key only
- WHEN a TeamMember row already exists for
(team, emp) - AND a valid API key is provided without acting header
- THEN system updates
section,role,active, andtext - AND returns
200with updated member object (samemember_id)
Scenario: Deactivate member via service endpoint
- WHEN client sends
PUT /api/service/project-memberswithactive: false - AND a valid API key is provided
- THEN system sets
activeto 0 - AND member no longer appears in
GET /api/project-members?active_only=true
Scenario: Missing API key rejected
- WHEN server has
USER_READER_API_KEYconfigured - AND client calls
PUT /api/service/project-memberswithout a valid key - THEN system returns
401 Unauthorized
Requirement: Service endpoint reuses portal write validation
The system MUST apply the same business validation as PUT /api/project-members for project existence, employee existence and eligibility, section membership in the project, role validity, and presence of a project team.
Scenario: Invalid section for project
- WHEN
section_idis not intMerakomisProjectSectionforproject_id - THEN system returns
400with a structured error indicating invalid section
Scenario: Project has no configured sections
- WHEN
tMerakomisProjectSectionhas no rows forproject_id - AND client attempts to add a member via the service endpoint
- THEN system returns
400indicating sections must be configured on the project first
Scenario: Archived employee rejected
- WHEN
emp_idrefers to an employee witharchive=1orremoved=1 - THEN system returns
400with validation error for employee
Scenario: Unknown employee
- WHEN
emp_iddoes not exist in the employee table - THEN system returns
404
Scenario: Unknown project
- WHEN
project_iddoes not exist - THEN system returns
404
Scenario: Invalid role
- WHEN
roleis 0, omitted, or not a valid member role - THEN system returns
400with validation error for role
Requirement: Portal project-members write remains unchanged
The system MUST continue to require X-Acting-Emp-Id and isRwMember authorization for PUT /api/project-members.
Scenario: Portal PUT still requires acting
- WHEN client calls
PUT /api/project-memberswithoutX-Acting-Emp-Id - THEN system returns an error indicating missing acting identity (same behavior as before this change)
Scenario: Portal PUT still enforces permissions
- WHEN acting employee does not meet
isRwMemberconditions - AND client calls
PUT /api/project-members - THEN system returns
403with structured errorforbidden