import type { AssigneeCandidate } from "../../domain/write.js"; import type { CredentialPort } from "../../ports/credentials.port.js"; import type { JiraAssigneeResolutionPort } from "../../ports/jira-assignee-resolution.port.js"; /** * Jira Cloud REST v3 user directory, read-only. * * Two endpoints, two questions: * * - `GET /rest/api/3/user/search?query=` - who might this name mean. Jira * matches display name and, where privacy settings allow it, email. The * answers are candidates. * - `GET /rest/api/3/user/assignable/search?issueKey=&accountId=` - may this * exact account hold this exact issue. Jira answers with the account when * it may and with nothing when it may not, which is the assignability check * without JAM having to interpret a permission model it does not own. * * `retry: false` on both. Their answers decide a mutation, so a * retried-and-stale answer is worse than a failure. * * Email is deliberately not part of the identity JAM works with. Jira's * privacy settings routinely blank it - most users on a real site come back * with `emailAddress: ""` - so resolving on it would work for some people and * silently fail for others on the same site. */ export declare class JiraCloudAssigneeResolutionAdapter implements JiraAssigneeResolutionPort { private readonly client; constructor(credentials: CredentialPort, fetchImpl?: typeof fetch); searchUsers(query: string): Promise; /** * `GET /rest/api/3/user?accountId=` - the exact lookup, not a search. * * Jira answers 404 when no such account exists or this token cannot see it. * Both mean the same thing to a caller who wanted to assign it, so both * become `undefined` rather than an error: "there is nobody to assign" is an * answer, and the policy layer is where it turns into a refusal. */ getUserByAccountId(accountId: string): Promise; isAssignable(issueKey: string, accountId: string): Promise; }