meraproject/openspec/specs/service-project-members/spec.md
keboss-m a7f3df859a Add service API for assigning employees to project teams.
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>
2026-07-14 15:30:59 +03:00

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-Id is omitted
  • AND no tMerakomisTeamMember row exists for (team, emp)
  • AND section_id is allowed for project_id
  • AND emp_id refers to a non-archived, non-removed employee
  • AND role is a valid member role
  • THEN system inserts a new TeamMember row
  • AND returns 200 with ok: true and the new member object including member_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, and text
  • AND returns 200 with updated member object (same member_id)

Scenario: Deactivate member via service endpoint

  • WHEN client sends PUT /api/service/project-members with active: false
  • AND a valid API key is provided
  • THEN system sets active to 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_KEY configured
  • AND client calls PUT /api/service/project-members without 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_id is not in tMerakomisProjectSection for project_id
  • THEN system returns 400 with a structured error indicating invalid section

Scenario: Project has no configured sections

  • WHEN tMerakomisProjectSection has no rows for project_id
  • AND client attempts to add a member via the service endpoint
  • THEN system returns 400 indicating sections must be configured on the project first

Scenario: Archived employee rejected

  • WHEN emp_id refers to an employee with archive=1 or removed=1
  • THEN system returns 400 with validation error for employee

Scenario: Unknown employee

  • WHEN emp_id does not exist in the employee table
  • THEN system returns 404

Scenario: Unknown project

  • WHEN project_id does not exist
  • THEN system returns 404

Scenario: Invalid role

  • WHEN role is 0, omitted, or not a valid member role
  • THEN system returns 400 with 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-members without X-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 isRwMember conditions
  • AND client calls PUT /api/project-members
  • THEN system returns 403 with structured error forbidden